Наследование: ObjMethod
Пример #1
0
        Expression GenImmediateCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            ParameterExpression p1 = Expression.Parameter(CompiledType, "__x__");

            _thisParam = p1;

            List <Expression> exprs = new List <Expression>();

            if (CompiledType == typeof(RestFnImpl))
            {
                exprs.Add(Expression.Assign(p1,
                                            Expression.New(Compiler.Ctor_RestFnImpl_1, Expression.Constant(_variadicMethod.RequiredArity))));
            }
            else
            {
                exprs.Add(Expression.Assign(p1, Expression.New(p1.Type)));
            }

            for (ISeq s = RT.seq(Methods); s != null; s = s.next())
            {
                FnMethod         method    = (FnMethod)s.first();
                LambdaExpression lambda    = method.GenerateImmediateLambda(rhc, this, context);
                string           fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + method.RequiredArity
                    : "_fn" + method.NumParams;
                exprs.Add(Expression.Assign(Expression.Field(p1, fieldName), lambda));
            }

            exprs.Add(p1);

            Expression expr = Expression.Block(new ParameterExpression[] { p1 }, exprs);

            return(expr);
        }
Пример #2
0
        private static int GetMethodKey(FnMethod method)
        {
            int arity = method.IsVariadic
                ? method.RequiredArity + 1  // to avoid the non-variadics, the last of which may have NumParams == this method RequireArity
                : method.NumParams;

            return(arity);
        }
Пример #3
0
 private void GenerateMethods(GenContext context)
 {
     for (ISeq s = RT.seq(_methods); s != null; s = s.next())
     {
         FnMethod method = (FnMethod)s.first();
         method.GenerateCode(context);
     }
 }
Пример #4
0
        static bool HasPrimDecls(ISeq forms)
        {
            for (ISeq s = forms; s != null; s = RT.next(s))
            {
                if (FnMethod.HasPrimInterface((ISeq)RT.first(s)))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #5
0
        // This naming convention drawn from the Java code.
        internal void ComputeNames(ISeq form, string name)
        {
            FnMethod enclosingMethod = (FnMethod)Compiler.METHODS.deref();

            string baseName = enclosingMethod != null
                ? (enclosingMethod.Fn._name + "$")
                : (Compiler.Munge(Compiler.CurrentNamespace.Name.Name) + "$");

            if (RT.second(form) is Symbol)
            {
                name = ((Symbol)RT.second(form)).Name;
            }

            _simpleName   = (name == null ? "fn" : Compiler.Munge(name).Replace(".", "_DOT_")) + "__" + RT.nextID();
            _name         = baseName + _simpleName;
            _internalName = _name.Replace('.', '/');
            _fnType       = RT.classForName(_internalName);
            // fn.fntype = Type.getObjectType(fn.internalName) -- JAVA
        }
Пример #6
0
        void LightCompileMethods()
        {
            Dictionary <int, DynamicMethod> dict = new Dictionary <int, DynamicMethod>();

            // Create a dynamic method that takes an array of closed-over values
            // and returns an instance of AFnImpl.

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

                //dict[key] = new WeakReference(method.DynMethod);
                dict[key] = method.DynMethod;
            }

            DynMethodMap[DynMethodMapKey] = dict;
            _dynMethodMap = dict;
        }
Пример #7
0
        protected override void GenerateMethods(GenContext context)
        {
            for (ISeq s = RT.seq(Methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                method.GenerateCode(this, context);
            }

            if (IsVariadic)
            {
                GenerateGetRequiredArityMethod(TypeBuilder, _variadicMethod.RequiredArity);
            }

            List <int> supportedArities = new List <int>();

            for (ISeq s = RT.seq(Methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                supportedArities.Add(method.NumParams);
            }

            GenerateHasArityMethod(TypeBuilder, supportedArities, IsVariadic, IsVariadic ? _variadicMethod.RequiredArity : 0);
        }
Пример #8
0
        protected override void EmitMethods(TypeBuilder tb)
        {
            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                method.Emit(this, tb);
            }

            if (IsVariadic)
            {
                EmitGetRequiredArityMethod(_typeBuilder, _variadicMethod.RequiredArity);
            }

            List <int> supportedArities = new List <int>();

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                supportedArities.Add(method.NumParams);
            }

            EmitHasArityMethod(_typeBuilder, supportedArities, IsVariadic, IsVariadic ? _variadicMethod.RequiredArity : 0);
        }
Пример #9
0
        private Expression GenerateImmediateLambda(GenContext context, Type baseClass)
        {
            //   ParameterExpression p1 = ThisParam ?? Expression.Parameter(baseClass, "____x");
            ParameterExpression p1 = Expression.Parameter(baseClass, "____x");

            _thisParam = p1;
            List <Expression> exprs = new List <Expression>();

            if (baseClass == typeof(RestFnImpl))
            {
                exprs.Add(Expression.Assign(p1,
                                            Expression.New(Compiler.Ctor_RestFnImpl_1, Expression.Constant(_variadicMethod.RequiredArity))));
            }
            else
            {
                exprs.Add(Expression.Assign(p1, Expression.New(p1.Type)));
            }

            GenContext newContext = CreateContext(context, null, baseClass);

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod         method    = (FnMethod)s.first();
                LambdaExpression lambda    = method.GenerateImmediateLambda(newContext);
                string           fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + method.RequiredArity
                    : "_fn" + method.NumParams;
                exprs.Add(Expression.Assign(Expression.Field(p1, fieldName), lambda));
            }

            exprs.Add(p1);

            Expression expr = Expression.Block(new ParameterExpression[] { p1 }, exprs);

            return(expr);
        }
Пример #10
0
        internal static FnMethod Parse(FnExpr fn, ISeq form)
        {
            // ([args] body ... )

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

            try
            {
                FnMethod method = new FnMethod(fn, (FnMethod)Compiler.METHODS.deref());
                // TODO: method.line = (Integer) LINE.deref();


                Var.pushThreadBindings(RT.map(
                                           Compiler.METHODS, method,
                                           Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(),
                                           Compiler.LOOP_LOCALS, null,
                                           Compiler.NEXT_LOCAL_NUM, 0));

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

                ParamParseState   paramState = ParamParseState.Required;
                IPersistentVector argLocals  = PersistentVector.EMPTY;
                int parmsCount = parms.count();

                for (int i = 0; i < parmsCount; i++)
                {
                    if (!(parms.nth(i) is Symbol))
                    {
                        throw new ArgumentException("fn params must be Symbols");
                    }
                    Symbol p = (Symbol)parms.nth(i);
                    if (p.Namespace != null)
                    {
                        throw new Exception("Can't use qualified name as parameter: " + p);
                    }
                    if (p.Equals(Compiler._AMP_))
                    {
                        if (paramState == ParamParseState.Required)
                        {
                            paramState = ParamParseState.Rest;
                        }
                        else
                        {
                            throw new Exception("Invalid parameter list");
                        }
                    }
                    else
                    {
                        LocalBinding b = Compiler.RegisterLocal(p,
                                                                paramState == ParamParseState.Rest ? Compiler.ISEQ : Compiler.TagOf(p),
                                                                null); // asdf-tag

                        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 Exception("Unexpected parameter");
                        }
                    }
                }

                if (method.NumParams > Compiler.MAX_POSITIONAL_ARITY)
                {
                    throw new Exception(string.Format("Can't specify more than {0} parameters", Compiler.MAX_POSITIONAL_ARITY));
                }
                Compiler.LOOP_LOCALS.set(argLocals);
                method._argLocals = argLocals;
                method._body      = (new BodyExpr.Parser()).Parse(body);
                return(method);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
Пример #11
0
        public static Expr Parse(object frm, string name)
        {
            ISeq form = (ISeq)frm;

            FnExpr fn = new FnExpr(Compiler.TagOf(form));

            if (((IMeta)form.first()).meta() != null)
            {
                fn._onceOnly  = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE));
                fn._superName = (string)RT.get(RT.meta(form.first()), KW_SUPER_NAME);
            }


            fn.ComputeNames(form, name);

            try
            {
                Var.pushThreadBindings(RT.map(
                                           Compiler.CONSTANTS, PersistentVector.EMPTY,
                                           Compiler.KEYWORDS, PersistentHashMap.EMPTY,
                                           Compiler.VARS, PersistentHashMap.EMPTY));

                //arglist might be preceded by symbol naming this fn
                if (RT.second(form) is Symbol)
                {
                    fn._thisName = ((Symbol)RT.second(form)).Name;
                    form         = RT.cons(Compiler.FN, RT.next(RT.next(form)));
                }

                // Normalize body
                // If it is (fn [arg...] body ...), turn it into
                //          (fn ([arg...] body...))
                // so that we can treat uniformly as (fn ([arg...] body...) ([arg...] body...) ... )
                if (RT.second(form) is IPersistentVector)
                {
                    form = RT.list(Compiler.FN, RT.next(form));
                }


                FnMethod variadicMethod = null;
                SortedDictionary <int, FnMethod> methods = new SortedDictionary <int, FnMethod>();

                for (ISeq s = RT.next(form); s != null; s = RT.next(s))
                {
                    FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s));
                    if (f.IsVariadic)
                    {
                        if (variadicMethod == null)
                        {
                            variadicMethod = f;
                        }
                        else
                        {
                            throw new Exception("Can't have more than 1 variadic overload");
                        }
                    }
                    else if (!methods.ContainsKey(f.RequiredArity))
                    {
                        methods[f.RequiredArity] = f;
                    }
                    else
                    {
                        throw new Exception("Can't have 2 overloads with the same arity.");
                    }
                }

                if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams)
                {
                    throw new Exception("Can't have fixed arity methods with more params than the variadic method.");
                }

                IPersistentCollection allMethods = null;
                foreach (FnMethod method in methods.Values)
                {
                    allMethods = RT.conj(allMethods, method);
                }
                if (variadicMethod != null)
                {
                    allMethods = RT.conj(allMethods, variadicMethod);
                }

                fn._methods        = allMethods;
                fn._variadicMethod = variadicMethod;
                fn._keywords       = (IPersistentMap)Compiler.KEYWORDS.deref();
                fn._vars           = (IPersistentMap)Compiler.VARS.deref();
                fn._constants      = (PersistentVector)Compiler.CONSTANTS.deref();
                fn._constantsID    = RT.nextID();
            }
            finally
            {
                Var.popThreadBindings();
            }
            // JAVA: fn.compile();
            return(fn);
        }
Пример #12
0
 internal void AddMethod(FnMethod method)
 {
     _methods = RT.conj(_methods, method);
 }
Пример #13
0
        public static Expr Parse(ParserContext pcon, ISeq form, string name)
        {
            ISeq origForm = form;

            FnExpr fn = new FnExpr(Compiler.TagOf(form));

            fn._src = form;

            if (((IMeta)form.first()).meta() != null)
            {
                fn._onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE));
            }

            fn.ComputeNames(form, name);

            List <string> prims = new List <string>();

            //arglist might be preceded by symbol naming this fn
            if (RT.second(form) is Symbol)
            {
                Symbol nm = (Symbol)RT.second(form);
                fn._thisName = nm.Name;
                fn._isStatic = false; // RT.booleanCast(RT.get(nm.meta(), Compiler.STATIC_KEY));
                form         = RT.cons(Compiler.FnSym, RT.next(RT.next(form)));
            }

            // Normalize body
            //now (fn [args] body...) or (fn ([args] body...) ([args2] body2...) ...)
            //turn former into latter
            if (RT.second(form) is IPersistentVector)
            {
                form = RT.list(Compiler.FnSym, RT.next(form));
            }

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

            GenContext newContext = null;

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

            newContext = context.WithNewDynInitHelper(fn.InternalName + "__dynInitHelper_" + RT.nextID().ToString());
            Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, newContext));


            try
            {
                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));
                    SortedDictionary <int, FnMethod> methods = new SortedDictionary <int, FnMethod>();
                    FnMethod variadicMethod = null;

                    for (ISeq s = RT.next(form); s != null; s = RT.next(s))
                    {
                        FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s), fn._isStatic);
                        if (f.IsVariadic)
                        {
                            if (variadicMethod == null)
                            {
                                variadicMethod = f;
                            }
                            else
                            {
                                throw new ParseException("Can't have more than 1 variadic overload");
                            }
                        }
                        else if (!methods.ContainsKey(f.RequiredArity))
                        {
                            methods[f.RequiredArity] = f;
                        }
                        else
                        {
                            throw new ParseException("Can't have 2 overloads with the same arity.");
                        }
                        if (f.Prim != null)
                        {
                            prims.Add(f.Prim);
                        }
                    }

                    if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams)
                    {
                        throw new ParseException("Can't have fixed arity methods with more params than the variadic method.");
                    }

                    if (fn._isStatic && fn.Closes.count() > 0)
                    {
                        throw new ParseException("static fns can't be closures");
                    }

                    IPersistentCollection allMethods = null;
                    foreach (FnMethod method in methods.Values)
                    {
                        allMethods = RT.conj(allMethods, method);
                    }
                    if (variadicMethod != null)
                    {
                        allMethods = RT.conj(allMethods, variadicMethod);
                    }

                    fn._methods          = allMethods;
                    fn._variadicMethod   = variadicMethod;
                    fn.Keywords          = (IPersistentMap)Compiler.KeywordsVar.deref();
                    fn.Vars              = (IPersistentMap)Compiler.VarsVar.deref();
                    fn.Constants         = (PersistentVector)Compiler.ConstantsVar.deref();
                    fn.KeywordCallsites  = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                    fn.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                    fn.VarCallsites      = (IPersistentSet)Compiler.VarCallsitesVar.deref();

                    fn._constantsID = RT.nextID();
                }
                finally
                {
                    Var.popThreadBindings();
                }


                IPersistentMap fmeta = RT.meta(origForm);
                if (fmeta != null)
                {
                    fmeta = fmeta.without(RT.LineKey).without(RT.ColumnKey).without(RT.SourceSpanKey).without(RT.FileKey);
                }
                fn._hasMeta = RT.count(fmeta) > 0;


                IPersistentVector primTypes = PersistentVector.EMPTY;
                foreach (string typename in prims)
                {
                    primTypes = primTypes.cons(Type.GetType(typename));
                }

                fn.Compile(
                    fn.IsVariadic ? typeof(RestFn) : typeof(AFunction),
                    null,
                    primTypes,
                    fn._onceOnly,
                    newContext);

                if (fn.SupportsMeta)
                {
                    return(new MetaExpr(fn, MapExpr.Parse(pcon.EvalOrExpr(), fmeta)));
                }
                else
                {
                    return(fn);
                }
            }
            finally
            {
                if (newContext != null)
                {
                    Var.popThreadBindings();
                }
            }
        }
Пример #14
0
        public static Expr Parse(ParserContext pcon, ISeq form)
        {
            bool tailPosition = Compiler.InTailCall(pcon.Rhc);

            pcon = pcon.EvalOrExpr();

            Expr    fexpr    = Compiler.Analyze(pcon, form.first());
            VarExpr varFexpr = fexpr as VarExpr;

            if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar) && RT.count(form) == 3)
            {
                Expr sexpr = Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form));
                if (sexpr is ConstantExpr csexpr)
                {
                    Type tval = csexpr.Val as Type;
                    if (tval != null)
                    {
                        return(new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), tval, Compiler.Analyze(pcon, RT.third(form))));
                    }
                }
            }

            if (RT.booleanCast(Compiler.GetCompilerOption(Compiler.DirectLinkingKeyword)) &&
                varFexpr != null &&
                pcon.Rhc != RHC.Eval)
            {
                Var v = varFexpr.Var;
                if (!v.isDynamic() && !RT.booleanCast(RT.get(v.meta(), Compiler.RedefKeyword, false)) && !RT.booleanCast(RT.get(v.meta(), RT.DeclaredKey, false)))
                {
                    Symbol formTag = Compiler.TagOf(form);
                    //object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword);
                    int    arity  = RT.count(form.next());
                    object sigtag = SigTag(arity, v);
                    object vtag   = RT.get(RT.meta(v), RT.TagKey);
                    if (StaticInvokeExpr.Parse(v, RT.next(form), formTag ?? sigtag ?? vtag) is StaticInvokeExpr ret && !((Compiler.IsCompiling || Compiler.IsCompilingDefType) && GenContext.IsInternalAssembly(ret.Method.DeclaringType.Assembly)))
                    {
                        //Console.WriteLine("invoke direct: {0}", v);
                        return(ret);
                    }
                    //Console.WriteLine("NOT direct: {0}", v);
                }
            }

            if (varFexpr != null && pcon.Rhc != RHC.Eval)
            {
                Var    v        = varFexpr.Var;
                object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword);
                int    arity    = RT.count(form.next());
                for (ISeq s = RT.seq(arglists); s != null; s = s.next())
                {
                    IPersistentVector sargs = (IPersistentVector)s.first();
                    if (sargs.count() == arity)
                    {
                        string primc = FnMethod.PrimInterface(sargs);
                        if (primc != null)
                        {
                            return(Compiler.Analyze(pcon,
                                                    ((IObj)RT.listStar(Symbol.intern(".invokePrim"),
                                                                       ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))),
                                                                       form.next())).withMeta((IPersistentMap)RT.conj(RT.meta(v), RT.meta(form)))));
                        }
                        break;
                    }
                }
            }

            if (fexpr is KeywordExpr kwFexpr && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound)
            {
                Expr target = Compiler.Analyze(pcon, RT.second(form));
                return(new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target));
            }

            IPersistentVector args = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form.next()); s != null; s = s.next())
            {
                args = args.cons(Compiler.Analyze(pcon, s.first()));
            }

            //if (args.count() > Compiler.MAX_POSITIONAL_ARITY)
            //    throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY));

            return(new InvokeExpr((string)Compiler.SourceVar.deref(),
                                  (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form),
                                  Compiler.TagOf(form),
                                  fexpr,
                                  args,
                                  tailPosition));
        }
Пример #15
0
        private static int GetMethodKey(FnMethod method)
        {
            int arity = method.IsVariadic 
                ? method.RequiredArity + 1  // to avoid the non-variadics, the last of which may have NumParams == this method RequireArity
                : method.NumParams;

            return arity;
        }
Пример #16
0
        internal static FnMethod Parse(FnExpr fn, ISeq form)
        {
            // ([args] body ... )

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

            try
            {
                FnMethod method = new FnMethod(fn, (FnMethod)Compiler.METHODS.deref());
                method._line = (int) Compiler.LINE.deref();

                Var.pushThreadBindings(RT.map(
                    Compiler.METHODS, method,
                    Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(),
                    Compiler.LOOP_LOCALS, null,
                    Compiler.NEXT_LOCAL_NUM, 0));

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

                ParamParseState paramState = ParamParseState.Required;
                IPersistentVector argLocals = PersistentVector.EMPTY;
                int parmsCount = parms.count();

                for (int i = 0; i < parmsCount; i++)
                {
                    if (!(parms.nth(i) is Symbol))
                        throw new ArgumentException("fn params must be Symbols");
                    Symbol p = (Symbol)parms.nth(i);
                    if (p.Namespace != null)
                        throw new Exception("Can't use qualified name as parameter: " + p);
                    if (p.Equals(Compiler._AMP_))
                    {
                        if (paramState == ParamParseState.Required)
                            paramState = ParamParseState.Rest;
                        else
                            throw new Exception("Invalid parameter list");
                    }
                    else
                    {
                        LocalBinding b = Compiler.RegisterLocal(p,
                            paramState == ParamParseState.Rest ? Compiler.ISEQ : Compiler.TagOf(p),
                            null);

                        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 Exception("Unexpected parameter");
                        }
                    }
                }

                if (method.NumParams > Compiler.MAX_POSITIONAL_ARITY)
                    throw new Exception(string.Format("Can't specify more than {0} parameters", Compiler.MAX_POSITIONAL_ARITY));
                Compiler.LOOP_LOCALS.set(argLocals);
                method._argLocals = argLocals;
                method._body = (new BodyExpr.Parser()).Parse(body,true);
                return method;
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
Пример #17
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);
         }
     }
 }
Пример #18
0
 public FnMethod(FnExpr fn, FnMethod parent)
 {
     _parent = parent;
     _fn     = fn;
 }
Пример #19
0
        internal static FnMethod Parse(FnExpr fn, ISeq form, bool isStatic)
        {
            // ([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('.', '/');

                method._retType = Compiler.TagType(Compiler.TagOf(parms));
                if (method._retType.IsPrimitive && !(method._retType == typeof(double) || method._retType == typeof(long)))
                    throw new ParseException("Only long and double primitives are supported");

                // register 'this' as local 0
                if ( !isStatic )
                    //method._thisBinding = Compiler.RegisterLocalThis(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null);
                    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 (isStatic)
                        //    throw new Exception("Variadic fns cannot be static");

                        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), true)
                            : Compiler.RegisterLocal(p,
                            paramState == ParamParseState.Rest ? Compiler.ISeqSym : Compiler.TagOf(p),
                            null,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;
                //if (isStatic)
                if ( method.Prim != null )
                    method._argTypes = argTypes.ToArray();
                method._body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return),body);
                return method;
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
Пример #20
0
        internal static object Compile(TextReader rdr, string sourceDirectory, string sourceName, string relativePath)
        {
            if (CompilePathVar.deref() == null)
                throw new InvalidOperationException("*compile-path* not set");

            object eofVal = new object();
            object form;

            //string sourcePath = sourceDirectory == null ? sourceName : sourceDirectory + "\\" + sourceName;
            string sourcePath = relativePath;

            LineNumberingTextReader lntr = rdr as LineNumberingTextReader ?? new LineNumberingTextReader(rdr);

            GenContext context = GenContext.CreateWithExternalAssembly(relativePath, ".dll", true);
            GenContext evalContext = GenContext.CreateWithInternalAssembly("EvalForCompile", false);

            Var.pushThreadBindings(RT.map(
                SourcePathVar, sourcePath,
                SourceVar, sourceName,
                MethodVar, null,
                LocalEnvVar, null,
                LoopLocalsVar, null,
                NextLocalNumVar, 0,
                RT.CurrentNSVar, RT.CurrentNSVar.deref(),
                    //LINE_BEFORE, lntr.LineNumber,
                    //LINE_AFTER, lntr.LineNumber,
                DocumentInfoVar, Expression.SymbolDocument(sourceName),  // I hope this is enough
                ConstantsVar, PersistentVector.EMPTY,
                ConstantIdsVar, new IdentityHashMap(),
                KeywordsVar, PersistentHashMap.EMPTY,
                VarsVar, PersistentHashMap.EMPTY,
                RT.UncheckedMathVar, RT.UncheckedMathVar.deref(),
                RT.WarnOnReflectionVar, RT.WarnOnReflectionVar.deref(),
                RT.DataReadersVar, RT.DataReadersVar.deref(),
                //KEYWORD_CALLSITES, PersistentVector.EMPTY,  // jvm doesn't do this, don't know why
                //VAR_CALLSITES, EmptyVarCallSites(),      // jvm doesn't do this, don't know why
                //PROTOCOL_CALLSITES, PersistentVector.EMPTY, // jvm doesn't do this, don't know why
                CompilerContextVar, context
                ));

            try
            {
                FnExpr objx = new FnExpr(null);
                objx.InternalName = sourcePath.Replace(Path.PathSeparator, '/').Substring(0, sourcePath.LastIndexOf('.')) + "__init";

                TypeBuilder exprTB = context.AssemblyGen.DefinePublicType("__REPL__", typeof(object), true);

                //List<string> names = new List<string>();
                List<Expr> exprs = new List<Expr>();

                int i = 0;
                while ((form = LispReader.read(lntr, false, eofVal, false)) != eofVal)
                {
                    //Java version: LINE_AFTER.set(lntr.LineNumber);

                    Compile1(context, evalContext, exprTB, form, exprs, ref i);

                    //Java version: LINE_BEFORE.set(lntr.LineNumber);
                }

                exprTB.CreateType();

                // Need to put the loader init in its own type because we can't generate calls on the MethodBuilders
                //  until after their types have been closed.

                TypeBuilder initTB = context.AssemblyGen.DefinePublicType("__Init__", typeof(object), true);

                Expression pushNSExpr = Expression.Call(null, Method_Compiler_PushNS);
                Expression popExpr = Expression.Call(null, Method_Var_popThreadBindings);

                BodyExpr bodyExpr = new BodyExpr(PersistentVector.create1(exprs));
                FnMethod method = new FnMethod(objx, null, bodyExpr);
                objx.AddMethod(method);

                objx.Keywords = (IPersistentMap)KeywordsVar.deref();
                objx.Vars = (IPersistentMap)VarsVar.deref();
                objx.Constants = (PersistentVector)ConstantsVar.deref();
                //objx.KeywordCallsites = (IPersistentVector)KEYWORD_CALLSITES.deref();
                //objx.ProtocolCallsites = (IPersistentVector)PROTOCOL_CALLSITES.deref();
                //objx.VarCallsites = (IPersistentSet)VAR_CALLSITES.deref();

                objx.KeywordCallsites = PersistentVector.EMPTY;
                objx.ProtocolCallsites = PersistentVector.EMPTY;
                objx.VarCallsites = (IPersistentSet)EmptyVarCallSites();

                objx.Compile(typeof(AFunction), null, PersistentVector.EMPTY, false, context);

                Expression fnNew = objx.GenCode(RHC.Expression,objx,context);
                Expression fnInvoke = Expression.Call(fnNew, fnNew.Type.GetMethod("invoke", System.Type.EmptyTypes));

                Expression tryCatch = Expression.TryCatchFinally(fnInvoke, popExpr);

                Expression body = Expression.Block(pushNSExpr, tryCatch);

                // create initializer call
                MethodBuilder mbInit = initTB.DefineMethod("Initialize", MethodAttributes.Public | MethodAttributes.Static);
                LambdaExpression initFn = Expression.Lambda(body);
                //initFn.CompileToMethod(mbInit, DebugInfoGenerator.CreatePdbGenerator());
                initFn.CompileToMethod(mbInit, context.IsDebuggable);

                initTB.CreateType();

                context.SaveAssembly();
            }
            catch (LispReader.ReaderException e)
            {
                throw new CompilerException(sourcePath, e.Line, e.InnerException);
            }
            finally
            {
                Var.popThreadBindings();
            }
            return null;
        }
Пример #21
0
        void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
            //objx arg is enclosing objx, not this


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

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

            ilg.Emit(OpCodes.Stloc, fnLocal);

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

            // Set up the methods

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

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

                FieldInfo fi = CompiledType.GetField(fieldName);

                ilg.Emit(OpCodes.Ldloc, fnLocal);


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

                ilg.EmitFieldSet(fi);
            }



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

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

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

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

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

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

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

            // Leave the instance on the stack.
            ilg.Emit(OpCodes.Ldloc, fnLocal);
        }
Пример #22
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();
            }
        }
Пример #23
0
 public FnMethod(FnExpr fn, FnMethod parent)
 {
     _parent = parent;
     _fn = fn;
 }
Пример #24
0
        public static Expr Parse(ParserContext pcon, ISeq form)
        {
            pcon = pcon.EvalOrExpr();

            Expr    fexpr    = Compiler.Analyze(pcon, form.first());
            VarExpr varFexpr = fexpr as VarExpr;

            if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar))
            {
                if (RT.second(form) is Symbol)
                {
                    Type t = HostExpr.MaybeType(RT.second(form), false);
                    if (t != null)
                    {
                        return(new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), t, Compiler.Analyze(pcon, RT.third(form))));
                    }
                }
            }

            if (varFexpr != null && pcon.Rhc != RHC.Eval)
            {
                Var    v        = varFexpr.Var;
                object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword);
                int    arity    = RT.count(form.next());
                for (ISeq s = RT.seq(arglists); s != null; s = s.next())
                {
                    IPersistentVector sargs = (IPersistentVector)s.first();
                    if (sargs.count() == arity)
                    {
                        string primc = FnMethod.PrimInterface(sargs);
                        if (primc != null)
                        {
                            return(Compiler.Analyze(pcon,
                                                    RT.listStar(Symbol.intern(".invokePrim"),
                                                                ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))),
                                                                form.next())));
                        }
                        break;
                    }
                }
            }

            KeywordExpr kwFexpr = fexpr as KeywordExpr;

            if (kwFexpr != null && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound)
            {
                Expr target = Compiler.Analyze(pcon, RT.second(form));
                return(new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target));
            }

            IPersistentVector args = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form.next()); s != null; s = s.next())
            {
                args = args.cons(Compiler.Analyze(pcon, s.first()));
            }

            //if (args.count() > Compiler.MAX_POSITIONAL_ARITY)
            //    throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY));

            return(new InvokeExpr((string)Compiler.SourceVar.deref(),
                                  (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form),
                                  Compiler.TagOf(form),
                                  fexpr,
                                  args));
        }
Пример #25
0
        internal static object Compile(TextReader rdr, string sourceDirectory, string sourceName, string relativePath)
        {
            if (COMPILE_PATH.deref() == null)
                throw new Exception("*compile-path* not set");

            object eofVal = new object();
            object form;

            //string sourcePath = sourceDirectory == null ? sourceName : sourceDirectory + "\\" + sourceName;
            string sourcePath = relativePath;

            LineNumberingTextReader lntr =
                (rdr is LineNumberingTextReader) ? (LineNumberingTextReader)rdr : new LineNumberingTextReader(rdr);

            GenContext context = new GenContext(sourceName, ".dll", sourceDirectory, true);
            GenContext evalContext = new GenContext("EvalForCompile", false);

            Var.pushThreadBindings(RT.map(
                SOURCE_PATH, sourcePath,
                SOURCE, sourceName,
                METHOD, null,
                LOCAL_ENV, null,
                LOOP_LOCALS, null,
                NEXT_LOCAL_NUM, 0,
                RT.CURRENT_NS, RT.CURRENT_NS.deref(),
                    //LINE_BEFORE, lntr.LineNumber,
                    //LINE_AFTER, lntr.LineNumber,
                DOCUMENT_INFO, Expression.SymbolDocument(sourceName),  // I hope this is enough
                CONSTANTS, PersistentVector.EMPTY,
                CONSTANT_IDS, new IdentityHashMap(),
                KEYWORDS, PersistentHashMap.EMPTY,
                VARS, PersistentHashMap.EMPTY,
                KEYWORD_CALLSITES, PersistentVector.EMPTY,  // jvm doesn't do this, don't know why
                VAR_CALLSITES, PersistentVector.EMPTY,      // jvm doesn't do this, don't know why
                PROTOCOL_CALLSITES, PersistentVector.EMPTY, // jvm doesn't do this, don't know why
                COMPILER_CONTEXT, context
                ));

            try
            {
                FnExpr objx = new FnExpr(null);
                objx.InternalName = sourcePath.Replace(Path.PathSeparator, '/').Substring(0, sourcePath.LastIndexOf('.')) + "__init";

                TypeBuilder exprTB = context.AssemblyGen.DefinePublicType("__REPL__", typeof(object), true);

                //List<string> names = new List<string>();
                List<Expr> exprs = new List<Expr>();

                int i = 0;
                while ((form = LispReader.read(lntr, false, eofVal, false)) != eofVal)
                {
                    //Java version: LINE_AFTER.set(lntr.LineNumber);

                    Compile1(context, evalContext, exprTB, form, exprs, ref i);

                    //Java version: LINE_BEFORE.set(lntr.LineNumber);
                }

                Type exprType = exprTB.CreateType();

                // Need to put the loader init in its own type because we can't generate calls on the MethodBuilders
                //  until after their types have been closed.

                TypeBuilder initTB = context.AssemblyGen.DefinePublicType("__Init__", typeof(object), true);

                Expression pushNSExpr = Expression.Call(null, Method_Compiler_PushNS);
                Expression popExpr = Expression.Call(null, Method_Var_popThreadBindings);

                BodyExpr bodyExpr = new BodyExpr(PersistentVector.create1(exprs));
                FnMethod method = new FnMethod(objx, null, bodyExpr);
                objx.AddMethod(method);

                objx.Keywords = (IPersistentMap)KEYWORDS.deref();
                objx.Vars = (IPersistentMap)VARS.deref();
                objx.Constants = (PersistentVector)CONSTANTS.deref();
                objx.KeywordCallsites = (IPersistentVector)KEYWORD_CALLSITES.deref();
                objx.ProtocolCallsites = (IPersistentVector)PROTOCOL_CALLSITES.deref();
                objx.VarCallsites = (IPersistentVector)VAR_CALLSITES.deref();

                objx.Compile(typeof(AFunction), PersistentVector.EMPTY, false, context);

                Expression fnNew = objx.GenCode(RHC.Expression,objx,context);
                Expression fnInvoke = Expression.Call(fnNew, fnNew.Type.GetMethod("invoke", System.Type.EmptyTypes));

                Expression tryCatch = Expression.TryCatchFinally(fnInvoke, popExpr);

                Expression body = Expression.Block(pushNSExpr, tryCatch);

                // create initializer call
                MethodBuilder mbInit = initTB.DefineMethod("Initialize", MethodAttributes.Public | MethodAttributes.Static);
                LambdaExpression initFn = Expression.Lambda(body);
                //initFn.CompileToMethod(mbInit, DebugInfoGenerator.CreatePdbGenerator());
                initFn.CompileToMethod(mbInit, context.IsDebuggable);

                initTB.CreateType();

                context.SaveAssembly();
            }
            catch (LispReader.ReaderException e)
            {
                throw new CompilerException(sourceName, e.Line, e.InnerException);
            }
            finally
            {
                Var.popThreadBindings();
            }
            return null;
        }
Пример #26
0
 internal void AddMethod(FnMethod method)
 {
     _methods = RT.conj(_methods,method);
 }
Пример #27
0
        internal static FnMethod Parse(FnExpr fn, ISeq form, bool isStatic)
        {
            // ([args] body ... )

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

            try
            {
                FnMethod method = new FnMethod(fn, (ObjMethod)Compiler.METHOD.deref());

                Var.pushThreadBindings(RT.map(
                    Compiler.METHOD, method,
                    Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(),
                    Compiler.LOOP_LOCALS, null,
                    Compiler.NEXT_LOCAL_NUM, 0));

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

                method._retType = Compiler.TagType(Compiler.TagOf(parms));
                if (method._retType.IsPrimitive && !(method._retType == typeof(double) || method._retType == typeof(long)))
                    throw new ArgumentException("Only long and double primitives are supported");

                // register 'this' as local 0
                if ( !isStatic )
                    method._thisBinding = Compiler.RegisterLocal(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null,false);

                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 ArgumentException("fn params must be Symbols");
                    Symbol p = (Symbol)parms.nth(i);
                    if (p.Namespace != null)
                        throw new Exception("Can't use qualified name as parameter: " + p);
                    if (p.Equals(Compiler._AMP_))
                    {
                        //if (isStatic)
                        //    throw new Exception("Variadic fns cannot be static");

                        if (paramState == ParamParseState.Required)
                            paramState = ParamParseState.Rest;
                        else
                            throw new Exception("Invalid parameter list");
                    }
                    else
                    {
                        Type pt = Compiler.PrimType(Compiler.TagType(Compiler.TagOf(p)));
                        //if (pt.IsPrimitive && !isStatic)
                        //{
                        //    pt = typeof(object);
                        //    p = (Symbol)((IObj)p).withMeta((IPersistentMap)RT.assoc(RT.meta(p), RT.TAG_KEY, null));
                        //    //throw new Exception("Non-static fn can't have primitive parameter: " + p);
                        //}
                        if (pt.IsPrimitive && !(pt == typeof(double) || pt == typeof(long)))
                            throw new ArgumentException("Only long and double primitives are supported: " + p);

                        if (paramState == ParamParseState.Rest && Compiler.TagOf(p) != null)
                            throw new Exception("& arg cannot have type hint");
                        if (paramState == ParamParseState.Rest && method.Prim != null)
                            throw new Exception("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), true)
                            : Compiler.RegisterLocal(p,
                            paramState == ParamParseState.Rest ? Compiler.ISEQ : Compiler.TagOf(p),
                            null,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 Exception("Unexpected parameter");
                        }
                    }
                }

                if (method.NumParams > Compiler.MAX_POSITIONAL_ARITY)
                    throw new Exception(string.Format("Can't specify more than {0} parameters", Compiler.MAX_POSITIONAL_ARITY));
                Compiler.LOOP_LOCALS.set(argLocals);
                method._argLocals = argLocals;
                //if (isStatic)
                if ( method.Prim != null )
                    method._argTypes = argTypes.ToArray();
                method._body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return),body);
                return method;
            }
            finally
            {
                Var.popThreadBindings();
            }
        }