상속: clojure.lang.CljCompiler.Ast.Expr, MaybePrimitiveExpr
예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
파일: HostExpr.cs 프로젝트: ryrency/Misc
        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);
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
        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;
            }
        }
예제 #11
0
 static void EmitUnboxArg(CljILGen ilg, Type argType, Type paramType)
 {
     if (argType == paramType)
     {
         return;
     }
     HostExpr.EmitUnboxArg(ilg, paramType);
 }
예제 #12
0
        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
        }
예제 #13
0
 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);
     }
 }
예제 #14
0
 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);
     }
 }
예제 #15
0
        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);
        }
예제 #16
0
 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);
     }
 }
예제 #17
0
        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);
            }
        }
예제 #18
0
        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);
                }
            }
        }
예제 #19
0
        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);
            }
        }
예제 #20
0
        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);
            }
        }
예제 #21
0
        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);
        }
예제 #22
0
        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);
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
            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()));
            }
예제 #25
0
        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);
            }
        }
예제 #26
0
파일: NewExpr.cs 프로젝트: ryrency/Misc
        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);
        }
예제 #27
0
        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);
        }
예제 #28
0
        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));
        }
예제 #29
0
        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);
        }
예제 #30
0
            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)));
            }