DynamoDS/Dynamo — pull request #1784 by ke-yu (2014-06-19 10:38:57+00:00)
Title: Compile IF node to if-else imperative block if in custom node context

Hi all, this pull request is just for technical review, it does not intend for being merged. As compiling IF node is pretty tricky, I'd request you to review the solution and see if I need to go ahead.

In short, we need to support recursive workflow which requires IF node to execute one of its branch at runtime. There is other issue in IF node, for example passing it as a function object. This issue is resolved through compiling IF node to inline conditional function, see pull request https://github.com/DynamoDS/Dynamo/pull/1758.

As on top level (homeworkspace) compiling graph nodes into scope will bring issues like preview, I only consider about doing that in '''custom node'''. We have two options.
* As inline conditional still executes both branches before checking condition, we could compile both branches into anonymous functions and passing function pointer to inline conditional function, and inside that function, these two function pointers gets evaluated. Basically the signature of inline conditional function would be
```%inlineconditional(cond: bool, trueBranch: fptr, falseBranch: fptr)()```
* Compile it to if-else structure.

In this pull request, the second option is used. But it also means:
* **replication doesn't work for IF node in custom node (has exceptions, see below)**.
* **IF node cannot be used as a function object in custom node**
* **IF node will be compiled to if-else block only when it has all inputs; otherwise still compiled to inline conditional**

So I added a class ```ScopedNodeModel```, and IF node inherits from this class. Usually we are using bottom-up compilation approach, i.e., we compile all upstream nodes (leave nodes) firstly and then finally the downstream nodes (root nodes). With the introduction of ```ScopedNodeModel```, this model is reversed: from top-down to exclude all upstream nodes that in the scope of some ```ScopedNodeModel``` and then use bottom-up to compile graph nodes in global scope. Those excluded graph nodes will be compiled by ```ScopedNodeModel```. As ```ScopedNodeModel``` would be nested or doesn't have enough inputs, or some nodes may escape from the scope of IF-node, the compilation process needs some tweaks. Please see its implementation.

For IF node in custom node, if it gets all inputs, it will be compiled to the following structure:
```
v = [Associative]
{
return = [Imperative]
{
...
if (cond)
{
...
return = ...;
}
else
{
return = ...;
}
}
}
```

That's the basic idea.

Nested IF node is not working right now because of a defect that the compilation of nested language block hangs in delta execution mode, see: http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-3768.

Please review this solution and let me know if it is still the right way to go.