Пример #1
0
        static public Expression Parse(object a)
        {
            if (a is Symbol)
            {
                if (((Symbol)a).val.IndexOf(".") == -1)
                {
                    return(new Var(a as Symbol));
                }
                else
                {
                    string aString    = ((Symbol)a).val;
                    int    posLastDot = aString.LastIndexOf(".");

                    Expression[] rands = new Expression[2];
                    rands[0] = Expression.Parse(Symbol.Create(aString.Substring(0, posLastDot)));
                    rands[1] = new Lit(Symbol.Create(aString.Substring(posLastDot + 1, aString.Length - posLastDot - 1)));

                    return(new App(Expression.Parse(Symbol.Create("get-property")), rands));
                }
            }
            if (a is Pair)
            {
                Pair   pair = a as Pair;
                object car  = pair.car;
                switch (car.ToString())
                {
                case "begin":
                    Expression[] exps = new Expression[pair.cdr.Count];
                    int          pos  = 0;
                    foreach (object obj in pair.cdr)
                    {
                        exps[pos] = Parse(obj);
//                          exps[pos].Mark(obj);
                        pos++;
                    }
                    Begin beginExps = new Begin(exps);
//                      beginExps.Mark(pair);
                    return(beginExps);

                case "if":
                    Pair       curr     = pair.cdr;
                    Expression test_exp = Parse(curr.car);
//                      test_exp.Mark(curr.car);
                    curr = curr.cdr;
                    Expression true_exp = Parse(curr.car);
//                      true_exp.Mark(curr.car);
                    curr = curr.cdr;
                    Expression false_exp = Parse(curr.car);
//                      false_exp.Mark(curr.car);
                    return(new If(test_exp, true_exp, false_exp));

                case "quote":
                    return(new Lit(pair.cdr.car));

                case "set!":
                {
                    Symbol var = pair.cdr.car as Symbol;
                    if (var == null)
                    {
                        throw new Exception("set! error -> variable must be a symbol: " + Util.Dump(pair));
                    }

                    Expression exp = Parse(pair.cdr.cdr.car) as Expression;
//                      exp.Mark(pair.cdr.cdr.car);
                    if (var.val.IndexOf('.') == -1)
                    {
                        Assignment assignment = new Assignment(var, exp);
//                          assignment.Mark(pair);
                        return(assignment);
                    }
                    else
                    {
                        string       aString    = var.val;
                        int          posLastDot = aString.LastIndexOf(".");
                        Expression[] rands      = new Expression[3];
                        rands[0] = Expression.Parse(Symbol.Create(aString.Substring(0, posLastDot)));
                        rands[1] = new Lit(Symbol.Create(aString.Substring(posLastDot + 1, aString.Length - posLastDot - 1)));
                        rands[2] = exp;

                        App app = new App(Expression.Parse(Symbol.Create("set-property")), rands);
//                          app.Mark(pair);
                        return(app);
                    }
                }

                case "lambda":
                    // Debug.WriteLine("sparsing lambda " + pair.ToString());
                    curr = pair.cdr  as Pair;
                    Symbol[] ids        = null;
                    bool     all_in_one = false;
                    if (curr.car != null)
                    {
                        if (curr.car is Pair)
                        {
                            Object[] ids_as_obj = (curr.car as Pair).ToArray();
                            ids = new Symbol[ids_as_obj.Length];
                            for (int i = 0; i < ids_as_obj.Length; i++)
                            {
                                ids[i] = ids_as_obj[i] as Symbol;
                                if (ids[i] == null)
                                {
                                    throw new Exception("lambda error -> params must be symbols: " + Util.Dump(pair));
                                }
                            }
                        }
                        else
                        {
                            all_in_one = true;
                            ids        = new Symbol[1];
                            ids[0]     = curr.car as Symbol;
                            if (ids[0] == null)
                            {
                                throw new Exception("lambda error -> params must be symbols: " + Util.Dump(pair));
                            }
                        }
                    }
                    curr = curr.cdr  as Pair;
                    // insert implied begin if neccessary
                    Expression body;
                    if (curr.cdr == null)
                    {
                        body = Parse(curr.car);
//                          if (curr.car is Pair)
//                              body.Mark(curr.car);
//                          else
//                              body.Mark(curr);
                    }
                    else
                    {
                        Expression[] begin = new Expression[curr.Count];
                        pos = 0;
                        foreach (object obj in curr)
                        {
                            begin[pos] = Parse(obj);
//                              begin[pos].Mark(obj);
                            pos++;
                        }
                        body = new Begin(begin);
                    }
                    return(new Proc(ids, body, all_in_one));

                default:                          // app
                    if (pair.hasMember)
                    {
                        Expression[] rands = new Expression[2];
                        if (pair.member.IndexOf('.') != -1)
                        {
                            string currentMember = pair.member;
                            int    posLastDot    = currentMember.LastIndexOf(".");

                            pair.member = currentMember.Substring(0, posLastDot);
                            rands[0]    = Expression.Parse(pair);
                            pair.member = currentMember;

                            rands[1] = new Lit(Symbol.Create(currentMember.Substring(posLastDot + 1, currentMember.Length - posLastDot - 1)));
                        }
                        else
                        {
                            pair.hasMember = false;
                            rands[0]       = Expression.Parse(pair);
                            pair.hasMember = true;

                            rands[1] = new Lit(Symbol.Create(pair.member));
                        }
                        return(new App(Expression.Parse(Symbol.Create("get-property")), rands));
                    }
                    else
                    {
                        Expression[] rands = null;
                        if (pair.cdr != null)
                        {
                            rands = new Expression[pair.cdr.Count];
                            pos   = 0;
                            foreach (object obj in pair.cdr)
                            {
                                rands[pos] = Expression.Parse(obj);
//                                  rands[pos].Mark(obj);
                                pos++;
                            }
                        }

                        IPrim prim = Primitives.getPrim(pair.car.ToString());
                        if (prim != null)
                        {
                            Primapp primapp = new Primapp(prim, rands);
//                              primapp.Mark(pair);
                            return(primapp);
                        }
                        else
                        {
                            App app = new App(Expression.Parse(pair.car), rands);
//                              app.Mark(pair);
                            return(app);
                        }
                    }
                }
            }
            else
            {
                return(new Lit(a));
            }
        }
Пример #2
0
        public object Eval(TextReader str)
        {
            //Console.WriteLine("starting eval");
            Object evaledObj = null;
            Object parsedObj = Util.read(str);


            if (parsedObj is Pair)
            {
                if (macros.Count > 0)
                {
//                  bool curRunHidden = DebugInfo.RunHidden;
//                  DebugInfo.RunHidden = true; //don't debug the macro expension code

                    Closure macroExpand = initEnv.Apply(Symbol.Create("macro-expand")) as Closure;
                    parsedObj = macroExpand.Eval(new Object[] { parsedObj });

//                  DebugInfo.RunHidden = curRunHidden;
                }

                Pair p = parsedObj as Pair;
                switch (p.car.ToString())
                {
                case "define":
                    Expression expr = null;
                    Symbol     def  = null;
                    if (p.cdr.car is Pair)                             // (define (fn x y) body)
                    {
                        Pair def_and_args = p.cdr.car as Pair;
                        Pair body         = p.cdr.cdr;
                        Pair syms         = def_and_args.cdr;
                        def  = Symbol.Create(def_and_args.car.ToString());
                        expr = Expression.Parse(Pair.Cons(Symbol.Create("lambda"), Pair.Cons(syms, body)));
                        // Debug.WriteLine(def + "-->" + expr);
                    }
                    else                             // (define fn (lambda (x y) body))
                    {
                        def  = Symbol.Create(p.cdr.car.ToString());
                        expr = Expression.Parse(p.cdr.cdr.car);
                    }
                    //initEnv = new Extended_Env(new Pair(def), new Pair(null), initEnv);
                    //Object value = Eval(expr);
                    //Console.WriteLine("defining: " + def);
//                      expr.Mark(p);
                    initEnv.Bind(def, Eval(expr));
                    break;

                case "macro":
                    Symbol name = p.cdr.car as Symbol;
                    // Console.WriteLine("macrodef" + name + " " + Expression.Parse(p.cdr.cdr.car).Eval(initEnv).ToString());
                    Closure transformer = (Closure)Expression.Parse(p.cdr.cdr.car).Eval(initEnv);
                    this.macros[name] = transformer;
                    // Console.WriteLine("macro: " + name);
                    break;

                default:
                    // need to call macro-expand in here. but how?
                    evaledObj = Util.Dump(Eval(Expression.Parse(parsedObj)));
                    break;
                }
            }
            else
            {
                evaledObj = Util.Dump(Eval(Expression.Parse(parsedObj)));
            }

            if (str.Peek() == -1)
            {
                return(evaledObj);
            }
            else
            {
                return(Eval(str));
            }
        }