Exemplo n.º 1
0
        /// <summary>
        /// Creates the lambda expression from the statements attached to this entry and the parameter definitions in the provided program context.
        /// </summary>
        public LambdaExpression CreateLambda(VisualProgram context)
        {
            if (!context.Environment.EntryDefinitions.TryGetValue(VisualEntryId, out var def))
            {
                throw new KeyNotFoundException($"Could not find an entry with ID '{VisualEntryId}' in the VisualProgram's entry definitions.");
            }

            // Create a parameter for each expected/defined parameter
            var parameters = def.Parameters.Map(Expression.Parameter);

            return(Expression.Lambda(
                       Expression.Block(
                           // Before doing the main body of the entry function, make expressions to copy the incoming parameters to variables
                           ParameterMap
                           .Where(mapping => !string.IsNullOrWhiteSpace(mapping.Value)) // Exclude any that don't actually map to anything
                           .Select(p => VariableAccessorFactory.CreateSetterExpression(
                                       context,
                                       VariableReference.Create(def.Parameters[p.Key], p.Value),
                                       parameters[p.Key]
                                       )
                                   ).Concat(
                               // Then do the actual main body
                               NodeUtils.FlattenExpressions(context, FirstStatement)
                               )
                           ),

                       // All lambdas will get a context parameter
                       // We also pass the defined parameters to the lambda so it knows what types to expect and what signature to have.
                       // This needs to happen regardless or not of whether the parameters are actually used by the entry function as this determines the delegate's signature.
                       new[] { context.Variables.compiledInstanceParameter }.Concat(parameters)
                       ));
        }
        /// <summary>Resolves this reference into a single <see cref="BlockExpression"/> containing all the sequential statements.
        /// If there are no statements that would end up in the block, throws an exception.</summary>
        /// <exception cref="Exception"></exception>
        public BlockExpression ResolveRequiredStatement(VisualProgram context)
        {
            var body = NodeUtils.FlattenExpressions(context, this);

            if (body.Count() == 0)
            {
                throw new Exception();                                // TODO Add meaningful message
            }
            return(Expression.Block(expressions: body));
        }
Exemplo n.º 3
0
        public override Expression CreateExpression(VisualProgram context)
        {
            var branches = NodeUtils.FlattenExpressions(context, TrueBranch, FalseBranch);

            return(Expression.IfThenElse(
                       Condition.ResolveRequiredExpression(context),
                       Expression.Block(branches.branch1Flattened),
                       Expression.Block(branches.branch2Flattened)
                       ));
        }
        /// <summary>
        /// Compiles the entries in the given Program into delegates.
        /// Returns the delegates themselves and the delegate signatures (excluding the context parameter).
        /// </summary>
        private FunctionStore CompileEntryDelegates(VisualProgram program)
        {
            var progEntryNodes = program.Nodes.OfType <VisualEntry>().ToDictionary(ve => ve.VisualEntryId, ve => ve);

            return(program.Environment.EntryDefinitions.ToDictionary(
                       entry => entry.Key,
                       entry => {
                // If the program does not contain this entry node OR it exists but is not connected to any statements, then return no delegate
                if (!progEntryNodes.TryGetValue(entry.Value.Id, out var startNode) || !startNode.FirstStatement.HasValue)
                {
                    return null;
                }

                // Create a parameter for each expected/defined parameter
                var parameters = entry.Value.Parameters.Map(Expression.Parameter);

                // Compile and return the lambda
                return Expression.Lambda(
                    Expression.Block(
                        // Before doing the main body of the entry function, make expressions to copy the incoming parameters to variables
                        startNode.ParameterMap
                        .Where(mapping => !string.IsNullOrWhiteSpace(mapping.Value))                                         // Exclude any that don't actually map to anything
                        .Select(p => VariableAccessorFactory.CreateSetterExpression(
                                    program,
                                    VariableReference.Create(entry.Value.Parameters[p.Key], p.Value),
                                    parameters[p.Key]
                                    )
                                ).Concat(
                            // Then do the actual main body
                            NodeUtils.FlattenExpressions(program, startNode.FirstStatement)
                            )
                        ),

                    // All lambdas will get a context parameter
                    // We also pass the defined parameters to the lambda so it knows what types to expect and what signature to have.
                    // This needs to happen regardless or not of whether the parameters are actually used by the entry function as this determines the delegate's signature.
                    new[] { program.Variables.compiledInstanceParameter }.Concat(parameters)
                    ).Compile();
            },
                       StringComparer.OrdinalIgnoreCase
                       ));
        }
 /// <summary>Resolves this reference into a single <see cref="BlockExpression"/> containing all the sequential statements.</summary>
 public BlockExpression ResolveStatement(VisualProgram context) => Expression.Block(expressions: NodeUtils.FlattenExpressions(context, this));