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, 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, List <MethodInfo> > overrideables;
GatherMethods(superClass, RT.seq(interfaces), out overrideables);
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 stub = CompileStub(genC, 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);
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, stub
));
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);
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.
//if (RT.CompileDLR)
ret.Compile(stub, stub, interfaces, false, genC);
//else
// ret.CompileNoDlr(stub, stub, interfaces, false, genC);
Compiler.RegisterDuplicateType(ret.CompiledType);
return(ret);
}