public Dictionary <string, Cell> Find(string key) { if (map.ContainsKey(key)) { return(map); } if (outer != null) { return(outer.Find(key)); } throw new CellNameNotFound(key); }
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); }