internal override void GenCode0(CodeGenContext context) { // String.Concat(String.Concat(arg1, arg2), args, ...); head.GenCode0(context); if (head.nd_next != null) { int first = context.StoreInTemp("head", Runtime.StringRef, head.location); for (Node n = head.nd_next; n != null; n = n.nd_next) { n.GenCode0(context); int second = context.StoreInTemp("tail", Runtime.StringRef, n.location); context.ldloc(first); context.ldloc(second); context.callvirt(Runtime.String.Concat); context.stloc(first); context.ReleaseLocal(second, true); } context.ldloc(first); context.ReleaseLocal(first, true); } }
internal override void GenCode0(CodeGenContext context) { // hash = new Hash(); context.newobj(Runtime.Hash.ctor); int hash = context.StoreInTemp("hash", Runtime.HashRef, location); Node entry = elements; while (entry != null) { bool key_created, value_created; ISimple key = context.PreCompute0(entry, "key", out key_created); entry = entry.nd_next; ISimple value = context.PreCompute0(entry, "value", out value_created); entry = entry.nd_next; // hash.Add(key, value); context.ldloc(hash); key.GenSimple(context); value.GenSimple(context); context.callvirt(Runtime.Hash.Add); context.ReleaseLocal(key, key_created); context.ReleaseLocal(value, value_created); } context.ldloc(hash); context.ReleaseLocal(hash, true); }
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 void AddScopeLocals(CodeGenContext context) { // ------------------ Start new Context ---------------------------- // [InteropMethod("MyClass")] // private class ActivationFrame: Ruby.Frame { ... } frame_def = context.CreateGlobalClass("_Internal", "Frame" + (N++), Runtime.FrameRef); Scope parentClass; for (parentClass = this; parentClass != null && !(parentClass is CLASS_OR_MODULE); parentClass = parentClass.parent_scope) ; string className = ""; if (parentClass != null) className = ((CLASS_OR_MODULE)parentClass).internal_name; ClassDef fileClass = FileClass(); string src = ""; if (fileClass != null && fileClass.Name().StartsWith("SourceFile_")) { src = fileClass.Name().Substring(11); frame_def.AddCustomAttribute(Runtime.FrameAttribute.ctor, new Constant[] { new StringConst(src), new StringConst(className) }); } foreach (string local in locals_list) CodeGenContext.AddField(frame_def, PERWAPI.FieldAttr.Public, ID.ToDotNetName(local), PrimitiveType.Object); // internal ActivationFrame(Frame caller): base(caller) { } CodeGenContext frame_ctor = context.CreateConstructor(frame_def, new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); frame_ctor.ldarg(0); frame_ctor.ldarg("caller"); frame_ctor.call(Runtime.Frame.ctor); frame_ctor.ret(); frame_ctor.Close(); // internal string file() { CodeGenContext file = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "file", PrimitiveType.String); file.startMethod(this.location); // return "thisfile.rb" file.ldstr(this.location.file); file.ret(); file.Close(); // internal override string methodName() { CodeGenContext methodName = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "methodName", PrimitiveType.String); methodName.startMethod(this.location); // return "CurrentMethodName" methodName.ldstr(CurrentMethodName()); methodName.ret(); methodName.Close(); CreateNestingMethod(frame_def, context); CreateLastClassMethod(frame_def, context); // ------------------ Return to Old Context ---------------------- // ActivationFrame frame = new ActivationFrame(caller); context.ldarg("caller"); context.newobj(frame_ctor.Method); int frame = context.StoreInTemp("frame", FrameClass, location); Debug.Assert(frame == 0); // frame.block_arg = block; context.ldloc(frame); LoadBlock0(context); context.stfld(Runtime.Frame.block_arg); if (this is BLOCK) { // frame.current_block = this; context.ldloc(frame); context.ldarg(0); context.stfld(Runtime.Frame.current_block); } }
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 Assign(CodeGenContext context, Node rhs) { // Gen right hand sides ListGen mrhs; if (rhs is ListGen && !(rhs is MultipleRHS)) mrhs = (ListGen)rhs; else mrhs = new ARGS(null, null, rhs, null, location, true); bool created; ISimple list = mrhs.GenArgList(context, out created); list.GenSimple(context); context.callvirt(Runtime.ArgList.CheckSingleRHS); int array = context.StoreInTemp("mrhs", Runtime.ArgListRef, location); context.ReleaseLocal(list, created); // Gen assignments to left hand sides for (LVALUE l = elements; l != null; l = (LVALUE)l.nd_next) { l.Assign(context, new MultipleRHS(array, l.location)); context.pop(); } context.ldloc(array); context.callvirt(Runtime.ArgList.ToRubyArray); context.ReleaseLocal(array, true); }
internal override ISimple GenArgList(CodeGenContext context, out bool created) { bool single = true; // ArgList arglist = new ArgList(); context.newobj(Runtime.ArgList.ctor); int arglist = context.StoreInTemp("arglist", Runtime.ArgListRef, location); int added = 0; for (Node arg = parameters; arg != null; arg = arg.nd_next) { //object argument = arg; bool argument_created; ISimple argument = context.PreCompute0(arg, "arg", out argument_created); // arglist.Add(argument); context.ldloc(arglist); argument.GenSimple(context); context.callvirt(Runtime.ArgList.Add); added++; context.ReleaseLocal(argument, argument_created); } if (added != 1) single = false; if (hashlist != null) { // object hash = hashlist; bool hash_created; ISimple hash = context.PreCompute(new HASH(hashlist, hashlist.location), "hashlist", out hash_created); // arglist.Add(hash); context.ldloc(arglist); hash.GenSimple(context); context.callvirt(Runtime.ArgList.Add); single = false; context.ReleaseLocal(hash, hash_created); } if (array != null) { // object list = array; bool list_created; ISimple list = context.PreCompute(array, "array", out list_created); // arglist.AddArray(list, caller); context.ldloc(arglist); list.GenSimple(context); context.ldloc(0); context.callvirt(Runtime.ArgList.AddArray); single = false; context.ReleaseLocal(list, list_created); } if (block != null) { // object b = block; bool b_created; ISimple b = context.PreCompute(block, "block", Runtime.ProcRef, out b_created); // arglist.block = b; context.ldloc(arglist); b.GenSimple(context); context.stfld(Runtime.ArgList.block); context.ReleaseLocal(b, b_created); } if (single) { context.ldloc(arglist); context.PushTrue(); context.stfld(Runtime.ArgList.single_arg); } created = true; return new LOCAL(arglist, location); }
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); }