/// <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) )); }