示例#1
0
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                ilg.Emit(OpCodes.Ldarg_0); // this
                FieldBuilder fb = ClosedOverFieldsMap[lb];
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Ldfld, fb);
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
                // TODO: ONCEONLY?
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
            }
        }
示例#2
0
        void EmitClosedOverFields(TypeBuilder tb)
        {
            _closedOverFields    = new List <FieldBuilder>(Closes.count());
            _closedOverFieldsMap = new Dictionary <LocalBinding, FieldBuilder>(Closes.count());

            // closed-overs map to instance fields.
            for (ISeq s = RT.keys(Closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();

                FieldAttributes attributes   = FieldAttributes.Public;
                bool            markVolatile = IsVolatile(lb);

                if (IsDefType)
                {
                    if (!IsMutable(lb))
                    {
                        attributes |= FieldAttributes.InitOnly;
                    }
                }

                Type type = lb.PrimitiveType ?? typeof(object);

                FieldBuilder fb = markVolatile
                    ? tb.DefineField(lb.Name, type, new Type[] { typeof(IsVolatile) }, Type.EmptyTypes, attributes)
                    : tb.DefineField(lb.Name, type, attributes);

                GenInterface.SetCustomAttributes(fb, GenInterface.ExtractAttributes(RT.meta(lb.Symbol)));

                _closedOverFields.Add(fb);
                _closedOverFieldsMap[lb] = fb;
            }
        }
示例#3
0
        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.Emit(OpCodes.Stfld, fb);
                        }
                        else
                        {
                            objx.EmitLocal(ilg, lb);
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                    }
                }
                ilg.Emit(OpCodes.Pop);
            }
        }
示例#4
0
文件: FnExpr.cs 项目: ryrency/Misc
        Expression GenDlrForFile(GenContext context)
        {
            EnsureTypeBuilt(context);

            //ConstructorInfo ctorInfo = _ctorInfo;
            ConstructorInfo ctorInfo = _fnType.GetConstructors()[0];

            // The incoming context holds info on the containing function.
            // That is the one that holds the closed-over variable values.

            List <Expression> args = new List <Expression>(_closes.count());

            for (ISeq s = RT.keys(_closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();
                if (lb.PrimitiveType != null)
                {
                    args.Add(context.FnExpr.GenUnboxedLocal(context, lb));
                }
                else
                {
                    args.Add(context.FnExpr.GenLocal(context, lb));
                }
            }

            return(Expression.New(ctorInfo, args));
        }
示例#5
0
        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);
        }
示例#6
0
        public virtual Expression GenCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            if (IsDefType)
            {
                return(Expression.Constant(null));
            }

            List <Expression> args = new List <Expression>(_closes.count() + 1);

            if (SupportsMeta)
            {
                args.Add(Expression.Constant(null, typeof(IPersistentMap))); // meta
            }
            for (ISeq s = RT.keys(_closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();
                if (lb.PrimitiveType != null)
                {
                    args.Add(objx.GenUnboxedLocal(context, lb));
                }
                else
                {
                    args.Add(objx.GenLocal(context, lb));
                }
            }

            Expression newExpr = Expression.New(_ctorInfo, args);

            return(newExpr);
        }
示例#7
0
        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);
        }
 public LocalBindingExpr(LocalBinding b, Symbol tag)
 {
     if (b.PrimitiveType != null && _tag != null)
         throw new InvalidOperationException("Can't type hint a primitive local");
     _b = b;
     _tag = tag;
 }
示例#9
0
 public LocalBindingExpr(LocalBinding b, Symbol tag)
 {
     if (b.PrimitiveType != null && _tag != null)
     {
         throw new InvalidOperationException("Can't type hint a primitive local");
     }
     _b   = b;
     _tag = tag;
 }
示例#10
0
 bool IsMutable(LocalBinding lb)
 {
     return(IsVolatile(lb)
            ||
            RT.booleanCast(RT.contains(Fields, lb.Symbol)) &&
            RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("unsynchronized-mutable")))
            ||
            lb.IsByRef);
 }
示例#11
0
文件: FnExpr.cs 项目: ryrency/Misc
        private void GenerateClosedOverFields(TypeBuilder baseTB)
        {
            _closedOverFields = new List <FieldBuilder>(_closes.count());

            // closed-overs map to instance fields.
            for (ISeq s = RT.keys(_closes); s != null; s = s.next())
            {
                LocalBinding lb   = (LocalBinding)s.first();
                Type         type = lb.PrimitiveType ?? typeof(object);
                _closedOverFields.Add(baseTB.DefineField(lb.Name, type, FieldAttributes.FamORAssem));
            }
        }
示例#12
0
文件: FnExpr.cs 项目: ryrency/Misc
        internal Expression GenUnboxedLocal(GenContext context, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (context.Mode == CompilerMode.File && _closes.containsKey(lb))
            {
                return(Expression.Convert(Expression.Field(_thisParam, lb.Name), primType));
            }
            else
            {
                return(lb.ParamExpression);
            }
        }
示例#13
0
        MethodBuilder GenerateStaticMethod(GenContext context)
        {
            string      methodName = GetStaticMethodName();
            FnExpr      fn         = context.FnExpr;
            TypeBuilder tb         = fn.TypeBuilder;

            List <ParameterExpression> parms = new List <ParameterExpression>(_argLocals.count() + 1);

            ParameterExpression thisParm = Expression.Parameter(fn.BaseType, "this");

            _thisBinding.ParamExpression = thisParm;
            fn.ThisParam = thisParm;
            parms.Add(thisParm);

            try
            {
                LabelTarget loopLabel = Expression.Label("top");

                Var.pushThreadBindings(RT.map(Compiler.LOOP_LABEL, loopLabel, Compiler.METHODS, this));



                for (int i = 0; i < _argLocals.count(); i++)
                {
                    LocalBinding        lb   = (LocalBinding)_argLocals.nth(i);
                    ParameterExpression parm = Expression.Parameter(typeof(object), lb.Name);
                    lb.ParamExpression = parm;
                    parms.Add(parm);
                }

                Expression body =
                    Expression.Block(
                        Expression.Label(loopLabel),
                        Compiler.MaybeBox(_body.GenDlr(context)));
                LambdaExpression lambda = Expression.Lambda(body, parms);
                // TODO: Figure out why the Java code nulls all the local variables here.


                // TODO: Cache all the CreateObjectTypeArray values
                MethodBuilder mb = tb.DefineMethod(methodName, MethodAttributes.Static, typeof(object), Compiler.CreateObjectTypeArray(NumParams));

                lambda.CompileToMethod(mb);
                //lambda.CompileToMethod(mb, true);
                return(mb);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
示例#14
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);
                }
            }
        }
示例#15
0
        internal Type[] CtorTypes()
        {
            int i = !SupportsMeta ? 0 : 1;

            Type[] ret = new Type[Closes.count() + i];

            if (SupportsMeta)
                ret[0] = typeof(IPersistentMap);

            for (ISeq s = RT.keys(Closes); s != null; s = s.next(), i++)
            {
                LocalBinding lb = (LocalBinding)s.first();
                ret[i] = lb.PrimitiveType ?? typeof(object);
            }
            return ret;
        }
示例#16
0
        internal Expression GenAssignLocal(GenContext context, LocalBinding lb, Expr val)
        {
            if (!IsMutable(lb))
            {
                throw new ArgumentException("Cannot assign to non-mutable: " + lb.Name);
            }

            FieldBuilder fb;

            if (_closedOverFieldsMap.TryGetValue(lb, out fb))
            {
                return(Expression.Assign(Expression.Field(_thisParam, _closedOverFieldsMap[lb]), val.GenCode(RHC.Expression, this, context)));
            }

            return(Expression.Assign(lb.ParamExpression, val.GenCode(RHC.Expression, this, context)));
        }
示例#17
0
        internal LambdaExpression GenerateImmediateLambda(RHC rhc, ObjExpr objx, GenContext context)
        {
            List <ParameterExpression> parmExprs = new List <ParameterExpression>(_argLocals.count());

            if (_thisBinding != null)
            {
                _thisBinding.ParamExpression = objx.ThisParam;
            }

            try
            {
                LabelTarget loopLabel = Expression.Label("top");

                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                for (int i = 0; i < _argLocals.count(); i++)
                {
                    LocalBinding b = (LocalBinding)_argLocals.nth(i);

                    ParameterExpression pexpr = Expression.Parameter(typeof(object), b.Name);
                    b.ParamExpression = pexpr;
                    parmExprs.Add(pexpr);
                }

                List <Expression> bodyExprs = new List <Expression>();
                //bodyExprs.AddRange(typedParmInitExprs);
                bodyExprs.Add(Expression.Label(loopLabel));
                bodyExprs.Add(Compiler.MaybeBox(_body.GenCode(rhc, objx, context)));


                Expression block;
                //if (typedParmExprs.Count > 0)
                //    block = Expression.Block(typedParmExprs, bodyExprs);
                //else
                block = Expression.Block(bodyExprs);

                return(Expression.Lambda(
                           FuncTypeHelpers.GetFFuncType(parmExprs.Count),
                           block,
                           Objx.ThisName,
                           parmExprs));
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
示例#18
0
文件: FnExpr.cs 项目: ryrency/Misc
 internal Expression GenLocal(GenContext context, LocalBinding lb)
 {
     if (context.Mode == CompilerMode.File && _closes.containsKey(lb))
     {
         Expression expr      = Expression.Field(_thisParam, lb.Name);
         Type       primtType = lb.PrimitiveType;
         if (primtType != null)
         {
             expr = Compiler.MaybeBox(Expression.Convert(expr, primtType));
         }
         return(expr);
     }
     else
     {
         return(lb.ParamExpression);
     }
 }
示例#19
0
文件: FnExpr.cs 项目: ryrency/Misc
        private Type[] CtorTypes()
        {
            if (_closes.count() == 0)
            {
                return(EMPTY_TYPE_ARRAY);
            }

            Type[] ret = new Type[_closes.count()];
            int    i   = 0;

            for (ISeq s = RT.keys(_closes); s != null; s = s.next(), i++)
            {
                LocalBinding lb = (LocalBinding)s.first();
                ret[i] = lb.PrimitiveType ?? typeof(object);
            }
            return(ret);
        }
示例#20
0
        public override Expression GenDlr(GenContext context)
        {
            LabelTarget loopLabel = (LabelTarget)Compiler.LOOP_LABEL.deref();

            if (loopLabel == null)
            {
                throw new InvalidOperationException("Recur not in proper context.");
            }

            int argCount = _args.count();

            List <ParameterExpression> tempVars     = new List <ParameterExpression>(argCount);
            List <Expression>          tempAssigns  = new List <Expression>(argCount);
            List <Expression>          finalAssigns = new List <Expression>(argCount);

            // Evaluate all the init forms into local variables.
            // TODO: Check the typing here.
            for (int i = 0; i < _loopLocals.count(); i++)
            {
                LocalBinding        b       = (LocalBinding)_loopLocals.nth(i);
                Expr                arg     = (Expr)_args.nth(i);
                ParameterExpression tempVar = Expression.Parameter(b.ParamExpression.Type, "__local__" + i);  //asdf-tag
                Expression          valExpr = ((Expr)_args.nth(i)).GenDlr(context);
                tempVars.Add(tempVar);

                if (tempVar.Type == typeof(Object))
                {
                    tempAssigns.Add(Expression.Assign(tempVar, Compiler.MaybeBox(valExpr)));
                }
                else
                {
                    tempAssigns.Add(Expression.Assign(tempVar, Expression.Convert(valExpr, tempVar.Type))); //asdf-tag
                }
                finalAssigns.Add(Expression.Assign(b.ParamExpression, tempVar));                            //asdf-tag
            }

            List <Expression> exprs = tempAssigns;

            exprs.AddRange(finalAssigns);
            exprs.Add(Expression.Goto(loopLabel));
            // need to do this to get a return value in the type inferencing -- else can't use this in a then or else clause.
            exprs.Add(Expression.Constant(null));
            return(Expression.Block(tempVars, exprs));
        }
示例#21
0
        internal static List <HostArg> ParseArgs(ParserContext pcon, ISeq argSeq)
        {
            List <HostArg> args = new List <HostArg>();

            for (ISeq s = argSeq; s != null; s = s.next())
            {
                object arg = s.first();

                HostArg.ParameterType paramType = HostArg.ParameterType.Standard;
                LocalBinding          lb        = null;

                ISeq argAsSeq = arg as ISeq;
                if (argAsSeq != null)
                {
                    Symbol op = RT.first(argAsSeq) as Symbol;
                    if (op != null && op.Equals(ByRefSym))
                    {
                        if (RT.Length(argAsSeq) != 2)
                        {
                            throw new ArgumentException("Wrong number of arguments to {0}", op.Name);
                        }

                        object localArg    = RT.second(argAsSeq);
                        Symbol symLocalArg = localArg as Symbol;
                        if (symLocalArg == null || (lb = Compiler.ReferenceLocal(symLocalArg)) == null)
                        {
                            throw new ArgumentException("Argument to {0} must be a local variable.", op.Name);
                        }

                        paramType = HostArg.ParameterType.ByRef;

                        arg = localArg;
                    }
                }

                Expr expr = Compiler.Analyze(pcon.EvalOrExpr(), arg);

                args.Add(new HostArg(paramType, expr, lb));
            }

            return(args);
        }
示例#22
0
 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);
 }
示例#23
0
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         if (_fnMode == FnMode.Full)
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]);
         }
         else
         {
             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));
             if (lb.PrimitiveType != null)
             {
                 ilg.Emit(OpCodes.Unbox, lb.PrimitiveType);
             }
         }
     }
     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);
     }
 }
示例#24
0
文件: FnExpr.cs 项目: ryrency/Misc
        //private MethodBuilder GenerateConstants(TypeBuilder fnTB, Type baseType)
        //{
        //    try
        //    {
        //        Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T));

        //        List<Expression> inits = new List<Expression>();
        //        for (int i = 0; i < _constants.count(); i++)
        //        {
        //            object o = _constants.nth(i);
        //            string stringValue = null;
        //            if (o is string)
        //                stringValue = (string)o;
        //            else
        //            {
        //                try
        //                {
        //                    stringValue = RT.printString(o);
        //                }
        //                catch (Exception)
        //                {
        //                    throw new Exception(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", o));
        //                }
        //                if (stringValue.Length == 0)
        //                    throw new Exception(String.Format("Can't embed unreadable object in code: " + o));
        //                if (stringValue.StartsWith("#<"))
        //                    throw new Exception(String.Format("Can't embed unreadable object in code: " + stringValue));
        //            }
        //            Expression init =
        //                Expression.Assign(
        //                    Expression.Field(null, baseType, ConstantName(i)),
        //                    Expression.Convert(Expression.Call(Compiler.Method_RT_readString, Expression.Constant(stringValue)),
        //                                       ConstantType(i)));
        //            inits.Add(init);
        //        }
        //        inits.Add(Expression.Default(typeof(void)));

        //        Expression block = Expression.Block(inits);
        //        LambdaExpression lambda = Expression.Lambda(block);
        //        MethodBuilder methodBuilder = fnTB.DefineMethod(STATIC_CTOR_HELPER_NAME, MethodAttributes.Private | MethodAttributes.Static);
        //        lambda.CompileToMethod(methodBuilder);
        //        return methodBuilder;
        //    }
        //    finally
        //    {
        //        Var.popThreadBindings();
        //    }

        //}

        private ConstructorBuilder GenerateConstructor(TypeBuilder fnTB, Type baseType)
        {
            ConstructorBuilder cb  = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
            ILGenerator        gen = cb.GetILGenerator();
            //Call base constructor
            ConstructorInfo baseCtorInfo = baseType.GetConstructor(EMPTY_TYPE_ARRAY);

            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Call, baseCtorInfo);

            int a = 0;

            for (ISeq s = RT.keys(_closes); s != null; s = s.next(), a++)
            {
                LocalBinding lb = (LocalBinding)s.first();
                FieldBuilder fb = _closedOverFields[a];

                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldarg, a + 1);
                gen.Emit(OpCodes.Stfld, fb);
            }
            gen.Emit(OpCodes.Ret);
            return(cb);
        }
示例#25
0
 internal bool IsMutable(LocalBinding lb)
 {
     return IsVolatile(lb)
         ||
         RT.booleanCast(RT.contains(Fields, lb.Symbol)) &&
            RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("unsynchronized-mutable")))
         ||
         lb.IsByRef;
 }
示例#26
0
 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);
 }
示例#27
0
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                ilg.Emit(OpCodes.Ldarg_0); // this
                FieldBuilder fb = _closedOverFieldsMap[lb];
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Ldfld, fb);
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
                // TODO: ONCEONLY?
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
            }
        }
示例#28
0
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms, 
            IPersistentVector fieldSyms, 
            Symbol thisSym,
            string tagName, 
            Symbol className, 
            Symbol typeTag, 
            ISeq methodForms,
            Object frm,
            IPersistentMap opts)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);
            ret.Src = frm;
            ret.Name = className.ToString();
            ret.ClassMeta = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);
            ret.Opts = opts;

            if (thisSym != null)
                ret.ThisName = thisSym.Name;

            if (fieldSyms != null)
            {
                IPersistentMap fmap = PersistentHashMap.EMPTY;
                object[] closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false, false);
                    fmap = fmap.assoc(sym, lb);
                    closesvec[i * 2] = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret.Closes = new PersistentArrayMap(closesvec);
                ret.Fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && (((Symbol)fieldSyms.nth(i)).Name.Equals("__meta") || ((Symbol)fieldSyms.nth(i)).Name.Equals("__extmap")); --i)
                    ret.AltCtorDrops++;
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;
            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                    throw new ParseException("only interfaces are supported, had: " + t.Name);
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary<IPersistentVector, IList<MethodInfo>> overrideables;
            Dictionary<IPersistentVector, IList<MethodInfo>> explicits;
            GatherMethods(superClass, RT.seq(interfaces), out overrideables, out explicits);

            ret._methodMap = overrideables;

  
            GenContext context = Compiler.IsCompiling
                ? Compiler.CompilerContextVar.get() as GenContext
                : (ret.IsDefType
                    ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true)
                    : (Compiler.CompilerContextVar.get() as GenContext
                        ??
                        Compiler.EvalContext));

            GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());

            Type baseClass = ret.CompileBaseClass(genC, superClass, SeqToTypeArray(interfaces), frm);
            Symbol thisTag = Symbol.intern(null, baseClass.FullName);

            try
            {
                Var.pushThreadBindings(
                    RT.mapUniqueKeys(
                        Compiler.ConstantsVar, PersistentVector.EMPTY,
                        Compiler.ConstantIdsVar, new IdentityHashMap(),
                        Compiler.KeywordsVar, PersistentHashMap.EMPTY,
                        Compiler.VarsVar, PersistentHashMap.EMPTY,
                        Compiler.KeywordCallsitesVar, PersistentVector.EMPTY,
                        Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY,
                        Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(),
                        Compiler.NoRecurVar, null,
                        Compiler.CompilerContextVar, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.mapUniqueKeys(
                            Compiler.MethodVar, null,
                            Compiler.LocalEnvVar, ret.Fields,
                            Compiler.CompileStubSymVar, Symbol.intern(null, tagName),
                            Compiler.CompileStubClassVar, baseClass
                            ));
                    ret.HintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret.AltCtorDrops);
                }
                // now (methodname [args] body)*

                ret.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();

                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables, explicits);
                    methods = RT.conj(methods, m);
                }

                ret.Methods = methods;
                ret.Keywords = (IPersistentMap)Compiler.KeywordsVar.deref();
                ret.Vars = (IPersistentMap)Compiler.VarsVar.deref();
                ret.Constants = (PersistentVector)Compiler.ConstantsVar.deref();
                ret.ConstantsID = RT.nextID();
                ret.KeywordCallsites = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                ret.VarCallsites = (IPersistentSet)Compiler.VarCallsitesVar.deref();
            }
            finally
            {
                if (ret.IsDefType)
                    Var.popThreadBindings();
                Var.popThreadBindings();
            }

            // TOD:  Really, the first baseclass here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call.
            // Might be able to flag baseclass classes and not try to convert, leading to a dynsite.

            ret.Compile(baseClass, baseClass, interfaces, false, genC);

            Compiler.RegisterDuplicateType(ret.CompiledType);

            return ret;
        }
示例#29
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
                    FieldBuilder fb = _closedOverFieldsMap[lb];
                    ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                    ilg.Emit(OpCodes.Ldfld, fb);
                    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);
            }
        }
示例#30
0
        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.Value);
        }
示例#31
0
        internal static LocalBinding RegisterLocal(Symbol sym, Symbol tag, Expr init)
        {
            int num = GetAndIncLocalNum();

            LocalBinding b = new LocalBinding(num,sym, tag, init);

            IPersistentMap localsMap = (IPersistentMap)LOCAL_ENV.deref();
            LOCAL_ENV.set(RT.assoc(localsMap,b.Symbol, b));
            FnMethod method = (FnMethod)METHODS.deref();
            method.Locals = (IPersistentMap)RT.assoc(method.Locals,b, b);
            method.IndexLocals = (IPersistentMap)RT.assoc(method.IndexLocals, num, b);
            return b;
        }
示例#32
0
 private static LocalBinding RegisterLocalInternal(Symbol sym, Symbol tag, Expr init, bool isThis, bool isArg, bool isByRef)
 {
     int num = GetAndIncLocalNum();
     LocalBinding b = new LocalBinding(num, sym, tag, init, isThis, isArg, isByRef);
     IPersistentMap localsMap = (IPersistentMap)LocalEnvVar.deref();
     LocalEnvVar.set(RT.assoc(localsMap, b.Symbol, b));
     ObjMethod method = (ObjMethod)MethodVar.deref();
     method.AddLocal(num, b);
     return b;
 }
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms,
            IPersistentVector fieldSyms,
            Symbol thisSym,
            string tagName,
            Symbol className,
            Symbol typeTag,
            ISeq methodForms,
            Object frm)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);
            ret._src = frm;
            ret._name = className.ToString();
            ret._classMeta = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);

            if (thisSym != null)
                ret._thisName = thisSym.Name;

            if (fieldSyms != null)
            {
                IPersistentMap fmap = PersistentHashMap.EMPTY;
                object[] closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false);
                    fmap = fmap.assoc(sym, lb);
                    closesvec[i * 2] = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret._closes = new PersistentArrayMap(closesvec);
                ret._fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i)
                    ret._altCtorDrops++;
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;
            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                    throw new ArgumentException("only interfaces are supported, had: " + t.Name);
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary<IPersistentVector, List<MethodInfo>> overrideables;
            GatherMethods(superClass, RT.seq(interfaces), out overrideables);

            ret._methodMap = overrideables;

            //string[] inames = InterfaceNames(interfaces);

            Type stub = CompileStub(superClass, ret, SeqToTypeArray(interfaces),frm);
            Symbol thisTag = Symbol.intern(null, stub.FullName);
            //Symbol stubTag = Symbol.intern(null,stub.FullName);
            //Symbol thisTag = Symbol.intern(null, tagName);

            // Needs its own GenContext so it has its own DynInitHelper
            // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition
            GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? (ret.IsDefType ? new GenContext("deftype" + RT.nextID().ToString(),".dll",".",true) : Compiler.EvalContext);
            GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());
            //genC.FnCompileMode = FnMode.Full;

            try
            {
                Var.pushThreadBindings(
                    RT.map(
                        Compiler.CONSTANTS, PersistentVector.EMPTY,
                        Compiler.CONSTANT_IDS, new IdentityHashMap(),
                        Compiler.KEYWORDS, PersistentHashMap.EMPTY,
                        Compiler.VARS, PersistentHashMap.EMPTY,
                        Compiler.KEYWORD_CALLSITES, PersistentVector.EMPTY,
                        Compiler.PROTOCOL_CALLSITES, PersistentVector.EMPTY,
                        Compiler.VAR_CALLSITES, PersistentVector.EMPTY,
                        Compiler.COMPILER_CONTEXT, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.map(
                            Compiler.METHOD, null,
                            Compiler.LOCAL_ENV, ret._fields,
                            Compiler.COMPILE_STUB_SYM, Symbol.intern(null, tagName),
                            Compiler.COMPILE_STUB_CLASS, stub
                            ));
                }
                // now (methodname [args] body)*
                // TODO: SourceLocation?
                //ret.line = (Integer)LINE.deref();
                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables);
                    methods = RT.conj(methods, m);
                }

                ret._methods = methods;
                ret.Keywords = (IPersistentMap)Compiler.KEYWORDS.deref();
                ret.Vars = (IPersistentMap)Compiler.VARS.deref();
                ret.Constants = (PersistentVector)Compiler.CONSTANTS.deref();
                ret._constantsID = RT.nextID();
                ret.KeywordCallsites = (IPersistentVector)Compiler.KEYWORD_CALLSITES.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.PROTOCOL_CALLSITES.deref();
                ret.VarCallsites = (IPersistentVector)Compiler.VAR_CALLSITES.deref();
            }
            finally
            {
                if (ret.IsDefType)
                    Var.popThreadBindings();
                Var.popThreadBindings();
            }

            ret.Compile(stub, interfaces, false, genC);
            Compiler.RegisterDuplicateType(ret.CompiledType);

            return ret;
        }
示例#34
0
        internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag)
        {
            // ([args] body ... )

            IPersistentVector parms = (IPersistentVector)RT.first(form);
            ISeq body = RT.next(form);

            try
            {
                FnMethod method = new FnMethod(fn, (ObjMethod)Compiler.MethodVar.deref());
                method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();

                Var.pushThreadBindings(RT.mapUniqueKeys(
                                           Compiler.MethodVar, method,
                                           Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(),
                                           Compiler.LoopLocalsVar, null,
                                           Compiler.NextLocalNumVar, 0));

                method._prim = PrimInterface(parms);
                //if (method._prim != null)
                //    method._prim = method._prim.Replace('.', '/');


                if (retTag is String)
                {
                    retTag = Symbol.intern(null, (string)retTag);
                }
                if (!(retTag is Symbol))
                {
                    retTag = null;
                }
                if (retTag != null)
                {
                    string retStr = ((Symbol)retTag).Name;
                    if (!(retStr.Equals("long") || retStr.Equals("double")))
                    {
                        retTag = null;
                    }
                }
                method._retType = Compiler.TagType(Compiler.TagOf(parms) ?? retTag);

                if (method._retType.IsPrimitive)
                {
                    if (!(method._retType == typeof(double) || method._retType == typeof(long)))
                    {
                        throw new ParseException("Only long and double primitives are supported");
                    }
                }
                else
                {
                    method._retType = typeof(object);
                }

                // register 'this' as local 0
                Compiler.RegisterLocalThis(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null);

                ParamParseState   paramState = ParamParseState.Required;
                IPersistentVector argLocals  = PersistentVector.EMPTY;
                List <Type>       argTypes   = new List <Type>();

                int parmsCount = parms.count();

                for (int i = 0; i < parmsCount; i++)
                {
                    if (!(parms.nth(i) is Symbol))
                    {
                        throw new ParseException("fn params must be Symbols");
                    }
                    Symbol p = (Symbol)parms.nth(i);
                    if (p.Namespace != null)
                    {
                        throw new ParseException("Can't use qualified name as parameter: " + p);
                    }
                    if (p.Equals(Compiler.AmpersandSym))
                    {
                        if (paramState == ParamParseState.Required)
                        {
                            paramState = ParamParseState.Rest;
                        }
                        else
                        {
                            throw new ParseException("Invalid parameter list");
                        }
                    }
                    else
                    {
                        Type pt = Compiler.PrimType(Compiler.TagType(Compiler.TagOf(p)));

                        if (pt.IsPrimitive && !(pt == typeof(double) || pt == typeof(long)))
                        {
                            throw new ParseException("Only long and double primitives are supported: " + p);
                        }

                        if (paramState == ParamParseState.Rest && Compiler.TagOf(p) != null)
                        {
                            throw new ParseException("& arg cannot have type hint");
                        }
                        if (paramState == ParamParseState.Rest && method.Prim != null)
                        {
                            throw new ParseException("fns taking primitives cannot be variadic");
                        }
                        if (paramState == ParamParseState.Rest)
                        {
                            pt = typeof(ISeq);
                        }
                        argTypes.Add(pt);
                        LocalBinding b = pt.IsPrimitive
                            ? Compiler.RegisterLocal(p, null, new MethodParamExpr(pt), pt, true)
                            : Compiler.RegisterLocal(p,
                                                     paramState == ParamParseState.Rest ? Compiler.ISeqSym : Compiler.TagOf(p),
                                                     null, pt, true);

                        argLocals = argLocals.cons(b);
                        switch (paramState)
                        {
                        case ParamParseState.Required:
                            method._reqParms = method._reqParms.cons(b);
                            break;

                        case ParamParseState.Rest:
                            method._restParm = b;
                            paramState       = ParamParseState.Done;
                            break;

                        default:
                            throw new ParseException("Unexpected parameter");
                        }
                    }
                }

                if (method.RequiredArity > Compiler.MaxPositionalArity)
                {
                    throw new ParseException(string.Format("Can't specify more than {0} parameters", Compiler.MaxPositionalArity));
                }
                Compiler.LoopLocalsVar.set(argLocals);
                method.ArgLocals = argLocals;
                method._argTypes = argTypes.ToArray();
                method.Body      = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body);
                return(method);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
示例#35
0
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         if (_fnMode == FnMode.Full)
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             FieldBuilder fb = _closedOverFieldsMap[lb];
             ilg.MaybeEmitVolatileOp(IsVolatile(lb));
             ilg.Emit(OpCodes.Ldfld, fb);
         }
         else
         {
             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));
             if (lb.PrimitiveType != null)
                 ilg.Emit(OpCodes.Unbox, lb.PrimitiveType);
         }
     }
     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);
 }
示例#36
0
        internal Expression GenAssignLocal(GenContext context, LocalBinding lb, Expr val)
        {
            if (!IsMutable(lb))
                throw new ArgumentException("Cannot assign to non-mutable: " + lb.Name);

            FieldBuilder fb;
            if ( _closedOverFieldsMap.TryGetValue(lb,out fb) )
                return Expression.Assign(Expression.Field(_thisParam,_closedOverFieldsMap[lb]), val.GenCode(RHC.Expression,this,context));

            return Expression.Assign(lb.ParamExpression, val.GenCode(RHC.Expression,this,context));
        }
示例#37
0
 public void AddLocal(int index, LocalBinding lb)
 {
     Locals = (IPersistentMap)RT.assoc(Locals, lb, lb);
     IndexLocals = (IPersistentMap)RT.assoc(IndexLocals, index, lb);
 }
示例#38
0
 static void CloseOver(LocalBinding b, ObjMethod method)
 {
     if (b != null && method != null)
     {
         LocalBinding lb = (LocalBinding)RT.get(method.Locals, b);
         if (lb == null)
         {
             method.Objx.Closes = (IPersistentMap)RT.assoc(method.Objx.Closes, b, b);
             CloseOver(b, method.Parent);
         }
         else
         {
             if (lb.Index == 0)
                 method.UsesThis = true;
             if (InCatchFinallyVar.deref() != null)
             {
                 method.LocalsUsedInCatchFinally = (PersistentHashSet)method.LocalsUsedInCatchFinally.cons(b.Index);
             }
         }
     }
 }
示例#39
0
 internal bool IsVolatile(LocalBinding lb)
 {
     return RT.booleanCast(RT.contains(Fields, lb.Symbol)) &&
         RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("volatile-mutable")));
 }
示例#40
0
 static void CloseOver(LocalBinding b, FnMethod method)
 {
     if (b != null && method != null)
     {
         if (RT.get(method.Locals, b) == null)
         {
             method.Fn.Closes = (IPersistentMap)RT.assoc(method.Fn.Closes, b, b);
             CloseOver(b, method.Parent);
         }
         else if (IN_CATCH_FINALLY.deref() != null)
         {
             method.LocalsUsedInCatchFinally = (PersistentHashSet)method.LocalsUsedInCatchFinally.cons(b.Index);
         }
     }
 }
示例#41
0
        internal static ObjExpr Build(
            IPersistentVector interfaceSyms,
            IPersistentVector fieldSyms,
            Symbol thisSym,
            string tagName,
            Symbol className,
            Symbol typeTag,
            ISeq methodForms,
            Object frm)
        {
            NewInstanceExpr ret = new NewInstanceExpr(null);

            ret._src         = frm;
            ret._name        = className.ToString();
            ret._classMeta   = GenInterface.ExtractAttributes(RT.meta(className));
            ret.InternalName = ret.Name;  // ret.Name.Replace('.', '/');
            // Java: ret.objtype = Type.getObjectType(ret.internalName);

            if (thisSym != null)
            {
                ret._thisName = thisSym.Name;
            }

            if (fieldSyms != null)
            {
                IPersistentMap fmap      = PersistentHashMap.EMPTY;
                object[]       closesvec = new object[2 * fieldSyms.count()];
                for (int i = 0; i < fieldSyms.count(); i++)
                {
                    Symbol       sym = (Symbol)fieldSyms.nth(i);
                    LocalBinding lb  = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false);
                    fmap                 = fmap.assoc(sym, lb);
                    closesvec[i * 2]     = lb;
                    closesvec[i * 2 + 1] = lb;
                }
                // Java TODO: inject __meta et al into closes - when?
                // use array map to preserve ctor order
                ret._closes = new PersistentArrayMap(closesvec);
                ret._fields = fmap;
                for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i)
                {
                    ret._altCtorDrops++;
                }
            }

            // Java TODO: set up volatiles
            //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey)));

            IPersistentVector interfaces = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next())
            {
                Type t = (Type)Compiler.Resolve((Symbol)s.first());
                if (!t.IsInterface)
                {
                    throw new ParseException("only interfaces are supported, had: " + t.Name);
                }
                interfaces = interfaces.cons(t);
            }
            Type superClass = typeof(Object);

            Dictionary <IPersistentVector, List <MethodInfo> > overrideables;

            GatherMethods(superClass, RT.seq(interfaces), out overrideables);

            ret._methodMap = overrideables;

            //string[] inames = InterfaceNames(interfaces);

            Type   stub    = CompileStub(superClass, ret, SeqToTypeArray(interfaces), frm);
            Symbol thisTag = Symbol.intern(null, stub.FullName);
            //Symbol stubTag = Symbol.intern(null,stub.FullName);
            //Symbol thisTag = Symbol.intern(null, tagName);

            // Needs its own GenContext so it has its own DynInitHelper
            // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition
            GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? (ret.IsDefType ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true) : Compiler.EvalContext);
            GenContext genC    = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());

            //genC.FnCompileMode = FnMode.Full;

            try
            {
                Var.pushThreadBindings(
                    RT.map(
                        Compiler.ConstantsVar, PersistentVector.EMPTY,
                        Compiler.ConstantIdsVar, new IdentityHashMap(),
                        Compiler.KeywordsVar, PersistentHashMap.EMPTY,
                        Compiler.VarsVar, PersistentHashMap.EMPTY,
                        Compiler.KeywordCallsitesVar, PersistentVector.EMPTY,
                        Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY,
                        Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(),
                        Compiler.NoRecurVar, null,
                        Compiler.CompilerContextVar, genC
                        ));

                if (ret.IsDefType)
                {
                    Var.pushThreadBindings(
                        RT.map(
                            Compiler.MethodVar, null,
                            Compiler.LocalEnvVar, ret._fields,
                            Compiler.CompileStubSymVar, Symbol.intern(null, tagName),
                            Compiler.CompileStubClassVar, stub
                            ));
                    ret._hintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret._altCtorDrops);
                }
                // now (methodname [args] body)*
                // TODO: SourceLocation?
                //ret.line = (Integer)LINE.deref();
                IPersistentCollection methods = null;
                for (ISeq s = methodForms; s != null; s = RT.next(s))
                {
                    NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables);
                    methods = RT.conj(methods, m);
                }

                ret.Methods           = methods;
                ret.Keywords          = (IPersistentMap)Compiler.KeywordsVar.deref();
                ret.Vars              = (IPersistentMap)Compiler.VarsVar.deref();
                ret.Constants         = (PersistentVector)Compiler.ConstantsVar.deref();
                ret._constantsID      = RT.nextID();
                ret.KeywordCallsites  = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                ret.VarCallsites      = (IPersistentSet)Compiler.VarCallsitesVar.deref();
            }
            finally
            {
                if (ret.IsDefType)
                {
                    Var.popThreadBindings();
                }
                Var.popThreadBindings();
            }

            // TOD:  Really, the first stub here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call.
            // Might be able to flag stub classes and not try to convert, leading to a dynsite.
            ret.Compile(stub, stub, interfaces, false, genC);
            Compiler.RegisterDuplicateType(ret.CompiledType);

            return(ret);
        }
示例#42
0
 public CatchClause(Type type, LocalBinding lb, Expr handler)
 {
     _type = type;
     _lb = lb;
     _handler = handler;
 }
示例#43
0
 public HostArg(ParameterType paramType, Expr argExpr, LocalBinding lb)
 {
     _paramType = paramType;
     _argExpr = argExpr;
     _localBinding = lb;
 }
示例#44
0
            public Expr Parse(ParserContext pcon, object frm)
            {
                string         source  = (string)Compiler.SourceVar.deref();
                IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();  // Compiler.GetSourceSpanMap(form);

                ISeq form = (ISeq)frm;

                IPersistentVector loopLocals = (IPersistentVector)Compiler.LoopLocalsVar.deref();

                if (pcon.Rhc != RHC.Return || loopLocals == null)
                {
                    throw new ParseException("Can only recur from tail position");
                }

                if (Compiler.NoRecurVar.deref() != null)
                {
                    throw new ParseException("Cannot recur across try");
                }

                IPersistentVector args = PersistentVector.EMPTY;

                for (ISeq s = RT.seq(form.next()); s != null; s = s.next())
                {
                    args = args.cons(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), s.first()));
                }
                if (args.count() != loopLocals.count())
                {
                    throw new ParseException(string.Format("Mismatched argument count to recur, expected: {0} args, got {1}",
                                                           loopLocals.count(), args.count()));
                }

                for (int i = 0; i < loopLocals.count(); i++)
                {
                    LocalBinding lb    = (LocalBinding)loopLocals.nth(i);
                    Type         primt = lb.PrimitiveType;
                    if (primt != null)
                    {
                        bool mismatch = false;
                        Type pt       = Compiler.MaybePrimitiveType((Expr)args.nth(i));
                        if (primt == typeof(long))
                        {
                            if (!(pt == typeof(long) || pt == typeof(int) || pt == typeof(short) || pt == typeof(uint) || pt == typeof(ushort) || pt == typeof(ulong) ||
                                  pt == typeof(char) || pt == typeof(byte) || pt == typeof(sbyte)))
                            {
                                mismatch = true;
                            }
                        }
                        else if (primt == typeof(double))
                        {
                            if (!(pt == typeof(double) || pt == typeof(float)))
                            {
                                mismatch = true;
                            }
                        }

                        if (mismatch)
                        {
                            lb.RecurMismatch = true;
                            if (RT.booleanCast(RT.WarnOnReflectionVar.deref()))
                            {
                                RT.errPrintWriter().WriteLine("{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, pt != null ? pt.Name : "Object", primt.Name);
                            }
                        }
                    }
                }


                return(new RecurExpr(source, spanMap, loopLocals, args));
            }
示例#45
0
 internal Expression GenUnboxedLocal(GenContext context, LocalBinding lb)
 {
     Type primType = lb.PrimitiveType;
     if (_closes.containsKey(lb) && _fnMode == FnMode.Full)
         return Expression.Convert(Expression.Field(_thisParam, lb.Name), primType);
     else
         return lb.ParamExpression;
 }
示例#46
0
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */
        static Type CompileStub(Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            GenContext  context = Compiler.CompilerContextVar.get() as GenContext ?? GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false);
            TypeBuilder tb      = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName, TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding    lb     = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                // TODO: FIgure out Volatile
                if (!ret.IsVolatile(lb))
                {
                    access |= FieldAttributes.InitOnly;
                }

                if (lb.PrimitiveType != null)
                {
                    tb.DefineField(lb.Name, lb.PrimitiveType, access);
                }
                else
                {
                    tb.DefineField(lb.Name, typeof(Object), access);
                }
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                ILGen ilg             = new ILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);


                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int    newLen    = ctorTypes.Length - ret._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);
                        ILGen ilg2             = new ILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                        {
                            ilg2.EmitLoadArg(i + 1);
                        }
                        for (int i = 0; i < ret._altCtorDrops; i++)
                        {
                            ilg2.EmitNull();
                        }
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();

            Compiler.RegisterDuplicateType(t);
            return(t);
        }
示例#47
0
 public BindingInit(LocalBinding binding, Expr init)
 {
     _binding = binding;
     _init = init;
 }
示例#48
0
 internal bool IsVolatile(LocalBinding lb)
 {
     return(RT.booleanCast(RT.contains(Fields, lb.Symbol)) &&
            RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("volatile-mutable"))));
 }
示例#49
0
 public void AddLocal(int index, LocalBinding lb)
 {
     Locals      = (IPersistentMap)RT.assoc(Locals, lb, lb);
     IndexLocals = (IPersistentMap)RT.assoc(IndexLocals, index, lb);
 }
示例#50
0
        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);
        }
示例#51
0
 internal Expression GenLocal(GenContext context, LocalBinding lb)
 {
     if ( _fnMode == FnMode.Full )
     {
         if (_closes.containsKey(lb))
         {
             Expression expr = Expression.Field(_thisParam, lb.Name);
             Type primtType = lb.PrimitiveType;
             if (primtType != null)
                 expr = Compiler.MaybeBox(Expression.Convert(expr, primtType));
             return expr;
         }
         else
             return lb.ParamExpression;
     }
     else
     {
         return lb.ParamExpression;
     }
 }