public static void AddGlobals(SchemeEnvironment e) { e.Insert(False.Value, False); e.Insert(True.Value, True); e.Insert(Nil.Value, Nil); e.Insert("+", new Cell(Plus)); e.Insert("-", new Cell(Minus)); e.Insert("*", new Cell(Multiply)); e.Insert("/", new Cell(Divide)); e.Insert("<", new Cell(LessThan)); e.Insert("<=", new Cell(LessThanEqual)); e.Insert(">", new Cell(GreaterThan)); e.Insert(">=", new Cell(GreaterThanEqual)); e.Insert("=", new Cell(Equal)); e.Insert("==", new Cell(Equal)); e.Insert("print", new Cell(Print)); e.Insert("head", new Cell(Head)); e.Insert("tail", new Cell(Tail)); e.Insert("null?", new Cell(Nullp)); e.Insert("list", new Cell(List)); e.Insert("cons", new Cell(Cons)); e.Insert("append", new Cell(Append)); e.Insert("length", new Cell(Length)); // Add CellType.[Name] definitions CellType cellType = CellType.SYMBOL; foreach (var kv in cellType.GetKeyValues <int>()) { e.Insert("CellType." + kv.Key, new Cell(kv.Value)); } }
protected Cell InternalEval(Cell x, SchemeEnvironment env) { Cell original = x; ++depth; recurse: if (debug) { if (original != x) { Console.WriteLine("{0}) {1} => {2}", new string('-', depth), original, x); } else { Console.WriteLine("{0}) {1}", new string('-', depth), x); } } ++stepCounter; if (x.Type == CellType.SYMBOL) { x = env.Find(x.Value)[x.Value]; goto done; } if (x.Type == CellType.NUMBER) { goto done; } if (x.ListValue.Count == 0) { x = StandardRuntime.Nil; goto done; } if (x.ListValue[0].Type == CellType.SYMBOL) { Cell sym = x.ListValue[0]; switch ((string)sym) { case "quote": // (quote exp) x = x.ListValue[1]; goto done; case "if": // (if test conseq [alt]) Cell test = x.ListValue[1]; Cell conseq = x.ListValue[2]; Cell alt = StandardRuntime.Nil; if (x.ListValue.Count >= 4) { alt = x.ListValue[3]; } Cell testval = Eval(test, env); Cell final = testval == StandardRuntime.False ? alt : conseq; x = final; goto recurse; case "set!": // (set! var exp) - must exist x = env.Find(x.ListValue[1].Value)[x.ListValue[1].Value] = Eval(x.ListValue[2], env); goto done; case "define": // (define var exp) - creates new Cell b = Eval(x.ListValue[2], env); env.Insert(x.ListValue[1].Value, b); x = b; goto done; case "lambda": // (lambda (var*) exp) x.Type = CellType.LAMBDA; x.Environment = env; goto done; case "macro": // (macro (var*) exp) x.Type = CellType.MACRO; x.Environment = env; goto done; case "begin": // (begin exp*) for (int i = 1; i < x.ListValue.Count - 1; ++i) { Eval(x.ListValue[i], env); } // tail recurse x = x.ListValue.Last(); goto recurse; } } // (proc exp*) Cell proc = Eval(x.ListValue[0], env); List <Cell> exps = new List <Cell>(); if (proc.Type == CellType.MACRO) { exps = x.Tail().ListValue; } else { for (int i = 1; i < x.ListValue.Count; ++i) { exps.Add(Eval(x.ListValue[i], env)); } } if (proc.Type == CellType.LAMBDA) { env = new SchemeEnvironment(proc.ListValue[1].ListValue, exps, proc.Environment); x = proc.ListValue[2]; goto recurse; } else if (proc.Type == CellType.MACRO) { SchemeEnvironment env2 = new SchemeEnvironment(proc.ListValue[1].ListValue, exps, proc.Environment); x = Eval(proc.ListValue[2], env2); goto recurse; } else if (proc.Type == CellType.PROC) { x = proc.ProcValue(exps.ToArray()); goto done; } else if (proc.Type == CellType.PROCENV) { x = proc.ProcEnvValue(exps.ToArray(), env); goto done; } throw new SchemeException("Invalid item in Eval"); done: if (debug) { Console.WriteLine("{0}) {1} => {2} ", new string('-', depth), original, x); } --depth; return(x); }