예제 #1
0
        private Expression GetDataExpression(int?node, int?output, Dictionary <int, bool> visited)
        {
            if (visited.ContainsKey(node.Value) && visited[node.Value])
            {
                throw new InvalidGraphException("Infinite data loop");
            }

            var currentNode = GetNode(node.Value);

            if (FunctionsFacade.IsPureFunction(currentNode.Type))
            {
                visited[node.Value] = true;
                var inputExpressions = new Expression[currentNode.Inputs.Length];
                for (int i = 0; i < currentNode.Inputs.Length; i++)
                {
                    var connection = currentNode.Inputs[i][0];
                    if (connection == null)
                    {
                        inputExpressions[i] = GetDefaultValueOfEmptyInput(currentNode.Type, i, currentNode.Data.Value);
                    }
                    else
                    {
                        inputExpressions[i] = GetDataExpression(connection.Node, connection.Output, visited);
                    }
                }
                visited[node.Value] = false;

                if (currentNode.Type == FunctionNames.Number)
                {
                    return(Expression.Constant((double?)Convert.ToDouble(currentNode.Data.Value), typeof(double?)));
                }
                else if (currentNode.Type == FunctionNames.Boolean)
                {
                    return(Expression.Constant((bool?)Convert.ToBoolean(currentNode.Data.Value), typeof(bool?)));
                }
                else if (currentNode.Type == FunctionNames.NumberArray)
                {
                    return(Expression.Constant(JsonConvert.DeserializeObject <double?[]>(currentNode.Data.Value), typeof(double?[])));
                }
                if (currentNode.Type == FunctionNames.Get)
                {
                    return(LocalVars[currentNode.Data.Value]);
                }
                else
                {
                    try
                    {
                        var tree = FunctionsFacade.GetExpressionTree(currentNode.Type, inputExpressions);
                        return(tree);
                    }
                    catch (NeedToConstructExpressionTreeException)
                    {
                        // If the function has been constructed before use that
                        if (CachedTrees.ContainsKey(currentNode.Type))
                        {
                            return(Expression.Invoke(CachedTrees[currentNode.Type], inputExpressions));
                        }
                        // If this is a recursive call of a function that hasn't been constructed yet use self pointer
                        else if (CallStackTreePointers.ContainsKey(currentNode.Type))
                        {
                            return(Expression.Invoke(CallStackTreePointers[currentNode.Type], inputExpressions));
                        }
                        // Otherwise construct a tree for the function
                        else
                        {
                            var graph       = FunctionsFacade.GetFunctionGraph(currentNode.Type);
                            var constructor = new ExpressionTreeConstructor(currentNode.Type, graph, FunctionsFacade, CachedTrees);
                            var tree        = constructor.Construct();
                            return(Expression.Invoke(tree, inputExpressions));
                        }
                    }
                }
            }
            else
            {
                switch (currentNode.Type)
                {
                case FunctionNames.Entry:
                    return(EntryParams[output.Value - 1]);

                case FunctionNames.ForEach:
                case FunctionNames.For:
                    return(LoopVars[Tuple.Create(currentNode.Id, output.Value)]);

                case FunctionNames.Set:
                    return(LocalVars[currentNode.Data.Value]);
                }
            }

            throw new InvalidGraphException($"Couldn't recognize node {currentNode.Type}");
        }
예제 #2
0
        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");
            }
        }