Exemple #1
0
        public void GenerateInto(Scope scope)
        {
            var hasReturn = SyntaxUtil.HasReturnStatement(Body);

            if (scope.IsInStatementContext)
            {
                if (hasReturn == false)
                {
                    SyntaxUtil.CreateReturnStatement(this.returnType, Body, scope.StatementContext.TryCreateResultStatement);
                }

                foreach (var b in Body)
                {
                    scope.StatementContext.AddStatement(b);
                }
            }
            else
            {
                if (hasReturn == false)
                {
                    SyntaxUtil.CreateReturnStatement(this.returnType, Body, (ExpressionSyntax e, out StatementSyntax s) => {
                        s = SyntaxFactory.ReturnStatement(e)
                            .WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                        return(true);
                    });
                }

                scope.Context.AddExpression(
                    SyntaxUtil.CreateImmediatelyInvokedFunction(returnType, Body));
            }
        }
        public IStatementContext AddStatement(StatementSyntax statement)
        {
            if (statement is ExpressionStatementSyntax exp)
            {
                subexpressions.Add(exp.Expression);
            }
            else
            {
                var returnType = ScriptDataType.Void;

                var annotations = statement.GetAnnotations(ScriptGenAnnotations.TypeAnnotationKind);

                if (annotations.Any())
                {
                    returnType = (ScriptDataType)int.Parse(annotations.First().Data);
                }

                subexpressions.Add(SyntaxUtil.CreateImmediatelyInvokedFunction(returnType, new[] { statement }));
            }

            return(this);
        }
        public void GenerateInto(Scope scope)
        {
            Debug.Assert(scope == this.containingScope, "Generating into an unexpected scope");
            Debug.Assert(this.condition != null, "Condition expression was not provided");
            Debug.Assert(whenTrueStatements.Any(), "WhenTrue was not provided");

            var generatedStatements = new List <StatementSyntax>();

            if (this.producesValue)
            {
                var resultType = SyntaxUtil.ScriptTypeSyntax(this.containingScope.Type);

                // Ensure that if a value must be produced, we have an else with default value
                if (whenFalseStatements.Any() == false)
                {
                    whenFalseStatements.Add(ExpressionStatement(DefaultExpression(resultType)));
                }

                if (this.shouldHoist)
                {
                    var initialization = DefaultExpression(resultType);

                    generatedStatements.Add(LocalDeclarationStatement(VariableDeclaration(resultType)
                                                                      .WithVariables(SingletonSeparatedList(
                                                                                         VariableDeclarator(resultVariable.Identifier)
                                                                                         .WithInitializer(
                                                                                             EqualsValueClause(initialization)))))
                                            .WithAdditionalAnnotations(ScriptGenAnnotations.HoistedResultVar));

                    if (HasResultVarAssignment(whenTrueStatements) == false)
                    {
                        InsertResultVarAssignment(whenTrueStatements);
                    }

                    if (whenFalseStatements.Any() && HasResultVarAssignment(whenFalseStatements) == false)
                    {
                        InsertResultVarAssignment(whenFalseStatements);
                    }
                }
                else
                {
                    if (SyntaxUtil.HasReturnStatement(whenTrueStatements) == false)
                    {
                        SyntaxUtil.CreateReturnStatement(this.containingScope.Type, whenTrueStatements, (ExpressionSyntax e, out StatementSyntax s) =>
                        {
                            s = ReturnStatement(e).WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                            return(true);
                        });
                    }

                    if (SyntaxUtil.HasReturnStatement(whenFalseStatements) == false)
                    {
                        SyntaxUtil.CreateReturnStatement(this.containingScope.Type, whenFalseStatements, (ExpressionSyntax e, out StatementSyntax s) =>
                        {
                            s = ReturnStatement(e).WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement);
                            return(true);
                        });
                    }
                }
            }

            var trueBlock = Block(whenTrueStatements);

            var unreachable = this.condition.IsEquivalentTo(SyntaxUtil.LiteralExpression(true));

            if (unreachable == false && whenFalseStatements.Any())
            {
                StatementSyntax falseBlock = Block(whenFalseStatements);

                // Collapse if/else if/...
                if (whenFalseStatements.Count == 1 && whenFalseStatements[0] is IfStatementSyntax ifStatement)
                {
                    falseBlock = ifStatement;
                }

                generatedStatements.Add(
                    IfStatement(condition, trueBlock, ElseClause(falseBlock))
                    .WithLeadingTrivia(SyntaxFactory.Whitespace(Environment.NewLine))
                    .WithAdditionalAnnotations(ScriptGenAnnotations.IfStatement));
            }
            else
            {
                generatedStatements.Add(
                    IfStatement(condition, trueBlock)
                    .WithLeadingTrivia(SyntaxFactory.Whitespace(Environment.NewLine))
                    .WithAdditionalAnnotations(ScriptGenAnnotations.IfStatement));
            }

            if (this.shouldHoist == false && this.producesValue)
            {
                var last = generatedStatements.Last();

                generatedStatements.Remove(last);
                generatedStatements.Add(last.WithAdditionalAnnotations(ScriptGenAnnotations.ResultStatement));
            }

            if (scope.IsInStatementContext || this.shouldHoist)
            {
                // Insert statements into appropriate statement context
                foreach (var statement in generatedStatements)
                {
                    scope.StatementContext.AddStatement(statement);
                }

                if (this.shouldHoist)
                {
                    // Insert result var into place
                    scope.Context.AddExpression(this.resultVariable);
                }
            }
            else
            {
                // Insert IIFE into place
                scope.Context.AddExpression(SyntaxUtil.CreateImmediatelyInvokedFunction(scope.Type, generatedStatements));
            }
        }