clojure.lang.CljCompiler.Ast.FnExpr.Parse C# (CSharp) Метод

Parse() приватный Метод

private Parse ( ParserContext pcon, ISeq form, string name ) : clojure.lang.CljCompiler.Ast.Expr
pcon ParserContext
form ISeq
name string
Результат clojure.lang.CljCompiler.Ast.Expr
        public static Expr Parse(ParserContext pcon, ISeq form, string name)
        {
            ISeq origForm = form;

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

            Keyword retKey = Keyword.intern(null, "rettag");  // TODO: make static
            object retTag = RT.get(RT.meta(form), retKey);
            ObjMethod enclosingMethod = (ObjMethod)Compiler.MethodVar.deref();
            fn._hasEnclosingMethod = enclosingMethod != null;


            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
             Symbol nm = RT.second(form) as Symbol;
            if (nm != null)
            {
                fn.ThisName = nm.Name;
                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;
                    bool usesThis = false;

                    for (ISeq s = RT.next(form); s != null; s = RT.next(s))
                    {
                        FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s), retTag);
                        if ( f.UsesThis)
                        {
                            //Console.WriteLine("{0} uses this",fn.Name);
                            usesThis = true;
                        }
                        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.");

                    fn.CanBeDirect = !fn._hasEnclosingMethod && fn.Closes.count() == 0 && !usesThis;

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

                    if ( fn.CanBeDirect )
                    {
                        for (ISeq s = RT.seq(allMethods); s != null; s = s.next())
                        {
                            FnMethod fm = s.first() as FnMethod;
                            if ( fm.Locals != null)
                            {
                                for (ISeq sl = RT.seq(RT.keys(fm.Locals)); sl != null; sl = sl.next())
                                {
                                    LocalBinding lb = sl.first() as LocalBinding;
                                    if ( lb.IsArg)
                                        lb.Index -= 1;
                                }
                            }
                        }
                    }

                    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).without(retKey);
                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();
            }
        }