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