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); } }
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 void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg) { if (_variadic) { ParameterInfo[] pinfos = _method.GetParameters(); for (int i = 0; i < pinfos.Length - 1; i++) { Expr e = (Expr)_args.nth(i); if (Compiler.MaybePrimitiveType(e) == pinfos[i].ParameterType) { ((MaybePrimitiveExpr)e).EmitUnboxed(RHC.Expression, objx, ilg); } else { e.Emit(RHC.Expression, objx, ilg); HostExpr.EmitUnboxArg(objx, ilg, pinfos[i].ParameterType); } } IPersistentVector restArgs = RT.subvec(_args, pinfos.Length - 1, _args.count()); MethodExpr.EmitArgsAsArray(restArgs, objx, ilg); ilg.EmitCall(Compiler.Method_ArraySeq_create); } else { MethodExpr.EmitTypedArgs(objx, ilg, _method.GetParameters(), _args); } ilg.EmitCall(_method); }
public override Expression GenCode(RHC rhc, ObjExpr objx, GenContext context) { Type targetType = _targetType; Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; if (_targetType == stubType) { targetType = objx.BaseType; } Expression target = _target.GenCode(RHC.Expression, objx, context); Expression call; if (targetType != null && _tinfo != null) { Expression convTarget = Expression.Convert(target, targetType); Expression access = GenAccess(rhc, objx, convTarget); call = HostExpr.GenBoxReturn(access, FieldType, objx, context); } else { // TODO: Convert to Dynamic call site call = Expression.Call(Compiler.Method_Reflector_GetInstanceFieldOrProperty, target, Expression.Constant(_fieldName)); } call = Compiler.MaybeAddDebugInfo(call, _spanMap, context.IsDebuggable); return(call); }
public override Expression GenAssign(RHC rhc, ObjExpr objx, GenContext context, Expr val) { Expression target = _target.GenCode(RHC.Expression, objx, context); Expression valExpr = val.GenCode(RHC.Expression, objx, context); Expression call; if (_targetType != null && _tinfo != null) { Expression convTarget = Expression.Convert(target, _targetType); Expression access = GenAccess(rhc, objx, convTarget); Expression unboxValExpr = HostExpr.GenUnboxArg(valExpr, FieldType); //call = Expression.Assign(access, Expression.Convert(valExpr, access.Type)); call = Expression.Assign(access, unboxValExpr); } else { // TODO: Convert to a dynamic call site call = Expression.Call( Compiler.Method_Reflector_SetInstanceFieldOrProperty, target, Expression.Constant(_fieldName), Compiler.MaybeBox(valExpr)); } call = Compiler.MaybeAddDebugInfo(call, _spanMap, context.IsDebuggable); return(call); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); HostExpr.EmitBoxReturn(objx, ilg, FieldType); } else { // We could convert this to a dynamic call-site _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Ldstr, _memberName); ilg.Emit(OpCodes.Call, Compiler.Method_Reflector_GetInstanceFieldOrProperty); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
private static MethodInfo GetMatchingMethodAux(Type targetType, IPersistentVector args, string methodName, bool getStatics) { MethodInfo method = null; List <MethodInfo> methods = HostExpr.GetMethods(targetType, args.count(), methodName, getStatics); if (methods.Count == 0) { method = null; } else { int index = 0; if (methods.Count > 1) { List <ParameterInfo[]> parms = new List <ParameterInfo[]>(methods.Count); List <Type> rets = new List <Type>(methods.Count); foreach (MethodInfo mi in methods) { parms.Add(mi.GetParameters()); rets.Add(mi.ReturnType); } index = GetMatchingParams(methodName, parms, args, rets); } method = (index >= 0 ? methods[index] : null); } return(method); }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Type targetType = _targetType; //Type stubType = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null; //if (_targetType == stubType) // targetType = objx.BaseType; GenContext.EmitDebugInfo(ilg, _spanMap); if (targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); MethodExpr.EmitPrepForCall(ilg, typeof(object), FieldDeclaringType); EmitGet(ilg); HostExpr.EmitBoxReturn(objx, ilg, FieldType); } else { // TODO: convert to dynamic? _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Ldstr, _fieldName); ilg.Emit(OpCodes.Call, Compiler.Method_Reflector_GetInstanceFieldOrProperty); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
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"; MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, GetReturnType(), _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); }
public InvokeExpr(string source, IPersistentMap spanMap, Symbol tag, Expr fexpr, IPersistentVector args, bool tailPosition) { _source = source; _spanMap = spanMap; _fexpr = fexpr; _args = args; _tailPosition = tailPosition; VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null) { Var fvar = varFexpr.Var; Var pvar = (Var)RT.get(fvar.meta(), Compiler.ProtocolKeyword); if (pvar != null && Compiler.ProtocolCallsitesVar.isBound) { _isProtocol = true; _siteIndex = Compiler.RegisterProtocolCallsite(fvar); Object pon = RT.get(pvar.get(), _onKey); _protocolOn = HostExpr.MaybeType(pon, false); if (_protocolOn != null) { IPersistentMap mmap = (IPersistentMap)RT.get(pvar.get(), _methodMapKey); Keyword mmapVal = (Keyword)mmap.valAt(Keyword.intern(fvar.sym)); if (mmapVal == null) { throw new ArgumentException(String.Format("No method of interface: {0} found for function: {1} of protocol: {2} (The protocol method may have been defined before and removed.)", _protocolOn.FullName, fvar.Symbol, pvar.Symbol)); } String mname = Compiler.munge(mmapVal.Symbol.ToString()); IList <MethodBase> methods = Reflector.GetMethods(_protocolOn, mname, null, args.count() - 1, false); if (methods.Count != 1) { throw new ArgumentException(String.Format("No single method: {0} of interface: {1} found for function: {2} of protocol: {3}", mname, _protocolOn.FullName, fvar.Symbol, pvar.Symbol)); } _onMethod = (MethodInfo)methods[0]; } } } if (tag != null) { _tag = tag; } else if (varFexpr != null) { Var v = varFexpr.Var; //object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); object sigTag = SigTag(_args.count(), v); _tag = sigTag ?? varFexpr.Tag; } else { _tag = null; } }
static void EmitUnboxArg(CljILGen ilg, Type argType, Type paramType) { if (argType == paramType) { return; } HostExpr.EmitUnboxArg(ilg, paramType); }
Expression GenDlrForMethod(RHC rhc, ObjExpr objx, GenContext context) { // The ctor is uniquely determined. Expression[] args = HostExpr.GenTypedArgs(objx, context, _ctor.GetParameters(), _args); return(Utils.SimpleNewHelper(_ctor, args)); // JAVA: emitClearLocals }
public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { EmitUnboxed(RHC.Expression, objx, ilg); HostExpr.EmitBoxReturn(objx, ilg, FieldType); 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 override Expression GenAssign(RHC rhc, ObjExpr objx, GenContext context, Expr val) { Expression access = GenCodeUnboxed(RHC.Expression, objx, context); Expression valExpr = val.GenCode(RHC.Expression, objx, context); Expression unboxValExpr = HostExpr.GenUnboxArg(valExpr, FieldType); Expression assign = Expression.Assign(access, unboxValExpr); assign = Compiler.MaybeAddDebugInfo(assign, _spanMap, context.IsDebuggable); return(assign); }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { EmitUnboxed(rhc, objx, ilg); if (rhc != RHC.Statement) { HostExpr.EmitBoxReturn(objx, ilg, _retType); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
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.EmitPropertySet(_tinfo); if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
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 ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]); 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); } } }
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); } }
public static void EmitTypedArg(ObjExpr objx, CljILGen ilg, Type paramType, Expr arg) { Type primt = Compiler.MaybePrimitiveType(arg); MaybePrimitiveExpr mpe = arg as MaybePrimitiveExpr; if (primt == paramType) { mpe.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(int) && paramType == typeof(long)) { mpe.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(long) && paramType == typeof(int)) { mpe.EmitUnboxed(RHC.Expression, objx, ilg); if (RT.booleanCast(RT.UncheckedMathVar.deref())) { ilg.Emit(OpCodes.Call, Compiler.Method_RT_uncheckedIntCast_long); } else { ilg.Emit(OpCodes.Call, Compiler.Method_RT_intCast_long); } } else if (primt == typeof(float) && paramType == typeof(double)) { mpe.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(double) && paramType == typeof(float)) { mpe.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { arg.Emit(RHC.Expression, objx, ilg); HostExpr.EmitUnboxArg(objx, ilg, paramType); } }
public override Expression GenCode(RHC rhc, ObjExpr objx, GenContext context) { Expression call; Type retType; if (_method != null) { call = GenDlrForMethod(objx, context); retType = _method.ReturnType; } else { call = GenerateComplexCall(objx, context); retType = typeof(object); } call = HostExpr.GenBoxReturn(call, retType, objx, context); call = Compiler.MaybeAddDebugInfo(call, _spanMap, context.IsDebuggable); return(call); }
static List <Type> ParseGenericMethodTypeArgs(ISeq targs) { List <Type> types = new List <Type>(); for (ISeq s = targs; s != null; s = s.next()) { object arg = s.first(); if (!(arg is Symbol)) { throw new ArgumentException("Malformed generic method designator: type arg must be a Symbol"); } Type t = HostExpr.MaybeType(arg, false); if (t == null) { throw new ArgumentException("Malformed generic method designator: invalid type arg"); } types.Add(t); } return(types); }
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 Expr Parse(ParserContext pcon, object frm) { //int line = (int)Compiler.LINE.deref(); ISeq form = (ISeq)frm; // form => (new Typename args ... ) if (form.count() < 2) { throw new ParseException("wrong number of arguments, expecting: (new Typename args ...)"); } Type t = HostExpr.MaybeType(RT.second(form), false); if (t == null) { throw new ParseException("Unable to resolve classname: " + RT.second(form)); } List <HostArg> args = HostExpr.ParseArgs(pcon, RT.next(RT.next(form))); return(new NewExpr(t, args, (IPersistentMap)Compiler.SourceSpanVar.deref())); }
public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val) { GenContext.EmitDebugInfo(ilg, _spanMap); if (_targetType != null && _tinfo != null) { _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Castclass, _targetType); val.Emit(RHC.Expression, objx, ilg); LocalBuilder tmp = ilg.DeclareLocal(typeof(object)); GenContext.SetLocalName(tmp, "valTemp"); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Stloc, tmp); if (FieldType.IsValueType) { HostExpr.EmitUnboxArg(objx, ilg, FieldType); } else { ilg.Emit(OpCodes.Castclass, FieldType); } EmitSet(ilg); ilg.Emit(OpCodes.Ldloc, tmp); } else { _target.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Ldstr, _memberName); val.Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Call, Compiler.Method_Reflector_SetInstanceFieldOrProperty); } if (rhc == RHC.Statement) { ilg.Emit(OpCodes.Pop); } }
private ConstructorInfo ComputeCtor() { int numArgs = _args.count(); List <ConstructorInfo> cinfos = new List <ConstructorInfo>(_type.GetConstructors() .Where(x => x.GetParameters().Length == numArgs && x.IsPublic)); if (cinfos.Count == 0) { throw new InvalidOperationException(string.Format("No constructor in type: {0} with {1} arguments", _type.Name, numArgs)); } int index = 0; if (cinfos.Count > 1) { List <ParameterInfo[]> parms = new List <ParameterInfo[]>(cinfos.Count); List <Type> rets = new List <Type>(cinfos.Count); foreach (ConstructorInfo cinfo in cinfos) { parms.Add(cinfo.GetParameters()); rets.Add(_type); } index = HostExpr.GetMatchingParams(".ctor", parms, _args, rets); } ConstructorInfo ctor = index >= 0 ? cinfos[index] : null; if (ctor == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) { ((TextWriter)RT.ERR.deref()).WriteLine("Reflection warning, line: {0} - call to {1} ctor can't be resolved.", /* line */ 0, _type.FullName); } return(ctor); }
void EmitProto(RHC rhc, ObjExpr objx, CljILGen ilg) { Label onLabel = ilg.DefineLabel(); Label callLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); Var v = ((VarExpr)_fexpr).Var; Expr e = (Expr)_args.nth(0); e.Emit(RHC.Expression, objx, ilg); // target ilg.Emit(OpCodes.Dup); // target, target LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object)); GenContext.SetLocalName(targetTemp, "target"); ilg.Emit(OpCodes.Stloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class ilg.EmitLoadArg(0); // class, this ilg.EmitFieldGet(objx.CachedTypeField(_siteIndex)); // class, cached-class ilg.Emit(OpCodes.Beq, callLabel); // if (_protocolOn != null) { ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Isinst, _protocolOn); // null or target ilg.Emit(OpCodes.Ldnull); // (null or target), null ilg.Emit(OpCodes.Cgt_Un); // (0 or 1) ilg.Emit(OpCodes.Brtrue, onLabel); } ilg.Emit(OpCodes.Ldloc, targetTemp); // target ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class LocalBuilder typeTemp = ilg.DeclareLocal(typeof(Type)); GenContext.SetLocalName(typeTemp, "type"); ilg.Emit(OpCodes.Stloc, typeTemp); // (typeType <= class) ilg.EmitLoadArg(0); // this ilg.Emit(OpCodes.Ldloc, typeTemp); // this, class ilg.EmitFieldSet(objx.CachedTypeField(_siteIndex)); // ilg.MarkLabel(callLabel); objx.EmitVar(ilg, v); // var ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn ilg.Emit(OpCodes.Castclass, typeof(AFunction)); ilg.Emit(OpCodes.Ldloc, targetTemp); // proto-fn, target EmitArgsAndCall(1, rhc, objx, ilg); ilg.Emit(OpCodes.Br, endLabel); ilg.MarkLabel(onLabel); ilg.Emit(OpCodes.Ldloc, targetTemp); // target if (_protocolOn != null) { ilg.Emit(OpCodes.Castclass, _protocolOn); MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count())); //if (rhc == RHC.Return) //{ // ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref(); // method.EmitClearLocals(context); //} ilg.Emit(OpCodes.Callvirt, _onMethod); HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType); } ilg.MarkLabel(endLabel); }
public static Expr Parse(ParserContext pcon, ISeq form) { pcon = pcon.EvalOrExpr(); Expr fexpr = Compiler.Analyze(pcon, form.first()); VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar)) { if (RT.second(form) is Symbol) { Type t = HostExpr.MaybeType(RT.second(form), false); if (t != null) { return(new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), t, Compiler.Analyze(pcon, RT.third(form)))); } } } if (varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); for (ISeq s = RT.seq(arglists); s != null; s = s.next()) { IPersistentVector sargs = (IPersistentVector)s.first(); if (sargs.count() == arity) { string primc = FnMethod.PrimInterface(sargs); if (primc != null) { return(Compiler.Analyze(pcon, RT.listStar(Symbol.intern(".invokePrim"), ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))), form.next()))); } break; } } } KeywordExpr kwFexpr = fexpr as KeywordExpr; if (kwFexpr != null && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound) { Expr target = Compiler.Analyze(pcon, RT.second(form)); return(new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target)); } IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(Compiler.Analyze(pcon, s.first())); } //if (args.count() > Compiler.MAX_POSITIONAL_ARITY) // throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY)); return(new InvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form), Compiler.TagOf(form), fexpr, args)); }
private void DoEmitPrim(ObjExpr fn, TypeBuilder tb) { MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual; string methodName = "invokePrim"; Type returnType; if (_retType == typeof(double) || _retType == typeof(long)) { returnType = ReturnType; } else { returnType = typeof(object); } MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes); 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 prim method MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes); SetCustomAttributes(regularMB); CljILGen regIlg = new CljILGen(regularMB.GetILGenerator()); 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 (ReturnType.IsValueType) { regIlg.Emit(OpCodes.Box, ReturnType); } regIlg.Emit(OpCodes.Ret); }
public Expr Parse(ParserContext pcon, object form) { ISeq sform = (ISeq)form; // form is one of: // (. x fieldname-sym) // (. x 0-ary-method) // (. x propertyname-sym) // (. x methodname-sym args)+ // (. x (methodname-sym args?)) // (. x (generic-m if (RT.Length(sform) < 3) { throw new ParseException("Malformed member expression, expecting (. target member ... )"); } string source = (string)Compiler.SourceVar.deref(); IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // Compiler.GetSourceSpanMap(form); Symbol tag = Compiler.TagOf(sform); // determine static or instance // static target must be symbol, either fully.qualified.Typename or Typename that has been imported Type t = HostExpr.MaybeType(RT.second(sform), false); // at this point, t will be non-null if static Expr instance = null; if (t == null) { instance = Compiler.Analyze(pcon.EvalOrExpr(), RT.second(sform)); } bool isZeroArityCall = RT.Length(sform) == 3 && RT.third(sform) is Symbol; if (isZeroArityCall) { PropertyInfo pinfo = null; FieldInfo finfo = null; // TODO: Figure out if we want to handle the -propname otherwise. bool isPropName = false; Symbol sym = (Symbol)RT.third(sform); if (sym.Name[0] == '-') { isPropName = true; sym = Symbol.intern(sym.Name.Substring(1)); } string fieldName = Compiler.munge(sym.Name); // The JVM version does not have to worry about Properties. It captures 0-arity methods under fields. // We have to put in special checks here for this. // Also, when reflection is required, we have to capture 0-arity methods under the calls that // are generated by StaticFieldExpr and InstanceFieldExpr. if (t != null) { if ((finfo = Reflector.GetField(t, fieldName, true)) != null) { return(new StaticFieldExpr(source, spanMap, tag, t, fieldName, finfo)); } if ((pinfo = Reflector.GetProperty(t, fieldName, true)) != null) { return(new StaticPropertyExpr(source, spanMap, tag, t, fieldName, pinfo)); } if (!isPropName && Reflector.GetArityZeroMethod(t, fieldName, true) != null) { return(new StaticMethodExpr(source, spanMap, tag, t, fieldName, null, new List <HostArg>())); } throw new MissingMemberException(t.Name, fieldName); } else if (instance != null && instance.HasClrType && instance.ClrType != null) { Type instanceType = instance.ClrType; if ((finfo = Reflector.GetField(instanceType, fieldName, false)) != null) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, finfo)); } if ((pinfo = Reflector.GetProperty(instanceType, fieldName, false)) != null) { return(new InstancePropertyExpr(source, spanMap, tag, instance, fieldName, pinfo)); } if (!isPropName && Reflector.GetArityZeroMethod(instanceType, fieldName, false) != null) { return(new InstanceMethodExpr(source, spanMap, tag, instance, fieldName, null, new List <HostArg>())); } if (pcon.IsAssignContext) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null } else { return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName)); } } else { // t is null, so we know this is not a static call // If instance is null, we are screwed anyway. // If instance is not null, then we don't have a type. // So we must be in an instance call to a property, field, or 0-arity method. // The code generated by InstanceFieldExpr/InstancePropertyExpr with a null FieldInfo/PropertyInfo // will generate code to do a runtime call to a Reflector method that will check all three. //return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null //return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName); if (pcon.IsAssignContext) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null } else { return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName)); } } } //ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); ISeq call; List <Type> typeArgs = null; object fourth = RT.fourth(sform); if (fourth is ISeq && RT.first(fourth) is Symbol && ((Symbol)RT.first(fourth)).Equals(TypeArgsSym)) { // We have a type args supplied for a generic method call // (. thing methodname (type-args type1 ... ) args ...) typeArgs = ParseGenericMethodTypeArgs(RT.next(fourth)); call = RT.listStar(RT.third(sform), RT.next(RT.next(RT.next(RT.next(sform))))); } else { call = RT.third(sform) is ISeq ? (ISeq)RT.third(sform) : RT.next(RT.next(sform)); } if (!(RT.first(call) is Symbol)) { throw new ParseException("Malformed member exception"); } string methodName = Compiler.munge(((Symbol)RT.first(call)).Name); List <HostArg> args = ParseArgs(pcon, RT.next(call)); return(t != null ? (MethodExpr)(new StaticMethodExpr(source, spanMap, tag, t, methodName, typeArgs, args)) : (MethodExpr)(new InstanceMethodExpr(source, spanMap, tag, instance, methodName, typeArgs, args))); }