picolisp

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/picolisp.git/
Log | Files | Refs | README | LICENSE

sys.src (86334B)


      1 // 17jul13abu
      2 // (c) Software Lab. Alexander Burger
      3 
      4 import java.util.*;
      5 import java.math.*;
      6 import java.io.*;
      7 import java.net.*;
      8 import java.nio.*;
      9 import java.nio.channels.*;
     10 import java.lang.reflect.*;
     11 
     12 /* Ersatz PicoLisp Interpreter (Poor Man's PicoLisp) */
     13 public class PicoLisp {
     14    final static Console Term = System.console();
     15    final static StringBuffer Line = new StringBuffer();
     16    final static Namespace Pico = new Namespace();
     17    final static Namespace Transient = new Namespace();
     18    final static byte MonLen[] = new byte[] {31,31,28,31,30,31,30,31,31,30,31,30,31};
     19    final static byte Version[] = new byte[] {<VERSION>};
     20 
     21    final static Number Zero = new Number(0);
     22    final static Number One = new Number(1);
     23    final static Number Two = new Number(2);
     24 
     25    final static NilSym Nil = new NilSym();
     26    final static Symbol pico = mkSymbol(new Symbol(Pico), "pico", Pico);
     27    final static Symbol T = mkSymbol(null, "T", Pico);
     28    final static Symbol Pid = mkSymbol(new Number(System.getProperty("PID")), "*Pid", Pico);
     29    final static Symbol At = mkSymbol(Nil, "@", Pico);
     30    final static Symbol At2 = mkSymbol(Nil, "@@", Pico);
     31    final static Symbol At3 = mkSymbol(Nil, "@@@", Pico);
     32    final static Symbol This = mkSymbol(Nil, "This", Pico);
     33    final static Symbol Prompt = mkSymbol(Nil, "*Prompt", Pico);
     34    final static Symbol Dbg = mkSymbol(Nil, "*Dbg", Pico);
     35    final static Symbol Scl = mkSymbol(Zero, "*Scl", Pico);
     36    final static Symbol Class = mkSymbol(Nil, "*Class", Pico);
     37    final static Symbol Run = mkSymbol(Nil, "*Run", Pico);
     38    final static Symbol Up = mkSymbol(Nil, "^", Pico);
     39    final static Symbol Err = mkSymbol(Nil, "*Err", Pico);
     40    final static Symbol Msg = mkSymbol(Nil, "*Msg", Pico);
     41    final static Symbol Uni = mkSymbol(Nil, "*Uni", Pico);
     42    final static Symbol Adr = mkSymbol(Nil, "*Adr", Pico);
     43    final static Symbol Bye = mkSymbol(Nil, "*Bye", Pico);
     44 
     45    final static Symbol Quote = mkSymbol(Zero, "quote", Pico);
     46    final static Symbol Meth = mkSymbol(One, "meth", Pico);
     47 
     48    final static String Delim = " \t\n\r\"'(),[]`~{}";
     49 
     50    static Catch Catch;
     51    static Env Env = new Env();
     52    static Process[] Pids = new Process[12];
     53    static PicoLispReader[] InFiles = new PicoLispReader[12];
     54    static PicoLispWriter[] OutFiles = new PicoLispWriter[12];
     55    final static PicoLispReader StdIn = new PicoLispReader(System.in, 0, null, 0);
     56    final static PicoLispWriter StdOut = new PicoLispWriter(System.out, 1);
     57    final static PicoLispWriter StdErr = new PicoLispWriter(System.err, 2);
     58    static PicoLispReader InFile = StdIn;
     59    static PicoLispWriter OutFile = StdOut;
     60    static Any TheCls, TheKey, Penv, Pnl;
     61    static String[] Argv;
     62    static String Home;
     63    static Calendar Cal;
     64    static int MaxFun;
     65    static long USec, Seed;
     66    static boolean Break, Jam, B;
     67    static Bind Brk;
     68 
     69    public static void main(String[] argv) {
     70       Argv = argv;
     71       <SYM> 1
     72       init();
     73       for (boolean first = true; ; first = false) {
     74          try {
     75             if (first)
     76                loadAll(null);
     77             for (;;)
     78                load(null, ':', Nil);
     79          }
     80          catch (Control e) {}
     81          catch (Throwable e) {error(null, null, e.toString());}
     82       }
     83    }
     84 
     85    final static void init() {
     86       int i;
     87       String s;
     88       Home = "";
     89       if (Argv.length > 0 && Argv[Argv.length-1].equals("+")) {
     90          Dbg.Car = T;
     91          String[] a = new String[Argv.length-1];
     92          System.arraycopy(Argv, 0, a, 0, a.length);
     93          Argv = a;
     94       }
     95       if (Argv.length > 0 && (s = Argv[0]).charAt(0) != '-' && ((i = s.lastIndexOf('/')) >= 0 && !(i == 1 && s.charAt(0) == '.')))
     96          Home = s.substring(0, i+1);
     97       try {
     98          if (Term != null) {
     99             final Pipe p = Pipe.open();
    100             StdIn.Chan = p.source();
    101             StdIn.Ops = SelectionKey.OP_READ;
    102             (new Thread() {
    103                public void run() {
    104                   for (;;) {
    105                      String s = Term.readLine();
    106                      if (s == null) {
    107                         StdOut.newline();
    108                         bye(0);
    109                      }
    110                      Line.append(s);
    111                      Line.append('\n');
    112                      try {p.sink().write(ByteBuffer.allocate(1));}
    113                      catch (IOException e) {giveup(e);}
    114                   }
    115                }
    116             } ).start();
    117          }
    118       }
    119       catch (IOException e) {giveup(e);}
    120       USec = System.nanoTime() / 1000;
    121    }
    122 
    123    final static void giveup(Exception e) {
    124       System.err.println(e);
    125       System.exit(1);
    126    }
    127 
    128    final static Any bye(int n) {
    129       if (!B) {
    130          B = true;
    131          unwind(null);
    132          Bye.Car.prog();
    133       }
    134       System.exit(n);
    135       return null;  /* Brain-dead Java */
    136    }
    137 
    138    final static Constructor javaConstructor(Any ex, Class cls, Class[] par)  throws NoSuchMethodException {
    139    looking:
    140       for (Constructor m : cls.getConstructors()) {
    141          Class<?>[] types = m.getParameterTypes();
    142          if (types.length == par.length) {
    143             for (int i = 0; i < types.length; ++i)
    144                if (!(types[i].isAssignableFrom(par[i])))
    145                   continue looking;
    146             return m;
    147          }
    148       }
    149       throw new NoSuchMethodException();
    150    }
    151 
    152    final static Method javaMethod(Any ex, Class cls, String nm, Class[] par)  throws NoSuchMethodException {
    153    looking:
    154       for (Method m : cls.getMethods()) {
    155          if (m.getName().equals(nm)) {
    156             Class<?>[] types = m.getParameterTypes();
    157             if (types.length == par.length) {
    158                for (int i = 0; i < types.length; ++i)
    159                   if (!(types[i].isAssignableFrom(par[i])))
    160                      continue looking;
    161                return m;
    162             }
    163          }
    164       }
    165       throw new NoSuchMethodException(nm);
    166    }
    167 
    168    final static int waitFd(Any ex, int fd, int ms) {
    169       int i;
    170       Selector sel;
    171       Any task = Env.Task,  at = At.Car;
    172       try {
    173          for (;;) {
    174             sel = Selector.open();
    175             int t = ms >= 0? ms : Integer.MAX_VALUE;
    176             if (fd >= 0 && InFiles[fd] != null)
    177                if (InFiles[fd].ready(sel))
    178                   t = 0;
    179                else
    180                   InFiles[fd].register(sel);
    181             for (Any x = Env.Task = Run.Car; x instanceof Cell; x = x.Cdr) {
    182                if (memq(x.Car, task) == null) {
    183                   if ((i = ((Number)x.Car.Car).Cnt) < 0) {
    184                      if ((i = ((Number)x.Car.Cdr.Car).Cnt) < t)
    185                         t = i;
    186                   }
    187                   else if (i != fd) {
    188                      if (i < InFiles.length && InFiles[i] != null)
    189                         if (InFiles[i].ready(sel))
    190                            t = 0;
    191                         else
    192                            InFiles[i].register(sel);
    193                   }
    194                }
    195             }
    196             long d = System.currentTimeMillis();
    197             if (t == 0)
    198                sel.selectNow();
    199             else
    200                sel.select(t);
    201             t = (int)(System.currentTimeMillis() - d);
    202             if (ms > 0  &&  (ms -= t) < 0)
    203                ms = 0;
    204             for (Any x = Env.Task; x instanceof Cell; x = x.Cdr) {
    205                if (memq(x.Car, task) == null) {
    206                   if ((i = ((Number)x.Car.Car).Cnt) < 0) {
    207                      if ((i = ((Number)x.Car.Cdr.Car).Cnt - t) > 0)
    208                         ((Number)x.Car.Cdr.Car).Cnt = i;
    209                      else {
    210                         ((Number)x.Car.Cdr.Car).Cnt = -((Number)x.Car.Car).Cnt;
    211                         At.Car = x.Car.Car;
    212                         x.Car.Cdr.Cdr.prog();
    213                      }
    214                   }
    215                   else if (i != fd) {
    216                      if (i < InFiles.length && InFiles[i] != null && InFiles[i].ready(sel)) {
    217                         At.Car = x.Car.Car;
    218                         x.Car.Cdr.prog();
    219                      }
    220                   }
    221                }
    222             }
    223             if (ms == 0 || fd < 0 || InFiles[fd] != null && InFiles[fd].ready(sel))
    224                break;
    225             sel.close();
    226          }
    227       }
    228       catch (IOException e) {giveup(e);}
    229       At.Car = at;
    230       Env.Task = task;
    231       return ms;
    232    }
    233 
    234    final static long initSeed(Any x) {
    235       long n;
    236       for (n = 0; x instanceof Cell; x = x.Cdr)
    237          n += initSeed(x.Car);
    238       if (x != Nil) {
    239          if (x instanceof Number && ((Number)x).Big == null)
    240             n += ((Number)x).Cnt;
    241          else {
    242             byte b[] = x instanceof Symbol? x.name().getBytes() : ((Number)x).Big.toByteArray();
    243             for (int i = 0; i < b.length; ++i)
    244                n += b[i];
    245          }
    246       }
    247       return n>=0? n*2 : -n*2+1;
    248    }
    249 
    250    final static Any date(int y, int m, int d) {
    251       int n;
    252 
    253       if (m<1 || m>12 || d<1 || d>MonLen[m] && (m!=2 || d!=29 || y%4!=0 || y%100==0 && y%400!=0))
    254          return Nil;
    255       n = (12*y + m - 3) / 12;
    256       return new Number((4404*y+367*m-1094)/12 - 2*n + n/4 - n/100 + n/400 + d);
    257    }
    258 
    259    final static Any date(int n) {
    260       int y = (100*n - 20) / 3652425;
    261       n += (y - y/4);
    262       y = (100*n - 20) / 36525;
    263       n -= 36525*y / 100;
    264       int m = (10*n - 5) / 306;
    265       int d = (10*n - 306*m + 5) / 10;
    266       if (m < 10)
    267          m += 3;
    268       else {
    269          ++y;
    270          m -= 9;
    271       }
    272       return new Cell(new Number(y), new Cell(new Number(m), new Cell(new Number(d), Nil)));
    273    }
    274 
    275    final static Any time(Calendar cal) {
    276       return new Number(cal.get(Calendar.HOUR_OF_DAY) * 3600 + cal.get(Calendar.MINUTE) * 60 + cal.get(Calendar.SECOND));
    277    }
    278 
    279    final static Any time(int h, int m, int s) {
    280       if (h < 0 || h > 23  ||  m < 0 || m > 59  ||  s < 0 || s > 60)
    281          return Nil;
    282       return new Number(h * 3600 + m * 60 + s);
    283    }
    284 
    285    final static char firstChar(Any s) {
    286       String nm = s.name();
    287       return nm.length() == 0? '\0' : nm.charAt(0);
    288    }
    289 
    290    final static String path(String s) {
    291       if (s.length() > 0)
    292          if (s.charAt(0) == '+') {
    293             if (s.length() > 1 && s.charAt(1) == '@')
    294                return '+' + Home + s.substring(1);
    295          }
    296          else if (s.charAt(0) == '@')
    297             return Home + s.substring(1);
    298       return s;
    299    }
    300 
    301    final static void unwind(Catch target) {
    302       int i, j, n;
    303       Bind p;
    304       Catch q;
    305       Any x, y;
    306       while ((q = Catch) != null) {
    307          while ((p = Env.Bind) != null) {
    308             if ((i = p.Eswp) != 0) {
    309                j = i;  n = 0;
    310                for (;;) {
    311                   ++n;
    312                   if (++j == 0 || (p = p.Link) == null)
    313                      break;
    314                   if (p.Eswp < i)
    315                      --j;
    316                }
    317                do {
    318                   for (p = Env.Bind, j = n; --j != 0; p = p.Link);
    319                   if ((p.Eswp -= i) >= 0) {
    320                      if (p.Eswp > 0)
    321                         p.Eswp = 0;
    322                      for (j = p.Cnt; (j -= 2) >= 0;) {
    323                         y = p.Data[j+1];
    324                         x = y.Car;  y.Car = p.Data[j];  p.Data[j] = x;
    325                      }
    326                   }
    327                } while (--n != 0);
    328             }
    329             if (Env.Bind == q.Env.Bind)
    330                break;
    331             if (Env.Bind.Eswp == 0)
    332                for (i = Env.Bind.Cnt; (i -= 2) >= 0;)
    333                   Env.Bind.Data[i+1].Car = Env.Bind.Data[i];
    334             Env.Bind = Env.Bind.Link;
    335          }
    336          while (Env.InFrames != q.Env.InFrames)
    337             Env.popInFiles();
    338          while (Env.OutFrames != q.Env.OutFrames)
    339             Env.popOutFiles();
    340          Env = q.Env;
    341          q.Fin.eval();
    342          Catch = q.Link;
    343          if (q == target)
    344             return;
    345       }
    346       while (Env.Bind != null) {
    347          if (Env.Bind.Eswp == 0)
    348             for (i = Env.Bind.Cnt; (i -= 2) >= 0;)
    349                Env.Bind.Data[i+1].Car = Env.Bind.Data[i];
    350          Env.Bind = Env.Bind.Link;
    351       }
    352       while (Env.InFrames != null)
    353          Env.popInFiles();
    354       while (Env.OutFrames != null)
    355          Env.popOutFiles();
    356    }
    357 
    358    final static void error(Any ex, Any x, String msg) {
    359       Up.Car = ex == null? Nil : ex;
    360       if (msg.length() != 0) {
    361          Msg.Car = mkStr(msg);
    362          for (Catch p = Catch;  p != null;  p = p.Link) {
    363             Any y = p.Tag;
    364             if (y != null)
    365                while (y instanceof Cell) {
    366                   if (msg.indexOf(y.Car.name()) >= 0)
    367                      throw new Control(ex, p.Tag, y.Car == Nil? Msg.Car : y.Car);
    368                   y = y.Cdr;
    369                }
    370          }
    371       }
    372       InFile.Chr = 0;
    373       Break = false;
    374       Line.delete(0, Line.length());
    375       Env.pushOutFile(new OutFrame(OutFiles[2], 0));
    376       if (InFile.Name != null)
    377          StdErr.Wr.print('[' + InFile.Name + ':' + InFile.Src  + "] ");
    378       if (ex != null) {
    379          StdErr.Wr.print("!? ");
    380          StdErr.print(ex);
    381          StdErr.newline();
    382       }
    383       if (x != null) {
    384          StdErr.print(x);
    385          StdErr.Wr.print(" -- ");
    386       }
    387       if (msg.length() != 0) {
    388          StdErr.Wr.print(msg);
    389          StdErr.newline();
    390          if (Err.Car != Nil && !Jam) {
    391             Jam = true;
    392             Err.Car.prog();
    393             Jam = false;
    394          }
    395          load(null, '?', Nil);
    396       }
    397       unwind(null);
    398       Env.Intern = pico;
    399       Env.Args = null;
    400       Env.Next = 0;
    401       Env.Task = Env.Make = Env.Yoke = null;
    402    }
    403 
    404    final static Any err(Any ex, Any x, String msg) {
    405       error(ex, x, msg);
    406       throw new Control();
    407    }
    408 
    409    final static Any brkLoad(Any x) {
    410       if (!Break) {
    411          Break = true;
    412          OutFile.Wr.flush();
    413          Brk = new Bind();
    414          Brk.add(Up.Car);  Brk.add(Up);  Up.Car = x;
    415          Brk.add(Run.Car);  Brk.add(Run);  Run.Car = Nil;
    416          Brk.add(At.Car);  Brk.add(At);
    417          Env.Bind = Brk;
    418          Env.pushOutFile(new OutFrame(OutFiles[1], 0));
    419          OutFile.print(x);
    420          OutFile.newline();
    421          load(null, '!', Nil);
    422          Env.popOutFiles();
    423          At.Car = Brk.Data[4];
    424          Run.Car = Brk.Data[2];
    425          x = Up.Car;
    426          Up.Car = Brk.Data[0];
    427          Env.Bind = Brk.Link;
    428          Break = false;
    429       }
    430       return x;
    431    }
    432 
    433    final static void trace(int i, Any x, String s) {
    434       if (i > 64)
    435          i = 64;
    436       while (--i >= 0)
    437          StdErr.space();
    438       if (x instanceof Symbol)
    439          StdErr.print(x);
    440       else {
    441          StdErr.print(x.Car);
    442          StdErr.space();
    443          StdErr.print(x.Cdr);
    444          StdErr.space();
    445          StdErr.print(This.Car);
    446       }
    447       StdErr.Wr.print(s);
    448    }
    449 
    450    final static Any execError(Any x) {return err(null, x, "Can't execute");}
    451    final static Any protError(Any x) {return err(null, x, "Protected symbol");}
    452    final static Any symError(Any x) {return err(null, x, "Symbol expected");}
    453    final static Any symNsError(Any ex, Any x) {return err(ex, x, "Bad symbol namespace");}
    454    final static Any  argError(Any ex, Any x) {return err(ex, x, "Bad argument");}
    455    final static Any cntError(Any ex, Any x) {return err(ex, x, "Small number expected");}
    456    final static void needVar(Any ex, Any x) {if (x instanceof Number) err(ex, x, "Variable expected");}
    457 
    458    final static void badFd(Any ex, Any x) {err(ex, x, "Bad FD");}
    459    final static void closeErr(IOException e) {err(null, null, e.toString());}
    460 
    461    final static Any load(Any ex, char pr, Any x) {
    462       if (x instanceof Symbol && firstChar(x) == '-')
    463          return ((Symbol)x).parse(true,null).eval();
    464       Symbol ns = Env.Intern;
    465       Env.pushInFile(x.rdOpen(ex));
    466       Transient.clear();
    467       x = Nil;
    468       for (;;) {
    469          Any y;
    470          if (InFile != StdIn)
    471             y = InFile.read('\0');
    472          else {
    473             if (pr != '\0'  &&  InFile.Chr == 0) {
    474                OutFile.Wr.print(Prompt.Car.run().name() + pr);
    475                OutFile.space();
    476                OutFile.Wr.flush();
    477             }
    478             y = InFile.read('\n');
    479             while (InFile.Chr > 0) {
    480                if (InFile.Chr == '\n') {
    481                   InFile.Chr = 0;
    482                   break;
    483                }
    484                if (InFile.Chr == '#')
    485                   InFile.comment();
    486                else {
    487                   if (InFile.Chr > ' ')
    488                      break;
    489                   InFile.get();
    490                }
    491             }
    492          }
    493          if (y == Nil) {
    494             Env.Intern = ns;
    495             Env.popInFiles();
    496             Transient.clear();
    497             return x;
    498          }
    499          if (InFile != StdIn || InFile.Chr != 0 || pr == '\0')
    500             x = y.eval();
    501          else {
    502             Any at = At.Car;
    503             x = At.Car = y.eval();
    504             At3.Car = At2.Car;
    505             At2.Car = at;
    506             OutFile.Wr.print("-> ");
    507             OutFile.Wr.flush();
    508             OutFile.print(x);
    509             OutFile.newline();
    510          }
    511       }
    512    }
    513 
    514    final static String opt() {
    515       if (Argv.length == 0 || Argv[0].equals("-"))
    516          return null;
    517       String s = Argv[0];
    518       String[] a = new String[Argv.length-1];
    519       System.arraycopy(Argv, 1, a, 0, a.length);
    520       Argv = a;
    521       return s;
    522    }
    523 
    524    final static Any loadAll(Any ex) {
    525       String s;
    526       Any x = Nil;
    527       while ((s = opt()) != null)
    528          x = load(ex, '\0', mkStr(s));
    529       return x;
    530    }
    531 
    532    final static Any undefined(Any x, Any ex) {
    533       return err(ex, x, "Undefined");
    534    }
    535 
    536    final static Any[] append(Any[] a, int i, Any x) {
    537       if (i == a.length) {
    538          Any[] b = new Any[i*2];
    539          System.arraycopy(a, 0, b, 0, i);
    540          a = b;
    541       }
    542       a[i] = x;
    543       return a;
    544    }
    545 
    546    final static int allocPid() {
    547       int i;
    548       for (i = 2; Pids[i] != null; ++i) {
    549          if (i == Pids.length) {
    550             Process[] p = new Process[i*2];
    551             System.arraycopy(Pids, 0, p, 0, i);
    552             Pids = p;
    553             break;
    554          }
    555       }
    556       return i;
    557    }
    558 
    559    final static int allocFd() {
    560       int i;
    561       for (i = 3; InFiles[i] != null || OutFiles[i] != null; ++i) {
    562          if (i == InFiles.length) {
    563             PicoLispReader[] r = new PicoLispReader[i*2];
    564             System.arraycopy(InFiles, 0, r, 0, i);
    565             InFiles = r;
    566             PicoLispWriter[] w = new PicoLispWriter[i*2];
    567             System.arraycopy(OutFiles, 0, w, 0, i);
    568             OutFiles = w;
    569             break;
    570          }
    571       }
    572       return i;
    573    }
    574 
    575    final static Any mkSocket(SocketChannel chan) throws IOException {
    576       int i = allocFd();
    577       Socket sock = chan.socket();
    578       new PicoLispReader(sock.getInputStream(), i, chan, SelectionKey.OP_READ);
    579       new PicoLispWriter(sock.getOutputStream(), i);
    580       return new Number(i);
    581    }
    582 
    583    final static Any accept(Any ex, int i) {
    584       try {
    585          SocketChannel chan = ((ServerSocketChannel)InFiles[i].Chan).accept();
    586          Adr.Car = mkStr(chan.socket().getInetAddress().getHostAddress());
    587          return mkSocket(chan);
    588       }
    589       catch (IOException e) {}
    590       return null;
    591    }
    592 
    593    final static Any mkChar(int c) {return new Symbol(null, "" + (char)(c >= 0x10000? 0xFFFF : c));}
    594    final static Any mkStr(String nm) {return nm == null || nm.length() == 0? Nil : new Symbol(null, nm);}
    595    final static Any mkStr(StringBuilder sb) {return mkStr(sb.toString());}
    596    final static Symbol mkSymbol(Any val) {return new Symbol(val, null);}
    597 
    598    final static Symbol mkSymbol(Any val, String nm, Namespace table) {
    599       Symbol sym;
    600       if ((sym = table.get(nm)) == null) {
    601          sym = new Symbol(val, nm);
    602          table.put(nm, sym);
    603       }
    604       return sym;
    605    }
    606 
    607    final static Any strToNum(String s, int scl) throws NumberFormatException {
    608       if (s.length() != 0 && s.charAt(0) == '+')
    609          s = s.substring(1);
    610       if (s.indexOf('.') <= 0)
    611          return new Number(s);
    612       return new Number((new BigDecimal(s)).setScale(scl, RoundingMode.HALF_UP).unscaledValue());
    613    }
    614 
    615    final static Any format(Any z, int scl, Any x) {
    616       char sep = '.', ign = '\0';
    617       if (x instanceof Cell) {
    618          sep = firstChar(x.Car.eval());
    619          if ((x = x.Cdr) instanceof Cell)
    620             ign = firstChar(x.Car.eval());
    621       }
    622       if (z instanceof Number)
    623          return mkStr(((Number)z).toString(scl,sep,ign));
    624       String s = z.name();
    625       StringBuilder sb = new StringBuilder();
    626       for (int i = 0; i < s.length(); ++i) {
    627          char c = s.charAt(i);
    628          if (c != ign)
    629             sb.append(c == sep? '.' : c);
    630       }
    631       try {return strToNum(sb.toString(), scl);}
    632       catch (NumberFormatException e) {return Nil;}
    633    }
    634 
    635    final static Any fish(Any ex, Any foo, Any[] v, Any res) {
    636       if (foo.apply(ex, false, v, 1) != Nil)
    637          return new Cell(v[0], res);
    638       if (v[0] instanceof Cell) {
    639          Any x = v[0];
    640          if ((v[0] = x.Cdr) != Nil)
    641             res = fish(ex, foo, v, res);
    642          v[0] = x.Car;
    643          res = fish(ex, foo, v, res);
    644          v[0] = x;
    645       }
    646       return res;
    647    }
    648 
    649    final static Any all(Namespace table) {
    650       Any x = Nil;
    651       for (Iterator<Symbol> it = table.values().iterator(); it.hasNext();)
    652          x = new Cell(it.next(), x);
    653       return x;
    654    }
    655 
    656    final static Any meta(Any x, Any y) {
    657       Any z;
    658       for (; x instanceof Cell; x = x.Cdr)
    659          if (x.Car instanceof Symbol && ((z = x.Car.get(y)) != Nil || (z = meta(x.Car.Car, y)) != Nil))
    660             return z;
    661       return Nil;
    662    }
    663 
    664    final static boolean isa(Any cls, Any x) {
    665       Any z;
    666       z = x = x.Car;
    667       while (x instanceof Cell) {
    668          if (!(x.Car instanceof Cell)) {
    669             while (x.Car instanceof Symbol) {
    670                if (cls == x.Car || isa(cls, x.Car))
    671                   return true;
    672                if (!((x = x.Cdr) instanceof Cell) || z == x)
    673                   return false;
    674             }
    675             return false;
    676          }
    677          if (z == (x = x.Cdr))
    678             return false;
    679       }
    680       return false;
    681    }
    682 
    683    final static void redefMsg(Any x, Any y) {
    684       StdErr.Wr.print("# ");
    685       StdErr.print(x);
    686       if (y != null) {
    687          StdErr.space();
    688          StdErr.print(y);
    689       }
    690       StdErr.Wr.println(" redefined");
    691       StdErr.Wr.flush();
    692    }
    693 
    694    final static void putSrc(Symbol s, Any k) {
    695       if (Dbg.Car != Nil && InFile != null && InFile.Name != null) {
    696          Any x = new Cell(new Number(InFile.Src), mkSymbol(null, InFile.Name, Transient));
    697          Any y = s.get(Dbg);
    698          if (k == null) {
    699             if (y == Nil)
    700                s.put(Dbg, new Cell(x, Nil));
    701             else
    702                y.Car = x;
    703          }
    704          else if (y == Nil)
    705             s.put(Dbg, new Cell(Nil, new Cell(x, Nil)));
    706          else {
    707             for (Any z = y.Cdr; z instanceof Cell; z = z.Cdr)
    708                if (z.Car.Car == k) {
    709                   z.Car.Cdr = x;
    710                   return;
    711                }
    712             y.Cdr = new Cell(new Cell(k, x), y.Cdr);
    713          }
    714       }
    715    }
    716 
    717    final static void redefine(Symbol s, Any x) {
    718       if (s.Car != Nil  &&  s != s.Car  &&  !x.equal(s.Car))
    719          redefMsg(s, null);
    720       s.Car = x;
    721       putSrc(s, null);
    722    }
    723 
    724    final static int xInt(Any x) {return ((Number)x).Cnt;}
    725    final static int evInt(Any ex) {return ((Number)ex.Car.eval()).Cnt;}
    726    final static long xLong(Any x) {return ((Number)x).longValue();}
    727    final static long evLong(Any ex) {return ((Number)ex.Car.eval()).longValue();}
    728    final static String evString(Any ex) {return ex.Car.eval().name();}
    729 
    730    final static Any circ(Any x) {
    731       HashSet<Any> mark = new HashSet<Any>();
    732       for (;;) {
    733          mark.add(x);
    734          if (!((x = x.Cdr) instanceof Cell))
    735             return null;
    736          if (mark.contains(x))
    737             return x;
    738       }
    739    }
    740 
    741    final static Any fill(Any x, Any s) {
    742       Any y, z;
    743       if (x instanceof Number || x == Nil)
    744          return null;
    745       if (x instanceof Symbol)
    746          return x != x.Car && (s==Nil? x!=At && firstChar(x)=='@' : memq(x,s)!=null)? x.Car : null;
    747       if (x.Car == Up) {
    748          x = x.Cdr;
    749          if (!((y = x.Car.eval()) instanceof Cell))
    750             return (z = fill(x.Cdr, s)) == null? x.Cdr : z;
    751          Any w = y;
    752          while (y.Cdr instanceof Cell)
    753             y = y.Cdr;
    754          y.Cdr = (z = fill(x.Cdr, s)) == null? x.Cdr : z;
    755          return w;
    756       }
    757       if ((y = fill(x.Car, s)) != null) {
    758          z = fill(x.Cdr, s);
    759          return new Cell(y, z == null? x.Cdr : z);
    760       }
    761       if ((y = fill(x.Cdr, s)) != null)
    762          return new Cell(x.Car, y);
    763       return null;
    764    }
    765 
    766    final static boolean isBlank(Any x) {
    767       if (x != Nil) {
    768          if (!(x instanceof Symbol))
    769             return false;
    770          String s = x.name();
    771          if (s != null)
    772             for (int i = 0; i < s.length(); ++i)
    773                if (s.charAt(i) > ' ')
    774                   return false;
    775       }
    776       return true;
    777    }
    778 
    779    final static Any funq(Any x) {
    780       Any y;
    781       if (x == Nil || x instanceof Symbol)
    782          return Nil;
    783       if (x instanceof Number)
    784          return ((Number)x).Big == null && ((Number)x).Cnt <= MaxFun? x : Nil;
    785       for (y = x.Cdr; y instanceof Cell; y = y.Cdr) {
    786          if (y == x)
    787             return Nil;
    788          if (y.Car instanceof Cell) {
    789             if (y.Car.Car instanceof Number) {
    790                if (y.Cdr instanceof Cell)
    791                   return Nil;
    792             }
    793             else if (y.Car.Car == Nil || y.Car.Car == T)
    794                return Nil;
    795          }
    796          else if (y.Cdr != Nil)
    797             return Nil;
    798       }
    799       if (y != Nil)
    800          return Nil;
    801       if ((x = x.Car) == Nil)
    802          return T;
    803       for (y = x; y instanceof Cell;)
    804          if (y.Car instanceof Number || y.Car instanceof Cell || y.Car == Nil || y.Car == T || x == (y = y.Cdr))
    805             return Nil;
    806       return y instanceof Number || y == T? Nil : x;
    807    }
    808 
    809    final static Any trim(Any x) {
    810       Any y;
    811       if (!(x instanceof Cell))
    812          return x;
    813       if ((y = trim(x.Cdr)) == Nil && isBlank(x.Car))
    814          return Nil;
    815       return new Cell(x.Car, y);
    816    }
    817 
    818    final static Any nCdr(int n, Any x) {
    819       while (--n >= 0)
    820          x = x.Cdr;
    821       return x;
    822    }
    823 
    824    final static Any nth(int n, Any x) {
    825       if (--n < 0)
    826          return Nil;
    827       return nCdr(n,x);
    828    }
    829 
    830    final static Any sort(Any ex, Any lst, Any foo) {
    831       Any x = lst, l = Nil, r = Nil, c = Nil;
    832       do {
    833          int i = foo == Nil? lst.Car.compare(x.Car) : foo.apply(ex, false, new Any[] {x.Car, lst.Car}, 2) == Nil? -1 : 1;
    834          if (i > 0)
    835             l = new Cell(x.Car, l);
    836          else if (i < 0)
    837             r = new Cell(x.Car, r);
    838          else
    839             c = new Cell(x.Car, c);
    840       } while ((x = x.Cdr) instanceof Cell);
    841       if ((lst = l) instanceof Cell) {
    842          if (l.Cdr instanceof Cell)
    843             for (lst = l = sort(ex, l, foo); (l = l.Cdr).Cdr instanceof Cell;);
    844          if (c instanceof Cell)
    845             for (l.Cdr = c; (l = l.Cdr).Cdr instanceof Cell;);
    846       }
    847       else if ((lst = c) instanceof Cell)
    848          for (l = c; l.Cdr instanceof Cell; l = l.Cdr);
    849       else
    850          return sort(ex, r, foo);
    851       if (r instanceof Cell)
    852          l.Cdr = r.Cdr instanceof Cell? sort(ex, r, foo) : r;
    853       return lst;
    854    }
    855 
    856    final static Any consIdx(Any x, Any y) {
    857       if (x.Cdr.Cdr instanceof Cell)
    858          y = consIdx(x.Cdr.Cdr, y);
    859       y = new Cell(x.Car, y);
    860       return x.Cdr.Car instanceof Cell? consIdx(x.Cdr.Car, y) : y;
    861    }
    862 
    863    final static Any idx(Any var, Any key, int flg) {
    864       Any x, y, z, p;
    865       boolean ad;
    866       int i;
    867       if (key == null)
    868          return var.Car instanceof Cell? consIdx(var.Car, Nil) : Nil;
    869       if (!((x = var.Car) instanceof Cell)) {
    870          if (flg > 0)
    871             var.Car = new Cell(key, Nil);
    872          return Nil;
    873       }
    874       p = var;
    875       ad = true;
    876       for (;;) {
    877          if ((i = key.compare(x.Car)) == 0) {
    878             if (flg < 0) {
    879                if (!(x.Cdr.Car instanceof Cell)) {
    880                   if (ad)
    881                      p.Car = x.Cdr.Cdr;
    882                   else
    883                      p.Cdr = x.Cdr.Cdr;
    884                }
    885                else if (!((y = x.Cdr.Cdr) instanceof Cell)) {
    886                   if (ad)
    887                      p.Car = x.Cdr.Car;
    888                   else
    889                      p.Cdr = x.Cdr.Car;
    890                }
    891                else if (!((z = y.Cdr.Car) instanceof Cell)) {
    892                   x.Car = y.Car;
    893                   x.Cdr.Cdr = y.Cdr.Cdr;
    894                }
    895                else {
    896                   while (z.Cdr.Car instanceof Cell)
    897                      z = (y = z).Cdr.Car;
    898                   x.Car = z.Car;
    899                   y.Cdr.Car = z.Cdr.Cdr;
    900                }
    901             }
    902             return x;
    903          }
    904          if (!(x.Cdr instanceof Cell)) {
    905             if (flg > 0)
    906                x.Cdr = i < 0? new Cell(new Cell(key, Nil), Nil) : new Cell(Nil, new Cell(key, Nil));
    907             return Nil;
    908          }
    909          if (i < 0) {
    910             if (!(x.Cdr.Car instanceof Cell)) {
    911                if (flg > 0)
    912                   x.Cdr.Car = new Cell(key, Nil);
    913                return Nil;
    914             }
    915             p = x.Cdr;  ad = true;
    916             x = p.Car;
    917          }
    918          else {
    919             if (!(x.Cdr.Cdr instanceof Cell)) {
    920                if (flg > 0)
    921                   x.Cdr.Cdr = new Cell(key, Nil);
    922                return Nil;
    923             }
    924             p = x.Cdr;  ad = false;
    925             x = p.Cdr;
    926          }
    927       }
    928    }
    929 
    930    final static Any consLup(Any x, Any y, Any from, Any to) {
    931       if (x instanceof Cell) {
    932          if (x.Car == T)
    933             return consLup(x.Cdr.Car, y, from, to);
    934          if (!(x.Car instanceof Cell))
    935             return consLup(x.Cdr.Cdr, y, from, to);
    936          if (to.compare(x.Car.Car) >= 0) {
    937             y = consLup(x.Cdr.Cdr, y, from, to);
    938             if (from.compare(x.Car.Car) <= 0) {
    939                y = new Cell(x.Car, y);
    940                return consLup(x.Cdr.Car, y, from, to);
    941             }
    942          }
    943          if (from.compare(x.Car.Car) <= 0)
    944             return consLup(x.Cdr.Car, y, from, to);
    945       }
    946       return y;
    947    }
    948 
    949    final static Any member(Any x, Any y) {
    950       Any z = y;
    951 
    952       while (y instanceof Cell) {
    953          if (x.equal(y.Car))
    954             return y;
    955          if (z == (y = y.Cdr))
    956             return null;
    957       }
    958       return y == Nil || !x.equal(y)? null : y;
    959    }
    960 
    961    final static Any memq(Any x, Any y) {
    962       Any z = y;
    963 
    964       while (y instanceof Cell) {
    965          if (x == y.Car)
    966             return y;
    967          if (z == (y = y.Cdr))
    968             return null;
    969       }
    970       return y == Nil || x != y? null : y;
    971    }
    972 
    973    final static int indx(Any x, Any y) {
    974       int i = 1;
    975       Any z = y;
    976 
    977       while (y instanceof Cell) {
    978          if (x.equal(y.Car))
    979             return i;
    980          ++i;
    981          if (z == (y = y.Cdr))
    982             return 0;
    983       }
    984       return 0;
    985    }
    986 
    987    final static boolean match(Any p, Any d) {
    988       Any x;
    989       for (;;) {
    990          if (!(p instanceof Cell)) {
    991             if (p instanceof Symbol  &&  firstChar(p) == '@') {
    992                p.Car = d;
    993                return true;
    994             }
    995             return p.equal(d);
    996          }
    997          if ((x = p.Car) instanceof Symbol  &&  firstChar(x) == '@') {
    998             if (!(d instanceof Cell)) {
    999                if (d.equal(p.Cdr)) {
   1000                   x.Car = Nil;
   1001                   return true;
   1002                }
   1003                return false;
   1004             }
   1005             if (match(p.Cdr, d.Cdr)) {
   1006                x.Car = new Cell(d.Car, Nil);
   1007                return true;
   1008             }
   1009             if (match(p.Cdr, d)) {
   1010                x.Car = Nil;
   1011                return true;
   1012             }
   1013             if (match(p, d.Cdr)) {
   1014                x.Car = new Cell(d.Car, x.Car);
   1015                return true;
   1016             }
   1017          }
   1018          if (!(d instanceof Cell) || !match(x, d.Car))
   1019             return false;
   1020          p = p.Cdr;
   1021          d = d.Cdr;
   1022       }
   1023    }
   1024 
   1025    final static boolean unify(Number n1, Any x1, Number n2, Any x2) {
   1026       lookup1:
   1027       while (x1 instanceof Symbol  &&  firstChar(x1) == '@') {
   1028          for (Any x = Penv;  x.Car instanceof Cell;  x = x.Cdr)
   1029             if (n1.Cnt == ((Number)x.Car.Car.Car).Cnt  &&  x1 == x.Car.Car.Cdr) {
   1030                n1 = (Number)x.Car.Cdr.Car;
   1031                x1 = x.Car.Cdr.Cdr;
   1032                continue lookup1;
   1033             }
   1034          break;
   1035       }
   1036       lookup2:
   1037       while (x2 instanceof Symbol  &&  firstChar(x2) == '@') {
   1038          for (Any x = Penv;  x.Car instanceof Cell;  x = x.Cdr)
   1039             if (n2.Cnt == ((Number)x.Car.Car.Car).Cnt  &&  x2 == x.Car.Car.Cdr) {
   1040                n2 = (Number)x.Car.Cdr.Car;
   1041                x2 = x.Car.Cdr.Cdr;
   1042                continue lookup2;
   1043             }
   1044          break;
   1045       }
   1046       if (n1.Cnt == n2.Cnt  &&  x1.equal(x2))
   1047          return true;
   1048       if (x1 instanceof Symbol  &&  firstChar(x1) == '@') {
   1049          if (x1 != At) {
   1050             Penv = new Cell(new Cell(new Cell(n1,x1), Nil), Penv);
   1051             Penv.Car.Cdr = new Cell(n2,x2);
   1052          }
   1053          return true;
   1054       }
   1055       if (x2 instanceof Symbol  &&  firstChar(x2) == '@') {
   1056          if (x2 != At) {
   1057             Penv = new Cell(new Cell(new Cell(n2,x2), Nil), Penv);
   1058             Penv.Car.Cdr = new Cell(n1,x1);
   1059          }
   1060          return true;
   1061       }
   1062       if (!(x1 instanceof Cell) || !(x2 instanceof Cell))
   1063          return x1.equal(x2);
   1064       Any env = Penv;
   1065       if (unify(n1, x1.Car, n2, x2.Car)  &&  unify(n1, x1.Cdr, n2, x2.Cdr))
   1066          return true;
   1067       Penv = env;
   1068       return false;
   1069    }
   1070 
   1071    final static Any lup(Number n, Any x) {
   1072       lup:
   1073       while (x instanceof Symbol  &&  firstChar(x) == '@') {
   1074          for (Any y = Penv;  y.Car instanceof Cell;  y = y.Cdr)
   1075             if (n.Cnt == ((Number)y.Car.Car.Car).Cnt  &&  x == y.Car.Car.Cdr) {
   1076                n = (Number)y.Car.Cdr.Car;
   1077                x = y.Car.Cdr.Cdr;
   1078                continue lup;
   1079             }
   1080          break;
   1081       }
   1082       return x instanceof Cell? new Cell(lup(n, x.Car), lup(n, x.Cdr)) : x;
   1083    }
   1084 
   1085    final static Any lookup(Number n, Any x) {
   1086       return (x = lup(n,x)) instanceof Symbol && firstChar(x) == '@'?  Nil : x;
   1087    }
   1088 
   1089    final static Any uniFill(Any x) {
   1090       if (x instanceof Number)
   1091          return x;
   1092       if (x instanceof Symbol)
   1093          return lup((Number)Pnl.Car, x);
   1094       return new Cell(uniFill(x.Car), uniFill(x.Cdr));
   1095    }
   1096 
   1097    final static Any evRun(boolean ev, Any x, int cnt, Any lst) {
   1098       int i, j = cnt, n = 0;
   1099       Bind b, bnd = Env.Bind;
   1100       Any s, y, z;
   1101       do {
   1102          ++n;
   1103          i = bnd.Eswp;
   1104          bnd.Eswp -= cnt;
   1105          if (i == 0) {
   1106             for (i = 0; i < bnd.Cnt; i+= 2) {
   1107                s = bnd.Data[i+1];
   1108                y = s.Car;
   1109                s.Car = bnd.Data[i];
   1110                bnd.Data[i] = y;
   1111             }
   1112             if (bnd.Data[1] == At && --j == 0)
   1113                break;
   1114          }
   1115       } while ((bnd = bnd.Link) != null);
   1116       if (!(lst instanceof Cell))
   1117          z = ev? x.eval() : x.run();
   1118       else {
   1119          bnd = new Bind();
   1120          do {
   1121             s = lst.Car;
   1122             bnd.add(s.Car);
   1123             bnd.add(s);
   1124          exclude:
   1125             for (b = Env.Bind, j = n; ;) {
   1126                for (i = 0; i < b.Cnt; i+= 2)
   1127                   if (s == b.Data[i+1]) {
   1128                      s.Car = b.Data[i];
   1129                      break exclude;
   1130                   }
   1131                if (--j == 0 || (b = b.Link) == null)
   1132                   break;
   1133             }
   1134          } while ((lst = lst.Cdr) instanceof Cell);
   1135          Env.Bind = bnd;
   1136          z = ev? x.eval() : x.run();
   1137          for (i = bnd.Cnt; (i -= 2) >= 0;)
   1138             bnd.Data[i+1].Car = bnd.Data[i];
   1139          Env.Bind = bnd.Link;
   1140       }
   1141       do {
   1142          for (bnd = Env.Bind, i = n; --i != 0; bnd = bnd.Link);
   1143          if ((bnd.Eswp += cnt) == 0)
   1144             for (i = bnd.Cnt; (i -= 2) >= 0;) {
   1145                s = bnd.Data[i+1];
   1146                y = s.Car;
   1147                s.Car = bnd.Data[i];
   1148                bnd.Data[i] = y;
   1149             }
   1150       } while (--n > 0);
   1151       return z;
   1152    }
   1153 
   1154    final static Any evMethod(Any o, Any ex, Any x) {
   1155       int i;
   1156       Any y = ex.Car;
   1157       Any cls = TheCls,  key = TheKey;
   1158       Bind bnd = new Bind();  bnd.add(At.Car);  bnd.add(At);
   1159       while (y instanceof Cell) {
   1160          bnd.add(x.Car.eval());  // Save new value
   1161          bnd.add(y.Car);  // and symbol
   1162          x = x.Cdr;
   1163          y = y.Cdr;
   1164       }
   1165       if (y == Nil || y != At) {
   1166          i = bnd.Cnt;
   1167          if (y != Nil) {
   1168             bnd.add(y.Car);  // Save old value
   1169             bnd.add(y);  // and symbol
   1170             y.Car = x;  // Set new value
   1171          }
   1172          do {
   1173             y = bnd.Data[--i];
   1174             x = y.Car;
   1175             y.Car = bnd.Data[--i];  // Set new value
   1176             bnd.Data[i] = x;  // Save old value
   1177          } while (i > 0);
   1178          bnd.add(This.Car);
   1179          bnd.add(This);
   1180          This.Car = o;
   1181          Env.Bind = bnd;
   1182          y = cls;  cls = Env.Cls;  Env.Cls = y;
   1183          y = key;  key = Env.Key;  Env.Key = y;
   1184          x = ex.Cdr.prog();
   1185       }
   1186       else {
   1187          int next, argc, j = 0;
   1188          Any arg, args[], av[] = null;
   1189          if (x instanceof Cell) {
   1190             av = new Any[6];
   1191             do
   1192                av = append(av, j++, x.Car.eval());
   1193             while ((x = x.Cdr) instanceof Cell);
   1194          }
   1195          next = Env.Next;  Env.Next = 0;
   1196          argc = Env.ArgC;  Env.ArgC = j;
   1197          arg = Env.Arg;    Env.Arg = Nil;
   1198          args = Env.Args;  Env.Args = av;
   1199          i = bnd.Cnt;
   1200          do {
   1201             y = bnd.Data[--i];
   1202             x = y.Car;
   1203             y.Car = bnd.Data[--i];  // Set new value
   1204             bnd.Data[i] = x;  // Save old value
   1205          } while (i > 0);
   1206          bnd.add(This.Car);
   1207          bnd.add(This);
   1208          This.Car = o;
   1209          Env.Bind = bnd;
   1210          y = cls;  cls = Env.Cls;  Env.Cls = y;
   1211          y = key;  key = Env.Key;  Env.Key = y;
   1212          x = ex.Cdr.prog();
   1213          Env.Args = args;
   1214          Env.Arg = arg;
   1215          Env.ArgC = argc;
   1216          Env.Next = next;
   1217       }
   1218       for (i = bnd.Cnt; (i -= 2) >= 0;)
   1219          bnd.Data[i+1].Car = bnd.Data[i];
   1220       Env.Bind = bnd.Link;
   1221       Env.Cls = cls;  Env.Key = key;
   1222       return x;
   1223    }
   1224 
   1225    final static Any method(Any x) {
   1226       Any y, z;
   1227       if ((y = x.Car) instanceof Cell) {
   1228          while ((z = y.Car) instanceof Cell) {
   1229             if (z.Car == TheKey)
   1230                return z.Cdr;
   1231             if (!((y = y.Cdr) instanceof Cell))
   1232                return null;
   1233          }
   1234          do
   1235             if ((x = method((TheCls = y).Car)) != null)
   1236                return x;
   1237          while ((y = y.Cdr) instanceof Cell);
   1238       }
   1239       return null;
   1240    }
   1241 
   1242    final static Any extra(Any x) {
   1243       Any y;
   1244       for (x = x.Car; x.Car instanceof Cell; x = x.Cdr);
   1245       while (x instanceof Cell) {
   1246          if (x == Env.Cls  ||  (y = extra(x.Car)) == null) {
   1247             while ((x = x.Cdr) instanceof Cell)
   1248                if ((y = method((TheCls = x).Car)) != null)
   1249                   return y;
   1250             return null;
   1251          }
   1252          if (y != null  &&  y != T)
   1253             return y;
   1254          x = x.Cdr;
   1255       }
   1256       return T;
   1257    }
   1258 
   1259    final static Any loop(Any x) {
   1260       Any a, y, z;
   1261       for (;;) {
   1262          y = x;
   1263          do {
   1264             if ((z = y.Car) instanceof Cell) {
   1265                if (z.Car == Nil) {
   1266                   if ((a = (z = z.Cdr).Car.eval()) == Nil)
   1267                      return z.Cdr.prog();
   1268                   At.Car = a;
   1269                }
   1270                else if (z.Car == T) {
   1271                   if ((a = (z = z.Cdr).Car.eval()) != Nil) {
   1272                      At.Car = a;
   1273                      return z.Cdr.prog();
   1274                   }
   1275                }
   1276                else
   1277                   z.eval();
   1278             }
   1279          } while ((y = y.Cdr) instanceof Cell);
   1280       }
   1281    }
   1282 
   1283    /* Ersatz PicoLisp Reader */
   1284    final static class InFrame {
   1285       InFrame Link;
   1286       PicoLispReader Rd;
   1287       int Pid;
   1288 
   1289       InFrame(PicoLispReader rd, int pid) {
   1290          Link = Env.InFrames;
   1291          Rd = rd;
   1292          Pid = pid;
   1293       }
   1294    }
   1295 
   1296    final static class PicoLispReader {
   1297       Reader Rd;
   1298       String Name;
   1299       char Eof1, Eof2;
   1300       int Fd, Chr, Src, Ops;
   1301       InputStream Stream;
   1302       SelectableChannel Chan;
   1303       SelectionKey Key;
   1304 
   1305       PicoLispReader(Reader rd, String nm, int fd, SelectableChannel chan, int ops) {
   1306          Rd = rd;
   1307          Name = nm;
   1308          InFiles[Fd = fd] = this;
   1309          Chan = chan;
   1310          Ops = ops;
   1311       }
   1312 
   1313       PicoLispReader(InputStream in, int fd, SelectableChannel chan, int ops) {
   1314          this(in == null? null : new InputStreamReader(in), null, fd, chan, ops);
   1315          Stream = in;
   1316       }
   1317 
   1318       PicoLispReader(String s, char eof1, char eof2) {
   1319          Rd = new StringReader(s);
   1320          Eof1 = eof1;
   1321          Eof2 = eof2;
   1322       }
   1323 
   1324       final boolean register(Selector sel) {
   1325          if (Ops != 0) {
   1326             try {
   1327                Chan.configureBlocking(false);
   1328                Key = Chan.register(sel, Ops);
   1329                return true;
   1330             }
   1331             catch (IOException e) {}
   1332          }
   1333          return false;
   1334       }
   1335 
   1336       final boolean ready(Selector sel) throws IOException {
   1337          if (Key == null)
   1338             return Rd != null && Rd.ready() || Stream != null && Stream.available() > 0;
   1339          boolean rdy = (Key.readyOps() & Ops) != 0;
   1340          Key.cancel();
   1341          Key = null;
   1342          try{Chan.configureBlocking(true);}
   1343          catch (IOException e) {}
   1344          return rdy;
   1345       }
   1346 
   1347       final void close() {
   1348          try {
   1349             if (Chan != null)
   1350                Chan.close();
   1351             if (Rd != null)
   1352                Rd.close();
   1353             InFiles[Fd] = null;
   1354          }
   1355          catch (IOException e) {closeErr(e);}
   1356       }
   1357 
   1358       final void eofErr() {err(null, null, "EOF Overrun");}
   1359       final void badInput() {err(null, null, "Bad input '" + (char)Chr + "'");}
   1360 
   1361       final int get() {
   1362          try {
   1363             if (this != StdIn || Term == null)
   1364                Chr = Rd.read();
   1365             else {
   1366                while (Line.length() == 0) {
   1367                   waitFd(null, 0, -1);
   1368                   ((Pipe.SourceChannel)StdIn.Chan).read(ByteBuffer.allocate(1));
   1369                }
   1370                Chr = Line.charAt(0);
   1371                Line.deleteCharAt(0);
   1372             }
   1373             if (Chr < 0) {
   1374                if ((Chr = Eof1) != 0)
   1375                   Eof1 = '\0';
   1376                else if ((Chr = Eof2) != 0)
   1377                   Eof2 = '\0';
   1378                else
   1379                   Chr = -1;
   1380             }
   1381             return Chr;
   1382          }
   1383          catch (IOException e) {return Chr = -1;}
   1384       }
   1385 
   1386       final boolean eol() {
   1387          if (Chr < 0)
   1388             return true;
   1389          if (Chr == '\n') {
   1390             Chr = 0;
   1391             return true;
   1392          }
   1393          if (Chr == '\r') {
   1394             get();
   1395             if (Chr == '\n')
   1396                Chr = 0;
   1397             return true;
   1398          }
   1399          return false;
   1400       }
   1401 
   1402       final int skipc(int c) {
   1403          if (Chr < 0)
   1404             return Chr;
   1405          for (;;) {
   1406             while (Chr <= ' ') {
   1407                get();
   1408                if (Chr < 0)
   1409                   return Chr;
   1410             }
   1411             if (Chr != c)
   1412                return Chr;
   1413             get();
   1414             while (Chr != '\n') {
   1415                if (Chr < 0)
   1416                   return Chr;
   1417                get();
   1418             }
   1419          }
   1420       }
   1421 
   1422       final void comment() {
   1423          get();
   1424          if (Chr != '{') {
   1425             while (Chr != '\n') {
   1426                if (Chr < 0)
   1427                   return;
   1428                get();
   1429             }
   1430          }
   1431          else {
   1432             for (;;) {
   1433                get();
   1434                if (Chr < 0)
   1435                   return;
   1436                if (Chr == '}' && (get() == '#'))
   1437                   break;
   1438             }
   1439             get();
   1440          }
   1441       }
   1442 
   1443       final int skip() {
   1444          for (;;) {
   1445             if (Chr < 0)
   1446                return Chr;
   1447             while (Chr <= ' ') {
   1448                get();
   1449                if (Chr < 0)
   1450                   return Chr;
   1451             }
   1452             if (Chr != '#')
   1453                return Chr;
   1454             comment();
   1455          }
   1456       }
   1457 
   1458       final boolean testEsc() {
   1459          for (;;) {
   1460             if (Chr < 0)
   1461                return false;
   1462             if (Chr == '^') {
   1463                get();
   1464                if (Chr == '@')
   1465                   badInput();
   1466                if (Chr == '?')
   1467                   Chr = 127;
   1468                else
   1469                   Chr &= 0x1F;
   1470                return true;
   1471             }
   1472             if (Chr != '\\')
   1473                return true;
   1474             if (get() != '\n')
   1475                return true;
   1476             do
   1477                get();
   1478             while (Chr == ' ' || Chr == '\t');
   1479          }
   1480       }
   1481 
   1482       final Any rdAtom(int c) {
   1483          Namespace table = Env.intern();
   1484          StringBuilder sb = new StringBuilder();
   1485          sb.append((char)c);
   1486          while (Chr > 0) {
   1487             if (Chr == '~') {
   1488                Symbol s = mkSymbol(null, sb.toString(), table);
   1489                if (!(((Symbol)s.Car).Obj instanceof Namespace))
   1490                   symNsError(null, s);
   1491                table = (Namespace)((Symbol)s.Car).Obj;
   1492                sb = new StringBuilder();
   1493             }
   1494             else {
   1495                if (Delim.indexOf(Chr) >= 0)
   1496                   break;
   1497                if (Chr == '\\')
   1498                   get();
   1499                sb.append((char)Chr);
   1500             }
   1501             get();
   1502          }
   1503          String s = sb.toString();
   1504          if (s.equals("NIL"))
   1505             return Nil;
   1506          try {return strToNum(s, ((Number)Scl.Car).Cnt);}
   1507          catch (NumberFormatException e) {return mkSymbol(Nil, s, table);}
   1508       }
   1509 
   1510       final Any rdList() {
   1511          Any x, res;
   1512          get();
   1513          for (;;) {
   1514             if (skip() == ')') {
   1515                get();
   1516                return Nil;
   1517             }
   1518             if (Chr == ']')
   1519                return Nil;
   1520             if (Chr != '~') {
   1521                res = x = new Cell(read0(false), Nil);
   1522                break;
   1523             }
   1524             get();
   1525             if ((res = x = read0(false).eval()) instanceof Cell) {
   1526                while (x.Cdr instanceof Cell)
   1527                   x = x.Cdr;
   1528                break;
   1529             }
   1530          }
   1531          for (;;) {
   1532             if (skip() == ')') {
   1533                get();
   1534                break;
   1535             }
   1536             if (Chr == ']')
   1537                break;
   1538             if (Chr == '.') {
   1539                get();
   1540                if (Delim.indexOf(Chr) >= 0) {
   1541                   x.Cdr = skip()==')' || Chr==']'? res : read0(false);
   1542                   if (skip() == ')')
   1543                      get();
   1544                   else if (Chr != ']')
   1545                      err(null, x, "Bad dotted pair");
   1546                   break;
   1547                }
   1548                x = x.Cdr = new Cell(rdAtom('.'), Nil);
   1549             }
   1550             else if (Chr != '~')
   1551                x = x.Cdr = new Cell(read0(false), Nil);
   1552             else {
   1553                get();
   1554                x.Cdr = read0(false).eval();
   1555                while (x.Cdr instanceof Cell)
   1556                   x = x.Cdr;
   1557             }
   1558          }
   1559          return res;
   1560       }
   1561 
   1562       final Any read0(boolean top) {
   1563          Any x, y;
   1564          if (skip() < 0) {
   1565             if (top)
   1566                return Nil;
   1567             eofErr();
   1568          }
   1569          if (top && Rd instanceof LineNumberReader)
   1570             Src = ((LineNumberReader)Rd).getLineNumber() + 1;
   1571          if (Chr == '(') {
   1572             x = rdList();
   1573             if (top  &&  Chr == ']')
   1574                get();
   1575             return x;
   1576          }
   1577          if (Chr == '[') {
   1578             x = rdList();
   1579             if (Chr != ']')
   1580                err(null, x, "Super parentheses mismatch");
   1581             get();
   1582             return x;
   1583          }
   1584          if (Chr == '\'') {
   1585             get();
   1586             return new Cell(Quote, read0(top));
   1587          }
   1588          if (Chr == ',') {
   1589             get();
   1590             x = read0(top);
   1591             if (Uni.Car != T)
   1592                x = (y = idx(Uni, x, 1)) instanceof Cell? y.Car : x;
   1593             return x;
   1594          }
   1595          if (Chr == '`') {
   1596             get();
   1597             return read0(top).eval();
   1598          }
   1599          if (Chr == '"') {
   1600             get();
   1601             if (Chr == '"') {
   1602                get();
   1603                return Nil;
   1604             }
   1605             if (!testEsc())
   1606                eofErr();
   1607             StringBuilder sb = new StringBuilder();
   1608             sb.append((char)Chr);
   1609             while (get() != '"') {
   1610                if (!testEsc())
   1611                   eofErr();
   1612                sb.append((char)Chr);
   1613             }
   1614             get();
   1615             return mkSymbol(null, sb.toString(), Transient);
   1616          }
   1617          if (Chr == ')' || Chr == ']' || Chr == '~')
   1618             badInput();
   1619          if (Chr == '\\')
   1620             get();
   1621          int i = Chr;
   1622          get();
   1623          return rdAtom(i);
   1624       }
   1625 
   1626       final Any read(int end) {
   1627          if (Chr == 0)
   1628             get();
   1629          if (Chr == end)
   1630             return Nil;
   1631          return read0(true);
   1632       }
   1633 
   1634       final Any token(Any x, char c) {
   1635          if (Chr == 0)
   1636             get();
   1637          if (skipc(c) < 0)
   1638             return null;
   1639          if (Chr == '"') {
   1640             get();
   1641             if (Chr == '"') {
   1642                get();
   1643                return Nil;
   1644             }
   1645             if (!testEsc())
   1646                return Nil;
   1647             Any y = x = new Cell(mkChar(Chr), Nil);
   1648             while (get() != '"' && testEsc())
   1649                y = y.Cdr = new Cell(mkChar(Chr), Nil);
   1650             get();
   1651             return x;
   1652          }
   1653          if (Chr >= '0' && Chr <= '9') {
   1654             StringBuilder sb = new StringBuilder();
   1655             sb.append((char)Chr);
   1656             while (get() >= '0' && Chr <= '9' || Chr == '.')
   1657                sb.append((char)Chr);
   1658             try {return strToNum(sb.toString(), ((Number)Scl.Car).Cnt);}
   1659             catch (NumberFormatException e) {}
   1660          }
   1661          if (Chr != '+' && Chr != '-') {
   1662             String s = x.name();
   1663             if (Chr >= 'A' && Chr <= 'Z' || Chr == '\\' || Chr >= 'a' && Chr <= 'z' || s.indexOf(Chr) >= 0) {
   1664                if (Chr == '\\')
   1665                   get();
   1666                StringBuilder sb = new StringBuilder();
   1667                sb.append((char)Chr);
   1668                while (get() >= '0' && Chr <= '9' || Chr >= 'A' && Chr <= 'Z' || Chr == '\\' || Chr >= 'a' && Chr <= 'z' || s.indexOf(Chr) >= 0) {
   1669                   if (Chr == '\\')
   1670                      get();
   1671                   sb.append((char)Chr);
   1672                }
   1673                s = sb.toString();
   1674                return s.equals("NIL")? Nil : mkSymbol(Nil, s, Env.intern());
   1675             }
   1676          }
   1677          c = (char)Chr;
   1678          get();
   1679          return mkChar(c);
   1680       }
   1681    }
   1682 
   1683    /* Ersatz PicoLisp Printer */
   1684    final static class OutFrame {
   1685       OutFrame Link;
   1686       PicoLispWriter Wr;
   1687       int Pid;
   1688 
   1689       OutFrame(PicoLispWriter wr, int pid) {
   1690          Link = Env.OutFrames;
   1691          Wr = wr;
   1692          Pid = pid;
   1693       }
   1694    }
   1695 
   1696    final static class PicoLispWriter {
   1697       PrintWriter Wr;
   1698       String Name;
   1699       int Fd;
   1700 
   1701       PicoLispWriter(PrintWriter wr, String nm, int fd) {
   1702          Wr = wr;
   1703          Name = nm;
   1704          OutFiles[Fd = fd] = this;
   1705       }
   1706 
   1707       PicoLispWriter(OutputStream out, int fd) {
   1708          this(new PrintWriter(out), null, fd);
   1709       }
   1710 
   1711       final void close() {
   1712          Wr.close();
   1713          OutFiles[Fd] = null;
   1714       }
   1715 
   1716       final void print(Any x) {Wr.print(x.toString());}
   1717       final void space() {Wr.print(' ');}
   1718 
   1719       final void newline() {
   1720          Wr.println();
   1721          Wr.flush();
   1722       }
   1723    }
   1724 
   1725    /* Ersatz PicoLisp VM */
   1726    final static class Bind {
   1727       Bind Link;
   1728       Any[] Data;
   1729       int Cnt, Eswp;
   1730 
   1731       Bind() {
   1732          Link = Env.Bind;
   1733          Data = new Any[12];
   1734       }
   1735 
   1736       final void add(Any x) {Data = append(Data, Cnt++, x);}
   1737    }
   1738 
   1739    final static class Env {
   1740       int Next, ArgC, Trace;
   1741       Bind Bind;
   1742       Symbol Intern;
   1743       Any Arg, Args[], Cls, Key, Task, Make, Yoke;
   1744       InFrame InFrames;
   1745       OutFrame OutFrames;
   1746 
   1747       Env() {Intern = pico;}
   1748 
   1749       Env(Env env) {
   1750          Next = env.Next;  ArgC = env.ArgC;  Trace = env.Trace;
   1751          Bind = env.Bind;
   1752          Intern = env.Intern;
   1753          Arg = env.Arg;  Args = env.Args;
   1754          Cls = env.Cls;  Key = env.Key;
   1755          Task = env.Task;
   1756          Make = env.Make;  Yoke = env.Yoke;
   1757          InFrames = env.InFrames;  OutFrames = env.OutFrames;
   1758       }
   1759 
   1760       final Namespace intern() {
   1761          return (Namespace)((Symbol)Intern.Car).Obj;
   1762       }
   1763 
   1764       final void pushInFile(InFrame in) {
   1765          InFrames = in;
   1766          InFile = InFiles[in.Rd.Fd];
   1767       }
   1768 
   1769       final void popInFiles() {
   1770          if (InFrames.Pid != 0) {
   1771             InFile.close();
   1772             if (InFrames.Pid > 1) {
   1773                try {
   1774                   Pids[InFrames.Pid].waitFor();
   1775                   Pids[InFrames.Pid] = null;
   1776                }
   1777                catch (InterruptedException e) {}  //#! sighandler()
   1778             }
   1779          }
   1780          InFile = (InFrames = InFrames.Link) == null? StdIn : InFiles[InFrames.Rd.Fd];
   1781       }
   1782 
   1783       final void pushOutFile(OutFrame out) {
   1784          OutFrames = out;
   1785          OutFile = OutFiles[out.Wr.Fd];
   1786       }
   1787 
   1788       final void popOutFiles() {
   1789          if (OutFrames.Pid != 0) {
   1790             OutFile.close();
   1791             if (OutFrames.Pid > 1) {
   1792                try {
   1793                   Pids[OutFrames.Pid].waitFor();
   1794                   Pids[OutFrames.Pid] = null;
   1795                }
   1796                catch (InterruptedException e) {}  //#! sighandler()
   1797             }
   1798          }
   1799          OutFile = (OutFrames = OutFrames.Link) == null? StdOut : OutFiles[OutFrames.Wr.Fd];
   1800       }
   1801    }
   1802 
   1803    final static class Catch {
   1804       Catch Link;
   1805       Any Tag, Fin;
   1806       Env Env;
   1807 
   1808       Catch(Any tag, Any fin, Env env) {
   1809          Tag = tag;
   1810          Fin = fin;
   1811          Env = new Env(env);
   1812          Link = Catch;  Catch = this;
   1813       }
   1814    }
   1815 
   1816    final static class Control extends RuntimeException {
   1817       Any Tag, Val;
   1818 
   1819       Control() {}
   1820 
   1821       Control(Any ex, Any tag, Any val) {
   1822          Tag = tag;
   1823          Val = val;
   1824          for (Catch p = Catch; p != null; p = p.Link)
   1825             if (p.Tag == T  ||  p.Tag == tag) {
   1826                unwind(p);
   1827                return;
   1828             }
   1829          err(ex, tag, "Tag not found");
   1830       }
   1831    }
   1832 
   1833    final static class Namespace extends HashMap<String,Symbol> {
   1834       final void copy(Namespace table) {
   1835          for (Iterator<Symbol> it = values().iterator(); it.hasNext();) {
   1836             Symbol sym = it.next();
   1837             if (table.get(sym.Name) == null)
   1838                table.put(sym.Name, sym);
   1839          }
   1840       }
   1841    }
   1842 
   1843    static abstract class Any {
   1844       Any Car, Cdr;
   1845 
   1846       abstract Any put(Any key, Any val);
   1847       abstract Any get(Any key);
   1848       abstract Any prop(Any key);
   1849       abstract Any putl(Any lst);
   1850       abstract Any getl();
   1851       abstract Any eval();
   1852       abstract Any prog();
   1853       abstract Any run();
   1854       abstract Any call(Any ex);
   1855       abstract Any func(Any ex);
   1856       abstract Any apply(Any ex, boolean cf, Any[] v, int n);
   1857       abstract boolean equal(Any x);
   1858       abstract int compare(Any x);
   1859       abstract long length();
   1860       abstract long size();
   1861       abstract InFrame rdOpen(Any ex);
   1862       abstract OutFrame wrOpen(Any ex);
   1863       abstract String name();
   1864    }
   1865 
   1866    final static class Number extends Any {
   1867       int Cnt;
   1868       BigInteger Big;
   1869 
   1870       Number(int i) {Cnt = i;}
   1871 
   1872       Number(long n) {
   1873          if (n >= Integer.MIN_VALUE  && n <= Integer.MAX_VALUE)
   1874             Cnt = (int)n;
   1875          else
   1876             Big = new BigInteger(new byte[] {(byte)(n>>56), (byte)(n>>48), (byte)(n>>40), (byte)(n>>32), (byte)(n>>24), (byte)(n>>16), (byte)(n>>8), (byte)n});
   1877       }
   1878 
   1879       Number(BigInteger b) {
   1880          if (b.bitLength() < 32)
   1881             Cnt = b.intValue();
   1882          else
   1883             Big = b;
   1884       }
   1885 
   1886       Number(String s) {
   1887          try {Cnt = Integer.parseInt(s);}
   1888          catch (NumberFormatException e) {Big = new BigInteger(s);}
   1889       }
   1890 
   1891       final long longValue() {return Big == null? Cnt : Big.longValue();}
   1892 
   1893       final static BigInteger big(int i) {
   1894          return new BigInteger(new byte[] {(byte)(i>>24), (byte)(i>>16), (byte)(i>>8), (byte)i});
   1895       }
   1896 
   1897       final Any put(Any key, Any val) {return symError(this);}
   1898       final Any get(Any key) {return symError(this);}
   1899       final Any prop(Any key) {return symError(this);}
   1900       final Any putl(Any lst) {return symError(this);}
   1901       final Any getl() {return symError(this);}
   1902       final Any eval() {return this;}
   1903       final Any prog() {return execError(this);}
   1904       final Any run() {return execError(this);}
   1905       final Any call(Any ex) {return ex;}
   1906 
   1907       final Any func(Any ex) {
   1908          try {
   1909             switch(Cnt) {
   1910             case 0:  // (quote . any) -> any
   1911                return ex.Cdr;
   1912             case 1:  // (meth 'obj ['any ..]) -> any
   1913                return doMeth(ex);
   1914             <FUN> 1
   1915             default:
   1916                return undefined(this, ex);
   1917             }
   1918          }
   1919          catch (Throwable e) {
   1920             if (e instanceof Control)
   1921                throw (Control)e;
   1922             return err(ex, null, e.toString());
   1923          }
   1924       }
   1925 
   1926       final static Any doMeth(Any ex) {
   1927          Any x, y, z;
   1928          z = (x = ex.Cdr).Car.eval();
   1929          for (TheKey = ex.Car; ; TheKey = TheKey.Car)
   1930             if (TheKey.Car instanceof Number) {
   1931                TheCls = null;
   1932                if ((y = method(z)) != null)
   1933                   return evMethod(z, y, x.Cdr);
   1934                err(ex, TheKey, "Bad message");
   1935             }
   1936       }
   1937 
   1938       <DEF> 1
   1939 
   1940       final Any apply(Any ex, boolean cf, Any[] v, int n) {
   1941          Any x, y = Nil;
   1942          if (n > 0) {
   1943             y = x = new Cell(mkSymbol(cf? v[0].Car : v[0]), Nil);
   1944             for (int i = 1; i < n; ++i)
   1945                x = x.Cdr = new Cell(mkSymbol(cf? v[i].Car : v[i]), Nil);
   1946          }
   1947          return func(new Cell(this, y));
   1948       }
   1949 
   1950       final boolean equal(Any x) {
   1951          if (x == this)
   1952             return true;
   1953          if (!(x instanceof Number))
   1954             return false;
   1955          Number num = (Number)x;
   1956          if (Big == null)
   1957             return num.Big == null && Cnt == num.Cnt;
   1958          return Big.equals(num.Big);
   1959       }
   1960 
   1961       final int compare(Any x) {
   1962          if (x == this)
   1963             return 0;
   1964          if (x == Nil)
   1965             return +1;
   1966          if (!(x instanceof Number))
   1967             return -1;
   1968          Number num = (Number)x;
   1969          if (Big == null) {
   1970             if (num.Big == null)
   1971                return Cnt == num.Cnt? 0 : Cnt > num.Cnt? 1 : -1;
   1972             return -num.Big.signum();
   1973          }
   1974          if (num.Big == null)
   1975             return Big.signum();
   1976          return Big.compareTo(num.Big);
   1977       }
   1978 
   1979       final long length() {return (Big == null? Integer.toString(Cnt) : Big.toString()).length();}
   1980 
   1981       final long size() {
   1982          if (Big == null) {
   1983             int n = 2 * (Cnt >= 0? Cnt : -Cnt);
   1984             if (n == 0)
   1985                return 1;
   1986             int i = 1;
   1987             while ((n >>= 8) != 0)
   1988                ++i;
   1989             return i;
   1990          }
   1991          return Big.toByteArray().length;
   1992       }
   1993 
   1994       final InFrame rdOpen(Any ex) {
   1995          int i;
   1996          InFrame f;
   1997          if ((i = Cnt) < 0) {
   1998             for (f = Env.InFrames;;) {
   1999                if ((f = f.Link) == null)
   2000                   badFd(ex, this);
   2001                if (++i == 0) {
   2002                   i = f.Rd.Fd;
   2003                   break;
   2004                }
   2005             }
   2006          }
   2007          if (i >= InFiles.length || InFiles[i] == null)
   2008             badFd(ex, this);
   2009          return new InFrame(InFiles[i],0);
   2010       }
   2011 
   2012       final OutFrame wrOpen(Any ex) {
   2013          int i;
   2014          OutFrame f;
   2015          if ((i = Cnt) < 0) {
   2016             for (f = Env.OutFrames;;) {
   2017                if ((f = f.Link) == null)
   2018                   badFd(ex, this);
   2019                if (++i == 0) {
   2020                   i = f.Wr.Fd;
   2021                   break;
   2022                }
   2023             }
   2024          }
   2025          if (i >= OutFiles.length || OutFiles[i] == null)
   2026             badFd(ex, this);
   2027          return new OutFrame(OutFiles[i],0);
   2028       }
   2029 
   2030       final String name() {return Big == null? Integer.toString(Cnt) : Big.toString();}
   2031       final public String toString() {return name();}
   2032 
   2033       final public String toString(int scl, char sep, char ign) {
   2034          String s = name();
   2035          StringBuilder sb = new StringBuilder();
   2036          if (s.charAt(0) == '-') {
   2037             sb.append('-');
   2038             s = s.substring(1);
   2039          }
   2040          if ((scl = s.length() - scl - 1) < 0) {
   2041             sb.append('0');
   2042             sb.append(sep);
   2043             while (scl < -1) {
   2044                sb.append('0');
   2045                ++scl;
   2046             }
   2047          }
   2048          for (int i = 0;;) {
   2049             sb.append(s.charAt(i++));
   2050             if (i == s.length())
   2051                return sb.toString();
   2052             if (scl == 0)
   2053                sb.append(sep);
   2054             else if (ign != '\0'  &&  scl > 0  &&  scl % 3 == 0)
   2055                sb.append(ign);
   2056             --scl;
   2057          }
   2058       }
   2059 
   2060       final Number abs() {
   2061          if (Big == null) {
   2062             if (Cnt >= 0)
   2063                return this;
   2064             if (Cnt != Integer.MIN_VALUE)
   2065                return new Number(-Cnt);
   2066             return new Number(-(long)Cnt);
   2067          }
   2068          return new Number(Big.abs());
   2069       }
   2070 
   2071       final Number neg() {
   2072          if (Big == null) {
   2073             if (Cnt != Integer.MIN_VALUE)
   2074                return new Number(-Cnt);
   2075             return new Number(-(long)Cnt);
   2076          }
   2077          return new Number(Big.negate());
   2078       }
   2079 
   2080       final Number add(Number num) {
   2081          if (Big == null) {
   2082             if (num.Big == null)
   2083                return new Number((long)Cnt + (long)num.Cnt);
   2084             return new Number(big(Cnt).add(num.Big));
   2085          }
   2086          if (num.Big == null)
   2087             return new Number(Big.add(big(num.Cnt)));
   2088          return new Number(Big.add(num.Big));
   2089       }
   2090 
   2091       final Number sub(Number num) {
   2092          if (Big == null) {
   2093             if (num.Big == null)
   2094                return new Number((long)Cnt - (long)num.Cnt);
   2095             return new Number(big(Cnt).subtract(num.Big));
   2096          }
   2097          if (num.Big == null)
   2098             return new Number(Big.subtract(big(num.Cnt)));
   2099          return new Number(Big.subtract(num.Big));
   2100       }
   2101 
   2102       final Number mul(Number num) {
   2103          if (Big == null) {
   2104             if (num.Big == null)
   2105                return new Number((long)Cnt * (long)num.Cnt);
   2106             return new Number(big(Cnt).multiply(num.Big));
   2107          }
   2108          if (num.Big == null)
   2109             return new Number(Big.multiply(big(num.Cnt)));
   2110          return new Number(Big.multiply(num.Big));
   2111       }
   2112 
   2113       final Number div(Number num) {
   2114          if (Big == null) {
   2115             if (num.Big == null)
   2116                return new Number((long)Cnt / (long)num.Cnt);
   2117             return new Number(big(Cnt).divide(num.Big));
   2118          }
   2119          if (num.Big == null)
   2120             return new Number(Big.divide(big(num.Cnt)));
   2121          return new Number(Big.divide(num.Big));
   2122       }
   2123 
   2124       final Number rem(Number num) {
   2125          if (Big == null) {
   2126             if (num.Big == null)
   2127                return new Number((long)Cnt % (long)num.Cnt);
   2128             return new Number(big(Cnt).remainder(num.Big));
   2129          }
   2130          if (num.Big == null)
   2131             return new Number(Big.remainder(big(num.Cnt)));
   2132          return new Number(Big.remainder(num.Big));
   2133       }
   2134 
   2135       final Number shift(int i) {
   2136          if (Big == null) {
   2137             if (i >= 0)
   2138                return new Number((long)Cnt >> i);
   2139             if (i > -32)
   2140                return new Number((long)Cnt << -i);
   2141             return new Number((new BigInteger(new byte[] {(byte)(Cnt>>24), (byte)(Cnt>>16), (byte)(Cnt>>8), (byte)Cnt})).shiftRight(i));
   2142          }
   2143          return new Number(Big.shiftRight(i));
   2144       }
   2145 
   2146       final boolean tst(Number num) {
   2147          if (Big == null) {
   2148             if (num.Big == null)
   2149                return Cnt == (Cnt & num.Cnt);
   2150             BigInteger b = big(Cnt);
   2151             return b.equals(b.and(num.Big));
   2152          }
   2153          if (num.Big == null)
   2154             return Big.equals(Big.and(big(num.Cnt)));
   2155          return Big.equals(Big.and(num.Big));
   2156       }
   2157 
   2158       final Number and(Number num) {
   2159          if (Big == null) {
   2160             if (num.Big == null)
   2161                return new Number((long)Cnt & (long)num.Cnt);
   2162             return new Number(big(Cnt).and(num.Big));
   2163          }
   2164          if (num.Big == null)
   2165             return new Number(Big.and(big(num.Cnt)));
   2166          return new Number(Big.and(num.Big));
   2167       }
   2168 
   2169       final Number or(Number num) {
   2170          if (Big == null) {
   2171             if (num.Big == null)
   2172                return new Number((long)Cnt | (long)num.Cnt);
   2173             return new Number(big(Cnt).or(num.Big));
   2174          }
   2175          if (num.Big == null)
   2176             return new Number(Big.or(big(num.Cnt)));
   2177          return new Number(Big.or(num.Big));
   2178       }
   2179 
   2180       final Number xor(Number num) {
   2181          if (Big == null) {
   2182             if (num.Big == null)
   2183                return new Number((long)Cnt ^ (long)num.Cnt);
   2184             return new Number(big(Cnt).xor(num.Big));
   2185          }
   2186          if (num.Big == null)
   2187             return new Number(Big.xor(big(num.Cnt)));
   2188          return new Number(Big.xor(num.Big));
   2189       }
   2190    }
   2191 
   2192    final static class Symbol extends Any {
   2193       Object Obj;
   2194       Any Prop[];
   2195       String Name;
   2196 
   2197       Symbol(Any val, String nm) {
   2198          Car = val == null? this : val;
   2199          Name = nm;
   2200       }
   2201 
   2202       Symbol(Object obj) {
   2203          Car = this;
   2204          Obj = obj;
   2205       }
   2206 
   2207       final void wipe() {
   2208          Car = Nil;
   2209          Prop = null;
   2210       }
   2211 
   2212       final Any put(Any key, Any val) {
   2213          if (key.equal(Zero))
   2214             Car = val;
   2215          else if (Prop != null) {
   2216             Any x;
   2217             int i = Prop.length, p = -1;
   2218             do {
   2219                if ((x = Prop[--i]) == null)
   2220                   p = i;
   2221                else if (x instanceof Cell) {
   2222                   if (key == x.Cdr) {
   2223                      if (val == Nil)
   2224                         Prop[i] = null;
   2225                      else if (val == T)
   2226                         Prop[i] = key;
   2227                      else
   2228                         x.Car = val;
   2229                      return val;
   2230                   }
   2231                }
   2232                else if (key == x) {
   2233                   if (val == Nil)
   2234                      Prop[i] = null;
   2235                   else if (val != T)
   2236                      Prop[i] = new Cell(val, key);
   2237                   return val;
   2238                }
   2239             } while (i != 0);
   2240             if (val != Nil) {
   2241                if (p < 0) {
   2242                   Any[] a = new Any[(p = Prop.length) * 2];
   2243                   System.arraycopy(Prop, 0, a, 0, p);
   2244                   Prop = a;
   2245                }
   2246                Prop[p] = val != T? new Cell(val, key) : key;
   2247             }
   2248          }
   2249          else if (val != Nil)
   2250             (Prop = new Any[3])[2] = val != T? new Cell(val, key) : key;
   2251          return val;
   2252       }
   2253 
   2254       final Any get(Any key) {
   2255          if (key.equal(Zero))
   2256             return Car;
   2257          if (Prop == null)
   2258             return Nil;
   2259          Any x;
   2260          int i = Prop.length;
   2261          do {
   2262             if ((x = Prop[--i]) != null) {
   2263                if (x instanceof Cell) {
   2264                   if (key == x.Cdr)
   2265                      return x.Car;
   2266                }
   2267                else if (key == x)
   2268                   return T;
   2269             }
   2270          } while (i != 0);
   2271          return Nil;
   2272       }
   2273 
   2274       final Any prop(Any key) {
   2275          Any x;
   2276 
   2277          if (Prop == null) {
   2278             (Prop = new Any[3])[2] = x = new Cell(Nil, key);
   2279             return x;
   2280          }
   2281          int i = Prop.length, p = -1;
   2282          do {
   2283             if ((x = Prop[--i]) == null)
   2284                p = i;
   2285             else if (x instanceof Cell) {
   2286                if (key == x.Cdr)
   2287                   return x;
   2288             }
   2289             else if (key == x)
   2290                return key;
   2291          } while (i != 0);
   2292          if (p < 0) {
   2293             Any[] a = new Any[(p = Prop.length) * 2];
   2294             System.arraycopy(Prop, 0, a, 0, p);
   2295             Prop = a;
   2296          }
   2297          Prop[p] = x = new Cell(Nil, key);
   2298          return x;
   2299       }
   2300 
   2301       final Any putl(Any lst) {
   2302          Prop = new Any[6];
   2303          int i = 0;
   2304          for (Any y = lst; y instanceof Cell; y = y.Cdr)
   2305             Prop = append(Prop, i++, y.Car);
   2306          return lst;
   2307       }
   2308 
   2309       final Any getl() {
   2310          Any x = Nil;
   2311          if (Prop != null)
   2312             for (int i = Prop.length; --i >= 0;)
   2313                if (Prop[i] != null)
   2314                   x = new Cell(Prop[i], x);
   2315          return x;
   2316       }
   2317 
   2318       final Any eval() {return Car;}
   2319       final Any prog() {return Car;}
   2320       final Any run() {return Car;}
   2321 
   2322       final Any call(Any ex) {
   2323          if (Car == Nil)
   2324             undefined(this, ex);
   2325          return Car.func(ex);
   2326       }
   2327 
   2328       final Any func(Any ex) {return Car.func(ex);}
   2329 
   2330       final Any apply(Any ex, boolean cf, Any[] v, int n) {
   2331          if (Car == Meth.Car) {
   2332             Any x, y, z, o = cf? v[0].Car : v[0];
   2333             TheCls = null;  TheKey = this;
   2334             if ((z = method(o)) != null) {
   2335                int i;
   2336                Any cls = Env.Cls;  Any key = Env.Key;
   2337                Env.Cls = TheCls;  Env.Key = TheKey;
   2338                Bind bnd = new Bind();  bnd.add(At.Car);  bnd.add(At);
   2339                for (x = z.Car, i = 0; x instanceof Cell; ++i) {
   2340                   bnd.add((y = x.Car).Car);  // Save value
   2341                   bnd.add(y);  // and symbol
   2342                   y.Car = i >= n? Nil : cf? v[i].Car : v[i];
   2343                   x = x.Cdr;
   2344                }
   2345                if (x == Nil || x != At) {
   2346                   if (x != Nil) {
   2347                      bnd.add(x.Car);  // Save value
   2348                      bnd.add(x);  // and symbol
   2349                      x.Car = Nil;  // Set to NIL
   2350                      while (--n >= i)
   2351                         x.Car = new Cell(mkSymbol(cf? v[n].Car : v[n]), x.Car);
   2352                   }
   2353                   bnd.add(This.Car);
   2354                   bnd.add(This);
   2355                   This.Car = o;
   2356                   Env.Bind = bnd;
   2357                   x = z.Cdr.prog();
   2358                }
   2359                else {
   2360                   int next, argc, j = 0;
   2361                   Any arg, args[], av[] = null;
   2362                   if (i < n) {
   2363                      av = new Any[6];
   2364                      do
   2365                         av = append(av, j++, x.Car.eval());
   2366                      while (++i < n);
   2367                   }
   2368                   next = Env.Next;  Env.Next = 0;
   2369                   argc = Env.ArgC;  Env.ArgC = j;
   2370                   arg = Env.Arg;    Env.Arg = Nil;
   2371                   args = Env.Args;  Env.Args = av;
   2372                   bnd.add(This.Car);
   2373                   bnd.add(This);
   2374                   This.Car = o;
   2375                   Env.Bind = bnd;
   2376                   x = z.Cdr.prog();
   2377                   Env.Args = args;
   2378                   Env.Arg = arg;
   2379                   Env.ArgC = argc;
   2380                   Env.Next = next;
   2381                }
   2382                for (i = bnd.Cnt; (i -= 2) >= 0;)
   2383                   bnd.Data[i+1].Car = bnd.Data[i];
   2384                Env.Bind = bnd.Link;
   2385                Env.Cls = cls;  Env.Key = key;
   2386                return x;
   2387             }
   2388             err(ex, o, "Bad object");
   2389          }
   2390          if (Car == Nil || Car == this)
   2391             undefined(this, ex);
   2392          return Car.apply(ex, cf, v, n);
   2393       }
   2394 
   2395       final boolean equal(Any x) {
   2396          if (x == this)
   2397             return true;
   2398          if (x instanceof Symbol) {
   2399             Symbol s = (Symbol)x;
   2400             if (Name != null)
   2401                return Name.equals(s.Name);
   2402             if (Obj != null)
   2403                return Obj.equals(s.Obj);
   2404          }
   2405          return false;
   2406       }
   2407 
   2408       final int compare(Any x) {
   2409          if (x == this)
   2410             return 0;
   2411          if (this == T || x == Nil || x instanceof Number)
   2412             return +1;
   2413          if (x == T  || x instanceof Cell)
   2414             return -1;
   2415          String a = Name;
   2416          String b = ((Symbol)x).Name;
   2417          if (a == null)
   2418             return b == null? hashCode() - x.hashCode() : -1;
   2419          if (b == null)
   2420             return +1;
   2421          return a.compareTo(b);
   2422       }
   2423 
   2424       final long length() {return name().length();}
   2425       final long size() {return name().getBytes().length;}
   2426 
   2427       final InFrame rdOpen(Any ex) {
   2428          try {
   2429             String nm = path(name());
   2430             if (nm.charAt(0) == '+')
   2431                nm = nm.substring(1);  // No file reader with "rw" mode
   2432             return new InFrame(new PicoLispReader(new LineNumberReader(new FileReader(nm)), nm, allocFd(), null, 0), 1);
   2433          }
   2434          catch (IOException e) {
   2435             err(ex, this, "Read open error");
   2436             return null;
   2437          }
   2438       }
   2439 
   2440       final OutFrame wrOpen(Any ex) {
   2441          try {
   2442             String nm = path(name());
   2443             if (nm.charAt(0) == '+')
   2444                return new OutFrame(new PicoLispWriter(new PrintWriter(new FileWriter(nm.substring(1), true)), nm, allocFd()), 1);
   2445             return new OutFrame(new PicoLispWriter(new PrintWriter(nm), nm, allocFd()), 1);
   2446          }
   2447          catch (IOException e) {
   2448             err(ex, this, "Write open error");
   2449             return null;
   2450          }
   2451       }
   2452 
   2453       final String name() {return Name != null? Name : Obj == null? "" : Obj.toString();}
   2454 
   2455       final public String toString() {
   2456          if (Name == null) {
   2457             String s;
   2458             if (Obj == null)
   2459                return "$" + hashCode();
   2460             int i = (s = Obj.getClass().toString()).lastIndexOf('.');
   2461             if (i >= 0)
   2462                s = s.substring(i + 1);
   2463             if (s.startsWith("class "))
   2464                s = s.substring(6);
   2465             return '$' + s;
   2466 
   2467          }
   2468          if (Env.intern().get(Name) == this) {
   2469             if (Name.equals("."))
   2470                return "\\.";
   2471             StringBuilder sb = new StringBuilder();
   2472             for (int i = 0; i < Name.length(); ++i) {
   2473                char c = Name.charAt(i);
   2474                if (c == '\\' || Delim.indexOf(c) >= 0)
   2475                   sb.append('\\');
   2476                sb.append(c);
   2477             }
   2478             return sb.toString();
   2479          }
   2480          StringBuilder sb = new StringBuilder();
   2481          sb.append('\"');
   2482          for (int i = 0; i < Name.length(); ++i) {
   2483             char c = Name.charAt(i);
   2484             if (c == '\\' || c == '^' || c == '"')
   2485                sb.append('\\');
   2486             else if (c == 127)
   2487                {sb.append('^');  c = '?';}
   2488             else if (c < ' ')
   2489                {sb.append('^');  c |= 0x40;}
   2490             sb.append(c);
   2491          }
   2492          sb.append('\"');
   2493          return sb.toString();
   2494       }
   2495 
   2496       final Any parse(boolean skp, Any s) {
   2497          Any x, y, z;
   2498          PicoLispReader rd;
   2499          if (s == null)
   2500             rd = new PicoLispReader(name(), '\n', ']');
   2501          else
   2502             rd = new PicoLispReader(name(), '\0', '\0');
   2503          if (skp)
   2504             rd.get();
   2505          if (s == null)
   2506             return rd.rdList();
   2507          if ((x = rd.token(s, '\0')) == null)
   2508             return Nil;
   2509          z = y = new Cell(x, Nil);
   2510          while ((x = rd.token(s, '\0')) != null)
   2511             y = y.Cdr = new Cell(x, Nil);
   2512          return z;
   2513       }
   2514    }
   2515 
   2516 
   2517    final static class NilSym extends Any {
   2518       NilSym() {
   2519          Car = this;
   2520          Cdr = this;
   2521       }
   2522 
   2523       final Any put(Any key, Any val) {return protError(this);}
   2524       final Any get(Any key) {return this;}
   2525       final Any prop(Any key) {return this;}
   2526       final Any putl(Any lst) {return protError(this);}
   2527       final Any getl() {return protError(this);}
   2528       final Any eval() {return this;}
   2529       final Any prog() {return this;}
   2530       final Any run() {return this;}
   2531       final Any call(Any ex) {return undefined(this,ex);}
   2532       final Any func(Any ex) {return undefined(this,ex);}
   2533       final Any apply(Any ex, boolean cf, Any[] v, int n) {return undefined(this,ex);}
   2534       final boolean equal(Any x) {return x == Nil;}
   2535       final int compare(Any x) {return x == this? 0 : -1;}
   2536       final long length() {return 0;}
   2537       final long size() {return 0;}
   2538       final InFrame rdOpen(Any ex) {return new InFrame(InFiles[0], 0);}
   2539       final OutFrame wrOpen(Any ex) {return new OutFrame(OutFiles[1], 0);}
   2540       final String name() {return "";}
   2541       final public String toString() {return "NIL";}
   2542    }
   2543 
   2544    final static class Cell extends Any {
   2545       Cell(Any car, Any cdr) {
   2546          Car = car;
   2547          Cdr = cdr;
   2548       }
   2549 
   2550       final Any put(Any key, Any val) {return symError(this);}
   2551 
   2552       final Any get(Any key) {
   2553          Any x, y = this;
   2554          if (key instanceof Number) {
   2555             int n = ((Number)key).Cnt;
   2556             if (n > 0) {
   2557                while (--n != 0)
   2558                   y = y.Cdr;
   2559                return y.Car;
   2560             }
   2561             if (n < 0) {
   2562                while (++n != 0)
   2563                   y = y.Cdr;
   2564                return y.Cdr;
   2565             }
   2566          }
   2567          else
   2568             do
   2569                if ((x = y.Car) instanceof Cell  &&  key == x.Car)
   2570                   return x.Cdr;
   2571             while ((y = y.Cdr) instanceof Cell);
   2572          return Nil;
   2573       }
   2574 
   2575       final Any prop(Any key) {return symError(this);}
   2576       final Any putl(Any lst) {return symError(this);}
   2577       final Any getl() {return symError(this);}
   2578       final Any eval() {return Car.call(this);}
   2579 
   2580       final Any prog() {
   2581          Any ex;
   2582          for (ex = this; ex.Cdr != Nil; ex = ex.Cdr)
   2583             ex.Car.eval();
   2584          return ex.Car.eval();
   2585       }
   2586 
   2587       final Any run() {
   2588          Any x, at = At.Car;
   2589          Any ex = this;
   2590          do
   2591             x = ex.Car.eval();
   2592          while ((ex = ex.Cdr) != Nil);
   2593          At.Car = at;
   2594          return x;
   2595       }
   2596 
   2597       final Any call(Any ex) {return eval().func(ex);}
   2598 
   2599       final Any func(Any ex) {
   2600          int i;
   2601          Any x, y;
   2602          Bind bnd = new Bind();  bnd.add(At.Car);  bnd.add(At);
   2603          for (x = Car; x instanceof Cell; x = x.Cdr) {
   2604             bnd.add((ex = ex.Cdr).Car.eval());  // Save new value
   2605             bnd.add(x.Car);  // and symbol
   2606          }
   2607          if (x == Nil || x != At) {
   2608             i = bnd.Cnt;
   2609             if (x != Nil) {
   2610                bnd.add(x.Car);  // Save old value
   2611                bnd.add(x);  // and symbol
   2612                x.Car = ex.Cdr;  // Set new value
   2613             }
   2614             do {
   2615                y = bnd.Data[--i];
   2616                x = y.Car;
   2617                y.Car = bnd.Data[--i];  // Set new value
   2618                bnd.Data[i] = x;  // Save old value
   2619             } while (i > 0);
   2620             Env.Bind = bnd;
   2621             x = Cdr.prog();
   2622          }
   2623          else {
   2624             int next, argc, j = 0;
   2625             Any arg, args[], av[] = null;
   2626             if (ex.Cdr != Nil) {
   2627                av = new Any[6];
   2628                do
   2629                   av = append(av, j++, (ex = ex.Cdr).Car.eval());
   2630                while (ex.Cdr != Nil);
   2631             }
   2632             next = Env.Next;  Env.Next = 0;
   2633             argc = Env.ArgC;  Env.ArgC = j;
   2634             arg = Env.Arg;    Env.Arg = Nil;
   2635             args = Env.Args;  Env.Args = av;
   2636             i = bnd.Cnt;
   2637             do {
   2638                y = bnd.Data[--i];
   2639                x = y.Car;
   2640                y.Car = bnd.Data[--i];  // Set new value
   2641                bnd.Data[i] = x;  // Save old value
   2642             } while (i > 0);
   2643             Env.Bind = bnd;
   2644             x = Cdr.prog();
   2645             Env.Args = args;
   2646             Env.Arg = arg;
   2647             Env.ArgC = argc;
   2648             Env.Next = next;
   2649          }
   2650          for (i = bnd.Cnt; (i -= 2) >= 0;)
   2651             bnd.Data[i+1].Car = bnd.Data[i];
   2652          Env.Bind = bnd.Link;
   2653          return x;
   2654       }
   2655 
   2656       final Any apply(Any ex, boolean cf, Any[] v, int n) {
   2657          int i;
   2658          Any x, y;
   2659          Bind bnd = new Bind();  bnd.add(At.Car);  bnd.add(At);
   2660          for (x = Car, i = 0; x instanceof Cell; ++i, x = x.Cdr) {
   2661             bnd.add((y = x.Car).Car);  // Save value
   2662             bnd.add(y);  // and symbol
   2663             y.Car = i >= n? Nil : cf? v[i].Car : v[i];
   2664          }
   2665          if (x == Nil || x != At) {
   2666             if (x != Nil) {
   2667                bnd.add(x.Car);  // Save old value
   2668                bnd.add(x);  // and symbol
   2669                x.Car = Nil;  // Set to NIL
   2670                while (--n >= i)
   2671                   x.Car = new Cell(mkSymbol(cf? v[n].Car : v[n]), x.Car);
   2672             }
   2673             Env.Bind = bnd;
   2674             x = Cdr.prog();
   2675          }
   2676          else {
   2677             int next, argc, j = 0;
   2678             Any arg, args[], av[] = null;
   2679             if (i < n) {
   2680                av = new Any[6];
   2681                do
   2682                   av = append(av, j++, cf? v[i].Car : v[i]);
   2683                while (++i < n);
   2684             }
   2685             next = Env.Next;  Env.Next = 0;
   2686             argc = Env.ArgC;  Env.ArgC = j;
   2687             arg = Env.Arg;    Env.Arg = Nil;
   2688             args = Env.Args;  Env.Args = av;
   2689             Env.Bind = bnd;
   2690             x = Cdr.prog();
   2691             Env.Args = args;
   2692             Env.Arg = arg;
   2693             Env.ArgC = argc;
   2694             Env.Next = next;
   2695          }
   2696          for (i = bnd.Cnt; (i -= 2) >= 0;)
   2697             bnd.Data[i+1].Car = bnd.Data[i];
   2698          Env.Bind = bnd.Link;
   2699          return x;
   2700       }
   2701 
   2702       final boolean equal(Any x) {
   2703          if (!(x instanceof Cell))
   2704             return false;
   2705          if (!x.Car.equal(Car))
   2706             return false;
   2707          HashSet<Any> mark = new HashSet<Any>();
   2708          Any y = this, a = x, b = y;
   2709          for (;;) {
   2710             if (!(x.Cdr instanceof Cell))
   2711                return x.Cdr.equal(y.Cdr);
   2712             if (!(y.Cdr instanceof Cell))
   2713                return false;
   2714             mark.add(x);  x = x.Cdr;  y = y.Cdr;
   2715             if (mark.contains(x)) {
   2716                for (;;) {
   2717                   if (a == x) {
   2718                      if (b != y)
   2719                         return false;
   2720                      for (;;) {
   2721                         a = a.Cdr;
   2722                         if ((b = b.Cdr) == y)
   2723                            return a == x;
   2724                         if (a == x)
   2725                            return true;
   2726                      }
   2727                   }
   2728                   if (b == y)
   2729                      return false;
   2730                   a = a.Cdr;  b = b.Cdr;
   2731                }
   2732             }
   2733             if (!x.Car.equal(y.Car))
   2734                return false;
   2735          }
   2736       }
   2737 
   2738       final int compare(Any x) {
   2739          if (x == this)
   2740             return 0;
   2741          if (x == T)
   2742             return -1;
   2743          if (!(x instanceof Cell))
   2744             return +1;
   2745          Any y = this;
   2746          Any a = this;
   2747          Any b = x;
   2748          for (;;) {
   2749             int n;
   2750             if ((n = y.Car.compare(x.Car)) != 0)
   2751                return n;
   2752             if (!((y = y.Cdr) instanceof Cell))
   2753                return y.compare(x.Cdr);
   2754             if (!((x = x.Cdr) instanceof Cell))
   2755                return x == T? -1 : +1;
   2756             if (y == a && x == b)
   2757                return 0;
   2758          }
   2759       }
   2760 
   2761       final long length() {
   2762          long n = 0;
   2763          HashSet<Any> mark = new HashSet<Any>();
   2764          for (Any x = this;;) {
   2765             ++n;
   2766             mark.add(x);
   2767             if (!((x = x.Cdr) instanceof Cell))
   2768                return n;
   2769             if (mark.contains(x))
   2770                return -1;
   2771          }
   2772       }
   2773 
   2774       final long size() {
   2775          long n = 0;
   2776          HashSet<Any> mark = new HashSet<Any>();
   2777          for (Any x = this;;) {
   2778             ++n;
   2779             if (x.Car instanceof Cell)
   2780                n += x.Car.size();
   2781             mark.add(x);
   2782             if (!((x = x.Cdr) instanceof Cell) || mark.contains(x))
   2783                return n;
   2784          }
   2785       }
   2786 
   2787       final InFrame rdOpen(Any ex) {
   2788          try {
   2789             int len = (int)length();
   2790             String[] cmd = new String[len];
   2791             Any x = this;
   2792             for (int i = 0; i < len; ++i) {
   2793                cmd[i] = x.Car.name();
   2794                x = x.Cdr;
   2795             }
   2796             int pid = allocPid();
   2797             return new InFrame(new PicoLispReader((Pids[pid] = Runtime.getRuntime().exec(cmd)).getInputStream(), allocFd(), null, 0), pid);
   2798          }
   2799          catch (IOException e) {
   2800             err(ex, this, "Pipe read open error");
   2801             return null;
   2802          }
   2803       }
   2804 
   2805       final OutFrame wrOpen(Any ex) {
   2806          try {
   2807             int len = (int)length();
   2808             String[] cmd = new String[len];
   2809             Any x = this;
   2810             for (int i = 0; i < len; ++i) {
   2811                cmd[i] = x.Car.name();
   2812                x = x.Cdr;
   2813             }
   2814             int pid = allocPid();
   2815             return new OutFrame(new PicoLispWriter((Pids[pid] = Runtime.getRuntime().exec(cmd)).getOutputStream(), allocFd()), pid);
   2816          }
   2817          catch (IOException e) {
   2818             err(ex, this, "Pipe write open error");
   2819             return null;
   2820          }
   2821       }
   2822 
   2823       final String name() {return Car.name() + Cdr.name();}
   2824 
   2825       final public String toString() {
   2826          Any x, y;
   2827          StringBuilder sb;
   2828          if (Car == Quote  &&  this != Cdr)
   2829             return '\'' + Cdr.toString();
   2830          x = this;
   2831          sb = new StringBuilder();
   2832          sb.append('(');
   2833          if ((y = circ(x)) == null) {
   2834             for (;;) {
   2835                sb.append(x.Car.toString());
   2836                if ((x = x.Cdr) == Nil)
   2837                   break;
   2838                if (!(x instanceof Cell)) {
   2839                   sb.append(" . ");
   2840                   sb.append(x.toString());
   2841                   break;
   2842                }
   2843                sb.append(' ');
   2844             }
   2845          }
   2846          else if (y == x) {
   2847             do {
   2848                sb.append(x.Car.toString());
   2849                sb.append(' ');
   2850             } while (y != (x = x.Cdr));
   2851             sb.append('.');
   2852          }
   2853          else {
   2854             do {
   2855                sb.append(x.Car.toString());
   2856                sb.append(' ');
   2857             } while (y != (x = x.Cdr));
   2858             sb.append(". (");
   2859             do {
   2860                sb.append(x.Car.toString());
   2861                sb.append(' ');
   2862             } while (y != (x = x.Cdr));
   2863             sb.append(".)");
   2864          }
   2865          sb.append(')');
   2866          return sb.toString();
   2867       }
   2868    }
   2869 }