Пример #1
0
        /// <summary>
        /// Returns the key/value pair for this key.
        /// </summary>
        /// <param name="key">The key to retrieve</param>
        /// <returns>The key/value pair for the key, or null if the key is not in the map.</returns>
        public override IMapEntry entryAt(object key)
        {
            IMapEntry me = _def.Keyslots.entryAt(key);

            return(me == null
                ? _ext.entryAt(key)
                : new MapEntry(me.key(), _vals[Util.ConvertToInt(me.val())]));
        }
        public void EntryAtOnIndexInRangeReturnsEntry()
        {
            CPV v = new CPV(new object[] { 4, 5, 6 });

            IMapEntry me = v.entryAt(1);

            Expect(me.key(), EqualTo(1));
            Expect(me.val(), EqualTo(5));
        }
Пример #3
0
        private static CustomAttributeBuilder CreateCustomAttributeBuilder(IMapEntry me)
        {
            Type           t    = (Type)me.key();
            IPersistentMap args = (IPersistentMap)me.val();

            object[] ctorArgs  = new object[0];
            Type[]   ctorTypes = Type.EmptyTypes;

            List <PropertyInfo> pInfos = new List <PropertyInfo>();
            List <Object>       pVals  = new List <object>();
            List <FieldInfo>    fInfos = new List <FieldInfo>();
            List <Object>       fVals  = new List <object>();

            for (ISeq s = RT.seq(args); s != null; s = s.next())
            {
                IMapEntry m2 = (IMapEntry)s.first();
                Keyword   k  = (Keyword)m2.key();
                object    v  = m2.val();
                if (k == ARGS_KEY)
                {
                    ctorArgs  = GetCtorArgs((IPersistentVector)v);
                    ctorTypes = GetCtorTypes(ctorArgs);
                }
                else
                {
                    string       name  = k.Name;
                    PropertyInfo pInfo = t.GetProperty(name);
                    if (pInfo != null)
                    {
                        pInfos.Add(pInfo);
                        pVals.Add(v);
                        continue;
                    }

                    FieldInfo fInfo = t.GetField(name);
                    if (fInfo != null)
                    {
                        fInfos.Add(fInfo);
                        fVals.Add(v);
                        continue;
                    }
                    throw new ArgumentException(String.Format("Unknown field/property: {0} for attribute: {1}", k.Name, t.FullName));
                }
            }

            ConstructorInfo ctor = t.GetConstructor(ctorTypes);

            if (ctor == null)
            {
                throw new ArgumentException(String.Format("Unable to find constructor for attribute: {0}", t.FullName));
            }

            CustomAttributeBuilder cb = new CustomAttributeBuilder(ctor, ctorArgs, pInfos.ToArray(), pVals.ToArray(), fInfos.ToArray(), fVals.ToArray());

            return(cb);
        }
Пример #4
0
        public void SeqOnNonEmptyIterates()
        {
            Dictionary <int, string> d = new Dictionary <int, string>();

            d[1] = "a";
            d[2] = "b";
            IPersistentMap m   = PersistentArrayMap.create(d);
            ISeq           s   = m.seq();
            IMapEntry      me1 = (IMapEntry)s.first();
            IMapEntry      me2 = (IMapEntry)s.next().first();
            ISeq           end = s.next().next();

            Expect(s.count(), EqualTo(2));
            Expect(me1.key(), EqualTo(1) | EqualTo(2));
            Expect(me1.val(), EqualTo(((int)me1.key() == 1 ? "a" : "b")));
            Expect(me2.key(), EqualTo(1) | EqualTo(2));
            Expect(me2.val(), EqualTo(((int)me2.key() == 1 ? "a" : "b")));
            Expect(end, Null);
        }
Пример #5
0
        public void EntryAtOnExistingKeyWorks()
        {
            MapEntry  me  = new MapEntry(1, "abc");
            IMapEntry me1 = me.entryAt(0);
            IMapEntry me2 = me.entryAt(1);

            Expect(me1.key()).To.Equal(0);
            Expect(me1.val()).To.Equal(1);
            Expect(me2.key()).To.Equal(1);
            Expect(me2.val()).To.Equal("abc");
        }
Пример #6
0
            private static IPersistentVector flattenMap(object form)
            {
                IPersistentVector keyvals = PersistentVector.EMPTY;

                for (ISeq s = RT.seq(form); s != null; s = s.next())
                {
                    IMapEntry e = (IMapEntry)s.first();
                    keyvals = (IPersistentVector)keyvals.cons(e.key());
                    keyvals = (IPersistentVector)keyvals.cons(e.val());
                }
                return(keyvals);
            }
Пример #7
0
        public void EntryAtReturnsEntryforKey()
        {
            Dictionary <int, string> d = new Dictionary <int, string>();

            d[1] = "a";
            d[2] = "b";

            IPersistentMap m  = PersistentArrayMap.create(d);
            IMapEntry      me = m.entryAt(1);

            Expect(me.key(), EqualTo(1));
            Expect(me.val(), EqualTo("a"));
        }
Пример #8
0
        public static Associative getThreadBindings()
        {
            Frame          f   = CurrentFrame;
            IPersistentMap ret = PersistentHashMap.EMPTY;

            for (ISeq bs = f.Bindings.seq(); bs != null; bs = bs.next())
            {
                IMapEntry e = (IMapEntry)bs.first();
                Var       v = (Var)e.key();
                TBox      b = (TBox)e.val();
                ret = ret.assoc(v, b.Val);
            }
            return(ret);
        }
Пример #9
0
        public void IDictionary_GetEnumerator_returns_an_enumerator()
        {
            Dictionary <int, string> d = new Dictionary <int, string>();

            d[1] = "a";
            d[2] = "b";

            IDictionary           id = (IDictionary)PersistentArrayMap.create(d);
            IDictionaryEnumerator e  = id.GetEnumerator();

            Expect(e.MoveNext());
            IMapEntry de1 = (IMapEntry)e.Current;

            Expect(e.MoveNext());
            IMapEntry de2 = (IMapEntry)e.Current;

            Expect(e.MoveNext(), False);

            Expect(de1.key(), EqualTo(1) | EqualTo(2));
            Expect(de2.key(), EqualTo(1) | EqualTo(2));
            Expect(de1.val(), EqualTo(((int)de1.key()) == 1 ? "a" : "b"));
            Expect(de2.val(), EqualTo(((int)de2.key()) == 1 ? "a" : "b"));
        }
Пример #10
0
        public static Expr Parse(IPersistentMap form)
        {
            IPersistentVector keyvals = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form); s != null; s = s.next())
            {
                IMapEntry e = (IMapEntry)s.first();
                keyvals = (IPersistentVector)keyvals.cons(Compiler.GenerateAST(e.key()));
                keyvals = (IPersistentVector)keyvals.cons(Compiler.GenerateAST(e.val()));
            }
            Expr ret = new MapExpr(keyvals);

            return(Compiler.OptionallyGenerateMetaInit(form, ret));
        }
Пример #11
0
        /// <summary>
        /// Get the method for a dispatch value and cache it.
        /// </summary>
        /// <param name="dispatchVal">The disaptch value.</param>
        /// <returns>The mest method.</returns>
        private IFn FindAndCacheBestMethod(object dispatchVal)
        {
            IMapEntry bestEntry = null;

            foreach (IMapEntry me in MethodTable)
            {
                if (IsA(dispatchVal, me.key()))
                {
                    if (bestEntry == null || Dominates(me.key(), bestEntry.key()))
                    {
                        bestEntry = me;
                    }
                    if (!Dominates(bestEntry.key(), me.key()))
                    {
                        throw new ArgumentException(String.Format("Multiple methods in multimethod {0} match dispatch value: {1} -> {2} and {3}, and neither is preferred",
                                                                  _name, dispatchVal, me.key(), bestEntry.key()));
                    }
                }
            }
            if (bestEntry == null)
            {
                return(null);
            }

            // ensure basis has stayed stable throughout, else redo
            if (_cachedHierarchy == _hierarchy.deref())
            {
                // place in cache
                _methodCache = _methodCache.assoc(dispatchVal, bestEntry.val());
                return((IFn)bestEntry.val());
            }
            else
            {
                ResetCache();
                return(FindAndCacheBestMethod(dispatchVal));
            }
        }
Пример #12
0
        /// <summary>
        /// Push a new frame of bindings onto the binding stack.
        /// </summary>
        /// <param name="bindings">The new bindings.</param>
        /// <remarks>Lowercase name for core.clj compatability.</remarks>
        public static void pushThreadBindings(Associative bindings)
        {
            Frame       f    = CurrentFrame;
            Associative bmap = f.Bindings;

            for (ISeq bs = bindings.seq(); bs != null; bs = bs.next())
            {
                IMapEntry e = (IMapEntry)bs.first();
                Var       v = (Var)e.key();
                v.Validate(e.val());
                v._count.incrementAndGet();
                bmap = bmap.assoc(v, new Box(e.val()));
            }
            CurrentFrame = new Frame(bindings, bmap, f);
        }
Пример #13
0
        private static List <CustomAttributeBuilder> CreateCustomAttributeBuilders(IMapEntry me)
        {
            Type           t     = (Type)me.key();
            IPersistentSet inits = (IPersistentSet)me.val();

            List <CustomAttributeBuilder> builders = new List <CustomAttributeBuilder>(inits.count());

            for (ISeq s = RT.seq(inits); s != null; s = s.next())
            {
                IPersistentMap init = (IPersistentMap)s.first();
                builders.Add(CreateCustomAttributeBuilder(t, init));
            }

            return(builders);
        }
Пример #14
0
            public override object first()
            {
                object    entry = _seq.first();
                IMapEntry me    = entry as IMapEntry;

                if (me != null)
                {
                    return(me.key());
                }
                else if (entry is DictionaryEntry)
                {
                    return(((DictionaryEntry)entry).Key);
                }
                throw new InvalidCastException("Cannot convert hashtable entry to IMapEntry or DictionaryEntry");
            }
Пример #15
0
        public static Expr Parse(ParserContext pcon, IPersistentMap form)
        {
            ParserContext pconToUse = pcon.EvalOrExpr();

            bool           keysConstant          = true;
            bool           valsConstant          = true;
            bool           allConstantKeysUnique = true;
            IPersistentSet constantKeys          = PersistentHashSet.EMPTY;

            IPersistentVector keyvals = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form); s != null; s = s.next())
            {
                IMapEntry e = (IMapEntry)s.first();
                Expr      k = Compiler.Analyze(pconToUse, e.key());
                Expr      v = Compiler.Analyze(pconToUse, e.val());
                keyvals = (IPersistentVector)keyvals.cons(k);
                keyvals = (IPersistentVector)keyvals.cons(v);
                if (k is LiteralExpr)
                {
                    object kval = k.Eval();
                    if (constantKeys.contains(kval))
                    {
                        allConstantKeysUnique = false;
                    }
                    else
                    {
                        constantKeys = (IPersistentSet)constantKeys.cons(kval);
                    }
                }
                else
                {
                    keysConstant = false;
                }
                if (!(v is LiteralExpr))
                {
                    valsConstant = false;
                }
            }

            Expr ret = new MapExpr(keyvals);

            if (form is IObj iobjForm && iobjForm.meta() != null)
            {
                return(Compiler.OptionallyGenerateMetaInit(pcon, form, ret));
            }
Пример #16
0
        /// <summary>
        /// Notify all watchers.
        /// </summary>
        public void notifyWatches(object oldval, object newval)
        {
            IPersistentMap ws = _watches;

            if (ws.count() > 0)
            {
                for (ISeq s = ws.seq(); s != null; s = s.next())
                {
                    IMapEntry me = (IMapEntry)s.first();
                    IFn       fn = (IFn)me.val();
                    if (fn != null)
                    {
                        fn.invoke(me.key(), this, oldval, newval);
                    }
                }
            }
        }
Пример #17
0
        public static void pushThreadBindings(Associative bindings)
        {
            Frame       f    = CurrentFrame;
            Associative bmap = f.Bindings;

            for (ISeq bs = bindings.seq(); bs != null; bs = bs.next())
            {
                IMapEntry e = (IMapEntry)bs.first();
                Var       v = (Var)e.key();
                if (!v._dynamic)
                {
                    throw new InvalidOperationException(String.Format("Can't dynamically bind non-dynamic var: {0}/{1}", v.Namespace, v.Symbol));
                }
                v.Validate(e.val());
                v._threadBound.set(true);
                bmap = bmap.assoc(v, new TBox(Thread.CurrentThread, e.val()));
            }
            CurrentFrame = new Frame(bmap, f);
        }
Пример #18
0
        public static Expr Parse(ParserContext pcon, IPersistentMap form)
        {
            ParserContext pconToUse = pcon.EvalOrExpr();
            bool          constant  = true;

            IPersistentVector keyvals = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form); s != null; s = s.next())
            {
                IMapEntry e = (IMapEntry)s.first();
                Expr      k = Compiler.Analyze(pconToUse, e.key());
                Expr      v = Compiler.Analyze(pconToUse, e.val());
                keyvals = (IPersistentVector)keyvals.cons(k);
                keyvals = (IPersistentVector)keyvals.cons(v);
                if (!(k is LiteralExpr && v is LiteralExpr))
                {
                    constant = false;
                }
            }
            Expr ret = new MapExpr(keyvals);

            IObj iobjForm = form as IObj;

            if (iobjForm != null && iobjForm.meta() != null)
            {
                return(Compiler.OptionallyGenerateMetaInit(pcon, form, ret));
            }
            else if (constant)
            {
                // This 'optimzation' works, mostly, unless you have nested map values.
                // The nested map values do not participate in the constants map, so you end up with the code to create the keys.
                // Result: huge duplication of keyword creation.  3X increase in init time to the REPL.
                //IPersistentMap m = PersistentHashMap.EMPTY;
                //for (int i = 0; i < keyvals.length(); i += 2)
                //    m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val);
                //return new ConstantExpr(m);
                return(ret);
            }
            else
            {
                return(ret);
            }
        }
Пример #19
0
        public ITransientMap conj(object val)
        {
            EnsureEditable();

            {
                IMapEntry e = val as IMapEntry;
                if (e != null)
                {
                    return(assoc(e.key(), e.val()));
                }
            }

            if (val is DictionaryEntry)
            {
                DictionaryEntry de = (DictionaryEntry)val;
                return(assoc(de.Key, de.Value));
            }

            {
                IPersistentVector v = val as IPersistentVector;
                if (v != null)
                {
                    if (v.count() != 2)
                    {
                        throw new ArgumentException("Vector arg to map conj must be a pair");
                    }
                    return(assoc(v.nth(0), v.nth(1)));
                }
            }

            // TODO: also handle KeyValuePair?
            ITransientMap ret = this;

            for (ISeq es = RT.seq(val); es != null; es = es.next())
            {
                IMapEntry e = (IMapEntry)es.first();
                ret = ret.assoc(e.key(), e.val());
            }
            return(ret);
        }
Пример #20
0
        private static CustomAttributeBuilder CreateCustomAttributeBuilder(IMapEntry me)
        {
            Type t = (Type) me.key();
            IPersistentMap args = (IPersistentMap)me.val();

            object[] ctorArgs = new object[0];
            Type[] ctorTypes = Type.EmptyTypes;

            List<PropertyInfo> pInfos = new List<PropertyInfo>();
            List<Object> pVals = new List<object>();
            List<FieldInfo> fInfos = new List<FieldInfo>();
            List<Object> fVals = new List<object>();

            for (ISeq s = RT.seq(args); s != null; s = s.next())
            {
                IMapEntry m2 = (IMapEntry)s.first();
                Keyword k = (Keyword) m2.key();
                object v = m2.val();
                if (k == ARGS_KEY)
                {
                    ctorArgs = GetCtorArgs((IPersistentVector)v);
                    ctorTypes = GetCtorTypes(ctorArgs);
                }
                else
                {
                    string name = k.Name;
                    PropertyInfo pInfo = t.GetProperty(name);
                    if (pInfo != null)
                    {
                        pInfos.Add(pInfo);
                        pVals.Add(v);
                        continue;
                    }

                    FieldInfo fInfo = t.GetField(name);
                    if (fInfo != null)
                    {
                        fInfos.Add(fInfo);
                        fVals.Add(v);
                        continue;
                    }
                    throw new ArgumentException(String.Format("Unknown field/property: {0} for attribute: {1}", k.Name, t.FullName));
                }
            }

            ConstructorInfo ctor = t.GetConstructor(ctorTypes);
            if (ctor == null)
                throw new ArgumentException(String.Format("Unable to find constructor for attribute: {0}", t.FullName));

            CustomAttributeBuilder cb = new CustomAttributeBuilder(ctor,ctorArgs,pInfos.ToArray(),pVals.ToArray(),fInfos.ToArray(),fVals.ToArray());

            return cb;
        }
Пример #21
0
        private static void EmitExposers(TypeBuilder proxyTB, Type superClass, IPersistentMap exposesFields)
        {
            for (ISeq s = RT.seq(exposesFields); s != null; s = s.next())
            {
                IMapEntry      me = (IMapEntry)s.first();
                Symbol         protectedFieldSym = (Symbol)me.key();
                IPersistentMap accessMap         = (IPersistentMap)me.val();

                string fieldName = protectedFieldSym.Name;
                Symbol getterSym = (Symbol)accessMap.valAt(_getKw, null);
                Symbol setterSym = (Symbol)accessMap.valAt(_setKW, null);

                FieldInfo fld = null;

                if (getterSym != null || setterSym != null)
                {
                    fld = superClass.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Instance);
                }


                if (getterSym != null)
                {
                    MethodAttributes attribs = MethodAttributes.Public;
                    if (fld.IsStatic)
                    {
                        attribs |= MethodAttributes.Static;
                    }

                    MethodBuilder mb  = proxyTB.DefineMethod(getterSym.Name, attribs, fld.FieldType, Type.EmptyTypes);
                    CljILGen      gen = new CljILGen(mb.GetILGenerator());
                    //if (fld.IsStatic)
                    //    gen.Emit(OpCodes.Ldsfld, fld);
                    //else
                    //{
                    //    gen.Emit(OpCodes.Ldarg_0);
                    //    gen.Emit(OpCodes.Ldfld, fld);
                    //}
                    if (!fld.IsStatic)
                    {
                        gen.EmitLoadArg(0);
                    }
                    gen.MaybeEmitVolatileOp(fld);
                    gen.EmitFieldGet(fld);

                    gen.Emit(OpCodes.Ret);
                }

                if (setterSym != null)
                {
                    MethodAttributes attribs = MethodAttributes.Public;
                    if (fld.IsStatic)
                    {
                        attribs |= MethodAttributes.Static;
                    }

                    MethodBuilder mb  = proxyTB.DefineMethod(setterSym.Name, attribs, typeof(void), new Type[] { fld.FieldType });
                    CljILGen      gen = new CljILGen(mb.GetILGenerator());
                    if (fld.IsStatic)
                    {
                        gen.Emit(OpCodes.Ldarg_0);
                        //gen.Emit(OpCodes.Stsfld, fld);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldarg_1);
                        //gen.Emit(OpCodes.Stfld, fld);
                    }
                    gen.MaybeEmitVolatileOp(fld);
                    gen.EmitFieldSet(fld);
                    gen.Emit(OpCodes.Ret);
                }
            }
        }
Пример #22
0
        static void DefineCtors(TypeBuilder proxyTB,
                                Type superClass,
                                string initName,
                                string postInitName,
                                ISeq ctors,
                                ISeq ctorTypes,
                                FieldBuilder initFB,
                                FieldBuilder postInitFB,
                                FieldBuilder stateFB,
                                string factoryName)
        {
            ISeq s1 = ctors;

            for (ISeq s = ctorTypes; s != null; s = s.next())
            {
                // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map.  Sigh.
                IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key()));
                s1 = s1.next();

                IMapEntry me = (IMapEntry)s.first();
                ISeq      thisParamTypesV = (ISeq)me.key();
                ISeq      baseParamTypesV = (ISeq)me.val();

                Type[] thisParamTypes = CreateTypeArray(thisParamTypesV);
                Type[] baseParamTypes = CreateTypeArray(baseParamTypesV);

                BindingFlags    flags     = BindingFlags.CreateInstance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
                ConstructorInfo superCtor = superClass.GetConstructor(flags, null, baseParamTypes, null);

                if (superCtor == null || superCtor.IsPrivate)
                {
                    throw new InvalidOperationException("Base class constructor missing or private");
                }

                ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes);
                GenInterface.SetCustomAttributes(cb, ctorAttributes);

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

                Label noInitLabel      = gen.DefineLabel();
                Label noPostInitLabel  = gen.DefineLabel();
                Label endPostInitLabel = gen.DefineLabel();
                Label endLabel         = gen.DefineLabel();

                LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object));
                LocalBuilder locInitVal   = gen.DeclareLocal(typeof(object));

                if (initFB != null)
                {
                    // init supplied
                    EmitGetVar(gen, initFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        }
                    }

                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]);

                    // Expecting:  [[super-ctor-args...] state]

                    // store the init return in a local
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Stloc, locInitVal);

                    // store the first element in a local
                    gen.EmitInt(0);                             // gen.Emit(OpCodes.Ldc_I4_0);
                    gen.EmitCall(Method_RT_nth);                // gen.Emit(OpCodes.Call, Method_RT_nth);
                    gen.Emit(OpCodes.Stloc, locSuperArgs);

                    // Stack this + super-ctor-args + call base-class ctor.
                    gen.EmitLoadArg(0);                         // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < baseParamTypes.Length; i++)
                    {
                        gen.Emit(OpCodes.Ldloc, locSuperArgs);
                        gen.EmitInt(i);                         // gen.Emit(OpCodes.Ldc_I4, i);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        if (baseParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]);
                        }
                        else
                        {
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                        }
                    }

                    gen.Emit(OpCodes.Call, superCtor);

                    if (stateFB != null)
                    {
                        gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldloc, locInitVal);
                        gen.EmitInt(1);                         // gen.Emit(OpCodes.Ldc_I4_1);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        gen.Emit(OpCodes.Castclass, typeof(object));
                        gen.EmitFieldSet(stateFB);              // gen.Emit(OpCodes.Stfld, stateFB);
                    }

                    gen.Emit(OpCodes.Br_S, endLabel);

                    // No init found
                    gen.MarkLabel(noInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, initName);

                    gen.MarkLabel(endLabel);
                }
                else  // no InitFB supplied.
                {
                    bool ok = thisParamTypes.Length == baseParamTypes.Length;
                    for (int i = 0; ok && i < thisParamTypes.Length; i++)
                    {
                        ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]);
                    }
                    if (!ok)
                    {
                        throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ");
                    }
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (baseParamTypes[i] != thisParamTypes[i])
                        {
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                        }
                    }
                    gen.Emit(OpCodes.Call, superCtor);
                }

                if (postInitFB != null)
                {
                    // post-init supplied
                    EmitGetVar(gen, postInitFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noPostInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                        {
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        }
                        gen.Emit(OpCodes.Castclass, thisParamTypes[i]);
                    }
                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);
                    gen.Emit(OpCodes.Pop);
                    gen.Emit(OpCodes.Br_S, endPostInitLabel);

                    // no post-init found

                    gen.MarkLabel(noPostInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, postInitName + " not defined");

                    gen.MarkLabel(endPostInitLabel);
                }

                gen.Emit(OpCodes.Ret);


                if (!String.IsNullOrEmpty(factoryName))
                {
                    MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes);
                    CljILGen      genf      = new CljILGen(factoryMB.GetILGenerator());

                    LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length];
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        locals[i] = genf.DeclareLocal(thisParamTypes[i]);
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                        genf.Emit(OpCodes.Stloc, locals[i]);
                    }


                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                    }
                    genf.EmitNew(cb);                           // genf.Emit(OpCodes.Newobj, cb);
                    genf.Emit(OpCodes.Ret);
                }
            }
        }
Пример #23
0
        /// <summary>
        /// Get the method for a dispatch value and cache it.
        /// </summary>
        /// <param name="dispatchVal">The disaptch value.</param>
        /// <returns>The mest method.</returns>
        private IFn FindAndCacheBestMethod(object dispatchVal)
        {
            _rw.EnterWriteLock();
            object         bestValue;
            IPersistentMap mt = _methodTable;
            IPersistentMap pt = _preferTable;
            object         ch = _cachedHierarchy;

            try
            {
                IMapEntry bestEntry = null;

                foreach (IMapEntry me in MethodTable)
                {
                    if (IsA(dispatchVal, me.key()))
                    {
                        if (bestEntry == null || Dominates(me.key(), bestEntry.key()))
                        {
                            bestEntry = me;
                        }
                        if (!Dominates(bestEntry.key(), me.key()))
                        {
                            throw new ArgumentException(String.Format("Multiple methods in multimethod {0} match dispatch value: {1} -> {2} and {3}, and neither is preferred",
                                                                      _name, dispatchVal, me.key(), bestEntry.key()));
                        }
                    }
                }
                if (bestEntry == null)
                {
                    bestValue = _methodTable.valAt(_defaultDispatchVal);
                    if (bestValue == null)
                    {
                        return(null);
                    }
                }
                else
                {
                    bestValue = bestEntry.val();
                }
            }
            finally
            {
                _rw.ExitWriteLock();
            }

            // ensure basis has stayed stable throughout, else redo
            _rw.EnterWriteLock();
            try
            {
                if (mt == _methodTable &&
                    pt == _preferTable &&
                    ch == _cachedHierarchy &&
                    _cachedHierarchy == _hierarchy.deref())
                {
                    // place in cache
                    _methodCache = _methodCache.assoc(dispatchVal, bestValue);
                    return((IFn)bestValue);
                }
                else
                {
                    ResetCache();
                    return(FindAndCacheBestMethod(dispatchVal));
                }
            }
            finally
            {
                _rw.ExitWriteLock();
            }
        }
Пример #24
0
        private static List<CustomAttributeBuilder> CreateCustomAttributeBuilders(IMapEntry me)
        {
 
            Type t = (Type)me.key();
            IPersistentSet inits = (IPersistentSet)me.val();

            List<CustomAttributeBuilder> builders = new List<CustomAttributeBuilder>(inits.count());

            for (ISeq s = RT.seq(inits); s != null; s = s.next())
            {
                IPersistentMap init = (IPersistentMap)s.first();
                builders.Add(CreateCustomAttributeBuilder(t, init));
            }

            return builders;
        }
Пример #25
0
        public static Expr Parse(ParserContext pcon, IPersistentMap form)
        {
            ParserContext pconToUse = pcon.EvalOrExpr();

            bool           keysConstant          = true;
            bool           valsConstant          = true;
            bool           allConstantKeysUnique = true;
            IPersistentSet constantKeys          = PersistentHashSet.EMPTY;

            IPersistentVector keyvals = PersistentVector.EMPTY;

            for (ISeq s = RT.seq(form); s != null; s = s.next())
            {
                IMapEntry e = (IMapEntry)s.first();
                Expr      k = Compiler.Analyze(pconToUse, e.key());
                Expr      v = Compiler.Analyze(pconToUse, e.val());
                keyvals = (IPersistentVector)keyvals.cons(k);
                keyvals = (IPersistentVector)keyvals.cons(v);
                if (k is LiteralExpr)
                {
                    object kval = k.Eval();
                    if (constantKeys.contains(kval))
                    {
                        allConstantKeysUnique = false;
                    }
                    else
                    {
                        constantKeys = (IPersistentSet)constantKeys.cons(kval);
                    }
                }
                else
                {
                    keysConstant = false;
                }
                if (!(v is LiteralExpr))
                {
                    valsConstant = false;
                }
            }

            Expr ret = new MapExpr(keyvals);

            IObj iobjForm = form as IObj;

            if (iobjForm != null && iobjForm.meta() != null)
            {
                return(Compiler.OptionallyGenerateMetaInit(pcon, form, ret));
            }
            //else if (constant)
            //{
            // This 'optimzation' works, mostly, unless you have nested map values.
            // The nested map values do not participate in the constants map, so you end up with the code to create the keys.
            // Result: huge duplication of keyword creation.  3X increase in init time to the REPL.
            //    //IPersistentMap m = PersistentHashMap.EMPTY;
            //    //for (int i = 0; i < keyvals.length(); i += 2)
            //    //    m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val);
            //    //return new ConstantExpr(m);
            //    return ret;
            //}
            else if (keysConstant)
            {
                // TBD: Add more detail to exception thrown below.
                if (!allConstantKeysUnique)
                {
                    throw new ArgumentException("Duplicate constant keys in map");
                }
                if (valsConstant)
                {
                    // This 'optimzation' works, mostly, unless you have nested map values.
                    // The nested map values do not participate in the constants map, so you end up with the code to create the keys.
                    // Result: huge duplication of keyword creation.  3X increase in init time to the REPL.
                    //IPersistentMap m = PersistentHashMap.EMPTY;
                    //for (int i = 0; i < keyvals.length(); i += 2)
                    //    m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val);
                    //return new ConstantExpr(m);
                    return(ret);
                }
                else
                {
                    return(ret);
                }
            }
            else
            {
                return(ret);
            }
        }
Пример #26
0
            protected override object Read(PushbackTextReader r, char caret, object opts)
            {
                int startLine = -1;
                int startCol  = -1;
                LineNumberingTextReader lntr = r as LineNumberingTextReader;

                if (lntr != null)
                {
                    startLine = lntr.LineNumber;
                    startCol  = lntr.ColumnNumber;
                }

                IPersistentMap metaAsMap;
                {
                    object meta = ReadAux(r, opts);

                    if (meta is Symbol || meta is String)
                    {
                        metaAsMap = RT.map(RT.TagKey, meta);
                    }
                    else if (meta is Keyword)
                    {
                        metaAsMap = RT.map(meta, true);
                    }
                    else if ((metaAsMap = meta as IPersistentMap) == null)
                    {
                        throw new ArgumentException("Metadata must be Symbol,Keyword,String or Map");
                    }
                }

                object o = ReadAux(r, opts);

                if (o is IMeta)
                {
                    if (startLine != -1 && o is ISeq)
                    {
                        metaAsMap = metaAsMap.assoc(RT.LineKey, startLine)
                                    .assoc(RT.ColumnKey, startCol)
                                    .assoc(RT.SourceSpanKey, RT.map(
                                               RT.StartLineKey, startLine,
                                               RT.StartColumnKey, startCol,
                                               RT.EndLineKey, lntr.LineNumber,
                                               RT.EndColumnKey, lntr.ColumnNumber));
                    }

                    if (o is IReference iref)
                    {
                        iref.resetMeta(metaAsMap);
                        return(o);
                    }
                    object ometa = RT.meta(o);
                    for (ISeq s = RT.seq(metaAsMap); s != null; s = s.next())
                    {
                        IMapEntry kv = (IMapEntry)s.first();
                        ometa = RT.assoc(ometa, kv.key(), kv.val());
                    }
                    return(((IObj)o).withMeta((IPersistentMap)ometa));
                }
                else
                {
                    throw new ArgumentException("Metadata can only be applied to IMetas");
                }
            }