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> 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.ComponentQueryField:
                yield return(RoslynBuilder.LocalVariableReference(v.DeclarationModel.VariableName));

                break;

            case VariableType.FunctionParameter:
                var variableDeclarationModel = v.DeclarationModel;
                if (variableDeclarationModel.IsGeneratedEcsComponent(out var groupDeclaration))
                {
                    var relevantContext = translator.FindContext(groupDeclaration);
                    if (relevantContext == null)
                    {
                        var variableName = v.DeclarationModel.Name;
                        translator.AddError(v, $"Could not find a matching component query for variable \"{variableName}\"");
                        throw new InvalidOperationException("No matching translation context for Declaration");
                    }
                    translator.context.RecordComponentAccess(relevantContext, v.DeclarationModel.DataType, translator.IsRecordingComponentAccesses);
                    yield return(RoslynBuilder.ArgumentReference(translator.context.GetComponentVariableName(groupDeclaration, variableDeclarationModel.DataType)));
                }
                else
                {
                    if (variableDeclarationModel.IsGeneratedEntity())
                    {
                        translator.context.RecordEntityAccess(variableDeclarationModel);
                    }
                    yield return(RoslynBuilder.ArgumentReference(variableDeclarationModel.VariableName));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }