//Function used to construct our expression. This is used to properly create a curried function call, which will be //able to support partial function application. protected Expression ToExpression( Expression function, IEnumerable <string> parameters, int expectedArgs, Dictionary <INode, string> symbols, Dictionary <INode, List <INode> > letEntries, HashSet <string> initializedIds, HashSet <string> conditionalIds) { //If no arguments have been supplied and if we are expecting arguments, simply return the function. if (arguments.Keys.Count == 0 && expectedArgs > 0) { return(function); } //If the number of expected arguments is greater than how many arguments have been supplied, we perform a partial //application, returning a function which takes the remaining arguments. if (arguments.Keys.Count < expectedArgs) { //Get all of the missing arguments. IEnumerable <string> missingArgs = parameters.Where( input => !arguments.ContainsKey(input) ); //Return a function that... return(Utils.MakeAnon( //...takes all of the missing arguments... missingArgs.ToList(), Expression.NewList_E( FSharpList <Expression> .Cons( //...and calls this function... function, Utils.SequenceToFSharpList( //...with the arguments which were supplied. parameters.Select( input => missingArgs.Contains(input) ? Expression.NewId(input) : arguments[input].compile( symbols, letEntries, initializedIds, conditionalIds))))))); } //If all the arguments were supplied, just return a standard function call expression. else { return(Expression.NewList_E( FSharpList <Expression> .Cons( function, Utils.SequenceToFSharpList( parameters.Select( input => arguments[input].compile( symbols, letEntries, initializedIds, conditionalIds)) ) ) )); } }
protected override Expression compileBody( Dictionary <INode, string> symbols, Dictionary <INode, List <INode> > letEntries, HashSet <string> initializedIds, HashSet <string> conditionalIds) { var arg = arguments.First().Value.compile( symbols, letEntries, initializedIds, conditionalIds); //idle :: (() -> A) -> A //Evaluates the given function in the Revit Idle thread. var idle = Expression.NewFunction_E( FSharpFunc <FSharpList <Value>, Value> .FromConverter( args => { var f = (args[0] as Value.Function).Item; if (dynSettings.Controller.DynamoViewModel.RunInDebug) { return(f.Invoke(FSharpList <Value> .Empty)); } return(IdlePromise <Value> .ExecuteOnIdle( () => f.Invoke(FSharpList <Value> .Empty))); })); //startTransaction :: () -> () //Starts a Dynamo Transaction. var startTransaction = Expression.NewFunction_E( FSharpFunc <FSharpList <Value>, Value> .FromConverter( _ => { if (_node.Controller.RunCancelled) { throw new CancelEvaluationException(false); } if (!dynSettings.Controller.DynamoViewModel.RunInDebug) { dynRevitSettings.Controller.InIdleThread = true; dynRevitSettings.Controller.InitTransaction(); } return(Value.NewDummy("started transaction")); })); //endTransaction :: () -> () //Ends a Dynamo Transaction. var endTransaction = Expression.NewFunction_E( FSharpFunc <FSharpList <Value>, Value> .FromConverter( _ => { if (!dynRevitSettings.Controller.DynamoViewModel.RunInDebug) { dynRevitSettings.Controller.EndTransaction(); dynRevitSettings.Controller.InIdleThread = false; dynSettings.Controller.DynamoViewModel.OnRequestLayoutUpdate(this, EventArgs.Empty); _node.ValidateConnections(); } else { _node.setDirty(false); } return(Value.NewDummy("ended transaction")); })); /* (define (idleArg) * (startTransaction) * (let ((a <arg>)) * (endTransaction) * a)) */ var idleArg = Expression.NewFun( FSharpList <FScheme.Parameter> .Empty, Expression.NewBegin( Utils.SequenceToFSharpList(new List <Expression> { Expression.NewList_E( Utils.SequenceToFSharpList( new List <Expression> { startTransaction })), Expression.NewLet( Utils.SequenceToFSharpList( new List <string> { "__result" }), Utils.SequenceToFSharpList( new List <Expression> { arg }), Expression.NewBegin( Utils.SequenceToFSharpList( new List <Expression> { Expression.NewList_E( Utils.SequenceToFSharpList( new List <Expression> { endTransaction })), Expression.NewId("__result") }))) }))); // (idle idleArg) return(Expression.NewList_E( Utils.SequenceToFSharpList(new List <Expression> { idle, idleArg }))); }