Annotation of 43BSD/contrib/B/src/bint/b3int.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
                      2: 
                      3: /*
                      4:   $Header: b3int.c,v 1.4 85/08/22 16:58:27 timo Exp $
                      5: */
                      6: 
                      7: /* B interpreter using theaded trees */
                      8: 
                      9: #include "b.h"
                     10: #include "b0fea.h"
                     11: #include "b1mem.h"
                     12: #include "b1obj.h"
                     13: #include "b2nod.h"
                     14: #include "b3err.h"
                     15: #include "b3sem.h"
                     16: #include "b3env.h"
                     17: #include "b3int.h"
                     18: #include "b3in2.h"
                     19: #include "b3sta.h"
                     20: 
                     21: 
                     22: /* Relicts from old system: */
                     23: 
                     24: Visible value resval;
                     25: Visible bool terminated;
                     26: 
                     27: 
                     28: /* Shorthands: */
                     29: 
                     30: #define Pop2(fun) (w = pop(), v = pop(), fun(v, w), release(v), release(w))
                     31: #define Pop1(fun) (v = pop(), fun(v), release(v))
                     32: #define Dyop(funvw) \
                     33:        (w = pop(), v = pop(), push(funvw), release(v), release(w))
                     34: #define Monop(funv) (v = pop(), push(funv), release(v))
                     35: #define Flagged() (Thread2(pc) != NilTree)
                     36: #define LocFlagged() (Thread2(pc) != NilTree && !noloc)
                     37: #define ValOrLoc(feval, floc) (LocFlagged() ? (floc) : (feval))
                     38: #define Jump() (tracing && tr_jump(), next = Thread2(pc))
                     39: #define Comp(op) (w = pop(), v = pop(), report = (compare(v, w) op 0), Comp2())
                     40: #define Comp2() (release(v), !Flagged() ? release(w) : Comp3())
                     41: #define Comp3() (report ? push(w) : (Jump(), release(w)))
                     42: #define F(n) ((value)*Branch(pc, (n)))
                     43: 
                     44: 
                     45: /* Execute a threaded tree until the end or until a terminating-command.
                     46:    The boolean argument 'wantvalue' tells whether it must deliver
                     47:    a value or not.
                     48: */
                     49: 
                     50: Hidden value
                     51: run(start, wantvalue) parsetree start; bool wantvalue; {
                     52:        value u, v, w; int k; bool X, Y; int call_stop= call_level;
                     53: #ifdef IBMPC
                     54:        int loopcnt= 0;
                     55: #endif
                     56:        parsetree old_next= next;
                     57:        /* While run can be used recursively, save some state info */
                     58: 
                     59:        next= start;
                     60:        for (;;) {
                     61: #ifdef IBMPC
                     62:                if (loopcnt++ == 100) {
                     63:                        bdos(0x2c, 0, 0);
                     64:                        /* forcing a DOS function call (get time) */
                     65:                        /* so that a break interrupt can be executed */
                     66:                        loopcnt= 0;
                     67:                }
                     68: #endif
                     69:                if (!still_ok) break;
                     70:                pc= next;
                     71:                if (pc == Halt) {
                     72:                        error(MESS(3500, "unexpected program halt"));
                     73:                        break;
                     74:                }
                     75:                if (!Is_parsetree(pc)) {
                     76:                        if (pc == Stop) {
                     77:                                if (call_level == call_stop) break;
                     78:                                ret();
                     79:                                continue;
                     80:                        }
                     81:                        if (!Is_number(pc)) syserr(MESS(3501, "run: bad thread"));
                     82:                        switch (intval(pc)) {
                     83:                        case 0:
                     84:                                pc= Stop;
                     85:                                break;
                     86:                        case 1:
                     87:                                error(
                     88:                        MESS(3502, "none of the alternative tests of SELECT succeeds"));
                     89:                                break;
                     90:                        case 2:
                     91:                                if (resexp == Rep)
                     92:                                        error(MESS(3503, "TEST-unit reports no outcome"));
                     93:                                else
                     94:                                        error(MESS(3504, "YIELD-unit returns no value"));
                     95:                                break;
                     96:                        case 3:
                     97:                                if (resexp == Rep)
                     98:                                 error(MESS(3505, "test-refinement reports no outcome"));
                     99:                                else
                    100:                                 error(MESS(3506, "refinement returns no value"));
                    101:                                 /* "expression-" seems superfluous here */
                    102:                                break;
                    103:                        default:
                    104:                                v= convert(pc, No, No);
                    105:                                error3(MESS(3507, "run-time error "), v, 0);
                    106:                                release(v);
                    107:                        }
                    108:                        continue;
                    109:                }
                    110:                next = Thread(pc);
                    111:                if (tracing) tr_node(pc);
                    112: /* <<<<<<<<<<<<<<<< */
                    113: switch (Nodetype(pc)) {
                    114: 
                    115: case HOW_TO:
                    116: case REFINEMENT:
                    117:        error(MESS(3508, "run: cannot execute unit-definition"));
                    118:        break;
                    119: 
                    120: case YIELD:
                    121: case TEST:
                    122:        switch (Nodetype(F(FPR_FORMALS))) {
                    123:        case TAG:
                    124:                break;
                    125:        case MONF: case MONPRD:
                    126:                w= pop(); v= pop();
                    127:                put(v, w); release(v); release(w);
                    128:                break;
                    129:        case DYAF: case DYAPRD:
                    130:                w= pop(); v= pop(); u= pop();
                    131:                put(u, w); release(u); release(w);
                    132:                u= pop();
                    133:                put(u, v); release(u); release(v);
                    134:                break;
                    135:        default:
                    136:                syserr(MESS(3509, "bad FPR_FORMAL"));
                    137:        }
                    138:        break;
                    139: 
                    140: /* Commands */
                    141: 
                    142: case SUITE:
                    143:        curlino = F(SUI_LINO);
                    144:        curline = F(SUI_CMD);
                    145:        break;
                    146: 
                    147: case IF:
                    148: case AND:
                    149: case WHILE:
                    150: case TEST_SUITE:
                    151:        if (!report) Jump(); break;
                    152: 
                    153: case OR: if (report) Jump(); break;
                    154: 
                    155: case FOR:
                    156:        w= pop(); v= pop();
                    157:        if (!in_ranger(v, &w)) { release(v); release(w); Jump(); }
                    158:        else { push(v); push(w); }
                    159:        break;
                    160: 
                    161: case PUT: Pop2(put_with_check); break;
                    162: case INSERT: Pop2(l_insert); break;
                    163: case REMOVE: Pop2(l_remove); break;
                    164: case CHOOSE: Pop2(choose); break;
                    165: case DRAW: Pop1(draw); break;
                    166: case SET_RANDOM: Pop1(set_random); break;
                    167: case DELETE: Pop1(l_delete); break;
                    168: case CHECK: if (!report) checkerr(); break;
                    169: 
                    170: case WRITE:
                    171:        nl(F(WRT_L_LINES));
                    172:        if (F(WRT_EXPR)) { v = pop(); writ(v); release(v); }
                    173:        nl(F(WRT_R_LINES));
                    174:        break;
                    175: 
                    176: case READ: Pop2(read_eg); break;
                    177: 
                    178: case READ_RAW: Pop1(read_raw); break;
                    179: 
                    180: case QUIT:
                    181:        if (resexp != Voi)
                    182:           error(MESS(3510, "QUIT may only occur in a HOW'TO or command-refinement"));
                    183:        if (call_level == 0 && still_ok) terminated= Yes;
                    184:        next= Stop; break;
                    185: case RETURN:
                    186:        if (resexp != Ret)
                    187:           error(MESS(3511, "RETURN may only occur in a YIELD or expression-refinement"));
                    188:        resval = pop(); next= Stop; break;
                    189: case REPORT:
                    190:        if (resexp != Rep)
                    191:           error(MESS(3512, "REPORT may only occur in a TEST-unit or test-refinement"));
                    192:        next= Stop; break;
                    193: case SUCCEED:
                    194:        if (resexp != Rep)
                    195:           error(MESS(3513, "SUCCEED may only occur in a TEST-unit or test-refinement"));
                    196:        report = Yes; next= Stop; break;
                    197: case FAIL:
                    198:        if (resexp != Rep)
                    199:           error(MESS(3514, "FAIL may only occur in a TEST-unit or test-refinement"));
                    200:        report = No; next= Stop; break;
                    201: 
                    202: case USER_COMMAND:
                    203:        x_user_command(F(UCMD_NAME), F(UCMD_ACTUALS), F(UCMD_DEF));
                    204:        break;
                    205: 
                    206: case EXTENDED_COMMAND:
                    207: #ifdef EXT_COMMAND
                    208:        x_extended_command(F(ECMD_NAME), F(ECMD_ACTUALS));
                    209: #endif
                    210:        break;
                    211: 
                    212: /* Expressions, targets */
                    213: 
                    214: case COLLATERAL:
                    215:        v = mk_compound(k= Nfields(F(COLL_SEQ)));
                    216:        while (--k >= 0)
                    217:                *Field(v, k) = pop();
                    218:        push(v);
                    219:        break;
                    220: 
                    221: /* Expressions, targets */
                    222: 
                    223: case SELECTION: Dyop(ValOrLoc(associate(v, w), tbsel_loc(v, w))); break;
                    224: 
                    225: case BEHEAD:
                    226:        w= pop(); v= pop();
                    227:        push(LocFlagged() ? trim_loc(v, w, '@') : behead(v, w));
                    228:        release(v); release(w);
                    229:        break;
                    230: 
                    231: case CURTAIL:
                    232:        w= pop(); v= pop();
                    233:        push(LocFlagged() ? trim_loc(v, w, '|') : curtail(v, w));
                    234:        release(v); release(w);
                    235:        break;
                    236: 
                    237: case MONF:
                    238:        v = pop();
                    239:        formula(Vnil, F(MON_NAME), v, F(MON_FCT));
                    240:        release(v);
                    241:        break;
                    242: 
                    243: case DYAF:
                    244:        w = pop(); v = pop();
                    245:        formula(v,  F(DYA_NAME), w, F(DYA_FCT));
                    246:        release(v); release(w);
                    247:        break;
                    248: 
                    249: case TEXT_LIT:
                    250:        v= F(XLIT_TEXT);
                    251:        if (F(XLIT_NEXT)) { w= pop(); v= concat(v, w); release(w); }
                    252:        else copy(v);
                    253:        push(v);
                    254:        break;
                    255: 
                    256: case TEXT_CONV:
                    257:        if (F(XCON_NEXT)) w= pop();
                    258:        u= pop();
                    259:        v= convert(u, Yes, Yes);
                    260:        release(u);
                    261:        if (F(XCON_NEXT)) {
                    262:                v= concat(u= v, w);
                    263:                release(u);
                    264:                release(w);
                    265:        }
                    266:        push(v);
                    267:        break;
                    268: 
                    269: case ELT_DIS: push(mk_elt()); break;
                    270: 
                    271: case LIST_DIS:
                    272:        u = mk_elt();
                    273:        k= Nfields(F(LDIS_SEQ));
                    274:        while (--k >= 0) {
                    275:                insert(v = pop(), &u);
                    276:                release(v);
                    277:        }
                    278:        push(u);
                    279:        break;
                    280: 
                    281: case RANGE_DIS: Dyop(mk_range(v, w)); break;
                    282: 
                    283: case TAB_DIS:
                    284:        u = mk_elt();
                    285:        k= Nfields(F(TDIS_SEQ));
                    286:        while ((k -= 2) >= 0) {
                    287:                w = pop(); v = pop();
                    288:                /* Should check for same key with different associate */
                    289:                replace(w, &u, v);
                    290:                release(v); release(w);
                    291:        }
                    292:        push(u);
                    293:        break;
                    294: 
                    295: /* Tests */
                    296: 
                    297: case NOT: report = !report; break;
                    298: 
                    299: /* Quantifiers can be described as follows:
                    300:    Report X at first test which reports Y.  If no test reports Y, report !X.
                    301:       type     X       Y
                    302:       SOME     Yes     Yes
                    303:       EACH     No      No
                    304:       NO       No      Yes. */
                    305: 
                    306: case EACH_IN:  X= Y= No; goto quant;
                    307: case NO_IN:    X= No; Y= Yes; goto quant;
                    308: case SOME_IN:  X= Y= Yes;
                    309: quant:
                    310:        w= pop(); v= pop();
                    311:        if (Is_compound(w) && report == Y) { report= X; Jump(); }
                    312:        else if (!in_ranger(v, &w)) { report= !X; Jump(); }
                    313:        else { push(v); push(w); break; }
                    314:        release(v); release(w);
                    315:        break;
                    316: 
                    317: case EACH_PARSING:     X= Y= No; goto parse;
                    318: case NO_PARSING:       X= No; Y= Yes; goto parse;
                    319: case SOME_PARSING:     X= Y= Yes;
                    320: parse:
                    321:        w= pop(); v= pop();
                    322:        if (Is_compound(w) && report == Y) { report= X; Jump(); }
                    323:        else if (!pa_ranger(v, &w)) { report= !X; Jump(); }
                    324:        else { push(v); push(w); break; }
                    325:        release(v); release(w);
                    326:        break;
                    327: 
                    328: case MONPRD:
                    329:        v = pop();
                    330:        proposition(Vnil, F(MON_NAME), v, F(MON_FCT));
                    331:        release(v);
                    332:        break;
                    333: 
                    334: case DYAPRD:
                    335:        w = pop(); v = pop();
                    336:        proposition(v, F(DYA_NAME), w, F(DYA_FCT));
                    337:        release(v); release(w);
                    338:        break;
                    339: 
                    340: case LESS_THAN: Comp(<); break;
                    341: case AT_MOST: Comp(<=); break;
                    342: case GREATER_THAN: Comp(>); break;
                    343: case AT_LEAST: Comp(>=); break;
                    344: case EQUAL: Comp(==); break;
                    345: case UNEQUAL: Comp(!=); break;
                    346: 
                    347: case TAGformal:
                    348:        call_formal(F(TAG_NAME), F(TAG_ID), LocFlagged());
                    349:        break;
                    350: 
                    351: case TAGlocal:
                    352:        push(ValOrLoc(v_local(F(TAG_NAME), F(TAG_ID)), local_loc(F(TAG_ID))));
                    353:        break;
                    354: 
                    355: case TAGglobal:
                    356:        push(ValOrLoc(v_global(F(TAG_NAME)), global_loc(F(TAG_NAME))));
                    357:        break;
                    358: 
                    359: case TAGmystery:
                    360:        if (LocFlagged()) push(l_mystery(F(TAG_NAME), F(TAG_ID)));
                    361:        else v_mystery(F(TAG_NAME), F(TAG_ID));
                    362:        break;
                    363: 
                    364: case TAGrefinement:
                    365:        call_refinement(F(TAG_NAME), F(TAG_ID), Flagged());
                    366:        break;
                    367: 
                    368: case TAGzerfun:
                    369:        formula(Vnil,  F(TAG_NAME), Vnil, F(TAG_ID));
                    370:        break;
                    371: 
                    372: case TAGzerprd:
                    373:        proposition(Vnil,  F(TAG_NAME), Vnil, F(TAG_ID));
                    374:        break;
                    375: 
                    376: case NUMBER:
                    377:        push(copy(F(NUM_VALUE)));
                    378:        break;
                    379: 
                    380: default:
                    381:        syserr(MESS(3515, "run: bad node type"));
                    382: 
                    383: }
                    384: /* >>>>>>>>>>>>>>>> */
                    385:        }
                    386:        v = Vnil;
                    387:        if (wantvalue && still_ok) v = pop();
                    388:        /* Unwind stack when stopped by error: */
                    389:        while (call_level != call_stop) ret();
                    390:        next= old_next;
                    391:        return v;
                    392: }
                    393: 
                    394: 
                    395: /* External interfaces: */
                    396: 
                    397: Visible Procedure execthread(start) parsetree start; {
                    398:        run(start, No);
                    399: }
                    400: 
                    401: Visible value evalthread(start) parsetree start; {
                    402:        return run(start, Yes);
                    403: }
                    404: 
                    405: Visible Procedure initint() {
                    406:        /* Dummy, relict */
                    407: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.