Пример #1
0
        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));
                }
            }
        }
Пример #2
0
 public Procedure(Cell parms, Cell body, Env env)
 {
     this.parms = parms.list.Select(x => x.symbol).ToList();
     this.body  = body;
     this.env   = env;
 }
Пример #3
0
        public Cell Call(List <Cell> args)
        {
            Env localEnv = new Env(parms, args, env);

            return(Program.Eval(body, localEnv));
        }