/***
* 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);
}