コード例 #1
0
 public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     ilg.EmitBoolean(_val);
     ilg.Emit(OpCodes.Box,typeof(bool));
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #2
0
ファイル: DefExpr.cs プロジェクト: robertlj/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     objx.EmitVar(ilg, _var);
     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);
 }
コード例 #3
0
ファイル: VarExpr.cs プロジェクト: telefunkenvf14/clojure-clr
 public void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val)
 {
     objx.EmitVar(ilg, _var);
     val.Emit(RHC.Expression, objx, ilg);
     ilg.Emit(OpCodes.Call, Compiler.Method_Var_set);
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #4
0
ファイル: ImportExpr.cs プロジェクト: JvJ/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     ilg.Emit(OpCodes.Call,Compiler.Method_Compiler_CurrentNamespace.GetGetMethod());
     ilg.Emit(OpCodes.Ldstr, _c);
     ilg.Emit(OpCodes.Call, Compiler.Method_RT_classForName);
     ilg.Emit(OpCodes.Call, Compiler.Method_Namespace_importClass1);
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #5
0
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     _expr.Emit(RHC.Expression, objx, ilg);
     ilg.Emit(OpCodes.Castclass, typeof(IObj));
     _meta.Emit(RHC.Expression, objx, ilg);
     ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
     ilg.EmitCall(Compiler.Method_IObj_withMeta);
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #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
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     ilg.Emit(OpCodes.Call, Compiler.Method_Compiler_CurrentNamespace.GetGetMethod());
     ilg.Emit(OpCodes.Ldstr, _c);
     ilg.Emit(OpCodes.Call, Compiler.Method_RT_classForName);
     ilg.Emit(OpCodes.Call, Compiler.Method_Namespace_importClass1);
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #8
0
ファイル: MetaExpr.cs プロジェクト: terkhorn/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     _expr.Emit(RHC.Expression, objx, ilg);
     ilg.Emit(OpCodes.Castclass, typeof(IObj));
     _meta.Emit(RHC.Expression, objx, ilg);
     ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
     ilg.EmitCall(Compiler.Method_IObj_withMeta);
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #9
0
ファイル: HostExpr.cs プロジェクト: rpete4130/clojure-clr
        internal static void EmitBoxReturn(ObjExpr objx, CljILGen ilg, Type returnType)

        {
            if (returnType == typeof(void))
            {
                ilg.Emit(OpCodes.Ldnull);
            }
            else if (returnType.IsPrimitive || returnType.IsValueType)
            {
                ilg.Emit(OpCodes.Box, returnType);
            }
        }
コード例 #10
0
        private void DefineBaseClassClosedOverConstructors(Type super, TypeBuilder tb)
        {
            // ctor that takes closed-overs and does nothing
            if (CtorTypes().Length > 0)
            {
                ConstructorBuilder cb  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
                CljILGen           ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));

                // store closed-overs in their fields
                int a = 0;

                for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
                {
                    FieldBuilder fb         = ClosedOverFields[a];
                    bool         isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]);

                    ilg.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
                    ilg.EmitLoadArg(a + 1);         // gen.Emit(OpCodes.Ldarg, a + 1);
                    ilg.MaybeEmitVolatileOp(isVolatile);
                    ilg.Emit(OpCodes.Stfld, fb);
                }
                ilg.Emit(OpCodes.Ret);

                if (AltCtorDrops > 0)
                {
                    Type[] ctorTypes = CtorTypes();
                    int    newLen    = ctorTypes.Length - AltCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                        {
                            altCtorTypes[i] = ctorTypes[i];
                        }
                        ConstructorBuilder cb2  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen           ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                        {
                            ilg2.EmitLoadArg(i + 1);
                        }
                        for (int i = 0; i < AltCtorDrops; i++)
                        {
                            ilg2.EmitNull();
                        }
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }
        }
コード例 #11
0
        public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            GenContext.EmitDebugInfo(ilg, _spanMap);
            if (_tinfo.IsLiteral)
            {
                // literal fields need to be inlined directly in here... We use GetRawConstant
                // which will work even in partial trust if the constant is protected.
                object value = _tinfo.GetRawConstantValue();
                switch (Type.GetTypeCode(_tinfo.FieldType))
                {
                case TypeCode.Boolean:
                    if ((bool)value)
                    {
                        ilg.Emit(OpCodes.Ldc_I4_1);
                    }
                    else
                    {
                        ilg.Emit(OpCodes.Ldc_I4_0);
                    }
                    break;

                case TypeCode.Byte: ilg.EmitInt((int)(byte)value); break;

                case TypeCode.Char: ilg.EmitInt((int)(char)value); break;

                case TypeCode.Double: ilg.EmitDouble((double)value); break;

                case TypeCode.Int16: ilg.EmitInt((int)(short)value); break;

                case TypeCode.Int32: ilg.EmitInt((int)value); break;

                case TypeCode.Int64: ilg.EmitLong((long)value); break;

                case TypeCode.SByte: ilg.EmitInt((int)(sbyte)value); break;

                case TypeCode.Single: ilg.EmitSingle((float)value); break;

                case TypeCode.String: ilg.EmitString((string)value); break;

                case TypeCode.UInt16: ilg.EmitInt((int)(ushort)value); break;

                case TypeCode.UInt32: ilg.Emit(OpCodes.Ldc_I4, (uint)value); break;

                case TypeCode.UInt64: ilg.Emit(OpCodes.Ldc_I8, (ulong)value); break;
                }
            }
            else
            {
                ilg.MaybeEmitVolatileOp(_tinfo);
                ilg.EmitFieldGet(_tinfo);
            }
        }
コード例 #12
0
ファイル: ObjMethod.cs プロジェクト: makufiru/clojure-clr
        protected static void EmitBody(ObjExpr objx, CljILGen ilg, Type retType, Expr body)
        {
            MaybePrimitiveExpr be = (MaybePrimitiveExpr)body;

            if (Util.IsPrimitive(retType) && be.CanEmitPrimitive)
            {
                Type bt = Compiler.MaybePrimitiveType(be);
                if (bt == retType)
                {
                    be.EmitUnboxed(RHC.Return, objx, ilg);
                }
                else if (retType == typeof(long) && bt == typeof(int))
                {
                    be.EmitUnboxed(RHC.Return, objx, ilg);
                    ilg.Emit(OpCodes.Conv_I8);
                }
                else if (retType == typeof(double) && bt == typeof(float))
                {
                    be.EmitUnboxed(RHC.Return, objx, ilg);
                    ilg.Emit(OpCodes.Conv_R8);
                }
                else if (retType == typeof(int) && bt == typeof(long))
                {
                    be.EmitUnboxed(RHC.Return, objx, ilg);
                    ilg.Emit(OpCodes.Call, Compiler.Method_RT_intCast_long);
                }
                else if (retType == typeof(float) && bt == typeof(double))
                {
                    be.EmitUnboxed(RHC.Return, objx, ilg);
                    ilg.Emit(OpCodes.Conv_R4);
                }
                else
                {
                    throw new ArgumentException(String.Format("Mismatched primitive return, expected: {0}, had: {1}", retType, be.ClrType));
                }
            }
            else
            {
                body.Emit(RHC.Return, objx, ilg);
                if (body.HasNormalExit())
                {
                    if (retType == typeof(void))
                    {
                        ilg.Emit(OpCodes.Pop);
                    }
                    else
                    {
                        EmitUnboxArg(ilg, typeof(object), retType);
                    }
                }
            }
        }
コード例 #13
0
 private void EmitKeywordCallsiteInits(CljILGen ilg)
 {
     for (int i = 0; i < KeywordCallsites.count(); i++)
     {
         Keyword k = (Keyword)KeywordCallsites.nth(i);
         EmitValue(k, ilg);
         ilg.Emit(OpCodes.Newobj, Compiler.Ctor_KeywordLookupSite_1);
         ilg.Emit(OpCodes.Dup);
         ilg.Emit(OpCodes.Stsfld, _keywordLookupSiteFields[i]);
         ilg.Emit(OpCodes.Castclass, typeof(ILookupThunk));
         ilg.Emit(OpCodes.Stsfld, _thunkFields[i]);
     }
 }
コード例 #14
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);
            }
        }
コード例 #15
0
        internal static void EmitArgsAsArray(IPersistentVector args, ObjExpr objx, CljILGen ilg)
        {
            ilg.EmitInt(args.count());
            ilg.Emit(OpCodes.Newarr, typeof(Object));

            for (int i = 0; i < args.count(); i++)
            {
                ilg.Emit(OpCodes.Dup);
                ilg.EmitInt(i);
                ((Expr)args.nth(i)).Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Stelem_Ref);
            }
        }
コード例 #16
0
ファイル: ThrowExpr.cs プロジェクト: nasser/Clojure.Runtime
 public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_excExpr == null)
     {
         ilg.Emit(OpCodes.Rethrow);
     }
     else
     {
         _excExpr.Emit(RHC.Expression, objx, ilg);
         ilg.Emit(OpCodes.Castclass, typeof(Exception));
         ilg.Emit(OpCodes.Throw);
     }
 }
コード例 #17
0
ファイル: ThrowExpr.cs プロジェクト: mjmcaulay/clojure-clr
 public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_excExpr == null)
     {
         ilg.Emit(OpCodes.Rethrow);
     }
     else
     {
         _excExpr.Emit(RHC.Expression, objx, ilg);
         ilg.Emit(OpCodes.Castclass, typeof(Exception));
         ilg.Emit(OpCodes.Throw);
     }
 }
コード例 #18
0
        static public void EmitDynamicCallPostlude(LambdaExpression lambda, Type delType, MethodBuilder mbLambda, CljILGen ilg)
        {
            if (!(Compiler.CompilerContextVar.deref() is GenContext))
            {
                // light compile

                MethodInfo mi = delType.GetMethod("Invoke");
                ilg.Emit(OpCodes.Callvirt, mi);
            }
            else
            {
                ilg.Emit(OpCodes.Call, mbLambda);
            }
        }
コード例 #19
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
 internal void EmitVarValue(CljILGen ilg, Var v)
 {
     int i = (int)Vars.valAt(v);
     if ( !v.isDynamic() )
     {
         EmitConstant(ilg, i, v);
         ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot);
     }
     else
     {
         EmitConstant(ilg, i, v);
         ilg.Emit(OpCodes.Call, Compiler.Method_Var_get);  // or just Method_Var_get??
     }
 }
コード例 #20
0
 public static void EmitByRefArg(HostArg ha, ObjExpr objx, CljILGen ilg)
 {
     if (ha.LocalBinding.IsArg)
     {
         ilg.Emit(OpCodes.Ldarga, ha.LocalBinding.Index);
     }
     else if (ha.LocalBinding.IsThis)
     {
         ilg.Emit(OpCodes.Ldarga, 0);
     }
     else
     {
         ilg.Emit(OpCodes.Ldloca, ha.LocalBinding.LocalVar);
     }
 }
コード例 #21
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);
                }
            }
        }
コード例 #22
0
        public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            _expr.Emit(RHC.Expression, objx, ilg);

            // This corresponds to the most general case code in System.Linq.Expressions.Compiler.LambdaCompiler

            Type opType = _expr.HasClrType && _expr.ClrType != null ? _expr.ClrType : typeof(object);

            if (opType.IsValueType)
            {
                ilg.Emit(OpCodes.Box, opType);
            }
            ilg.Emit(OpCodes.Isinst, _t);
            ilg.Emit(OpCodes.Ldnull);
            ilg.Emit(OpCodes.Cgt_Un);
        }
コード例 #23
0
 void EmitThenForHashes(ObjExpr objx, CljILGen ilg, Expr test, Expr then, Label defaultLabel, bool emitUnboxed)
 {
     _expr.Emit(RHC.Expression, objx, ilg);
     test.Emit(RHC.Expression, objx, ilg);
     if (_testType == _hashIdentityKey)
     {
         ilg.Emit(OpCodes.Ceq);
         ilg.Emit(OpCodes.Brfalse, defaultLabel);
     }
     else
     {
         ilg.Emit(OpCodes.Call, Compiler.Method_Util_equiv);
         ilg.Emit(OpCodes.Brfalse, defaultLabel);
     }
     EmitExpr(objx, ilg, then, emitUnboxed);
 }
コード例 #24
0
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_coll is IPersistentList || _coll is LazySeq) // JVM does not include LazySeq test.  I'm getting it in some places.  LazySeq of 0 size got us here, we'll treat as an empty list
     {
         ilg.EmitFieldGet(ListEmptyFI);
     }
     else if (_coll is IPersistentVector)
     {
         ilg.EmitFieldGet(VectorEmptyFI);
     }
     else if (_coll is IPersistentMap)
     {
         ilg.EmitFieldGet(HashMapEmptyFI);
     }
     else if (_coll is IPersistentSet)
     {
         ilg.EmitFieldGet(HashSetEmptyFI);
     }
     else
     {
         throw new InvalidOperationException("Unknown collection type.");
     }
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #25
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);
 }
コード例 #26
0
        public override void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, ReturnType, ArgTypes);

            SetCustomAttributes(mb);

            CljILGen ilg       = new CljILGen(mb.GetILGenerator());
            Label    loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));
                ilg.MarkLabel(loopLabel);
                EmitBody(Objx, ilg, _retType, Body);
                if (Body.HasNormalExit())
                {
                    ilg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
            {
                tb.DefineMethodOverride(mb, ExplicitMethodInfo);
            }
        }
コード例 #27
0
ファイル: FnMethod.cs プロジェクト: nasser/Clojure.Runtime
        private void DoEmit(ObjExpr fn, TypeBuilder tb)
        {
            MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;
            MethodBuilder    mb      = tb.DefineMethod(MethodName, attribs, ReturnType, ArgTypes);

            SetCustomAttributes(mb);

            CljILGen baseIlg = new CljILGen(mb.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                Body.Emit(RHC.Return, fn, baseIlg);
                if (Body.HasNormalExit())
                {
                    baseIlg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
            {
                tb.DefineMethodOverride(mb, ExplicitMethodInfo);
            }
        }
コード例 #28
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
        private void EmitMetaFunctions(TypeBuilder fnTB)
        {
            // IPersistentMap meta()
            MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes);
            CljILGen gen = new CljILGen(metaMB.GetILGenerator());
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitFieldGet(MetaField);
            }
            else
                gen.EmitNull();
            gen.Emit(OpCodes.Ret);

            // IObj withMeta(IPersistentMap)
            MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) });
            gen = new CljILGen(withMB.GetILGenerator());

            if (SupportsMeta)
            {
                gen.EmitLoadArg(1);   // meta arg
                foreach (FieldBuilder fb in ClosedOverFields)
                {
                    gen.EmitLoadArg(0);
                    gen.MaybeEmitVolatileOp(fb);
                    gen.EmitFieldGet(fb);
                }

                gen.EmitNew(CtorInfo);
            }
            else
                gen.EmitLoadArg(0);  //this
            gen.Emit(OpCodes.Ret);
        }
コード例 #29
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);
            }

            //if ( rhc == RHC.Return )
            //{
            //    ObjMethod2 method = (ObjMethod2)Compiler.MethodVar.deref();
            //    method.EmitClearLocals(context);
            //}

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

            ilg.Emit(OpCodes.Callvirt, mi);
        }
コード例 #30
0
ファイル: NewExpr.cs プロジェクト: terkhorn/clojure-clr
        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);
            }
        }
コード例 #31
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);
        }
コード例 #32
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
 private void EmitLoadNsInitForDeftype(CljILGen ilg)
 {
     string nsname = ((Symbol)RT.second(Src)).Namespace;
     if ( !nsname.Equals("clojure.core"))
     {
         ilg.EmitString("clojure.core");
         ilg.EmitString("require");
         ilg.EmitCall(Compiler.Method_RT_var2);
         ilg.EmitCall(Compiler.Method_Var_getRawRoot);
         ilg.Emit(OpCodes.Castclass, typeof(IFn));
         ilg.EmitNull();
         ilg.EmitString(nsname);
         ilg.EmitCall(Compiler.Method_Symbol_intern2);
         ilg.EmitCall(Compiler.Methods_IFn_invoke[1]);
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #33
0
 public override void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     objx.EmitKeyword(ilg, _kw);
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #34
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
        private void EmitListAsObjectArray(object value, CljILGen ilg)
        {
            ICollection coll = (ICollection)value;

            ilg.EmitInt(coll.Count);
            ilg.Emit(OpCodes.Newarr, typeof(Object));

            int i = 0;
            foreach (Object item in coll)
            {
                ilg.Emit(OpCodes.Dup);
                ilg.EmitInt(i++);
                EmitValue(item, ilg);
                //HostExpr.EmitBoxReturn(this, ilg, item.GetType());
                ilg.Emit(OpCodes.Stelem_Ref);
            }
        }
コード例 #35
0
        static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, List <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;

            if (context != null && context.DynInitHelper != null)
            {
                call = context.DynInitHelper.ReduceDyn(dyn);
            }

            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);
            }
        }
コード例 #36
0
ファイル: NewExpr.cs プロジェクト: terkhorn/clojure-clr
        private void EmitTargetExpression(ObjExpr objx, CljILGen ilg)
        {
            if (Compiler.CompileStubOrigClassVar.isBound && Compiler.CompileStubOrigClassVar.deref() != null && objx.TypeBlder != null)
            {
                ilg.Emit(OpCodes.Ldtoken, objx.TypeBlder);
            }
            else if (_type != null)
            {
                ilg.Emit(OpCodes.Ldtoken, _type);
            }
            else
            {
                throw new ArgumentException("Cannot generate type for NewExpr. Serious!");
            }

            ilg.Emit(OpCodes.Call, Compiler.Method_Type_GetTypeFromHandle);
        }
コード例 #37
0
ファイル: TheVarExpr.cs プロジェクト: terkhorn/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     objx.EmitVar(ilg, _var);
     if (rhc == RHC.Statement)
     {
         ilg.Emit(OpCodes.Pop);
     }
 }
コード例 #38
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);
        }
コード例 #39
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);
        }
コード例 #40
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);
        }
コード例 #41
0
ファイル: EmptyExpr.cs プロジェクト: stuman08/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_coll is IPersistentList)
         ilg.EmitFieldGet(ListEmptyFI);
     else if (_coll is IPersistentVector)
         ilg.EmitFieldGet(VectorEmptyFI);
     else if (_coll is IPersistentMap)
         ilg.EmitFieldGet(HashMapEmptyFI);
     else if (_coll is IPersistentSet)
         ilg.EmitFieldGet(HashSetEmptyFI);
     else
         throw new InvalidOperationException("Unknown collection type.");
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #42
0
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     if (_coll is IPersistentList || _coll is LazySeq) // JVM does not include LazySeq test.  I'm getting it in some places.  LazySeq of 0 size got us here, we'll treat as an empty list
         ilg.EmitFieldGet(ListEmptyFI);
     else if (_coll is IPersistentVector)
         ilg.EmitFieldGet(VectorEmptyFI);
     else if (_coll is IPersistentMap)
         ilg.EmitFieldGet(HashMapEmptyFI);
     else if (_coll is IPersistentSet)
         ilg.EmitFieldGet(HashSetEmptyFI);
     else
         throw new InvalidOperationException("Unknown collection type.");
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #43
0
ファイル: InstanceOfExpr.cs プロジェクト: JvJ/clojure-clr
        public void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            _expr.Emit(RHC.Expression, objx, ilg);

            // This corresponds to the most general case code in System.Linq.Expressions.Compiler.LambdaCompiler

            Type opType = _expr.HasClrType && _expr.ClrType != null ? _expr.ClrType : typeof(object);
            if (opType.IsValueType)
            {
                ilg.Emit(OpCodes.Box, opType);
            }
            ilg.Emit(OpCodes.Isinst, _t);
            ilg.Emit(OpCodes.Ldnull);
            ilg.Emit(OpCodes.Cgt_Un);
        }
コード例 #44
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals)
        {
            if (_typeBuilder != null)
            {
                // Full compile
                ilg.Emit(OpCodes.Castclass, _typeBuilder);

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    if (letFnLocals.contains(lb))
                    {
                        FieldBuilder fb;
                        _closedOverFieldsMap.TryGetValue(lb, out fb);

                        Type primt = lb.PrimitiveType;
                        ilg.Emit(OpCodes.Dup);  // this
                        if (primt != null)
                        {
                            objx.EmitUnboxedLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                        else
                        {
                            objx.EmitLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                    }
                }
                ilg.Emit(OpCodes.Pop);
            }
        }
コード例 #45
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private void EmitStaticConstructorBody(CljILGen ilg)
        {
            GenContext.EmitDebugInfo(ilg, SpanMap);

            if (Constants.count() > 0)
                EmitConstantFieldInits(ilg);

            if (KeywordCallsites.count() > 0)
                EmitKeywordCallsiteInits(ilg);

            ilg.Emit(OpCodes.Ret);
        }
コード例 #46
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        void EmitSwapThunk(TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod("swapThunk", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(int), typeof(ILookupThunk) });
            CljILGen ilg = new CljILGen(mb.GetILGenerator());

            Label endLabel = ilg.DefineLabel();
            Label[] labels = new Label[KeywordCallsites.count()];
            for (int i = 0; i < KeywordCallsites.count(); i++)
                labels[i] = ilg.DefineLabel();

            ilg.EmitLoadArg(1);
            ilg.Emit(OpCodes.Switch, labels);
            ilg.Emit(OpCodes.Br, endLabel);

            for (int i = 0; i < KeywordCallsites.count(); i++)
            {
                ilg.MarkLabel(labels[i]);
                ilg.EmitLoadArg(2);
                ilg.EmitFieldSet(_thunkFields[i]);
                ilg.Emit(OpCodes.Br, endLabel);
            }

            ilg.MarkLabel(endLabel);
            ilg.Emit(OpCodes.Ret);
        }
コード例 #47
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private void EmitConstantFieldInits(CljILGen ilg)
        {
            try
            {
                Var.pushThreadBindings(RT.map(RT.PrintDupVar, true));

                for (int i = 0; i < Constants.count(); i++)
                {
                    if (ConstantFields[i] != null)
                    {
                        EmitValue(Constants.nth(i), ilg);
                        if ( Constants.nth(i).GetType() != ConstantType(i) )
                            ilg.Emit(OpCodes.Castclass, ConstantType(i));
                        FieldBuilder fb = ConstantFields[i];
                        ilg.Emit(OpCodes.Stsfld,fb);
                    }
                }
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
コード例 #48
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        protected void EmitValue(object value, CljILGen ilg)
        {
            bool partial = true;

            if (value == null)
                ilg.Emit(OpCodes.Ldnull);
            else if (value is String)
                ilg.Emit(OpCodes.Ldstr, (String)value);
            else if (value is Boolean)
            {
                ilg.EmitBoolean((Boolean)value);
                ilg.Emit(OpCodes.Box,typeof(bool));
            }
            else if (value is Int32)
            {
                ilg.EmitInt((int)value);
                ilg.Emit(OpCodes.Box, typeof(int));
            }
            else if (value is Int64)
            {
                ilg.EmitLong((long)value);
                ilg.Emit(OpCodes.Box, typeof(long));
            }
            else if (value is Double)
            {
                ilg.EmitDouble((double)value);
                ilg.Emit(OpCodes.Box, typeof(double));
            }
            else if (value is Char)
            {
                ilg.EmitChar((char)value);
                ilg.Emit(OpCodes.Box,typeof(char));
            }
            else if (value is Type)
            {
                Type t = (Type)value;
                if (t.IsValueType)
                    ilg.EmitType(t);
                else
                {
                    //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName));
                    ilg.EmitString(((Type)value).FullName);
                    ilg.EmitCall(Compiler.Method_RT_classForName);
                }
            }
            else if (value is Symbol)
            {
                Symbol sym = (Symbol)value;
                if (sym.Namespace == null)
                    ilg.EmitNull();
                else
                    ilg.EmitString(sym.Namespace);
                ilg.EmitString(sym.Name);
                ilg.EmitCall(Compiler.Method_Symbol_intern2);
            }
            else if (value is Keyword)
            {
                Keyword keyword = (Keyword)value;
                if (keyword.Namespace == null)
                    ilg.EmitNull();
                else
                    ilg.EmitString(keyword.Namespace);
                ilg.EmitString(keyword.Name);
                ilg.EmitCall(Compiler.Method_RT_keyword);
            }
            else if (value is Var)
            {
                Var var = (Var)value;
                ilg.EmitString(var.Namespace.Name.ToString());
                ilg.EmitString(var.Symbol.Name.ToString());
                ilg.EmitCall(Compiler.Method_RT_var2);
            }
            else if (value is IType)
            {
                IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes);

                for (ISeq s = RT.seq(fields); s != null; s = s.next())
                {
                    Symbol field = (Symbol)s.first();
                    Type k = Compiler.TagType(Compiler.TagOf(field));
                    object val = Reflector.GetInstanceFieldOrProperty(value, field.Name);
                    EmitValue(val, ilg);
                    if (k.IsPrimitive)
                    {
                        ilg.Emit(OpCodes.Castclass, k);
                    }

                }

                ConstructorInfo cinfo = value.GetType().GetConstructors()[0];
                ilg.EmitNew(cinfo);
            }
            else if (value is IRecord)
            {
                //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public);
                EmitValue(PersistentArrayMap.create((IDictionary)value), ilg);

                MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null);
                ilg.EmitCall(createMI);
            }
            else if (value is IPersistentMap)
            {
                IPersistentMap map = (IPersistentMap)value;
                List<object> entries = new List<object>(map.count() * 2);
                foreach (IMapEntry entry in map)
                {
                    entries.Add(entry.key());
                    entries.Add(entry.val());
                }
                EmitListAsObjectArray(entries, ilg);
                ilg.EmitCall(Compiler.Method_RT_map);
            }
            else if (value is IPersistentVector)
            {
                EmitListAsObjectArray(value, ilg);
                ilg.EmitCall(Compiler.Method_RT_vector);
            }
            else if (value is PersistentHashSet)
            {
                ISeq vs = RT.seq(value);
                if (vs == null)
                    ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY);
                else
                {
                    EmitListAsObjectArray(vs, ilg);
                    ilg.EmitCall(Compiler.Method_PersistentHashSet_create);
                }
            }
            else if (value is ISeq || value is IPersistentList)
            {
                EmitListAsObjectArray(value, ilg);
                ilg.EmitCall(Compiler.Method_PersistentList_create);
            }
            else if (value is Regex)
            {
                ilg.EmitString(((Regex)value).ToString());
                ilg.EmitNew(Compiler.Ctor_Regex_1);
            }
            else
            {
                string cs = null;
                try
                {
                    cs = RT.printString(value);
                }
                catch (Exception)
                {
                    throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value));
                }
                if (cs.Length == 0)
                    throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value));
                if (cs.StartsWith("#<"))
                    throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs));

                ilg.EmitString(cs);
                ilg.EmitCall(Compiler.Method_RT_readString);
                partial = false;
            }

            if (partial)
            {
                if (value is IObj && RT.count(((IObj)value).meta()) > 0)
                {
                    ilg.Emit(OpCodes.Castclass, typeof(IObj));
                    Object m = ((IObj)value).meta();
                    EmitValue(Compiler.ElideMeta(m), ilg);
                    ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                    ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta);
                }
            }
        }
コード例 #49
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        protected static void EmitHasArityMethod(TypeBuilder tb, IList<int> arities, bool isVariadic, int reqArity)
        {
            // TODO: Convert to a Switch instruction
            MethodBuilder mb = tb.DefineMethod(
                "HasArity",
                MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(bool),
                new Type[] { typeof(int) });

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

            Label falseLabel = gen.DefineLabel();
            Label trueLabel = gen.DefineLabel();

            if (isVariadic)
            {
                gen.EmitLoadArg(1);
                gen.EmitInt(reqArity);
                gen.Emit(OpCodes.Bge, trueLabel);
            }

            if (arities != null)
            {
                foreach (int i in arities)
                {
                    gen.EmitLoadArg(1);
                    gen.EmitInt(i);
                    gen.Emit(OpCodes.Beq, trueLabel);
                }
            }

            gen.MarkLabel(falseLabel);
            gen.EmitBoolean(false);
            gen.Emit(OpCodes.Ret);

            gen.MarkLabel(trueLabel);
            gen.EmitBoolean(true);
            gen.Emit(OpCodes.Ret);
        }
コード例 #50
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
 internal void EmitVarValue(CljILGen ilg, Var v)
 {
     int i = (int)Vars.valAt(v);
     if ( !v.isDynamic() )
     {
         EmitConstant(ilg, i, v);
         ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot);
     }
     else
     {
         EmitConstant(ilg, i, v);
         ilg.Emit(OpCodes.Call, Compiler.Method_Var_get);  // or just Method_Var_get??
     }
 }
コード例 #51
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         ilg.Emit(OpCodes.Ldarg_0); // this
         FieldBuilder fb = _closedOverFieldsMap[lb];
         ilg.MaybeEmitVolatileOp(IsVolatile(lb));
         ilg.Emit(OpCodes.Ldfld, fb);
     }
     else if (lb.IsArg)
     {
         //int argOffset = IsStatic ? 0 : 1;
         //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);
 }
コード例 #52
0
ファイル: TheVarExpr.cs プロジェクト: TerabyteX/clojure-clr
 public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
 {
     objx.EmitVar(ilg, _var);
     if (rhc == RHC.Statement)
         ilg.Emit(OpCodes.Pop);
 }
コード例 #53
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
 internal void EmitConstant(CljILGen ilg, int id, object val)
 {
     FieldBuilder fb = null;
     if ( ConstantFields != null && ConstantFields.TryGetValue(id, out fb))
     {
         ilg.MaybeEmitVolatileOp(fb);
         ilg.Emit(OpCodes.Ldsfld, fb);
     }
     else
         EmitValue(val, ilg);
 }
コード例 #54
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val)
        {
            if (!IsMutable(lb))
                throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name);

            FieldBuilder fb = null;
            bool hasField = _closedOverFieldsMap.TryGetValue(lb, out fb);

            ilg.Emit(OpCodes.Ldarg_0);  // this

            Type primt = lb.PrimitiveType;
            if (primt != null)
            {
                MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr;
                if (!(mbe != null && mbe.CanEmitPrimitive))
                    throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name);
                mbe.EmitUnboxed(RHC.Expression, this, ilg);

            }
            else
            {
                val.Emit(RHC.Expression, this, ilg);
            }

            if (hasField)
            {
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Stfld, fb);
            }
            else
                ilg.Emit(OpCodes.Stloc, lb.LocalVar);
        }
コード例 #55
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        public MethodBuilder EmitConstants(TypeBuilder fnTB)
        {
            try
            {
                Var.pushThreadBindings(RT.map(RT.PrintDupVar, true));

                MethodBuilder mb = fnTB.DefineMethod(StaticCtorHelperName + "_constants", MethodAttributes.Private | MethodAttributes.Static);
                CljILGen ilg = new CljILGen(mb.GetILGenerator());

                for (int i = 0; i < Constants.count(); i++)
                {
                    FieldBuilder fb;
                    if (ConstantFields.TryGetValue(i, out fb))
                    {
                        EmitValue(Constants.nth(i), ilg);
                        if (Constants.nth(i).GetType() != ConstantType(i))
                            ilg.Emit(OpCodes.Castclass, ConstantType(i));
                        ilg.Emit(OpCodes.Stsfld, fb);
                    }
                }
                ilg.Emit(OpCodes.Ret);

                return mb;
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
コード例 #56
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        public virtual void Emit(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

            if (IsDefType)
                ilg.Emit(OpCodes.Ldnull);
            else
            {
                if (SupportsMeta)
                {
                    ilg.Emit(OpCodes.Ldnull);
                    ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                }

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    if (lb.PrimitiveType != null)
                        objx.EmitUnboxedLocal(ilg, lb);
                    else
                        objx.EmitLocal(ilg, lb);
                }

                ilg.Emit(OpCodes.Newobj, _ctorInfo);
            }

            if (rhc == RHC.Statement)
                ilg.Emit(OpCodes.Pop);
        }
コード例 #57
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private void EmitMetaFunctions(TypeBuilder fnTB)
        {
            // IPersistentMap meta()
            MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes);
            CljILGen gen = new CljILGen(metaMB.GetILGenerator());
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitFieldGet(_metaField);
            }
            else
                gen.EmitNull();
            gen.Emit(OpCodes.Ret);

            // IObj withMeta(IPersistentMap)
            MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) });
            gen = new CljILGen(withMB.GetILGenerator());

            if (SupportsMeta)
            {
                gen.EmitLoadArg(1);   // meta arg
                foreach (FieldBuilder fb in _closedOverFields)
                {
                    gen.EmitLoadArg(0);
                    gen.MaybeEmitVolatileOp(fb);
                    gen.EmitFieldGet(fb);
                }

                gen.EmitNew(_ctorInfo);
            }
            else
                gen.EmitLoadArg(0);  //this
            gen.Emit(OpCodes.Ret);
        }
コード例 #58
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        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);
            }
        }
コード例 #59
0
ファイル: RecurExpr.cs プロジェクト: stuman08/clojure-clr
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label loopLabel = (Label)Compiler.LoopLabelVar.deref();
            if (loopLabel == null)
                throw new InvalidOperationException("Recur not in proper context.");

            {
                for (int i = 0; i < _loopLocals.count(); i++)
                {
                    LocalBinding lb = (LocalBinding)_loopLocals.nth(i);
                    Expr arg = (Expr)_args.nth(i);

                    Type primt = lb.PrimitiveType;
                    if (primt != null)
                    {
                        MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr;
                        Type pt = Compiler.MaybePrimitiveType(arg);
                        if (pt == primt)
                        {
                            mpeArg.EmitUnboxed(RHC.Expression, objx, ilg);
                        }
                        else if (primt == typeof(long) && pt == typeof(int))
                        {
                            mpeArg.EmitUnboxed(RHC.Expression, objx, ilg);
                            ilg.Emit(OpCodes.Conv_I8);
                        }
                        else if (primt == typeof(double) && pt == typeof(float))
                        {
                            mpeArg.EmitUnboxed(RHC.Expression, objx, ilg);
                            ilg.Emit(OpCodes.Conv_R8);
                        }
                        else if (primt == typeof(int) && pt == typeof(long))
                        {
                            mpeArg.EmitUnboxed(RHC.Expression, objx, ilg);
                            ilg.EmitCall(Compiler.Method_RT_intCast_long);

                        }
                        else if (primt == typeof(float) && pt == typeof(double))
                        {
                            mpeArg.EmitUnboxed(RHC.Expression, objx, ilg);
                            ilg.Emit(OpCodes.Conv_R4);
                        }
                        else
                        {
                            throw new ArgumentException(String.Format(
                                    "{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}",
                                    _source, _spanMap != null ? (int)_spanMap.valAt(RT.StartLineKey, 0) : 0,
                                    lb.Name, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name));
                        }

                    }
                    else
                    {
                        arg.Emit(RHC.Expression, objx, ilg);
                    }

                }
            }
            for (int i = _loopLocals.count() - 1; i >= 0; i--)
            {
                LocalBinding lb = (LocalBinding)_loopLocals.nth(i);
                Type primt = lb.PrimitiveType;
                if (lb.IsArg)
                    //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1));
                    ilg.EmitStoreArg(lb.Index);
                else
                {
                    ilg.Emit(OpCodes.Stloc, lb.LocalVar);
                }
            }

            ilg.Emit(OpCodes.Br, loopLabel);
            //if (rhc != RHC.Statement)
            //    ilg.Emit(OpCodes.Ldnull);
        }
コード例 #60
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private ConstructorBuilder EmitNonMetaConstructor(TypeBuilder fnTB, Type baseType)
        {
            Type[] ctorTypes = CtorTypes();
            Type[] noMetaCtorTypes = new Type[ctorTypes.Length - 1];
            for (int i = 1; i < ctorTypes.Length; i++)
                noMetaCtorTypes[i - 1] = ctorTypes[i];

            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, noMetaCtorTypes);
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            gen.EmitLoadArg(0);
            gen.EmitNull();     // null meta
            for (int i = 0; i < noMetaCtorTypes.Length; i++)
                gen.EmitLoadArg(i + 1);
            gen.Emit(OpCodes.Call, _ctorInfo);
            gen.Emit(OpCodes.Ret);

            return cb;
        }