flow.c (31150B)
1 /* 30oct07abu 2 * (c) Software Lab. Alexander Burger 3 */ 4 5 #include "pico.h" 6 7 static void redefMsg(any x, any y) { 8 FILE *oSave = OutFile; 9 10 OutFile = stderr; 11 outString("# "); 12 print(x); 13 if (y) 14 space(), print(y); 15 outString(" redefined\n"); 16 OutFile = oSave; 17 } 18 19 static void redefine(any ex, any s, any x) { 20 NeedSymb(ex,s); 21 CheckVar(ex,s); 22 if (!isNil(val(s)) && s != val(s) && !equal(x,val(s))) 23 redefMsg(s,NULL); 24 val(s) = x; 25 } 26 27 // (quote . any) -> any 28 any doQuote(any x) {return cdr(x);} 29 30 // (as 'any1 . any2) -> any2 | NIL 31 any doAs(any x) { 32 x = cdr(x); 33 if (isNil(EVAL(car(x)))) 34 return Nil; 35 return cdr(x); 36 } 37 38 // (lit 'any) -> any 39 any doLit(any x) { 40 x = cadr(x); 41 if (isNum(x = EVAL(x)) || isSym(x) && x==val(x) || isCell(x) && isNum(car(x))) 42 return x; 43 return cons(Quote, x); 44 } 45 46 // (eval 'any ['cnt]) -> any 47 any doEval(any x) { 48 cell c1; 49 bindFrame *p; 50 51 x = cdr(x), Push(c1, EVAL(car(x))), x = cdr(x); 52 if (!isNum(x = EVAL(car(x))) || !(p = Env.bind)) 53 data(c1) = EVAL(data(c1)); 54 else { 55 int cnt, n, i; 56 bindFrame *q; 57 58 for (cnt = (int)unBox(x), n = 0;;) { 59 ++n; 60 if (p->i <= 0) { 61 if (p->i-- == 0) { 62 for (i = 0; i < p->cnt; ++i) { 63 x = val(p->bnd[i].sym); 64 val(p->bnd[i].sym) = p->bnd[i].val; 65 p->bnd[i].val = x; 66 } 67 if (p->cnt && p->bnd[0].sym == At && !--cnt) 68 break; 69 } 70 } 71 if (!(q = Env.bind->link)) 72 break; 73 Env.bind->link = q->link, q->link = p, p = q; 74 } 75 Env.bind = p; 76 data(c1) = EVAL(data(c1)); 77 for (;;) { 78 if (p->i < 0) { 79 if (++p->i == 0) 80 for (i = p->cnt; --i >= 0;) { 81 x = val(p->bnd[i].sym); 82 val(p->bnd[i].sym) = p->bnd[i].val; 83 p->bnd[i].val = x; 84 } 85 } 86 if (!--n) 87 break; 88 q = Env.bind->link, Env.bind->link = q->link, q->link = p, p = q; 89 } 90 Env.bind = p; 91 } 92 return Pop(c1); 93 } 94 95 // (run 'any ['cnt]) -> any 96 any doRun(any x) { 97 cell c1; 98 bindFrame *p; 99 100 x = cdr(x), data(c1) = EVAL(car(x)), x = cdr(x); 101 if (!isNum(data(c1))) { 102 Save(c1); 103 if (!isNum(x = EVAL(car(x))) || !(p = Env.bind)) 104 data(c1) = isSym(data(c1))? val(data(c1)) : run(data(c1)); 105 else { 106 int cnt, n, i; 107 bindFrame *q; 108 109 for (cnt = (int)unBox(x), n = 0;;) { 110 ++n; 111 if (p->i <= 0) { 112 if (p->i-- == 0) { 113 for (i = 0; i < p->cnt; ++i) { 114 x = val(p->bnd[i].sym); 115 val(p->bnd[i].sym) = p->bnd[i].val; 116 p->bnd[i].val = x; 117 } 118 if (p->cnt && p->bnd[0].sym==At && !--cnt) 119 break; 120 } 121 } 122 if (!(q = Env.bind->link)) 123 break; 124 Env.bind->link = q->link, q->link = p, p = q; 125 } 126 Env.bind = p; 127 data(c1) = isSym(data(c1))? val(data(c1)) : prog(data(c1)); 128 for (;;) { 129 if (p->i < 0) { 130 if (++p->i == 0) 131 for (i = p->cnt; --i >= 0;) { 132 x = val(p->bnd[i].sym); 133 val(p->bnd[i].sym) = p->bnd[i].val; 134 p->bnd[i].val = x; 135 } 136 } 137 if (!--n) 138 break; 139 q = Env.bind->link, Env.bind->link = q->link, q->link = p, p = q; 140 } 141 Env.bind = p; 142 } 143 drop(c1); 144 } 145 return data(c1); 146 } 147 148 // (def 'sym 'any) -> sym 149 // (def 'sym 'sym 'any) -> sym 150 any doDef(any ex) { 151 any x, y; 152 cell c1, c2, c3; 153 154 x = cdr(ex), Push(c1, EVAL(car(x))); 155 NeedSymb(ex,data(c1)); 156 CheckVar(ex,data(c1)); 157 x = cdr(x), Push(c2, EVAL(car(x))); 158 if (!isCell(cdr(x))) { 159 if (!equal(data(c2), y = val(data(c1)))) { 160 if (!isNil(y) && data(c1) != y) 161 redefMsg(data(c1),NULL); 162 val(data(c1)) = data(c2); 163 } 164 } 165 else { 166 x = cdr(x), Push(c3, EVAL(car(x))); 167 if (!equal(data(c3), y = get(data(c1), data(c2)))) { 168 if (!isNil(y)) 169 redefMsg(data(c1), data(c2)); 170 put(data(c1), data(c2), data(c3)); 171 } 172 } 173 return Pop(c1); 174 } 175 176 // (de sym . any) -> sym 177 any doDe(any ex) { 178 redefine(ex, cadr(ex), cddr(ex)); 179 return cadr(ex); 180 } 181 182 // (dm sym . fun) -> sym 183 // (dm (sym . cls) . fun) -> sym 184 // (dm (sym sym [. cls]) . fun) -> sym 185 any doDm(any ex) { 186 any x, y, msg, cls; 187 188 x = cdr(ex); 189 if (!isCell(car(x))) 190 msg = car(x), cls = val(Class); 191 else { 192 msg = caar(x); 193 cls = !isCell(cdar(x))? cdar(x) : 194 get(isNil(cddar(x))? val(Class) : cddar(x), cadar(x)); 195 } 196 if (msg != T) 197 redefine(ex, msg, val(Meth)); 198 if (isSymb(cdr(x))) { 199 y = val(cdr(x)); 200 for (;;) { 201 if (!isCell(y) || !isCell(car(y))) 202 err(ex, msg, "Bad message"); 203 if (caar(y) == msg) { 204 x = car(y); 205 break; 206 } 207 y = cdr(y); 208 } 209 } 210 for (y = val(cls); isCell(y) && isCell(car(y)); y = cdr(y)) 211 if (caar(y) == msg) { 212 if (!equal(cdr(x), cdar(y))) 213 redefMsg(msg,cls); 214 cdar(y) = cdr(x); 215 return msg; 216 } 217 if (!isCell(car(x))) 218 val(cls) = cons(x, val(cls)); 219 else 220 val(cls) = cons(cons(caar(x), cdr(x)), val(cls)); 221 return msg; 222 } 223 224 /* Evaluate method invocation */ 225 static any evMethod(any o, any expr, any x) { 226 any y = car(expr); 227 methFrame m; 228 struct { // bindFrame 229 struct bindFrame *link; 230 int i, cnt; 231 struct {any sym; any val;} bnd[length(y)+3]; 232 } f; 233 234 m.link = Env.meth; 235 m.key = TheKey; 236 m.cls = TheCls; 237 f.link = Env.bind, Env.bind = (bindFrame*)&f; 238 f.i = sizeof(f.bnd) / (2*sizeof(any)) - 2; 239 f.cnt = 1, f.bnd[0].sym = At, f.bnd[0].val = val(At); 240 while (isCell(y)) { 241 f.bnd[f.cnt].sym = car(y); 242 f.bnd[f.cnt].val = EVAL(car(x)); 243 ++f.cnt, x = cdr(x), y = cdr(y); 244 } 245 if (isNil(y)) { 246 while (--f.i > 0) { 247 x = val(f.bnd[f.i].sym); 248 val(f.bnd[f.i].sym) = f.bnd[f.i].val; 249 f.bnd[f.i].val = x; 250 } 251 f.bnd[f.cnt].sym = This; 252 f.bnd[f.cnt++].val = val(This); 253 val(This) = o; 254 Env.meth = &m; 255 x = prog(cdr(expr)); 256 } 257 else if (y != At) { 258 f.bnd[f.cnt].sym = y, f.bnd[f.cnt++].val = val(y), val(y) = x; 259 while (--f.i > 0) { 260 x = val(f.bnd[f.i].sym); 261 val(f.bnd[f.i].sym) = f.bnd[f.i].val; 262 f.bnd[f.i].val = x; 263 } 264 f.bnd[f.cnt].sym = This, f.bnd[f.cnt++].val = val(This), val(This) = o; 265 Env.meth = &m; 266 x = prog(cdr(expr)); 267 } 268 else { 269 int n, cnt; 270 cell *arg; 271 cell c[n = cnt = length(x)]; 272 273 while (--n >= 0) 274 Push(c[n], EVAL(car(x))), x = cdr(x); 275 while (--f.i > 0) { 276 x = val(f.bnd[f.i].sym); 277 val(f.bnd[f.i].sym) = f.bnd[f.i].val; 278 f.bnd[f.i].val = x; 279 } 280 n = Env.next, Env.next = cnt; 281 arg = Env.arg, Env.arg = c; 282 f.bnd[f.cnt].sym = This; 283 f.bnd[f.cnt++].val = val(This); 284 val(This) = o; 285 Env.meth = &m; 286 x = prog(cdr(expr)); 287 if (cnt) 288 drop(c[cnt-1]); 289 Env.arg = arg, Env.next = n; 290 } 291 while (--f.cnt >= 0) 292 val(f.bnd[f.cnt].sym) = f.bnd[f.cnt].val; 293 Env.bind = f.link; 294 Env.meth = Env.meth->link; 295 return x; 296 } 297 298 any method(any x) { 299 any y, z; 300 301 if (isCell(y = val(x))) { 302 if (isCell(car(y))) { 303 if (caar(y) == TheKey) 304 return cdar(y); 305 for (;;) { 306 z = y; 307 if (!isCell(y = cdr(y))) 308 return NULL; 309 if (!isCell(car(y))) 310 break; 311 if (caar(y) == TheKey) { 312 cdr(z) = cdr(y), cdr(y) = val(x), val(x) = y; 313 return cdar(y); 314 } 315 } 316 } 317 do 318 if (x = method(car(TheCls = y))) 319 return x; 320 while (isCell(y = cdr(y))); 321 } 322 return NULL; 323 } 324 325 // (box 'any) -> sym 326 any doBox(any x) { 327 x = cdr(x); 328 return consSym(EVAL(car(x)),0); 329 } 330 331 // (new ['typ ['any ..]]) -> obj 332 any doNew(any ex) { 333 any x, y; 334 cell c1, c2; 335 336 x = cdr(ex); 337 Push(c1, consSym(EVAL(car(x)),0)); 338 TheKey = T, TheCls = Nil; 339 if (y = method(data(c1))) 340 evMethod(data(c1), y, cdr(x)); 341 else { 342 Save(c2); 343 while (isCell(x = cdr(x))) { 344 data(c2) = EVAL(car(x)), x = cdr(x); 345 put(data(c1), data(c2), EVAL(car(x))); 346 } 347 } 348 return Pop(c1); 349 } 350 351 // (type 'any) -> lst 352 any doType(any ex) { 353 any x, y, z; 354 355 x = cdr(ex), x = EVAL(car(x)); 356 if (isSymb(x)) { 357 z = x = val(x); 358 while (isCell(x)) { 359 if (!isCell(car(x))) { 360 y = x; 361 while (isSymb(car(x))) { 362 if (!isCell(x = cdr(x))) 363 return isNil(x)? y : Nil; 364 if (z == x) 365 return Nil; 366 } 367 return Nil; 368 } 369 if (z == (x = cdr(x))) 370 return Nil; 371 } 372 } 373 return Nil; 374 } 375 376 static bool isa(any ex, any cls, any x) { 377 any z; 378 379 z = x = val(x); 380 while (isCell(x)) { 381 if (!isCell(car(x))) { 382 while (isSymb(car(x))) { 383 if (cls == car(x) || isa(ex, cls, car(x))) 384 return YES; 385 if (!isCell(x = cdr(x)) || z == x) 386 return NO; 387 } 388 return NO; 389 } 390 if (z == (x = cdr(x))) 391 return NO; 392 } 393 return NO; 394 } 395 396 // (isa 'cls|typ 'any) -> obj | NIL 397 any doIsa(any ex) { 398 any x; 399 cell c1; 400 401 x = cdr(ex), Push(c1, EVAL(car(x))); 402 x = cdr(x), x = EVAL(car(x)); 403 drop(c1); 404 if (isSymb(x)) { 405 if (isSymb(data(c1))) 406 return isa(ex, data(c1), x)? x : Nil; 407 while (isCell(data(c1))) { 408 if (!isa(ex, car(data(c1)), x)) 409 return Nil; 410 data(c1) = cdr(data(c1)); 411 } 412 return x; 413 } 414 return Nil; 415 } 416 417 // (method 'msg 'obj) -> fun 418 any doMethod(any ex) { 419 any x, y; 420 421 x = cdr(ex), y = EVAL(car(x)); 422 x = cdr(x), x = EVAL(car(x)); 423 TheKey = y; 424 return method(x)? : Nil; 425 } 426 427 // (meth 'obj ..) -> any 428 any doMeth(any ex) { 429 any x, y; 430 cell c1; 431 432 x = cdr(ex), Push(c1, EVAL(car(x))); 433 NeedSymb(ex,data(c1)); 434 for (TheKey = car(ex); ; TheKey = val(TheKey)) { 435 if (!isSymb(TheKey)) 436 err(ex, car(ex), "Bad message"); 437 if (isNum(val(TheKey))) { 438 TheCls = Nil; 439 if (y = method(data(c1))) { 440 x = evMethod(data(c1), y, cdr(x)); 441 drop(c1); 442 return x; 443 } 444 err(ex, TheKey, "Bad message"); 445 } 446 } 447 } 448 449 // (send 'msg 'obj ['any ..]) -> any 450 any doSend(any ex) { 451 any x, y; 452 cell c1, c2; 453 454 x = cdr(ex), Push(c1, EVAL(car(x))); 455 NeedSymb(ex,data(c1)); 456 x = cdr(x), Push(c2, EVAL(car(x))); 457 NeedSymb(ex,data(c2)); 458 TheKey = data(c1), TheCls = Nil; 459 if (y = method(data(c2))) { 460 x = evMethod(data(c2), y, cdr(x)); 461 drop(c1); 462 return x; 463 } 464 err(ex, TheKey, "Bad message"); 465 } 466 467 // (try 'msg 'obj ['any ..]) -> any 468 any doTry(any ex) { 469 any x, y; 470 cell c1, c2; 471 472 x = cdr(ex), Push(c1, EVAL(car(x))); 473 NeedSymb(ex,data(c1)); 474 x = cdr(x), Push(c2, EVAL(car(x))); 475 if (isSymb(data(c2))) { 476 TheKey = data(c1), TheCls = Nil; 477 if (y = method(data(c2))) { 478 x = evMethod(data(c2), y, cdr(x)); 479 drop(c1); 480 return x; 481 } 482 } 483 drop(c1); 484 return Nil; 485 } 486 487 // (super ['any ..]) -> any 488 any doSuper(any ex) { 489 any x, y; 490 methFrame m; 491 492 m.key = TheKey = Env.meth->key; 493 x = val(isNil(Env.meth->cls)? val(This) : car(Env.meth->cls)); 494 while (isCell(car(x))) 495 x = cdr(x); 496 while (isCell(x)) { 497 if (y = method(car(TheCls = x))) { 498 m.cls = TheCls; 499 m.link = Env.meth, Env.meth = &m; 500 x = evExpr(y, cdr(ex)); 501 Env.meth = Env.meth->link; 502 return x; 503 } 504 x = cdr(x); 505 } 506 err(ex, TheKey, "Bad super"); 507 } 508 509 static any extra(any x) { 510 any y; 511 512 for (x = val(x); isCell(car(x)); x = cdr(x)); 513 while (isCell(x)) { 514 if (x == Env.meth->cls || !(y = extra(car(x)))) { 515 while (isCell(x = cdr(x))) 516 if (y = method(car(TheCls = x))) 517 return y; 518 return NULL; 519 } 520 if (y && y != Zero) 521 return y; 522 x = cdr(x); 523 } 524 return Zero; 525 } 526 527 // (extra ['any ..]) -> any 528 any doExtra(any ex) { 529 any x, y; 530 methFrame m; 531 532 m.key = TheKey = Env.meth->key; 533 if ((y = extra(val(This))) && y != Zero) { 534 m.cls = TheCls; 535 m.link = Env.meth, Env.meth = &m; 536 x = evExpr(y, cdr(ex)); 537 Env.meth = Env.meth->link; 538 return x; 539 } 540 err(ex, TheKey, "Bad extra"); 541 } 542 543 // (with 'sym . prg) -> any 544 any doWith(any ex) { 545 any x; 546 bindFrame f; 547 548 x = cdr(ex); 549 if (isNil(x = EVAL(car(x)))) 550 return Nil; 551 NeedSymb(ex,x); 552 Bind(This,f), val(This) = x; 553 x = prog(cddr(ex)); 554 Unbind(f); 555 return x; 556 } 557 558 // (bind 'sym|lst . prg) -> any 559 any doBind(any ex) { 560 any x, y; 561 562 x = cdr(ex); 563 if (isNum(y = EVAL(car(x)))) 564 argError(ex, y); 565 if (isNil(y)) 566 return prog(cdr(x)); 567 if (isSym(y)) { 568 bindFrame f; 569 570 Bind(y,f); 571 x = prog(cdr(x)); 572 Unbind(f); 573 return x; 574 } 575 { 576 struct { // bindFrame 577 struct bindFrame *link; 578 int i, cnt; 579 struct {any sym; any val;} bnd[length(y)]; 580 } f; 581 582 f.link = Env.bind, Env.bind = (bindFrame*)&f; 583 f.i = f.cnt = 0; 584 while (isCell(y)) { 585 if (isNum(car(y))) 586 argError(ex, car(y)); 587 if (isSym(car(y))) { 588 f.bnd[f.cnt].sym = car(y); 589 f.bnd[f.cnt].val = val(car(y)); 590 } 591 else { 592 f.bnd[f.cnt].sym = caar(y); 593 f.bnd[f.cnt].val = val(caar(y)); 594 val(caar(y)) = cdar(y); 595 } 596 ++f.cnt, y = cdr(y); 597 } 598 x = prog(cdr(x)); 599 while (--f.cnt >= 0) 600 val(f.bnd[f.cnt].sym) = f.bnd[f.cnt].val; 601 Env.bind = f.link; 602 return x; 603 } 604 } 605 606 // (job 'lst . prg) -> any 607 any doJob(any ex) { 608 any x = cdr(ex); 609 any y = EVAL(car(x)); 610 any z; 611 cell c1; 612 struct { // bindFrame 613 struct bindFrame *link; 614 int i, cnt; 615 struct {any sym; any val;} bnd[length(y)]; 616 } f; 617 618 Push(c1,y); 619 f.link = Env.bind, Env.bind = (bindFrame*)&f; 620 f.i = f.cnt = 0; 621 while (isCell(y)) { 622 f.bnd[f.cnt].sym = caar(y); 623 f.bnd[f.cnt].val = val(caar(y)); 624 val(caar(y)) = cdar(y); 625 ++f.cnt, y = cdr(y); 626 } 627 z = prog(cdr(x)); 628 for (f.cnt = 0, y = Pop(c1); isCell(y); ++f.cnt, y = cdr(y)) { 629 cdar(y) = val(caar(y)); 630 val(caar(y)) = f.bnd[f.cnt].val; 631 } 632 Env.bind = f.link; 633 return z; 634 } 635 636 // (let sym 'any . prg) -> any 637 // (let (sym 'any ..) . prg) -> any 638 any doLet(any x) { 639 any y; 640 641 x = cdr(x); 642 if (!isCell(y = car(x))) { 643 bindFrame f; 644 645 x = cdr(x), Bind(y,f), val(y) = EVAL(car(x)); 646 x = prog(cdr(x)); 647 Unbind(f); 648 } 649 else { 650 struct { // bindFrame 651 struct bindFrame *link; 652 int i, cnt; 653 struct {any sym; any val;} bnd[(length(y)+1)/2]; 654 } f; 655 656 f.link = Env.bind, Env.bind = (bindFrame*)&f; 657 f.i = f.cnt = 0; 658 do { 659 f.bnd[f.cnt].sym = car(y); 660 f.bnd[f.cnt].val = val(car(y)); 661 val(car(y)) = EVAL(cadr(y)); 662 ++f.cnt; 663 } while (isCell(y = cddr(y))); 664 x = prog(cdr(x)); 665 while (--f.cnt >= 0) 666 val(f.bnd[f.cnt].sym) = f.bnd[f.cnt].val; 667 Env.bind = f.link; 668 } 669 return x; 670 } 671 672 // (let? sym 'any . prg) -> any 673 any doLetQ(any ex) { 674 any x, y, z; 675 bindFrame f; 676 677 x = cdr(ex), y = car(x), x = cdr(x); 678 if (isNil(z = EVAL(car(x)))) 679 return Nil; 680 Bind(y,f), val(y) = z; 681 x = prog(cdr(x)); 682 Unbind(f); 683 return x; 684 } 685 686 // (use sym . prg) -> any 687 // (use (sym ..) . prg) -> any 688 any doUse(any x) { 689 any y; 690 691 x = cdr(x); 692 if (!isCell(y = car(x))) { 693 bindFrame f; 694 695 Bind(y,f); 696 x = prog(cdr(x)); 697 Unbind(f); 698 } 699 else { 700 struct { // bindFrame 701 struct bindFrame *link; 702 int i, cnt; 703 struct {any sym; any val;} bnd[length(y)]; 704 } f; 705 706 f.link = Env.bind, Env.bind = (bindFrame*)&f; 707 f.i = f.cnt = 0; 708 do { 709 f.bnd[f.cnt].sym = car(y); 710 f.bnd[f.cnt].val = val(car(y)); 711 ++f.cnt; 712 } while (isCell(y = cdr(y))); 713 x = prog(cdr(x)); 714 while (--f.cnt >= 0) 715 val(f.bnd[f.cnt].sym) = f.bnd[f.cnt].val; 716 Env.bind = f.link; 717 } 718 return x; 719 } 720 721 // (and 'any ..) -> any 722 any doAnd(any x) { 723 any a; 724 725 x = cdr(x); 726 do { 727 if (isNil(a = EVAL(car(x)))) 728 return Nil; 729 val(At) = a; 730 } 731 while (isCell(x = cdr(x))); 732 return a; 733 } 734 735 // (or 'any ..) -> any 736 any doOr(any x) { 737 any a; 738 739 x = cdr(x); 740 do 741 if (!isNil(a = EVAL(car(x)))) 742 return val(At) = a; 743 while (isCell(x = cdr(x))); 744 return Nil; 745 } 746 747 // (nand 'any ..) -> flg 748 any doNand(any x) { 749 any a; 750 751 x = cdr(x); 752 do { 753 if (isNil(a = EVAL(car(x)))) 754 return T; 755 val(At) = a; 756 } 757 while (isCell(x = cdr(x))); 758 return Nil; 759 } 760 761 // (nor 'any ..) -> flg 762 any doNor(any x) { 763 any a; 764 765 x = cdr(x); 766 do { 767 if (!isNil(a = EVAL(car(x)))) { 768 val(At) = a; 769 return Nil; 770 } 771 } while (isCell(x = cdr(x))); 772 return T; 773 } 774 775 // (xor 'any 'any) -> flg 776 any doXor(any x) { 777 bool f; 778 779 x = cdr(x), f = isNil(EVAL(car(x))), x = cdr(x); 780 return f ^ isNil(EVAL(car(x)))? T : Nil; 781 } 782 783 // (bool 'any) -> flg 784 any doBool(any x) {return isNil(EVAL(cadr(x)))? Nil : T;} 785 786 // (not 'any) -> flg 787 any doNot(any x) {return isNil(EVAL(cadr(x)))? T : Nil;} 788 789 // (nil . prg) -> NIL 790 any doNil(any x) { 791 while (isCell(x = cdr(x))) 792 if (isCell(car(x))) 793 evList(car(x)); 794 return Nil; 795 } 796 797 // (t . prg) -> T 798 any doT(any x) { 799 while (isCell(x = cdr(x))) 800 if (isCell(car(x))) 801 evList(car(x)); 802 return T; 803 } 804 805 // (prog . prg) -> any 806 any doProg(any x) {return prog(cdr(x));} 807 808 // (prog1 'any1 . prg) -> any1 809 any doProg1(any x) { 810 cell c1; 811 812 x = cdr(x), Push(c1, val(At) = EVAL(car(x))); 813 while (isCell(x = cdr(x))) 814 if (isCell(car(x))) 815 evList(car(x)); 816 return Pop(c1); 817 } 818 819 // (prog2 'any1 'any2 . prg) -> any2 820 any doProg2(any x) { 821 cell c1; 822 823 x = cdr(x), EVAL(car(x)); 824 x = cdr(x), Push(c1, val(At) = EVAL(car(x))); 825 while (isCell(x = cdr(x))) 826 if (isCell(car(x))) 827 evList(car(x)); 828 return Pop(c1); 829 } 830 831 // (if 'any1 'any2 . prg) -> any 832 any doIf(any x) { 833 any a; 834 835 x = cdr(x); 836 if (isNil(a = EVAL(car(x)))) 837 return prog(cddr(x)); 838 val(At) = a; 839 x = cdr(x); 840 return EVAL(car(x)); 841 } 842 843 // (if2 'any1 'any2 'any3 'any4 'any5 . prg) -> any 844 any doIf2(any x) { 845 any a; 846 847 x = cdr(x); 848 if (isNil(a = EVAL(car(x)))) { 849 x = cdr(x); 850 if (isNil(a = EVAL(car(x)))) 851 return prog(cddddr(x)); 852 val(At) = a; 853 x = cdddr(x); 854 return EVAL(car(x)); 855 } 856 val(At) = a; 857 x = cdr(x); 858 if (isNil(a = EVAL(car(x)))) { 859 x = cddr(x); 860 return EVAL(car(x)); 861 } 862 val(At) = a; 863 x = cdr(x); 864 return EVAL(car(x)); 865 } 866 867 // (ifn 'any1 'any2 . prg) -> any 868 any doIfn(any x) { 869 any a; 870 871 x = cdr(x); 872 if (!isNil(a = EVAL(car(x)))) { 873 val(At) = a; 874 return prog(cddr(x)); 875 } 876 x = cdr(x); 877 return EVAL(car(x)); 878 } 879 880 // (when 'any . prg) -> any 881 any doWhen(any x) { 882 any a; 883 884 x = cdr(x); 885 if (isNil(a = EVAL(car(x)))) 886 return Nil; 887 val(At) = a; 888 return prog(cdr(x)); 889 } 890 891 // (unless 'any . prg) -> any 892 any doUnless(any x) { 893 any a; 894 895 x = cdr(x); 896 if (!isNil(a = EVAL(car(x)))) { 897 val(At) = a; 898 return Nil; 899 } 900 return prog(cdr(x)); 901 } 902 903 // (cond ('any1 . prg1) ('any2 . prg2) ..) -> any 904 any doCond(any x) { 905 any a; 906 907 while (isCell(x = cdr(x))) { 908 if (!isNil(a = EVAL(caar(x)))) { 909 val(At) = a; 910 return prog(cdar(x)); 911 } 912 } 913 return Nil; 914 } 915 916 // (nond ('any1 . prg1) ('any2 . prg2) ..) -> any 917 any doNond(any x) { 918 any a; 919 920 while (isCell(x = cdr(x))) { 921 if (isNil(a = EVAL(caar(x)))) 922 return prog(cdar(x)); 923 val(At) = a; 924 } 925 return Nil; 926 } 927 928 // (case 'any (any1 . prg1) (any2 . prg2) ..) -> any 929 any doCase(any x) { 930 any y, z; 931 932 x = cdr(x), val(At) = EVAL(car(x)); 933 while (isCell(x = cdr(x))) { 934 y = car(x), z = car(y); 935 if (z == T || equal(val(At), z)) 936 return prog(cdr(y)); 937 if (isCell(z)) { 938 do 939 if (equal(val(At), car(z))) 940 return prog(cdr(y)); 941 while (isCell(z = cdr(z))); 942 } 943 } 944 return Nil; 945 } 946 947 // (state 'var ((sym|lst sym [. prg]) . prg) ..) -> any 948 any doState(any ex) { 949 any x, y, z, a; 950 cell c1; 951 952 x = cdr(ex); 953 Push(c1, EVAL(car(x))); 954 NeedVar(ex,data(c1)); 955 CheckVar(ex,data(c1)); 956 while (isCell(x = cdr(x))) { 957 y = caar(x), z = car(y); 958 if (z==T || z==val(data(c1)) || isCell(z) && memq(val(data(c1)),z)) { 959 y = cdr(y); 960 if (!isCell(cdr(y))) 961 goto st1; 962 if (!isNil(a = prog(cdr(y)))) { 963 val(At) = a; 964 st1: 965 val(data(c1)) = car(y); 966 drop(c1); 967 return prog(cdar(x)); 968 } 969 } 970 } 971 drop(c1); 972 return Nil; 973 } 974 975 // (while 'any . prg) -> any 976 any doWhile(any x) { 977 any cond, a; 978 cell c1; 979 980 cond = car(x = cdr(x)), x = cdr(x); 981 Push(c1, Nil); 982 while (!isNil(a = EVAL(cond))) { 983 val(At) = a; 984 data(c1) = prog(x); 985 } 986 return Pop(c1); 987 } 988 989 // (until 'any . prg) -> any 990 any doUntil(any x) { 991 any cond, a; 992 cell c1; 993 994 cond = car(x = cdr(x)), x = cdr(x); 995 Push(c1, Nil); 996 while (isNil(a = EVAL(cond))) 997 data(c1) = prog(x); 998 val(At) = a; 999 return Pop(c1); 1000 } 1001 1002 // (loop ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any 1003 any doLoop(any ex) { 1004 any x, y, a; 1005 1006 for (;;) { 1007 x = cdr(ex); 1008 do { 1009 if (isCell(y = car(x))) { 1010 if (isNil(car(y))) { 1011 y = cdr(y); 1012 if (isNil(a = EVAL(car(y)))) 1013 return prog(cdr(y)); 1014 val(At) = a; 1015 } 1016 else if (car(y) == T) { 1017 y = cdr(y); 1018 if (!isNil(a = EVAL(car(y)))) { 1019 val(At) = a; 1020 return prog(cdr(y)); 1021 } 1022 } 1023 else 1024 evList(y); 1025 } 1026 } while (isCell(x = cdr(x))); 1027 } 1028 } 1029 1030 // (do 'flg|num ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any 1031 any doDo(any x) { 1032 any f, y, z, a; 1033 1034 x = cdr(x); 1035 if (isNil(f = EVAL(car(x)))) 1036 return Nil; 1037 if (isNum(f) && num(f) < 0) 1038 return Nil; 1039 x = cdr(x), z = Nil; 1040 for (;;) { 1041 if (isNum(f)) { 1042 if (f == Zero) 1043 return z; 1044 f = (any)(num(f) - 4); 1045 } 1046 y = x; 1047 do { 1048 if (!isNum(z = car(y))) { 1049 if (isSym(z)) 1050 z = val(z); 1051 else if (isNil(car(z))) { 1052 z = cdr(z); 1053 if (isNil(a = EVAL(car(z)))) 1054 return prog(cdr(z)); 1055 val(At) = a; 1056 z = Nil; 1057 } 1058 else if (car(z) == T) { 1059 z = cdr(z); 1060 if (!isNil(a = EVAL(car(z)))) { 1061 val(At) = a; 1062 return prog(cdr(z)); 1063 } 1064 z = Nil; 1065 } 1066 else 1067 z = evList(z); 1068 } 1069 } while (isCell(y = cdr(y))); 1070 } 1071 } 1072 1073 // (at '(cnt1 . cnt2) . prg) -> any 1074 any doAt(any ex) { 1075 any x; 1076 1077 x = cdr(ex), x = EVAL(car(x)); 1078 NeedCell(ex,x); 1079 NeedNum(ex,car(x)); 1080 NeedNum(ex,cdr(x)); 1081 if (num(car(x) += 4) < num(cdr(x))) 1082 return Nil; 1083 car(x) = Zero; 1084 return prog(cddr(ex)); 1085 } 1086 1087 // (for sym|(sym2 . sym) 'lst ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any 1088 // (for (sym|(sym2 . sym) 'any1 'any2 [. prg]) ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any 1089 any doFor(any ex) { 1090 any x, y, body, cond, a; 1091 cell c1; 1092 struct { // bindFrame 1093 struct bindFrame *link; 1094 int i, cnt; 1095 struct {any sym; any val;} bnd[2]; 1096 } f; 1097 1098 f.link = Env.bind, Env.bind = (bindFrame*)&f; 1099 f.i = 0; 1100 if (!isCell(y = car(x = cdr(ex))) || !isCell(cdr(y))) { 1101 if (!isCell(y)) { 1102 f.cnt = 1; 1103 f.bnd[0].sym = y; 1104 f.bnd[0].val = val(y); 1105 } 1106 else { 1107 f.cnt = 2; 1108 f.bnd[0].sym = cdr(y); 1109 f.bnd[0].val = val(cdr(y)); 1110 f.bnd[1].sym = car(y); 1111 f.bnd[1].val = val(car(y)); 1112 val(f.bnd[1].sym) = Zero; 1113 } 1114 y = Nil; 1115 x = cdr(x), Push(c1, EVAL(car(x))); 1116 body = x = cdr(x); 1117 while (isCell(data(c1))) { 1118 val(f.bnd[0].sym) = car(data(c1)), data(c1) = cdr(data(c1)); 1119 if (f.cnt == 2) 1120 val(f.bnd[1].sym) = (any)(num(val(f.bnd[1].sym)) + 4); 1121 do { 1122 if (!isNum(y = car(x))) { 1123 if (isSym(y)) 1124 y = val(y); 1125 else if (isNil(car(y))) { 1126 y = cdr(y); 1127 if (isNil(a = EVAL(car(y)))) { 1128 y = prog(cdr(y)); 1129 goto for1; 1130 } 1131 val(At) = a; 1132 y = Nil; 1133 } 1134 else if (car(y) == T) { 1135 y = cdr(y); 1136 if (!isNil(a = EVAL(car(y)))) { 1137 val(At) = a; 1138 y = prog(cdr(y)); 1139 goto for1; 1140 } 1141 y = Nil; 1142 } 1143 else 1144 y = evList(y); 1145 } 1146 } while (isCell(x = cdr(x))); 1147 x = body; 1148 } 1149 for1: 1150 drop(c1); 1151 if (f.cnt == 2) 1152 val(f.bnd[1].sym) = f.bnd[1].val; 1153 val(f.bnd[0].sym) = f.bnd[0].val; 1154 Env.bind = f.link; 1155 return y; 1156 } 1157 if (!isCell(car(y))) { 1158 f.cnt = 1; 1159 f.bnd[0].sym = car(y); 1160 f.bnd[0].val = val(car(y)); 1161 } 1162 else { 1163 f.cnt = 2; 1164 f.bnd[0].sym = cdar(y); 1165 f.bnd[0].val = val(cdar(y)); 1166 f.bnd[1].sym = caar(y); 1167 f.bnd[1].val = val(caar(y)); 1168 val(f.bnd[1].sym) = Zero; 1169 } 1170 y = cdr(y); 1171 val(f.bnd[0].sym) = EVAL(car(y)); 1172 y = cdr(y), cond = car(y), y = cdr(y); 1173 Push(c1,Nil); 1174 body = x = cdr(x); 1175 while (!isNil(a = EVAL(cond))) { 1176 val(At) = a; 1177 if (f.cnt == 2) 1178 val(f.bnd[1].sym) = (any)(num(val(f.bnd[1].sym)) + 4); 1179 do { 1180 if (!isNum(data(c1) = car(x))) { 1181 if (isSym(data(c1))) 1182 data(c1) = val(data(c1)); 1183 else if (isNil(car(data(c1)))) { 1184 data(c1) = cdr(data(c1)); 1185 if (isNil(a = EVAL(car(data(c1))))) { 1186 data(c1) = prog(cdr(data(c1))); 1187 goto for2; 1188 } 1189 val(At) = a; 1190 data(c1) = Nil; 1191 } 1192 else if (car(data(c1)) == T) { 1193 data(c1) = cdr(data(c1)); 1194 if (!isNil(a = EVAL(car(data(c1))))) { 1195 val(At) = a; 1196 data(c1) = prog(cdr(data(c1))); 1197 goto for2; 1198 } 1199 data(c1) = Nil; 1200 } 1201 else 1202 data(c1) = evList(data(c1)); 1203 } 1204 } while (isCell(x = cdr(x))); 1205 if (isCell(y)) 1206 val(f.bnd[0].sym) = prog(y); 1207 x = body; 1208 } 1209 for2: 1210 if (f.cnt == 2) 1211 val(f.bnd[1].sym) = f.bnd[1].val; 1212 val(f.bnd[0].sym) = f.bnd[0].val; 1213 Env.bind = f.link; 1214 return Pop(c1); 1215 } 1216 1217 static any Thrown; 1218 1219 // (catch 'sym . prg) -> any 1220 any doCatch(any ex) { 1221 any x, y; 1222 catchFrame f; 1223 1224 x = cdr(ex), f.tag = EVAL(car(x)); 1225 NeedSymb(ex,f.tag); 1226 f.link = CatchPtr, CatchPtr = &f; 1227 f.env = Env; 1228 y = setjmp(f.rst)? Thrown : prog(cdr(x)); 1229 CatchPtr = f.link; 1230 return y; 1231 } 1232 1233 // (throw 'sym 'any) 1234 any doThrow(any ex) { 1235 any x, tag; 1236 catchFrame *p; 1237 1238 x = cdr(ex), tag = EVAL(car(x)); 1239 x = cdr(x), Thrown = EVAL(car(x)); 1240 for (p = CatchPtr; p; p = p->link) 1241 if (p->tag == T || tag == p->tag) { 1242 unwind(p); 1243 longjmp(p->rst, 1); 1244 } 1245 err(ex, tag, "Tag not found"); 1246 } 1247 1248 // (finally exe . prg) -> any 1249 any doFinally(any x) { 1250 catchFrame f; 1251 cell c1; 1252 1253 x = cdr(x); 1254 f.tag = car(x); 1255 f.link = CatchPtr, CatchPtr = &f; 1256 f.env = Env; 1257 Push(c1, prog(cdr(x))); 1258 EVAL(f.tag); 1259 CatchPtr = f.link; 1260 return Pop(c1); 1261 } 1262 1263 static outFrame Out; 1264 static struct { // bindFrame 1265 struct bindFrame *link; 1266 int i, cnt; 1267 struct {any sym; any val;} bnd[2]; // for 'Up' and 'At' 1268 } Brk; 1269 1270 void brkLoad(any x) { 1271 if (!isNil(val(Dbg)) && !Env.brk) { 1272 Env.brk = YES; 1273 Brk.cnt = 2; 1274 Brk.bnd[0].sym = Up, Brk.bnd[0].val = val(Up), val(Up) = x; 1275 Brk.bnd[1].sym = At, Brk.bnd[1].val = val(At); 1276 Brk.link = Env.bind, Env.bind = (bindFrame*)&Brk; 1277 Out.fp = stdout, pushOutFiles(&Out); 1278 print(x), crlf(); 1279 load(NULL, '!', Nil); 1280 popOutFiles(); 1281 val(At) = Brk.bnd[1].val; 1282 val(Up) = Brk.bnd[0].val; 1283 Env.bind = Brk.link; 1284 Env.brk = NO; 1285 } 1286 } 1287 1288 // (! . prg) -> any 1289 any doBreak(any ex) { 1290 brkLoad(cdr(ex)); 1291 return EVAL(cdr(ex)); 1292 } 1293 1294 // (e . prg) -> any 1295 any doE(any ex) { 1296 any x; 1297 cell c1, at; 1298 1299 if (!Env.brk) 1300 err(ex, NULL, "No Break"); 1301 Push(c1,val(Dbg)), val(Dbg) = Nil; 1302 Push(at, val(At)), val(At) = Brk.bnd[1].val; 1303 if (Env.inFiles && Env.inFiles->link) 1304 Chr = Env.inFiles->next, Env.get = Env.inFiles->get, InFile = Env.inFiles->link->fp; 1305 popOutFiles(); 1306 x = isCell(cdr(ex))? prog(cdr(ex)) : EVAL(val(Up)); 1307 pushOutFiles(&Out); 1308 if (Env.inFiles && Env.inFiles->link) 1309 Env.inFiles->next = Chr, Chr = 0; 1310 InFile = stdin, OutFile = stdout; 1311 val(At) = data(at); 1312 val(Dbg) = Pop(c1); 1313 return x; 1314 } 1315 1316 static void traceIndent(int i, any x, char *s) { 1317 if (i > 64) 1318 i = 64; 1319 while (--i >= 0) 1320 Env.put(' '); 1321 if (!isCell(x)) 1322 print(x); 1323 else 1324 print(car(x)), space(), print(cdr(x)), space(), print(val(This)); 1325 outString(s); 1326 } 1327 1328 static void traceSym(any x) { 1329 if (x != At) 1330 space(), print(val(x)); 1331 else { 1332 int i = Env.next; 1333 1334 while (--i >= 0) 1335 space(), print(data(Env.arg[i])); 1336 } 1337 } 1338 1339 // ($ sym|lst lst . prg) -> any 1340 any doTrace(any x) { 1341 any foo, body; 1342 FILE *oSave; 1343 void (*putSave)(int); 1344 cell c1; 1345 1346 if (isNil(val(Dbg))) 1347 return prog(cdddr(x)); 1348 oSave = OutFile, OutFile = stderr; 1349 putSave = Env.put, Env.put = putStdout; 1350 x = cdr(x), foo = car(x); 1351 x = cdr(x), body = cdr(x); 1352 traceIndent(++Trace, foo, " :"); 1353 for (x = car(x); isCell(x); x = cdr(x)) 1354 traceSym(car(x)); 1355 if (!isNil(x) && !isNum(x)) 1356 traceSym(x); 1357 crlf(); 1358 Env.put = putSave; 1359 OutFile = oSave; 1360 Push(c1, prog(body)); 1361 OutFile = stderr; 1362 Env.put = putStdout; 1363 traceIndent(Trace--, foo, " = "), print(data(c1)), crlf(); 1364 Env.put = putSave; 1365 OutFile = oSave; 1366 return Pop(c1); 1367 } 1368 1369 // (bye 'num|NIL) 1370 any doBye(any ex) { 1371 any x = EVAL(cadr(ex)); 1372 1373 bye(isNil(x)? 0 : xNum(ex,x)); 1374 }