private BoundBlock BuildBlock(BoundStatement node) { var block = node as BoundBlock; if (block != null) return block; var builder = new BlockBuilder(this); builder.Add(node); return builder.BuildBlock(node.Location); }
private BoundBlock BuildBlock(SyntaxNode syntax, SourceLocation location) { IEnumerable<SyntaxNode> items; var block = syntax as BlockSyntax; if (block != null) items = block.Statements; else items = new[] { syntax }; var builder = new BlockBuilder(this); foreach (var item in items) { var node = item.Accept(this); var statement = node as BoundStatement ?? new BoundExpressionStatement((BoundExpression)node, GetLocation(item)); builder.Add(statement); } return builder.BuildBlock(location ?? SourceLocation.Missing); }
// // rescue stmts ... if (StandardError === $!) { stmts; } // rescue <types> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; } // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; } // internal IfStatementTest/*!*/ Transform(AstGenerator/*!*/ gen, ResultOperation resultOperation) { Assert.NotNull(gen); MSA.Expression condition; if (_types.Length != 0 || _splatType != null) { var comparisonSiteStorage = Ast.Constant(new BinaryOpStorage(gen.Context)); if (_types.Length == 0) { // splat only: condition = MakeCompareSplattedExceptions(gen, comparisonSiteStorage, TransformSplatType(gen)); } else if (_types.Length == 1 && _splatType == null) { condition = MakeCompareException(gen, comparisonSiteStorage, _types[0].TransformRead(gen)); } else { // forall{i}: <temps[i]> = evaluate type[i] var temps = new MSA.Expression[_types.Length + (_splatType != null ? 1 : 0)]; var exprs = new BlockBuilder(); int i = 0; while (i < _types.Length) { var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object)); temps[i] = tmp; exprs.Add(Ast.Assign(tmp, _types[i].TransformRead(gen))); i++; } if (_splatType != null) { var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(IList)); temps[i] = tmp; exprs.Add(Ast.Assign(tmp, TransformSplatType(gen))); i++; } Debug.Assert(i == temps.Length); // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>) i = 0; condition = MakeCompareException(gen, comparisonSiteStorage, temps[i++]); while (i < _types.Length) { condition = Ast.OrElse(condition, MakeCompareException(gen, comparisonSiteStorage, temps[i++])); } if (_splatType != null) { condition = Ast.OrElse(condition, MakeCompareSplattedExceptions(gen, comparisonSiteStorage, temps[i++])); } Debug.Assert(i == temps.Length); // (temps[0] = type[0], ..., temps[n] == type[n], condition) exprs.Add(condition); condition = exprs; } } else { condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable); } return AstUtils.IfCondition(condition, gen.TransformStatements( // <lvalue> = e; (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null, // body: _statements, resultOperation ) ); }
private MSAst.Expression ReduceWorker(bool optimizeDynamicConvert) { MSAst.Expression result; if (_tests.Length > 100) { // generate: // if(x) { // body // goto end // } else { // } // elseBody // end: // // to avoid deeply recursive trees which can stack overflow. BlockBuilder builder = new BlockBuilder(); var label = Ast.Label(); for (int i = 0; i < _tests.Length; i++) { IfStatementTest ist = _tests[i]; builder.Add( Ast.Condition( optimizeDynamicConvert ? TransformAndDynamicConvert(ist.Test, typeof(bool)) : GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, ist.Test), Ast.Block( TransformMaybeSingleLineSuite(ist.Body, GlobalParent.IndexToLocation(ist.Test.StartIndex)), Ast.Goto(label) ), Utils.Empty() ) ); } if (_else != null) { builder.Add(_else); } builder.Add(Ast.Label(label)); result = builder.ToExpression(); } else { // Now build from the inside out if (_else != null) { result = _else; } else { result = AstUtils.Empty(); } int i = _tests.Length; while (i-- > 0) { IfStatementTest ist = _tests[i]; result = GlobalParent.AddDebugInfoAndVoid( Ast.Condition( optimizeDynamicConvert ? TransformAndDynamicConvert(ist.Test, typeof(bool)) : GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, ist.Test), TransformMaybeSingleLineSuite(ist.Body, GlobalParent.IndexToLocation(ist.Test.StartIndex)), result ), new SourceSpan(GlobalParent.IndexToLocation(ist.StartIndex), GlobalParent.IndexToLocation(ist.HeaderIndex)) ); } } return result; }
private MSAst.Expression ReduceWorker(bool optimizeDynamicConvert) { MSAst.Expression result; if (_tests.Length > 100) { // generate: // if(x) { // body // goto end // } else { // } // elseBody // end: // // to avoid deeply recursive trees which can stack overflow. BlockBuilder builder = new BlockBuilder(); var label = Ast.Label(); for (int i = 0; i < _tests.Length; i++) { IfStatementTest ist = _tests[i]; builder.Add( Ast.Condition( optimizeDynamicConvert ? TransformAndDynamicConvert(ist.Test, typeof(bool)) : GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, ist.Test), Ast.Block( TransformMaybeSingleLineSuite(ist.Body, GlobalParent.IndexToLocation(ist.Test.StartIndex)), Ast.Goto(label) ), Utils.Empty() ) ); } if (_else != null) { builder.Add(_else); } builder.Add(Ast.Label(label)); result = builder.ToExpression(); } else { // Now build from the inside out if (_else != null) { result = _else; } else { result = AstUtils.Empty(); } int i = _tests.Length; while (i-- > 0) { IfStatementTest ist = _tests[i]; result = GlobalParent.AddDebugInfoAndVoid( Ast.Condition( optimizeDynamicConvert ? TransformAndDynamicConvert(ist.Test, typeof(bool)) : GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, ist.Test), TransformMaybeSingleLineSuite(ist.Body, GlobalParent.IndexToLocation(ist.Test.StartIndex)), result ), new SourceSpan(GlobalParent.IndexToLocation(ist.StartIndex), GlobalParent.IndexToLocation(ist.HeaderIndex)) ); } } return(result); }
// // rescue stmts ... if (StandardError === $!) { stmts; } // rescue <types> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; } // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; } // /*!*/ internal IfStatementTest Transform(AstGenerator/*!*/ gen, ResultOperation resultOperation) { Assert.NotNull(gen); MSA.Expression condition; if (_types.Length != 0) { var comparisonSiteStorage = Ast.Constant(new BinaryOpStorage(gen.Context)); if (_types.Length == 1) { condition = MakeCompareException(gen, comparisonSiteStorage, _types[0].TransformRead(gen), _types[0] is SplattedArgument); } else { // forall{i}: <temps[i]> = evaluate type[i] var temps = new MSA.Expression[_types.Length]; var exprs = new BlockBuilder(); for (int i = 0; i < _types.Length; i++) { var t = _types[i].TransformRead(gen); var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, t.Type); temps[i] = tmp; exprs.Add(Ast.Assign(tmp, t)); } // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>) condition = MakeCompareException(gen, comparisonSiteStorage, temps[0], _types[0] is SplattedArgument); for (int i = 1; i < _types.Length; i++) { condition = Ast.OrElse(condition, MakeCompareException(gen, comparisonSiteStorage, temps[i], _types[i] is SplattedArgument)); } // (temps[0] = type[0], ..., temps[n] == type[n], condition) exprs.Add(condition); condition = exprs; } } else { condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable); } return AstUtils.IfCondition(condition, gen.TransformStatements( // <lvalue> = e; (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null, // body: _statements, resultOperation ) ); }
// // rescue stmts ... if (StandardError === $!) { stmts; } // rescue <types> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; } // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; } // internal IfStatementTest /*!*/ Transform(AstGenerator /*!*/ gen, ResultOperation resultOperation) { Assert.NotNull(gen); MSA.Expression condition; if (_types.Length != 0 || _splatType != null) { var comparisonSiteStorage = Ast.Constant(new BinaryOpStorage(gen.Context)); if (_types.Length == 0) { // splat only: condition = MakeCompareSplattedExceptions(gen, comparisonSiteStorage, TransformSplatType(gen)); } else if (_types.Length == 1 && _splatType == null) { condition = MakeCompareException(gen, comparisonSiteStorage, _types[0].TransformRead(gen)); } else { // forall{i}: <temps[i]> = evaluate type[i] var temps = new MSA.Expression[_types.Length + (_splatType != null ? 1 : 0)]; var exprs = new BlockBuilder(); int i = 0; while (i < _types.Length) { var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object)); temps[i] = tmp; exprs.Add(Ast.Assign(tmp, _types[i].TransformRead(gen))); i++; } if (_splatType != null) { var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(IList)); temps[i] = tmp; exprs.Add(Ast.Assign(tmp, TransformSplatType(gen))); i++; } Debug.Assert(i == temps.Length); // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>) i = 0; condition = MakeCompareException(gen, comparisonSiteStorage, temps[i++]); while (i < _types.Length) { condition = Ast.OrElse(condition, MakeCompareException(gen, comparisonSiteStorage, temps[i++])); } if (_splatType != null) { condition = Ast.OrElse(condition, MakeCompareSplattedExceptions(gen, comparisonSiteStorage, temps[i++])); } Debug.Assert(i == temps.Length); // (temps[0] = type[0], ..., temps[n] == type[n], condition) exprs.Add(condition); condition = exprs; } } else { condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable); } return(AstUtils.IfCondition(condition, gen.TransformStatements( // <lvalue> = e; (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null, // body: _statements, resultOperation ) )); }
private BoundIf BuildSetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary value) { var withLocal = builder.CreateTemporary(); builder.Add(new BoundSetVariable( withLocal, new BoundGetVariable(_withIdentifiers[withScope.Identifier]), SourceLocation.Missing )); var setter = new BoundSetMember( new BoundGetVariable(withLocal), BoundConstant.Create(fallback.Name), new BoundGetVariable(value), SourceLocation.Missing ); BoundBlock @else; if (withScope.Parent == null) { @else = BuildBlock(BuildSet( fallback, new BoundGetVariable(value) )); } else { @else = BuildBlock(BuildSetWithScope( builder, withScope.Parent, fallback, value )); } return new BoundIf( new BoundHasMember( new BoundGetVariable(withLocal), fallback.Name ), BuildBlock(setter), @else, SourceLocation.Missing ); }
private BoundStatement BuildSet(IIdentifier identifier, BoundExpression value) { switch (identifier.Type) { case IdentifierType.Parameter: return new BoundSetVariable( _scope.GetArgument(identifier), value, SourceLocation.Missing ); case IdentifierType.Scoped: var builder = new BlockBuilder(this); var valueTemporary = builder.CreateTemporary(); builder.Add(new BoundSetVariable( valueTemporary, value, SourceLocation.Missing )); builder.Add(BuildSetWithScope(builder, identifier.WithScope, identifier.Fallback, valueTemporary)); return builder.BuildBlock(SourceLocation.Missing); case IdentifierType.Local: case IdentifierType.Global: if (identifier.Type == IdentifierType.Global) _scope.IsGlobalScopeReferenced = true; if (identifier.Closure == null) return new BoundSetVariable(_scope.GetLocal(identifier), value, SourceLocation.Missing); return new BoundSetVariable( _scope.GetClosureField(identifier), value, SourceLocation.Missing ); /* // These are handled upstream. case IdentifierType.This: case IdentifierType.Null: case IdentifierType.Undefined: case IdentifierType.Arguments: */ default: throw new InvalidOperationException("Cannot find variable of argument"); } }
private BoundIf BuildGetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary result, BoundTemporary withTarget) { var withLocal = builder.CreateTemporary(); builder.Add(new BoundSetVariable( withLocal, new BoundGetVariable(_withIdentifiers[withScope.Identifier]), SourceLocation.Missing )); var getter = new BlockBuilder(this); if (withTarget != null) { getter.Add(new BoundSetVariable( withTarget, new BoundGetVariable(withLocal), SourceLocation.Missing )); } getter.Add(new BoundSetVariable( result, BuildGetMember( new BoundGetVariable(withLocal), BoundConstant.Create(fallback.Name) ), SourceLocation.Missing )); BoundBlock @else; if (withScope.Parent == null) { @else = BuildBlock(new BoundSetVariable( result, BuildGet( fallback, null ), SourceLocation.Missing )); } else { @else = BuildBlock(BuildGetWithScope( builder, withScope.Parent, fallback, result, withTarget )); } return new BoundIf( new BoundHasMember( new BoundGetVariable(withLocal), fallback.Name ), getter.BuildBlock(SourceLocation.Missing), @else, SourceLocation.Missing ); }
private BoundExpression BuildGet(IIdentifier identifier, BoundTemporary withTarget) { switch (identifier.Type) { case IdentifierType.Null: return new BoundGetVariable(BoundMagicVariable.Null); case IdentifierType.Undefined: return new BoundGetVariable(BoundMagicVariable.Undefined); case IdentifierType.This: _scope.IsThisReferenced = true; return new BoundGetVariable(BoundMagicVariable.This); case IdentifierType.Arguments: _scope.IsArgumentsReferenced = true; return new BoundGetVariable(BoundMagicVariable.Arguments); case IdentifierType.Parameter: return new BoundGetVariable(_scope.GetArgument(identifier)); case IdentifierType.Scoped: var builder = new BlockBuilder(this); var result = builder.CreateTemporary(); builder.Add( BuildGetWithScope(builder, identifier.WithScope, identifier.Fallback, result, withTarget) ); return builder.BuildExpression(result, SourceLocation.Missing); case IdentifierType.Local: case IdentifierType.Global: if (identifier.Closure != null) return new BoundGetVariable(_scope.GetClosureField(identifier)); return new BoundGetVariable(_scope.GetLocal(identifier)); default: throw new InvalidOperationException("Cannot find variable of argument"); } }