internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals) { if (TypeBuilder != null) { // Full compile ilg.Emit(OpCodes.Castclass, TypeBuilder); for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (letFnLocals.contains(lb)) { ClosedOverFieldsMap.TryGetValue(lb, out FieldBuilder fb); Type primt = lb.PrimitiveType; ilg.Emit(OpCodes.Dup); // this if (primt != null) { objx.EmitUnboxedLocal(ilg, lb); ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else { objx.EmitLocal(ilg, lb); ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } } } ilg.Emit(OpCodes.Pop); } }
internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val) { if (!IsMutable(lb)) throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name); FieldBuilder fb = null; bool hasField = ClosedOverFieldsMap.TryGetValue(lb, out fb); ilg.Emit(OpCodes.Ldarg_0); // this Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr; if (!(mbe != null && mbe.CanEmitPrimitive)) throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name); mbe.EmitUnboxed(RHC.Expression, this, ilg); } else { val.Emit(RHC.Expression, this, ilg); } if (hasField) { ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else ilg.Emit(OpCodes.Stloc, lb.LocalVar); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = ClosedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
private void EmitMetaFunctions(TypeBuilder fnTB) { // IPersistentMap meta() MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes); CljILGen gen = new CljILGen(metaMB.GetILGenerator()); if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitFieldGet(MetaField); } else gen.EmitNull(); gen.Emit(OpCodes.Ret); // IObj withMeta(IPersistentMap) MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) }); gen = new CljILGen(withMB.GetILGenerator()); if (SupportsMeta) { gen.EmitLoadArg(1); // meta arg foreach (FieldBuilder fb in ClosedOverFields) { gen.EmitLoadArg(0); gen.MaybeEmitVolatileOp(fb); gen.EmitFieldGet(fb); } gen.EmitNew(CtorInfo); } else gen.EmitLoadArg(0); //this gen.Emit(OpCodes.Ret); }
protected override void EmitSet(CljILGen ilg) { if (_tinfo.IsInitOnly) { throw new InvalidOperationException(String.Format("Attempt to set readonly field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType)); } ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); }
internal void EmitConstant(CljILGen ilg, int id, object val) { FieldBuilder fb = null; if ( ConstantFields != null && ConstantFields.TryGetValue(id, out fb)) { ilg.MaybeEmitVolatileOp(fb); ilg.Emit(OpCodes.Ldsfld, fb); } else EmitValue(val, ilg); }
private void DefineBaseClassClosedOverConstructors(Type super, TypeBuilder tb) { // ctor that takes closed-overs and does nothing if (CtorTypes().Length > 0) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); CljILGen ilg = new CljILGen(cb.GetILGenerator()); ilg.EmitLoadArg(0); ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes)); // store closed-overs in their fields int a = 0; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { FieldBuilder fb = ClosedOverFields[a]; bool isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]); ilg.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); ilg.EmitLoadArg(a + 1); // gen.Emit(OpCodes.Ldarg, a + 1); ilg.MaybeEmitVolatileOp(isVolatile); ilg.Emit(OpCodes.Stfld, fb); } ilg.Emit(OpCodes.Ret); if (AltCtorDrops > 0) { Type[] ctorTypes = CtorTypes(); int newLen = ctorTypes.Length - 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 < AltCtorDrops; i++) { ilg2.EmitNull(); } ilg2.Emit(OpCodes.Call, cb); ilg2.Emit(OpCodes.Ret); } } } }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { GenContext.EmitDebugInfo(ilg, _spanMap); if (_tinfo.IsLiteral) { // literal fields need to be inlined directly in here... We use GetRawConstant // which will work even in partial trust if the constant is protected. object value = _tinfo.GetRawConstantValue(); switch (Type.GetTypeCode(_tinfo.FieldType)) { case TypeCode.Boolean: if ((bool)value) { ilg.Emit(OpCodes.Ldc_I4_1); } else { ilg.Emit(OpCodes.Ldc_I4_0); } break; case TypeCode.Byte: ilg.EmitInt((int)(byte)value); break; case TypeCode.Char: ilg.EmitInt((int)(char)value); break; case TypeCode.Double: ilg.EmitDouble((double)value); break; case TypeCode.Int16: ilg.EmitInt((int)(short)value); break; case TypeCode.Int32: ilg.EmitInt((int)value); break; case TypeCode.Int64: ilg.EmitLong((long)value); break; case TypeCode.SByte: ilg.EmitInt((int)(sbyte)value); break; case TypeCode.Single: ilg.EmitSingle((float)value); break; case TypeCode.String: ilg.EmitString((string)value); break; case TypeCode.UInt16: ilg.EmitInt((int)(ushort)value); break; case TypeCode.UInt32: ilg.Emit(OpCodes.Ldc_I4, (uint)value); break; case TypeCode.UInt64: ilg.Emit(OpCodes.Ldc_I8, (ulong)value); break; } } else { ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldGet(_tinfo); } }
public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { GenContext.EmitDebugInfo(ilg, _spanMap); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); HostExpr.EmitUnboxArg(objx, ilg, FieldType); ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
private ConstructorBuilder EmitConstructorForNonDefType(TypeBuilder fnTB, Type baseType) { ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); CljILGen gen = new CljILGen(cb.GetILGenerator()); GenContext.EmitDebugInfo(gen, SpanMap); //Call base constructor ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null); if (baseCtorInfo == null) { throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName); } gen.EmitLoadArg(0); gen.Emit(OpCodes.Call, baseCtorInfo); // Store Meta if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitLoadArg(1); gen.Emit(OpCodes.Castclass, typeof(IPersistentMap)); gen.EmitFieldSet(MetaField); } // store closed-overs in their fields int a = 0; int offset = !SupportsMeta ? 1 : 2; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { //LocalBinding lb = (LocalBinding)s.first(); FieldBuilder fb = ClosedOverFields[a]; bool isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitLoadArg(a + offset); // gen.Emit(OpCodes.Ldarg, a + 1); gen.MaybeEmitVolatileOp(isVolatile); gen.Emit(OpCodes.Stfld, fb); } gen.Emit(OpCodes.Ret); return(cb); }
public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { if (_tinfo.IsInitOnly) { throw new InvalidOperationException(String.Format("Attempt to set readonly static field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType)); } GenContext.EmitDebugInfo(ilg, _spanMap); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); HostExpr.EmitUnboxArg(objx, ilg, FieldType); ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = ClosedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else // FnMode.Light { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); } } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); if (lb.PrimitiveType != null) ilg.Emit(OpCodes.Unbox, lb.PrimitiveType); } } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
protected override void EmitGet(CljILGen ilg) { ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldGet(_tinfo); }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals) { if (_typeBuilder != null) { // Full compile ilg.Emit(OpCodes.Castclass, _typeBuilder); for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (letFnLocals.contains(lb)) { FieldBuilder fb; _closedOverFieldsMap.TryGetValue(lb, out fb); Type primt = lb.PrimitiveType; ilg.Emit(OpCodes.Dup); // this if (primt != null) { objx.EmitUnboxedLocal(ilg, lb); ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else { objx.EmitLocal(ilg, lb); ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } } } ilg.Emit(OpCodes.Pop); } }
internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val) { if (!IsMutable(lb)) throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name); FieldBuilder fb = null; bool hasField = _closedOverFieldsMap.TryGetValue(lb, out fb); ilg.Emit(OpCodes.Ldarg_0); // this Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr; if (!(mbe != null && mbe.CanEmitPrimitive)) throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name); mbe.EmitUnboxed(RHC.Expression, this, ilg); } else { val.Emit(RHC.Expression, this, ilg); } if (hasField) { ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else ilg.Emit(OpCodes.Stloc, lb.LocalVar); }
private void EmitMetaFunctions(TypeBuilder fnTB) { // IPersistentMap meta() MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes); CljILGen gen = new CljILGen(metaMB.GetILGenerator()); if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitFieldGet(_metaField); } else gen.EmitNull(); gen.Emit(OpCodes.Ret); // IObj withMeta(IPersistentMap) MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) }); gen = new CljILGen(withMB.GetILGenerator()); if (SupportsMeta) { gen.EmitLoadArg(1); // meta arg foreach (FieldBuilder fb in _closedOverFields) { gen.EmitLoadArg(0); gen.MaybeEmitVolatileOp(fb); gen.EmitFieldGet(fb); } gen.EmitNew(_ctorInfo); } else gen.EmitLoadArg(0); //this gen.Emit(OpCodes.Ret); }
private ConstructorBuilder EmitConstructor(TypeBuilder fnTB, Type baseType) { ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); CljILGen gen = new CljILGen(cb.GetILGenerator()); GenContext.EmitDebugInfo(gen, SpanMap); //Call base constructor ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public,null,Type.EmptyTypes,null); if (baseCtorInfo == null) throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName); gen.EmitLoadArg(0); gen.Emit(OpCodes.Call, baseCtorInfo); // Store Meta if (SupportsMeta) { gen.EmitLoadArg(0); gen.EmitLoadArg(1); gen.Emit(OpCodes.Castclass, typeof(IPersistentMap)); gen.EmitFieldSet(_metaField); } // store closed-overs in their fields int a = 0; int offset = !SupportsMeta ? 1 : 2; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { //LocalBinding lb = (LocalBinding)s.first(); FieldBuilder fb = _closedOverFields[a]; bool isVolatile = IsVolatile(_closedOverFieldsToBindingsMap[fb]); gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); gen.EmitLoadArg(a + offset); // gen.Emit(OpCodes.Ldarg, a + 1); gen.MaybeEmitVolatileOp(isVolatile); gen.Emit(OpCodes.Stfld, fb); } gen.Emit(OpCodes.Ret); return cb; }
private static void EmitExposers(TypeBuilder proxyTB, Type superClass, IPersistentMap exposesFields) { for ( ISeq s = RT.seq(exposesFields); s != null; s = s.next() ) { IMapEntry me = (IMapEntry)s.first(); Symbol protectedFieldSym = (Symbol)me.key(); IPersistentMap accessMap = (IPersistentMap)me.val(); string fieldName = protectedFieldSym.Name; Symbol getterSym = (Symbol)accessMap.valAt(_getKw, null); Symbol setterSym = (Symbol)accessMap.valAt(_setKW, null); FieldInfo fld = null; if ( getterSym != null || setterSym != null ) fld = superClass.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Instance); if (getterSym != null) { MethodAttributes attribs = MethodAttributes.Public; if (fld.IsStatic) attribs |= MethodAttributes.Static; MethodBuilder mb = proxyTB.DefineMethod(getterSym.Name, attribs, fld.FieldType, Type.EmptyTypes); CljILGen gen = new CljILGen(mb.GetILGenerator()); //if (fld.IsStatic) // gen.Emit(OpCodes.Ldsfld, fld); //else //{ // gen.Emit(OpCodes.Ldarg_0); // gen.Emit(OpCodes.Ldfld, fld); //} if (!fld.IsStatic) gen.EmitLoadArg(0); gen.MaybeEmitVolatileOp(fld); gen.EmitFieldGet(fld); gen.Emit(OpCodes.Ret); } if (setterSym != null) { MethodAttributes attribs = MethodAttributes.Public; if (fld.IsStatic) attribs |= MethodAttributes.Static; MethodBuilder mb = proxyTB.DefineMethod(setterSym.Name, attribs, typeof(void), new Type[] { fld.FieldType }); CljILGen gen = new CljILGen(mb.GetILGenerator()); if (fld.IsStatic) { gen.Emit(OpCodes.Ldarg_0); //gen.Emit(OpCodes.Stsfld, fld); } else { gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_1); //gen.Emit(OpCodes.Stfld, fld); } gen.MaybeEmitVolatileOp(fld); gen.EmitFieldSet(fld); gen.Emit(OpCodes.Ret); } } }
internal void EmitConstant(CljILGen ilg, int id, object val) { if (_fnMode == Ast.FnMode.Light) { if (val == null) { ilg.EmitNull(); } if (val.GetType().IsPrimitive) { EmitPrimitive(ilg, val); ilg.Emit(OpCodes.Box,val.GetType()); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Constants); ilg.EmitInt(id); ilg.EmitLoadElement(typeof(Object)); ilg.Emit(OpCodes.Castclass, ConstantType(id)); } } else { FieldBuilder fb = null; if (_fnMode == FnMode.Full && ConstantFields != null && ConstantFields.TryGetValue(id, out fb)) { ilg.MaybeEmitVolatileOp(fb); ilg.Emit(OpCodes.Ldsfld, fb); } else EmitValue(val, ilg); } }
void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg) { //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any //objx arg is enclosing objx, not this // Create the function instance LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType); if (CompiledType == typeof(RestFnImpl)) { ilg.EmitInt(_variadicMethod.RequiredArity); ilg.EmitNew(Compiler.Ctor_RestFnImpl_1); } else { ilg.EmitNew(Compiler.Ctor_AFnImpl); } ilg.Emit(OpCodes.Stloc, fnLocal); //ilg.EmitString(String.Format("Creating fn {0}", Name)); //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) })); // Set up the methods for (ISeq s = RT.seq(_methods); s != null; s = s.next()) { FnMethod method = (FnMethod)s.first(); int key = GetMethodKey(method); string fieldName = IsVariadic && method.IsVariadic ? "_fnDo" + (key - 1) // because key is arity+1 for variadic : "_fn" + key; FieldInfo fi = CompiledType.GetField(fieldName); ilg.Emit(OpCodes.Ldloc, fnLocal); EmitGetDynMethod(key, ilg); ilg.EmitType(fi.FieldType); ilg.Emit(OpCodes.Ldloc, fnLocal); ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate); ilg.Emit(OpCodes.Castclass, fi.FieldType); ilg.MaybeEmitVolatileOp(fi); ilg.EmitFieldSet(fi); } // setup the constants and locals ilg.Emit(OpCodes.Ldloc, fnLocal); if (Constants.count() > 0) { EmitGetCompiledConstants(ilg); } else { ilg.EmitInt(0); ilg.EmitArray(typeof(Object[])); } if (Closes.count() > 0) { int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index); ilg.EmitInt(maxIndex + 1); ilg.Emit(OpCodes.Newarr, typeof(object)); for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); ilg.Emit(OpCodes.Dup); ilg.EmitInt(lb.Index); objx.EmitLocal(ilg, lb); ilg.EmitStoreElement(typeof(object)); } } else { ilg.EmitInt(0); ilg.EmitArray(typeof(Object[])); } // Create the closure ilg.EmitNew(Compiler.Ctor_Closure_2); // Assign the clojure ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure); // Leave the instance on the stack. ilg.Emit(OpCodes.Ldloc, fnLocal); }
private void DefineBaseClassClosedOverConstructors(Type super, TypeBuilder tb) { // ctor that takes closed-overs and does nothing if (CtorTypes().Length > 0) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis,CtorTypes()); CljILGen ilg = new CljILGen(cb.GetILGenerator()); ilg.EmitLoadArg(0); ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes)); // store closed-overs in their fields int a = 0; for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++) { FieldBuilder fb = ClosedOverFields[a]; bool isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]); ilg.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); ilg.EmitLoadArg(a + 1); // gen.Emit(OpCodes.Ldarg, a + 1); ilg.MaybeEmitVolatileOp(isVolatile); ilg.Emit(OpCodes.Stfld, fb); } ilg.Emit(OpCodes.Ret); if (AltCtorDrops > 0) { Type[] ctorTypes = CtorTypes(); int newLen = ctorTypes.Length - 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 < AltCtorDrops; i++) ilg2.EmitNull(); ilg2.Emit(OpCodes.Call, cb); ilg2.Emit(OpCodes.Ret); } } } }