internal override MSA.Expression/*!*/ Transform(AstGenerator/*!*/ gen) { MSA.Expression parentScope = gen.CurrentScopeVariable; ScopeBuilder scope = new ScopeBuilder(); // define hidden parameters and RHS-placeholders (#1..#n will be used as RHS of a parallel assignment): MSA.Expression blockParameter, selfParameter; MSA.ParameterExpression[] parameters = DefineParameters(out selfParameter, out blockParameter); MSA.Expression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyBlockScope)); MSA.LabelTarget redoLabel = Ast.Label(); gen.EnterBlockDefinition( scope, blockParameter, selfParameter, scopeVariable, redoLabel ); if (_definedScope != null) { _definedScope.TransformLocals(scope); } MSA.Expression paramInit = MakeParametersInitialization(gen, parameters); MSA.ParameterExpression blockUnwinder = scope.DefineHiddenVariable("#unwinder", typeof(BlockUnwinder)); MSA.Expression loop = AstFactory.Infinite(null, redoLabel, AstUtils.Try( gen.TransformStatements(_body, ResultOperation.Return) ).Catch(blockUnwinder, // redo: AstUtils.IfThen(Ast.Field(blockUnwinder, BlockUnwinder.IsRedoField), Ast.Continue(redoLabel)), // next: gen.Return(Ast.Field(blockUnwinder, BlockUnwinder.ReturnValueField)) ) ); if (gen.TraceEnabled) { int firstStatementLine = _body.Count > 0 ? _body[0].Location.Start.Line : Location.End.Line; int lastStatementLine = _body.Count > 0 ? _body[_body.Count - 1].Location.End.Line : Location.End.Line; loop = Ast.TryFinally( Ast.Block( Methods.TraceBlockCall.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(firstStatementLine)), loop ), Methods.TraceBlockReturn.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(lastStatementLine)) ); } MSA.Expression body = Ast.Block( Ast.Assign(scopeVariable, Methods.CreateBlockScope.OpCall(scope.VisibleVariables(), parentScope, blockParameter, selfParameter) ), paramInit, loop, Ast.Empty() ); body = gen.AddReturnTarget(scope.CreateScope(body)); gen.LeaveBlockDefinition(); int parameterCount = _parameters.LeftValues.Count; var attributes = _parameters.GetBlockSignatureAttributes(); return Methods.DefineBlock.OpCall( gen.CurrentScopeVariable, gen.CurrentRfcVariable, gen.CurrentSelfVariable, Ast.Lambda( BlockDispatcher.GetDelegateType(parameterCount, attributes), body, gen.EncodeMethodName(gen.CurrentMethod.MethodName, Location), new ReadOnlyCollection<MSA.ParameterExpression>(parameters) ), Ast.Constant(parameterCount), Ast.Constant(attributes) ); }
internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen) { MSA.Expression parentScope = gen.CurrentScopeVariable; ScopeBuilder scope = new ScopeBuilder(); // define hidden parameters and RHS-placeholders (#1..#n will be used as RHS of a parallel assignment): MSA.Expression blockParameter, selfParameter; MSA.ParameterExpression[] parameters = DefineParameters(out selfParameter, out blockParameter); MSA.Expression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyBlockScope)); MSA.LabelTarget redoLabel = Ast.Label(); gen.EnterBlockDefinition( scope, blockParameter, selfParameter, scopeVariable, redoLabel ); if (_definedScope != null) { _definedScope.TransformLocals(scope); } MSA.Expression paramInit = MakeParametersInitialization(gen, parameters); MSA.ParameterExpression blockUnwinder = scope.DefineHiddenVariable("#unwinder", typeof(BlockUnwinder)); MSA.Expression loop = AstFactory.Infinite(null, redoLabel, AstUtils.Try( gen.TransformStatements(_body, ResultOperation.Return) ).Catch(blockUnwinder, // redo: AstUtils.IfThen(Ast.Field(blockUnwinder, BlockUnwinder.IsRedoField), Ast.Continue(redoLabel)), // next: gen.Return(Ast.Field(blockUnwinder, BlockUnwinder.ReturnValueField)) ) ); if (gen.TraceEnabled) { int firstStatementLine = _body.Count > 0 ? _body[0].Location.Start.Line : Location.End.Line; int lastStatementLine = _body.Count > 0 ? _body[_body.Count - 1].Location.End.Line : Location.End.Line; loop = Ast.TryFinally( Ast.Block( Methods.TraceBlockCall.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(firstStatementLine)), loop ), Methods.TraceBlockReturn.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(lastStatementLine)) ); } MSA.Expression body = Ast.Block( Ast.Assign(scopeVariable, Methods.CreateBlockScope.OpCall(scope.VisibleVariables(), parentScope, blockParameter, selfParameter) ), paramInit, loop, Ast.Empty() ); body = gen.AddReturnTarget(scope.CreateScope(body)); gen.LeaveBlockDefinition(); int parameterCount = _parameters.LeftValues.Count; var attributes = _parameters.GetBlockSignatureAttributes(); return(Methods.DefineBlock.OpCall( gen.CurrentScopeVariable, gen.CurrentRfcVariable, gen.CurrentSelfVariable, Ast.Lambda( BlockDispatcher.GetDelegateType(parameterCount, attributes), body, gen.EncodeMethodName(gen.CurrentMethod.MethodName, Location), new ReadOnlyCollection <MSA.ParameterExpression>(parameters) ), Ast.Constant(parameterCount), Ast.Constant(attributes) )); }
private MSA.Expression /*!*/ TransformBody(AstGenerator /*!*/ gen, MSA.Expression /*!*/ methodDefinitionVariable) { string encodedName = gen.EncodeMethodName(_name, Location); ScopeBuilder scope = new ScopeBuilder(); MSA.Expression parentScope = gen.CurrentScopeVariable; MSA.ParameterExpression[] parameters = DefineParameters(gen, scope); MSA.Expression currentMethodVariable = scope.DefineHiddenVariable("#method", typeof(RubyMethodInfo)); MSA.Expression rfcVariable = scope.DefineHiddenVariable("#rfc", typeof(RuntimeFlowControl)); MSA.Expression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyMethodScope)); MSA.Expression selfParameter = parameters[0]; MSA.Expression blockParameter = parameters[1]; gen.EnterMethodDefinition( scope, selfParameter, scopeVariable, blockParameter, rfcVariable, currentMethodVariable, _name, _parameters ); DefinedScope.TransformLocals(scope); MSA.ParameterExpression unwinder = scope.DefineHiddenVariable("#unwinder", typeof(MethodUnwinder)); MSA.Expression body = AstFactory.MakeUserMethodBody( gen, Location.End.Line, blockParameter, rfcVariable, unwinder, Ast.Block( Ast.Assign(currentMethodVariable, methodDefinitionVariable), Ast.Assign(scopeVariable, Methods.CreateMethodScope.OpCall( scope.VisibleVariables(), parentScope, currentMethodVariable, rfcVariable, selfParameter, blockParameter) ), _parameters.TransformOptionalsInitialization(gen), gen.TraceEnabled ? Methods.TraceMethodCall.OpCall(scopeVariable, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(Location.Start.Line)) : Ast.Empty(), Body.TransformResult(gen, ResultOperation.Return), Ast.Empty() ), ResultOperation.Return, (gen.Profiler != null) ? gen.Profiler.GetTickIndex(encodedName) : -1, (gen.Profiler != null) ? scope.DefineHiddenVariable("#stamp", typeof(long)) : null, gen.ReturnLabel ); body = gen.AddReturnTarget(scope.CreateScope(body)); gen.LeaveMethodDefinition(); return(CreateLambda( encodedName, parameters, body )); }