public Procedure(Cell parms, Cell body, Env env) { this.parms = parms.list.Select(x => x.symbol).ToList(); this.body = body; this.env = env; }
// // Eval // static public Cell Eval(Cell x) { return(Eval(x, GlobalEnv)); }
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)); } } }
// // Initialize an environment with some standard functions // static Program() { GlobalEnv["+"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { number = x[0].number + x[1].number, Type = Cell.CellType.Number }), Type = Cell.CellType.Function }; GlobalEnv["-"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { number = x[0].number - x[1].number, Type = Cell.CellType.Number }), Type = Cell.CellType.Function }; GlobalEnv["*"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { number = x[0].number * x[1].number, Type = Cell.CellType.Number }), Type = Cell.CellType.Function }; GlobalEnv["/"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { number = x[0].number / x[1].number, Type = Cell.CellType.Number }), Type = Cell.CellType.Function }; GlobalEnv["="] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].number == x[1].number, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv["<"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].number < x[1].number, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv[">"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].number > x[1].number, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv["<="] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].number <= x[1].number, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv[">="] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].number >= x[1].number, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv["car"] = new Cell() { func = new Func <List <Cell>, Cell>(x => x[0].list.First()), Type = Cell.CellType.Function }; GlobalEnv["cdr"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { list = x[0].list.Skip(1).ToList(), Type = Cell.CellType.List }), Type = Cell.CellType.Function }; GlobalEnv["cons"] = new Cell() { func = new Func <List <Cell>, Cell>( x => { Cell res = new Cell() { Type = Cell.CellType.List }; res.list.Add(x[0]); res.list.AddRange(x[1].list); return(res); }), Type = Cell.CellType.Function }; GlobalEnv["append"] = new Cell() { func = new Func <List <Cell>, Cell>( x => { Cell res = new Cell() { Type = Cell.CellType.List }; res.list.AddRange(x[0].list); res.list.AddRange(x[1].list); return(res); }), Type = Cell.CellType.Function }; GlobalEnv["length"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { number = x[0].list.Count, Type = Cell.CellType.Number }), Type = Cell.CellType.Function }; GlobalEnv["null?"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { boolval = x[0].list.Count == 0, Type = Cell.CellType.Bool }), Type = Cell.CellType.Function }; GlobalEnv["list"] = new Cell() { func = new Func <List <Cell>, Cell>( x => new Cell() { list = x, Type = Cell.CellType.List }), Type = Cell.CellType.Function }; }