示例#1
0
 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));
 }
示例#2
0
        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);
        }