internal void GenCall(CodeGenContext context) { int result = context.CreateLocal("result", PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); PERWAPI.CILLabel retryLabel = context.NewLabel(); context.CodeLabel(retryLabel); context.StartBlock(Clause.Try); { // object result = Call(...) GenCall0(context); context.stloc(result); context.Goto(endLabel); } PERWAPI.TryBlock tryBlock = context.EndTryBlock(); context.StartBlock(Clause.Catch); { CatchBreakException(context, result, endLabel); } context.EndCatchBlock(Runtime.BreakExceptionRef, tryBlock); context.StartBlock(Clause.Catch); { CatchRetryException(context, retryLabel); } context.EndCatchBlock(Runtime.RetryExceptionRef, tryBlock); context.CodeLabel(endLabel); context.ldloc(result); context.ReleaseLocal(result, true); }
internal override void GenCode0(CodeGenContext context) { PERWAPI.CILLabel elseLabel = context.NewLabel(); PERWAPI.CILLabel endLabel = context.NewLabel(); // if (Eval.Test(cond)) cond.GenCode(context); context.call(Runtime.Eval.Test); context.brfalse(elseLabel); body.GenCode(context); context.br(endLabel); context.CodeLabel(elseLabel); _else.GenCode(context); context.CodeLabel(endLabel); }
internal override void GenCode0(CodeGenContext context) { PERWAPI.CILLabel finalLabel = context.NewLabel(); int RescueTemp = context.CreateLocal("rescueTemp", PERWAPI.PrimitiveType.Object); context.ldnull(); context.stloc(RescueTemp); if (ensure != null) { context.StartBlock(Clause.Try); // outer try block with finally context.StartBlock(Clause.Try); // inner try block with catch } GenInnerBlock(context, RescueTemp); if (ensure != null) { context.Goto(finalLabel); PERWAPI.TryBlock innerTry = context.EndTryBlock(); context.StartBlock(Clause.Catch); GenRescue(context, null, 0, null); context.EndCatchBlock(Runtime.SystemExceptionRef, innerTry); PERWAPI.TryBlock outerTry = context.EndTryBlock(); // Fixme: reset labels to prevent branches out of finally block. context.StartBlock(Clause.Finally); ensure.GenCode(context); if (context.Reachable()) context.pop(); context.endfinally(); context.EndFinallyBlock(outerTry); context.CodeLabel(finalLabel); context.newEndPoint(location); } context.ldloc(RescueTemp); context.ReleaseLocal(RescueTemp, true); }
internal override void GenCode0(CodeGenContext context) { int RescueTemp = context.CreateLocal("rescueTemp", PERWAPI.PrimitiveType.Object); int ExceptionTemp = context.CreateLocal("exceptionTemp", PERWAPI.PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); context.StartBlock(Clause.Try); { expr.GenCode(context); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(endLabel); } } PERWAPI.TryBlock tryBlock = context.EndTryBlock(); context.StartBlock(Clause.Catch); { PERWAPI.CILLabel stdErrLabel = context.NewLabel(); context.stloc(ExceptionTemp); context.ldloc(ExceptionTemp); context.ldfld(Runtime.RubyException.parent); context.isinst(Runtime.StandardErrorRef); context.brtrue(stdErrLabel); context.ldloc(ExceptionTemp); context.throwOp(); context.CodeLabel(stdErrLabel); rescue.GenCode(context); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(endLabel); } } context.EndCatchBlock(Runtime.RubyExceptionRef, tryBlock); context.CodeLabel(endLabel); context.ldloc(RescueTemp); context.ReleaseLocal(RescueTemp, true); context.ReleaseLocal(ExceptionTemp, true); }
internal void GenCode(CodeGenContext context, PERWAPI.CILLabel endLabel, int RescueTemp, int exception) { for (RESCUE_CLAUSE clause = this; clause != null; clause = clause.next) { PERWAPI.CILLabel nextClause = context.NewLabel(); PERWAPI.CILLabel thisClause = context.NewLabel(); context.ldc_i4(0); LOCAL exceptionCaught = context.StoreInLocal("caught", PERWAPI.PrimitiveType.Boolean, this.location); for (Node type = clause.types; type != null; type = type.nd_next) { PERWAPI.CILLabel label1 = context.NewLabel(); // Precompute each separately to avoid computing a list of types type.GenCode0(context); LOCAL tt = context.StoreInLocal("type", PERWAPI.PrimitiveType.Object, type.location); new METHOD_CALL(tt, ID.intern(Tokens.tEQQ), new AST.LOCAL(exception, type.location), type.location).GenCode(context); context.ReleaseLocal(tt.local, true); context.call(Runtime.Eval.Test); context.brfalse(label1); context.PushTrue(); context.stloc(exceptionCaught.local); context.CodeLabel(label1); } context.ldloc(exceptionCaught.local); context.brtrue(thisClause); context.ReleaseLocal(exceptionCaught.local, true); context.br(nextClause); context.CodeLabel(thisClause); if (clause.var != null) { clause.var.Assign(context, new AST.LOCAL(exception, clause.var.location)); context.pop(); } if (clause.body != null) clause.body.GenCode(context); else context.ldnull(); if (context.Reachable()) context.stloc(RescueTemp); // reset $! //Eval.ruby_errinfo.value = null; context.ldsfld(Runtime.Eval.ruby_errinfo); context.ldnull(); context.stfld(Runtime.global_variable.value); context.Goto(endLabel); context.CodeLabel(nextClause); } }
internal void GenRescue(CodeGenContext context, PERWAPI.CILLabel endLabel, int RescueTemp, RESCUE_CLAUSE clauses) { // catch (System.Exception e) { int e = context.StoreInTemp("e", Runtime.SystemExceptionRef, location); //if (e is Ruby.ControlException) PERWAPI.CILLabel else1 = context.NewLabel(); context.ldloc(e); context.isinst(Runtime.ControlExceptionRef); context.brfalse(else1); // throw e; context.rethrow(); context.CodeLabel(else1); // Ruby.Exception exception; int exception = context.CreateLocal("exception", Runtime.ExceptionRef); //if (!(e is Ruby.RubyException)) PERWAPI.CILLabel else2 = context.NewLabel(); PERWAPI.CILLabel end = context.NewLabel(); context.ldloc(e); context.isinst(Runtime.RubyExceptionRef); context.brtrue(else2); // exception = new Ruby.CLRException(frame, e); context.ldloc(0); context.ldloc(e); context.newobj(Runtime.CLRException.ctor); context.stloc(exception); context.br(end); //else context.CodeLabel(else2); // exception = (Ruby.RubyException)e.parent; context.ldloc(e); context.cast(Runtime.RubyExceptionRef); context.ldfld(Runtime.RubyException.parent); context.stloc(exception); context.CodeLabel(end); //Eval.ruby_errinfo.value = exception; context.ldsfld(Runtime.Eval.ruby_errinfo); context.ldloc(exception); context.stfld(Runtime.global_variable.value); if (clauses != null) clauses.GenCode(context, endLabel, RescueTemp, exception); context.rethrow(); context.ReleaseLocal(e, true); context.ReleaseLocal(exception, true); }
internal override void GenCode0(CodeGenContext context) { PERWAPI.CILLabel endLabel = context.NewLabel(); Node clause; if (target != null) { context.newLine(target.location); target.GenCode(context); LOCAL t = context.StoreInLocal("target", PrimitiveType.Object, location); for (clause = body; clause != null && clause is WHEN; clause = clause.nd_next) ((WHEN)clause).GenCode(context, t, endLabel); context.ReleaseLocal(t.local, true); } else { for (clause = body; clause != null && clause is WHEN; clause = clause.nd_next) { context.newLine(clause.location); ((WHEN)clause).GenCode(context, endLabel); } } if (clause != null) /* assume else clause */ clause.GenCode(context); else context.ldnull(); context.CodeLabel(endLabel); context.newEndPoint(location); }
internal void AddScopeBody(CodeGenContext context) { returnTemp = context.CreateLocal("returnTemp", PrimitiveType.Object); context.labels = new Labels(); context.labels.Redo = context.NewLabel(); context.labels.Return = context.NewLabel(); // try { ... } context.StartBlock(Clause.Try); { if (BEGIN != null) BEGIN.GenCode(context); context.CodeLabel(context.labels.Redo); if (body != null) { body.GenCode(context); if (context.Reachable()) context.stloc(returnTemp); } context.Goto(context.labels.Return); } PERWAPI.TryBlock tryBlock = context.EndTryBlock(); CatchReturnException(context, tryBlock); // ReturnLabel: // return returnTemp; context.CodeLabel(context.labels.Return); context.newEndPoint(location); if (context.Method.GetRetType() != PERWAPI.PrimitiveType.Void) context.ldloc(returnTemp); context.ret(); context.ReleaseLocal(returnTemp, true); }
internal override void GenCode0(CodeGenContext context) { context.ldloc(0); context.call(Runtime.Frame.get_Tilde); PERWAPI.CILLabel label1 = context.NewLabel(); context.brfalse(label1); context.ldloc(0); context.call(Runtime.Frame.get_Tilde); context.ldloc(0); switch (ch) { case '&': context.callvirt(Runtime.Match.last_match); break; case '`': context.callvirt(Runtime.Match.match_pre); break; case '\'': context.callvirt(Runtime.Match.match_post); break; case '+': context.callvirt(Runtime.Match.match_last); break; default: throw new NotImplementedException("BACK_REF $" + ch); } PERWAPI.CILLabel label2 = context.NewLabel(); context.br(label2); context.CodeLabel(label1); context.ldnull(); context.CodeLabel(label2); }
private void CopyNormalFormals(CodeGenContext context, Scope scope) { PERWAPI.CILLabel OKLabel = context.NewLabel(); if (min_args > 0) { // if (args.Length < min_args) context.ldarg("args"); context.callvirt(Runtime.ArgList.get_Length); int length = context.StoreInTemp("length", PrimitiveType.Int32, location); context.ldloc(length); context.ldc_i4(min_args); context.bge(OKLabel); //context.Inst(Op.clt); //context.brfalse(OKLabel); // context.Branch(BranchOp.bge, OKLabel); // throw new ArgumentError(string.Format("wrong number of arguments ({0} for {1})", args.Length, arity).raise(caller); // FIXME: next line needs a String context.ldstr("wrong number of arguments ({0} for {1})"); context.ldloc(length); context.box(PrimitiveType.Int32); context.ldc_i4(min_args); context.box(PrimitiveType.Int32); context.call(Runtime.SystemString.Format); context.newobj(Runtime.ArgumentError.ctor); context.ldloc(0); context.callvirt(Runtime.Exception.raise); context.throwOp(); context.ReleaseLocal(length, true); // OKLabel: context.CodeLabel(OKLabel); } // Copy parameters to locals for (Node f = normal; f != null; f = f.nd_next) { string name = ID.ToDotNetName(((VAR)f).vid); // local.f = args.GetNext(); context.ldloc(0); context.ldarg("args"); context.callvirt(Runtime.ArgList.GetNext); context.stfld(scope.GetFrameField(name)); } }
private void CatchBreakException(CodeGenContext context, int result, PERWAPI.CILLabel endLabel) { // catch (Exception exception) int exception = context.StoreInTemp("exception", Runtime.BreakExceptionRef, location); PERWAPI.CILLabel reThrowLabel = context.NewLabel(); // if (exception.scope != current_frame) goto reThrowLabel; context.ldloc(0); context.ldloc(exception); context.ldfld(Runtime.BreakException.scope); context.bne( reThrowLabel); // result = exception.return_value; context.ldloc(exception); context.ldfld(Runtime.BreakException.return_value); context.stloc(result); // goto endLabel; context.Goto(endLabel); // reThrowLabel: context.CodeLabel(reThrowLabel); // throw exception; context.ldloc(exception); context.throwOp(); context.ReleaseLocal(exception, true); }
private void CatchRetryException(CodeGenContext context, PERWAPI.CILLabel retryLabel) { // catch (Exception exception) int exception = context.StoreInTemp("exception", Runtime.RetryExceptionRef, location); PERWAPI.CILLabel reThrowLabel = context.NewLabel(); // if (exception.scope != current_frame) goto reThrowLabel; context.ldloc(0); context.ldloc(exception); context.ldfld(Runtime.RetryException.scope); context.bne( reThrowLabel); // goto retryLabel context.Goto(retryLabel); // reThrowLabel: context.CodeLabel(reThrowLabel); // throw exception; context.ldloc(exception); context.throwOp(); context.ReleaseLocal(exception, true); }
internal override void GenCode0(CodeGenContext context) { PERWAPI.CILLabel elseLabel = context.NewLabel(); PERWAPI.CILLabel endLabel = context.NewLabel(); // if (Eval.Test(cond)) context.newLine(cond.location); cond.GenCode(context); context.call(Runtime.Eval.Test); context.brfalse(elseLabel); if (body != null) { context.newStartPoint(body.location); body.GenCode(context); } else context.ldnull(); if (context.Reachable()) context.br(endLabel); context.CodeLabel(elseLabel); if (_else != null) { context.newStartPoint(_else.location); _else.GenCode(context); } else context.ldnull(); context.CodeLabel(endLabel); context.newEndPoint(location); }
internal void GenCode(CodeGenContext context, PERWAPI.CILLabel endLabel) { PERWAPI.CILLabel elseLabel = context.NewLabel(); context.newLine(comparison.location); // if (comparision.ToRubyArray().includes(true, caller)) bool created; ISimple list = comparison.GenArgList(context, out created); list.GenSimple(context); context.ReleaseLocal(list, created); context.callvirt(Runtime.ArgList.ToRubyArray); new TRUE(comparison.location).GenCode(context); context.ldloc(0); context.callvirt(Runtime.Array.includes); context.brfalse(elseLabel); if (body != null) { context.newStartPoint(body.location); body.GenCode(context); } else context.ldnull(); context.br(endLabel); context.CodeLabel(elseLabel); }
private void GenInnerBlock(CodeGenContext context, int RescueTemp) { PERWAPI.CILLabel elseLabel = context.NewLabel(); Labels catchLabels = new Labels(); catchLabels.Break = context.labels.Break; catchLabels.Next = context.labels.Next; catchLabels.Redo = context.labels.Redo; catchLabels.Return = context.labels.Return; catchLabels.Retry = context.NewLabel(); context.CodeLabel(catchLabels.Retry); context.StartBlock(Clause.Try); { if (body != null) body.GenCode(context); else context.ldnull(); if (context.Reachable()) { context.stloc(RescueTemp); context.Goto(elseLabel); } } PERWAPI.TryBlock innerTry = context.EndTryBlock(); PERWAPI.CILLabel endLabel = context.NewLabel(); if (rescue != null) { context.StartBlock(Clause.Catch); { Labels original = context.labels; context.labels = catchLabels; GenRescue(context, endLabel, RescueTemp, rescue); context.labels = original; } context.EndCatchBlock(Runtime.SystemExceptionRef, innerTry); } context.CodeLabel(elseLabel); { if (_else != null) { _else.GenCode(context); if (context.Reachable()) context.stloc(RescueTemp); } } context.CodeLabel(endLabel); }
private void CopyOptionalFormals(CodeGenContext context, Scope scope) { for (ASSIGNMENT opt = (ASSIGNMENT)optional; opt != null; opt = (ASSIGNMENT)opt.nd_next) { PERWAPI.CILLabel runout_label = context.NewLabel(); PERWAPI.CILLabel end_label = context.NewLabel(); string name = ID.ToDotNetName(((VAR)(opt.lhs)).vid); Node defaultValue = opt.rhs; // if (args.RunOut()) goto RunOut context.ldarg("args"); context.callvirt(Runtime.ArgList.RunOut); context.brtrue(runout_label); // locals.name = args.GetNext(); context.ldloc(0); context.ldarg("args"); context.callvirt(Runtime.ArgList.GetNext); context.br(end_label); // RunOut: context.CodeLabel(runout_label); // object def = defaultValue; bool created; ISimple def = context.PreCompute(defaultValue, "default", out created); // locals.name = defaultValue context.ldloc(0); def.GenSimple(context); context.ReleaseLocal(def, created); context.CodeLabel(end_label); // locals.name = ... context.stfld(scope.GetFrameField(name)); } }
internal override void Defined(CodeGenContext context) { if (qualified) if (scope != null) { // object result; int result = context.CreateLocal("result", PrimitiveType.Object); PERWAPI.CILLabel endLabel = context.NewLabel(); // try { context.StartBlock(Clause.Try); { // result = Eval.const_defined(scope, vid, caller); scope.GenCode(context); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); context.stloc(result); context.leave(endLabel); } TryBlock block = context.EndTryBlock(); // catch (System.Exception) { context.StartBlock(Clause.Catch); { // result = null; context.ldnull(); context.stloc(result); context.leave(endLabel); } context.EndCatchBlock(Runtime.SystemExceptionRef, block); context.CodeLabel(endLabel); context.ldloc(result); context.ReleaseLocal(result, true); } else { context.ldsfld(Ruby.Compiler.Runtime.Init.rb_cObject); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); } else { context.ruby_cbase(parent_scope); context.ldstr(vid.ToString()); context.ldloc(0); context.call(Runtime.Eval.const_defined); } }
internal override void Defined(CodeGenContext context) { PERWAPI.CILLabel undefined_label = context.NewLabel(); PERWAPI.CILLabel end_label = context.NewLabel(); for (Node arg = parameters; arg != null; arg = arg.nd_next) { arg.Defined(context); context.brfalse(undefined_label); } if (array != null) { array.Defined(context); context.brfalse(undefined_label); } if (hashlist != null) { hashlist.Defined(context); context.brfalse(undefined_label); } if (block != null) { block.Defined(context); context.brfalse(undefined_label); } context.PushTrue(); context.box(PrimitiveType.Boolean); if (!IsEmpty) { context.br(end_label); context.CodeLabel(undefined_label); context.PushFalse(); context.box(PrimitiveType.Boolean); context.CodeLabel(end_label); } }
internal override void Defined(CodeGenContext context) { CILLabel endLabel = context.NewLabel(); context.ldloc(0); context.call(Runtime.Frame.get_Tilde); context.dup(); context.brfalse(endLabel); context.ldc_i4(nth); context.callvirt(Runtime.Match.defined_nth); context.CodeLabel(endLabel); }
internal override void GenCode0(CodeGenContext context) { context.newLine(location); if (lhs is ARRAY_ACCESS) // for array access -> need to avoid recomputation of lhs index ((ARRAY_ACCESS)lhs).AssignOp(context, op, rhs); else if (lhs is CVAR && op == "||") { CILLabel alreadyDefined1 = new CILLabel(); CILLabel alreadyDefined2 = new CILLabel(); CILLabel alreadyDefined3 = new CILLabel(); Node lhsDefined = new DEFINED(lhs, location); lhsDefined.GenCode(context); context.brtrue(alreadyDefined1); lhs.Assign(context, rhs); context.br(alreadyDefined2); context.CodeLabel(alreadyDefined1); lhs.Assign(context, METHOD_CALL.Create(lhs, op, rhs, location)); context.CodeLabel(alreadyDefined2); } else lhs.Assign(context, METHOD_CALL.Create(lhs, op, rhs, location)); }
internal void CatchReturnException(CodeGenContext context, PERWAPI.TryBlock tryBlock) { // catch (Ruby.ReturnException exception) { ... } context.StartBlock(Clause.Catch); { PERWAPI.CILLabel falseLabel = context.NewLabel(); int exception = context.StoreInTemp("exception", Runtime.ReturnExceptionRef, location); // if (exception.scope == thisframe) context.ldloc(exception); context.ldfld(Runtime.ReturnException.scope); context.ldloc(0); context.bne(falseLabel); // returnTemp = exception.return_value; context.ldloc(exception); context.ldfld(Runtime.ReturnException.return_value); context.stloc(returnTemp); context.Goto(context.labels.Return); // falseLabel: context.CodeLabel(falseLabel); // throw exception context.rethrow(); context.ReleaseLocal(exception, true); } context.EndCatchBlock(Runtime.ReturnExceptionRef, tryBlock); }
internal override void GenCode0(CodeGenContext context) { Labels original = context.labels; // ---------------- Create new label context for loop ---------------------- context.labels = new Labels(); context.labels.Next = context.NewLabel(); context.labels.Break = context.NewLabel(); context.labels.Redo = context.NewLabel(); context.labels.Retry = context.NewLabel(); context.labels.Return = original.Return; context.CodeLabel(context.labels.Retry); context.newStartPoint(location); context.ldnull(); context.stloc(parent_scope.returnTemp); context.CodeLabel(context.labels.Redo); if (body != null) { body.GenCode(context); if (context.Reachable()) context.pop(); } context.CodeLabel(context.labels.Next); // if (Eval.Test(cond)) context.newLine(cond.location); cond.GenCode(context); context.call(Runtime.Eval.Test); if (whileTrue) context.brtrue(context.labels.Retry); else context.brfalse(context.labels.Retry); context.CodeLabel(context.labels.Break); context.newEndPoint(location); context.ldloc(parent_scope.returnTemp); // --------------------- Restore Label context ------------------------- context.labels = original; }