private Expression GetControlExpression(int node, Dictionary <int, bool> visited) { if (visited.ContainsKey(node) && visited[node]) { throw new InvalidGraphException("Infinite flow loop"); } visited[node] = true; var currentNode = GetNode(node); var inputDataExpressions = new Expression[currentNode.Inputs.Length]; var outputFlowExpressions = new Expression[currentNode.Outputs.Length]; // ASSUMPTION: first input socket is a flow socket, the rest are data sockets for (int i = 1; i < currentNode.Inputs.Length; i++) { var connection = currentNode.Inputs[i][0]; if (connection == null) { inputDataExpressions[i] = GetDefaultValueOfEmptyInput(currentNode.Type, i, currentNode.Data.Value); } else { inputDataExpressions[i] = GetDataExpression(node, i); } } for (int i = 0; i < currentNode.Outputs.Length; i++) { var connection = currentNode.Outputs[i][0]; if (connection != null && !FunctionsFacade.IsPureFunction(GetNode(connection.Node).Type)) { outputFlowExpressions[i] = GetControlExpression(connection.Node, visited); } else { outputFlowExpressions[i] = Expression.Empty(); } } visited[node] = false; switch (currentNode.Type) { case FunctionNames.If: return(Expression.IfThenElse( Expression.Convert(inputDataExpressions.ElementAtOrDefault(1), typeof(bool)), outputFlowExpressions.ElementAtOrDefault(0), outputFlowExpressions.ElementAtOrDefault(1) )); case FunctionNames.ForEach: return(Expression.Block( ExpressionUtils.ForEach( inputDataExpressions.ElementAtOrDefault(1), LoopVars[Tuple.Create(node, 1)], outputFlowExpressions.ElementAtOrDefault(0) ), outputFlowExpressions.ElementAtOrDefault(3) )); case FunctionNames.For: throw new NotImplementedException(); case FunctionNames.While: throw new NotImplementedException(); case FunctionNames.Return: return(Expression.Return(ReturnTarget, inputDataExpressions.ElementAtOrDefault(1))); case FunctionNames.Set: return(Expression.Block( Expression.Assign(LocalVars[currentNode.Data.Value], inputDataExpressions.ElementAtOrDefault(1)), outputFlowExpressions[0] )); default: throw new InvalidGraphException("Not a control function or is entry"); } }