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 }