private void CreateLastClassMethod(ClassDef Class, CodeGenContext context) { CodeGenContext lastClass = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "lastClass", Runtime.ClassRef); lastClass.startMethod(this.location); int frame = lastClass.CreateLocal("frame", Runtime.FrameRef); lastClass.ldarg(0); lastClass.stloc(frame); lastClass.LastClass(this, true); lastClass.ret(); lastClass.ReleaseLocal(frame, true); lastClass.Close(); }
private void CreateNestingMethod(ClassDef Class, CodeGenContext context) { List<FieldDef> list = new List<FieldDef>(); for (Scope parent = this; parent != null; parent = parent.parent_scope) if (parent is CLASS_OR_MODULE) list.Add(((CLASS_OR_MODULE)parent).singletonField); // internal override Class[] nesting() { CodeGenContext nesting = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "nesting", new PERWAPI.ZeroBasedArray(Runtime.ClassRef)); nesting.startMethod(this.location); // Class[] array = new Class[list.Count]; nesting.ldc_i4(list.Count); nesting.newarr(Runtime.ClassRef); int array = nesting.CreateLocal("array", new PERWAPI.ZeroBasedArray(Runtime.ClassRef)); nesting.stloc(array); for (int i = 0; i < list.Count; i++) { // array[i] = list[i]; nesting.ldloc(array); nesting.ldc_i4(i); nesting.ldsfld(list[i]); nesting.stelem_ref(); } // return array; nesting.ldloc(array); nesting.ret(); nesting.ReleaseLocal(array, true); nesting.Close(); }
internal override void GenCode0(CodeGenContext context) { CodeGenContext Begin = context.CreateMethod(FileClass(), MethAttr.PublicStatic, "Begin" + (seq++), PrimitiveType.Object, new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); Begin.startMethod(this.location); AddScopeLocals(Begin); AddScopeBody(Begin); Begin.ReleaseLocal(0, true); Begin.Close(); // Begin(recv, caller); context.ldarg("recv"); context.ldloc(0); context.call(Begin.Method); context.pop(); }
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); } }
private void GenCallMethod(ClassDef Class, CodeGenContext context) { List<Param> args = new List<Param>(); args.Add(new Param(ParamAttr.Default, "last_class", Runtime.ClassRef)); args.Add(new Param(ParamAttr.Default, "recv", PrimitiveType.Object)); args.Add(new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); CodeGenContext Call; if (formals.ShortAndSimple()) { args.Add(new Param(ParamAttr.Default, "block", Runtime.ProcRef)); for (StaticLocalVar formal = formals.normal; formal != null; formal = (StaticLocalVar)formal.nd_next) args.Add(new Param(ParamAttr.Default, formal.vid, PrimitiveType.Object)); Call = context.CreateMethod(Class, MethAttr.PublicVirtual, "Call" + formals.min_args, PrimitiveType.Object, args.ToArray()); } else { args.Add(new Param(ParamAttr.Default, "args", Runtime.ArgListRef)); // internal static object Calln(Class last_class, object recv, Frame caller, Proc block, ArrayList args) Call = context.CreateMethod(Class, MethAttr.PublicVirtual, "Calln", PrimitiveType.Object, args.ToArray()); } Call.orig_func = Call.Method; // BBTAG Call.orig_func_formals = formals; // BBTAG Call.currentSkeleton = context.currentSkeleton; // BBTAG Call.postPassList = context.postPassList; // BBTAG Call.peFiles = context.peFiles; // BBTAG Call.startMethod(this.location); AddScopeLocals(Call); if (formals.ShortAndSimple()) formals.CopySimple(Call, this); else formals.CopyToLocals(Call, this); AddScopeBody(Call); Call.newEndPoint(location); Call.ReleaseLocal(0, true); Call.Close(); }
private void GenCallMethod(ClassDef Class, CodeGenContext context) { // internal static object Calln(Class last_class, object recv, Frame caller, ArgList args) CodeGenContext Calln = context.CreateMethod(Class, MethAttr.PublicVirtual, "Calln", PrimitiveType.Object, new Param(ParamAttr.Default, "last_class", Runtime.ClassRef), new Param(ParamAttr.Default, "ruby_class", Runtime.ClassRef), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef), new Param(ParamAttr.Default, "args", Runtime.ArgListRef)); Calln.startMethod(this.location); AddScopeLocals(Calln); if (args != null) { new ASSIGNMENT(args, new BLOCKARGS(args.location), args.location).GenCode(Calln); // Fixme: should be inside try block for ReturnException Calln.pop(); } AddScopeBody(Calln); Calln.ReleaseLocal(0, true); Calln.Close(); }
private void AddInteropMethod(CodeGenContext context) { List<Param> args = new List<Param>(); if (formals.arity < 0) { Param param = new Param(ParamAttr.Default, "args", new PERWAPI.ZeroBasedArray(PERWAPI.PrimitiveType.Object)); param.AddCustomAttribute(Runtime.ParamArrayAttribute.ctor, new byte[0]); args.Add(param); } else for (int i = 1; i <= this.formals.arity; i++) args.Add(new Param(ParamAttr.Default, "p" + i, PrimitiveType.Object)); // public object method_id(...) { try { CodeGenContext method = context.CreateMethod(CLASS_OR_MODULE.CurrentInteropClass(), MethAttr.PublicVirtual, Translate(this.method_id), PERWAPI.PrimitiveType.Object, args.ToArray()); method.startMethod(this.location); // return Eval.Calln(this, "method_id", ...); method.ldarg(0); method.ldstr(method_id); if (formals.arity < 0) { method.ldarg(1); method.call(Runtime.Eval.Calln); } else { for (int i = 1; i <= args.Count; i++) method.ldarg(i); method.call(Runtime.Eval.Call(args.Count)); } method.ret(); method.Close(); } catch (PERWAPI.DescriptorException e) { Compiler.LogWarning(e.Message); } }
private void GenInvokeMethod(ClassDef Class, CodeGenContext context) { // internal object Invoke(Class last_class, object recv, Frame caller, Frame frame); CodeGenContext Invoke = context.CreateMethod(Class, MethAttr.PublicVirtual, "Invoke", PrimitiveType.Object, new Param(ParamAttr.Default, "last_class", Runtime.ClassRef), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef), new Param(ParamAttr.Default, "frame", Runtime.FrameRef)); Invoke.ldarg("frame"); Invoke.cast(FrameClass); int frame = Invoke.StoreInTemp("frame", FrameClass, location); AddScopeBody(Invoke); Invoke.ReleaseLocal(frame, true); Invoke.Close(); }
internal override void GenCode0(CodeGenContext context) { bool scope_created, super_created; CodeGenContext newContext = new CodeGenContext(context); // scope and super must be evaluated in surrounding scope and passed to Init method ISimple scope = PushScope(context, out scope_created); ISimple super = PushSuper(context, out super_created); string basename = ID.ToDotNetName(name.vid); // BBTAG: try and get the superclass PERWAPI.Class superClass = Runtime.ObjectRef; bool superClassFound = false; PERWAPI.Method superClassConstructor0 = null; PERWAPI.Method superClassConstructor1 = Runtime.Object.ctor; if (this is CLASS) { superClass = ((CLASS)this).GetSuperClassRef(newContext); if (superClass != null) { superClassFound = true; superClassConstructor0 = superClass.GetMethodDesc(".ctor", new Type[0]); if (superClassConstructor0 is MethodDef) superClassConstructor0 = ((MethodDef)superClassConstructor0).MakeRefOf(); superClassConstructor1 = superClass.GetMethodDesc(".ctor", new Type[] { Runtime.ClassRef }); if (superClassConstructor1 is MethodDef) superClassConstructor1 = ((MethodDef)superClassConstructor1).MakeRefOf(); } else superClass = Runtime.ObjectRef; } //public class MyClass: Object { // check if this class has already been created in a referenced DLL // FIXME: this won't work for nested classes PERWAPI.Class classRef = ClassSkeleton.FindPERWAPIClass(null, name, context.peFiles); bool defineInteropClass = (classRef == null); // if it seems like an extension of a ruby builtin class, don't generate an interop class // FIXME: this won't work for nested classes if (Ruby.Runtime.BuiltinClasses.IsBuiltinClass(basename)) { Compiler.InteropWarning(basename + " is a Ruby built-in class, interop class not generated"); defineInteropClass = false; } //ClassDef interopClass = newContext.CreateNestedClass(CurrentInteropClass(), basename, Runtime.ObjectRef); // BBTAG ClassDef interopClass = null; if (defineInteropClass) { if (superClass is PERWAPI.ClassDef) interopClass = newContext.CreateNestedClass(CurrentInteropClass(), basename, ((PERWAPI.ClassDef)superClass).MakeRefOf()); // BBTAG else interopClass = newContext.CreateNestedClass(CurrentInteropClass(), basename, superClass); // BBTAG interopClasses.Push(interopClass); classRef = interopClass; } //context.classes[classname] = interopClass; // BBTAG: create skeleton for this class ClassSkeleton skeleton; if (context.currentSkeleton.nestedClasses.ContainsKey(basename)) skeleton = context.currentSkeleton.nestedClasses[basename]; else skeleton = new ClassSkeleton(basename, classRef); skeleton.lexicalParent = context.currentSkeleton; newContext.currentSkeleton = skeleton; skeleton.lexicalParent.nestedClasses[basename] = skeleton; if (!superClassFound && this is AST.CLASS && ((AST.CLASS)this).super_class != null && defineInteropClass) { // do not add to post pass list if supertype is a built-in Ruby class //List<string> qualifiedSuperClass = ClassSkeleton.ConstNodeToClassList(((AST.CLASS)this).super_class); //if (!(qualifiedSuperClass.Count == 1 && Ruby.Runtime.BuiltinClasses.IsBuiltinClass(qualifiedSuperClass[0]))) newContext.postPassList.Add(new ClassSkeletonPostPass(skeleton, interopClass, ((AST.CLASS)this).super_class)); } // public static Class classname; int seqNo = 0; internal_name = basename; while (FileClass().GetField(internal_name) != null) internal_name = basename + (seqNo++); // Define singleton in file class so that it gets initialized by .cctor singletonField = FileClass().AddField(PERWAPI.FieldAttr.PublicStatic, internal_name, Runtime.ClassRef); newContext.CurrentRubyClass = singletonField; // public MyClass() : base(singleton) { }; CodeGenContext class_constructor = null; if (defineInteropClass) { if (interopClass.GetMethod(".ctor", new Type[0]) == null) { CodeGenContext class_constructor0 = newContext.CreateConstructor(interopClass); class_constructor0.ldarg(0); if (superClassConstructor0 != null) class_constructor0.call(superClassConstructor0); else { class_constructor0.ldsfld(singletonField); class_constructor0.call(superClassConstructor1); } class_constructor0.ret(); class_constructor0.Close(); } // public MyClass(Class klass) : base(klass) { }; MethodDef ctor = interopClass.GetMethod(".ctor", new Type[] { Runtime.ClassRef }); //CodeGenContext class_constructor; if (ctor == null) { class_constructor = newContext.CreateConstructor(interopClass, new Param(ParamAttr.Default, "klass", Runtime.ClassRef)); class_constructor.ldarg(0); class_constructor.ldarg("klass"); class_constructor.call(superClassConstructor1); class_constructor.ret(); class_constructor.Close(); } else { class_constructor = new CodeGenContext(); class_constructor.Method = ctor; } } // internal static void Init_fullname(object scope, object super, object recv, Frame caller) { CodeGenContext Init = newContext.CreateMethod(FileClass(), MethAttr.PublicStatic, "Init_" + internal_name, PrimitiveType.Object, new Param(ParamAttr.Default, "scope", PrimitiveType.Object), new Param(ParamAttr.Default, "super", PrimitiveType.Object), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef)); skeleton.initMethod = Init.Method; Init.startMethod(this.location); AddScopeLocals(Init); // singleton = scope.define_???(...) DefineClass(Init, singletonField); // recv = singleton; Init.ldsfld(singletonField); Init.starg("recv"); // Fixme: should be conditional // singleton.define_allocator(allocator); if (defineInteropClass) { FieldDef allocator = DefineAllocator(newContext, class_constructor.Method); if (allocator != null) { Init.ldsfld(singletonField); Init.ldsfld(allocator); Init.call(Runtime.Class.define_alloc_func); } } AddScopeBody(Init); Init.ReleaseLocal(0, true); Init.Close(); if (defineInteropClass) interopClasses.Pop(); // --------------------- Return to old Context ---------------------------- context.newLine(location); // Init(scope, super, recv, caller); scope.GenSimple(context); super.GenSimple(context); context.ldarg("recv"); context.ldloc(0); context.call(Init.Method); context.ReleaseLocal(super, super_created); context.ReleaseLocal(scope, scope_created); }
internal override FieldDef DefineAllocator(CodeGenContext context, MethodDef ctor) { // Conservative - don't create allocator if we're not sure what the base class is // BBTAG: should be able to create this in all cases now, since we do a test in // define_alloc_func //if (super_class != null) // return null; ClassRef baseClass = Runtime.MethodBodyNRef(0); ClassDef allocator = context.CreateGlobalClass("_Internal", "Method_" + internal_name + "_Allocator", baseClass); context.currentSkeleton.allocator = allocator; // internal static Call0(Class last_class, object recv, ...) { body } CodeGenContext Call = context.CreateMethod(allocator, MethAttr.PublicVirtual, "Call0", PrimitiveType.Object, new Param[] { new Param(ParamAttr.Default, "last_class", Runtime.ClassRef), new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef), new Param(ParamAttr.Default, "block", Runtime.ProcRef)}); // return new MyClass((Class)recv)); Call.ldarg("recv"); Call.cast(Runtime.ClassRef); Call.newobj(ctor); Call.ret(); Call.Close(); // internal MyAllocator() {} CodeGenContext constructor = context.CreateConstructor(allocator); constructor.ldarg(0); constructor.call(Runtime.MethodBodyCtor(baseClass)); constructor.ret(); constructor.Close(); // internal static MyAllocator singleton; FieldDef singleton = CodeGenContext.AddField(allocator, FieldAttr.PublicStatic, "myRubyMethod", allocator); // static MyAllocator() { // singleton = new MyAllocator(); // } CodeGenContext staticConstructor = context.CreateStaticConstructor(allocator); staticConstructor.newobj(constructor.Method); staticConstructor.stsfld(singleton); staticConstructor.ret(); staticConstructor.Close(); return singleton; }
private PERWAPI.ClassDef GenerateClassForFile(CodeGenContext context, string file_name, bool autoLoad, List<SOURCEFILE> files) { if (fileClass == null) CreateClassForFile(context, file_name); // internal static object Load(object recv, Caller caller, Proc block) LoadMethod = context.CreateMethod(fileClass, MethAttr.PublicStatic, "Load", PrimitiveType.Object, new Param[] { new Param(ParamAttr.Default, "recv", PrimitiveType.Object), new Param(ParamAttr.Default, "caller", Runtime.FrameRef) }); LoadMethod.startMethod(location); AddScopeLocals(LoadMethod); AddScopeBody(LoadMethod); LoadMethod.ReleaseLocal(0, true); // } LoadMethod.Close(); if (autoLoad) { // accessing this field should trigger the .cctor to load the main source file CodeGenContext.AddField(fileClass, FieldAttr.PublicStatic, "loaded", PrimitiveType.Boolean); // public static .cctor() { CodeGenContext cctor = context.CreateStaticConstructor(fileClass); // register other ruby source files in assembly so that they can be loaded if requested foreach (SOURCEFILE f in files) { if (f.fileClass == null) f.CreateClassForFile(context, File.stripExtension(f.location.file)); // Ruby.Runtime.Program.AddProgram(filename, fileClass); cctor.ldstr(File.stripExtension(f.location.file)); cctor.ldtoken(f.fileClass); cctor.call(Runtime.SystemType.GetTypeFromHandle); cctor.call(Runtime.Program.AddProgram); } // Load(Object.ruby_top_self, null); cctor.ldsfld(Runtime.Object.ruby_top_self); cctor.ldnull(); cctor.call(LoadMethod.Method); cctor.pop(); cctor.ret(); // } cctor.Close(); } return fileClass; }