public static IEnumerable <SyntaxNode> BuildMethod(this RoslynTranslator roslynTranslator, IFunctionModel stack, IPortModel portModel) { roslynTranslator.ClearBuiltStacks(); var generatedName = roslynTranslator.MakeUniqueName(stack.CodeTitle); var methodSyntaxNode = RoslynBuilder.DeclareMethod( generatedName, AccessibilityFlags.Public, stack.ReturnType.Resolve(roslynTranslator.Stencil)); var localDeclarationNodes = BuildLocalDeclarations(roslynTranslator, stack); var argumentNodes = BuildArguments(roslynTranslator.Stencil, stack); methodSyntaxNode = methodSyntaxNode.WithParameterList(SyntaxFactory.ParameterList( SyntaxFactory.SeparatedList(argumentNodes.ToArray()))); methodSyntaxNode = methodSyntaxNode.WithBody(SyntaxFactory.Block(localDeclarationNodes.ToArray())); if (stack.EnableProfiling) { throw new NotImplementedException("BuildMethod Profiling not implemented"); // methodSyntaxNode = methodSyntaxNode.WithAdditionalAnnotations(InstrumentForProfiling.profilingAnnotation); } BlockSyntax stackBlock = SyntaxFactory.Block(); roslynTranslator.BuildStack(stack, ref stackBlock); foreach (var statement in stackBlock.Statements) { methodSyntaxNode = methodSyntaxNode.AddBodyStatements(statement); } yield return(methodSyntaxNode); }
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 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> 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)); }