コード例 #1
0
ファイル: LetExpr.cs プロジェクト: redchew-fork/clojure-clr
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            List <LocalBuilder> locals = new List <LocalBuilder>();

            for (int i = 0; i < _bindingInits.count(); i++)
            {
                BindingInit bi       = (BindingInit)_bindingInits.nth(i);
                Type        primType = Compiler.MaybePrimitiveType(bi.Init);
                if (primType != null)
                {
                    LocalBuilder local = ilg.DeclareLocal(primType);
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
                else
                {
                    LocalBuilder local = ilg.DeclareLocal(typeof(Object));
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    bi.Init.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
            }

            Label loopLabel = ilg.DefineLabel();

            ilg.MarkLabel(loopLabel);

            try
            {
                if (_isLoop)
                {
                    Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel));
                }

                if (emitUnboxed)
                {
                    ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg);
                }
                else
                {
                    _body.Emit(rhc, objx, ilg);
                }
            }
            finally
            {
                if (_isLoop)
                {
                    Var.popThreadBindings();
                }
            }
        }
コード例 #2
0
ファイル: DefExpr.cs プロジェクト: redchew-fork/clojure-clr
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            objx.EmitVar(ilg, _var);

            if (_shadowsCoreMapping)
            {
                LocalBuilder locNs = ilg.DeclareLocal(typeof(Namespace));
                GenContext.SetLocalName(locNs, "ns");

                ilg.Emit(OpCodes.Dup);
                ilg.EmitFieldGet(VarNsFI);
                ilg.Emit(OpCodes.Stloc, locNs);

                LocalBuilder locSym = ilg.DeclareLocal(typeof(Symbol));
                GenContext.SetLocalName(locSym, "sym");

                ilg.Emit(OpCodes.Dup);
                ilg.EmitFieldGet(VarSymFI);
                ilg.Emit(OpCodes.Stloc, locSym);

                ilg.Emit(OpCodes.Ldloc, locNs);
                ilg.Emit(OpCodes.Ldloc, locSym);
                ilg.Emit(OpCodes.Call, NamespaceReferMI);
            }

            if (_isDynamic)
            {
                ilg.Emit(OpCodes.Call, Compiler.Method_Var_setDynamic0);
            }
            if (_meta != null)
            {
                if (_initProvided || true) //IncludesExplicitMetadata((MapExpr)_meta))
                {
                    ilg.Emit(OpCodes.Dup);
                    _meta.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                    ilg.Emit(OpCodes.Call, Compiler.Method_Var_setMeta);
                }
            }
            if (_initProvided)
            {
                ilg.Emit(OpCodes.Dup);
                if (_init is FnExpr expr)
                {
                    expr.EmitForDefn(objx, ilg);
                }
                else
                {
                    _init.Emit(RHC.Expression, objx, ilg);
                }
                ilg.Emit(OpCodes.Call, Compiler.Method_Var_bindRoot);
            }
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
コード例 #3
0
        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);
                    }
                }
            }
        }
コード例 #4
0
ファイル: NewExpr.cs プロジェクト: terkhorn/clojure-clr
        private void EmitForNoArgValueTypeCtor(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            LocalBuilder loc = ilg.DeclareLocal(_type);

            ilg.Emit(OpCodes.Ldloca, loc);
            ilg.Emit(OpCodes.Initobj, _type);
            ilg.Emit(OpCodes.Box, _type);
        }
コード例 #5
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (_catchExprs.count() == 0 && _finallyExpr == null)
            {
                // degenerate case
                _tryExpr.Emit(rhc, objx, ilg);
                return;
            }

            LocalBuilder retLocal = ilg.DeclareLocal(typeof(Object));

            ilg.BeginExceptionBlock();
            _tryExpr.Emit(rhc, objx, ilg);
            if (rhc != RHC.Statement)
            {
                ilg.Emit(OpCodes.Stloc, retLocal);
            }

            for (int i = 0; i < _catchExprs.count(); i++)
            {
                CatchClause clause = (CatchClause)_catchExprs.nth(i);
                ilg.BeginCatchBlock(clause.Type);
                // Exception should be on the stack.  Put in clause local
                clause.Lb.LocalVar = ilg.DeclareLocal(clause.Type);
                ilg.Emit(OpCodes.Stloc, clause.Lb.LocalVar);
                clause.Handler.Emit(rhc, objx, ilg);
                if (rhc != RHC.Statement)
                {
                    ilg.Emit(OpCodes.Stloc, retLocal);
                }
            }

            if (_finallyExpr != null)
            {
                ilg.BeginFinallyBlock();
                _finallyExpr.Emit(RHC.Statement, objx, ilg);
            }
            ilg.EndExceptionBlock();
            if (rhc != RHC.Statement)
            {
                ilg.Emit(OpCodes.Ldloc, retLocal);
            }
        }
コード例 #6
0
 public static void EmitPrepForCall(CljILGen ilg, Type targetType, Type declaringType)
 {
     EmitConvertToType(ilg, targetType, declaringType, false);
     if (declaringType.IsValueType)
     {
         LocalBuilder vtTemp = ilg.DeclareLocal(declaringType);
         GenContext.SetLocalName(vtTemp, "valueTemp");
         ilg.Emit(OpCodes.Stloc, vtTemp);
         ilg.Emit(OpCodes.Ldloca, vtTemp);
     }
 }
コード例 #7
0
ファイル: DefExpr.cs プロジェクト: telefunkenvf14/clojure-clr
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            objx.EmitVar(ilg, _var);

            if ( _shadowsCoreMapping )
            {
                LocalBuilder locNs = ilg.DeclareLocal(typeof(Namespace));
                GenContext.SetLocalName(locNs, "ns");

                ilg.Emit(OpCodes.Dup);
                ilg.EmitFieldGet(VarNsFI);
                ilg.Emit(OpCodes.Stloc,locNs);

                LocalBuilder locSym = ilg.DeclareLocal(typeof(Symbol));
                GenContext.SetLocalName(locSym, "sym");

                ilg.Emit(OpCodes.Dup);
                ilg.EmitFieldGet(VarSymFI);
                ilg.Emit(OpCodes.Stloc, locSym);

                ilg.Emit(OpCodes.Ldloc, locNs);
                ilg.Emit(OpCodes.Ldloc, locSym);
                ilg.Emit(OpCodes.Call, NamespaceReferMI);
            }

            if (_isDynamic)
            {
                ilg.Emit(OpCodes.Call, Compiler.Method_Var_setDynamic0);
            }
            if (_meta != null)
            {
                if (_initProvided || true) //IncludesExplicitMetadata((MapExpr)_meta))
                {
                    ilg.Emit(OpCodes.Dup);
                    _meta.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                    ilg.Emit(OpCodes.Call, Compiler.Method_Var_setMeta);
                }
            }
            if (_initProvided)
            {
                ilg.Emit(OpCodes.Dup);
                if (_init is FnExpr)
                    ((FnExpr)_init).EmitForDefn(objx, ilg);
                else
                    _init.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Call,Compiler.Method_Var_bindRoot);
            }
            if (rhc == RHC.Statement)
                ilg.Emit(OpCodes.Pop);
        }
コード例 #8
0
ファイル: TryExpr.cs プロジェクト: corvusalba/clojure-clr
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (_catchExprs.count() == 0 && _finallyExpr == null)
            {
                // degenerate case
                _tryExpr.Emit(rhc, objx, ilg);
                return;
            }

            LocalBuilder retLocal = ilg.DeclareLocal(typeof(Object));

            ilg.BeginExceptionBlock();
            _tryExpr.Emit(rhc, objx, ilg);
            if (rhc != RHC.Statement)
                ilg.Emit(OpCodes.Stloc, retLocal);

            for (int i = 0; i < _catchExprs.count(); i++)
            {
                CatchClause clause = (CatchClause)_catchExprs.nth(i);
                ilg.BeginCatchBlock(clause.Type);
                // Exception should be on the stack.  Put in clause local
                clause.Lb.LocalVar = ilg.DeclareLocal(clause.Type);
                ilg.Emit(OpCodes.Stloc, clause.Lb.LocalVar);
                clause.Handler.Emit(rhc, objx, ilg);
                if (clause.Handler.HasNormalExit() && rhc != RHC.Statement)
                    ilg.Emit(OpCodes.Stloc, retLocal);
            }

            if (_finallyExpr != null)
            {
                ilg.BeginFinallyBlock();
                _finallyExpr.Emit(RHC.Statement, objx, ilg);
            }
            ilg.EndExceptionBlock();
            if (rhc != RHC.Statement)
                ilg.Emit(OpCodes.Ldloc, retLocal);
        }
コード例 #9
0
        void CreateStaticCtor()
        {
            ConstructorBuilder ctorB = _typeBuilder.DefineConstructor(MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
            CljILGen           gen   = new CljILGen(ctorB.GetILGenerator());

            foreach (SiteInfo si in _siteInfos)
            {
                string setterName = String.Format("{0}_setter", si.FieldBuilder.Name);

                MethodBuilder mbSetter = _typeBuilder.DefineMethod(
                    setterName,
                    MethodAttributes.Public | MethodAttributes.Static,
                    CallingConventions.Standard,
                    si.SiteType,
                    Type.EmptyTypes);
                //LambdaExpression initL = Expression.Lambda(Expression.Assign(Expression.Field(null, fb), fbInit));
                //initL.CompileToMethod(mbSetter);
                CljILGen setterIlg = new CljILGen(mbSetter.GetILGenerator());

                if (!(si.Binder is IClojureBinder b))
                {
                    throw new InvalidOperationException("Binder of unknown type");
                }
                b.GenerateCreationIL(mbSetter.GetILGenerator());

                setterIlg.EmitCall(si.SiteType.GetMethod("Create"));
                setterIlg.Emit(OpCodes.Dup);
                LocalBuilder v0 = setterIlg.DeclareLocal(typeof(Object));
                setterIlg.Emit(OpCodes.Stloc, v0);
                setterIlg.Emit(OpCodes.Stsfld, si.FieldBuilder);
                setterIlg.Emit(OpCodes.Ldloc, v0);
                setterIlg.Emit(OpCodes.Ret);

                gen.EmitCall(mbSetter);
                gen.Emit(OpCodes.Pop);
            }

            gen.Emit(OpCodes.Ret);
        }
コード例 #10
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            int n = _bindingInits.count();

            // Define our locals
            for (int i = 0; i < n; i++)
            {
                BindingInit  bi    = (BindingInit)_bindingInits.nth(i);
                LocalBuilder local = ilg.DeclareLocal(typeof(IFn));
                bi.Binding.LocalVar = local;
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Stloc, local);
            }

            // Then initialize

            IPersistentSet lbset = PersistentHashSet.EMPTY;

            for (int i = 0; i < n; i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                lbset = (IPersistentSet)lbset.cons(bi.Binding);

                bi.Init.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Stloc, bi.Binding.LocalVar);
            }

            for (int i = 0; i < n; i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                ObjExpr     fe = (ObjExpr)bi.Init;

                ilg.Emit(OpCodes.Ldloc, bi.Binding.LocalVar);
                fe.EmitLetFnInits(ilg, bi.Binding.LocalVar, objx, lbset);
            }

            _body.Emit(rhc, objx, ilg);
        }
コード例 #11
0
ファイル: LetFnExpr.cs プロジェクト: clojure/clojure-clr
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            int n = _bindingInits.count();

            // Define our locals
            for (int i = 0; i < n; i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                LocalBuilder local = ilg.DeclareLocal(typeof(IFn));
                bi.Binding.LocalVar = local;
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Stloc, local);
            }

            // Then initialize

            IPersistentSet lbset = PersistentHashSet.EMPTY;

            for (int i = 0; i < n; i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                lbset = (IPersistentSet)lbset.cons(bi.Binding);

                bi.Init.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Stloc,bi.Binding.LocalVar);
            }

            for (int i = 0; i < n; i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                ObjExpr fe = (ObjExpr)bi.Init;

                ilg.Emit(OpCodes.Ldloc, bi.Binding.LocalVar);
                fe.EmitLetFnInits(ilg, bi.Binding.LocalVar, objx, lbset);
            }

            _body.Emit(rhc, objx, ilg);
        }
コード例 #12
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);
            }
        }
コード例 #13
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        static void DefineCtors(TypeBuilder proxyTB, 
            Type superClass,
            string initName,
            string postInitName,
            ISeq ctors,
            ISeq ctorTypes,
            FieldBuilder initFB,
            FieldBuilder postInitFB,
            FieldBuilder stateFB,
            string factoryName)
        {
            ISeq s1 = ctors;
            for (ISeq s = ctorTypes; s != null; s = s.next())
            {
                // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map.  Sigh.
                IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key()));
                s1 = s1.next();

                IMapEntry me = (IMapEntry)s.first();
                ISeq thisParamTypesV = (ISeq)me.key();
                ISeq baseParamTypesV = (ISeq)me.val();

                Type[] thisParamTypes = CreateTypeArray(thisParamTypesV);
                Type[] baseParamTypes = CreateTypeArray(baseParamTypesV);

                BindingFlags flags = BindingFlags.CreateInstance| BindingFlags.NonPublic| BindingFlags.Public| BindingFlags.Instance;
                ConstructorInfo superCtor = superClass.GetConstructor(flags,null,baseParamTypes,null);

                if (superCtor == null || superCtor.IsPrivate)
                    throw new InvalidOperationException("Base class constructor missing or private");

                ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes);
                GenInterface.SetCustomAttributes(cb, ctorAttributes);

                CljILGen gen = new CljILGen(cb.GetILGenerator());

                Label noInitLabel = gen.DefineLabel();
                Label noPostInitLabel = gen.DefineLabel();
                Label endPostInitLabel = gen.DefineLabel();
                Label endLabel = gen.DefineLabel();

                LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object));
                LocalBuilder locInitVal = gen.DeclareLocal(typeof(object));

                if (initFB != null)
                {
                    // init supplied
                    EmitGetVar(gen, initFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Box,thisParamTypes[i]);
                    }

                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]);

                    // Expecting:  [[super-ctor-args...] state]

                    // store the init return in a local
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Stloc,locInitVal);

                    // store the first element in a local
                    gen.EmitInt(0);                             // gen.Emit(OpCodes.Ldc_I4_0);
                    gen.EmitCall(Method_RT_nth);                // gen.Emit(OpCodes.Call, Method_RT_nth);
                    gen.Emit(OpCodes.Stloc, locSuperArgs);

                    // Stack this + super-ctor-args + call base-class ctor.
                    gen.EmitLoadArg(0);                         // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < baseParamTypes.Length; i++)
                    {
                        gen.Emit(OpCodes.Ldloc, locSuperArgs);
                        gen.EmitInt(i);                         // gen.Emit(OpCodes.Ldc_I4, i);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        if (baseParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]);
                        else
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                    }

                    gen.Emit(OpCodes.Call, superCtor);

                    if (stateFB != null)
                    {
                        gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldloc, locInitVal);
                        gen.EmitInt(1);                         // gen.Emit(OpCodes.Ldc_I4_1);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        gen.Emit(OpCodes.Castclass, typeof(object));
                        gen.EmitFieldSet(stateFB);              // gen.Emit(OpCodes.Stfld, stateFB);
                    }

                    gen.Emit(OpCodes.Br_S, endLabel);

                    // No init found
                    gen.MarkLabel(noInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, initName);

                    gen.MarkLabel(endLabel);
                }
                else  // no InitFB supplied.
                {
                    bool ok = thisParamTypes.Length == baseParamTypes.Length;
                    for (int i = 0; ok && i < thisParamTypes.Length; i++)
                        ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]);
                    if (!ok)
                        throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ");
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for ( int i=0; i< thisParamTypes.Length; i++ )
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (baseParamTypes[i] != thisParamTypes[i])
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                    }
                    gen.Emit(OpCodes.Call, superCtor);
                }

                if (postInitFB != null)
                {
                    // post-init supplied
                    EmitGetVar(gen, postInitFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noPostInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        gen.Emit(OpCodes.Castclass, thisParamTypes[i]);
                    }
                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);
                    gen.Emit(OpCodes.Pop);
                    gen.Emit(OpCodes.Br_S, endPostInitLabel);

                    // no post-init found

                    gen.MarkLabel(noPostInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen,postInitName + " not defined");

                    gen.MarkLabel(endPostInitLabel);
               }

                gen.Emit(OpCodes.Ret);

                if (!String.IsNullOrEmpty(factoryName))
                {
                    MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes);
                    CljILGen genf = new CljILGen(factoryMB.GetILGenerator());

                    LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length];
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        locals[i] = genf.DeclareLocal(thisParamTypes[i]);
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                        genf.Emit(OpCodes.Stloc, locals[i]);
                    }

                    for (int i = 0; i < thisParamTypes.Length; i++)
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);

                    genf.EmitNew(cb);                           // genf.Emit(OpCodes.Newobj, cb);
                    genf.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #14
0
ファイル: InvokeExpr.cs プロジェクト: terkhorn/clojure-clr
        // TODO: Eliminate common code between EmitProtoLight and EmitProtoFull

        void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);

            e.Emit(RHC.Expression, objx, ilg);               // target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));

            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc, targetTemp);             //   (targetTemp <= target)

            ilg.EmitString(String.Format("In Light Proto for {0}", v.Symbol.ToString()));
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Ldloc, targetTemp);              // target
            //    ilg.Emit(OpCodes.Isinst, _protocolOn);            // (target or null)
            //    ilg.Emit(OpCodes.Ldnull);                         // (target or null), null
            //    ilg.Emit(OpCodes.Cgt_Un);                         // (0 or 1)
            //    ilg.Emit(OpCodes.Brtrue, onLabel);
            //}

            objx.EmitVar(ilg, v);                                   // var
            ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn


            ilg.Emit(OpCodes.Dup);
            ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType"));
            ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString"));
            ilg.EmitString("Expected AFunction, got ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) }));
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));


            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.EmitString("Castclass worked ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));


            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1, rhc, objx, ilg);

            ilg.EmitString("gen'd args and called");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            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);
        }
コード例 #15
0
        void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
            //objx arg is enclosing objx, not this


            // Create the function instance
            LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType);

            if (CompiledType == typeof(RestFnImpl))
            {
                ilg.EmitInt(_variadicMethod.RequiredArity);
                ilg.EmitNew(Compiler.Ctor_RestFnImpl_1);
            }
            else
            {
                ilg.EmitNew(Compiler.Ctor_AFnImpl);
            }

            ilg.Emit(OpCodes.Stloc, fnLocal);

            //ilg.EmitString(String.Format("Creating fn {0}", Name));
            //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            // Set up the methods

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                int      key    = GetMethodKey(method);

                string fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + (key - 1)  // because key is arity+1 for variadic
                    : "_fn" + key;

                FieldInfo fi = CompiledType.GetField(fieldName);

                ilg.Emit(OpCodes.Ldloc, fnLocal);


                EmitGetDynMethod(key, ilg);
                ilg.EmitType(fi.FieldType);
                ilg.Emit(OpCodes.Ldloc, fnLocal);
                ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate);
                ilg.Emit(OpCodes.Castclass, fi.FieldType);

                ilg.EmitFieldSet(fi);
            }



            // setup the constants and locals
            ilg.Emit(OpCodes.Ldloc, fnLocal);

            if (Constants.count() > 0)
            {
                EmitGetCompiledConstants(ilg);
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            if (Closes.count() > 0)
            {
                int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index);

                ilg.EmitInt(maxIndex + 1);
                ilg.Emit(OpCodes.Newarr, typeof(object));

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    ilg.Emit(OpCodes.Dup);
                    ilg.EmitInt(lb.Index);
                    objx.EmitLocal(ilg, lb);
                    ilg.EmitStoreElement(typeof(object));
                }
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            // Create the closure
            ilg.EmitNew(Compiler.Ctor_Closure_2);

            // Assign the clojure
            ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure);

            // Leave the instance on the stack.
            ilg.Emit(OpCodes.Ldloc, fnLocal);
        }
コード例 #16
0
ファイル: IfExpr.cs プロジェクト: JvJ/clojure-clr
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            Label nullLabel = ilg.DefineLabel();
            Label falseLabel = ilg.DefineLabel();
            Label endLabel = ilg.DefineLabel();
            Label trueLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            StaticMethodExpr sme = _testExpr as StaticMethodExpr;
            if (sme != null && sme.CanEmitIntrinsicPredicate())
                sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel);
            else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool))
            {
                ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Brfalse, falseLabel);
            }
            else
            {
                LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(tempLoc, "test");

                _testExpr.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Stloc, tempLoc);

                ilg.Emit(OpCodes.Brfalse, nullLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Isinst, typeof(bool));
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Cgt_Un);
                ilg.Emit(OpCodes.Brfalse, trueLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Unbox_Any, typeof(bool));
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
                ilg.Emit(OpCodes.Brtrue, falseLabel);
            }

            ilg.MarkLabel(trueLabel);

            if (emitUnboxed)
                ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg);
            else
                _thenExpr.Emit(rhc, objx, ilg);

            if ( _thenExpr.HasNormalExit() )
                ilg.Emit(OpCodes.Br, endLabel);

            ilg.MarkLabel(nullLabel);
            ilg.MarkLabel(falseLabel);

            if (emitUnboxed)
                ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg);
            else
                _elseExpr.Emit(rhc, objx, ilg);
            ilg.MarkLabel(endLabel);
        }
コード例 #17
0
ファイル: NewExpr.cs プロジェクト: TerabyteX/clojure-clr
 private void EmitForNoArgValueTypeCtor(RHC rhc, ObjExpr objx, CljILGen ilg)
  {
      LocalBuilder loc = ilg.DeclareLocal(_type);
      ilg.Emit(OpCodes.Ldloca, loc);
      ilg.Emit(OpCodes.Initobj, _type);
      ilg.Emit(OpCodes.Ldloc, loc);
      ilg.Emit(OpCodes.Box, _type);
  }
コード例 #18
0
ファイル: InvokeExpr.cs プロジェクト: EricThorsen/clojure-clr
        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);
        }
コード例 #19
0
ファイル: FnExpr.cs プロジェクト: kocubinski/clojure-clr
        void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {

            //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
            //objx arg is enclosing objx, not this

            
            // Create the function instance
            LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType);
            
            if (CompiledType == typeof(RestFnImpl))
            {
                ilg.EmitInt(_variadicMethod.RequiredArity);
                ilg.EmitNew(Compiler.Ctor_RestFnImpl_1);
            }
            else
            {
                ilg.EmitNew(Compiler.Ctor_AFnImpl);
            }

            ilg.Emit(OpCodes.Stloc, fnLocal);

            //ilg.EmitString(String.Format("Creating fn {0}", Name));
            //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            // Set up the methods

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                int key = GetMethodKey(method);
 
                string fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + (key - 1)  // because key is arity+1 for variadic
                    : "_fn" + key;

                FieldInfo fi = CompiledType.GetField(fieldName);

                ilg.Emit(OpCodes.Ldloc, fnLocal);


                EmitGetDynMethod(key, ilg);
                ilg.EmitType(fi.FieldType);
                ilg.Emit(OpCodes.Ldloc, fnLocal);
                ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate);
                ilg.Emit(OpCodes.Castclass, fi.FieldType);

                ilg.EmitFieldSet(fi);
            }



            // setup the constants and locals
            ilg.Emit(OpCodes.Ldloc, fnLocal);

            if (Constants.count() > 0)
            {
                EmitGetCompiledConstants(ilg);
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            if (Closes.count() > 0)
            {

                int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index);

                ilg.EmitInt(maxIndex + 1);
                ilg.Emit(OpCodes.Newarr, typeof(object));

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    ilg.Emit(OpCodes.Dup);
                    ilg.EmitInt(lb.Index);
                    objx.EmitLocal(ilg, lb);
                    ilg.EmitStoreElement(typeof(object));
                }
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            // Create the closure
            ilg.EmitNew(Compiler.Ctor_Closure_2);

            // Assign the clojure
            ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure);

            // Leave the instance on the stack.
            ilg.Emit(OpCodes.Ldloc, fnLocal);
        }
コード例 #20
0
        protected override void EmitStatics(TypeBuilder tb)
        {
            if (IsDefType)
            {
                // getBasis()
                {
                    MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes);
                    CljILGen ilg = new CljILGen(mbg.GetILGenerator());
                    EmitValue(HintedFields, ilg);
                    ilg.Emit(OpCodes.Ret);
                }

                if (Fields.count() > HintedFields.count())
                {
                    // create(IPersistentMap)
                    MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) });
                    CljILGen gen = new CljILGen(mbc.GetILGenerator());

                    LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword));
                    List<LocalBuilder> locals = new List<LocalBuilder>();
                    for (ISeq s = RT.seq(HintedFields); s != null; s = s.next())
                    {
                        string bName = ((Symbol)s.first()).Name;
                        Type t = Compiler.TagType(Compiler.TagOf(s.first()));

                        // local_kw = Keyword.intern(bname)
                        // local_i = arg_0.valAt(kw,null)
                        gen.EmitLoadArg(0);
                        gen.EmitString(bName);
                        gen.EmitCall(Compiler.Method_Keyword_intern_string);
                        gen.Emit(OpCodes.Dup);
                        gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex);
                        gen.EmitNull();
                        gen.EmitCall(Compiler.Method_IPersistentMap_valAt2);
                        LocalBuilder lb = gen.DeclareLocal(t);
                        locals.Add(lb);
                        if (t.IsPrimitive)
                            gen.EmitUnbox(t);
                        gen.Emit(OpCodes.Stloc, lb.LocalIndex);

                        // arg_0 = arg_0.without(local_kw);
                        gen.EmitLoadArg(0);
                        gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex);
                        gen.EmitCall(Compiler.Method_IPersistentMap_without);
                        gen.EmitStoreArg(0);
                    }

                    foreach (LocalBuilder lb in locals)
                        gen.Emit(OpCodes.Ldloc, lb.LocalIndex);
                    gen.EmitNull();
                    gen.EmitLoadArg(0);
                    gen.EmitCall(Compiler.Method_RT_seqOrElse);
                    gen.EmitNew(CtorInfo);

                    gen.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #21
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (objx.FnMode == FnMode.Light)
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                ie.Emit(rhc, objx, ilg);
            }
            else
            {
                Label endLabel = ilg.DefineLabel();
                Label faultLabel = ilg.DefineLabel();

                GenContext.EmitDebugInfo(ilg, _spanMap);

                LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk));
                LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
                LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(thunkLoc, "thunk");
                GenContext.SetLocalName(targetLoc, "target");
                GenContext.SetLocalName(resultLoc, "result");

                // TODO: Debug info

                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                     // thunk
                ilg.Emit(OpCodes.Stloc, thunkLoc);                                  //  (thunkLoc <= thunk)

                _target.Emit(RHC.Expression, objx, ilg);                         // target
                ilg.Emit(OpCodes.Stloc, targetLoc);                                  //   (targetLoc <= target)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, targetLoc);
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
                ilg.Emit(OpCodes.Stloc, resultLoc);                                 //    (resultLoc <= result)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, resultLoc);
                ilg.Emit(OpCodes.Beq, faultLabel);

                ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
                ilg.Emit(OpCodes.Br, endLabel);

                ilg.MarkLabel(faultLabel);
                ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));           // site
                ilg.Emit(OpCodes.Ldloc, targetLoc);                                  // site, target
                ilg.EmitCall(Compiler.Method_ILookupSite_fault);                    // new-thunk
                ilg.Emit(OpCodes.Dup);                                              // new-thunk, new-thunk
                ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                      // new-thunk

                ilg.Emit(OpCodes.Ldloc, targetLoc);                                 // new-thunk, target
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

                ilg.MarkLabel(endLabel);                                           // result
                if (rhc == RHC.Statement)
                    ilg.Emit(OpCodes.Pop);
            }
        }
コード例 #22
0
ファイル: LetExpr.cs プロジェクト: corvusalba/clojure-clr
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            List<LocalBuilder> locals = new List<LocalBuilder>();

            for (int i = 0; i < _bindingInits.count(); i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                Type primType = Compiler.MaybePrimitiveType(bi.Init);
                if (primType != null)
                {
                    LocalBuilder local = ilg.DeclareLocal(primType);
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
                else
                {
                    LocalBuilder local = ilg.DeclareLocal(typeof(Object));
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    bi.Init.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
             }

            Label loopLabel = ilg.DefineLabel();
            ilg.MarkLabel(loopLabel);

            try
            {
                if (_isLoop)
                    Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel));

                if (emitUnboxed)
                    ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg);
                else
                    _body.Emit(rhc, objx, ilg);
            }
            finally
            {
                if (_isLoop)
                    Var.popThreadBindings();
            }
        }
コード例 #23
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel   = ilg.DefineLabel();
            Label faultLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _spanMap);

            LocalBuilder thunkLoc  = ilg.DeclareLocal(typeof(ILookupThunk));
            LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
            LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));

            GenContext.SetLocalName(thunkLoc, "thunk");
            GenContext.SetLocalName(targetLoc, "target");
            GenContext.SetLocalName(resultLoc, "result");

            // TODO: Debug info

            // pseudo-code:
            //  ILookupThunk thunk = objclass.ThunkField(i)
            //  object target = ...code...
            //  object val = thunk.get(target)
            //  if ( val != thunk )
            //     return val
            //  else
            //     KeywordLookupSite site = objclass.SiteField(i)
            //     thunk = site.fault(target)
            //     objclass.ThunkField(i) = thunk
            //     val = thunk.get(target)
            //     return val

            ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                   // thunk
            ilg.Emit(OpCodes.Stloc, thunkLoc);                               //  (thunkLoc <= thunk)

            _target.Emit(RHC.Expression, objx, ilg);                         // target
            ilg.Emit(OpCodes.Stloc, targetLoc);                              //   (targetLoc <= target)

            ilg.Emit(OpCodes.Ldloc, thunkLoc);
            ilg.Emit(OpCodes.Ldloc, targetLoc);
            ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
            ilg.Emit(OpCodes.Stloc, resultLoc);                                //    (resultLoc <= result)

            ilg.Emit(OpCodes.Ldloc, thunkLoc);
            ilg.Emit(OpCodes.Ldloc, resultLoc);
            ilg.Emit(OpCodes.Beq, faultLabel);

            ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
            ilg.Emit(OpCodes.Br, endLabel);

            ilg.MarkLabel(faultLabel);
            ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));         // site
            ilg.Emit(OpCodes.Ldloc, targetLoc);                                // site, target
            ilg.EmitCall(Compiler.Method_ILookupSite_fault);                   // new-thunk
            ilg.Emit(OpCodes.Dup);                                             // new-thunk, new-thunk
            ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                     // new-thunk

            ilg.Emit(OpCodes.Ldloc, targetLoc);                                // new-thunk, target
            ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

            ilg.MarkLabel(endLabel);                                           // result
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
コード例 #24
0
ファイル: IfExpr.cs プロジェクト: willemdijkgraaf/ClojureClr
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            Label nullLabel  = ilg.DefineLabel();
            Label falseLabel = ilg.DefineLabel();
            Label endLabel   = ilg.DefineLabel();
            Label trueLabel  = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            StaticMethodExpr sme = _testExpr as StaticMethodExpr;

            if (sme != null && sme.CanEmitIntrinsicPredicate())
            {
                sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel);
            }
            else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool))
            {
                ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Brfalse, falseLabel);
            }
            else
            {
                LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(tempLoc, "test");

                _testExpr.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Stloc, tempLoc);

                ilg.Emit(OpCodes.Brfalse, nullLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Isinst, typeof(bool));
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Cgt_Un);
                ilg.Emit(OpCodes.Brfalse, trueLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Unbox_Any, typeof(bool));
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
                ilg.Emit(OpCodes.Brtrue, falseLabel);
            }

            ilg.MarkLabel(trueLabel);

            if (emitUnboxed)
            {
                ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg);
            }
            else
            {
                _thenExpr.Emit(rhc, objx, ilg);
            }


            if (_thenExpr.HasNormalExit())
            {
                ilg.Emit(OpCodes.Br, endLabel);
            }

            ilg.MarkLabel(nullLabel);
            ilg.MarkLabel(falseLabel);

            if (emitUnboxed)
            {
                ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg);
            }
            else
            {
                _elseExpr.Emit(rhc, objx, ilg);
            }
            ilg.MarkLabel(endLabel);
        }
コード例 #25
0
        protected override void EmitStatics(TypeBuilder tb)
        {
            if (IsDefType)
            {
                // getBasis()
                {
                    MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes);
                    CljILGen      ilg = new CljILGen(mbg.GetILGenerator());
                    EmitValue(HintedFields, ilg);
                    ilg.Emit(OpCodes.Ret);
                }

                if (Fields.count() > HintedFields.count())
                {
                    // create(IPersistentMap)
                    MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) });
                    CljILGen      gen = new CljILGen(mbc.GetILGenerator());

                    LocalBuilder        kwLocal = gen.DeclareLocal(typeof(Keyword));
                    List <LocalBuilder> locals  = new List <LocalBuilder>();
                    for (ISeq s = RT.seq(HintedFields); s != null; s = s.next())
                    {
                        string bName = ((Symbol)s.first()).Name;
                        Type   t     = Compiler.TagType(Compiler.TagOf(s.first()));

                        // local_kw = Keyword.intern(bname)
                        // local_i = arg_0.valAt(kw,null)
                        gen.EmitLoadArg(0);
                        gen.EmitString(bName);
                        gen.EmitCall(Compiler.Method_Keyword_intern_string);
                        gen.Emit(OpCodes.Dup);
                        gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex);
                        gen.EmitNull();
                        gen.EmitCall(Compiler.Method_IPersistentMap_valAt2);
                        LocalBuilder lb = gen.DeclareLocal(t);
                        locals.Add(lb);
                        if (t.IsPrimitive)
                        {
                            gen.EmitUnbox(t);
                        }
                        gen.Emit(OpCodes.Stloc, lb.LocalIndex);

                        // arg_0 = arg_0.without(local_kw);
                        gen.EmitLoadArg(0);
                        gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex);
                        gen.EmitCall(Compiler.Method_IPersistentMap_without);
                        gen.EmitStoreArg(0);
                    }

                    foreach (LocalBuilder lb in locals)
                    {
                        gen.Emit(OpCodes.Ldloc, lb.LocalIndex);
                    }
                    gen.EmitNull();             // __meta
                    gen.EmitLoadArg(0);         // __extmap
                    gen.EmitCall(Compiler.Method_RT_seqOrElse);
                    gen.Emit(OpCodes.Ldc_I4_0); // __hash
                    gen.Emit(OpCodes.Ldc_I4_0); // __hasheq
                    gen.EmitNew(CtorInfo);

                    gen.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #26
0
ファイル: InvokeExpr.cs プロジェクト: stuman08/clojure-clr
        // TODO: Eliminate common code between EmitProtoLight and EmitProtoFull
        void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);
            e.Emit(RHC.Expression, objx, ilg);               // target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));
            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc, targetTemp);             //   (targetTemp <= target)

            ilg.EmitString(String.Format("In Light Proto for {0}",v.Symbol.ToString()));
            ilg.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[] { typeof(string) }));

            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Ldloc, targetTemp);              // target
            //    ilg.Emit(OpCodes.Isinst, _protocolOn);            // (target or null)
            //    ilg.Emit(OpCodes.Ldnull);                         // (target or null), null
            //    ilg.Emit(OpCodes.Cgt_Un);                         // (0 or 1)
            //    ilg.Emit(OpCodes.Brtrue, onLabel);
            //}

            objx.EmitVar(ilg, v);                                 // var
            ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot);         // proto-fn

                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType"));
                ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString"));
                ilg.EmitString("Expected AFunction, got ");
                ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) }));
                ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.EmitString("Castclass worked ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1, rhc, objx, ilg);

            ilg.EmitString("gen'd args and called");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            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);
        }
コード例 #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
ファイル: MethodExpr.cs プロジェクト: chrisortman/clojure-clr
 public static void EmitPrepForCall(CljILGen ilg, Type targetType, Type declaringType)
 {
     EmitConvertToType(ilg, targetType, declaringType, false);
     if (declaringType.IsValueType)
     {
         LocalBuilder vtTemp = ilg.DeclareLocal(declaringType);
         GenContext.SetLocalName(vtTemp, "valueTemp");
         ilg.Emit(OpCodes.Stloc, vtTemp);
         ilg.Emit(OpCodes.Ldloca, vtTemp);
     }
 }
コード例 #29
0
ファイル: MethodExpr.cs プロジェクト: chrisortman/clojure-clr
        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);
                    }
                }
            }
        }
コード例 #30
0
ファイル: MethodExpr.cs プロジェクト: einert/clojure-clr
        static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, IList <ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda)
        {
            Expression call = dyn;

            GenContext context = Compiler.CompilerContextVar.deref() as GenContext;

            DynInitHelper.SiteInfo siteInfo;
            if (context != null && context.DynInitHelper != null)
            {
                call = context.DynInitHelper.ReduceDyn(dyn, out siteInfo);
            }
            else
            {
                throw new InvalidOperationException("Don't know how to handle callsite in this case");
            }

            if (returnType == typeof(void))
            {
                call       = Expression.Block(call, Expression.Default(typeof(object)));
                returnType = typeof(object);
            }
            else if (returnType != call.Type)
            {
                call = Expression.Convert(call, returnType);
            }

            call = GenContext.AddDebugInfo(call, spanMap);


            delType  = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes);
            lambda   = Expression.Lambda(delType, call, paramExprs);
            mbLambda = null;

            if (context == null)
            {
                // light compile

                Delegate d   = lambda.Compile();
                int      key = RT.nextID();
                CacheDelegate(key, d);

                ilg.EmitInt(key);
                ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate);
                ilg.Emit(OpCodes.Castclass, delType);
            }
            else
            {
                mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes);
                //lambda.CompileToMethod(mbLambda);
                // Now we get to do all this code create by hand.
                // the primary code is
                // (loc1 = fb).Target.Invoke(loc1,*args);
                // if return type if void, pop the value and push a null
                // if return type does not match the call site, add a conversion
                CljILGen ilg2 = new CljILGen(mbLambda.GetILGenerator());
                ilg2.EmitFieldGet(siteInfo.FieldBuilder);
                ilg2.Emit(OpCodes.Dup);
                LocalBuilder siteVar = ilg2.DeclareLocal(siteInfo.DelegateType);
                ilg2.Emit(OpCodes.Stloc, siteVar);
                ilg2.EmitFieldGet(siteInfo.SiteType.GetField("Target"));
                ilg2.Emit(OpCodes.Ldloc, siteVar);
                for (int i = 0; i < paramExprs.Count; i++)
                {
                    ilg2.EmitLoadArg(i);
                }

                ilg2.EmitCall(siteInfo.DelegateType.GetMethod("Invoke"));
                if (returnType == typeof(void))
                {
                    ilg2.Emit(OpCodes.Pop);
                    ilg2.EmitNull();
                }
                else if (returnType != call.Type)
                {
                    EmitConvertToType(ilg2, call.Type, returnType, false);
                }

                ilg2.Emit(OpCodes.Ret);


                /*
                 *             return Expression.Block(
                 * new[] { site },
                 * Expression.Call(
                 * Expression.Field(
                 *  Expression.Assign(site, access),
                 *  cs.GetType().GetField("Target")
                 * ),
                 * node.DelegateType.GetMethod("Invoke"),
                 * ClrExtensions.ArrayInsert(site, node.Arguments)
                 * )
                 */
            }
        }