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())); } }
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)); }
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)); }
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(); } }
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)); } }
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> 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); }