Ejemplo n.º 1
0
            public Expr Parse(ParserContext pcon, object frm)
            {
                // frm is:  (reify this-name? [interfaces] (method-name [args] body)* )
                ISeq      form            = (ISeq)frm;
                ObjMethod enclosingMethod = (ObjMethod)Compiler.MethodVar.deref();
                string    baseName        = enclosingMethod != null
                    ? (ObjExpr.TrimGenId(enclosingMethod.Objx.Name) + "$")
                    : (Compiler.munge(Compiler.CurrentNamespace.Name.Name) + "$");
                string simpleName = "reify__" + RT.nextID();
                string className  = baseName + simpleName;

                ISeq rform = RT.next(form);

                IPersistentVector interfaces = ((IPersistentVector)RT.first(rform)).cons(Symbol.intern("clojure.lang.IObj"));

                rform = RT.next(rform);

                ObjExpr ret  = Build(interfaces, null, null, className, Symbol.intern(className), null, rform, frm);
                IObj    iobj = frm as IObj;

                if (iobj != null && iobj.meta() != null)
                {
                    return(new MetaExpr(ret, MapExpr.Parse(pcon.EvalOrExpr(), iobj.meta())));
                }
                else
                {
                    return(ret);
                }
            }
Ejemplo n.º 2
0
            public Expr Parse(ParserContext pcon, object frms)
            {
                ISeq forms = (ISeq)frms;

                if (Util.equals(RT.first(forms), Compiler.DoSym))
                {
                    forms = RT.next(forms);
                }

                IPersistentVector exprs = PersistentVector.EMPTY;

                for (; forms != null; forms = forms.next())
                {
                    Expr e = (pcon.Rhc != RHC.Eval && (pcon.Rhc == RHC.Statement || forms.next() != null))
                        ? Compiler.Analyze(pcon.SetRhc(RHC.Statement), forms.first())
                        : Compiler.Analyze(pcon, forms.first());
                    exprs = exprs.cons(e);
                }
                if (exprs.count() == 0)
                {
                    exprs = exprs.cons(Compiler.NilExprInstance);
                }

                return(new BodyExpr(exprs));
            }
Ejemplo n.º 3
0
 /// <summary>
 /// Gets the (immutable) value the reference is holding.
 /// </summary>
 /// <returns>The value</returns>
 public override object deref()
 {
     if (_errors != null)
     {
         throw new Exception("Agent has errors", (Exception)RT.first(_errors));
     }
     return(_state);
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Send a message to the agent.
        /// </summary>
        /// <param name="fn">The function to be called on the current state and the supplied arguments.</param>
        /// <param name="args">The extra arguments to the function.</param>
        /// <param name="solo"><value>true</value> means execute on its own thread (send-off);
        /// <value>false</value> means use a thread pool thread (send).</param>
        /// <returns>This agent.</returns>
        public object dispatch(IFn fn, ISeq args, Boolean solo)
        {
            if (_errors != null)
            {
                throw new Exception("Agent has errors", (Exception)RT.first(_errors));
            }
            Action action = new Action(this, fn, args, solo);

            DispatchAction(action);

            return(this);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        internal static Type[] CreateTypeArray(ISeq seq)
        {
            List <Type> types = new List <Type>();

            for (ISeq s = seq?.seq(); s != null; s = s.next())
            {
                Object o       = s.first();
                Type   oAsType = o as Type;
                if (oAsType != null)
                {
                    types.Add(oAsType);
                }
                else if (o is ISeq)
                {
                    object first         = RT.first(o);
                    Symbol firstAsSymbol = first as Symbol;
                    if (firstAsSymbol == null || !firstAsSymbol.Equals(HostExpr.ByRefSym))
                    {
                        throw new ArgumentException("First element of parameter definition is not by-ref");
                    }

                    Type secondAsType = RT.second(o) as Type;

                    if (secondAsType == null)
                    {
                        throw new ArgumentException("by-ref must be paired with a type");
                    }

                    types.Add(secondAsType.MakeByRefType());
                }
                else
                {
                    throw new ArgumentException("Bad parameter definition");
                }
            }

            if (types.Count == 0)
            {
                return(Type.EmptyTypes);
            }

            return(types.ToArray <Type>());
        }
Ejemplo n.º 7
0
            protected override object Read(PushbackTextReader r, char eq)
            {
                if (!RT.booleanCast(RT.READEVAL.deref()))
                {
                    throw new Exception("EvalReader not allowed when *read-eval* is false.");
                }
                Object o = read(r, true, null, true);

                if (o is Symbol)
                {
                    return(RT.classForName(o.ToString()));
                }
                else if (o is IPersistentList)
                {
                    Symbol fs = (Symbol)RT.first(o);
                    if (fs.Equals(THE_VAR))
                    {
                        Symbol vs = (Symbol)RT.second(o);
                        return(RT.var(vs.Namespace, vs.Name));  //Compiler.resolve((Symbol) RT.second(o),true);
                    }
                    if (fs.Name.EndsWith("."))
                    {
                        Object[] args = RT.toArray(RT.next(o));
                        return(Reflector.InvokeConstructor(RT.classForName(fs.Name.Substring(0, fs.Name.Length - 1)), args));
                    }
                    if (Compiler.NamesStaticMember(fs))
                    {
                        Object[] args = RT.toArray(RT.next(o));
                        return(Reflector.InvokeStaticMethod(fs.Namespace, fs.Name, args));
                    }
                    Object v = Compiler.maybeResolveIn(Compiler.CurrentNamespace, fs);
                    if (v is Var)
                    {
                        return(((IFn)v).applyTo(RT.next(o)));
                    }
                    throw new Exception("Can't resolve " + fs);
                }
                else
                {
                    throw new ArgumentException("Unsupported #= form");
                }
            }
Ejemplo n.º 8
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);
        }
Ejemplo n.º 9
0
            public Expr Parse(object frms)
            {
                ISeq forms = (ISeq)frms;

                if (Util.equals(RT.first(forms), Compiler.DO))
                {
                    forms = RT.next(forms);
                }

                IPersistentVector exprs = PersistentVector.EMPTY;

                for (ISeq s = forms; s != null; s = s.next())
                {
                    if (s.next() == null)
                    {
                        // in tail recurive position
                        try
                        {
                            Var.pushThreadBindings(PersistentHashMap.create(Compiler.IN_TAIL_POSITION, RT.T));
                            exprs = exprs.cons(Compiler.GenerateAST(s.first()));
                        }
                        finally
                        {
                            Var.popThreadBindings();
                        }
                    }
                    else
                    {
                        exprs = exprs.cons(Compiler.GenerateAST(s.first()));
                    }
                }
                if (exprs.count() == 0)
                {
                    exprs = exprs.cons(Compiler.NIL_EXPR);
                }

                return(new BodyExpr(exprs));
            }
Ejemplo n.º 10
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();
            }
        }
Ejemplo n.º 11
0
 public static bool HasPrimInterface(ISeq form)
 {
     return(RT.first(form) is IPersistentVector parms && IsPrimInterface(parms));
 }
Ejemplo n.º 12
0
            public Expr Parse(ParserContext pcon, object form)
            {
                ISeq sform = (ISeq)form;

                // form is one of:
                //  (. x fieldname-sym)
                //  (. x 0-ary-method)
                //  (. x propertyname-sym)
                //  (. x methodname-sym args)+
                //  (. x (methodname-sym args?))
                //  (. x (generic-m

                if (RT.Length(sform) < 3)
                {
                    throw new ParseException("Malformed member expression, expecting (. target member ... )");
                }

                string         source  = (string)Compiler.SourceVar.deref();
                IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();  // Compiler.GetSourceSpanMap(form);

                Symbol tag = Compiler.TagOf(sform);

                // determine static or instance
                // static target must be symbol, either fully.qualified.Typename or Typename that has been imported

                Type t = HostExpr.MaybeType(RT.second(sform), false);
                // at this point, t will be non-null if static

                Expr instance = null;

                if (t == null)
                {
                    instance = Compiler.Analyze(pcon.EvalOrExpr(), RT.second(sform));
                }

                bool isZeroArityCall = RT.Length(sform) == 3 && RT.third(sform) is Symbol;

                if (isZeroArityCall)
                {
                    PropertyInfo pinfo = null;
                    FieldInfo    finfo = null;

                    // TODO: Figure out if we want to handle the -propname otherwise.

                    bool   isPropName = false;
                    Symbol sym        = (Symbol)RT.third(sform);
                    if (sym.Name[0] == '-')
                    {
                        isPropName = true;
                        sym        = Symbol.intern(sym.Name.Substring(1));
                    }

                    string fieldName = Compiler.munge(sym.Name);
                    // The JVM version does not have to worry about Properties.  It captures 0-arity methods under fields.
                    // We have to put in special checks here for this.
                    // Also, when reflection is required, we have to capture 0-arity methods under the calls that
                    //   are generated by StaticFieldExpr and InstanceFieldExpr.
                    if (t != null)
                    {
                        if ((finfo = Reflector.GetField(t, fieldName, true)) != null)
                        {
                            return(new StaticFieldExpr(source, spanMap, tag, t, fieldName, finfo));
                        }
                        if ((pinfo = Reflector.GetProperty(t, fieldName, true)) != null)
                        {
                            return(new StaticPropertyExpr(source, spanMap, tag, t, fieldName, pinfo));
                        }
                        if (!isPropName && Reflector.GetArityZeroMethod(t, fieldName, true) != null)
                        {
                            return(new StaticMethodExpr(source, spanMap, tag, t, fieldName, null, new List <HostArg>()));
                        }
                        throw new MissingMemberException(t.Name, fieldName);
                    }
                    else if (instance != null && instance.HasClrType && instance.ClrType != null)
                    {
                        Type instanceType = instance.ClrType;
                        if ((finfo = Reflector.GetField(instanceType, fieldName, false)) != null)
                        {
                            return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, finfo));
                        }
                        if ((pinfo = Reflector.GetProperty(instanceType, fieldName, false)) != null)
                        {
                            return(new InstancePropertyExpr(source, spanMap, tag, instance, fieldName, pinfo));
                        }
                        if (!isPropName && Reflector.GetArityZeroMethod(instanceType, fieldName, false) != null)
                        {
                            return(new InstanceMethodExpr(source, spanMap, tag, instance, fieldName, null, new List <HostArg>()));
                        }
                        if (pcon.IsAssignContext)
                        {
                            return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null
                        }
                        else
                        {
                            return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName));
                        }
                    }
                    else
                    {
                        //  t is null, so we know this is not a static call
                        //  If instance is null, we are screwed anyway.
                        //  If instance is not null, then we don't have a type.
                        //  So we must be in an instance call to a property, field, or 0-arity method.
                        //  The code generated by InstanceFieldExpr/InstancePropertyExpr with a null FieldInfo/PropertyInfo
                        //     will generate code to do a runtime call to a Reflector method that will check all three.
                        //return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null
                        //return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName);
                        if (pcon.IsAssignContext)
                        {
                            return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null
                        }
                        else
                        {
                            return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName));
                        }
                    }
                }

                //ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form));

                ISeq        call;
                List <Type> typeArgs = null;

                object fourth = RT.fourth(sform);

                if (fourth is ISeq && RT.first(fourth) is Symbol && ((Symbol)RT.first(fourth)).Equals(TypeArgsSym))
                {
                    // We have a type args supplied for a generic method call
                    // (. thing methodname (type-args type1 ... ) args ...)
                    typeArgs = ParseGenericMethodTypeArgs(RT.next(fourth));
                    call     = RT.listStar(RT.third(sform), RT.next(RT.next(RT.next(RT.next(sform)))));
                }
                else
                {
                    call = RT.third(sform) is ISeq ? (ISeq)RT.third(sform) : RT.next(RT.next(sform));
                }

                if (!(RT.first(call) is Symbol))
                {
                    throw new ParseException("Malformed member exception");
                }

                string methodName = Compiler.munge(((Symbol)RT.first(call)).Name);

                List <HostArg> args = ParseArgs(pcon, RT.next(call));

                return(t != null
                    ? (MethodExpr)(new StaticMethodExpr(source, spanMap, tag, t, methodName, typeArgs, args))
                    : (MethodExpr)(new InstanceMethodExpr(source, spanMap, tag, instance, methodName, typeArgs, args)));
            }
Ejemplo n.º 13
0
            public Expr Parse(object frm)
            {
                ISeq form = (ISeq)frm;

                // form => (let  [var1 val1 var2 val2 ... ] body ... )
                //      or (loop [var1 val1 var2 val2 ... ] body ... )

                bool isLoop = RT.first(form).Equals(Compiler.LOOP);

                IPersistentVector bindings = RT.second(form) as IPersistentVector;

                if (bindings == null)
                {
                    throw new ArgumentException("Bad binding form, expected vector");
                }

                if ((bindings.count() % 2) != 0)
                {
                    throw new ArgumentException("Bad binding form, expected matched symbol/value pairs.");
                }

                ISeq body = RT.next(RT.next(form));

                // TODO: This is one place where context makes a difference.  Need to figure this out.
                //  Second test clause added in Rev 1216.
                // if (ctxt == C.EVAL || (context == c.EXPRESSION && isLoop))
                //    return Generate(RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)));

                // As of Rev 1216, I tried tjos out.
                // However, it goes into an infinite loop.  Still need to figure this out.
                //if (isLoop)
                //    Generate(RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)));

                IPersistentMap dynamicBindings = RT.map(
                    Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(),
                    Compiler.NEXT_LOCAL_NUM, Compiler.NEXT_LOCAL_NUM.deref());

                if (isLoop)
                {
                    dynamicBindings = dynamicBindings.assoc(Compiler.LOOP_LOCALS, null);
                }

                try
                {
                    Var.pushThreadBindings(dynamicBindings);

                    IPersistentVector bindingInits = PersistentVector.EMPTY;
                    IPersistentVector loopLocals   = PersistentVector.EMPTY;

                    for (int i = 0; i < bindings.count(); i += 2)
                    {
                        if (!(bindings.nth(i) is Symbol))
                        {
                            throw new ArgumentException("Bad binding form, expected symbol, got " + bindings.nth(i));
                        }

                        Symbol sym = (Symbol)bindings.nth(i);
                        if (sym.Namespace != null)
                        {
                            throw new Exception("Can't let qualified name: " + sym);
                        }

                        Expr init = Compiler.GenerateAST(bindings.nth(i + 1));
                        // Sequential enhancement of env (like Lisp let*)
                        LocalBinding b  = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init);
                        BindingInit  bi = new BindingInit(b, init);
                        bindingInits = bindingInits.cons(bi);

                        if (isLoop)
                        {
                            loopLocals = loopLocals.cons(b);
                        }
                    }
                    if (isLoop)
                    {
                        Compiler.LOOP_LOCALS.set(loopLocals);
                    }

                    return(new LetExpr(bindingInits,
                                       new BodyExpr.Parser().Parse(body),
                                       isLoop));
                }
                finally
                {
                    Var.popThreadBindings();
                }
            }
Ejemplo n.º 14
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();
                }
            }
        }
Ejemplo n.º 15
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);
        }
Ejemplo n.º 16
0
        public static NewInstanceMethod Parse(ObjExpr objx, ISeq form, Symbol thisTag, Dictionary <IPersistentVector, IList <MethodInfo> > overrideables, Dictionary <IPersistentVector, IList <MethodInfo> > explicits)
        {
            // (methodname [this-name args*] body...)
            // this-name might be nil

            NewInstanceMethod method = new NewInstanceMethod(objx, (ObjMethod)Compiler.MethodVar.deref());

            Symbol dotName = (Symbol)RT.first(form);
            Symbol name;
            string methodName;

            int idx = dotName.Name.LastIndexOf(".");

            if (idx >= 0)
            {
                // we have an explicit interface implementation
                string dotNameStr    = dotName.Name;
                string interfaceName = dotNameStr.Substring(0, idx);

                method.ExplicitInterface = RT.classForName(interfaceName);
                if (method.ExplicitInterface == null)
                {
                    throw new ParseException(String.Format("Unable to find interface {0} for explicit method implemntation: {1}", interfaceName, dotNameStr));
                }

                methodName = dotNameStr.Substring(idx + 1);
                name       = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName));
            }
            else
            {
                name       = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName));
                methodName = name.Name;
            }

            IPersistentVector parms = (IPersistentVector)RT.second(form);

            if (parms.count() == 0 || !(parms.nth(0) is Symbol))
            {
                throw new ParseException("Must supply at least one argument for 'this' in: " + dotName);
            }

            Symbol thisName = (Symbol)parms.nth(0);

            parms = RT.subvec(parms, 1, parms.count());
            ISeq body = RT.next(RT.next(form));

            try
            {
                method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();

                // register as the current method and set up a new env frame
                // PathNode pnade = new PathNode(PATHTYPE.PATH, (PathNode) CLEAR_PATH.get());
                Var.pushThreadBindings(
                    RT.mapUniqueKeys(
                        Compiler.MethodVar, method,
                        Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(),
                        Compiler.LoopLocalsVar, null,
                        Compiler.NextLocalNumVar, 0
                        // CLEAR_PATH, pnode,
                        // CLEAR_ROOT, pnode,
                        // CLEAR_SITES, PersistentHashMap.EMPTY
                        ));

                // register 'this' as local 0
                //method._thisBinding = Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null);
                Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null);

                IPersistentVector argLocals = PersistentVector.EMPTY;
                method._retType  = Compiler.TagType(Compiler.TagOf(name));
                method._argTypes = new Type[parms.count()];
                bool     hinted = Compiler.TagOf(name) != null;
                Type[]   pTypes = new Type[parms.count()];
                Symbol[] pSyms  = new Symbol[parms.count()];
                bool[]   pRefs  = new bool[parms.count()];

                for (int i = 0; i < parms.count(); i++)
                {
                    // Param should be symbol or (by-ref symbol)
                    Symbol p;
                    bool   isByRef = false;

                    object pobj = parms.nth(i);
                    if (pobj is Symbol)
                    {
                        p = (Symbol)pobj;
                    }
                    else if (pobj is ISeq)
                    {
                        ISeq   pseq   = (ISeq)pobj;
                        object first  = RT.first(pseq);
                        object second = RT.second(pseq);
                        if (!(first is Symbol && ((Symbol)first).Equals(HostExpr.ByRefSym)))
                        {
                            throw new ParseException("First element in parameter pair must be by-ref");
                        }
                        if (!(second is Symbol))
                        {
                            throw new ParseException("Params must be Symbols");
                        }
                        isByRef = true;
                        p       = (Symbol)second;
                        hinted  = true;
                    }
                    else
                    {
                        throw new ParseException("Params must be Symbols or of the form (by-ref Symbol)");
                    }

                    object tag = Compiler.TagOf(p);
                    if (tag != null)
                    {
                        hinted = true;
                    }
                    if (p.Namespace != null)
                    {
                        p = Symbol.intern(p.Name);
                    }
                    Type pType = Compiler.TagType(tag);
                    if (isByRef)
                    {
                        pType = pType.MakeByRefType();
                    }

                    pTypes[i] = pType;
                    pSyms[i]  = p;
                    pRefs[i]  = isByRef;
                }

                Dictionary <IPersistentVector, IList <MethodInfo> > matches =
                    method.IsExplicit
                    ? FindMethodsWithNameAndArity(method.ExplicitInterface, methodName, parms.count(), overrideables, explicits)
                    : FindMethodsWithNameAndArity(methodName, parms.count(), overrideables);

                IPersistentVector  mk = MSig(methodName, pTypes, method._retType);
                IList <MethodInfo> ms = null;
                if (matches.Count > 0)
                {
                    // multiple matches
                    if (matches.Count > 1)
                    {
                        // must be hinted and match one method
                        if (!hinted)
                        {
                            throw new ParseException("Must hint overloaded method: " + name.Name);
                        }
                        if (!matches.TryGetValue(mk, out ms))
                        {
                            throw new ParseException("Can't find matching overloaded method: " + name.Name);
                        }

                        method._minfos = ms;
                    }
                    else // one match
                    {
                        // if hinted, validate match,
                        if (hinted)
                        {
                            if (!matches.TryGetValue(mk, out ms))
                            {
                                throw new ParseException("Can't find matching method: " + name.Name + ", leave off hints for auto match.");
                            }

                            method._minfos = ms;

                            //if (m.ReturnType != method._retType)
                            //    throw new ArgumentException(String.Format("Mismatched return type: {0}, expected {1}, had: {2}",
                            //        name.Name, m.ReturnType.Name, method._retType.Name));
                        }
                        else // adopt found method sig
                        {
                            using (var e = matches.GetEnumerator())
                            {
                                e.MoveNext();
                                mk = e.Current.Key;
                                ms = e.Current.Value;
                            }
                            MethodInfo m = ms[0];
                            method._retType = m.ReturnType;
                            pTypes          = Compiler.GetTypes(m.GetParameters());
                            method._minfos  = ms;
                        }
                    }
                }
                else
                {
                    throw new ParseException("Can't define method not in interfaces: " + name.Name);
                }

                if (method.IsExplicit)
                {
                    method.ExplicitMethodInfo = ms[0];
                }

                // validate unique name + arity among additional methods

                for (int i = 0; i < parms.count(); i++)
                {
                    LocalBinding lb = Compiler.RegisterLocal(pSyms[i], null, new MethodParamExpr(pTypes[i]), true, pRefs[i]);
                    argLocals           = argLocals.assocN(i, lb);
                    method._argTypes[i] = pTypes[i];
                }

                Compiler.LoopLocalsVar.set(argLocals);
                method._name      = name.Name;
                method.MethodMeta = GenInterface.ExtractAttributes(RT.meta(name));
                method.Parms      = parms;
                method.ArgLocals  = argLocals;
                method.Body       = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body);
                return(method);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
Ejemplo n.º 17
0
        public static bool HasPrimInterface(ISeq form)
        {
            IPersistentVector parms = RT.first(form) as IPersistentVector;

            return(parms != null && IsPrimInterface(parms));
        }
Ejemplo n.º 18
0
 static bool isUnquoteSplicing(object form)
 {
     return(form is ISeq && Util.equals(RT.first(form), UNQUOTE_SPLICING));
 }
Ejemplo n.º 19
0
 // Per rev 1184
 static bool isUnquote(object form)
 {
     return(form is ISeq && Util.equals(RT.first(form), UNQUOTE));
 }
Ejemplo n.º 20
0
            public Expr Parse(object frm)
            {
                ISeq form = (ISeq)frm;

                // form is one of:
                //  (. x fieldname-sym)
                //  (. x 0-ary-method)
                //  (. x propertyname-sym)
                //  (. x methodname-sym args+)
                //  (. x (methodname-sym args?))

                if (RT.Length(form) < 3)
                {
                    throw new ArgumentException("Malformed member expression, expecting (. target member ... )");
                }

                // determine static or instance
                // static target must be symbol, either fully.qualified.Typename or Typename that has been imported

                Type t = Compiler.MaybeType(RT.second(form), false);
                // at this point, t will be non-null if static

                Expr instance = null;

                if (t == null)
                {
                    instance = Compiler.GenerateAST(RT.second(form));
                }

                bool isFieldOrProperty = false;

                if (RT.Length(form) == 3 && RT.third(form) is Symbol)
                {
                    Symbol sym = (Symbol)RT.third(form);
                    if (t != null)
                    {
                        isFieldOrProperty =
                            t.GetField(sym.Name, BindingFlags.Static | BindingFlags.Public) != null ||
                            t.GetProperty(sym.Name, BindingFlags.Static | BindingFlags.Public) != null;
                    }
                    else if (instance != null && instance.HasClrType && instance.ClrType != null)
                    {
                        Type instanceType = instance.ClrType;
                        isFieldOrProperty =
                            instanceType.GetField(sym.Name, BindingFlags.Instance | BindingFlags.Public) != null ||
                            instanceType.GetProperty(sym.Name, BindingFlags.Instance | BindingFlags.Public) != null;
                    }
                }

                if (isFieldOrProperty)
                {
                    Symbol sym = (Symbol)RT.third(form);
                    if (t != null)
                    {
                        return(new StaticFieldExpr(t, sym.Name));
                    }
                    else
                    {
                        return(new InstanceFieldExpr(instance, sym.Name));
                    }
                }


                ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form));

                if (!(RT.first(call) is Symbol))
                {
                    throw new ArgumentException("Malformed member exception");
                }

                string            methodName = ((Symbol)RT.first(call)).Name;
                IPersistentVector args       = PersistentVector.EMPTY;

                for (ISeq s = RT.next(call); s != null; s = s.next())
                {
                    args = args.cons(Compiler.GenerateAST(s.first()));
                }

                return(t != null
                    ? (MethodExpr)(new StaticMethodExpr(t, methodName, args))
                    : (MethodExpr)(new InstanceMethodExpr(instance, methodName, args)));
            }
Ejemplo n.º 21
0
            public Expr Parse(ParserContext pcon, object frm)
            {
                ISeq form = (ISeq)frm;

                // form => (let  [var1 val1 var2 val2 ... ] body ... )
                //      or (loop [var1 val1 var2 val2 ... ] body ... )

                bool isLoop = RT.first(form).Equals(Compiler.LoopSym);

                if (!(RT.second(form) is IPersistentVector bindings))
                {
                    throw new ParseException("Bad binding form, expected vector");
                }

                if ((bindings.count() % 2) != 0)
                {
                    throw new ParseException("Bad binding form, expected matched symbol/value pairs.");
                }

                ISeq body = RT.next(RT.next(form));

                if (pcon.Rhc == RHC.Eval ||
                    (pcon.Rhc == RHC.Expression && isLoop))
                {
                    return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID()));
                }

                ObjMethod      method                  = (ObjMethod)Compiler.MethodVar.deref();
                IPersistentMap backupMethodLocals      = method.Locals;
                IPersistentMap backupMethodIndexLocals = method.IndexLocals;

                IPersistentVector recurMismatches = PersistentVector.EMPTY;

                for (int i = 0; i < bindings.count() / 2; i++)
                {
                    recurMismatches = recurMismatches.cons(false);
                }

                // may repeat once for each binding with a mismatch, return breaks
                while (true)
                {
                    IPersistentMap dynamicBindings = RT.map(
                        Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(),
                        Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref());
                    method.SetLocals(backupMethodLocals, backupMethodIndexLocals);

                    if (isLoop)
                    {
                        dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null);
                    }

                    try
                    {
                        Var.pushThreadBindings(dynamicBindings);

                        IPersistentVector bindingInits = PersistentVector.EMPTY;
                        IPersistentVector loopLocals   = PersistentVector.EMPTY;

                        for (int i = 0; i < bindings.count(); i += 2)
                        {
                            if (!(bindings.nth(i) is Symbol))
                            {
                                throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i));
                            }

                            Symbol sym = (Symbol)bindings.nth(i);
                            if (sym.Namespace != null)
                            {
                                throw new ParseException("Can't let qualified name: " + sym);
                            }

                            Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name);
                            if (isLoop)
                            {
                                if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2)))
                                {
                                    HostArg        ha  = new HostArg(HostArg.ParameterType.Standard, init, null);
                                    List <HostArg> has = new List <HostArg>(1)
                                    {
                                        ha
                                    };
                                    init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false);
                                    if (RT.booleanCast(RT.WarnOnReflectionVar.deref()))
                                    {
                                        RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym);
                                    }
                                }
                                else if (Compiler.MaybePrimitiveType(init) == typeof(int))
                                {
                                    List <HostArg> args = new List <HostArg>
                                    {
                                        new HostArg(HostArg.ParameterType.Standard, init, null)
                                    };
                                    init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false);
                                }
                                else if (Compiler.MaybePrimitiveType(init) == typeof(float))
                                {
                                    List <HostArg> args = new List <HostArg>
                                    {
                                        new HostArg(HostArg.ParameterType.Standard, init, null)
                                    };
                                    init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false);
                                }
                            }

                            // Sequential enhancement of env (like Lisp let*)
                            LocalBinding b  = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, typeof(Object), false);
                            BindingInit  bi = new BindingInit(b, init);
                            bindingInits = bindingInits.cons(bi);

                            if (isLoop)
                            {
                                loopLocals = loopLocals.cons(b);
                            }
                        }
                        if (isLoop)
                        {
                            Compiler.LoopLocalsVar.set(loopLocals);
                        }

                        Expr bodyExpr;
                        bool moreMismatches = false;
                        try
                        {
                            if (isLoop)
                            {
                                object methodReturnContext = pcon.Rhc == RHC.Return ? Compiler.MethodReturnContextVar.deref() : null;
                                // stuff with clear paths,
                                Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null,
                                                              Compiler.MethodReturnContextVar, methodReturnContext));
                            }
                            bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body);
                        }
                        finally
                        {
                            if (isLoop)
                            {
                                Var.popThreadBindings();

                                for (int i = 0; i < loopLocals.count(); i++)
                                {
                                    LocalBinding lb = (LocalBinding)loopLocals.nth(i);
                                    if (lb.RecurMismatch)
                                    {
                                        recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true);
                                        moreMismatches  = true;
                                    }
                                }
                            }
                        }

                        if (!moreMismatches)
                        {
                            return(new LetExpr(bindingInits, bodyExpr, isLoop));
                        }
                    }
                    finally
                    {
                        Var.popThreadBindings();
                    }
                }
            }
Ejemplo n.º 22
0
 /// <summary>
 /// Peek at the top (first) element in the stack.
 /// </summary>
 /// <returns>The top (first) element.</returns>
 public object peek()
 {
     return(RT.first(_f));
 }
Ejemplo n.º 23
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);
        }
Ejemplo n.º 24
0
            public Expr Parse(ParserContext pcon, object form)
            {
                // (def x) or (def x initexpr) or (def x "docstring" initexpr)
                string docstring = null;

                if (RT.count(form) == 4 && (RT.third(form) is String))
                {
                    docstring = (String)RT.third(form);
                    form      = RT.list(RT.first(form), RT.second(form), RT.fourth(form));
                }

                if (RT.count(form) > 3)
                {
                    throw new ParseException("Too many arguments to def");
                }

                if (RT.count(form) < 2)
                {
                    throw new ParseException("Too few arguments to def");
                }

                Symbol sym = RT.second(form) as Symbol;

                if (sym == null)
                {
                    throw new ParseException("First argument to def must be a Symbol.");
                }

                //Console.WriteLine("Def {0}", sym.Name);

                Var v = Compiler.LookupVar(sym, true);

                if (v == null)
                {
                    throw new ParseException("Can't refer to qualified var that doesn't exist");
                }

                if (!v.Namespace.Equals(Compiler.CurrentNamespace))
                {
                    if (sym.Namespace == null)
                    {
                        v = Compiler.CurrentNamespace.intern(sym);
                        Compiler.RegisterVar(v);
                    }

                    //throw new Exception(string.Format("Name conflict, can't def {0} because namespace: {1} refers to: {2}",
                    //            sym, Compiler.CurrentNamespace.Name, v));
                    else
                    {
                        throw new ParseException("Can't create defs outside of current namespace");
                    }
                }

                IPersistentMap mm        = sym.meta();
                bool           isDynamic = RT.booleanCast(RT.get(mm, Compiler.DynamicKeyword));

                if (isDynamic)
                {
                    v.setDynamic();
                }
                if (!isDynamic && sym.Name.StartsWith("*") && sym.Name.EndsWith("*") && sym.Name.Length > 2)
                {
                    RT.errPrintWriter().WriteLine("Warning: {0} not declared dynamic and thus is not dynamically rebindable, "
                                                  + "but its name suggests otherwise. Please either indicate ^:dynamic {0} or change the name. ({1}:{2}\n",
                                                  sym, Compiler.SourcePathVar.get(), Compiler.LineVar.get());
                }

                if (RT.booleanCast(RT.get(mm, Compiler.ArglistsKeyword)))
                {
                    IPersistentMap vm = v.meta();
                    //vm = (IPersistentMap)RT.assoc(vm, Compiler.STATIC_KEY, true);
                    // drop quote
                    vm = (IPersistentMap)RT.assoc(vm, Compiler.ArglistsKeyword, RT.second(mm.valAt(Compiler.ArglistsKeyword)));
                    v.setMeta(vm);
                }

                Object source_path = Compiler.SourcePathVar.get();

                source_path = source_path ?? "NO_SOURCE_FILE";
                mm          = (IPersistentMap)RT.assoc(mm, RT.LineKey, Compiler.LineVar.get())
                              .assoc(RT.ColumnKey, Compiler.ColumnVar.get())
                              .assoc(RT.FileKey, source_path);
                //.assoc(RT.SOURCE_SPAN_KEY,Compiler.SOURCE_SPAN.deref());
                if (docstring != null)
                {
                    mm = (IPersistentMap)RT.assoc(mm, RT.DocKey, docstring);
                }

                //  Following comment in JVM version
                //mm = mm.without(RT.DOC_KEY)
                //            .without(Keyword.intern(null, "arglists"))
                //            .without(RT.FILE_KEY)
                //            .without(RT.LINE_KEY)
                //            .without(RT.COLUMN_KEY)
                //            .without(Keyword.intern(null, "ns"))
                //            .without(Keyword.intern(null, "name"))
                //            .without(Keyword.intern(null, "added"))
                //            .without(Keyword.intern(null, "static"));

                mm = (IPersistentMap)Compiler.ElideMeta(mm);

                Expr meta         = mm == null || mm.count() == 0 ? null : Compiler.Analyze(pcon.EvalOrExpr(), mm);
                Expr init         = Compiler.Analyze(pcon.EvalOrExpr(), RT.third(form), v.Symbol.Name);
                bool initProvided = RT.count(form) == 3;

                return(new DefExpr(
                           (string)Compiler.SourceVar.deref(),
                           Compiler.LineVarDeref(),
                           Compiler.ColumnVarDeref(),
                           v, init, meta, initProvided, isDynamic));
            }
Ejemplo n.º 25
0
            //(case* expr shift mask  default map<minhash, [test then]> table-type test-type skip-check?)
            //prepared by case macro and presumed correct
            //case macro binds actual expr in let so expr is always a local,
            //no need to worry about multiple evaluation
            public Expr Parse(ParserContext pcon, object frm)
            {
                ISeq form = (ISeq)frm;

                if (pcon.Rhc == RHC.Eval)
                {
                    return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "case__" + RT.nextID()));
                }

                IPersistentVector args = LazilyPersistentVector.create(form.next());

                object         exprForm    = args.nth(0);
                int            shift       = Util.ConvertToInt(args.nth(1));
                int            mask        = Util.ConvertToInt(args.nth(2));
                object         defaultForm = args.nth(3);
                IPersistentMap caseMap     = (IPersistentMap)args.nth(4);
                Keyword        switchType  = (Keyword)args.nth(5);
                Keyword        testType    = (Keyword)args.nth(6);
                IPersistentSet skipCheck   = RT.count(args) < 8 ? null : (IPersistentSet)args.nth(7);

                ISeq             keys     = RT.keys(caseMap);
                int              low      = Util.ConvertToInt(RT.first(keys));
                int              high     = Util.ConvertToInt(RT.nth(keys, RT.count(keys) - 1));
                LocalBindingExpr testexpr = (LocalBindingExpr)Compiler.Analyze(pcon.SetRhc(RHC.Expression), exprForm);


                SortedDictionary <int, Expr> tests = new SortedDictionary <int, Expr>();
                Dictionary <int, Expr>       thens = new Dictionary <int, Expr>();

                foreach (IMapEntry me in caseMap)
                {
                    int    minhash  = Util.ConvertToInt(me.key());
                    object pair     = me.val(); // [test-val then-expr]
                    object first    = RT.first(pair);
                    Expr   testExpr = testType == _intKey
                        ? NumberExpr.Parse(Util.ConvertToInt(first))
                        : (first == null ? Compiler.NilExprInstance : new ConstantExpr(first));

                    tests[minhash] = testExpr;
                    Expr thenExpr;
                    thenExpr       = Compiler.Analyze(pcon, RT.second(pair));
                    thens[minhash] = thenExpr;
                }

                Expr defaultExpr;

                defaultExpr = Compiler.Analyze(pcon, defaultForm);

                return(new CaseExpr(
                           (IPersistentMap)Compiler.SourceSpanVar.deref(),
                           testexpr,
                           shift,
                           mask,
                           low,
                           high,
                           defaultExpr,
                           tests,
                           thens,
                           switchType,
                           testType,
                           skipCheck));
            }
Ejemplo n.º 26
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();
            }
        }