public static void EmitTypedArgs(ObjExpr objx, CljILGen ilg, ParameterInfo[] parms, List <HostArg> args) { for (int i = 0; i < parms.Length; i++) { HostArg ha = args[i]; ParameterInfo pi = parms[i]; bool argIsByRef = ha.ParamType == HostArg.ParameterType.ByRef; bool paramIsByRef = pi.ParameterType.IsByRef; if (!paramIsByRef) { EmitTypedArg(objx, ilg, pi.ParameterType, ha.ArgExpr); } else // paramIsByRef { if (argIsByRef) { EmitByRefArg(ha, objx, ilg); } else { EmitTypedArg(objx, ilg, parms[i].ParameterType, args[i].ArgExpr); LocalBuilder loc = ilg.DeclareLocal(pi.ParameterType); loc.SetLocalSymInfo("_byRef_temp" + i); ilg.Emit(OpCodes.Stloc, loc); ilg.Emit(OpCodes.Ldloca, loc); } } } }
public static void EmitByRefArg(HostArg ha, ObjExpr objx, CljILGen ilg) { if (ha.LocalBinding.IsArg) { ilg.Emit(OpCodes.Ldarga, ha.LocalBinding.Index); } else if (ha.LocalBinding.IsThis) { ilg.Emit(OpCodes.Ldarga, 0); } else { ilg.Emit(OpCodes.Ldloca, ha.LocalBinding.LocalVar); } }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LoopSym); IPersistentVector bindings = RT.second(form) as IPersistentVector; if (bindings == null) throw new ParseException("Bad binding form, expected vector"); if ((bindings.count() % 2) != 0) throw new ParseException("Bad binding form, expected matched symbol/value pairs."); ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID()); ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = PersistentVector.EMPTY; for (int i = 0; i < bindings.count() / 2; i++) { recurMismatches = recurMismatches.cons(false); } // may repeat once for each binding with a mismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); method.Locals = backupMethodLocals; method.IndexLocals = backupMethodIndexLocals; if (isLoop) dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null); try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) throw new ParseException("Can't let qualified name: " + sym); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); if (isLoop) { if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2)) ) { HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); List<HostArg> has = new List<HostArg>(1); has.Add(ha); init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false); if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); } else if (Compiler.MaybePrimitiveType(init) == typeof(int)) { List<HostArg> args = new List<HostArg>(); args.Add(new HostArg(HostArg.ParameterType.Standard, init, null)); init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false); } else if (Compiler.MaybePrimitiveType(init) == typeof(float)) { List<HostArg> args = new List<HostArg>(); args.Add(new HostArg(HostArg.ParameterType.Standard, init, null)); init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false); } } // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) loopLocals = loopLocals.cons(b); } if (isLoop) Compiler.LoopLocalsVar.set(loopLocals); Expr bodyExpr; bool moreMismatches = false; try { if (isLoop) { // stuff with clear paths, Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null)); } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { Var.popThreadBindings(); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMismatch) { recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true); moreMismatches = true; } } } } if (!moreMismatches) return new LetExpr(bindingInits, bodyExpr, isLoop); } finally { Var.popThreadBindings(); } } }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LoopSym); if (!(RT.second(form) is IPersistentVector bindings)) { throw new ParseException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ParseException("Bad binding form, expected matched symbol/value pairs."); } ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID())); } ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = PersistentVector.EMPTY; for (int i = 0; i < bindings.count() / 2; i++) { recurMismatches = recurMismatches.cons(false); } // may repeat once for each binding with a mismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); method.SetLocals(backupMethodLocals, backupMethodIndexLocals); if (isLoop) { dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null); } try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) { throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new ParseException("Can't let qualified name: " + sym); } Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); if (isLoop) { if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2))) { HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); List <HostArg> has = new List <HostArg>(1) { ha }; init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false); if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) { RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); } } else if (Compiler.MaybePrimitiveType(init) == typeof(int)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false); } else if (Compiler.MaybePrimitiveType(init) == typeof(float)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false); } } // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, typeof(Object), false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) { loopLocals = loopLocals.cons(b); } } if (isLoop) { Compiler.LoopLocalsVar.set(loopLocals); } Expr bodyExpr; bool moreMismatches = false; try { if (isLoop) { object methodReturnContext = pcon.Rhc == RHC.Return ? Compiler.MethodReturnContextVar.deref() : null; // stuff with clear paths, Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null, Compiler.MethodReturnContextVar, methodReturnContext)); } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { Var.popThreadBindings(); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMismatch) { recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true); moreMismatches = true; } } } } if (!moreMismatches) { return(new LetExpr(bindingInits, bodyExpr, isLoop)); } } finally { Var.popThreadBindings(); } } }
public static void EmitByRefArg(HostArg ha, ObjExpr objx, CljILGen ilg) { if (ha.LocalBinding.IsArg) ilg.Emit(OpCodes.Ldarga, ha.LocalBinding.Index); else if (ha.LocalBinding.IsThis) ilg.Emit(OpCodes.Ldarga, 0); else ilg.Emit(OpCodes.Ldloca, ha.LocalBinding.LocalVar); }
protected Expression GenDlrForMethod(ObjExpr objx, GenContext context) { if (_method.DeclaringType == (Type)Compiler.CompileStubOrigClassVar.deref()) { _method = FindEquivalentMethod(_method, objx.BaseType); } int argCount = _args.Count; IList <DynamicMetaObject> argsPlus = new List <DynamicMetaObject>(argCount + (IsStaticCall ? 0 : 1)); if (!IsStaticCall) { argsPlus.Add(new DynamicMetaObject(Expression.Convert(GenTargetExpression(objx, context), _method.DeclaringType), BindingRestrictions.Empty)); } List <int> refPositions = new List <int>(); ParameterInfo[] methodParms = _method.GetParameters(); for (int i = 0; i < argCount; i++) { HostArg ha = _args[i]; Expr e = ha.ArgExpr; Type argType = e.HasClrType ? (e.ClrType ?? typeof(object)) : typeof(Object); //Type t; switch (ha.ParamType) { case HostArg.ParameterType.ByRef: refPositions.Add(i); argsPlus.Add(new DynamicMetaObject(HostExpr.GenUnboxArg(GenTypedArg(objx, context, argType, e), methodParms[i].ParameterType.GetElementType()), BindingRestrictions.Empty)); break; case HostArg.ParameterType.Standard: Type ptype = methodParms[i].ParameterType; if (ptype.IsGenericParameter) { ptype = argType; } Expression typedArg = GenTypedArg(objx, context, ptype, e); argsPlus.Add(new DynamicMetaObject(typedArg, BindingRestrictions.Empty)); break; default: throw Util.UnreachableCode(); } } // TODO: get rid of use of Default OverloadResolverFactory factory = ClojureContext.Default.SharedOverloadResolverFactory; DefaultOverloadResolver res = factory.CreateOverloadResolver(argsPlus, new CallSignature(argCount), IsStaticCall ? CallTypes.None : CallTypes.ImplicitInstance); List <MethodBase> methods = new List <MethodBase>(); methods.Add(_method); BindingTarget bt = res.ResolveOverload(_methodName, methods, NarrowingLevel.None, NarrowingLevel.All); if (!bt.Success) { throw new ArgumentException("Conflict in argument matching. -- Internal error."); } Expression call = bt.MakeExpression(); if (refPositions.Count > 0) { ParameterExpression resultParm = Expression.Parameter(typeof(Object[])); List <Expression> stmts = new List <Expression>(refPositions.Count + 2); stmts.Add(Expression.Assign(resultParm, call)); // TODO: Fold this into the loop above foreach (int i in refPositions) { HostArg ha = _args[i]; Expr e = ha.ArgExpr; Type argType = e.HasClrType ? (e.ClrType ?? typeof(object)) : typeof(Object); stmts.Add(Expression.Assign(_args[i].LocalBinding.ParamExpression, Expression.Convert(Expression.ArrayIndex(resultParm, Expression.Constant(i + 1)), argType))); } Type returnType = HasClrType ? ClrType : typeof(object); stmts.Add(Expression.Convert(Expression.ArrayIndex(resultParm, Expression.Constant(0)), returnType)); call = Expression.Block(new ParameterExpression[] { resultParm }, stmts); } call = _arithmeticRewriter.Visit(call); return(call); }