public Interpreter()
        {
            globalenv = new Env(null, null, null);
            reader = new Reader(this);
            symbolTable = new SymbolTable();

            Assembly[] asm = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly a in asm)
            {
                addTypesFrom(a);
            }

            internBuiltins();
            Primitives.internAll(this);
            LASTVAL.setGlobalValue(null);
            NEXTLASTVAL.setGlobalValue(null);
            THIRDLASTVAL.setGlobalValue(null);

            //these primitives are here, rather than in Primitives, because their implementation
            //requires calls to gfs bound to symbols
            Intern("intern", new Function(internf));
            Intern("eval", new Function(evalf));
            Intern("load", new Function(loadf));
            Intern("map->list", new Function(map_to_list));
            Intern("apply", new Function(apply));
            Intern("<", new Function(lt));
            Intern("<=", new Function(lteq));
            Intern(">", new Function(gt));
            Intern(">=", new Function(gteq));
            Intern("==", new Function(eqeq));
            Intern("!=", new Function(noteq));

            strgf = (GenericFunction)intern("str").getGlobalValue();
            get_enum_gf = (GenericFunction)intern("get-enum").getGlobalValue();
            compare_gf = (BinOp)intern("compare").getGlobalValue();

            Intern("interpreter", this);
        }
        internal static void internAll(Interpreter interpreter)
        {
            interpreter.Intern("not", new Function(not));
            interpreter.Intern("to-bool", new Function(to_bool));
            interpreter.Intern("nil?", new Function(nilp));
            interpreter.Intern("symbol?", new Function(symbolp));
            interpreter.Intern("eqv?", new Function(eqv));
            interpreter.Intern("eql?", new Function(eql));
            interpreter.Intern("cons", new Function(cons));
            interpreter.Intern("cons?", new Function(consp));
            interpreter.Intern("atom?", new Function(atomp));
            interpreter.Intern("first", new Function(first));
            interpreter.Intern("rest", new Function(rest));
            interpreter.Intern("set-first", new Function(setfirst));
            interpreter.Intern("set-rest", new Function(setrest));
            interpreter.Intern("second", new Function(second));
            interpreter.Intern("third", new Function(third));
            interpreter.Intern("fourth", new Function(fourth));
            interpreter.Intern("reverse", new Function(reverse));
            interpreter.Intern("list?", new Function(listp));
            interpreter.Intern("len", new Function(listlength));
            interpreter.Intern("nth", new Function(nth));
            interpreter.Intern("nth-rest", new Function(nthrest));
            interpreter.Intern("append", new Function(append));
            interpreter.Intern("concat!", new Function(concat_d));
            interpreter.Intern("type-of", new Function(type_of));
            interpreter.Intern("is?", new Function(isp));
            interpreter.Intern("even?", new Function(evenp));
            interpreter.Intern("gensym", new Function(gensym));
            interpreter.Intern("macroexpand-1", new Function(macroexpand_1));
            interpreter.Intern("vector", new Function(vector));
            interpreter.Intern("vector-of", new Function(vector_of));
            interpreter.Intern("throw", new Function(throwfun));
            interpreter.Intern("try-catch-finally", new Function(try_catch_finally));

            interpreter.Intern("<i", new Function(lti));
            interpreter.Intern("addi", new Function(addints));

            BinOp addop = new BinOp();
            addop.AddMethod(typeof(Int32), typeof(Int32), new Function(addints));
            addop.AddMethod(typeof(Int32), typeof(Object), new Function(addobjs));
            addop.AddMethod(typeof(Object), typeof(Object), new Function(addobjs));
            interpreter.Intern("add", addop);

            BinOp subtractop = new BinOp();
            subtractop.AddMethod(typeof(Int32), typeof(Int32), new Function(subtractints));
            subtractop.AddMethod(typeof(Int32), typeof(Object), new Function(subtractobjs));
            subtractop.AddMethod(typeof(Object), typeof(Object), new Function(subtractobjs));
            interpreter.Intern("subtract", subtractop);

            BinOp multiplyop = new BinOp();
            multiplyop.AddMethod(typeof(Int32), typeof(Int32), new Function(multiplyints));
            multiplyop.AddMethod(typeof(Int32), typeof(Object), new Function(multiplyobjs));
            multiplyop.AddMethod(typeof(Object), typeof(Object), new Function(multiplyobjs));
            interpreter.Intern("multiply", multiplyop);

            BinOp divideop = new BinOp();
            divideop.AddMethod(typeof(Int32), typeof(Int32), new Function(divideints));
            divideop.AddMethod(typeof(Int32), typeof(Object), new Function(divideobjs));
            divideop.AddMethod(typeof(Object), typeof(Object), new Function(divideobjs));
            interpreter.Intern("divide", divideop);

            BinOp compareop = new BinOp();
            compareop.AddMethod(typeof(Int32), typeof(Int32), new Function(subtractints));
            compareop.AddMethod(typeof(Int32), typeof(Object), new Function(compareobjs));
            compareop.AddMethod(typeof(Object), typeof(Object), new Function(compareobjs));
            interpreter.Intern("compare", compareop);

            BinOp bitorop = new BinOp();
            bitorop.AddMethod(typeof(Enum), typeof(Enum), new Function(bitorenum));
            bitorop.AddMethod(typeof(Object), typeof(Object), new Function(bitor));
            interpreter.Intern("bit-or", bitorop);

            BinOp bitandop = new BinOp();
            bitandop.AddMethod(typeof(Enum), typeof(Enum), new Function(bitandenum));
            bitandop.AddMethod(typeof(Object), typeof(Object), new Function(bitand));
            interpreter.Intern("bit-and", bitandop);

            BinOp bitxorop = new BinOp();
            bitxorop.AddMethod(typeof(Enum), typeof(Enum), new Function(bitxorenum));
            bitxorop.AddMethod(typeof(Object), typeof(Object), new Function(bitxor));
            interpreter.Intern("bit-xor", bitxorop);

            GenericFunction bitnotgf = new GenericFunction();
            bitnotgf.AddMethod(typeof(Enum), new Function(bitnotenum));
            bitnotgf.AddMethod(typeof(Object), new Function(bitnot));
            interpreter.Intern("bit-not", bitnotgf);

            GenericFunction get_enum_gf = new GenericFunction();
            get_enum_gf.AddMethod(typeof(IEnumerator), new Function(get_enum_IEnumerator));
            get_enum_gf.AddMethod(typeof(IEnumerable), new Function(get_enum_IEnumerable));
            get_enum_gf.AddMethod(null, new Function(get_enum_nil));
            interpreter.Intern("get-enum", get_enum_gf);

            GenericFunction strgf = new GenericFunction();
            strgf.AddMethod(null, new Function(strnil));
            strgf.AddMethod(typeof(Object), new Function(strobj));
            interpreter.Intern("str", strgf);

            //interpreter.Intern("pr",new GenericFunction());
        }