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)); } }
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)); } }