static public Cell Eval(Cell x, Env env) { if (x.Type == Cell.CellType.Undefined) { throw new Exception("Undefined cell type"); } // Symbol if (x.Type == Cell.CellType.Symbol) { return(env[x.symbol]); } // Number else if (x.Type != Cell.CellType.List) { return(x); } // List if (x.list[0].symbol == "begin") { Cell res = null; foreach (var exp in x.list.Skip(1)) { res = Eval(exp, env); } return(res); } else if (x.list[0].symbol == "quote") { return(x.list[1]); } else if (x.list[0].symbol == "if") { var test = x.list[1]; var conseq = x.list[2]; var alt = x.list[3]; var exp = (Eval(test, env).boolval) == true ? conseq : alt; return(Eval(exp, env)); } else if (x.list[0].symbol == "define") { var variable = x.list[1]; var exp = x.list[2]; env[variable.symbol] = Eval(exp, env); return(null); } else if (x.list[0].symbol == "set!") { env[x.list[1].symbol] = Eval(x.list[2], env); return(null); } else if (x.list[0].symbol == "lambda") { return(new Cell() { proc = new Procedure(x.list[1], x.list[2], env), Type = Cell.CellType.Procedure }); } else { var proc = Eval(x.list[0], env); var args = x.list.Skip(1).Select(n => Eval(n, env)).ToList(); if (proc.Type == Cell.CellType.Procedure) { // Lambda call return(proc.proc.Call(args)); } else { // Function call return((Cell)proc.func.DynamicInvoke(args)); } } }
public Procedure(Cell parms, Cell body, Env env) { this.parms = parms.list.Select(x => x.symbol).ToList(); this.body = body; this.env = env; }
public Cell Call(List <Cell> args) { Env localEnv = new Env(parms, args, env); return(Program.Eval(body, localEnv)); }