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