public Extended_Env(Symbol[] inSyms, Object[] inVals, Env inEnv) { this.env = inEnv; for (int pos=0; pos < inSyms.Length; pos++) { Symbol currSym = (Symbol) inSyms[pos]; if (!currSym.ToString().Equals(".")) //this.bindings.AddNew(currSym, inVals[pos]); //Hashlist this.bindings[currSym] = inVals[pos]; else { // multiple values passed in (R5RS 4.1.4) currSym = (Symbol) inSyms[pos+1]; //this.bindings.AddNew(currSym, Pair.FromArrayAt(inVals,pos)); //Hashlist this.bindings[currSym] = Pair.FromArrayAt(inVals,pos); break; } } }
public abstract object Bind(Symbol id, Object val);
public Extended_Env Extend(Symbol[] syms, Object[] vals) { return new Extended_Env(syms, vals, this); }
public override object Bind(Symbol id, Object val) { throw new Exception("Unbound variable " + id); }
public abstract object Apply(Symbol id);
public override object Apply(Symbol id) { if (this.bindings.ContainsKey(id)) return bindings[id]; else return env.Apply(id); }
// this and above should be merged somehow (may be obvious actually) /* public override object Bind(Symbol[] inSyms, Object[] inVals) { for (int pos=0; pos < inSyms.Length; pos++) { Symbol currSym = (Symbol) inSyms[pos]; if (!currSym.ToString().Equals(".")) this.bindings[currSym] = inVals[pos]; else { // multiple values passed in (R5RS 4.1.4) currSym = (Symbol) inSyms[pos+1]; this.bindings[currSym] = Pair.FromArrayAt(inVals,pos); break; } } return null; } */ public override object Bind(Symbol id, Object val) { if (this.bindings.ContainsKey(id) || env == The_Empty_Env) { bindings[id] = val; return id; } else { return env.Bind(id,val); } }
public Assignment(Symbol id, Expression val) { this.id = id; this.val = val; }
public override object Apply(Symbol id) { throw new Exception("Unbound variable " + id); }
public Var(Symbol id) { this.id = id; }
public Symbol[] ids; // if null, gets all args as a list #endregion Fields #region Constructors public Proc(Symbol[] ids, Expression body, bool all_in_one) { this.ids = ids; this.body = body; this.all_in_one = all_in_one; }
public static 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 static Symbol Create(String symName) { Symbol retVal; if (syms[symName] == null) { retVal = new Symbol(symName); syms.Add(symName, retVal); } else retVal = (Symbol) syms[symName]; return retVal; }
public Closure(Symbol[] ids, Expression body, bool all_in_one, Env env) { this.ids = ids; this.body = body; this.all_in_one = all_in_one; this.env = env; }