public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { ilg.EmitBoolean(_val); ilg.Emit(OpCodes.Box,typeof(bool)); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { EmitUnboxed(rhc, objx, ilg); HostExpr.EmitBoxReturn(objx, ilg, typeof(bool)); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { objx.EmitVar(ilg, _var); if (_isDynamic) { ilg.Emit(OpCodes.Call, Compiler.Method_Var_setDynamic0); } if (_meta != null) { if (_initProvided || true) //IncludesExplicitMetadata((MapExpr)_meta)) { ilg.Emit(OpCodes.Dup); _meta.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Call, Compiler.Method_Var_setMeta); } } if (_initProvided) { ilg.Emit(OpCodes.Dup); if (_init is FnExpr) ((FnExpr)_init).EmitForDefn(objx, ilg); else _init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Call,Compiler.Method_Var_bindRoot); } if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { objx.EmitVar(ilg, _var); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Call, Compiler.Method_Var_set); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { ilg.Emit(OpCodes.Call,Compiler.Method_Compiler_CurrentNamespace.GetGetMethod()); ilg.Emit(OpCodes.Ldstr, _c); ilg.Emit(OpCodes.Call, Compiler.Method_RT_classForName); ilg.Emit(OpCodes.Call, Compiler.Method_Namespace_importClass1); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { for (int i = 0; i < _exprs.count() - 1; i++) { Expr e = (Expr)_exprs.nth(i); e.Emit(RHC.Statement, objx, ilg); } LastExpr.Emit(rhc, objx, ilg); }
public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { for (int i = 0; i < _exprs.count() - 1; i++) { Expr e = (Expr)_exprs.nth(i); e.Emit(RHC.Statement, objx, ilg); } MaybePrimitiveExpr mbe = (MaybePrimitiveExpr)LastExpr; mbe.EmitUnboxed(rhc, objx, ilg); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { _expr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IObj)); _meta.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.EmitCall(Compiler.Method_IObj_withMeta); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_excExpr == null) { ilg.Emit(OpCodes.Rethrow); } else { _excExpr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(Exception)); ilg.Emit(OpCodes.Throw); } }
public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { Type t = _n.GetType(); if (t == typeof(int)) ilg.EmitLong((long)(int)_n); else if (t == typeof(double)) ilg.EmitDouble((double)_n); else if (t == typeof(long)) ilg.EmitLong((long)_n); else throw new ArgumentException("Unsupported Number type: " + _n.GetType().Name); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { objx.EmitVar(ilg, _var); if ( _shadowsCoreMapping ) { LocalBuilder locNs = ilg.DeclareLocal(typeof(Namespace)); GenContext.SetLocalName(locNs, "ns"); ilg.Emit(OpCodes.Dup); ilg.EmitFieldGet(VarNsFI); ilg.Emit(OpCodes.Stloc,locNs); LocalBuilder locSym = ilg.DeclareLocal(typeof(Symbol)); GenContext.SetLocalName(locSym, "sym"); ilg.Emit(OpCodes.Dup); ilg.EmitFieldGet(VarSymFI); ilg.Emit(OpCodes.Stloc, locSym); ilg.Emit(OpCodes.Ldloc, locNs); ilg.Emit(OpCodes.Ldloc, locSym); ilg.Emit(OpCodes.Call, NamespaceReferMI); } if (_isDynamic) { ilg.Emit(OpCodes.Call, Compiler.Method_Var_setDynamic0); } if (_meta != null) { if (_initProvided || true) //IncludesExplicitMetadata((MapExpr)_meta)) { ilg.Emit(OpCodes.Dup); _meta.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Call, Compiler.Method_Var_setMeta); } } if (_initProvided) { ilg.Emit(OpCodes.Dup); if (_init is FnExpr) ((FnExpr)_init).EmitForDefn(objx, ilg); else _init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Call,Compiler.Method_Var_bindRoot); } if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { List<LocalBuilder> locals = new List<LocalBuilder>(); for (int i = 0; i < _bindingInits.count(); i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); Type primType = Compiler.MaybePrimitiveType(bi.Init); if (primType != null) { LocalBuilder local = ilg.DeclareLocal(primType); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } else { LocalBuilder local = ilg.DeclareLocal(typeof(Object)); locals.Add(local); GenContext.SetLocalName(local, bi.Binding.Name); bi.Binding.LocalVar = local; bi.Init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc, local); } } Label loopLabel = ilg.DefineLabel(); ilg.MarkLabel(loopLabel); try { if (_isLoop) Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel)); if (emitUnboxed) ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg); else _body.Emit(rhc, objx, ilg); } finally { if (_isLoop) Var.popThreadBindings(); } }
//static readonly FieldInfo VectorEmptyFI = typeof(PersistentVector).GetField("EMPTY"); public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_coll is IPersistentList || _coll is LazySeq) // JVM does not include LazySeq test. I'm getting it in some places. LazySeq of 0 size got us here, we'll treat as an empty list ilg.EmitFieldGet(ListEmptyFI); else if (_coll is IPersistentVector) ilg.EmitFieldGet(TupleEmptyFI); else if (_coll is IPersistentMap) ilg.EmitFieldGet(HashMapEmptyFI); else if (_coll is IPersistentSet) ilg.EmitFieldGet(HashSetEmptyFI); else throw new InvalidOperationException("Unknown collection type."); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_coll is IPersistentList) ilg.EmitFieldGet(ListEmptyFI); else if (_coll is IPersistentVector) ilg.EmitFieldGet(VectorEmptyFI); else if (_coll is IPersistentMap) ilg.EmitFieldGet(HashMapEmptyFI); else if (_coll is IPersistentSet) ilg.EmitFieldGet(HashSetEmptyFI); else throw new InvalidOperationException("Unknown collection type."); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { _expr.Emit(RHC.Expression, objx, ilg); // This corresponds to the most general case code in System.Linq.Expressions.Compiler.LambdaCompiler Type opType = _expr.HasClrType && _expr.ClrType != null ? _expr.ClrType : typeof(object); if (opType.IsValueType) { ilg.Emit(OpCodes.Box, opType); } ilg.Emit(OpCodes.Isinst, _t); ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Cgt_Un); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { GenContext.EmitDebugInfo(ilg, _spanMap); if (_ctor != null) EmitForMethod(rhc, objx, ilg); else if (_isNoArgValueTypeCtor) EmitForNoArgValueTypeCtor(rhc, objx, ilg); else { EmitComplexCall(rhc, objx, ilg); if (_type.IsValueType) HostExpr.EmitBoxReturn(objx, ilg, _type); } if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { GenContext.EmitDebugInfo(ilg, _spanMap); Type retType; if (_method != null) { EmitForMethod(objx, ilg); retType = _method.ReturnType; } else { EmitComplexCall(objx, ilg); retType = typeof(object); } HostExpr.EmitBoxReturn(objx, ilg, retType); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { int n = _bindingInits.count(); // Define our locals for (int i = 0; i < n; i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); LocalBuilder local = ilg.DeclareLocal(typeof(IFn)); bi.Binding.LocalVar = local; ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Stloc, local); } // Then initialize IPersistentSet lbset = PersistentHashSet.EMPTY; for (int i = 0; i < n; i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); lbset = (IPersistentSet)lbset.cons(bi.Binding); bi.Init.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stloc,bi.Binding.LocalVar); } for (int i = 0; i < n; i++) { BindingInit bi = (BindingInit)_bindingInits.nth(i); ObjExpr fe = (ObjExpr)bi.Init; ilg.Emit(OpCodes.Ldloc, bi.Binding.LocalVar); fe.EmitLetFnInits(ilg, bi.Binding.LocalVar, objx, lbset); } _body.Emit(rhc, objx, ilg); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_catchExprs.count() == 0 && _finallyExpr == null) { // degenerate case _tryExpr.Emit(rhc, objx, ilg); return; } LocalBuilder retLocal = ilg.DeclareLocal(typeof(Object)); ilg.BeginExceptionBlock(); _tryExpr.Emit(rhc, objx, ilg); if (rhc != RHC.Statement) ilg.Emit(OpCodes.Stloc, retLocal); for (int i = 0; i < _catchExprs.count(); i++) { CatchClause clause = (CatchClause)_catchExprs.nth(i); ilg.BeginCatchBlock(clause.Type); // Exception should be on the stack. Put in clause local clause.Lb.LocalVar = ilg.DeclareLocal(clause.Type); ilg.Emit(OpCodes.Stloc, clause.Lb.LocalVar); clause.Handler.Emit(rhc, objx, ilg); if (clause.Handler.HasNormalExit() && rhc != RHC.Statement) ilg.Emit(OpCodes.Stloc, retLocal); } if (_finallyExpr != null) { ilg.BeginFinallyBlock(); _finallyExpr.Emit(RHC.Statement, objx, ilg); } ilg.EndExceptionBlock(); if (rhc != RHC.Statement) ilg.Emit(OpCodes.Ldloc, retLocal); }
/*** * 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) { //GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false); //GenContext context = Compiler.IsCompiling ? Compiler.CompilerContextVar.get() as GenContext : GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false); //context = GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false); 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; // 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()); 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); }
private void DoEmitPrimOrStatic(ObjExpr fn, TypeBuilder tb, bool isStatic) { MethodAttributes attribs = isStatic ? MethodAttributes.Static | MethodAttributes.Public : MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string methodName = isStatic ? "invokeStatic" : "invokePrim"; Type returnType; if (_retType == typeof(double) || _retType == typeof(long)) { returnType = GetReturnType(); } else { returnType = typeof(object); } MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes); if (!isStatic) { SetCustomAttributes(baseMB); } CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator()); try { Label loopLabel = baseIlg.DefineLabel(); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); GenContext.EmitDebugInfo(baseIlg, SpanMap); baseIlg.MarkLabel(loopLabel); EmitBody(Objx, baseIlg, _retType, _body); if (_body.HasNormalExit()) { baseIlg.Emit(OpCodes.Ret); } } finally { Var.popThreadBindings(); } // Generate the regular invoke, calling the static or prim method MethodBuilder regularMB = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), GetArgTypes()); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); if (!isStatic) { regIlg.Emit(OpCodes.Ldarg_0); } for (int i = 0; i < _argTypes.Length; i++) { regIlg.EmitLoadArg(i + 1); HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]); } regIlg.Emit(OpCodes.Call, baseMB); if (GetReturnType().IsValueType) { regIlg.Emit(OpCodes.Box, GetReturnType()); } regIlg.Emit(OpCodes.Ret); }
internal void EmitForDefn(ObjExpr objx, CljILGen ilg) { Emit(RHC.Expression, objx, ilg); }
void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed) { Label nullLabel = ilg.DefineLabel(); Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Label trueLabel = ilg.DefineLabel(); GenContext.EmitDebugInfo(ilg, _sourceSpan); StaticMethodExpr sme = _testExpr as StaticMethodExpr; if (sme != null && sme.CanEmitIntrinsicPredicate()) { sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel); } else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool)) { ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Brfalse, falseLabel); } else { LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(tempLoc, "test"); _testExpr.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Stloc, tempLoc); ilg.Emit(OpCodes.Brfalse, nullLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Isinst, typeof(bool)); ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Cgt_Un); ilg.Emit(OpCodes.Brfalse, trueLabel); ilg.Emit(OpCodes.Ldloc, tempLoc); ilg.Emit(OpCodes.Unbox_Any, typeof(bool)); ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Ceq); ilg.Emit(OpCodes.Brtrue, falseLabel); } ilg.MarkLabel(trueLabel); if (emitUnboxed) { ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg); } else { _thenExpr.Emit(rhc, objx, ilg); } if (_thenExpr.HasNormalExit()) { ilg.Emit(OpCodes.Br, endLabel); } ilg.MarkLabel(nullLabel); ilg.MarkLabel(falseLabel); if (emitUnboxed) { ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg); } else { _elseExpr.Emit(rhc, objx, ilg); } ilg.MarkLabel(endLabel); }
protected abstract void EmitSet(CljILGen ilg);
protected override void EmitTargetExpression(ObjExpr objx, CljILGen ilg) { ilg.Emit(OpCodes.Ldtoken, _type); ilg.Emit(OpCodes.Call, Compiler.Method_Type_GetTypeFromHandle); }
protected static void EmitHasArityMethod(TypeBuilder tb, IList<int> arities, bool isVariadic, int reqArity) { // TODO: Convert to a Switch instruction MethodBuilder mb = tb.DefineMethod( "HasArity", MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(bool), new Type[] { typeof(int) }); CljILGen gen = new CljILGen(mb.GetILGenerator()); Label falseLabel = gen.DefineLabel(); Label trueLabel = gen.DefineLabel(); if (isVariadic) { gen.EmitLoadArg(1); gen.EmitInt(reqArity); gen.Emit(OpCodes.Bge, trueLabel); } if (arities != null) { foreach (int i in arities) { gen.EmitLoadArg(1); gen.EmitInt(i); gen.Emit(OpCodes.Beq, trueLabel); } } gen.MarkLabel(falseLabel); gen.EmitBoolean(false); gen.Emit(OpCodes.Ret); gen.MarkLabel(trueLabel); gen.EmitBoolean(true); gen.Emit(OpCodes.Ret); }
static void EmitPrimitive(CljILGen ilg, object val) { switch (Type.GetTypeCode(val.GetType()) ) { case TypeCode.Boolean: ilg.EmitBoolean((bool)val); break; case TypeCode.Byte: ilg.EmitByte((byte)val); break; case TypeCode.Char: ilg.EmitChar((char)val); break; case TypeCode.Decimal: ilg.EmitDecimal((decimal)val); break; case TypeCode.Double: ilg.EmitDouble((double)val); break; case TypeCode.Int16: ilg.EmitShort((short)val); break; case TypeCode.Int32: ilg.EmitInt((int)val); break; case TypeCode.Int64: ilg.EmitLong((long)val); break; case TypeCode.SByte: ilg.EmitSByte((sbyte)val); break; case TypeCode.Single: ilg.EmitSingle((float)val); break; case TypeCode.UInt16: ilg.EmitUShort((ushort)val); break; case TypeCode.UInt32: ilg.EmitUInt((uint)val); break; case TypeCode.UInt64: ilg.EmitULong((ulong)val); break; default: throw new InvalidOperationException("Unknown constant type in EmitPrimitive"); } }
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 EmitVar(CljILGen ilg, Var var) { int i = (int)Vars.valAt(var); EmitConstant(ilg, i, var); }
static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, List <ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda) { Expression call = dyn; GenContext context = Compiler.CompilerContextVar.deref() as GenContext; if (context != null && context.DynInitHelper != null) { call = context.DynInitHelper.ReduceDyn(dyn); } if (returnType == typeof(void)) { call = Expression.Block(call, Expression.Default(typeof(object))); returnType = typeof(object); } else if (returnType != call.Type) { call = Expression.Convert(call, returnType); } call = GenContext.AddDebugInfo(call, spanMap); delType = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes); lambda = Expression.Lambda(delType, call, paramExprs); mbLambda = null; if (context == null) { // light compile Delegate d = lambda.Compile(); int key = RT.nextID(); CacheDelegate(key, d); ilg.EmitInt(key); ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate); ilg.Emit(OpCodes.Castclass, delType); } else { mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes); lambda.CompileToMethod(mbLambda); } }
private void EmitComplexCall(ObjExpr objx, CljILGen ilg) { // This is made more complex than I'd like by light-compiling. // Without light-compile, we could just: // Emit the target expression // Emit the arguments (and build up the parameter list for the lambda) // Create the lambda, compile to a methodbuilder, and call it. // Light-compile forces us to // create a lambda at the beginning because we must // compile it to a delegate, to get the type // write code to grab the delegate from a cache // Then emit the target expression // emit the arguments (but note we need already to have built the parameter list) // Call the delegate // Combined, this becomes // Build the parameter list // Build the dynamic call and lambda (slightly different for light-compile vs full) // if light-compile // build the delegate // cache it // emit code to retrieve and cast it // emit the target expression // emit the args // emit the call (slightly different for light compile vs full) // // Build the parameter list List <ParameterExpression> paramExprs = new List <ParameterExpression>(_args.Count + 1); List <Type> paramTypes = new List <Type>(_args.Count + 1); Type targetType = GetTargetType(); if (!targetType.IsPrimitive) { targetType = typeof(object); } paramExprs.Add(Expression.Parameter(targetType)); paramTypes.Add(targetType); int i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: { Type byRefType = argType.MakeByRefType(); paramExprs.Add(Expression.Parameter(byRefType, ha.LocalBinding.Name)); paramTypes.Add(byRefType); break; } case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr) { paramExprs.Add(Expression.Parameter(argType, ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(argType); } else { paramExprs.Add(Expression.Parameter(typeof(object), ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(typeof(object)); } break; default: throw Util.UnreachableCode(); } } // Build dynamic call and lambda Type returnType = HasClrType ? ClrType : typeof(object); InvokeMemberBinder binder = new ClojureInvokeMemberBinder(ClojureContext.Default, _methodName, paramExprs.Count, IsStaticCall); // This is what I want to do. //DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramExprs); // Unfortunately, the Expression.Dynamic method does not respect byRef parameters. // The workaround appears to be to roll your delegate type and then use Expression.MakeDynamic, as below. List <Type> callsiteParamTypes = new List <Type>(paramTypes.Count + 1); callsiteParamTypes.Add(typeof(System.Runtime.CompilerServices.CallSite)); callsiteParamTypes.AddRange(paramTypes); Type dynType = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, callsiteParamTypes.ToArray()); #if CLR2 // Not covariant. Sigh. List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count); paramsAsExprs.AddRange(paramExprs.ToArray()); DynamicExpression dyn = Expression.MakeDynamic(dynType, binder, paramsAsExprs); #else DynamicExpression dyn = Expression.MakeDynamic(dynType, binder, paramExprs); #endif LambdaExpression lambda; Type delType; MethodBuilder mbLambda; EmitDynamicCallPreamble(dyn, _spanMap, "__interop_" + _methodName + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda); // Emit target + args EmitTargetExpression(objx, ilg); i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: EmitByRefArg(ha, objx, ilg); break; case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr) { ((MaybePrimitiveExpr)ha.ArgExpr).EmitUnboxed(RHC.Expression, objx, ilg); } else { ha.ArgExpr.Emit(RHC.Expression, objx, ilg); } break; default: throw Util.UnreachableCode(); } } EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg); }
protected abstract void EmitTargetExpression(ObjExpr objx, CljILGen ilg);
internal static void EmitUnboxArg(CljILGen ilg, Type paramType) { if (paramType.IsPrimitive) { MethodInfo m = null; if (paramType == typeof(bool)) { m = HostExpr.Method_RT_booleanCast; } else if (paramType == typeof(char)) { m = HostExpr.Method_RT_charCast; } else if (paramType == typeof(IntPtr)) { m = HostExpr.Method_RT_intPtrCast; } else if (paramType == typeof(UIntPtr)) { m = HostExpr.Method_RT_uintPtrCast; } else { var typeCode = Type.GetTypeCode(paramType); if (RT.booleanCast(RT.UncheckedMathVar.deref())) { switch (typeCode) { case TypeCode.SByte: m = HostExpr.Method_RT_uncheckedSbyteCast; break; case TypeCode.Byte: m = HostExpr.Method_RT_uncheckedByteCast; break; case TypeCode.Int16: m = HostExpr.Method_RT_uncheckedShortCast; break; case TypeCode.UInt16: m = HostExpr.Method_RT_uncheckedUshortCast; break; case TypeCode.Int32: m = HostExpr.Method_RT_uncheckedIntCast; break; case TypeCode.UInt32: m = HostExpr.Method_RT_uncheckedUintCast; break; case TypeCode.Int64: m = HostExpr.Method_RT_uncheckedLongCast; break; case TypeCode.UInt64: m = HostExpr.Method_RT_uncheckedUlongCast; break; case TypeCode.Single: m = HostExpr.Method_RT_uncheckedFloatCast; break; case TypeCode.Double: m = HostExpr.Method_RT_uncheckedDoubleCast; break; case TypeCode.Char: m = HostExpr.Method_RT_uncheckedCharCast; break; case TypeCode.Decimal: m = HostExpr.Method_RT_uncheckedDecimalCast; break; default: throw new ArgumentOutOfRangeException("paramType", paramType, string.Format("Don't know how to handle typeCode {0} for paramType", typeCode)); } } else { switch (typeCode) { case TypeCode.SByte: m = HostExpr.Method_RT_sbyteCast; break; case TypeCode.Byte: m = HostExpr.Method_RT_byteCast; break; case TypeCode.Int16: m = HostExpr.Method_RT_shortCast; break; case TypeCode.UInt16: m = HostExpr.Method_RT_ushortCast; break; case TypeCode.Int32: m = HostExpr.Method_RT_intCast; break; case TypeCode.UInt32: m = HostExpr.Method_RT_uintCast; break; case TypeCode.Int64: m = HostExpr.Method_RT_longCast; break; case TypeCode.UInt64: m = HostExpr.Method_RT_ulongCast; break; case TypeCode.Single: m = HostExpr.Method_RT_floatCast; break; case TypeCode.Double: m = HostExpr.Method_RT_doubleCast; break; case TypeCode.Char: m = HostExpr.Method_RT_charCast; break; case TypeCode.Decimal: m = HostExpr.Method_RT_decimalCast; break; default: throw new ArgumentOutOfRangeException("paramType", paramType, string.Format("Don't know how to handle typeCode {0} for paramType", typeCode)); } } } ilg.Emit(OpCodes.Castclass, typeof(Object)); ilg.Emit(OpCodes.Call, m); } else { // TODO: Properly handle value types here. Really, we need to know the incoming type. if (paramType.IsValueType) { ilg.Emit(OpCodes.Unbox_Any, paramType); } else { ilg.Emit(OpCodes.Castclass, paramType); } } }
public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { DoEmit(rhc, objx, ilg, true); }
internal static void EmitUnboxArg(ObjExpr objx, CljILGen ilg, Type paramType) { EmitUnboxArg(ilg, paramType); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { DoEmit(rhc, objx, ilg, false); }
protected override void EmitSet(CljILGen ilg) { ilg.EmitPropertySet(_tinfo); }
protected override void EmitTargetExpression(ObjExpr objx, CljILGen ilg) { _target.Emit(RHC.Expression, objx, ilg); }
protected override void EmitSet(CljILGen ilg) { ilg.EmitFieldSet(_tinfo); }
private void EmitGetCompiledConstants(CljILGen ilg) { ilg.EmitInt(DynMethodMapKey); ilg.Emit(OpCodes.Call, Method_FnExpr_GetCompiledConstants); }
protected override void EmitSet(CljILGen ilg) { ilg.MaybeEmitVolatileOp(_tinfo); ilg.EmitFieldSet(_tinfo); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { _target.Emit(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_Monitor_Exit); Compiler.NilExprInstance.Emit(rhc, objx, ilg); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Label?loopLabel = (Label)Compiler.LoopLabelVar.deref(); if (loopLabel == null) { throw new InvalidOperationException("Recur not in proper context."); } { for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(long) && pt == typeof(int)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(double) && pt == typeof(float)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(int) && pt == typeof(long)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); //ilg.EmitCall(Compiler.Method_RT_intCast_long); ilg.Emit(OpCodes.Conv_I4); } else if (primt == typeof(float) && pt == typeof(double)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { throw new ArgumentException(String.Format( "{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", _source, _spanMap != null ? (int)_spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name)); } } else { arg.Emit(RHC.Expression, objx, ilg); } } } for (int i = _loopLocals.count() - 1; i >= 0; i--) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); //Type primt = lb.PrimitiveType; if (lb.IsArg) { //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1)); if (lb.DeclaredType != typeof(Object) && !lb.DeclaredType.IsPrimitive) { ilg.Emit(OpCodes.Castclass, lb.DeclaredType); } ilg.EmitStoreArg(lb.Index); } else { ilg.Emit(OpCodes.Stloc, lb.LocalVar); } } ilg.Emit(OpCodes.Br, loopLabel.Value); }
protected override void EmitStatics(TypeBuilder tb) { if (IsDefType) { // getBasis() { MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes); CljILGen ilg = new CljILGen(mbg.GetILGenerator()); EmitValue(_hintedFields, ilg); ilg.Emit(OpCodes.Ret); } if (Fields.count() > _hintedFields.count()) { // create(IPersistentMap) MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) }); CljILGen gen = new CljILGen(mbc.GetILGenerator()); LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword)); List <LocalBuilder> locals = new List <LocalBuilder>(); for (ISeq s = RT.seq(_hintedFields); s != null; s = s.next()) { string bName = ((Symbol)s.first()).Name; Type t = Compiler.TagType(Compiler.TagOf(s.first())); // local_kw = Keyword.intern(bname) // local_i = arg_0.valAt(kw,null) gen.EmitLoadArg(0); gen.EmitString(bName); gen.EmitCall(Compiler.Method_Keyword_intern_string); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex); gen.EmitNull(); gen.EmitCall(Compiler.Method_IPersistentMap_valAt2); LocalBuilder lb = gen.DeclareLocal(t); locals.Add(lb); if (t.IsPrimitive) { gen.EmitUnbox(t); } gen.Emit(OpCodes.Stloc, lb.LocalIndex); // arg_0 = arg_0.without(local_kw); gen.EmitLoadArg(0); gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex); gen.EmitCall(Compiler.Method_IPersistentMap_without); gen.EmitStoreArg(0); } foreach (LocalBuilder lb in locals) { gen.Emit(OpCodes.Ldloc, lb.LocalIndex); } gen.EmitNull(); gen.EmitLoadArg(0); gen.EmitCall(Compiler.Method_RT_seqOrElse); gen.EmitNew(_ctorInfo); gen.Emit(OpCodes.Ret); } } }
static public void EmitDynamicCallPostlude(LambdaExpression lambda, Type delType, MethodBuilder mbLambda, CljILGen ilg) { GenContext context = Compiler.CompilerContextVar.deref() as GenContext; if (context == null) { // light compile MethodInfo mi = delType.GetMethod("Invoke"); ilg.Emit(OpCodes.Callvirt, mi); } else { ilg.Emit(OpCodes.Call, mbLambda); } }
public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { objx.EmitUnboxedLocal(ilg, _b); }
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); }
public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { GenContext.EmitDebugInfo(ilg, _spanMap); ilg.EmitPropertyGet(_tinfo); }
internal void EmitVarValue(CljILGen ilg, Var v) { int i = (int)Vars.valAt(v); if ( !v.isDynamic() ) { EmitConstant(ilg, i, v); ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); } else { EmitConstant(ilg, i, v); ilg.Emit(OpCodes.Call, Compiler.Method_Var_get); // or just Method_Var_get?? } }
public abstract void Emit(RHC rhc, ObjExpr objx, CljILGen ilg);
protected void EmitValue(object value, CljILGen ilg) { bool partial = true; if (value == null) ilg.Emit(OpCodes.Ldnull); else if (value is String) ilg.Emit(OpCodes.Ldstr, (String)value); else if (value is Boolean) { ilg.EmitBoolean((Boolean)value); ilg.Emit(OpCodes.Box,typeof(bool)); } else if (value is Int32) { ilg.EmitInt((int)value); ilg.Emit(OpCodes.Box, typeof(int)); } else if (value is Int64) { ilg.EmitLong((long)value); ilg.Emit(OpCodes.Box, typeof(long)); } else if (value is Double) { ilg.EmitDouble((double)value); ilg.Emit(OpCodes.Box, typeof(double)); } else if (value is Char) { ilg.EmitChar((char)value); ilg.Emit(OpCodes.Box,typeof(char)); } else if (value is Type) { Type t = (Type)value; if (t.IsValueType) ilg.EmitType(t); else { //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName)); ilg.EmitString(((Type)value).FullName); ilg.EmitCall(Compiler.Method_RT_classForName); } } else if (value is Symbol) { Symbol sym = (Symbol)value; if (sym.Namespace == null) ilg.EmitNull(); else ilg.EmitString(sym.Namespace); ilg.EmitString(sym.Name); ilg.EmitCall(Compiler.Method_Symbol_intern2); } else if (value is Keyword) { Keyword keyword = (Keyword)value; if (keyword.Namespace == null) ilg.EmitNull(); else ilg.EmitString(keyword.Namespace); ilg.EmitString(keyword.Name); ilg.EmitCall(Compiler.Method_RT_keyword); } else if (value is Var) { Var var = (Var)value; ilg.EmitString(var.Namespace.Name.ToString()); ilg.EmitString(var.Symbol.Name.ToString()); ilg.EmitCall(Compiler.Method_RT_var2); } else if (value is IType) { IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes); for (ISeq s = RT.seq(fields); s != null; s = s.next()) { Symbol field = (Symbol)s.first(); Type k = Compiler.TagType(Compiler.TagOf(field)); object val = Reflector.GetInstanceFieldOrProperty(value, field.Name); EmitValue(val, ilg); if (k.IsPrimitive) { ilg.Emit(OpCodes.Castclass, k); } } ConstructorInfo cinfo = value.GetType().GetConstructors()[0]; ilg.EmitNew(cinfo); } else if (value is IRecord) { //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); EmitValue(PersistentArrayMap.create((IDictionary)value), ilg); MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null); ilg.EmitCall(createMI); } else if (value is IPersistentMap) { IPersistentMap map = (IPersistentMap)value; List<object> entries = new List<object>(map.count() * 2); foreach (IMapEntry entry in map) { entries.Add(entry.key()); entries.Add(entry.val()); } EmitListAsObjectArray(entries, ilg); ilg.EmitCall(Compiler.Method_RT_map); } else if (value is IPersistentVector) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_RT_vector); } else if (value is PersistentHashSet) { ISeq vs = RT.seq(value); if (vs == null) ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY); else { EmitListAsObjectArray(vs, ilg); ilg.EmitCall(Compiler.Method_PersistentHashSet_create); } } else if (value is ISeq || value is IPersistentList) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_PersistentList_create); } else if (value is Regex) { ilg.EmitString(((Regex)value).ToString()); ilg.EmitNew(Compiler.Ctor_Regex_1); } else { string cs = null; try { cs = RT.printString(value); } catch (Exception) { throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value)); } if (cs.Length == 0) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value)); if (cs.StartsWith("#<")) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs)); ilg.EmitString(cs); ilg.EmitCall(Compiler.Method_RT_readString); partial = false; } if (partial) { if (value is IObj && RT.count(((IObj)value).meta()) > 0) { ilg.Emit(OpCodes.Castclass, typeof(IObj)); Object m = ((IObj)value).meta(); EmitValue(Compiler.ElideMeta(m), ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta); } } }
private void EmitConstantFieldInits(CljILGen ilg) { try { Var.pushThreadBindings(RT.map(RT.PrintDupVar, true)); for (int i = 0; i < Constants.count(); i++) { if (ConstantFields[i] != null) { EmitValue(Constants.nth(i), ilg); if ( Constants.nth(i).GetType() != ConstantType(i) ) ilg.Emit(OpCodes.Castclass, ConstantType(i)); FieldBuilder fb = ConstantFields[i]; ilg.Emit(OpCodes.Stsfld,fb); } } } finally { Var.popThreadBindings(); } }
internal void EmitKeyword(CljILGen ilg, Keyword kw) { int i = (int)Keywords.valAt(kw); EmitConstant(ilg, i, kw); }
protected void EmitValue(object value, CljILGen ilg) { bool partial = true; if (value == null) { ilg.Emit(OpCodes.Ldnull); } else if (value is String) { ilg.Emit(OpCodes.Ldstr, (String)value); } else if (value is Boolean) { ilg.EmitBoolean((Boolean)value); ilg.Emit(OpCodes.Box, typeof(bool)); } else if (value is Int32) { ilg.EmitInt((int)value); ilg.Emit(OpCodes.Box, typeof(int)); } else if (value is Int64) { ilg.EmitLong((long)value); ilg.Emit(OpCodes.Box, typeof(long)); } else if (value is Double) { ilg.EmitDouble((double)value); ilg.Emit(OpCodes.Box, typeof(double)); } else if (value is Char) { ilg.EmitChar((char)value); ilg.Emit(OpCodes.Box, typeof(char)); } else if (value is Type) { Type t = (Type)value; if (t.IsValueType) { ilg.EmitType(t); } else { //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName)); ilg.EmitString(((Type)value).FullName); ilg.EmitCall(Compiler.Method_RT_classForName); } } else if (value is Symbol) { Symbol sym = (Symbol)value; if (sym.Namespace == null) { ilg.EmitNull(); } else { ilg.EmitString(sym.Namespace); } ilg.EmitString(sym.Name); ilg.EmitCall(Compiler.Method_Symbol_intern2); } else if (value is Keyword) { Keyword keyword = (Keyword)value; if (keyword.Namespace == null) { ilg.EmitNull(); } else { ilg.EmitString(keyword.Namespace); } ilg.EmitString(keyword.Name); ilg.EmitCall(Compiler.Method_RT_keyword); } else if (value is Var) { Var var = (Var)value; ilg.EmitString(var.Namespace.Name.ToString()); ilg.EmitString(var.Symbol.Name.ToString()); ilg.EmitCall(Compiler.Method_RT_var2); } else if (value is IType) { IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes); for (ISeq s = RT.seq(fields); s != null; s = s.next()) { Symbol field = (Symbol)s.first(); Type k = Compiler.TagType(Compiler.TagOf(field)); object val = Reflector.GetInstanceFieldOrProperty(value, field.Name); EmitValue(val, ilg); if (k.IsPrimitive) { ilg.Emit(OpCodes.Castclass, k); } } ConstructorInfo cinfo = value.GetType().GetConstructors()[0]; ilg.EmitNew(cinfo); } else if (value is IRecord) { //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); EmitValue(PersistentArrayMap.create((IDictionary)value), ilg); MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null); ilg.EmitCall(createMI); } else if (value is IPersistentMap) { IPersistentMap map = (IPersistentMap)value; List <object> entries = new List <object>(map.count() * 2); foreach (IMapEntry entry in map) { entries.Add(entry.key()); entries.Add(entry.val()); } EmitListAsObjectArray(entries, ilg); ilg.EmitCall(Compiler.Method_RT_map); } else if (value is IPersistentVector) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_RT_vector); } else if (value is PersistentHashSet) { ISeq vs = RT.seq(value); if (vs == null) { ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY); } else { EmitListAsObjectArray(vs, ilg); ilg.EmitCall(Compiler.Method_PersistentHashSet_create); } } else if (value is ISeq || value is IPersistentList) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_PersistentList_create); } else if (value is Regex) { ilg.EmitString(((Regex)value).ToString()); ilg.EmitNew(Compiler.Ctor_Regex_1); } else { string cs = null; try { cs = RT.printString(value); } catch (Exception) { throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value)); } if (cs.Length == 0) { throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value)); } if (cs.StartsWith("#<")) { throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs)); } ilg.EmitString(cs); ilg.EmitCall(Compiler.Method_RT_readString); partial = false; } if (partial) { if (value is IObj && RT.count(((IObj)value).meta()) > 0) { ilg.Emit(OpCodes.Castclass, typeof(IObj)); Object m = ((IObj)value).meta(); EmitValue(Compiler.ElideMeta(m), ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta); } } }
private void EmitParamsForMethod(ObjExpr objx, CljILGen ilg) { ParameterInfo[] pis = _ctor.GetParameters(); MethodExpr.EmitTypedArgs(objx, ilg, pis, _args); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { objx.EmitVar(ilg, _var); if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
private void EmitComplexCall(RHC rhc, ObjExpr objx, CljILGen ilg) { // See the notes on MethodExpr.EmitComplexCall on why this is so complicated List <ParameterExpression> paramExprs = new List <ParameterExpression>(_args.Count + 1); List <Type> paramTypes = new List <Type>(_args.Count + 1); paramExprs.Add(Expression.Parameter(typeof(Type))); paramTypes.Add(typeof(Type)); int i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: { Type byRefType = argType.MakeByRefType(); paramExprs.Add(Expression.Parameter(byRefType, ha.LocalBinding.Name)); paramTypes.Add(byRefType); break; } case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr) { paramExprs.Add(Expression.Parameter(argType, ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(argType); } else { paramExprs.Add(Expression.Parameter(typeof(object), ha.LocalBinding != null ? ha.LocalBinding.Name : "__temp_" + i)); paramTypes.Add(typeof(object)); } break; default: throw Util.UnreachableCode(); } } // Build dynamic call and lambda Type returnType = HasClrType ? ClrType : typeof(object); CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count); DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramExprs); MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_ctor_" + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda); // Emit target + args EmitTargetExpression(objx, ilg); i = 0; foreach (HostArg ha in _args) { i++; Expr e = ha.ArgExpr; Type argType = e.HasClrType && e.ClrType != null && e.ClrType.IsPrimitive ? e.ClrType : typeof(object); switch (ha.ParamType) { case HostArg.ParameterType.ByRef: MethodExpr.EmitByRefArg(ha, objx, ilg); break; case HostArg.ParameterType.Standard: if (argType.IsPrimitive && ha.ArgExpr is MaybePrimitiveExpr expr) { expr.EmitUnboxed(RHC.Expression, objx, ilg); } else { ha.ArgExpr.Emit(RHC.Expression, objx, ilg); } break; default: throw Util.UnreachableCode(); } } MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Label loopLabel = (Label)Compiler.LoopLabelVar.deref(); if (loopLabel == null) throw new InvalidOperationException("Recur not in proper context."); { for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(long) && pt == typeof(int)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(double) && pt == typeof(float)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(int) && pt == typeof(long)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_RT_intCast_long); } else if (primt == typeof(float) && pt == typeof(double)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { throw new ArgumentException(String.Format( "{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", _source, _spanMap != null ? (int)_spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name)); } } else { arg.Emit(RHC.Expression, objx, ilg); } } } for (int i = _loopLocals.count() - 1; i >= 0; i--) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Type primt = lb.PrimitiveType; if (lb.IsArg) //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1)); ilg.EmitStoreArg(lb.Index); else { ilg.Emit(OpCodes.Stloc, lb.LocalVar); } } ilg.Emit(OpCodes.Br, loopLabel); //if (rhc != RHC.Statement) // ilg.Emit(OpCodes.Ldnull); }
private void EmitGetDynMethod(int arity, CljILGen ilg) { ilg.EmitInt(DynMethodMapKey); ilg.EmitInt(arity); ilg.Emit(OpCodes.Call, Method_FnExpr_GetDynMethod); }