public override void AddObject(LispObject obj) { if (obj == null) { throw new ArgumentNullException("obj"); } if (this.IsClosed) { throw new ApplicationException(); // todo2[ak] } if (this.ClosedDot) { throw new ApplicationException(); // todo2[ak] (a b c . d e) <-- e is wrong! } if (this.OpenedDot) { _curr.Cdr.Value = obj; this.ClosedDot = true; } else { Cons newCons = new Cons(obj, Symbol.Nil); if (_head == null) { _head = newCons; _curr = _head; } else { _curr.Cdr.Value = newCons; _curr = newCons; } } }
private static string ConsToStringImpl(Cons cons, bool addParens) { StringBuilder sb = new StringBuilder(); LispObject car = cons.Car.Value; LispObject cdr = cons.Cdr.Value; bool isQuoteCons = car == Symbol.Quote; if (isQuoteCons) { sb.Append("'"); } else { if (addParens) { sb.Append("("); } sb.Append(car.ToString()); } if (cdr == Symbol.Nil) { // add nothing. } else if (cdr is Cons) { Cons cdrCons = (Cons)cdr; if (cdrCons.Car.Value == Symbol.Quote) { sb.Append(" QUOTE "); var quoteArg = cdrCons.Cdr.Value; if (quoteArg is Cons) { sb.Append(((Cons)quoteArg).Car.Value.ToString()); } else if (quoteArg is Atom) { sb.Append(quoteArg.ToString()); } else { throw new ApplicationException(); // wtf } } else { if (!isQuoteCons) { sb.Append(" "); } sb.Append(ConsToStringImpl((Cons)cdrCons, false)); } } else { throw new NotImplementedException(); } if (!isQuoteCons) { if (addParens) { sb.Append(")"); } } string res = sb.ToString(); return res; }
public static Cons MakeQuote(LispObject quoted) { Cons cons = new Cons(Symbol.Quote, new Cons(quoted, Symbol.Nil)); return cons; }
public static LispObject MakeList(IEnumerable<LispObject> objs) { using (IEnumerator<LispObject> enmr = objs.GetEnumerator()) { Cons cons = null; Place lastCdr = null; while (true) { bool next = enmr.MoveNext(); if (!next) { break; } LispObject curr = enmr.Current; if (cons == null) { cons = new Cons(curr, Symbol.Nil); lastCdr = cons.Cdr; } else { Cons innerCons = new Cons(curr, Symbol.Nil); lastCdr.Value = innerCons; lastCdr = innerCons.Cdr; } } return cons == null ? (LispObject)Symbol.Nil : (LispObject)cons; } }
public static Cons MakeFunction(LispObject lambda) { Cons cons = new Cons(Symbol.Function, new Cons(lambda, Symbol.Nil)); return cons; }
public static string ConsToString(Cons cons) { return ConsToStringImpl(cons, true); }
public QuoteParsingContext() { _innerCons = new Cons(Symbol.Nil, Symbol.Nil); _cons = new Cons(Symbol.Quote, _innerCons); }
private string WriteCons(Cons cons) { StringBuilder sb = new StringBuilder(); Machina machina = new Machina(cons); while (true) { if (machina.Runner.IsStart && !machina.Runner.IsCarProcessed) { if (machina.Runner.IsValidQuotation) { sb.Append("'"); } else { sb.Append("("); } } // deal with car if (!machina.Runner.IsCarProcessed) { var car = machina.Runner.Current.Car.Value; if (machina.Runner.IsStart && machina.Runner.IsValidQuotation) { // add nothing - apostrophe ' already added } else { if (car is Atom) { // car is atom sb.Append(car.ToString()); } else { // car is cons machina.Sink(); continue; } } } // deal with cdr var cdr = machina.Runner.Current.Cdr.Value; if (cdr is Atom) { // cdr is atom if (cdr == Symbol.Nil) { // got NIL at cdr, thus close the list. if (machina.Runner.IsValidQuotation) { // don't close } else { sb.Append(")"); } machina.Float(); if (machina.IsEmpty) { break; } else { machina.Runner.MarkCarProcessed(); } } else { throw new NotImplementedException(); } } else { bool needSpace = !(machina.Runner.IsStart && machina.Runner.IsValidQuotation); machina.Advance(); if (needSpace) { sb.Append(" "); } } } string res = sb.ToString(); return res; }
internal Runner(Cons head) { this.Head = head; this.Current = head; }
internal Machina(Cons head) { _runners = new Stack<Runner>(); _runners.Push(new Runner(head)); }