public static Lisp Eql(Lisp a, Lisp b) { if (ReferenceEquals(a, b)) { return(Lisp.T); } if ((a == null) || (b == null)) { return(Lisp.NIL); } return(a.Eql(b)); }
public Op Step() { Lisp instr = Pop(ref C); Lisp l, t, f, a1, a2; int i1, i2; Cons c; op = (instr as Opcode).op; has_arg = false; if (stop) { return(op); } switch (op) { case Op.NIL: Push(Lisp.NIL, ref S); break; case Op.LD: arg = Top(C); has_arg = true; Load(); break; case Op.LDC: arg = Top(C); has_arg = true; Push(Pop(ref C), ref S); break; case Op.ST: arg = Top(C); has_arg = true; Store(); break; case Op.LDF: arg = Top(C); has_arg = true; Push(new Cons(Pop(ref C), E), ref S); break; case Op.AP: Push(C, ref D); Push(E, ref D); E = Pop(ref S); C = Pop(ref E); Push(Pop(ref S), ref E); Push(S, ref D); S = Lisp.NIL; break; case Op.RTN: S = new Cons(Top(S), Pop(ref D)); E = Pop(ref D); C = Pop(ref D); break; case Op.DUM: E = new ConsC(null, E); break; case Op.RAP: Push(C, ref D); Push(Top(E), ref D); E = Pop(ref S); C = Pop(ref E); (E as Cons).Car = Pop(ref S); Push(S, ref D); S = null; break; case Op.SEL: l = Pop(ref S); t = Pop(ref C); f = Pop(ref C); Push(C, ref D); C = l == Lisp.NIL ? f : t; break; case Op.JOIN: C = Pop(ref D); break; case Op.CAR: c = Pop(ref S) as Cons; Push(c.Car, ref S); break; case Op.CDR: c = Pop(ref S) as Cons; Push(c.Cdr, ref S); break; case Op.ATOM: l = Pop(ref S); Push(Lisp.Bool(!(l is Cons)), ref S); break; case Op.INT: l = Pop(ref S); Push(Lisp.Bool(l is Integer), ref S); break; case Op.SYM: l = Pop(ref S); Push(Lisp.Bool(l is Symbol), ref S); break; case Op.STR: l = Pop(ref S); Push(Lisp.Bool(l is Str), ref S); break; case Op.CONS: a1 = Pop(ref S); a2 = Pop(ref S); Push(new Cons(a1, a2), ref S); break; case Op.EQ: a2 = Pop(ref S); a1 = Pop(ref S); Push(Lisp.Eq(a1, a2), ref S); break; case Op.EQL: a2 = Pop(ref S); a1 = Pop(ref S); Push(Lisp.Eql(a1, a2), ref S); break; case Op.ADD: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(new Integer(i1 + i2), ref S); break; case Op.SUB: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(new Integer(i1 - i2), ref S); break; case Op.MUL: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(new Integer(i1 * i2), ref S); break; case Op.DIV: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(new Integer(i1 / i2), ref S); break; case Op.REM: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(new Integer(i1 % i2), ref S); break; case Op.LEQ: i2 = (Pop(ref S) as Integer).ivalue; i1 = (Pop(ref S) as Integer).ivalue; Push(Lisp.Bool(i1 <= i2), ref S); break; case Op.AND: a2 = (Pop(ref S)); a1 = (Pop(ref S)); Push(Lisp.Bool((a1 != Lisp.NIL) && (a2 != Lisp.NIL)), ref S); break; case Op.OR: a2 = (Pop(ref S)); a1 = (Pop(ref S)); Push(Lisp.Bool((a1 != Lisp.NIL) || (a2 != Lisp.NIL)), ref S); break; case Op.NOT: Push(Lisp.Bool(Pop(ref S) == Lisp.NIL), ref S); break; case Op.TRY: a1 = Pop(ref C); // First try a2 = Pop(ref C); // Second try Push(C, ref D); // Push continuation for JOIN C = a1; Push(D, ref R); // Build Resumption Push(a2, ref R); Push(E, ref R); Push(S, ref R); break; case Op.FAIL: if (R == null) // Complete failure { S = new Cons(FAIL, Lisp.NIL); E = D = Lisp.NIL; C = new Cons(new Integer((int)Op.STOP), Lisp.NIL); } else // Try resuming { S = Pop(ref R); E = Pop(ref R); C = Pop(ref R); D = Pop(ref R); } break; case Op.STOP: stop = true; break; case Op.PRINT: l = Pop(ref S); c = l as Cons; if (c == null) { prtout.AppendLine(l.ToString()); //Console.WriteLine(l); } else { while (c != null) { prtout.Append($"{c.Car} "); //Console.Write(c.Car); //Console.Write(" "); c = c.Cdr as Cons; } prtout.AppendLine(); Console.WriteLine(); } break; case Op.ERR: Console.WriteLine("******ERROR******"); l = Pop(ref S); c = l as Cons; if (c == null) { prtout.AppendLine(l.ToString()); //Console.WriteLine(l); } else { while (c != null) { prtout.Append($"{c.Car} "); Console.Write(c.Car); Console.Write(" "); c = c.Cdr as Cons; } prtout.AppendLine(); Console.WriteLine(); } stop = true; error = true; break; case Op.PRIM: l = Pop(ref S); a1 = null; if (l is Symbol) { l = (l as Symbol).GlobalValue; if (l is Primitive) { a1 = new Integer((l as Primitive).id); } } Push(a1, ref S); // return nil or primitive id break; /* * case Op.PCALL: * l = Pop(ref S); * arg = Top(C); * Push(Primitives.Call(arg, l), S); * break; */ default: throw new ApplicationException("Unknown Opcode"); } return(op); }