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> 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)); } }
IEnumerable <MemberDeclarationSyntax> BuildComponentMembers(RoslynTranslator translator) { var states = new List <SwitchSectionSyntax>(); var variables = new Dictionary <string, FieldDeclarationSyntax>(); var stateIndex = 0; // Add members (MoveNext + variables) from coroutine nodes in stack var stack = Parent.IterationContext.Query; BuildStack(translator, stack, ref variables, ref states, ref stateIndex); // Fields var members = new List <MemberDeclarationSyntax> { RoslynBuilder.DeclareField( typeof(int), RoslynEcsBuilder.CoroutineStateVariableName, AccessibilityFlags.Private) }; members.AddRange(variables.Values); // Parameters + Arguments foreach (var component in m_AccessedComponents) { var componentName = GetComponentVariableName(IterationContext.Query, component); var componentType = component.Resolve(IterationContext.Stencil); m_Parameters.Add( Argument(IdentifierName(componentName)) .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword)), Parameter(Identifier(componentName)) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(TypeSystem.BuildTypeSyntax(componentType))); } foreach (var localVariable in IterationContext.Query.FunctionVariableModels) { m_Parameters.Add( Argument(IdentifierName(localVariable.Name)), Parameter(Identifier(localVariable.Name)) .WithType(TypeSystem.BuildTypeSyntax(localVariable.DataType.Resolve(IterationContext.Stencil)))); } // Create MoveNext method members.Add( RoslynBuilder.DeclareMethod(k_MoveNext, AccessibilityFlags.Public, typeof(bool)) .WithParameterList( ParameterList(SeparatedList(m_Parameters.Values))) .WithBody( Block( SwitchStatement(IdentifierName(RoslynEcsBuilder.CoroutineStateVariableName)) .WithOpenParenToken(Token(SyntaxKind.OpenParenToken)) .WithCloseParenToken(Token(SyntaxKind.CloseParenToken)) .WithSections(List(states)), ReturnStatement( LiteralExpression(SyntaxKind.FalseLiteralExpression))))); return(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> 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> 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 IEnumerable <SyntaxNode> BuildFunctionCall(this RoslynTranslator translator, FunctionCallNodeModel call, IPortModel portModel) { if (call.MethodInfo == null) { yield break; } var instance = BuildArgumentList(translator, call, out var argumentList); var typeArgumentList = new List <TypeSyntax>(); if (call.MethodInfo.IsGenericMethod) { foreach (var typeArgument in call.TypeArguments) { typeArgumentList.Add(TypeSystem.BuildTypeSyntax(typeArgument.Resolve(translator.Stencil))); } } TypeArgumentListSyntax typeArgList = null; if (typeArgumentList.Any()) { typeArgList = SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(typeArgumentList.First())); } SyntaxNode method = RoslynBuilder.MethodInvocation(call.Title, call.MethodInfo, instance, argumentList, typeArgList); yield return(method); }
public static IEnumerable <SyntaxNode> BuildInlineExpression(this RoslynTranslator translator, InlineExpressionNodeModel v, IPortModel portModel) { var expressionCode = "var ___exp = (" + v.Expression + ")"; var syntaxTree = CSharpSyntaxTree.ParseText(expressionCode); var buildInlineExpression = syntaxTree.GetRoot().DescendantNodesAndSelf().OfType <ParenthesizedExpressionSyntax>().FirstOrDefault(); yield return(buildInlineExpression); }
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> 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 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 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> 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> 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> 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(); } }
public static IEnumerable <SyntaxNode> BuildFunctionRefCall(this RoslynTranslator translator, FunctionRefCallNodeModel call, IPortModel portModel) { if (call.Function.Destroyed) { yield break; } ExpressionSyntax instance = BuildArgumentList(translator, call, out var argumentList); if (!call.Function.IsInstanceMethod) { instance = SyntaxFactory.IdentifierName(((VSGraphModel)call.Function.GraphModel).TypeName); } InvocationExpressionSyntax invocationExpressionSyntax = null; #if UNITY_EDITOR var instancePort = call.InstancePort; if (instancePort != null && instancePort.DataType.GraphModelReference != null) { var genericTypeName = call.InstancePort.DataType.Name(translator.Stencil); invocationExpressionSyntax = FunctionInvokeExpression(genericTypeName, call.Function.CodeTitle, instance, argumentList); } #endif // not a VisualBehaviour reference method call if (invocationExpressionSyntax == null) { invocationExpressionSyntax = instance == null || (instance is LiteralExpressionSyntax && (instance).IsKind(SyntaxKind.NullLiteralExpression)) ? SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(call.Function.CodeTitle)) : SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, instance, SyntaxFactory.IdentifierName(call.Function.CodeTitle))) ; invocationExpressionSyntax = invocationExpressionSyntax.WithArgumentList( SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argumentList))); } if (portModel == null) { yield return(SyntaxFactory.ExpressionStatement( invocationExpressionSyntax) .NormalizeWhitespace()); } else { yield return(invocationExpressionSyntax.NormalizeWhitespace()); } }
public static List <StatementSyntax> BuildLocalDeclarations(RoslynTranslator roslynTranslator, IFunctionModel stack) { var localDeclarationNodes = new List <StatementSyntax>(); if (stack.VariableDeclarations == null) { return(localDeclarationNodes); } localDeclarationNodes.AddRange(stack.VariableDeclarations .Where(localDecl => localDecl.VariableType == VariableType.FunctionVariable) .Select(localDecl => localDecl.DeclareLocalVariable(roslynTranslator))); return(localDeclarationNodes); }
public static IEnumerable <SyntaxNode> BuildIfCondition(this RoslynEcsTranslator translator, IfConditionNodeModel statement, IPortModel portModel) { // TODO: de-duplicate code after if stacks var firstThenStack = RoslynTranslator.GetConnectedStack(statement, 0); var firstElseStack = RoslynTranslator.GetConnectedStack(statement, 1); // this enables more elegant code generation with no duplication // find first stack reachable from both then/else stacks var endStack = RoslynTranslator.FindCommonDescendant(firstThenStack, firstElseStack); if (endStack != null) { // Debug.Log($"If in stack {statement.parentStackModel} Common descendant: {endStack}"); // building the branches will stop at the common descendant translator.EndStack = endStack; } // ie. follow outputs, find all stacks with multiple inputs, compare them until finding the common one if it exists // BuildStack should take an abort stack parameter, returning when recursing on it // the parent buildStack call will then continue on this end stack var thenBlock = Block(); if (endStack != firstThenStack) { translator.BuildStack(firstThenStack, ref thenBlock, StackExitStrategy.Inherit); } var elseBlock = Block(); if (endStack != firstElseStack) { translator.BuildStack(firstElseStack, ref elseBlock, StackExitStrategy.Inherit); } var ifNode = RoslynBuilder.IfStatement( translator.BuildPort(statement.IfPort).SingleOrDefault(), thenBlock, elseBlock); yield return(ifNode); }
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> BuildLoop(this RoslynTranslator translator, LoopNodeModel statement, IPortModel portModel) { IPortModel outputPortModel = statement.OutputPort; if (outputPortModel == null) { yield break; } LoopStackModel loopStackModel = outputPortModel.ConnectionPortModels.FirstOrDefault()?.NodeModel as LoopStackModel; if (loopStackModel == null) { yield break; } foreach (var statementSyntax in translator.BuildNode(loopStackModel)) { yield return(statementSyntax); } }
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> BuildFunctionRefCall(this RoslynTranslator translator, FunctionRefCallNodeModel call, IPortModel portModel) { if (call.Function.Destroyed) { yield break; } ExpressionSyntax instance = BuildArgumentList(translator, call, out var argumentList); if (!call.Function.IsInstanceMethod) { instance = SyntaxFactory.IdentifierName(((VSGraphModel)call.Function.GraphModel).TypeName); } var invocationExpressionSyntax = instance == null || instance is LiteralExpressionSyntax && instance.IsKind(SyntaxKind.NullLiteralExpression) ? SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(call.Function.CodeTitle)) : SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, instance, SyntaxFactory.IdentifierName(call.Function.CodeTitle))) ; invocationExpressionSyntax = invocationExpressionSyntax.WithArgumentList( SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argumentList))); if (portModel == null) { yield return(SyntaxFactory.ExpressionStatement( invocationExpressionSyntax) .NormalizeWhitespace()); } else { yield return(invocationExpressionSyntax.NormalizeWhitespace()); } }
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)); }
static void BuildStack(RoslynTranslator translator, IStackModel stack, ref Dictionary <string, FieldDeclarationSyntax> variables, ref List <SwitchSectionSyntax> states, ref int stateIndex) { translator.RegisterBuiltStack(stack); foreach (var node in stack.NodeModels) { switch (node) { case IfConditionNodeModel _: translator.AddError(node, "Coroutine (e.g. Wait) and Condition nodes can't coexist within the same stack for now. This feature is coming in a further release"); continue; case ReturnNodeModel _: translator.AddError(node, "Coroutine (e.g. Wait) and Return nodes can't coexist within the same stack for now. This feature is coming in a further release"); continue; } var blocks = translator.BuildNode(node); if (node is CoroutineNodeModel coroutineNode) { foreach (var variable in coroutineNode.Fields) { if (variables.ContainsKey(variable.Key)) { continue; } variables.Add(variable.Key, variable.Value); } foreach (var block in blocks) { states.Add(SwitchSection() .WithLabels( SingletonList <SwitchLabelSyntax>( CaseSwitchLabel( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(stateIndex))))) .WithStatements( SingletonList(block as StatementSyntax))); stateIndex++; } } else { var statements = new List <StatementSyntax>(); foreach (var block in blocks) { switch (block) { case StatementSyntax statementNode: statements.Add(statementNode); break; case ExpressionSyntax expressionNode: statements.Add( ExpressionStatement(expressionNode) .WithAdditionalAnnotations( new SyntaxAnnotation(Annotations.AnnotationKind, node.NodeAssetReference.GetInstanceID().ToString()))); break; default: throw new InvalidOperationException("Expected a statement or expression " + $"node, found a {node.GetType()} when building {block}"); } } states.Add(SwitchSection() .WithLabels( SingletonList <SwitchLabelSyntax>( CaseSwitchLabel( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(stateIndex))))) .WithStatements( SingletonList((StatementSyntax)Block(statements) .AddStatements( RoslynEcsBuilder.BuildCoroutineNextState(), ReturnStatement( LiteralExpression(SyntaxKind.TrueLiteralExpression)))))); stateIndex++; } } foreach (var outputPort in stack.OutputPorts) { foreach (var connectedStack in outputPort.ConnectionPortModels) { if (connectedStack.NodeModel is IStackModel nextStack) { BuildStack(translator, nextStack, ref variables, ref states, ref stateIndex); } } } }
public static IEnumerable <SyntaxNode> BuildStaticConstantNode(this RoslynTranslator translator, SystemConstantNodeModel model, IPortModel portModel) { yield return(SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName(model.DeclaringType.Name(translator.Stencil)), SyntaxFactory.IdentifierName(model.Identifier))); }
public static IEnumerable <SyntaxNode> BuildThisNode(this RoslynTranslator translator, ThisNodeModel model, IPortModel portModel) { yield return(SyntaxFactory.ThisExpression()); }
public static IEnumerable <SyntaxNode> BuildUnaryOperator(this RoslynTranslator translator, UnaryOperatorNodeModel model, IPortModel portModel) { yield return(RoslynBuilder.UnaryOperator(model.kind, translator.BuildPort(model.InputPort).SingleOrDefault())); }
public ClassDeclarationSyntax Build(RoslynTranslator translator, VSGraphModel graphModel) { var baseClass = m_NeedToCompleteDependenciesFirst ? nameof(ComponentSystem) : nameof(JobComponentSystem); m_ClassDeclaration = m_ClassDeclaration.WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( IdentifierName(baseClass))))); foreach (var queryTracking in m_QueryHasStateTracking) { var trackingMembers = new List <MemberDeclarationSyntax>(); if (queryTracking.Value.Tracking) { trackingMembers.Add( FieldDeclaration( VariableDeclaration( PredefinedType( Token(SyntaxKind.BoolKeyword))) .WithVariables( SingletonSeparatedList( VariableDeclarator( Identifier("Processed"))))) .WithModifiers( TokenList( Token(SyntaxKind.InternalKeyword)))); } DeclareComponent <ISystemStateComponentData>(queryTracking.Value.ComponentName, trackingMembers); } foreach (var eventSystem in m_EventSystems) { // ClearEvents<TestEvent2>.Initialize(World); InitializationStatements.Add(ExpressionStatement(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GenericName( Identifier("EventSystem")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(eventSystem.FullName)))), IdentifierName("Initialize"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName("World"))))))); } if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) != 0) { DeclareAndInitField(typeof(TracingRecorderSystem), nameof(TracingRecorderSystem), initValue: InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("World"), GenericName( Identifier(nameof(World.GetExistingSystem))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(nameof(TracingRecorderSystem)))))))); } HashSet <string> declaredQueries = new HashSet <string>(); foreach (var group in m_WrittenComponentsPerGroup) { declaredQueries.Add(group.Key.Query.ComponentQueryDeclarationModel.GetId()); DeclareEntityQueries(group.Value); } // declare unused queries in case there's a Count Entities In Query node somewhere foreach (var graphVariable in graphModel.GraphVariableModels.OfType <ComponentQueryDeclarationModel>().Where(q => !declaredQueries.Contains(q.GetId()))) { var args = graphVariable.Components.Select(c => SyntaxFactory.Argument( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("ComponentType"), GenericName( Identifier("ReadOnly")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(c.Component.TypeHandle.Resolve(graphModel.Stencil) .FullName)))))) )); var initValue = MakeInitQueryExpression(args); DeclareAndInitField(typeof(EntityQuery), graphVariable.VariableName, initValue: initValue); } var singletonMembers = new List <FieldDeclarationSyntax>(); var initArguments = new List <AssignmentExpressionSyntax>(); foreach (var graphVariable in graphModel.GraphVariableModels .Where(g => g.VariableType == VariableType.GraphVariable)) { singletonMembers.Add(graphVariable.DeclareField(translator, false) .WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.VariableAnnotationKind))); initArguments.Add(RoslynBuilder.Assignment( IdentifierName(graphVariable.VariableName), translator.Constant(graphVariable.InitializationModel.ObjectValue, m_Stencil))); } if (singletonMembers.Any()) { DeclareComponent <IComponentData>(SingletonComponentTypeName, singletonMembers); InitializationStatements.Add(ExpressionStatement( RoslynBuilder.MethodInvocation( nameof(EntityManager.CreateEntity), IdentifierName(nameof(EntityManager)), new[] { Argument(TypeOfExpression(IdentifierName(SingletonComponentTypeName))) }, Enumerable.Empty <TypeSyntax>()))); InitializationStatements.Add( ExpressionStatement( RoslynBuilder.MethodInvocation( SafeGuardNamingSystem.SetSingletonName, null, new[] { Argument(RoslynBuilder.DeclareNewObject( IdentifierName(SingletonComponentTypeName), Enumerable.Empty <ArgumentSyntax>(), initArguments)) }, Enumerable.Empty <TypeSyntax>()))); } // TODO : Remove this once there is real Systems' dependency tool var attributes = new List <AttributeListSyntax>(); foreach (var assetModel in m_Stencil.UpdateAfter.Where(a => a.GraphModel.Stencil is EcsStencil)) { RegisterAttributes <UpdateAfterAttribute>(attributes, assetModel.Name); } foreach (var assetModel in m_Stencil.UpdateBefore.Where(a => a.GraphModel.Stencil is EcsStencil)) { RegisterAttributes <UpdateBeforeAttribute>(attributes, assetModel.Name); } m_ClassDeclaration = m_ClassDeclaration .AddAttributeLists(attributes.ToArray()) .AddMembers(m_ClassMembers.OrderBy(x => x is FieldDeclarationSyntax ? 0 : 1).ToArray()); if (m_InitializationStatements != null) { var onCreateManagerOverride = RoslynBuilder.DeclareMethod( SafeGuardNamingSystem.OnCreateManagerName, AccessibilityFlags.Protected | AccessibilityFlags.Override, typeof(void)); m_ClassDeclaration = m_ClassDeclaration .AddMembers( onCreateManagerOverride.WithBody( Block(m_InitializationStatements))); } if (m_SingletonUpdateSyntax != null) { AddStatement(m_SingletonUpdateSyntax); } var onUpdateBlock = Block(m_UpdateStatements); return(m_ClassDeclaration.AddMembers( RoslynEcsTranslator.MakeOnUpdateOverride( onUpdateBlock, m_NeedToCompleteDependenciesFirst, m_CreatedManagers))); }
void BuildIfConditionNode(IfConditionNodeModel node, RoslynEcsTranslator translator, int stateIndex) { translator.BuildNode(node); var firstThenStack = RoslynTranslator.GetConnectedStack(node, 0); var firstElseStack = RoslynTranslator.GetConnectedStack(node, 1); var ifState = m_States[stateIndex]; var ifIndex = GetCurrentStateIndex(); var endStackIndex = 0; if (translator.EndStack != null) { m_StackIndexes.TryGetValue(translator.EndStack, out endStackIndex); } // Reserve then/else/complete states first var thenIndex = ifIndex; var thenBlock = Block().AddStatements(ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression))); StateData thenState = null; if (firstThenStack != null) { if (firstThenStack == translator.EndStack && endStackIndex != 0) { thenBlock = Block().AddStatements(BuildGoToState(endStackIndex)); } else { thenIndex += 1; thenState = RequestNewState(); TryAddStackIndex(firstThenStack, thenIndex); thenBlock = Block().AddStatements(BuildGoToState(thenIndex)); } } var elseIndex = thenIndex + 1; var elseBlock = Block().AddStatements(ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression))); StateData elseState = null; if (firstElseStack != null) { if (firstElseStack == translator.EndStack && endStackIndex != 0) { elseBlock = Block().AddStatements(BuildGoToState(endStackIndex)); } else { elseState = RequestNewState(); TryAddStackIndex(firstElseStack, elseIndex); elseBlock = Block().AddStatements(BuildGoToState(elseIndex)); } } // Then Build stacks ifState.Statements.Add(RoslynBuilder.IfStatement( translator.BuildPort(node.IfPort).SingleOrDefault(), thenBlock, elseBlock) .WithAdditionalAnnotations( new SyntaxAnnotation(Annotations.VSNodeMetadata, node.Guid.ToString()))); ifState.Statements.Add(ReturnStatement(LiteralExpression(SyntaxKind.TrueLiteralExpression))); ifState.SkipStateBuilding = true; var reserveEndStackState = translator.EndStack != null && translator.EndStack != firstElseStack && translator.EndStack != firstThenStack && endStackIndex == 0; if (reserveEndStackState) { var endState = RequestNewState(); endState.NextStateIndex = GetNextStateIndex(translator.EndStack); TryAddStackIndex(translator.EndStack, GetCurrentStateIndex()); } var origBuiltStacks = translator.BuiltStacks; translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); if (translator.EndStack != firstThenStack) { if (translator.EndStack != null && thenState != null) { thenState.NextStateIndex = m_StackIndexes[translator.EndStack]; } BuildStack(translator, firstThenStack, thenIndex, StackExitStrategy.Inherit); } var partialStacks = translator.BuiltStacks; translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); if (translator.EndStack != firstElseStack) { if (translator.EndStack != null && elseState != null) { elseState.NextStateIndex = m_StackIndexes[translator.EndStack]; } BuildStack(translator, firstElseStack, elseIndex, StackExitStrategy.Inherit); } translator.BuiltStacks.UnionWith(partialStacks); }
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)); }