Пример #1
0
            public Expr Parse(ParserContext pcon, object frm)
            {
                ISeq form = (ISeq)frm;

                // (if test then) or (if test then else)

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

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


                Expr testExpr = Compiler.Analyze(pcon.EvalOrExpr().SetAssign(false), RT.second(form));
                Expr thenExpr = Compiler.Analyze(pcon.SetAssign(false), RT.third(form));
                Expr elseExpr = Compiler.Analyze(pcon.SetAssign(false), RT.fourth(form));

                return(new IfExpr((IPersistentMap)Compiler.SourceSpanVar.deref(), testExpr, thenExpr, elseExpr));
            }
Пример #2
0
        public void ExplictIPersistentCollectionConsWorks()
        {
            MapEntry me             = new MapEntry(1, "abc");
            IPersistentCollection c = (IPersistentCollection)me;
            ISeq s = c.cons(2).seq();

            Expect(me.count()).To.Equal(2);
            Expect(me.key()).To.Equal(1);
            Expect(me.val()).To.Equal("abc");

            Expect(s.count()).To.Equal(3);
            Expect(s.first()).To.Equal(1);
            Expect(s.next().first()).To.Equal("abc");
            Expect(s.next().next().first()).To.Equal(2);
            Expect(s.next().next().next()).To.Be.Null();
        }
Пример #3
0
        public void ExplictIPersistentCollectionConsWorks()
        {
            MapEntry me             = new MapEntry(1, "abc");
            IPersistentCollection c = (IPersistentCollection)me;
            ISeq s = c.cons(2).seq();

            Expect(me.count(), EqualTo(2));
            Expect(me.key(), EqualTo(1));
            Expect(me.val(), EqualTo("abc"));

            Expect(s.count(), EqualTo(3));
            Expect(s.first(), EqualTo(1));
            Expect(s.next().first(), EqualTo("abc"));
            Expect(s.next().next().first(), EqualTo(2));
            Expect(s.next().next().next(), Null);
        }
Пример #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
 private static Object process_output(Object o, int level)
 {
     if (o is IPersistentCollection)
     {
         o = ((IPersistentCollection)o).seq();
     }
     if (o is ISeq)
     {
         ISeq     r2     = (ISeq)o;
         object[] outArr = new object[r2.count()];
         int      i      = 0;
         while (r2 != null)
         {
             outArr[i] = level == 1 ? process_output(r2.first(), 0) : cleanValue(r2.first());
             i++;
             r2 = r2.next();
         }
         return(level == 1 ? pack(outArr) : outArr);
     }
     else
     {
         return(level == 1 ? pack(cleanValue(o)) : cleanValue(o));
     }
 }
Пример #6
0
            public Expr Parse(ParserContext pcon, object frm)
            {
                //int line = (int)Compiler.LINE.deref();

                ISeq form = (ISeq)frm;

                // form => (new Typename args ... )

                if (form.count() < 2)
                {
                    throw new ParseException("wrong number of arguments, expecting: (new Typename args ...)");
                }

                Type t = HostExpr.MaybeType(RT.second(form), false);

                if (t == null)
                {
                    throw new ParseException("Unable to resolve classname: " + RT.second(form));
                }

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

                return(new NewExpr(t, args, (IPersistentMap)Compiler.SourceSpanVar.deref()));
            }
Пример #7
0
        private static object MacroexpandSeq1(ISeq form)
        {
            object op = RT.first(form);

            if (IsSpecial(op))
                return form;

            // macro expansion
            Var v = IsMacro(op);
            if (v != null)
            {
                try
                {
                    Var.pushThreadBindings(RT.map(RT.MACRO_META, RT.meta(form)));
                    return v.applyTo(form.next());
                }
                finally
                {
                    Var.popThreadBindings();
                }
            }
            else
            {
                if (op is Symbol)
                {
                    Symbol sym = (Symbol)op;
                    string sname = sym.Name;
                    // (.substring s 2 5) => (. x substring 2 5)
                    if (sname[0] == '.')
                    {
                        if (form.count() < 2)
                            throw new ArgumentException("Malformed member expression, expecting (.member target ...)");
                        Symbol method = Symbol.intern(sname.Substring(1));
                        // TODO:  Figure out why the following change made in Java Rev 1158 breaks ants.clj
                        // Note on that revision: force instance member interpretation of (.method ClassName), e.g. (.getMethods String) works
                        //  However, when I do this, it makes ants.clj choke on: (def white-brush (new SolidBrush (.White Color)))
                        object target = RT.second(form);
                        if (MaybeType(target, false) != null)
                            //target = RT.list(IDENTITY, target);
                            target = ((IObj)RT.list(IDENTITY, target)).withMeta(RT.map(RT.TAG_KEY, CLASS));
                        return RT.listStar(DOT, target, method, form.next().next());
                        // safe substitute: return RT.listStar(Compiler.DOT, RT.second(form), method, form.next().next());
                    }
                    else if (NamesStaticMember(sym))
                    {
                        Symbol target = Symbol.intern(sym.Namespace);
                        Type t = MaybeType(target, false);
                        if (t != null)
                        {
                            Symbol method = Symbol.intern(sym.Name);
                            return RT.listStar(Compiler.DOT, target, method, form.next());
                        }
                    }
                    else
                    {
                        // (x.substring 2 5) =>  (. s substring 2 5)
                        int index = sname.LastIndexOf('.');
                        if (index == sname.Length - 1)
                            return RT.listStar(Compiler.NEW, Symbol.intern(sname.Substring(0, index)), form.next());
                    }
                }

            }
            return form;
        }
Пример #8
0
        private static object MacroexpandSeq1(ISeq form)
        {
            object op = RT.first(form);

            if (IsSpecial(op))
                return form;

            // macro expansion
            Var v = IsMacro(op);
            if (v != null)
            {
                try
                {
                    return v.applyTo(RT.cons(form, RT.cons(LocalEnvVar.get(), form.next())));
                }
                catch (ArityException e)
                {
                    // hide the 2 extra params for a macro
                    throw new ArityException(e.Actual - 2, e.Name);
                }
            }
            else
            {
                Symbol sym = op as Symbol;
                if (sym != null)
                {
                    string sname = sym.Name;
                    // (.substring s 2 5) => (. x substring 2 5)
                    if (sname[0] == '.')
                    {
                        if (form.count() < 2)
                            throw new ArgumentException("Malformed member expression, expecting (.member target ...)");
                        Symbol method = Symbol.intern(sname.Substring(1));
                        object target = RT.second(form);
                        if (HostExpr.MaybeType(target, false) != null)
                            target = ((IObj)RT.list(IdentitySym, target)).withMeta(RT.map(RT.TagKey, ClassSym));
                        // We need to make sure source information gets transferred
                        return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(DotSym, target, method, form.next().next())), form);
                    }
                    else if (NamesStaticMember(sym))
                    {
                        Symbol target = Symbol.intern(sym.Namespace);
                        Type t = HostExpr.MaybeType(target, false);
                        if (t != null)
                        {
                            Symbol method = Symbol.intern(sym.Name);
                            // We need to make sure source information gets transferred
                            return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(Compiler.DotSym, target, method, form.next())), form);
                        }
                    }
                    else
                    {
                        // (x.substring 2 5) =>  (. x substring 2 5)
                        // also (package.class.name ... ) (. package.class name ... )
                        int index = sname.LastIndexOf('.');
                        if (index == sname.Length - 1)
                            // We need to make sure source information gets transferred
                            return MaybeTransferSourceInfo(RT.listStar(Compiler.NewSym, Symbol.intern(sname.Substring(0, index)), form.next()), form);
                    }
                }

            }
            return form;
        }
Пример #9
0
        public void Range_has_correct_count()
        {
            ISeq r = (ISeq)_createFn(2L, 20L);

            Expect(r.count(), EqualTo(18));
        }
Пример #10
0
        private static object MacroexpandSeq1(ISeq form)
        {
            object op = RT.first(form);

            if (IsSpecial(op))
                return form;

            // macro expansion
            Var v = IsMacro(op);
            if (v != null)
            {
                // TODO: Check this against current code
                return v.applyTo(RT.cons(form, RT.cons(LOCAL_ENV.get(), form.next())));
            }
            else
            {
                if (op is Symbol)
                {
                    Symbol sym = (Symbol)op;
                    string sname = sym.Name;
                    // (.substring s 2 5) => (. x substring 2 5)
                    if (sname[0] == '.')
                    {
                        if (form.count() < 2)
                            throw new ArgumentException("Malformed member expression, expecting (.member target ...)");
                        Symbol method = Symbol.intern(sname.Substring(1));
                        object target = RT.second(form);
                        if (HostExpr.MaybeType(target, false) != null)
                            target = ((IObj)RT.list(IDENTITY, target)).withMeta(RT.map(RT.TAG_KEY, CLASS));
                        // We need to make sure source information gets transferred
                        return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(DOT, target, method, form.next().next())), form);
                    }
                    else if (NamesStaticMember(sym))
                    {
                        Symbol target = Symbol.intern(sym.Namespace);
                        Type t = HostExpr.MaybeType(target, false);
                        if (t != null)
                        {
                            Symbol method = Symbol.intern(sym.Name);
                            // We need to make sure source information gets transferred
                            return MaybeTransferSourceInfo(PreserveTag(form, RT.listStar(Compiler.DOT, target, method, form.next())), form);
                        }
                    }
                    else
                    {
                        // (x.substring 2 5) =>  (. x substring 2 5)
                        // also (package.class.name ... ) (. package.class name ... )
                        int index = sname.LastIndexOf('.');
                        if (index == sname.Length - 1)
                            // We need to make sure source information gets transferred
                            return MaybeTransferSourceInfo(RT.listStar(Compiler.NEW, Symbol.intern(sname.Substring(0, index)), form.next()), form);
                    }
                }

            }
            return form;
        }
Пример #11
0
        private static Expression GenerateIfExpr(ISeq form)
        {
            if (form.count() > 4)
                throw new Exception("Too many arguments to if");

            if (form.count() < 3)
                throw new Exception("Too few arguments to if");

            object test = RT.second(form);
            object trueClause = RT.third(form);
            object falseClause = RT.fourth(form);

            // TODO: if test has Boolean type, no need to box, just test directly.
            Expression realExpr = Expression.Call(Method_RT_IsTrue, MaybeBox(Generate(test)));
            Expression thenExpr = Generate(trueClause);
            Expression elseExpr = Generate(falseClause);

            if (thenExpr.Type != elseExpr.Type)
            {
                // Try to reconcile
                if (thenExpr.Type.IsAssignableFrom(elseExpr.Type) && elseExpr.Type != typeof(void))
                    elseExpr = Expression.Convert(elseExpr, thenExpr.Type);
                else if (elseExpr.Type.IsAssignableFrom(thenExpr.Type) && thenExpr.Type != typeof(void))
                    thenExpr = Expression.Convert(thenExpr, elseExpr.Type);
                else
                {
                    if (thenExpr.Type == typeof(void))
                        thenExpr = Expression.Block(thenExpr, Expression.Default(elseExpr.Type));
                    else if (elseExpr.Type == typeof(void))
                        elseExpr = Expression.Block(elseExpr, Expression.Default(thenExpr.Type));
                    else
                    {
                        // TODO: Can we find a common ancestor?  probably not.
                        thenExpr = Expression.Convert(thenExpr, typeof(object));
                        elseExpr = Expression.Convert(elseExpr, typeof(object));
                    }
                }
            }
            return Expression.Condition(realExpr, thenExpr, elseExpr);
        }
Пример #12
0
        private static Expression GenerateHostExpr(ISeq form)
        {
            // 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 = MaybeType(RT.second(form),false);
            // at this point, t will be non-null if static
            Expression instance = null;
            if (t == null)
                instance = Generate(RT.second(form));

            if (  form.count() == 3 && RT.third(form) is Symbol )
            {
                Symbol sym = (Symbol) RT.third(form);
                if ( t != null )
                {
                    FieldInfo f = t.GetField(sym.Name, BindingFlags.Static | BindingFlags.Public);
                    if (f != null)
                        return Expression.Field(null, f);

                    PropertyInfo p = t.GetProperty(sym.Name, BindingFlags.Static | BindingFlags.Public);
                    if (p != null)
                        return Expression.Property(null, p);
                }
                else
                {
                    // I doubt that this will work.  We will have to do a runtime determination
                    FieldInfo f = instance.Type.GetField(sym.Name, BindingFlags.Instance | BindingFlags.Public);
                    if (f != null)
                        return Expression.Field(instance, f);

                    PropertyInfo p = instance.Type.GetProperty(sym.Name, BindingFlags.Instance | BindingFlags.Public);
                    if (p != null)
                        return Expression.Property(instance, p);
                }
            }

            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;
            int numArgs = call.count() - 1;

            Expression[] args = new Expression[numArgs];
            int i = 0;
            for (ISeq s = call.next(); s != null; s = s.next(), i++)
                args[i] = Generate(s.first());

            BindingFlags flags = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.InvokeMethod;

            if (t != null)
                flags |= BindingFlags.Static;
            else
                flags |= BindingFlags.Instance;

            Type targetType = t ?? instance.Type;

            //DEBUG:
            //IEnumerable<MethodInfo> einfo1 = targetType.GetMethods();
            //List<MethodInfo> infos1 = new List<MethodInfo>(einfo1);

            IEnumerable<MethodInfo> einfo = targetType.GetMethods(flags).Where(info => info.Name == methodName && info.GetParameters().Length == args.Length);
            List<MethodInfo> infos = new List<MethodInfo>(einfo);

            if (t != null && infos.Count == 0)
                throw new InvalidOperationException(string.Format("No method named: {0} in type: {1}", methodName, targetType.Name));
            else if (infos.Count == 1)
            {
                // TODO: if t is not null, but instance isn't typed, we may be missing overloads.  So I added a t != null.
                // We can improve this when we add better type info propagation.

                // we have a unique match, generate call directly
                if (t != null)
                    return AstUtils.SimpleCallHelper(infos[0], args);
                else
                    //return Expression.Call(instance, infos[0], args);  //asdf-tag
                    return AstUtils.SimpleCallHelper(instance,infos[0], args);
            }
            else
            {
                if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
                {
                    // TODO: use DLR IO
                    ((TextWriter)RT.ERR.deref()).WriteLine(string.Format("Reflection warning, line: {0} - call to {1} can't be resolved.\n", /* line ,*/0, methodName));
                }

                Expression[] moreArgs = new Expression[3];
                moreArgs[0] = Expression.Constant(methodName);
                moreArgs[1] = t != null ? Expression.Constant(t) : instance;
                moreArgs[2] = Expression.NewArrayInit(typeof(object), MaybeBox(args));

                if (t != null)
                    return Expression.Call(Method_Reflector_CallStaticMethod, moreArgs);
                else
                    return Expression.Call(Method_Reflector_CallInstanceMethod, moreArgs);
            }
        }
Пример #13
0
        private static Expression GenerateDefExpr(ISeq form)
        {
            if (form.count() > 3)
                throw new Exception("Too many arguments to def");

            if (form.count() < 2)
                throw new Exception("Too few arguments to def");

            Symbol sym = RT.second(form) as Symbol;
            bool initProvided = form.count() == 3;

            if (sym == null)
                throw new Exception("Second argument to def must be a Symbol.");

            Var v = lookupVar(sym, true);

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

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

            IPersistentMap mm = sym.meta();
            // TODO: add source line info metadata.
            //mm = (IPersistentMap) RT.assoc(RT.LINE_KEY, LINE.get()).assoc(RT.FILE_KEY, SOURCE.get());

            // Bizarrely, we don't have to do anything to actually create the var, the lookupVar did that for us.
            // Will this work in a compiled class file?

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

            Expression varExpr = GenerateConstExpr(v);

            if (initProvided)
                exprs.Add(Expression.Call(varExpr, Method_Var_BindRoot, MaybeBox(Generate(RT.third(form))))); ;

            if (mm != null)
                exprs.Add(Expression.Call(varExpr, Method_Var_SetMeta, GenerateMapExpr(mm)));

            exprs.Add(varExpr);

            return Expression.Block(exprs);
        }
Пример #14
0
        private static Expression GenerateAssignExpr(ISeq form)
        {
            if (form.count() != 3)
                throw new ArgumentException("Malformed assignment, expecting (set! target val)");

            object target = RT.second(form);
            object init = RT.third(form);

            Var v;

            if ( (v = FindAsVar(target)) != null)
                return GenerateVarAssignExpr(v, init);

            Type t;

            if ((t = FindAsDirectStaticFieldReference(target)) != null)
                return GenerateDirectStaticFieldAssignExpr(t, (target as Symbol).Name, init);

            if ( IsFieldReference(target))
                return GenerateFieldAssignExpr(RT.second((ISeq)target),(string) RT.third((ISeq)target),init);

            throw new ArgumentException("Invalid assignment target");
        }
Пример #15
0
        private static Expression GenerateNewExpr(ISeq form)
        {
            // form => (new Classname args ... )
            if (form.count() < 2)
                throw new Exception("wrong number of arguments, expecting: (new Classname args ...)");
            Type t = MaybeType(RT.second(form), false);
            if (t == null)
                throw new ArgumentException("Unable to resolve classname: " + RT.second(form));

            int numArgs = form.count() - 2;
            Expression[] args = new Expression[numArgs];
            int i = 0;
            for (ISeq s = RT.next(RT.next(form)); s != null; s = s.next(), i++)
                args[i] = Generate(s.first());

            List<ConstructorInfo> cinfos = new List<ConstructorInfo>(t.GetConstructors().Where(x => x.GetParameters().Length == numArgs && x.IsPublic));

            if (cinfos.Count == 0)
                throw new InvalidOperationException(string.Format("No constructor in type: {0} with {1} arguments", t.Name, numArgs));

            else if (cinfos.Count == 1)
            {
                // we have a unique match, generate directly
                // Need to try to convert the arguments, or the call to Expression.New will choke
                ConstructorInfo info = cinfos[0];
                Expression[] convArgs = new Expression[numArgs];
                for ( i=0; i < numArgs; i++ )
                    convArgs[i] = Expression.Convert(args[i],info.GetParameters()[i].ParameterType);
                return Expression.New(info, convArgs);
            }
            else
            {
                // we must defer to runtime

                if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
                {
                    // TODO: use DLR IO
                    ((TextWriter)RT.ERR.deref()).WriteLine(string.Format("Reflection warning, line: {0} - call to new can't be resolved.\n", /* line ,*/0));
                }

                Expression[] moreArgs = new Expression[2];
                moreArgs[0] = Expression.Constant(t);
                moreArgs[1] = Expression.NewArrayInit(typeof(object), MaybeBox(args));

                return Expression.Call(Method_Reflector_InvokeConstructor, moreArgs);
            }
        }