Пример #1
0
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */
        static Type CompileStub(Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            GenContext  context = Compiler.CompilerContextVar.get() as GenContext ?? GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false);
            TypeBuilder tb      = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName, TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding    lb     = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                // TODO: FIgure out Volatile
                if (!ret.IsVolatile(lb))
                {
                    access |= FieldAttributes.InitOnly;
                }

                if (lb.PrimitiveType != null)
                {
                    tb.DefineField(lb.Name, lb.PrimitiveType, access);
                }
                else
                {
                    tb.DefineField(lb.Name, typeof(Object), access);
                }
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                ILGen ilg             = new ILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);


                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int    newLen    = ctorTypes.Length - ret._altCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                        {
                            altCtorTypes[i] = ctorTypes[i];
                        }
                        ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        ILGen ilg2             = new ILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                        {
                            ilg2.EmitLoadArg(i + 1);
                        }
                        for (int i = 0; i < ret._altCtorDrops; i++)
                        {
                            ilg2.EmitNull();
                        }
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();

            Compiler.RegisterDuplicateType(t);
            return(t);
        }
Пример #2
0
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms,
            IPersistentVector fieldSyms,
            Symbol thisSym,
            string tagName,
            Symbol className,
            Symbol typeTag,
            ISeq methodForms,
            Object frm)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);

            ret._src         = frm;
            ret._name        = className.ToString();
            ret._classMeta   = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);

            if (thisSym != null)
            {
                ret._thisName = thisSym.Name;
            }

            if (fieldSyms != null)
            {
                IPersistentMap fmap      = PersistentHashMap.EMPTY;
                object[]       closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol       sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb  = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false);
                    fmap                 = fmap.assoc(sym, lb);
                    closesvec[i * 2]     = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret._closes = new PersistentArrayMap(closesvec);
                ret._fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i)
                {
                    ret._altCtorDrops++;
                }
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                {
                    throw new ParseException("only interfaces are supported, had: " + t.Name);
                }
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary <IPersistentVector, List <MethodInfo> > overrideables;

            GatherMethods(superClass, RT.seq(interfaces), out overrideables);

            ret._methodMap = overrideables;

            //string[] inames = InterfaceNames(interfaces);

            Type   stub    = CompileStub(superClass, ret, SeqToTypeArray(interfaces), frm);
            Symbol thisTag = Symbol.intern(null, stub.FullName);
            //Symbol stubTag = Symbol.intern(null,stub.FullName);
            //Symbol thisTag = Symbol.intern(null, tagName);

            // Needs its own GenContext so it has its own DynInitHelper
            // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition
            GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? (ret.IsDefType ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true) : Compiler.EvalContext);
            GenContext genC    = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());

            //genC.FnCompileMode = FnMode.Full;

            try
            {
                Var.pushThreadBindings(
                    RT.map(
                        Compiler.ConstantsVar, PersistentVector.EMPTY,
                        Compiler.ConstantIdsVar, new IdentityHashMap(),
                        Compiler.KeywordsVar, PersistentHashMap.EMPTY,
                        Compiler.VarsVar, PersistentHashMap.EMPTY,
                        Compiler.KeywordCallsitesVar, PersistentVector.EMPTY,
                        Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY,
                        Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(),
                        Compiler.NoRecurVar, null,
                        Compiler.CompilerContextVar, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.map(
                            Compiler.MethodVar, null,
                            Compiler.LocalEnvVar, ret._fields,
                            Compiler.CompileStubSymVar, Symbol.intern(null, tagName),
                            Compiler.CompileStubClassVar, stub
                            ));
                    ret._hintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret._altCtorDrops);
                }
                // now (methodname [args] body)*
                // TODO: SourceLocation?
                //ret.line = (Integer)LINE.deref();
                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables);
                    methods = RT.conj(methods, m);
                }

                ret.Methods           = methods;
                ret.Keywords          = (IPersistentMap)Compiler.KeywordsVar.deref();
                ret.Vars              = (IPersistentMap)Compiler.VarsVar.deref();
                ret.Constants         = (PersistentVector)Compiler.ConstantsVar.deref();
                ret._constantsID      = RT.nextID();
                ret.KeywordCallsites  = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                ret.VarCallsites      = (IPersistentSet)Compiler.VarCallsitesVar.deref();
            }
            finally
            {
                if (ret.IsDefType)
                {
                    Var.popThreadBindings();
                }
                Var.popThreadBindings();
            }

            // TOD:  Really, the first stub here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call.
            // Might be able to flag stub classes and not try to convert, leading to a dynsite.
            ret.Compile(stub, stub, interfaces, false, genC);
            Compiler.RegisterDuplicateType(ret.CompiledType);

            return(ret);
        }
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms,
            IPersistentVector fieldSyms,
            Symbol thisSym,
            string tagName,
            Symbol className,
            Symbol typeTag,
            ISeq methodForms,
            Object frm)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);
            ret._src = frm;
            ret._name = className.ToString();
            ret._classMeta = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);

            if (thisSym != null)
                ret._thisName = thisSym.Name;

            if (fieldSyms != null)
            {
                IPersistentMap fmap = PersistentHashMap.EMPTY;
                object[] closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false);
                    fmap = fmap.assoc(sym, lb);
                    closesvec[i * 2] = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret._closes = new PersistentArrayMap(closesvec);
                ret._fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i)
                    ret._altCtorDrops++;
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;
            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                    throw new ArgumentException("only interfaces are supported, had: " + t.Name);
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary<IPersistentVector, List<MethodInfo>> overrideables;
            GatherMethods(superClass, RT.seq(interfaces), out overrideables);

            ret._methodMap = overrideables;

            //string[] inames = InterfaceNames(interfaces);

            Type stub = CompileStub(superClass, ret, SeqToTypeArray(interfaces),frm);
            Symbol thisTag = Symbol.intern(null, stub.FullName);
            //Symbol stubTag = Symbol.intern(null,stub.FullName);
            //Symbol thisTag = Symbol.intern(null, tagName);

            // Needs its own GenContext so it has its own DynInitHelper
            // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition
            GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? (ret.IsDefType ? new GenContext("deftype" + RT.nextID().ToString(),".dll",".",true) : Compiler.EvalContext);
            GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());
            //genC.FnCompileMode = FnMode.Full;

            try
            {
                Var.pushThreadBindings(
                    RT.map(
                        Compiler.CONSTANTS, PersistentVector.EMPTY,
                        Compiler.CONSTANT_IDS, new IdentityHashMap(),
                        Compiler.KEYWORDS, PersistentHashMap.EMPTY,
                        Compiler.VARS, PersistentHashMap.EMPTY,
                        Compiler.KEYWORD_CALLSITES, PersistentVector.EMPTY,
                        Compiler.PROTOCOL_CALLSITES, PersistentVector.EMPTY,
                        Compiler.VAR_CALLSITES, PersistentVector.EMPTY,
                        Compiler.COMPILER_CONTEXT, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.map(
                            Compiler.METHOD, null,
                            Compiler.LOCAL_ENV, ret._fields,
                            Compiler.COMPILE_STUB_SYM, Symbol.intern(null, tagName),
                            Compiler.COMPILE_STUB_CLASS, stub
                            ));
                }
                // now (methodname [args] body)*
                // TODO: SourceLocation?
                //ret.line = (Integer)LINE.deref();
                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables);
                    methods = RT.conj(methods, m);
                }

                ret._methods = methods;
                ret.Keywords = (IPersistentMap)Compiler.KEYWORDS.deref();
                ret.Vars = (IPersistentMap)Compiler.VARS.deref();
                ret.Constants = (PersistentVector)Compiler.CONSTANTS.deref();
                ret._constantsID = RT.nextID();
                ret.KeywordCallsites = (IPersistentVector)Compiler.KEYWORD_CALLSITES.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.PROTOCOL_CALLSITES.deref();
                ret.VarCallsites = (IPersistentVector)Compiler.VAR_CALLSITES.deref();
            }
            finally
            {
                if (ret.IsDefType)
                    Var.popThreadBindings();
                Var.popThreadBindings();
            }

            ret.Compile(stub, interfaces, false, genC);
            Compiler.RegisterDuplicateType(ret.CompiledType);

            return ret;
        }
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */
        static Type CompileStub(Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            //GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? Compiler.EvalContext;
            //GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? new GenContext("stub" + RT.nextID().ToString(), ".dll", ".", CompilerMode.Immediate);
            GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? new GenContext("stub" + RT.nextID().ToString(), ".dll", ".", false);
            TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.COMPILE_STUB_PREFIX + "." + ret.InternalName, TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                // TODO: FIgure out Volatile
                if (!ret.IsVolatile(lb))
                    access |= FieldAttributes.InitOnly;

                if (lb.PrimitiveType != null)
                    tb.DefineField(lb.Name, lb.PrimitiveType, access);
                else
                    tb.DefineField(lb.Name, typeof(Object), access);
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                ILGen ilg = new ILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);

                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int newLen = ctorTypes.Length - ret._altCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                            altCtorTypes[i] = ctorTypes[i];
                        ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        ILGen ilg2 = new ILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                            ilg2.EmitLoadArg(i + 1);
                        for (int i = 0; i < ret._altCtorDrops; i++)
                            ilg2.EmitNull();
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();
            Compiler.RegisterDuplicateType(t);
            return t;
        }
Пример #5
0
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms, 
            IPersistentVector fieldSyms, 
            Symbol thisSym,
            string tagName, 
            Symbol className, 
            Symbol typeTag, 
            ISeq methodForms,
            Object frm,
            IPersistentMap opts)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);
            ret.Src = frm;
            ret.Name = className.ToString();
            ret.ClassMeta = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);
            ret.Opts = opts;

            if (thisSym != null)
                ret.ThisName = thisSym.Name;

            if (fieldSyms != null)
            {
                IPersistentMap fmap = PersistentHashMap.EMPTY;
                object[] closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false, false);
                    fmap = fmap.assoc(sym, lb);
                    closesvec[i * 2] = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret.Closes = new PersistentArrayMap(closesvec);
                ret.Fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && (((Symbol)fieldSyms.nth(i)).Name.Equals("__meta") || ((Symbol)fieldSyms.nth(i)).Name.Equals("__extmap")); --i)
                    ret.AltCtorDrops++;
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;
            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                    throw new ParseException("only interfaces are supported, had: " + t.Name);
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary<IPersistentVector, IList<MethodInfo>> overrideables;
            Dictionary<IPersistentVector, IList<MethodInfo>> explicits;
            GatherMethods(superClass, RT.seq(interfaces), out overrideables, out explicits);

            ret._methodMap = overrideables;

  
            GenContext context = Compiler.IsCompiling
                ? Compiler.CompilerContextVar.get() as GenContext
                : (ret.IsDefType
                    ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true)
                    : (Compiler.CompilerContextVar.get() as GenContext
                        ??
                        Compiler.EvalContext));

            GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());

            Type baseClass = ret.CompileBaseClass(genC, superClass, SeqToTypeArray(interfaces), frm);
            Symbol thisTag = Symbol.intern(null, baseClass.FullName);

            try
            {
                Var.pushThreadBindings(
                    RT.mapUniqueKeys(
                        Compiler.ConstantsVar, PersistentVector.EMPTY,
                        Compiler.ConstantIdsVar, new IdentityHashMap(),
                        Compiler.KeywordsVar, PersistentHashMap.EMPTY,
                        Compiler.VarsVar, PersistentHashMap.EMPTY,
                        Compiler.KeywordCallsitesVar, PersistentVector.EMPTY,
                        Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY,
                        Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(),
                        Compiler.NoRecurVar, null,
                        Compiler.CompilerContextVar, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.mapUniqueKeys(
                            Compiler.MethodVar, null,
                            Compiler.LocalEnvVar, ret.Fields,
                            Compiler.CompileStubSymVar, Symbol.intern(null, tagName),
                            Compiler.CompileStubClassVar, baseClass
                            ));
                    ret.HintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret.AltCtorDrops);
                }
                // now (methodname [args] body)*

                ret.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();

                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables, explicits);
                    methods = RT.conj(methods, m);
                }

                ret.Methods = methods;
                ret.Keywords = (IPersistentMap)Compiler.KeywordsVar.deref();
                ret.Vars = (IPersistentMap)Compiler.VarsVar.deref();
                ret.Constants = (PersistentVector)Compiler.ConstantsVar.deref();
                ret.ConstantsID = RT.nextID();
                ret.KeywordCallsites = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                ret.VarCallsites = (IPersistentSet)Compiler.VarCallsitesVar.deref();
            }
            finally
            {
                if (ret.IsDefType)
                    Var.popThreadBindings();
                Var.popThreadBindings();
            }

            // TOD:  Really, the first baseclass here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call.
            // Might be able to flag baseclass classes and not try to convert, leading to a dynsite.

            ret.Compile(baseClass, baseClass, interfaces, false, genC);

            Compiler.RegisterDuplicateType(ret.CompiledType);

            return ret;
        }
Пример #6
0
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */
        // TODO: Preparse method heads to pick up signatures, implement those methods as abstract or as NotImpelmented so that Reflection can pick up calls during compilation and avoide a callsite.
        static Type CompileStub(GenContext context, Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName + RT.nextID(), TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                if (!ret.IsMutable(lb))
                    access |= FieldAttributes.InitOnly;

                Type fieldType = lb.PrimitiveType ?? typeof(Object);

                if (ret.IsVolatile(lb))
                   tb.DefineField(lb.Name, fieldType, new Type[] { typeof(IsVolatile) }, Type.EmptyTypes, access);
                else
                    tb.DefineField(lb.Name, fieldType, access);
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                CljILGen ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);

                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int newLen = ctorTypes.Length - ret._altCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                            altCtorTypes[i] = ctorTypes[i];
                        ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                            ilg2.EmitLoadArg(i + 1);
                        for (int i = 0; i < ret._altCtorDrops; i++)
                            ilg2.EmitNull();
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();
            //Compiler.RegisterDuplicateType(t);
            return t;
        }