Example #1
0
        static MalVal EVAL(MalVal orig_ast, Dictionary <string, MalVal> env)
        {
            MalVal a0;

            //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
            if (!orig_ast.list_Q())
            {
                return(eval_ast(orig_ast, env));
            }

            // apply list
            MalList ast = (MalList)orig_ast;

            if (ast.size() == 0)
            {
                return(ast);
            }
            a0 = ast[0];
            if (!(a0 is MalSymbol))
            {
                throw new Mal.types.MalError("attempt to apply on non-symbol '"
                                             + Mal.printer._pr_str(a0, true) + "'");
            }
            var el = (MalList)eval_ast(ast, env);
            var f  = (MalFunc)el[0];

            return(f.apply(el.rest()));
        }
Example #2
0
 static MalVal eval_ast(MalVal ast, Env env)
 {
     if (ast is MalSymbol)
     {
         return(env.get((MalSymbol)ast));
     }
     else if (ast is MalList)
     {
         MalList old_lst = (MalList)ast;
         MalList new_lst = ast.list_Q() ? new MalList()
                                     : (MalList) new MalVector();
         foreach (MalVal mv in old_lst.getValue())
         {
             new_lst.conj_BANG(EVAL(mv, env));
         }
         return(new_lst);
     }
     else if (ast is MalHashMap)
     {
         var new_dict = new Dictionary <string, MalVal>();
         foreach (var entry in ((MalHashMap)ast).getValue())
         {
             new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env));
         }
         return(new MalHashMap(new_dict));
     }
     else
     {
         return(ast);
     }
 }
Example #3
0
        // eval
        static MalVal EVAL(MalVal orig_ast, Dictionary <string, MalVal> env)
        {
            MalVal a0;

            // Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
            if (orig_ast is MalSymbol)
            {
                MalSymbol sym = (MalSymbol)orig_ast;
                return((MalVal)env[sym.getName()]);
            }
            else if (orig_ast is MalVector)
            {
                MalVector old_lst = (MalVector)orig_ast;
                MalVector new_lst = new MalVector();
                foreach (MalVal mv in old_lst.getValue())
                {
                    new_lst.conj_BANG(EVAL(mv, env));
                }
                return(new_lst);
            }
            else if (orig_ast is MalHashMap)
            {
                var new_dict = new Dictionary <string, MalVal>();
                foreach (var entry in ((MalHashMap)orig_ast).getValue())
                {
                    new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env));
                }
                return(new MalHashMap(new_dict));
            }
            else if (!(orig_ast is MalList))
            {
                return(orig_ast);
            }

            // apply list
            MalList ast = (MalList)orig_ast;

            if (ast.size() == 0)
            {
                return(ast);
            }
            a0 = ast[0];
            if (!(a0 is MalSymbol))
            {
                throw new Mal.types.MalError("attempt to apply on non-symbol '"
                                             + Mal.printer._pr_str(a0, true) + "'");
            }
            MalFunc f         = (MalFunc)EVAL(ast[0], env);
            MalList arguments = new MalList();

            foreach (MalVal mv in ast.rest().getValue())
            {
                arguments.conj_BANG(EVAL(mv, env));
            }
            return(f.apply(arguments));
        }
Example #4
0
        private static List <object> MapMalListToDotNetList(MalList malList)
        {
            List <object> dotNetList = new List <object>();

            foreach (MalVal malVal in malList.getValue())
            {
                dotNetList.Add(MapMalToDotNet(malVal));
            }
            return(dotNetList);
        }
Example #5
0
        static MalVal EVAL(MalVal orig_ast, Env env)
        {
            MalVal  a0, a1, a2, res;
            MalList el;

            //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
            if (!orig_ast.list_Q())
            {
                return(eval_ast(orig_ast, env));
            }

            // apply list
            MalList ast = (MalList)orig_ast;

            if (ast.size() == 0)
            {
                return(ast);
            }
            a0 = ast[0];
            if (!(a0 is MalSymbol))
            {
                throw new Mal.types.MalError("attempt to apply on non-symbol '"
                                             + Mal.printer._pr_str(a0, true) + "'");
            }

            switch (((MalSymbol)a0).getName())
            {
            case "def!":
                a1  = ast[1];
                a2  = ast[2];
                res = EVAL(a2, env);
                env.set((MalSymbol)a1, res);
                return(res);

            case "let*":
                a1 = ast[1];
                a2 = ast[2];
                MalSymbol key;
                MalVal    val;
                Env       let_env = new Env(env);
                for (int i = 0; i < ((MalList)a1).size(); i += 2)
                {
                    key = (MalSymbol)((MalList)a1)[i];
                    val = ((MalList)a1)[i + 1];
                    let_env.set(key, EVAL(val, let_env));
                }
                return(EVAL(a2, let_env));

            default:
                el = (MalList)eval_ast(ast, env);
                var f = (MalFunc)el[0];
                return(f.apply(el.rest()));
            }
        }
Example #6
0
 public Env(Env outer, MalList binds, MalList exprs) {
     this.outer = outer;
     for (int i=0; i<binds.size(); i++) {
         string sym = ((MalSymbol)binds.nth(i)).getName();
         if (sym == "&") {
             data[((MalSymbol)binds.nth(i+1)).getName()] = exprs.slice(i);
             break;
         } else {
             data[sym] = exprs.nth(i);
         }
     }
 }
Example #7
0
 // eval
 public static bool starts_with(MalVal ast, string sym)
 {
     if (ast is MalList && !(ast is MalVector))
     {
         MalList list = (MalList)ast;
         if (list.size() == 2 && list[0] is MalSymbol)
         {
             MalSymbol a0 = (MalSymbol)list[0];
             return(a0.getName() == sym);
         }
     }
     return(false);
 }
Example #8
0
 public Env(Env outer, MalList binds, MalList exprs)
 {
     this.outer = outer;
     for (int i = 0; i < binds.size(); i++)
     {
         string sym = ((MalSymbol)binds.nth(i)).getName();
         if (sym == "&")
         {
             data[((MalSymbol)binds.nth(i + 1)).getName()] = exprs.slice(i);
             break;
         }
         else
         {
             data[sym] = exprs.nth(i);
         }
     }
 }
Example #9
0
        public static MalVal qq_loop(MalList ast)
        {
            MalVal acc = new MalList();

            for (int i = ast.size() - 1; 0 <= i; i -= 1)
            {
                MalVal elt = ast[i];
                if (starts_with(elt, "splice-unquote"))
                {
                    acc = new MalList(new MalSymbol("concat"), ((MalList)elt)[1], acc);
                }
                else
                {
                    acc = new MalList(new MalSymbol("cons"), quasiquote(elt), acc);
                }
            }
            return(acc);
        }
Example #10
0
        public static MalVal read_list(Reader rdr, MalList lst, char start, char end)
        {
            string token = rdr.next();

            if (token[0] != start)
            {
                throw new ParseError("expected '" + start + "'");
            }

            while ((token = rdr.peek()) != null && token[0] != end)
            {
                lst.conj_BANG(read_form(rdr));
            }

            if (token == null)
            {
                throw new ParseError("expected '" + end + "', got EOF");
            }
            rdr.next();

            return(lst);
        }
Example #11
0
        static MalVal EVAL(MalVal orig_ast, Env env)
        {
            MalVal  a0, a1, a2, res;
            MalList el;

            while (true)
            {
                //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
                if (!orig_ast.list_Q())
                {
                    return(eval_ast(orig_ast, env));
                }

                // apply list
                MalVal expanded = macroexpand(orig_ast, env);
                if (!expanded.list_Q())
                {
                    return(eval_ast(expanded, env));
                }
                MalList ast = (MalList)expanded;

                if (ast.size() == 0)
                {
                    return(ast);
                }
                a0 = ast[0];

                String a0sym = a0 is MalSymbol ? ((MalSymbol)a0).getName()
                                           : "__<*fn*>__";

                switch (a0sym)
                {
                case "def!":
                    a1  = ast[1];
                    a2  = ast[2];
                    res = EVAL(a2, env);
                    env.set((MalSymbol)a1, res);
                    return(res);

                case "let*":
                    a1 = ast[1];
                    a2 = ast[2];
                    MalSymbol key;
                    MalVal    val;
                    Env       let_env = new Env(env);
                    for (int i = 0; i < ((MalList)a1).size(); i += 2)
                    {
                        key = (MalSymbol)((MalList)a1)[i];
                        val = ((MalList)a1)[i + 1];
                        let_env.set(key, EVAL(val, let_env));
                    }
                    orig_ast = a2;
                    env      = let_env;
                    break;

                case "quote":
                    return(ast[1]);

                case "quasiquote":
                    orig_ast = quasiquote(ast[1]);
                    break;

                case "defmacro!":
                    a1  = ast[1];
                    a2  = ast[2];
                    res = EVAL(a2, env);
                    ((MalFunc)res).setMacro();
                    env.set(((MalSymbol)a1), res);
                    return(res);

                case "macroexpand":
                    a1 = ast[1];
                    return(macroexpand(a1, env));

                case "try*":
                    try {
                        return(EVAL(ast[1], env));
                    } catch (Exception e) {
                        if (ast.size() > 2)
                        {
                            MalVal exc;
                            a2 = ast[2];
                            MalVal a20 = ((MalList)a2)[0];
                            if (((MalSymbol)a20).getName() == "catch*")
                            {
                                if (e is Mal.types.MalException)
                                {
                                    exc = ((Mal.types.MalException)e).getValue();
                                }
                                else
                                {
                                    exc = new MalString(e.Message);
                                }
                                return(EVAL(((MalList)a2)[2],
                                            new Env(env, ((MalList)a2).slice(1, 2),
                                                    new MalList(exc))));
                            }
                        }
                        throw e;
                    }

                case "do":
                    eval_ast(ast.slice(1, ast.size() - 1), env);
                    orig_ast = ast[ast.size() - 1];
                    break;

                case "if":
                    a1 = ast[1];
                    MalVal cond = EVAL(a1, env);
                    if (cond == Mal.types.Nil || cond == Mal.types.False)
                    {
                        // eval false slot form
                        if (ast.size() > 3)
                        {
                            orig_ast = ast[3];
                        }
                        else
                        {
                            return(Mal.types.Nil);
                        }
                    }
                    else
                    {
                        // eval true slot form
                        orig_ast = ast[2];
                    }
                    break;

                case "fn*":
                    MalList a1f     = (MalList)ast[1];
                    MalVal  a2f     = ast[2];
                    Env     cur_env = env;
                    return(new MalFunc(a2f, env, a1f,
                                       args => EVAL(a2f, new Env(cur_env, a1f, args))));

                default:
                    el = (MalList)eval_ast(ast, env);
                    var    f     = (MalFunc)el[0];
                    MalVal fnast = f.getAst();
                    if (fnast != null)
                    {
                        orig_ast = fnast;
                        env      = f.genEnv(el.rest());
                    }
                    else
                    {
                        return(f.apply(el.rest()));
                    }
                    break;
                }
            }
        }
Example #12
0
        public static MalVal read_hash_map(Reader rdr)
        {
            MalList lst = (MalList)read_list(rdr, new MalList(), '{', '}');

            return(new MalHashMap(lst));
        }
Example #13
0
        static MalVal EVAL(MalVal orig_ast, Env env)
        {
            MalVal  a0, a1, a2, res;
            MalList el;

            while (true)
            {
                //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
                if (!orig_ast.list_Q())
                {
                    return(eval_ast(orig_ast, env));
                }

                // apply list
                MalList ast = (MalList)orig_ast;
                if (ast.size() == 0)
                {
                    return(ast);
                }
                a0 = ast[0];

                String a0sym = a0 is MalSymbol ? ((MalSymbol)a0).getName()
                                           : "__<*fn*>__";

                switch (a0sym)
                {
                case "def!":
                    a1  = ast[1];
                    a2  = ast[2];
                    res = EVAL(a2, env);
                    env.set((MalSymbol)a1, res);
                    return(res);

                case "let*":
                    a1 = ast[1];
                    a2 = ast[2];
                    MalSymbol key;
                    MalVal    val;
                    Env       let_env = new Env(env);
                    for (int i = 0; i < ((MalList)a1).size(); i += 2)
                    {
                        key = (MalSymbol)((MalList)a1)[i];
                        val = ((MalList)a1)[i + 1];
                        let_env.set(key, EVAL(val, let_env));
                    }
                    orig_ast = a2;
                    env      = let_env;
                    break;

                case "quote":
                    return(ast[1]);

                case "quasiquote":
                    orig_ast = quasiquote(ast[1]);
                    break;

                case "do":
                    eval_ast(ast.slice(1, ast.size() - 1), env);
                    orig_ast = ast[ast.size() - 1];
                    break;

                case "if":
                    a1 = ast[1];
                    MalVal cond = EVAL(a1, env);
                    if (cond == Mal.types.Nil || cond == Mal.types.False)
                    {
                        // eval false slot form
                        if (ast.size() > 3)
                        {
                            orig_ast = ast[3];
                        }
                        else
                        {
                            return(Mal.types.Nil);
                        }
                    }
                    else
                    {
                        // eval true slot form
                        orig_ast = ast[2];
                    }
                    break;

                case "fn*":
                    MalList a1f     = (MalList)ast[1];
                    MalVal  a2f     = ast[2];
                    Env     cur_env = env;
                    return(new MalFunc(a2f, env, a1f,
                                       args => EVAL(a2f, new Env(cur_env, a1f, args))));

                default:
                    el = (MalList)eval_ast(ast, env);
                    var    f     = (MalFunc)el[0];
                    MalVal fnast = f.getAst();
                    if (fnast != null)
                    {
                        orig_ast = fnast;
                        env      = f.genEnv(el.rest());
                    }
                    else
                    {
                        return(f.apply(el.rest()));
                    }
                    break;
                }
            }
        }
Example #14
0
        // repl
        static void Main(string[] args)
        {
            var repl_env             = new Mal.env.Env(null);
            Func <string, MalVal> RE = (string str) => EVAL(READ(str), repl_env);

            // core.cs: defined using C#
            foreach (var entry in core.ns)
            {
                repl_env.set(new MalSymbol(entry.Key), entry.Value);
            }
            repl_env.set(new MalSymbol("eval"), new MalFunc(
                             a => EVAL(a[0], repl_env)));
            int fileIdx = 0;

            if (args.Length > 0 && args[0] == "--raw")
            {
                Mal.readline.mode = Mal.readline.Mode.Raw;
                fileIdx           = 1;
            }
            MalList _argv = new MalList();

            for (int i = fileIdx + 1; i < args.Length; i++)
            {
                _argv.conj_BANG(new MalString(args[i]));
            }
            repl_env.set(new MalSymbol("*ARGV*"), _argv);

            // core.mal: defined using the language itself
            RE("(def! not (fn* (a) (if a false true)))");
            RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");

            if (args.Length > fileIdx)
            {
                RE("(load-file \"" + args[fileIdx] + "\")");
                return;
            }

            // repl loop
            while (true)
            {
                string line;
                try {
                    line = Mal.readline.Readline("user> ");
                    if (line == null)
                    {
                        break;
                    }
                    if (line == "")
                    {
                        continue;
                    }
                } catch (IOException e) {
                    Console.WriteLine("IOException: " + e.Message);
                    break;
                }
                try {
                    Console.WriteLine(PRINT(RE(line)));
                } catch (Mal.types.MalContinue) {
                    continue;
                } catch (Exception e) {
                    Console.WriteLine("Error: " + e.Message);
                    Console.WriteLine(e.StackTrace);
                    continue;
                }
            }
        }
Example #15
0
        // repl
        static void Main(string[] args)
        {
            var repl_env = new Mal.env.Env(null);
            Func<string, MalVal> RE = (string str) => EVAL(READ(str), repl_env);

            // core.cs: defined using C#
            foreach (var entry in core.ns) {
                repl_env.set(new MalSymbol(entry.Key), entry.Value);
            }
            repl_env.set(new MalSymbol("eval"), new MalFunc(
                        a => EVAL(a[0], repl_env)));
            int fileIdx = 1;
            if (args.Length > 0 && args[0] == "--raw") {
                Mal.readline.mode = Mal.readline.Mode.Raw;
                fileIdx = 2;
            }
            MalList _argv = new MalList();
            for (int i=fileIdx; i < args.Length; i++) {
                _argv.conj_BANG(new MalString(args[i]));
            }
            repl_env.set(new MalSymbol("*ARGV*"), _argv);

            // core.mal: defined using the language itself
            RE("(def! not (fn* (a) (if a false true)))");
            RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");

            if (args.Length > fileIdx) {
                RE("(load-file \"" + args[fileIdx] + "\")");
                return;
            }

            // repl loop
            while (true) {
                string line;
                try {
                    line = Mal.readline.Readline("user> ");
                    if (line == null) { break; }
                    if (line == "") { continue; }
                } catch (IOException e) {
                    Console.WriteLine("IOException: " + e.Message);
                    break;
                }
                try {
                    Console.WriteLine(PRINT(RE(line)));
                } catch (Mal.types.MalContinue) {
                    continue;
                } catch (Exception e) {
                    Console.WriteLine("Error: " + e.Message);
                    Console.WriteLine(e.StackTrace);
                    continue;
                }
            }
        }
Example #16
0
 public static string _pr_str_args(MalList args, String sep,
                                   bool print_readably)
 {
     return(join(args.getValue(), sep, print_readably));
 }
Example #17
0
        // repl
        static void Main(string[] args)
        {
            var repl_env             = new Mal.env.Env(null);
            Func <string, MalVal> RE = (string str) => EVAL(READ(str), repl_env);

            // core.cs: defined using C#
            foreach (var entry in core.ns)
            {
                repl_env.set(new MalSymbol(entry.Key), entry.Value);
            }
            repl_env.set(new MalSymbol("eval"), new MalFunc(
                             a => EVAL(a[0], repl_env)));
            int fileIdx = 0;

            if (args.Length > 0 && args[0] == "--raw")
            {
                Mal.readline.mode = Mal.readline.Mode.Raw;
                fileIdx           = 1;
            }
            MalList _argv = new MalList();

            for (int i = fileIdx + 1; i < args.Length; i++)
            {
                _argv.conj_BANG(new MalString(args[i]));
            }
            repl_env.set(new MalSymbol("*ARGV*"), _argv);

            // core.mal: defined using the language itself
            RE("(def! not (fn* (a) (if a false true)))");
            RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
            RE("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))");
            RE("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))");

            if (args.Length > fileIdx)
            {
                RE("(load-file \"" + args[fileIdx] + "\")");
                return;
            }

            // repl loop
            while (true)
            {
                string line;
                try {
                    line = Mal.readline.Readline("user> ");
                    if (line == null)
                    {
                        break;
                    }
                    if (line == "")
                    {
                        continue;
                    }
                } catch (IOException e) {
                    Console.WriteLine("IOException: " + e.Message);
                    break;
                }
                try {
                    Console.WriteLine(PRINT(RE(line)));
                } catch (Mal.types.MalContinue) {
                    continue;
                } catch (Mal.types.MalException e) {
                    Console.WriteLine("Error: " +
                                      printer._pr_str(e.getValue(), false));
                    continue;
                } catch (Exception e) {
                    Console.WriteLine("Error: " + e.Message);
                    Console.WriteLine(e.StackTrace);
                    continue;
                }
            }
        }
Example #18
0
        static MalVal EVAL(MalVal orig_ast, Env env)
        {
            MalVal a0, a1, a2, res;

            while (true)
            {
                MalVal dbgeval = env.get("DEBUG-EVAL");
                if (dbgeval != null && dbgeval != Mal.types.Nil &&
                    dbgeval != Mal.types.False)
                {
                    Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
                }
                if (orig_ast is MalSymbol)
                {
                    string key = ((MalSymbol)orig_ast).getName();
                    res = env.get(key);
                    if (res == null)
                    {
                        throw new Mal.types.MalException("'" + key + "' not found");
                    }
                    return(res);
                }
                else if (orig_ast is MalVector)
                {
                    MalVector old_lst = (MalVector)orig_ast;
                    MalVector new_lst = new MalVector();
                    foreach (MalVal mv in old_lst.getValue())
                    {
                        new_lst.conj_BANG(EVAL(mv, env));
                    }
                    return(new_lst);
                }
                else if (orig_ast is MalHashMap)
                {
                    var new_dict = new Dictionary <string, MalVal>();
                    foreach (var entry in ((MalHashMap)orig_ast).getValue())
                    {
                        new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env));
                    }
                    return(new MalHashMap(new_dict));
                }
                else if (!(orig_ast is MalList))
                {
                    return(orig_ast);
                }

                // apply list
                MalList ast = (MalList)orig_ast;

                if (ast.size() == 0)
                {
                    return(ast);
                }
                a0 = ast[0];

                String a0sym = a0 is MalSymbol ? ((MalSymbol)a0).getName()
                                           : "__<*fn*>__";

                switch (a0sym)
                {
                case "def!":
                    a1  = ast[1];
                    a2  = ast[2];
                    res = EVAL(a2, env);
                    env.set((MalSymbol)a1, res);
                    return(res);

                case "let*":
                    a1 = ast[1];
                    a2 = ast[2];
                    MalSymbol key;
                    MalVal    val;
                    Env       let_env = new Env(env);
                    for (int i = 0; i < ((MalList)a1).size(); i += 2)
                    {
                        key = (MalSymbol)((MalList)a1)[i];
                        val = ((MalList)a1)[i + 1];
                        let_env.set(key, EVAL(val, let_env));
                    }
                    orig_ast = a2;
                    env      = let_env;
                    break;

                case "quote":
                    return(ast[1]);

                case "quasiquote":
                    orig_ast = quasiquote(ast[1]);
                    break;

                case "do":
                    foreach (MalVal mv in ast.slice(1, ast.size() - 1).getValue())
                    {
                        EVAL(mv, env);
                    }
                    orig_ast = ast[ast.size() - 1];
                    break;

                case "if":
                    a1 = ast[1];
                    MalVal cond = EVAL(a1, env);
                    if (cond == Mal.types.Nil || cond == Mal.types.False)
                    {
                        // eval false slot form
                        if (ast.size() > 3)
                        {
                            orig_ast = ast[3];
                        }
                        else
                        {
                            return(Mal.types.Nil);
                        }
                    }
                    else
                    {
                        // eval true slot form
                        orig_ast = ast[2];
                    }
                    break;

                case "fn*":
                    MalList a1f     = (MalList)ast[1];
                    MalVal  a2f     = ast[2];
                    Env     cur_env = env;
                    return(new MalFunc(a2f, env, a1f,
                                       args => EVAL(a2f, new Env(cur_env, a1f, args))));

                default:
                    MalFunc f         = (MalFunc)EVAL(ast[0], env);
                    MalList arguments = new MalList();
                    foreach (MalVal mv in ast.rest().getValue())
                    {
                        arguments.conj_BANG(EVAL(mv, env));
                    }
                    MalVal fnast = f.getAst();
                    if (fnast != null)
                    {
                        orig_ast = fnast;
                        env      = f.genEnv(arguments);
                    }
                    else
                    {
                        return(f.apply(arguments));
                    }
                    break;
                }
            }
        }
Example #19
0
File: reader.cs Project: nboyd/mal
        public static MalVal read_list(Reader rdr, MalList lst, char start, char end)
        {
            string token = rdr.next();
            if (token[0] != start) {
                throw new ParseError("expected '" + start + "'");
            }

            while ((token = rdr.peek()) != null && token[0] != end) {
                lst.conj_BANG(read_form(rdr));
            }

            if (token == null) {
                throw new ParseError("expected '" + end + "', got EOF");
            }
            rdr.next();

            return lst;
        }
Example #20
0
        // eval
        static MalVal EVAL(MalVal orig_ast, Env env)
        {
            MalVal a0, a1, a2, res;
            MalVal dbgeval = env.get("DEBUG-EVAL");

            if (dbgeval != null && dbgeval != Mal.types.Nil &&
                dbgeval != Mal.types.False)
            {
                Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
            }
            if (orig_ast is MalSymbol)
            {
                string key = ((MalSymbol)orig_ast).getName();
                res = env.get(key);
                if (res == null)
                {
                    throw new Mal.types.MalException("'" + key + "' not found");
                }
                return(res);
            }
            else if (orig_ast is MalVector)
            {
                MalVector old_lst = (MalVector)orig_ast;
                MalVector new_lst = new MalVector();
                foreach (MalVal mv in old_lst.getValue())
                {
                    new_lst.conj_BANG(EVAL(mv, env));
                }
                return(new_lst);
            }
            else if (orig_ast is MalHashMap)
            {
                var new_dict = new Dictionary <string, MalVal>();
                foreach (var entry in ((MalHashMap)orig_ast).getValue())
                {
                    new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env));
                }
                return(new MalHashMap(new_dict));
            }
            else if (!(orig_ast is MalList))
            {
                return(orig_ast);
            }

            // apply list
            MalList ast = (MalList)orig_ast;

            if (ast.size() == 0)
            {
                return(ast);
            }
            a0 = ast[0];
            if (!(a0 is MalSymbol))
            {
                throw new Mal.types.MalError("attempt to apply on non-symbol '"
                                             + Mal.printer._pr_str(a0, true) + "'");
            }

            switch (((MalSymbol)a0).getName())
            {
            case "def!":
                a1  = ast[1];
                a2  = ast[2];
                res = EVAL(a2, env);
                env.set((MalSymbol)a1, res);
                return(res);

            case "let*":
                a1 = ast[1];
                a2 = ast[2];
                MalSymbol key;
                MalVal    val;
                Env       let_env = new Env(env);
                for (int i = 0; i < ((MalList)a1).size(); i += 2)
                {
                    key = (MalSymbol)((MalList)a1)[i];
                    val = ((MalList)a1)[i + 1];
                    let_env.set(key, EVAL(val, let_env));
                }
                return(EVAL(a2, let_env));

            default:
                MalFunc f         = (MalFunc)EVAL(ast[0], env);
                MalList arguments = new MalList();
                foreach (MalVal mv in ast.rest().getValue())
                {
                    arguments.conj_BANG(EVAL(mv, env));
                }
                return(f.apply(arguments));
            }
        }
Example #21
0
        // repl
        static void Main(string[] args) {
            var repl_env = new Mal.env.Env(null);
            Func<string, MalVal> RE = (string str) => EVAL(READ(str), repl_env);
            
            // core.cs: defined using C#
            foreach (var entry in core.ns) {
                repl_env.set(new MalSymbol(entry.Key), entry.Value);
            }
            repl_env.set(new MalSymbol("eval"), new MalFunc(
                        a => EVAL(a[0], repl_env)));
            int fileIdx = 0;
            if (args.Length > 0 && args[0] == "--raw") {
                Mal.readline.mode = Mal.readline.Mode.Raw;
                fileIdx = 1;
            }
            MalList _argv = new MalList();
            for (int i=fileIdx+1; i < args.Length; i++) {
                _argv.conj_BANG(new MalString(args[i]));
            }
            repl_env.set(new MalSymbol("*ARGV*"), _argv);

            // core.mal: defined using the language itself
            RE("(def! *host-language* \"c#\")");
            RE("(def! not (fn* (a) (if a false true)))");
            RE("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
            RE("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))");
            RE("(def! *gensym-counter* (atom 0))");
            RE("(def! gensym (fn* [] (symbol (str \"G__\" (swap! *gensym-counter* (fn* [x] (+ 1 x)))))))");
            RE("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) (let* (condvar (gensym)) `(let* (~condvar ~(first xs)) (if ~condvar ~condvar (or ~@(rest xs)))))))))");

            if (args.Length > fileIdx) {
                RE("(load-file \"" + args[fileIdx] + "\")");
                return;
            }

            // repl loop
            RE("(println (str \"Mal [\" *host-language* \"]\"))");
            while (true) {
                string line;
                try {
                    line = Mal.readline.Readline("user> ");
                    if (line == null) { break; }
                    if (line == "") { continue; }
                } catch (IOException e) {
                    Console.WriteLine("IOException: " + e.Message);
                    break;
                }
                try {
                    Console.WriteLine(PRINT(RE(line)));
                } catch (Mal.types.MalContinue) {
                    continue;
                } catch (Mal.types.MalException e) {
                    Console.WriteLine("Error: " +
                            printer._pr_str(e.getValue(), false));
                    continue;
                } catch (Exception e) {
                    Console.WriteLine("Error: " + e.Message);
                    Console.WriteLine(e.StackTrace);
                    continue;
                }
            }
        }
Example #22
0
 public static string _pr_str_args(MalList args, String sep,
                                   bool print_readably) {
     return join(args.getValue(), sep, print_readably);
 }