Пример #1
0
 public Procedure(Cell parms, Cell body, Env env)
 {
     this.parms = parms.list.Select(x => x.symbol).ToList();
     this.body  = body;
     this.env   = env;
 }
Пример #2
0
 //
 // Eval
 //
 static public Cell Eval(Cell x)
 {
     return(Eval(x, GlobalEnv));
 }
Пример #3
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));
                }
            }
        }
Пример #4
0
        //
        // 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
            };
        }