protected override void BuildAstForPartialMultiOutput( NodeModel model, AssociativeNode rhs, List <AssociativeNode> resultAst) { base.BuildAstForPartialMultiOutput(model, rhs, resultAst); var kvps = Definition.ReturnKeys.Select( (rtnKey, idx) => new KeyValuePair <AssociativeNode, AssociativeNode>(AstFactory.BuildStringNode(rtnKey), model.GetAstIdentifierForOutputIndex(idx))); var dict = new DictionaryExpressionBuilder(); foreach (var kvp in kvps) { dict.AddKey(kvp.Key); dict.AddValue(kvp.Value); } resultAst.Add(AstFactory.BuildAssignment(model.AstIdentifierForPreview, dict.ToFunctionCall())); }
/// <summary> /// Compiles a collection of Dynamo nodes into a function definition for a custom node. /// </summary> /// <param name="functionId"></param> /// <param name="returnKeys"></param> /// <param name="functionName"></param> /// <param name="funcBody"></param> /// <param name="outputNodes"></param> /// <param name="parameters"></param> /// <param name="verboseLogging"></param> internal void CompileCustomNodeDefinition( Guid functionId, IEnumerable <string> returnKeys, string functionName, IEnumerable <NodeModel> funcBody, IEnumerable <AssociativeNode> outputNodes, IEnumerable <TypedParameter> parameters, bool verboseLogging) { OnAstNodeBuilding(functionId); var functionBody = new CodeBlockNode(); var asts = CompileToAstNodes(funcBody, CompilationContext.None, verboseLogging); functionBody.Body.AddRange(asts.SelectMany(t => t.Item2)); var outputs = outputNodes.ToList(); if (outputs.Count > 1) { /* rtn_dict = Dictionary.ByKeysValues({key0, ..., keyn}, {out0, ..., outn}); * return = rtn_dict; */ // return dictionary, holds all outputs string rtnName = "__temp_rtn_" + functionId.ToString().Replace("-", String.Empty); //// indexers for each output var indexers = returnKeys != null ? returnKeys.Select(AstFactory.BuildStringNode) as IEnumerable <AssociativeNode> : Enumerable.Range(0, outputs.Count).Select(AstFactory.BuildIntNode); // Create AST for Dictionary initialization var kvps = outputs.Zip(indexers, (outputId, indexer) => new KeyValuePair <AssociativeNode, AssociativeNode>(indexer, outputId)); var dict = new DictionaryExpressionBuilder(); foreach (var kvp in kvps) { dict.AddKey(kvp.Key); dict.AddValue(kvp.Value); } functionBody.Body.Add(AstFactory.BuildAssignment(AstFactory.BuildIdentifier(rtnName), dict.ToFunctionCall())); // finally, return the return array functionBody.Body.Add(AstFactory.BuildReturnStatement(AstFactory.BuildIdentifier(rtnName))); } else { // For single output, directly return that identifier or null. AssociativeNode returnValue = outputs.Count == 1 && outputs[0] != null ? outputs[0] : new NullNode(); functionBody.Body.Add(AstFactory.BuildReturnStatement(returnValue)); } Type allTypes = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var); //Create a new function definition var functionDef = new FunctionDefinitionNode { Name = functionName.Replace("-", string.Empty), Signature = new ArgumentSignatureNode { Arguments = parameters.Select(param => AstFactory.BuildParamNode(param.Name, param.Type)).ToList() }, FunctionBody = functionBody, ReturnType = allTypes }; OnAstNodeBuilt(functionId, new[] { functionDef }); }