public static IEnumerable <SyntaxNode> BuildSetPropertyNode(this RoslynTranslator translator, SetPropertyGroupNodeModel model, IPortModel portModel) { SyntaxNode leftHand; IPortModel instancePort = model.InstancePort; if (!instancePort.Connected) { leftHand = SyntaxFactory.ThisExpression(); } else { leftHand = translator.BuildPort(instancePort).SingleOrDefault(); } foreach (var member in model.Members) { string memberId = member.GetId(); IPortModel inputPort = model.InputsById[memberId]; SyntaxNode rightHandExpression = translator.BuildPort(inputPort).SingleOrDefault(); if (rightHandExpression == null) { continue; } MemberAccessExpressionSyntax access = RoslynBuilder.MemberReference(leftHand, member.Path[0]); for (int i = 1; i < member.Path.Count; i++) { access = RoslynBuilder.MemberReference(access, member.Path[i]); } yield return(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, access, rightHandExpression as ExpressionSyntax)); } }
public static IEnumerable <SyntaxNode> BuildSetVariable(this RoslynTranslator translator, SetVariableNodeModel statement, IPortModel portModel) { var decl = translator.BuildPort(statement.InstancePort).SingleOrDefault(); var value = translator.BuildPort(statement.ValuePort).SingleOrDefault(); yield return(decl == null || value == null ? null : RoslynBuilder.Assignment(decl, value)); }
public static SyntaxNode SetProperty(RoslynTranslator translator, AssignmentKind kind, IPortModel instancePortModel, IPortModel valuePortModel, params string[] members) { ExpressionSyntax instance = instancePortModel.Connected ? translator.BuildPort(instancePortModel).FirstOrDefault() as ExpressionSyntax : SyntaxFactory.ThisExpression(); ExpressionSyntax value = translator.BuildPort(valuePortModel).FirstOrDefault() as ExpressionSyntax; return(SetProperty(kind, instance, value, members)); }
public static IEnumerable <SyntaxNode> BuildMacroRefNode(this RoslynTranslator translator, MacroRefNodeModel model, IPortModel portModel) { if (model.Macro == null) { translator.AddError( model, $"The asset of macro node {model.Title} is missing."); return(Enumerable.Empty <SyntaxNode>()); } var variableDeclarations = portModel.Direction == Direction.Input ? model.DefinedInputVariables : model.DefinedOutputVariables; var declaration = variableDeclarations.Single(v => v.VariableName == portModel.UniqueId); translator.InMacro.Push(model); var variableNodeModel = ((VSGraphModel)declaration.GraphModel) .FindUsages((VariableDeclarationModel)declaration) .Single(); var returnValue = translator.BuildPort(variableNodeModel.OutputPort); translator.InMacro.Pop(); return(returnValue); }
public static IEnumerable <SyntaxNode> BuildIfCondition(this RoslynTranslator translator, IfConditionNodeModel statement, IPortModel portModel) { // this enables more elegant code generation with no duplication // if() { then(); } else { else(); } // codeAfterIf(); // instead of duplicating the code after the if in each branch // find first stack reachable from both then/else stacks var firstThenStack = RoslynTranslator.GetConnectedStack(statement, 0); var firstElseStack = RoslynTranslator.GetConnectedStack(statement, 1); var endStack = RoslynTranslator.FindCommonDescendant(statement.ParentStackModel, firstThenStack, firstElseStack); if (endStack != null) { // building the branches will stop at the common descendant translator.EndStack = endStack; // Debug.Log($"If in stack {statement.parentStackModel} Common descendant: {endStack}"); } // ie. follow outputs, find all stacks with multiple inputs, compare them until finding the common one if it exists // BuildStack checks the m_EndStack field, returning when recursing on it // the parent buildStack call will then continue on this end stack var origBuiltStacks = translator.BuiltStacks; translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); HashSet <IStackModel> partialStacks = new HashSet <IStackModel>(); StatementSyntax syntax = null; // construct multiple if else if else ... from right to left, starting with the last else foreach (var conditionWithAction in statement.ConditionsWithActionsPorts.Reverse()) { var stack = RoslynTranslator.GetConnectedStack(conditionWithAction.Action); BlockSyntax block = SyntaxFactory.Block(); if (endStack == null || endStack != stack) // stop before the end stack { translator.BuildStack(stack, ref block, StackExitStrategy.Inherit); } if (conditionWithAction.Condition == null) // last else { syntax = block; } else // if = if() { current statement } else { prev statement that might be an if } { var condition = (ExpressionSyntax)translator.BuildPort(conditionWithAction.Condition).SingleOrDefault(); syntax = SyntaxFactory.IfStatement(condition, block) .WithElse(SyntaxFactory.ElseClause(syntax)); } partialStacks.UnionWith(translator.BuiltStacks); translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); } translator.BuiltStacks = partialStacks; yield return(syntax); }
public static SyntaxNode GetProperty(RoslynTranslator translator, IPortModel instancePortModel, params string[] members) { ExpressionSyntax instance = instancePortModel.Connected ? translator.BuildPort(instancePortModel).FirstOrDefault() as ExpressionSyntax : SyntaxFactory.ThisExpression(); return(GetProperty(instance, members)); }
public static IEnumerable <SyntaxNode> BuildUnaryOperator(this RoslynTranslator translator, UnaryOperatorNodeModel model, IPortModel portModel) { var semantic = model.Kind == UnaryOperatorKind.PostDecrement || model.Kind == UnaryOperatorKind.PostIncrement ? RoslynTranslator.PortSemantic.Write : RoslynTranslator.PortSemantic.Read; yield return(RoslynBuilder.UnaryOperator(model.Kind, translator.BuildPort(model.InputPort, semantic).SingleOrDefault())); }
public static IEnumerable <SyntaxNode> BuildReturn(this RoslynTranslator translator, ReturnNodeModel returnModel, IPortModel portModel) { if (returnModel.InputPort == null) { yield return(SyntaxFactory.ReturnStatement()); } else { yield return(SyntaxFactory.ReturnStatement( translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax)); } }
public static IEnumerable <SyntaxNode> BuildReturn(this RoslynTranslator translator, ReturnNodeModel returnModel, IPortModel portModel) { if (returnModel.ParentStackModel.OwningFunctionModel.ReturnType == typeof(void).GenerateTypeHandle(translator.Stencil)) { yield return(SyntaxFactory.ReturnStatement()); } else { yield return(SyntaxFactory.ReturnStatement( translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax)); } }
public static IEnumerable <SyntaxNode> BuildVariable(this RoslynTranslator translator, IVariableModel v, IPortModel portModel) { if (v is IConstantNodeModel constantNodeModel) { if (constantNodeModel.ObjectValue != null) { if (constantNodeModel is IStringWrapperConstantModel) { yield return(translator.Constant(constantNodeModel.ObjectValue.ToString(), translator.Stencil)); } else { yield return(translator.Constant(constantNodeModel.ObjectValue, translator.Stencil)); } } yield break; } if (translator.InMacro.Count > 0 && v.DeclarationModel.VariableType == VariableType.GraphVariable && v.DeclarationModel.Modifiers == ModifierFlags.ReadOnly) { MacroRefNodeModel oldValue = translator.InMacro.Pop(); var syntaxNodes = translator.BuildPort(oldValue.InputsById[v.DeclarationModel.VariableName]); translator.InMacro.Push(oldValue); foreach (var syntaxNode in syntaxNodes) { yield return(syntaxNode); } yield break; } switch (v.DeclarationModel.VariableType) { case VariableType.FunctionVariable: case VariableType.GraphVariable: case VariableType.ComponentQueryField: yield return(RoslynBuilder.LocalVariableReference(v.DeclarationModel.Name)); break; case VariableType.FunctionParameter: yield return(RoslynBuilder.ArgumentReference(v.DeclarationModel.Name)); break; // case VariableType.Literal: // case VariableType.InlineExpression: default: throw new ArgumentOutOfRangeException(); } }
static ExpressionSyntax BuildArgumentList(RoslynTranslator translator, IFunctionCallModel call, out List <ArgumentSyntax> argumentList) { ExpressionSyntax instance = null; if (call is IHasInstancePort modelWithInstancePort && modelWithInstancePort.InstancePort != null) { instance = (ExpressionSyntax)translator.BuildPort(modelWithInstancePort.InstancePort).SingleOrDefault(); } argumentList = new List <ArgumentSyntax>(); foreach (IPortModel port in call.GetParameterPorts()) { var syntaxNode = translator.BuildPort(port).SingleOrDefault(); if (syntaxNode != null) { var argumentNode = syntaxNode as ArgumentSyntax ?? SyntaxFactory.Argument(syntaxNode as ExpressionSyntax); argumentList.Add(argumentNode); } } return(instance); }
public static IEnumerable <SyntaxNode> BuildMethod(this RoslynTranslator roslynTranslator, KeyDownEventModel stack, IPortModel portModel) { BlockSyntax block = SyntaxFactory.Block(); roslynTranslator.BuildStack(stack, ref block); string methodName; switch (stack.mode) { case KeyDownEventModel.EventMode.Pressed: methodName = nameof(Input.GetKeyDown); break; case KeyDownEventModel.EventMode.Released: methodName = nameof(Input.GetKeyUp); break; default: methodName = nameof(Input.GetKey); break; } var conditionExpression = (ExpressionSyntax)roslynTranslator.BuildPort(stack.KeyPort).Single(); IfStatementSyntax keydownCheck = (SyntaxFactory.IfStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(nameof(Input)), SyntaxFactory.IdentifierName(methodName))) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument( conditionExpression)))), block) .NormalizeWhitespace()); roslynTranslator.AddEventRegistration(keydownCheck); yield break; }
public static IEnumerable <SyntaxNode> BuildWhile(this RoslynTranslator translator, WhileHeaderModel whileHeaderModelStatement, IPortModel portModel) { if (whileHeaderModelStatement.IndexVariableDeclarationModel != null) { yield return(whileHeaderModelStatement.IndexVariableDeclarationModel.DeclareLoopIndexVariable()); } var whileBlock = SyntaxFactory.Block(); foreach (var localDeclaration in BuildLocalDeclarations(translator, whileHeaderModelStatement)) { whileBlock = whileBlock.AddStatements(localDeclaration); } translator.BuildStack(whileHeaderModelStatement, ref whileBlock, StackExitStrategy.Continue); IPortModel loopExecutionInputPortModel = whileHeaderModelStatement.InputPort; IPortModel insertLoopPortModel = loopExecutionInputPortModel?.ConnectionPortModels?.FirstOrDefault(); var insertLoopNodeModel = insertLoopPortModel?.NodeModel as IHasMainInputPort; IPortModel conditionInputPortModel = insertLoopNodeModel?.InputPort; SeparatedSyntaxList <ExpressionSyntax> incrementExpressions = SyntaxFactory.SeparatedList <ExpressionSyntax>(); if (whileHeaderModelStatement.IndexVariableDeclarationModel != null) { incrementExpressions = SyntaxFactory.SingletonSeparatedList <ExpressionSyntax>( SyntaxFactory.PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, SyntaxFactory.IdentifierName(whileHeaderModelStatement.IndexVariableDeclarationModel.name))); } yield return(SyntaxFactory.ForStatement(null, SyntaxFactory.SeparatedList <ExpressionSyntax>(), translator.BuildPort(conditionInputPortModel).SingleOrDefault() as ExpressionSyntax, incrementExpressions, whileBlock)); }
public static IEnumerable <SyntaxNode> BuildUnaryOperator(this RoslynTranslator translator, UnaryOperatorNodeModel model, IPortModel portModel) { yield return(RoslynBuilder.UnaryOperator(model.kind, translator.BuildPort(model.InputPort).SingleOrDefault())); }
public static IEnumerable <SyntaxNode> BuildGetPropertyNode(this RoslynTranslator translator, GetPropertyGroupNodeModel model, IPortModel portModel) { var instancePort = model.InstancePort; var input = !instancePort.Connected ? SyntaxFactory.ThisExpression() : translator.BuildPort(instancePort).SingleOrDefault(); if (input == null) { yield break; } var member = model.Members.FirstOrDefault(m => m.GetId() == portModel.UniqueId); if (member.Path == null || member.Path.Count == 0) { yield break; } var access = RoslynBuilder.MemberReference(input, member.Path[0]); for (int i = 1; i < member.Path.Count; i++) { access = RoslynBuilder.MemberReference(access, member.Path[i]); } yield return(access); }
public static IEnumerable <SyntaxNode> BuildForEach(this RoslynTranslator translator, ForEachHeaderModel forEachHeaderModelStatement, IPortModel portModel) { IPortModel loopExecutionInputPortModel = forEachHeaderModelStatement.InputPort; IPortModel insertLoopPortModel = loopExecutionInputPortModel?.ConnectionPortModels?.FirstOrDefault(); var insertLoopNodeModel = insertLoopPortModel?.NodeModel as IHasMainInputPort; IPortModel collectionInputPortModel = insertLoopNodeModel?.InputPort; if (collectionInputPortModel == null || !collectionInputPortModel.Connected || !collectionInputPortModel.DataType.IsVsArrayType(translator.Stencil)) { yield break; } var collectionName = translator.MakeUniqueName("Collection"); SyntaxNode collectionSyntax = translator.BuildPort(collectionInputPortModel).SingleOrDefault(); yield return(RoslynBuilder.DeclareLoopCollectionVariable(collectionSyntax, collectionName)); if (forEachHeaderModelStatement.IndexVariableDeclarationModel != null) { yield return(forEachHeaderModelStatement.IndexVariableDeclarationModel.DeclareLoopIndexVariable(-1)); } if (forEachHeaderModelStatement.CountVariableDeclarationModel != null) { var collectionInput = translator.BuildPort(collectionInputPortModel).SingleOrDefault() as ExpressionSyntax; yield return(forEachHeaderModelStatement.CountVariableDeclarationModel.DeclareLoopCountVariable( collectionInput, collectionName, translator)); } var forEachBlock = SyntaxFactory.Block(); foreach (var localDeclaration in BuildLocalDeclarations(translator, forEachHeaderModelStatement)) { forEachBlock = forEachBlock.AddStatements(localDeclaration); } if (forEachHeaderModelStatement.IndexVariableDeclarationModel != null) { forEachBlock = forEachBlock.AddStatements(SyntaxFactory.ExpressionStatement( SyntaxFactory.PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, SyntaxFactory.IdentifierName(forEachHeaderModelStatement.IndexVariableDeclarationModel.name))) ); } translator.BuildStack(forEachHeaderModelStatement, ref forEachBlock, StackExitStrategy.Continue); var itemModel = forEachHeaderModelStatement.ItemVariableDeclarationModel; if (itemModel == null) { yield break; } yield return(SyntaxFactory.ForEachStatement( SyntaxFactory.IdentifierName("var"), SyntaxFactory.Identifier(itemModel.VariableName), SyntaxFactory.IdentifierName(collectionName), forEachBlock)); }