public Env(Env outer, eList binds, eList exprs) { this.outer = outer; for (int i = 0; i < binds.size(); i++) { string sym = ((eSymbol)binds.nth(i)).getName(); if (sym == "&") { data[((eSymbol)binds.nth(i + 1)).getName()] = exprs.slice(i); break; } else { data[sym] = exprs.nth(i); } } }
static eValue Eval(eValue orig_ast, Env env) { eValue a0, a1, a2, res; eList el; while (true) { if (!orig_ast.list_Q()) { return(ParseAST(orig_ast, env)); } eValue expanded = macroexpand(orig_ast, env); if (!expanded.list_Q()) { return(ParseAST(expanded, env)); } eList ast = (eList)expanded; if (ast.size() == 0) { return(ast); } a0 = ast[0]; String a0sym = a0 is eSymbol ? ((eSymbol)a0).getName() : "__<*fn*>__"; switch (a0sym) { case "def": // define vareable res = Eval(ast[2] /* vareable value */, env); env.set((eSymbol)ast[1] /* vareable name */, res); return(res); case "let": a1 = ast[1]; a2 = ast[2]; eSymbol key; eValue val; Env let_env = new Env(env); for (int i = 0; i < ((eList)a1).size(); i += 2) { key = (eSymbol)((eList)a1) [i]; val = ((eList)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": // define macros res = Eval(ast[2] /* macros value */, env); ((eFunction)res).setMacro(); env.set(((eSymbol)ast[1] /* macros name */), res); return(res); case "macroexpand": // return macros body return(macroexpand(ast[1] /* macros name */, env)); case "try*": try { return(Eval(ast[1], env)); } catch (Exception e) { if (ast.size() > 2) { eValue exc; a2 = ast[2]; eValue a20 = ((eList)a2) [0]; if (((eSymbol)a20).getName() == "catch*") { if (e is Evil.Types.eException) { exc = ((Evil.Types.eException)e).getValue(); } else { exc = new eString(e.StackTrace); } return(Eval(((eList)a2) [2], new Env(env, ((eList)a2).slice(1, 2), new eList(exc)))); } } throw e; } case "do": // simple block construction ParseAST(ast.slice(1, ast.size() - 1), env); orig_ast = ast[ast.size() - 1]; break; case "if": a1 = ast[1]; eValue cond = Eval(a1, env); if (cond == Evil.Types.Nil || cond == Evil.Types.False) { // eval false slot form if (ast.size() > 3) { orig_ast = ast[3]; } else { return(Evil.Types.Nil); } } else { // eval true slot form orig_ast = ast[2]; } break; case "fn": eList a1f = (eList)ast[1]; eValue a2f = ast[2]; Env cur_env = env; return(new eFunction(a2f, env, a1f, args => Eval(a2f, new Env(cur_env, a1f, args)))); default: el = (eList)ParseAST(ast, env); var f = (eFunction)el[0]; eValue fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; env = f.genEnv(el.rest()); } else { return(f.apply(el.rest())); } break; } } }