Пример #1
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);
        }
Пример #2
0
        void EmitArgsAndCall(int firstArgToEmit, RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            for (int i = firstArgToEmit; i < Math.Min(Compiler.MaxPositionalArity, _args.count()); i++)
            {
                Expr e = (Expr)_args.nth(i);
                e.Emit(RHC.Expression, objx, ilg);
            }
            if (_args.count() > Compiler.MaxPositionalArity)
            {
                IPersistentVector restArgs = PersistentVector.EMPTY;
                for (int i = Compiler.MaxPositionalArity; i < _args.count(); i++)
                {
                    restArgs = restArgs.cons(_args.nth(i));
                }
                MethodExpr.EmitArgsAsArray(restArgs, objx, ilg);
            }

            // In JVM.  No necessary here.
            //if (_tailPosition)
            //{
            //    ObjMethod method = (ObjMethod)Compiler.MethodVar.deref();
            //    method.EmitClearThis(ilg);
            //}

            MethodInfo mi = Compiler.Methods_IFn_invoke[Math.Min(Compiler.MaxPositionalArity + 1, _args.count())];

            ilg.Emit(OpCodes.Callvirt, mi);
        }
Пример #3
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);
            }
        }
Пример #4
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);
            }
        }
Пример #5
0
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     MethodExpr.EmitArgsAsArray(_keys, objx, ilg);
     ilg.Emit(OpCodes.Call, Compiler.Method_RT_set);
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
Пример #6
0
        internal void EmitIntrinsicPredicate(RHC rhc, ObjExpr objx, CljILGen ilg, Label falseLabel)
        {
            GenContext.EmitDebugInfo(ilg, _spanMap);

            if (_method != null)
            {
                MethodExpr.EmitTypedArgs(objx, ilg, _method.GetParameters(), _args);
                // JVM: clear locals
                Intrinsics.EmitPred(_method, ilg, falseLabel);
            }
            else
            {
                throw new InvalidOperationException("Unboxed emit of unknown member");
            }
        }
Пример #7
0
        public override void EmitUnboxed(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);
            }
            else
            {
                throw new InvalidOperationException("Unboxed emit of unknown member.");
            }
        }
Пример #8
0
        public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            // See MethodExpr.EmitComplexCall to see why this is so complicated

            //  Build the parameter list

            List <ParameterExpression> paramExprs = new List <ParameterExpression>();
            List <Type> paramTypes = new List <Type>();

            Type paramType            = _target.HasClrType && _target.ClrType != null && _target.ClrType.IsPrimitive ? _target.ClrType : typeof(object);
            ParameterExpression param = Expression.Parameter(paramType);

            paramExprs.Add(param);
            paramTypes.Add(paramType);


            // Build dynamic call and lambda
            Type returnType = HasClrType ? ClrType : typeof(object);

            GetMemberBinder binder = new ClojureGetZeroArityMemberBinder(ClojureContext.Default, _memberName, false);

#if CLR2
            // Not covariant. Sigh.
            List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count);
            paramsAsExprs.AddRange(paramExprs.ToArray());
            DynamicExpression dyn = Expression.Dynamic(binder, returnType, paramsAsExprs);
#else
            DynamicExpression dyn = Expression.Dynamic(binder, returnType, paramExprs);
#endif



            LambdaExpression lambda;
            Type             delType;
            MethodBuilder    mbLambda;

            MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_" + _memberName + RT.nextID(), returnType, paramExprs, paramTypes.ToArray(), ilg, out lambda, out delType, out mbLambda);

            //  Emit target + args (no args, actually)

            _target.Emit(RHC.Expression, objx, ilg);

            MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg);
        }
Пример #9
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            bool           allKeysConstant       = true;
            bool           allConstantKeysUnique = true;
            IPersistentSet constantKeys          = PersistentHashSet.EMPTY;

            for (int i = 0; i < _keyvals.count(); i += 2)
            {
                Expr k = (Expr)_keyvals.nth(i);
                if (k is LiteralExpr)
                {
                    object kval = k.Eval();
                    if (constantKeys.contains(kval))
                    {
                        allConstantKeysUnique = false;
                    }
                    else
                    {
                        constantKeys = (IPersistentSet)constantKeys.cons(kval);
                    }
                }
                else
                {
                    allKeysConstant = false;
                }
            }

            MethodExpr.EmitArgsAsArray(_keyvals, objx, ilg);

            if ((allKeysConstant && allConstantKeysUnique) || (_keyvals.count() <= 2))
            {
                ilg.EmitCall(Compiler.Method_RT_mapUniqueKeys);
            }
            else
            {
                ilg.EmitCall(Compiler.Method_RT_map);
            }

            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
Пример #10
0
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_args.count() <= Tuple.MAX_SIZE)
     {
         for (int i = 0; i < _args.count(); i++)
         {
             ((Expr)_args.nth(i)).Emit(RHC.Expression, objx, ilg);
         }
         ilg.Emit(OpCodes.Call, Compiler.Methods_CreateTuple[_args.count()]);
     }
     else
     {
         MethodExpr.EmitArgsAsArray(_args, objx, ilg);
         ilg.Emit(OpCodes.Call, Compiler.Method_RT_vector);
     }
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
Пример #11
0
        public override void EmitUnboxed(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);
            }
            else
            {
                throw new InvalidOperationException("Unboxed emit of unknown member.");
            }
        }
Пример #12
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);
        }
Пример #13
0
        // TODO: See if it is worth removing the code duplication with MethodExp.GenDlr.

        private Expression GenerateComplexCall(RHC rhc, ObjExpr objx, GenContext context)
        {
            Expression call;

            Expression target = GenTargetExpression(objx, context);

            List <Expression>          exprs       = new List <Expression>(_args.Count);
            List <ParameterExpression> sbParams    = new List <ParameterExpression>();
            List <Expression>          sbInits     = new List <Expression>();
            List <Expression>          sbTransfers = new List <Expression>();

            MethodExpr.GenerateComplexArgList(objx, context, _args, out exprs, out sbParams, out sbInits, out sbTransfers);

            Expression[] argExprs = ClrExtensions.ArrayInsert <Expression>(target, exprs);


            Type returnType = this.ClrType;
            Type stubType   = Compiler.CompileStubOrigClassVar.isBound ? (Type)Compiler.CompileStubOrigClassVar.deref() : null;

            if (returnType == stubType)
            {
                returnType = objx.BaseType;
            }

            // TODO: get rid of Default
            CreateInstanceBinder binder = new ClojureCreateInstanceBinder(ClojureContext.Default, _args.Count);
            DynamicExpression    dyn    = Expression.Dynamic(binder, typeof(object), argExprs);

            // I'd like to use returnType in place of typeof(object) in the previous,
            // But I can't override ReturnType in DefaultCreateInstanceBinder and this causes an error.
            // Look for the conversion below.

            //if (context.Mode == CompilerMode.File)
            if (context.DynInitHelper != null)
            {
                call = context.DynInitHelper.ReduceDyn(dyn);
            }
            else
            {
                call = dyn;
            }

            call = Expression.Convert(call, returnType);

            if (sbParams.Count > 0)
            {
                // We have ref/out params.  Construct the complicated call;

                ParameterExpression   callValParam = Expression.Parameter(returnType, "__callVal");
                ParameterExpression[] allParams    = ClrExtensions.ArrayInsert <ParameterExpression>(callValParam, sbParams);

                call = Expression.Block(
                    returnType,
                    allParams,
                    Expression.Block(sbInits),
                    Expression.Assign(callValParam, call),
                    Expression.Block(sbTransfers),
                    callValParam);
            }

            return(call);
        }
Пример #14
0
        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);

#if CLR2
            // Not covariant. Sigh.
            List <Expression> paramsAsExprs = new List <Expression>(paramExprs.Count);
            paramsAsExprs.AddRange(paramExprs.ToArray());
            DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramsAsExprs);
#else
            DynamicExpression dyn = Expression.Dynamic(binder, typeof(object), paramExprs);
#endif

            LambdaExpression lambda;
            Type             delType;
            MethodBuilder    mbLambda;

            MethodExpr.EmitDynamicCallPreamble(dyn, _spanMap, "__interop_ctor_" + 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:
                    MethodExpr.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();
                }
            }

            MethodExpr.EmitDynamicCallPostlude(lambda, delType, mbLambda, ilg);
        }
Пример #15
0
 private void EmitParamsForMethod(ObjExpr objx, CljILGen ilg)
 {
     ParameterInfo[] pis = _ctor.GetParameters();
     MethodExpr.EmitTypedArgs(objx, ilg, pis, _args);
 }