protected void SetCustomAttributes(MethodBuilder mb) { GenInterface.SetCustomAttributes(mb, MethodMeta); if (Parms != null) { for (int i = 0; i < Parms.count(); i++) { IPersistentMap meta = GenInterface.ExtractAttributes(RT.meta(Parms.nth(i))); if (meta != null && meta.count() > 0) { ParameterBuilder pb = mb.DefineParameter(i + 1, ParameterAttributes.None, ((Symbol)Parms.nth(i)).Name); GenInterface.SetCustomAttributes(pb, meta); } } } }
void GeneratePrimMethod(ObjExpr objx, GenContext context) { TypeBuilder tb = objx.TypeBuilder; MethodBuilder mb = tb.DefineMethod("invokePrim", MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, StaticReturnType, StaticMethodArgTypes); //Console.Write("InMd: {0} {1}(", ReturnType.Name, "invokePrim"); //foreach (Type t in ArgTypes) // Console.Write("{0}", t.Name); //Console.WriteLine(")"); GenInterface.SetCustomAttributes(mb, _methodMeta); if (_parms != null) { for (int i = 0; i < _parms.count(); i++) { IPersistentMap meta = GenInterface.ExtractAttributes(RT.meta(_parms.nth(i))); if (meta != null && meta.count() > 0) { ParameterBuilder pb = mb.DefineParameter(i + 1, ParameterAttributes.None, ((Symbol)_parms.nth(i)).Name); GenInterface.SetCustomAttributes(pb, meta); } } } ILGen gen = new ILGen(mb.GetILGenerator()); gen.EmitLoadArg(0); for (int i = 1; i <= _argLocals.count(); i++) { gen.EmitLoadArg(i); } gen.EmitCall(_staticMethodBuilder); gen.Emit(OpCodes.Ret); if (IsExplicit) { tb.DefineMethodOverride(mb, _explicitMethodInfo); } }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (_compiledType != null) { return(_compiledType); } string publicTypeName = IsDefType || (_isStatic && Compiler.IsCompiling) ? InternalName : InternalName + "__" + RT.nextID(); //Console.WriteLine("DefFn {0}, {1}", publicTypeName, context.AssemblyBuilder.GetName().Name); _typeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(_typeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) { _typeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } } ObjExpr.MarkAsSerializable(_typeBuilder); GenInterface.SetCustomAttributes(_typeBuilder, _classMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(_typeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(_typeBuilder); EmitKeywordCallsiteDefs(_typeBuilder); DefineStaticConstructor(_typeBuilder); if (SupportsMeta) { _metaField = _typeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); } EmitClosedOverFields(_typeBuilder); EmitProtocolCallsites(_typeBuilder); _ctorInfo = EmitConstructor(_typeBuilder, superType); if (_altCtorDrops > 0) { EmitFieldOnlyConstructor(_typeBuilder, superType); } if (SupportsMeta) { EmitNonMetaConstructor(_typeBuilder, superType); EmitMetaFunctions(_typeBuilder); } EmitStatics(_typeBuilder); EmitMethods(_typeBuilder); //if (KeywordCallsites.count() > 0) // EmitSwapThunk(_typeBuilder); _compiledType = _typeBuilder.CreateType(); if (context.DynInitHelper != null) { context.DynInitHelper.FinalizeType(); } // If we don't pick up the ctor after we finalize the type, // we sometimes get a ctor which is not a RuntimeConstructorInfo // This causes System.DynamicILGenerator.Emit(opcode,ContructorInfo) to blow up. // The error says the ConstructorInfo is null, but there is a second case in the code. // Thank heavens one can run Reflector on mscorlib. ConstructorInfo[] cis = _compiledType.GetConstructors(); foreach (ConstructorInfo ci in cis) { if (ci.GetParameters().Length == CtorTypes().Length) { _ctorInfo = ci; break; } } return(_compiledType); } finally { if (IsDefType) { Var.popThreadBindings(); } } } finally { Var.popThreadBindings(); } }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (CompiledType != null) { return(CompiledType); } string publicTypeName = IsDefType /* || (CanBeDirect && Compiler.IsCompiling) */ ? InternalName : InternalName + "__" + RT.nextID(); TypeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(TypeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) { TypeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } } ObjExpr.MarkAsSerializable(TypeBuilder); GenInterface.SetCustomAttributes(TypeBuilder, ClassMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(TypeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType, Compiler.CompilingDefTypeVar, true )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(TypeBuilder); EmitKeywordCallsiteDefs(TypeBuilder); DefineStaticConstructor(TypeBuilder); if (SupportsMeta) { MetaField = TypeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); } // If this IsDefType, then it has already emitted the closed-over fields on the base class. if (!IsDefType) { EmitClosedOverFields(TypeBuilder); } EmitProtocolCallsites(TypeBuilder); CtorInfo = EmitConstructor(TypeBuilder, superType); if (AltCtorDrops > 0) { EmitFieldOnlyConstructors(TypeBuilder, superType); } if (SupportsMeta) { EmitNonMetaConstructor(TypeBuilder, superType); EmitMetaFunctions(TypeBuilder); } EmitStatics(TypeBuilder); EmitMethods(TypeBuilder); CompiledType = TypeBuilder.CreateType(); if (context.DynInitHelper != null) { context.DynInitHelper.FinalizeType(); } CtorInfo = GetConstructorWithArgCount(CompiledType, CtorTypes().Length); return(CompiledType); } finally { if (IsDefType) { Var.popThreadBindings(); } } } finally { Var.popThreadBindings(); } }
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); }
protected ATProject() { service = Driver.getInstance(); }
public static NewInstanceMethod Parse(ObjExpr objx, ISeq form, Symbol thisTag, Dictionary <IPersistentVector, IList <MethodInfo> > overrideables, Dictionary <IPersistentVector, IList <MethodInfo> > explicits) { // (methodname [this-name args*] body...) // this-name might be nil NewInstanceMethod method = new NewInstanceMethod(objx, (ObjMethod)Compiler.MethodVar.deref()); Symbol dotName = (Symbol)RT.first(form); Symbol name; string methodName; int idx = dotName.Name.LastIndexOf("."); if (idx >= 0) { // we have an explicit interface implementation string dotNameStr = dotName.Name; string interfaceName = dotNameStr.Substring(0, idx); method.ExplicitInterface = RT.classForName(interfaceName); if (method.ExplicitInterface == null) { throw new ParseException(String.Format("Unable to find interface {0} for explicit method implemntation: {1}", interfaceName, dotNameStr)); } methodName = dotNameStr.Substring(idx + 1); name = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName)); } else { name = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName)); methodName = name.Name; } IPersistentVector parms = (IPersistentVector)RT.second(form); if (parms.count() == 0 || !(parms.nth(0) is Symbol)) { throw new ParseException("Must supply at least one argument for 'this' in: " + dotName); } Symbol thisName = (Symbol)parms.nth(0); parms = RT.subvec(parms, 1, parms.count()); ISeq body = RT.next(RT.next(form)); try { method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // register as the current method and set up a new env frame // PathNode pnade = new PathNode(PATHTYPE.PATH, (PathNode) CLEAR_PATH.get()); Var.pushThreadBindings( RT.mapUniqueKeys( Compiler.MethodVar, method, Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.LoopLocalsVar, null, Compiler.NextLocalNumVar, 0 // CLEAR_PATH, pnode, // CLEAR_ROOT, pnode, // CLEAR_SITES, PersistentHashMap.EMPTY )); // register 'this' as local 0 //method._thisBinding = Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null); Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null); IPersistentVector argLocals = PersistentVector.EMPTY; method._retType = Compiler.TagType(Compiler.TagOf(name)); method._argTypes = new Type[parms.count()]; bool hinted = Compiler.TagOf(name) != null; Type[] pTypes = new Type[parms.count()]; Symbol[] pSyms = new Symbol[parms.count()]; bool[] pRefs = new bool[parms.count()]; for (int i = 0; i < parms.count(); i++) { // Param should be symbol or (by-ref symbol) Symbol p; bool isByRef = false; object pobj = parms.nth(i); if (pobj is Symbol) { p = (Symbol)pobj; } else if (pobj is ISeq) { ISeq pseq = (ISeq)pobj; object first = RT.first(pseq); object second = RT.second(pseq); if (!(first is Symbol && ((Symbol)first).Equals(HostExpr.ByRefSym))) { throw new ParseException("First element in parameter pair must be by-ref"); } if (!(second is Symbol)) { throw new ParseException("Params must be Symbols"); } isByRef = true; p = (Symbol)second; hinted = true; } else { throw new ParseException("Params must be Symbols or of the form (by-ref Symbol)"); } object tag = Compiler.TagOf(p); if (tag != null) { hinted = true; } if (p.Namespace != null) { p = Symbol.intern(p.Name); } Type pType = Compiler.TagType(tag); if (isByRef) { pType = pType.MakeByRefType(); } pTypes[i] = pType; pSyms[i] = p; pRefs[i] = isByRef; } Dictionary <IPersistentVector, IList <MethodInfo> > matches = method.IsExplicit ? FindMethodsWithNameAndArity(method.ExplicitInterface, methodName, parms.count(), overrideables, explicits) : FindMethodsWithNameAndArity(methodName, parms.count(), overrideables); IPersistentVector mk = MSig(methodName, pTypes, method._retType); IList <MethodInfo> ms = null; if (matches.Count > 0) { // multiple matches if (matches.Count > 1) { // must be hinted and match one method if (!hinted) { throw new ParseException("Must hint overloaded method: " + name.Name); } if (!matches.TryGetValue(mk, out ms)) { throw new ParseException("Can't find matching overloaded method: " + name.Name); } method._minfos = ms; } else // one match { // if hinted, validate match, if (hinted) { if (!matches.TryGetValue(mk, out ms)) { throw new ParseException("Can't find matching method: " + name.Name + ", leave off hints for auto match."); } method._minfos = ms; //if (m.ReturnType != method._retType) // throw new ArgumentException(String.Format("Mismatched return type: {0}, expected {1}, had: {2}", // name.Name, m.ReturnType.Name, method._retType.Name)); } else // adopt found method sig { using (var e = matches.GetEnumerator()) { e.MoveNext(); mk = e.Current.Key; ms = e.Current.Value; } MethodInfo m = ms[0]; method._retType = m.ReturnType; pTypes = Compiler.GetTypes(m.GetParameters()); method._minfos = ms; } } } else { throw new ParseException("Can't define method not in interfaces: " + name.Name); } if (method.IsExplicit) { method.ExplicitMethodInfo = ms[0]; } // validate unique name + arity among additional methods for (int i = 0; i < parms.count(); i++) { LocalBinding lb = Compiler.RegisterLocal(pSyms[i], null, new MethodParamExpr(pTypes[i]), true, pRefs[i]); argLocals = argLocals.assocN(i, lb); method._argTypes[i] = pTypes[i]; } Compiler.LoopLocalsVar.set(argLocals); method._name = name.Name; method.MethodMeta = GenInterface.ExtractAttributes(RT.meta(name)); method.Parms = parms; method.ArgLocals = argLocals; method.Body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body); return(method); } finally { Var.popThreadBindings(); } }
public void SetReal(Facade realInstance) { real = realInstance; }