public static IEnumerable <SyntaxNode> BuildBinaryOperator(this RoslynEcsTranslator translator, BinaryOperatorNodeModel model, IPortModel portModel)
        {
            if (model.kind == BinaryOperatorKind.Equals)
            {
                yield return(InvocationExpression(
                                 MemberAccessExpression(
                                     SyntaxKind.SimpleMemberAccessExpression,
                                     PredefinedType(Token(SyntaxKind.ObjectKeyword)),
                                     IdentifierName("Equals")))
                             .WithArgumentList(
                                 ArgumentList(
                                     SeparatedList(new[]
                {
                    Argument((ExpressionSyntax)translator.BuildPort(model.InputPortA).SingleOrDefault()),
                    Argument((ExpressionSyntax)translator.BuildPort(model.InputPortB).SingleOrDefault())
                }))));
            }

            else
            {
                yield return(RoslynBuilder.BinaryOperator(model.kind,
                                                          translator.BuildPort(model.InputPortA).SingleOrDefault(),
                                                          translator.BuildPort(model.InputPortB).SingleOrDefault()));
            }
        }
예제 #2
0
        public static IEnumerable <SyntaxNode> BuildSetVariable(this RoslynEcsTranslator translator, SetVariableNodeModel statement, IPortModel portModel)
        {
            if (statement.InstancePort.ConnectionPortModels.First().NodeModel is VariableNodeModel variableNode &&
                variableNode.ReferencedObject is IVariableDeclarationModel &&
                variableNode.DeclarationModel.VariableType == VariableType.GraphVariable)
            {
                translator.context.RequestSingletonUpdate();
            }

            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));
        }
예제 #3
0
        public static IEnumerable <SyntaxNode> BuildGetPropertyNode(this RoslynEcsTranslator translator, GetPropertyGroupNodeModel model, IPortModel portModel)
        {
            var instancePort = model.InstancePort;
            var input        = !instancePort.Connected ? 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> BuildReturn(this RoslynEcsTranslator translator,
                                                    ReturnNodeModel returnModel, IPortModel portModel)
 {
     if (translator.context is CoroutineContext coroutineContext)
     {
         if (returnModel.ParentStackModel.OwningFunctionModel is CoroutineStackModel)
         {
             yield return(ReturnStatement(LiteralExpression(SyntaxKind.TrueLiteralExpression)));
         }
         else
         {
             coroutineContext.SkipStateBuilding = true;
             yield return(ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression)));
         }
     }
     else
     {
         if (returnModel.InputPort == null)
         {
             yield return(ReturnStatement());
         }
         else
         {
             yield return(ReturnStatement(
                              translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax));
         }
     }
 }
 public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
 {
     if (m_Model.InputsById.TryGetValue(node.Identifier.Text, out var portModel))
     {
         return(m_Translator.BuildPort(portModel).FirstOrDefault());
     }
     return(base.VisitIdentifierName(node));
 }
예제 #6
0
        public static IEnumerable <SyntaxNode> BuildVariable(this RoslynEcsTranslator translator, IVariableModel v, IPortModel portModel)
        {
            if (v is IConstantNodeModel model)
            {
                if (model.ObjectValue != null)
                {
                    yield return(translator.Constant(model.ObjectValue, translator.Stencil, model.Type));
                }

                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.GraphVariable:
                yield return(translator.context.GetSingletonVariable(v.DeclarationModel));

                break;

            case VariableType.FunctionVariable:
            case VariableType.ComponentGroupField:
                yield return(RoslynBuilder.LocalVariableReference(v.DeclarationModel.VariableName));

                break;

            case VariableType.FunctionParameter:
                var variableDeclarationModel = v.DeclarationModel;
                if (variableDeclarationModel.VariableIsAGeneratedEcsComponent(out var groupDeclaration))
                {
                    var relevantContext = translator.FindContext(groupDeclaration);
                    translator.context.RecordComponentAccess(relevantContext, v.DeclarationModel.DataType, translator.IsRecordingComponentAccesses);
                    yield return(RoslynBuilder.ArgumentReference(translator.context.GetComponentVariableName(groupDeclaration, variableDeclarationModel.DataType)));
                }
                else
                {
                    yield return(RoslynBuilder.ArgumentReference(v.DeclarationModel.VariableName));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #7
0
            public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
            {
                var portModel = m_Model.InputsById[node.Identifier.Text];

                if (portModel != null)
                {
                    return(m_Translator.BuildPort(portModel).FirstOrDefault());
                }
                return(base.VisitIdentifierName(node));
            }
        public static IEnumerable <SyntaxNode> BuildReturn(this RoslynEcsTranslator translator, ReturnNodeModel returnModel, IPortModel portModel)
        {
            // TODO Implement Return statement in coroutine
            if (translator.context is CoroutineContext)
            {
                translator.AddError(returnModel, "Return node isn't allowed in Coroutine (e.g. Wait) execution stack for now. This feature is coming in a further release");
                yield break;
            }

            if (returnModel.InputPort == null)
            {
                yield return(ReturnStatement());
            }
            else
            {
                yield return(ReturnStatement(
                                 translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax));
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
 public static IEnumerable <SyntaxNode> BuildReturn(this RoslynEcsTranslator translator, ReturnNodeModel returnModel, IPortModel portModel)
 {
     yield return(ReturnStatement(
                      translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax));
 }
        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);
        }