picolisp

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

subr.c (37844B)


      1 /* 22jul13abu
      2  * (c) Software Lab. Alexander Burger
      3  */
      4 
      5 #include "pico.h"
      6 
      7 // (car 'var) -> any
      8 any doCar(any ex) {
      9    any x = cdr(ex);
     10    x = EVAL(car(x));
     11    NeedVar(ex,x);
     12    return car(x);
     13 }
     14 
     15 // (cdr 'lst) -> any
     16 any doCdr(any ex) {
     17    any x = cdr(ex);
     18    x = EVAL(car(x));
     19    NeedLst(ex,x);
     20    return cdr(x);
     21 }
     22 
     23 any doCaar(any ex) {
     24    any x = cdr(ex);
     25    x = EVAL(car(x));
     26    NeedVar(ex,x);
     27    return caar(x);
     28 }
     29 
     30 any doCadr(any ex) {
     31    any x = cdr(ex);
     32    x = EVAL(car(x));
     33    NeedLst(ex,x);
     34    return cadr(x);
     35 }
     36 
     37 any doCdar(any ex) {
     38    any x = cdr(ex);
     39    x = EVAL(car(x));
     40    NeedVar(ex,x);
     41    return cdar(x);
     42 }
     43 
     44 any doCddr(any ex) {
     45    any x = cdr(ex);
     46    x = EVAL(car(x));
     47    NeedLst(ex,x);
     48    return cddr(x);
     49 }
     50 
     51 any doCaaar(any ex) {
     52    any x = cdr(ex);
     53    x = EVAL(car(x));
     54    NeedVar(ex,x);
     55    return caaar(x);
     56 }
     57 
     58 any doCaadr(any ex) {
     59    any x = cdr(ex);
     60    x = EVAL(car(x));
     61    NeedLst(ex,x);
     62    return caadr(x);
     63 }
     64 
     65 any doCadar(any ex) {
     66    any x = cdr(ex);
     67    x = EVAL(car(x));
     68    NeedVar(ex,x);
     69    return cadar(x);
     70 }
     71 
     72 any doCaddr(any ex) {
     73    any x = cdr(ex);
     74    x = EVAL(car(x));
     75    NeedLst(ex,x);
     76    return caddr(x);
     77 }
     78 
     79 any doCdaar(any ex) {
     80    any x = cdr(ex);
     81    x = EVAL(car(x));
     82    NeedVar(ex,x);
     83    return cdaar(x);
     84 }
     85 
     86 any doCdadr(any ex) {
     87    any x = cdr(ex);
     88    x = EVAL(car(x));
     89    NeedLst(ex,x);
     90    return cdadr(x);
     91 }
     92 
     93 any doCddar(any ex) {
     94    any x = cdr(ex);
     95    x = EVAL(car(x));
     96    NeedVar(ex,x);
     97    return cddar(x);
     98 }
     99 
    100 any doCdddr(any ex) {
    101    any x = cdr(ex);
    102    x = EVAL(car(x));
    103    NeedLst(ex,x);
    104    return cdddr(x);
    105 }
    106 
    107 any doCaaaar(any ex) {
    108    any x = cdr(ex);
    109    x = EVAL(car(x));
    110    NeedVar(ex,x);
    111    return caaaar(x);
    112 }
    113 
    114 any doCaaadr(any ex) {
    115    any x = cdr(ex);
    116    x = EVAL(car(x));
    117    NeedLst(ex,x);
    118    return caaadr(x);
    119 }
    120 
    121 any doCaadar(any ex) {
    122    any x = cdr(ex);
    123    x = EVAL(car(x));
    124    NeedVar(ex,x);
    125    return caadar(x);
    126 }
    127 
    128 any doCaaddr(any ex) {
    129    any x = cdr(ex);
    130    x = EVAL(car(x));
    131    NeedLst(ex,x);
    132    return caaddr(x);
    133 }
    134 
    135 any doCadaar(any ex) {
    136    any x = cdr(ex);
    137    x = EVAL(car(x));
    138    NeedVar(ex,x);
    139    return cadaar(x);
    140 }
    141 
    142 any doCadadr(any ex) {
    143    any x = cdr(ex);
    144    x = EVAL(car(x));
    145    NeedLst(ex,x);
    146    return cadadr(x);
    147 }
    148 
    149 any doCaddar(any ex) {
    150    any x = cdr(ex);
    151    x = EVAL(car(x));
    152    NeedVar(ex,x);
    153    return caddar(x);
    154 }
    155 
    156 any doCadddr(any ex) {
    157    any x = cdr(ex);
    158    x = EVAL(car(x));
    159    NeedLst(ex,x);
    160    return cadddr(x);
    161 }
    162 
    163 any doCdaaar(any ex) {
    164    any x = cdr(ex);
    165    x = EVAL(car(x));
    166    NeedVar(ex,x);
    167    return cdaaar(x);
    168 }
    169 
    170 any doCdaadr(any ex) {
    171    any x = cdr(ex);
    172    x = EVAL(car(x));
    173    NeedLst(ex,x);
    174    return cdaadr(x);
    175 }
    176 
    177 any doCdadar(any ex) {
    178    any x = cdr(ex);
    179    x = EVAL(car(x));
    180    NeedVar(ex,x);
    181    return cdadar(x);
    182 }
    183 
    184 any doCdaddr(any ex) {
    185    any x = cdr(ex);
    186    x = EVAL(car(x));
    187    NeedLst(ex,x);
    188    return cdaddr(x);
    189 }
    190 
    191 any doCddaar(any ex) {
    192    any x = cdr(ex);
    193    x = EVAL(car(x));
    194    NeedVar(ex,x);
    195    return cddaar(x);
    196 }
    197 
    198 any doCddadr(any ex) {
    199    any x = cdr(ex);
    200    x = EVAL(car(x));
    201    NeedLst(ex,x);
    202    return cddadr(x);
    203 }
    204 
    205 any doCdddar(any ex) {
    206    any x = cdr(ex);
    207    x = EVAL(car(x));
    208    NeedVar(ex,x);
    209    return cdddar(x);
    210 }
    211 
    212 any doCddddr(any ex) {
    213    any x = cdr(ex);
    214    x = EVAL(car(x));
    215    NeedLst(ex,x);
    216    return cddddr(x);
    217 }
    218 
    219 // (nth 'lst 'cnt ..) -> lst
    220 any doNth(any ex) {
    221    any x;
    222    cell c1;
    223 
    224    x = cdr(ex),  Push(c1, EVAL(car(x))),  x = cdr(x);
    225    for (;;) {
    226       if (!isCell(data(c1)))
    227          return Pop(c1);
    228       data(c1) = nth((int)evCnt(ex,x), data(c1));
    229       if (!isCell(x = cdr(x)))
    230          return Pop(c1);
    231       data(c1) = car(data(c1));
    232    }
    233 }
    234 
    235 // (con 'lst 'any) -> any
    236 any doCon(any ex) {
    237    any x;
    238    cell c1;
    239 
    240    x = cdr(ex),  Push(c1, EVAL(car(x)));
    241    NeedPair(ex,data(c1));
    242    x = cdr(x),  x = cdr(data(c1)) = EVAL(car(x));
    243    drop(c1);
    244    return x;
    245 }
    246 
    247 // (cons 'any ['any ..]) -> lst
    248 any doCons(any x) {
    249    any y;
    250    cell c1;
    251 
    252    x = cdr(x);
    253    Push(c1, y = cons(EVAL(car(x)),Nil));
    254    while (isCell(cdr(x = cdr(x))))
    255       y = cdr(y) = cons(EVAL(car(x)),Nil);
    256    cdr(y) = EVAL(car(x));
    257    return Pop(c1);
    258 }
    259 
    260 // (conc 'lst ..) -> lst
    261 any doConc(any x) {
    262    any y, z;
    263    cell c1;
    264 
    265    x = cdr(x),  Push(c1, y = EVAL(car(x)));
    266    while (isCell(x = cdr(x))) {
    267       z = EVAL(car(x));
    268       if (!isCell(y))
    269          y = data(c1) = z;
    270       else {
    271          while (isCell(cdr(y)))
    272             y = cdr(y);
    273          cdr(y) = z;
    274       }
    275    }
    276    return Pop(c1);
    277 }
    278 
    279 // (circ 'any ..) -> lst
    280 any doCirc(any x) {
    281    any y;
    282    cell c1;
    283 
    284    x = cdr(x);
    285    Push(c1, y = cons(EVAL(car(x)),Nil));
    286    while (isCell(x = cdr(x)))
    287       y = cdr(y) = cons(EVAL(car(x)),Nil);
    288    cdr(y) = data(c1);
    289    return Pop(c1);
    290 }
    291 
    292 // (rot 'lst ['cnt]) -> lst
    293 any doRot(any ex) {
    294    any x, y, z;
    295    int n;
    296    cell c1;
    297 
    298    x = cdr(ex),  Push(c1, y = EVAL(car(x)));
    299    if (isCell(y)) {
    300       n = isCell(x = cdr(x))? (int)evCnt(ex,x) : 0;
    301       x = car(y);
    302       while (--n  &&  isCell(y = cdr(y))  &&  y != data(c1))
    303          z = car(y),  car(y) = x,  x = z;
    304       car(data(c1)) = x;
    305    }
    306    return Pop(c1);
    307 }
    308 
    309 // (list 'any ['any ..]) -> lst
    310 any doList(any x) {
    311    any y;
    312    cell c1;
    313 
    314    x = cdr(x);
    315    Push(c1, y = cons(EVAL(car(x)),Nil));
    316    while (isCell(x = cdr(x)))
    317       y = cdr(y) = cons(EVAL(car(x)),Nil);
    318    return Pop(c1);
    319 }
    320 
    321 // (need 'cnt ['lst ['any]]) -> lst
    322 // (need 'cnt ['num|sym]) -> lst
    323 any doNeed(any ex) {
    324    int n;
    325    any x;
    326    cell c1, c2;
    327 
    328    n = (int)evCnt(ex, x = cdr(ex));
    329    x = cdr(x),  Push(c1, EVAL(car(x)));
    330    if (isCell(data(c1)) || isNil(data(c1)))
    331       Push(c2, EVAL(cadr(x)));
    332    else {
    333       Push(c2, data(c1));
    334       data(c1) = Nil;
    335    }
    336    x = data(c1);
    337    if (n > 0)
    338       for (n -= length(x); n > 0; --n)
    339          data(c1) = cons(data(c2), data(c1));
    340    else if (n) {
    341       if (!isCell(x))
    342          data(c1) = x = cons(data(c2),Nil);
    343       else
    344          while (isCell(cdr(x)))
    345             ++n,  x = cdr(x);
    346       while (++n < 0)
    347          x = cdr(x) = cons(data(c2),Nil);
    348    }
    349    return Pop(c1);
    350 }
    351 
    352 // (range 'num1 'num2 ['num3]) -> lst
    353 any doRange(any ex) {
    354    any x;
    355    cell c1, c2, c3, c4;
    356 
    357    x = cdr(ex),  Push(c1, EVAL(car(x)));  // Start value
    358    NeedNum(ex,data(c1));
    359    x = cdr(x),  Push(c2, EVAL(car(x)));  // End value
    360    NeedNum(ex,data(c2));
    361    x = cdr(x),  Push(c3, One);  // Increment
    362    if (!isNil(x = EVAL(car(x)))) {
    363       NeedNum(ex, data(c3) = x);
    364       if (IsZero(x) || isNeg(x))
    365          argError(ex,x);
    366    }
    367    Push(c4, x = cons(data(c1), Nil));
    368    if (bigCompare(data(c2), data(c1)) >= 0) {
    369       for (;;) {
    370          data(c1) = bigCopy(data(c1));
    371          if (!isNeg(data(c1)))
    372             bigAdd(data(c1), data(c3));
    373          else {
    374             bigSub(data(c1), data(c3));
    375             if (!IsZero(data(c1)))
    376                neg(data(c1));
    377          }
    378          if (bigCompare(data(c2), data(c1)) < 0)
    379             break;
    380          x = cdr(x) = cons(data(c1), Nil);
    381       }
    382    }
    383    else {
    384       for (;;) {
    385          data(c1) = bigCopy(data(c1));
    386          if (!isNeg(data(c1)))
    387             bigSub(data(c1), data(c3));
    388          else {
    389             bigAdd(data(c1), data(c3));
    390             if (!IsZero(data(c1)))
    391                neg(data(c1));
    392          }
    393          if (bigCompare(data(c2), data(c1)) > 0)
    394             break;
    395          x = cdr(x) = cons(data(c1),Nil);
    396       }
    397    }
    398    drop(c1);
    399    return data(c4);
    400 }
    401 
    402 // (full 'any) -> bool
    403 any doFull(any x) {
    404    x = cdr(x);
    405    for (x = EVAL(car(x)); isCell(x); x = cdr(x))
    406       if (isNil(car(x)))
    407          return Nil;
    408    return T;
    409 }
    410 
    411 // (make .. [(made 'lst ..)] .. [(link 'any ..)] ..) -> any
    412 any doMake(any x) {
    413    any *make, *yoke;
    414    cell c1;
    415 
    416    Push(c1, Nil);
    417    make = Env.make;
    418    yoke = Env.yoke;
    419    Env.make = Env.yoke = &data(c1);
    420    while (isCell(x = cdr(x)))
    421       if (isCell(car(x)))
    422          evList(car(x));
    423    Env.yoke = yoke;
    424    Env.make = make;
    425    return Pop(c1);
    426 }
    427 
    428 static void makeError(any ex) {err(ex, NULL, "Not making");}
    429 
    430 // (made ['lst1 ['lst2]]) -> lst
    431 any doMade(any x) {
    432    if (!Env.make)
    433       makeError(x);
    434    if (isCell(x = cdr(x))) {
    435       *Env.yoke = EVAL(car(x));
    436       if (x = cdr(x), !isCell(x = EVAL(car(x)))) {
    437          any y;
    438 
    439          x = *Env.yoke;
    440          while (isCell(y = cdr(x)))
    441             x = y;
    442       }
    443       Env.make = &cdr(x);
    444    }
    445    return *Env.yoke;
    446 }
    447 
    448 // (chain 'lst ..) -> lst
    449 any doChain(any x) {
    450    any y;
    451 
    452    if (!Env.make)
    453       makeError(x);
    454    x = cdr(x);
    455    do
    456       if (isCell(*Env.make = y = EVAL(car(x))))
    457          do
    458             Env.make = &cdr(*Env.make);
    459          while (isCell(*Env.make));
    460    while (isCell(x = cdr(x)));
    461    return y;
    462 }
    463 
    464 // (link 'any ..) -> any
    465 any doLink(any x) {
    466    any y;
    467 
    468    if (!Env.make)
    469       makeError(x);
    470    x = cdr(x);
    471    do {
    472       y = EVAL(car(x));
    473       Env.make = &cdr(*Env.make = cons(y, Nil));
    474    } while (isCell(x = cdr(x)));
    475    return y;
    476 }
    477 
    478 // (yoke 'any ..) -> any
    479 any doYoke(any x) {
    480    any y;
    481 
    482    if (!Env.make)
    483       makeError(x);
    484    x = cdr(x);
    485    do {
    486       y = EVAL(car(x));
    487       *Env.yoke = cons(y, *Env.yoke);
    488    } while (isCell(x = cdr(x)));
    489    while (isCell(*Env.make))
    490       Env.make = &cdr(*Env.make);
    491    return y;
    492 }
    493 
    494 // (copy 'any) -> any
    495 any doCopy(any x) {
    496    any y, z;
    497    cell c1;
    498 
    499    x = cdr(x);
    500    if (!isCell(x = EVAL(car(x))))
    501       return x;
    502    Push(c1, y = cons(car(x), cdr(z = x)));
    503    while (isCell(x = cdr(y))) {
    504       if (x == z) {
    505          cdr(y) = data(c1);
    506          break;
    507       }
    508       y = cdr(y) = cons(car(x), cdr(x));
    509    }
    510    return Pop(c1);
    511 }
    512 
    513 // (mix 'lst cnt|'any ..) -> lst
    514 any doMix(any x) {
    515    any y;
    516    cell c1, c2;
    517 
    518    x = cdr(x);
    519    if (!isCell(data(c1) = EVAL(car(x))) && !isNil(data(c1)))
    520       return data(c1);
    521    if (!isCell(x = cdr(x)))
    522       return Nil;
    523    Save(c1);
    524    Push(c2,
    525       y = cons(
    526          isNum(car(x))? car(nth((int)unBox(car(x)),data(c1))) : EVAL(car(x)),
    527          Nil ) );
    528    while (isCell(x = cdr(x)))
    529       y = cdr(y) = cons(
    530          isNum(car(x))? car(nth((int)unBox(car(x)),data(c1))) : EVAL(car(x)),
    531          Nil );
    532    drop(c1);
    533    return data(c2);
    534 }
    535 
    536 // (append 'lst ..) -> lst
    537 any doAppend(any x) {
    538    any y, z;
    539    cell c1;
    540 
    541    while (isCell(cdr(x = cdr(x)))) {
    542       if (isCell(y = EVAL(car(x)))) {
    543          Push(c1, z = cons(car(y), cdr(y)));
    544          while (isCell(y = cdr(z)))
    545             z = cdr(z) = cons(car(y), cdr(y));
    546          while (isCell(cdr(x = cdr(x)))) {
    547             for (y = EVAL(car(x)); isCell(y); y = cdr(z))
    548                z = cdr(z) = cons(car(y), cdr(y));
    549             cdr(z) = y;
    550          }
    551          cdr(z) = EVAL(car(x));
    552          return Pop(c1);
    553       }
    554    }
    555    return EVAL(car(x));
    556 }
    557 
    558 // (delete 'any 'lst) -> lst
    559 any doDelete(any x) {
    560    any y, z;
    561    cell c1, c2, c3;
    562 
    563    x = cdr(x),  Push(c1, y = EVAL(car(x)));
    564    x = cdr(x);
    565    if (!isCell(x = EVAL(car(x)))) {
    566       drop(c1);
    567       return x;
    568    }
    569    if (equal(y, car(x))) {
    570       drop(c1);
    571       return cdr(x);
    572    }
    573    Push(c2, x);
    574    Push(c3, z = cons(car(x), Nil));
    575    while (isCell(x = cdr(x))) {
    576       if (equal(y, car(x))) {
    577          cdr(z) = cdr(x);
    578          drop(c1);
    579          return data(c3);
    580       }
    581       z = cdr(z) = cons(car(x), Nil);
    582    }
    583    cdr(z) = x;
    584    drop(c1);
    585    return data(c3);
    586 }
    587 
    588 // (delq 'any 'lst) -> lst
    589 any doDelq(any x) {
    590    any y, z;
    591    cell c1, c2, c3;
    592 
    593    x = cdr(x),  Push(c1, y = EVAL(car(x)));
    594    x = cdr(x);
    595    if (!isCell(x = EVAL(car(x)))) {
    596       drop(c1);
    597       return x;
    598    }
    599    if (y == car(x)) {
    600       drop(c1);
    601       return cdr(x);
    602    }
    603    Push(c2, x);
    604    Push(c3, z = cons(car(x), Nil));
    605    while (isCell(x = cdr(x))) {
    606       if (y == car(x)) {
    607          cdr(z) = cdr(x);
    608          drop(c1);
    609          return data(c3);
    610       }
    611       z = cdr(z) = cons(car(x), Nil);
    612    }
    613    cdr(z) = x;
    614    drop(c1);
    615    return data(c3);
    616 }
    617 
    618 // (replace 'lst 'any1 'any2 ..) -> lst
    619 any doReplace(any x) {
    620    any y;
    621    int i, n = length(cdr(x = cdr(x))) + 1 & ~1;
    622    cell c1, c2, c[n];
    623 
    624    if (!isCell(data(c1) = EVAL(car(x))))
    625       return data(c1);
    626    Save(c1);
    627    for (i = 0; i < n; ++i)
    628       x = cdr(x),  Push(c[i], EVAL(car(x)));
    629    for (x = car(data(c1)), i = 0;  i < n;  i += 2)
    630       if (equal(x, data(c[i]))) {
    631          x = data(c[i+1]);
    632          break;
    633       }
    634    Push(c2, y = cons(x,Nil));
    635    while (isCell(data(c1) = cdr(data(c1)))) {
    636       for (x = car(data(c1)), i = 0;  i < n;  i += 2)
    637          if (equal(x, data(c[i]))) {
    638             x = data(c[i+1]);
    639             break;
    640          }
    641       y = cdr(y) = cons(x, Nil);
    642    }
    643    cdr(y) = data(c1);
    644    drop(c1);
    645    return data(c2);
    646 }
    647 
    648 // (strip 'any) -> any
    649 any doStrip(any x) {
    650    x = cdr(x),  x = EVAL(car(x));
    651    while (isCell(x)  &&  car(x) == Quote  && x != cdr(x))
    652       x = cdr(x);
    653    return x;
    654 }
    655 
    656 // (split 'lst 'any ..) -> lst
    657 any doSplit(any x) {
    658    any y;
    659    int i, n = length(cdr(x = cdr(x)));
    660    cell c1, c[n], res, sub;
    661 
    662    if (!isCell(data(c1) = EVAL(car(x))))
    663       return data(c1);
    664    Save(c1);
    665    for (i = 0; i < n; ++i)
    666       x = cdr(x),  Push(c[i], EVAL(car(x)));
    667    Push(res, x = Nil);
    668    Push(sub, y = Nil);
    669    do {
    670       for (i = 0;  i < n;  ++i) {
    671          if (equal(car(data(c1)), data(c[i]))) {
    672             if (isNil(x))
    673                x = data(res) = cons(data(sub), Nil);
    674             else
    675                x = cdr(x) = cons(data(sub), Nil);
    676             y = data(sub) = Nil;
    677             goto spl1;
    678          }
    679       }
    680       if (isNil(y))
    681          y = data(sub) = cons(car(data(c1)), Nil);
    682       else
    683          y = cdr(y) = cons(car(data(c1)), Nil);
    684 spl1: ;
    685    } while (isCell(data(c1) = cdr(data(c1))));
    686    y = cons(data(sub), Nil);
    687    drop(c1);
    688    if (isNil(x))
    689       return y;
    690    cdr(x) = y;
    691    return data(res);
    692 }
    693 
    694 // (reverse 'lst) -> lst
    695 any doReverse(any x) {
    696    any y;
    697    cell c1;
    698 
    699    x = cdr(x),  Push(c1, x = EVAL(car(x)));
    700    for (y = Nil; isCell(x); x = cdr(x))
    701       y = cons(car(x), y);
    702    drop(c1);
    703    return y;
    704 }
    705 
    706 // (flip 'lst ['cnt])) -> lst
    707 any doFlip(any ex) {
    708    any x, y, z;
    709    int n;
    710    cell c1;
    711 
    712    x = cdr(ex);
    713    if (!isCell(y = EVAL(car(x))) || !isCell(z = cdr(y)))
    714       return y;
    715    if (!isCell(x = cdr(x))) {
    716       cdr(y) = Nil;
    717       for (;;) {
    718          x = cdr(z),  cdr(z) = y;
    719          if (!isCell(x))
    720             return z;
    721          y = z,  z = x;
    722       }
    723    }
    724    Push(c1, y);
    725    n = (int)evCnt(ex,x) - 1;
    726    drop(c1);
    727    if (n <= 0)
    728       return y;
    729    cdr(y) = cdr(z),  cdr(z) = y;
    730    while (--n && isCell(x = cdr(y)))
    731       cdr(y) = cdr(x),  cdr(x) = z,  z = x;
    732    return z;
    733 }
    734 
    735 static any trim(any x) {
    736    any y;
    737 
    738    if (!isCell(x))
    739       return x;
    740    if (isNil(y = trim(cdr(x))) && isBlank(car(x)))
    741       return Nil;
    742    return cons(car(x),y);
    743 }
    744 
    745 // (trim 'lst) -> lst
    746 any doTrim(any x) {
    747    cell c1;
    748 
    749    x = cdr(x),  Push(c1, EVAL(car(x)));
    750    x = trim(data(c1));
    751    drop(c1);
    752    return x;
    753 }
    754 
    755 // (clip 'lst) -> lst
    756 any doClip(any x) {
    757    cell c1;
    758 
    759    x = cdr(x),  Push(c1, EVAL(car(x)));
    760    while (isCell(data(c1)) && isBlank(car(data(c1))))
    761       data(c1) = cdr(data(c1));
    762    x = trim(data(c1));
    763    drop(c1);
    764    return x;
    765 }
    766 
    767 // (head 'cnt|lst 'lst) -> lst
    768 any doHead(any ex) {
    769    long n;
    770    any x, y;
    771    cell c1, c2;
    772 
    773    x = cdr(ex);
    774    if (isNil(data(c1) = EVAL(car(x))))
    775       return Nil;
    776    x = cdr(x);
    777    if (isCell(data(c1))) {
    778       Save(c1);
    779       if (isCell(x = EVAL(car(x)))) {
    780          for (y = data(c1);  equal(car(y), car(x));  x = cdr(x))
    781             if (!isCell(y = cdr(y)))
    782                return Pop(c1);
    783       }
    784       drop(c1);
    785       return Nil;
    786    }
    787    if ((n = xCnt(ex,data(c1))) == 0)
    788       return Nil;
    789    if (!isCell(x = EVAL(car(x))))
    790       return x;
    791    if (n < 0  &&  (n += length(x)) <= 0)
    792       return Nil;
    793    Push(c1,x);
    794    Push(c2, x = cons(car(data(c1)), Nil));
    795    while (--n  &&  isCell(data(c1) = cdr(data(c1))))
    796       x = cdr(x) = cons(car(data(c1)), Nil);
    797    drop(c1);
    798    return data(c2);
    799 }
    800 
    801 // (tail 'cnt|lst 'lst) -> lst
    802 any doTail(any ex) {
    803    long n;
    804    any x, y;
    805    cell c1;
    806 
    807    x = cdr(ex);
    808    if (isNil(data(c1) = EVAL(car(x))))
    809       return Nil;
    810    x = cdr(x);
    811    if (isCell(data(c1))) {
    812       Save(c1);
    813       if (isCell(x = EVAL(car(x)))) {
    814          do
    815             if (equal(x,data(c1)))
    816                return Pop(c1);
    817          while (isCell(x = cdr(x)));
    818       }
    819       drop(c1);
    820       return Nil;
    821    }
    822    if ((n = xCnt(ex,data(c1))) == 0)
    823       return Nil;
    824    if (!isCell(x = EVAL(car(x))))
    825       return x;
    826    if (n < 0)
    827       return nth(1 - n, x);
    828    for (y = cdr(x);  --n;  y = cdr(y))
    829       if (!isCell(y))
    830          return x;
    831    while (isCell(y))
    832       x = cdr(x),  y = cdr(y);
    833    return x;
    834 }
    835 
    836 // (stem 'lst 'any ..) -> lst
    837 any doStem(any x) {
    838    int i, n = length(cdr(x = cdr(x)));
    839    cell c1, c[n];
    840 
    841    Push(c1, EVAL(car(x)));
    842    for (i = 0; i < n; ++i)
    843       x = cdr(x),  Push(c[i], EVAL(car(x)));
    844    for (x = data(c1); isCell(x); x = cdr(x)) {
    845       for (i = 0;  i < n;  ++i)
    846          if (equal(car(x), data(c[i]))) {
    847             data(c1) = cdr(x);
    848             break;
    849          }
    850    }
    851    return Pop(c1);
    852 }
    853 
    854 // (fin 'any) -> num|sym
    855 any doFin(any x) {
    856    x = cdr(x),  x = EVAL(car(x));
    857    while (isCell(x))
    858       x = cdr(x);
    859    return x;
    860 }
    861 
    862 // (last 'lst) -> any
    863 any doLast(any x) {
    864    x = cdr(x),  x = EVAL(car(x));
    865    if (!isCell(x))
    866       return x;
    867    while (isCell(cdr(x)))
    868       x = cdr(x);
    869    return car(x);
    870 }
    871 
    872 // (== 'any ..) -> flg
    873 any doEq(any x) {
    874    cell c1;
    875 
    876    x = cdr(x),  Push(c1, EVAL(car(x)));
    877    while (isCell(x = cdr(x)))
    878       if (data(c1) != EVAL(car(x))) {
    879          drop(c1);
    880          return Nil;
    881       }
    882    drop(c1);
    883    return T;
    884 }
    885 
    886 // (n== 'any ..) -> flg
    887 any doNEq(any x) {
    888    cell c1;
    889 
    890    x = cdr(x),  Push(c1, EVAL(car(x)));
    891    while (isCell(x = cdr(x)))
    892       if (data(c1) != EVAL(car(x))) {
    893          drop(c1);
    894          return T;
    895       }
    896    drop(c1);
    897    return Nil;
    898 }
    899 
    900 // (= 'any ..) -> flg
    901 any doEqual(any x) {
    902    cell c1;
    903 
    904    x = cdr(x),  Push(c1, EVAL(car(x)));
    905    while (isCell(x = cdr(x)))
    906       if (!equal(data(c1), EVAL(car(x)))) {
    907          drop(c1);
    908          return Nil;
    909       }
    910    drop(c1);
    911    return T;
    912 }
    913 
    914 // (<> 'any ..) -> flg
    915 any doNEqual(any x) {
    916    cell c1;
    917 
    918    x = cdr(x),  Push(c1, EVAL(car(x)));
    919    while (isCell(x = cdr(x)))
    920       if (!equal(data(c1), EVAL(car(x)))) {
    921          drop(c1);
    922          return T;
    923       }
    924    drop(c1);
    925    return Nil;
    926 }
    927 
    928 // (=0 'any) -> 0 | NIL
    929 any doEq0(any x) {
    930    x = cdr(x);
    931    return isNum(x = EVAL(car(x))) && IsZero(x)? x : Nil;
    932 }
    933 
    934 // (=T 'any) -> flg
    935 any doEqT(any x) {
    936    x = cdr(x);
    937    return T == EVAL(car(x))? T : Nil;
    938 }
    939 
    940 // (n0 'any) -> flg
    941 any doNEq0(any x) {
    942    x = cdr(x);
    943    return isNum(x = EVAL(car(x))) && IsZero(x)? Nil : T;
    944 }
    945 
    946 // (nT 'any) -> flg
    947 any doNEqT(any x) {
    948    x = cdr(x);
    949    return T == EVAL(car(x))? Nil : T;
    950 }
    951 
    952 // (< 'any ..) -> flg
    953 any doLt(any x) {
    954    any y;
    955    cell c1;
    956 
    957    x = cdr(x),  Push(c1, EVAL(car(x)));
    958    while (isCell(x = cdr(x))) {
    959       y = EVAL(car(x));
    960       if (compare(data(c1), y) >= 0) {
    961          drop(c1);
    962          return Nil;
    963       }
    964       data(c1) = y;
    965    }
    966    drop(c1);
    967    return T;
    968 }
    969 
    970 // (<= 'any ..) -> flg
    971 any doLe(any x) {
    972    any y;
    973    cell c1;
    974 
    975    x = cdr(x),  Push(c1, EVAL(car(x)));
    976    while (isCell(x = cdr(x))) {
    977       y = EVAL(car(x));
    978       if (compare(data(c1), y) > 0) {
    979          drop(c1);
    980          return Nil;
    981       }
    982       data(c1) = y;
    983    }
    984    drop(c1);
    985    return T;
    986 }
    987 
    988 // (> 'any ..) -> flg
    989 any doGt(any x) {
    990    any y;
    991    cell c1;
    992 
    993    x = cdr(x),  Push(c1, EVAL(car(x)));
    994    while (isCell(x = cdr(x))) {
    995       y = EVAL(car(x));
    996       if (compare(data(c1), y) <= 0) {
    997          drop(c1);
    998          return Nil;
    999       }
   1000       data(c1) = y;
   1001    }
   1002    drop(c1);
   1003    return T;
   1004 }
   1005 
   1006 // (>= 'any ..) -> flg
   1007 any doGe(any x) {
   1008    any y;
   1009    cell c1;
   1010 
   1011    x = cdr(x),  Push(c1, EVAL(car(x)));
   1012    while (isCell(x = cdr(x))) {
   1013       y = EVAL(car(x));
   1014       if (compare(data(c1), y) < 0) {
   1015          drop(c1);
   1016          return Nil;
   1017       }
   1018       data(c1) = y;
   1019    }
   1020    drop(c1);
   1021    return T;
   1022 }
   1023 
   1024 // (max 'any ..) -> any
   1025 any doMax(any x) {
   1026    any y;
   1027    cell c1;
   1028 
   1029    x = cdr(x),  Push(c1, EVAL(car(x)));
   1030    while (isCell(x = cdr(x)))
   1031       if (compare(y = EVAL(car(x)), data(c1)) > 0)
   1032          data(c1) = y;
   1033    return Pop(c1);
   1034 }
   1035 
   1036 // (min 'any ..) -> any
   1037 any doMin(any x) {
   1038    any y;
   1039    cell c1;
   1040 
   1041    x = cdr(x),  Push(c1, EVAL(car(x)));
   1042    while (isCell(x = cdr(x)))
   1043       if (compare(y = EVAL(car(x)), data(c1)) < 0)
   1044          data(c1) = y;
   1045    return Pop(c1);
   1046 }
   1047 
   1048 // (atom 'any) -> flg
   1049 any doAtom(any x) {
   1050    x = cdr(x);
   1051    return !isCell(EVAL(car(x)))? T : Nil;
   1052 }
   1053 
   1054 // (pair 'any) -> any
   1055 any doPair(any x) {
   1056    x = cdr(x);
   1057    return isCell(x = EVAL(car(x)))? x : Nil;
   1058 }
   1059 
   1060 // (circ? 'any) -> any
   1061 any doCircQ(any x) {
   1062    x = cdr(x);
   1063    return isCell(x = EVAL(car(x))) && (x = circ(x))? x : Nil;
   1064 }
   1065 
   1066 // (lst? 'any) -> flg
   1067 any doLstQ(any x) {
   1068    x = cdr(x);
   1069    return isCell(x = EVAL(car(x))) || isNil(x)? T : Nil;
   1070 }
   1071 
   1072 // (num? 'any) -> num | NIL
   1073 any doNumQ(any x) {
   1074    x = cdr(x);
   1075    return isNum(x = EVAL(car(x)))? x : Nil;
   1076 }
   1077 
   1078 // (sym? 'any) -> flg
   1079 any doSymQ(any x) {
   1080    x = cdr(x);
   1081    return isSym(EVAL(car(x)))? T : Nil;
   1082 }
   1083 
   1084 // (flg? 'any) -> flg
   1085 any doFlgQ(any x) {
   1086    x = cdr(x);
   1087    return isNil(x = EVAL(car(x))) || x==T? T : Nil;
   1088 }
   1089 
   1090 // (member 'any 'lst) -> any
   1091 any doMember(any x) {
   1092    cell c1;
   1093 
   1094    x = cdr(x),  Push(c1, EVAL(car(x)));
   1095    x = cdr(x),  x = EVAL(car(x));
   1096    return member(Pop(c1), x) ?: Nil;
   1097 }
   1098 
   1099 // (memq 'any 'lst) -> any
   1100 any doMemq(any x) {
   1101    cell c1;
   1102 
   1103    x = cdr(x),  Push(c1, EVAL(car(x)));
   1104    x = cdr(x),  x = EVAL(car(x));
   1105    return memq(Pop(c1), x) ?: Nil;
   1106 }
   1107 
   1108 // (mmeq 'lst 'lst) -> any
   1109 any doMmeq(any x) {
   1110    any y, z;
   1111    cell c1;
   1112 
   1113    x = cdr(x),  Push(c1, EVAL(car(x)));
   1114    x = cdr(x),  y = EVAL(car(x));
   1115    for (x = Pop(c1);  isCell(x);  x = cdr(x))
   1116       if (z = memq(car(x), y))
   1117          return z;
   1118    return Nil;
   1119 }
   1120 
   1121 // (sect 'lst 'lst) -> lst
   1122 any doSect(any x) {
   1123    cell c1, c2, c3;
   1124 
   1125    x = cdr(x),  Push(c1, EVAL(car(x)));
   1126    x = cdr(x),  Push(c2, EVAL(car(x)));
   1127    Push(c3, x = Nil);
   1128    while (isCell(data(c1))) {
   1129       if (member(car(data(c1)), data(c2)))
   1130          if (isNil(x))
   1131             x = data(c3) = cons(car(data(c1)), Nil);
   1132          else
   1133             x = cdr(x) = cons(car(data(c1)), Nil);
   1134       data(c1) = cdr(data(c1));
   1135    }
   1136    drop(c1);
   1137    return data(c3);
   1138 }
   1139 
   1140 // (diff 'lst 'lst) -> lst
   1141 any doDiff(any x) {
   1142    cell c1, c2, c3;
   1143 
   1144    x = cdr(x),  Push(c1, EVAL(car(x)));
   1145    x = cdr(x),  Push(c2, EVAL(car(x)));
   1146    Push(c3, x = Nil);
   1147    while (isCell(data(c1))) {
   1148       if (!member(car(data(c1)), data(c2)))
   1149          if (isNil(x))
   1150             x = data(c3) = cons(car(data(c1)), Nil);
   1151          else
   1152             x = cdr(x) = cons(car(data(c1)), Nil);
   1153       data(c1) = cdr(data(c1));
   1154    }
   1155    drop(c1);
   1156    return data(c3);
   1157 }
   1158 
   1159 // (index 'any 'lst) -> cnt | NIL
   1160 any doIndex(any x) {
   1161    int n;
   1162    cell c1;
   1163 
   1164    x = cdr(x),  Push(c1, EVAL(car(x)));
   1165    x = cdr(x),  x = EVAL(car(x));
   1166    return (n = indx(Pop(c1), x))? boxCnt(n) : Nil;
   1167 }
   1168 
   1169 // (offset 'lst1 'lst2) -> cnt | NIL
   1170 any doOffset(any x) {
   1171    int n;
   1172    any y;
   1173    cell c1;
   1174 
   1175    x = cdr(x),  Push(c1, EVAL(car(x)));
   1176    x = cdr(x),  y = EVAL(car(x));
   1177    for (n = 1, x = Pop(c1);  isCell(y);  ++n, y = cdr(y))
   1178       if (equal(x,y))
   1179          return boxCnt(n);
   1180    return Nil;
   1181 }
   1182 
   1183 // (prior 'lst1 'lst2) -> lst | NIL
   1184 any doPrior(any x) {
   1185    any y;
   1186    cell c1;
   1187 
   1188    x = cdr(x),  Push(c1, EVAL(car(x)));
   1189    x = cdr(x),  y = EVAL(car(x));
   1190    if ((x = Pop(c1)) != y)
   1191       while (isCell(y)) {
   1192          if (x == cdr(y))
   1193             return y;
   1194          y = cdr(y);
   1195       }
   1196    return Nil;
   1197 }
   1198 
   1199 // (length 'any) -> cnt | T
   1200 any doLength(any x) {
   1201    int n, c;
   1202    any y;
   1203 
   1204    if (isNum(x = EVAL(cadr(x))))
   1205       return numToSym(x, 0, -1, 0);
   1206    if (isSym(x)) {
   1207       for (n = 0, c = symChar(name(x));  c;  ++n, c = symChar(NULL));
   1208       return boxCnt(n);
   1209    }
   1210    for (n = 0, y = x;;) {
   1211       ++n;
   1212       *(word*)&car(y) |= 1;
   1213       if (!isCell(y = cdr(y))) {
   1214          do
   1215             *(word*)&car(x) &= ~1;
   1216          while (isCell(x = cdr(x)));
   1217          return boxCnt(n);
   1218       }
   1219       if (num(car(y)) & 1) {
   1220          while (x != y)
   1221             *(word*)&car(x) &= ~1,  x = cdr(x);
   1222          do
   1223             *(word*)&car(x) &= ~1;
   1224          while (y != (x = cdr(x)));
   1225          return T;
   1226       }
   1227    }
   1228 }
   1229 
   1230 static int size(any x) {
   1231    int n;
   1232    any y;
   1233 
   1234    for (n = 0, y = x;;) {
   1235       ++n;
   1236       if (isCell(car(y)))
   1237          n += size(car(y));
   1238       *(word*)&car(y) |= 1;
   1239       if (!isCell(y = cdr(y))) {
   1240          do
   1241             *(word*)&car(x) &= ~1;
   1242          while (isCell(x = cdr(x)));
   1243          return n;
   1244       }
   1245       if (num(car(y)) & 1) {
   1246          while (x != y)
   1247             *(word*)&car(x) &= ~1,  x = cdr(x);
   1248          do
   1249             *(word*)&car(x) &= ~1;
   1250          while (y != (x = cdr(x)));
   1251          return n;
   1252       }
   1253    }
   1254 }
   1255 
   1256 // (size 'any) -> cnt
   1257 any doSize(any ex) {
   1258    any x = cdr(ex);
   1259 
   1260    if (isNum(x = EVAL(car(x))))
   1261       return boxCnt(numBytes(x));
   1262    if (!isSym(x))
   1263       return boxCnt(size(x));
   1264    if (isExt(x))
   1265       return boxCnt(dbSize(ex,x));
   1266    return isNum(x = name(x))? boxCnt(numBytes(x)) : Zero;
   1267 }
   1268 
   1269 // (bytes 'any) -> cnt
   1270 any doBytes(any x) {
   1271    return boxCnt(binSize(EVAL(cadr(x))));
   1272 }
   1273 
   1274 // (assoc 'any 'lst) -> lst
   1275 any doAssoc(any x) {
   1276    any y;
   1277    cell c1;
   1278 
   1279    x = cdr(x),  Push(c1, EVAL(car(x)));
   1280    x = cdr(x),  y = EVAL(car(x));
   1281    for (x = Pop(c1);  isCell(y);  y = cdr(y))
   1282       if (isCell(car(y)) && equal(x,caar(y)))
   1283          return car(y);
   1284    return Nil;
   1285 }
   1286 
   1287 // (asoq 'any 'lst) -> lst
   1288 any doAsoq(any x) {
   1289    any y;
   1290    cell c1;
   1291 
   1292    x = cdr(x),  Push(c1, EVAL(car(x)));
   1293    x = cdr(x),  y = EVAL(car(x));
   1294    for (x = Pop(c1);  isCell(y);  y = cdr(y))
   1295       if (isCell(car(y)) && x == caar(y))
   1296          return car(y);
   1297    return Nil;
   1298 }
   1299 
   1300 static any Rank;
   1301 
   1302 any rank1(any lst, int n) {
   1303    int i;
   1304 
   1305    if (isCell(car(lst)) && compare(caar(lst), Rank) > 0)
   1306       return NULL;
   1307    if (n == 1)
   1308       return car(lst);
   1309    i = n / 2;
   1310    return rank1(nCdr(i,lst), n-i) ?: rank1(lst, i);
   1311 }
   1312 
   1313 any rank2(any lst, int n) {
   1314    int i;
   1315 
   1316    if (isCell(car(lst)) && compare(Rank, caar(lst)) > 0)
   1317       return NULL;
   1318    if (n == 1)
   1319       return car(lst);
   1320    i = n / 2;
   1321    return rank2(nCdr(i,lst), n-i) ?: rank2(lst, i);
   1322 }
   1323 
   1324 // (rank 'any 'lst ['flg]) -> lst
   1325 any doRank(any x) {
   1326    any y;
   1327    cell c1, c2;
   1328 
   1329    x = cdr(x),  Push(c1, EVAL(car(x)));
   1330    x = cdr(x),  Push(c2, y = EVAL(car(x)));
   1331    x = cdr(x),  x = EVAL(car(x));
   1332    Rank = Pop(c1);
   1333    if (isCell(y))
   1334       return (isNil(x)? rank1(y, length(y)) : rank2(y, length(y))) ?: Nil;
   1335    return Nil;
   1336 }
   1337 
   1338 /* Pattern matching */
   1339 bool match(any p, any d) {
   1340    any x;
   1341 
   1342    for (;;) {
   1343       if (!isCell(p)) {
   1344          if (isSym(p)  &&  firstByte(p) == '@') {
   1345             val(p) = d;
   1346             return YES;
   1347          }
   1348          return equal(p,d);
   1349       }
   1350       if (isSym(x = car(p))  &&  firstByte(x) == '@') {
   1351          if (!isCell(d)) {
   1352             if (equal(d, cdr(p))) {
   1353                val(x) = Nil;
   1354                return YES;
   1355             }
   1356             return NO;
   1357          }
   1358          if (match(cdr(p), cdr(d))) {
   1359             val(x) = cons(car(d), Nil);
   1360             return YES;
   1361          }
   1362          if (match(cdr(p), d)) {
   1363             val(x) = Nil;
   1364             return YES;
   1365          }
   1366          if (match(p, cdr(d))) {
   1367             val(x) = cons(car(d), val(x));
   1368             return YES;
   1369          }
   1370       }
   1371       if (!isCell(d) || !match(x, car(d)))
   1372          return NO;
   1373       p = cdr(p);
   1374       d = cdr(d);
   1375    }
   1376 }
   1377 
   1378 // (match 'lst1 'lst2) -> flg
   1379 any doMatch(any x) {
   1380    cell c1, c2;
   1381 
   1382    x = cdr(x),  Push(c1, EVAL(car(x)));
   1383    x = cdr(x),  Push(c2, EVAL(car(x)));
   1384    x = match(data(c1), data(c2))? T : Nil;
   1385    drop(c1);
   1386    return x;
   1387 }
   1388 
   1389 // Fill template structure
   1390 static any fill(any x, any s) {
   1391    any y;
   1392    cell c1;
   1393 
   1394    if (isNum(x))
   1395       return NULL;
   1396    if (isSym(x))
   1397       return x != val(x) && (isNil(s)? x!=At && firstByte(x)=='@' : memq(x,s)!=NULL)? val(x) : NULL;
   1398    if (car(x) == Up) {
   1399       x = cdr(x);
   1400       if (!isCell(y = EVAL(car(x))))
   1401          return fill(cdr(x), s) ?: cdr(x);
   1402       Push(c1, y);
   1403       while (isCell(cdr(y)))
   1404          y = cdr(y);
   1405       cdr(y) = fill(cdr(x), s) ?: cdr(x);
   1406       return Pop(c1);
   1407    }
   1408    if (y = fill(car(x), s)) {
   1409       Push(c1,y);
   1410       y = fill(cdr(x), s);
   1411       return cons(Pop(c1), y ?: cdr(x));
   1412    }
   1413    if (y = fill(cdr(x), s))
   1414       return cons(car(x), y);
   1415    return NULL;
   1416 }
   1417 
   1418 // (fill 'any ['sym|lst]) -> any
   1419 any doFill(any x) {
   1420    cell c1, c2;
   1421 
   1422    x = cdr(x),  Push(c1, EVAL(car(x)));
   1423    x = cdr(x),  Push(c2, EVAL(car(x)));
   1424    if (x = fill(data(c1), data(c2))) {
   1425       drop(c1);
   1426       return x;
   1427    }
   1428    return Pop(c1);
   1429 }
   1430 
   1431 /* Declarative Programming */
   1432 cell *Penv, *Pnl;
   1433 
   1434 static bool unify(any n1, any x1, any n2, any x2) {
   1435    any x, env;
   1436 
   1437 lookup1:
   1438    if (isSym(x1)  &&  firstByte(x1) == '@')
   1439       for (x = data(*Penv);  isCell(car(x));  x = cdr(x))
   1440          if (unDig(n1) == unDig(caaar(x))  &&  x1 == cdaar(x)) {
   1441             n1 = cadar(x);
   1442             x1 = cddar(x);
   1443             goto lookup1;
   1444          }
   1445 lookup2:
   1446    if (isSym(x2)  &&  firstByte(x2) == '@')
   1447       for (x = data(*Penv);  isCell(car(x));  x = cdr(x))
   1448          if (unDig(n2) == unDig(caaar(x))  &&  x2 == cdaar(x)) {
   1449             n2 = cadar(x);
   1450             x2 = cddar(x);
   1451             goto lookup2;
   1452          }
   1453    if (unDig(n1) == unDig(n2)  &&  equal(x1, x2))
   1454       return YES;
   1455    if (isSym(x1)  &&  firstByte(x1) == '@') {
   1456       if (x1 != At) {
   1457          data(*Penv) = cons(cons(cons(n1,x1), Nil), data(*Penv));
   1458          cdar(data(*Penv)) = cons(n2,x2);
   1459       }
   1460       return YES;
   1461    }
   1462    if (isSym(x2)  &&  firstByte(x2) == '@') {
   1463       if (x2 != At) {
   1464          data(*Penv) = cons(cons(cons(n2,x2), Nil), data(*Penv));
   1465          cdar(data(*Penv)) = cons(n1,x1);
   1466       }
   1467       return YES;
   1468    }
   1469    if (!isCell(x1) || !isCell(x2))
   1470       return equal(x1, x2);
   1471    env = data(*Penv);
   1472    if (unify(n1, car(x1), n2, car(x2))  &&  unify(n1, cdr(x1), n2, cdr(x2)))
   1473       return YES;
   1474    data(*Penv) = env;
   1475    return NO;
   1476 }
   1477 
   1478 static any lup(any n, any x) {
   1479    any y;
   1480    cell c1;
   1481 
   1482 lup:
   1483    if (isSym(x)  &&  firstByte(x) == '@')
   1484       for (y = data(*Penv);  isCell(car(y));  y = cdr(y))
   1485          if (unDig(n) == unDig(caaar(y))  &&  x == cdaar(y)) {
   1486             n = cadar(y);
   1487             x = cddar(y);
   1488             goto lup;
   1489          }
   1490    if (!isCell(x))
   1491       return x;
   1492    Push(c1, lup(n, car(x)));
   1493    x = lup(n, cdr(x));
   1494    return cons(Pop(c1), x);
   1495 }
   1496 
   1497 static any lookup(any n, any x) {
   1498    return isSym(x = lup(n,x)) && firstByte(x)=='@'?  Nil : x;
   1499 }
   1500 
   1501 static any uniFill(any x) {
   1502    cell c1;
   1503 
   1504    if (isNum(x))
   1505       return x;
   1506    if (isSym(x))
   1507       return lup(car(data(*Pnl)), x);
   1508    Push(c1, uniFill(car(x)));
   1509    x = uniFill(cdr(x));
   1510    return cons(Pop(c1), x);
   1511 }
   1512 
   1513 // (prove 'lst ['lst]) -> lst
   1514 any doProve(any x) {
   1515    int i;
   1516    cell *envSave, *nlSave, at, q, dbg, env, n, nl, alt, tp1, tp2, e;
   1517 
   1518    x = cdr(x);
   1519    if (!isCell(data(q) = EVAL(car(x))))
   1520       return Nil;
   1521    Save(q);
   1522    Push(at,val(At));
   1523    envSave = Penv,  Penv = &env,  nlSave = Pnl,  Pnl = &nl;
   1524    if (x = cdr(x), isNil(x = EVAL(car(x))))
   1525       data(dbg) = NULL;
   1526    else
   1527       Push(dbg, x);
   1528    Push(env, caar(data(q))),  car(data(q)) = cdar(data(q));
   1529    Push(n, car(data(env))),  data(env) = cdr(data(env));
   1530    Push(nl, car(data(env))),  data(env) = cdr(data(env));
   1531    Push(alt, car(data(env))),  data(env) = cdr(data(env));
   1532    Push(tp1, car(data(env))),  data(env) = cdr(data(env));
   1533    Push(tp2, car(data(env))),  data(env) = cdr(data(env));
   1534    Push(e,Nil);
   1535    while (isCell(data(tp1)) || isCell(data(tp2))) {
   1536       if (isCell(data(alt))) {
   1537          data(e) = data(env);
   1538          if (!unify(car(data(nl)), cdar(data(tp1)), data(n), caar(data(alt)))) {
   1539             if (!isCell(data(alt) = cdr(data(alt)))) {
   1540                data(env) = caar(data(q)),  car(data(q)) = cdar(data(q));
   1541                data(n) = car(data(env)),  data(env) = cdr(data(env));
   1542                data(nl) = car(data(env)),  data(env) = cdr(data(env));
   1543                data(alt) = car(data(env)),  data(env) = cdr(data(env));
   1544                data(tp1) = car(data(env)),  data(env) = cdr(data(env));
   1545                data(tp2) = car(data(env)),  data(env) = cdr(data(env));
   1546             }
   1547          }
   1548          else {
   1549             if (data(dbg)  &&  memq(caar(data(tp1)), data(dbg))) {
   1550                outWord(indx(car(data(alt)), get(caar(data(tp1)), T)));
   1551                space();
   1552                print(uniFill(car(data(tp1)))), newline();
   1553             }
   1554             if (isCell(cdr(data(alt))))
   1555                car(data(q)) =
   1556                   cons(
   1557                      cons(data(n),
   1558                         cons(data(nl),
   1559                            cons(cdr(data(alt)),
   1560                               cons(data(tp1), cons(data(tp2),data(e))) ) ) ),
   1561                      car(data(q)) );
   1562             data(nl) = cons(data(n), data(nl));
   1563             data(n) = box(2 + unDig(data(n)));
   1564             data(tp2) = cons(cdr(data(tp1)), data(tp2));
   1565             data(tp1) = cdar(data(alt));
   1566             data(alt) = Nil;
   1567          }
   1568       }
   1569       else if (!isCell(x = data(tp1))) {
   1570          data(tp1) = car(data(tp2)),  data(tp2) = cdr(data(tp2));
   1571          data(nl) = cdr(data(nl));
   1572       }
   1573       else if (car(x) == T) {
   1574          while (isCell(car(data(q)))  &&
   1575                               unDig(caaar(data(q))) >= unDig(car(data(nl))) )
   1576             car(data(q)) = cdar(data(q));
   1577          data(tp1) = cdr(x);
   1578       }
   1579       else if (isNum(caar(x))) {
   1580          data(e) = prog(cdar(x));
   1581          for (i = unDig(caar(x)), x = data(nl);  (i -= 2) > 0;)
   1582             x = cdr(x);
   1583          data(nl) = cons(car(x), data(nl));
   1584          data(tp2) = cons(cdr(data(tp1)), data(tp2));
   1585          data(tp1) = data(e);
   1586       }
   1587       else if (caar(x) == Up) {
   1588          if (!isNil(data(e) = prog(cddar(x)))  &&
   1589                      unify(car(data(nl)), cadar(x), car(data(nl)), data(e)) )
   1590             data(tp1) = cdr(x);
   1591          else {
   1592             data(env) = caar(data(q)),  car(data(q)) = cdar(data(q));
   1593             data(n) = car(data(env)),  data(env) = cdr(data(env));
   1594             data(nl) = car(data(env)),  data(env) = cdr(data(env));
   1595             data(alt) = car(data(env)),  data(env) = cdr(data(env));
   1596             data(tp1) = car(data(env)),  data(env) = cdr(data(env));
   1597             data(tp2) = car(data(env)),  data(env) = cdr(data(env));
   1598          }
   1599       }
   1600       else if (!isCell(data(alt) = get(caar(x), T))) {
   1601          data(env) = caar(data(q)),  car(data(q)) = cdar(data(q));
   1602          data(n) = car(data(env)),  data(env) = cdr(data(env));
   1603          data(nl) = car(data(env)),  data(env) = cdr(data(env));
   1604          data(alt) = car(data(env)),  data(env) = cdr(data(env));
   1605          data(tp1) = car(data(env)),  data(env) = cdr(data(env));
   1606          data(tp2) = car(data(env)),  data(env) = cdr(data(env));
   1607       }
   1608    }
   1609    for (data(e) = Nil,  x = data(env);  isCell(cdr(x));  x = cdr(x))
   1610       if (!unDig(caaar(x)))
   1611          data(e) = cons(cons(cdaar(x), lookup(Zero, cdaar(x))), data(e));
   1612    val(At) = data(at);
   1613    drop(q);
   1614    Penv = envSave,  Pnl = nlSave;
   1615    return isCell(data(e))? data(e) : isCell(data(env))? T : Nil;
   1616 }
   1617 
   1618 // (-> any [num]) -> any
   1619 any doArrow(any x) {
   1620    int i;
   1621    any y;
   1622 
   1623    if (!isNum(caddr(x)))
   1624       return lookup(car(data(*Pnl)), cadr(x));
   1625    for (i = unDig(caddr(x)), y = data(*Pnl);  (i -= 2) > 0;)
   1626       y = cdr(y);
   1627    return lookup(car(y), cadr(x));
   1628 }
   1629 
   1630 // (unify 'any) -> lst
   1631 any doUnify(any x) {
   1632    cell c1;
   1633 
   1634    Push(c1, EVAL(cadr(x)));
   1635    if (unify(cadr(data(*Pnl)), data(c1), car(data(*Pnl)), data(c1))) {
   1636       drop(c1);
   1637       return data(*Penv);
   1638    }
   1639    drop(c1);
   1640    return Nil;
   1641 }
   1642 
   1643 /* List Merge Sort: Bill McDaniel, DDJ Jun99 */
   1644 static bool cmp(any ex, any foo, cell c[2]) {
   1645    if (isNil(foo))
   1646       return compare(car(data(c[0])), car(data(c[1]))) < 0;
   1647    return !isNil(apply(ex, foo, YES, 2, c));
   1648 }
   1649 
   1650 // (sort 'lst ['fun]) -> lst
   1651 any doSort(any ex) {
   1652    int i;
   1653    any x;
   1654    cell p, foo, in[2], out[2], last[2];
   1655    any *tail[2];
   1656 
   1657    x = cdr(ex);
   1658    if (!isCell(data(out[0]) = EVAL(car(x))))
   1659       return data(out[0]);
   1660    Save(out[0]);
   1661    x = cdr(x),  Push(foo, EVAL(car(x)));
   1662    Push(out[1], Nil);
   1663    Save(in[0]);
   1664    Save(in[1]);
   1665    Push(p, Nil);
   1666    Push(last[1], Nil);
   1667    do {
   1668       data(in[0]) = data(out[0]);
   1669       data(in[1]) = data(out[1]);
   1670 
   1671       i = isCell(data(in[1]))  &&  !cmp(ex, data(foo), in);
   1672       if (isCell(data(p) = data(in[i])))
   1673          data(in[i]) = cdr(data(in[i]));
   1674       data(out[0]) = data(p);
   1675       tail[0] = &cdr(data(p));
   1676       data(last[1]) = data(out[0]);
   1677       cdr(data(p)) = Nil;
   1678       i = 0;
   1679       data(out[1]) = Nil;
   1680       tail[1] = &data(out[1]);
   1681       while (isCell(data(in[0])) || isCell(data(in[1]))) {
   1682          if (!isCell(data(in[1]))) {
   1683             if (isCell(data(p) = data(in[0])))
   1684                data(in[0]) = cdr(data(in[0]));
   1685             data(last[0]) = data(p);
   1686             if (cmp(ex, data(foo), last))
   1687                i = 1 - i;
   1688          }
   1689          else if (!isCell(data(in[0]))) {
   1690             data(last[0]) = data(p) = data(in[1]),  data(in[1]) = cdr(data(in[1]));
   1691             if (cmp(ex, data(foo), last))
   1692                i = 1 - i;
   1693          }
   1694          else if (data(last[0]) = data(in[0]),  cmp(ex, data(foo), last)) {
   1695             data(last[0]) = data(in[1]);
   1696             if (!cmp(ex, data(foo), last))
   1697                data(p) = data(in[1]),  data(in[1]) = cdr(data(in[1]));
   1698             else {
   1699                if (cmp(ex, data(foo), in))
   1700                   data(p) = data(in[0]),  data(in[0]) = cdr(data(in[0]));
   1701                else
   1702                   data(p) = data(in[1]),  data(in[1]) = cdr(data(in[1]));
   1703                i = 1 - i;
   1704             }
   1705          }
   1706          else {
   1707             data(last[0]) = data(in[1]);
   1708             if (cmp(ex, data(foo), last))
   1709                data(p) = data(in[0]),  data(in[0]) = cdr(data(in[0]));
   1710             else {
   1711                if (cmp(ex, data(foo), in))
   1712                   data(p) = data(in[0]),  data(in[0]) = cdr(data(in[0]));
   1713                else
   1714                   data(p) = data(in[1]),  data(in[1]) = cdr(data(in[1]));
   1715             }
   1716          }
   1717          *tail[i] = data(p);
   1718          tail[i] = &cdr(data(p));
   1719          cdr(data(p)) = Nil;
   1720          data(last[1]) = data(p);
   1721       }
   1722    } while (isCell(data(out[1])));
   1723    return Pop(out[0]);
   1724 }