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); } }
public MalFunc(MalVal ast, Mal.env.Env env, MalList fparams, Func <MalList, MalVal> fn) { this.fn = fn; this.ast = ast; this.env = env; this.fparams = fparams; }
public static MalVal macroexpand(MalVal ast, Env env) { while (is_macro_call(ast, env)) { MalSymbol a0 = (MalSymbol)((MalList)ast)[0]; MalFunc mac = (MalFunc) env.get(a0); ast = mac.apply(((MalList)ast).rest()); } return ast; }
public static MalVal macroexpand(MalVal ast, Env env) { while (is_macro_call(ast, env)) { MalSymbol a0 = (MalSymbol)((MalList)ast)[0]; MalFunc mac = (MalFunc)env.get(a0); ast = mac.apply(((MalList)ast).rest()); } return(ast); }
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())); } }
public static bool is_macro_call(MalVal ast, Env env) { if (ast is MalList) { MalVal a0 = ((MalList)ast)[0]; if (a0 is MalSymbol && env.find((MalSymbol)a0) != null) { MalVal mac = env.get((MalSymbol)a0); if (mac is MalFunc && ((MalFunc)mac).isMacro()) { return true; } } } return false; }
public static bool is_macro_call(MalVal ast, Env env) { if (ast is MalList) { MalVal a0 = ((MalList)ast)[0]; if (a0 is MalSymbol && env.find((MalSymbol)a0) != null) { MalVal mac = env.get((MalSymbol)a0); if (mac is MalFunc && ((MalFunc)mac).isMacro()) { return(true); } } } return(false); }
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()); } }
// eval 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; } }
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 "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; } } }
public static MalVal RE(string str, Env env) { return(EVAL(READ(str), env)); }
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; } } }
// 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)); } }
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; } } }
public MalFunc(MalVal ast, Mal.env.Env env, MalList fparams, Func<MalList, MalVal> fn) { this.fn = fn; this.ast = ast; this.env = env; this.fparams = fparams; }
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.StackTrace); } 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; } } }
public Interpreter(Env env) { this.env = env; Initialize(); }
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; } } }