Annotation of 43BSD/contrib/B/src/bint/b2gen.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
        !             2: 
        !             3: /* $Header: b2gen.c,v 1.4 85/08/27 10:57:31 timo Exp $ */
        !             4: 
        !             5: /* Code generation */
        !             6: 
        !             7: #include "b.h"
        !             8: #include "b0fea.h"
        !             9: #include "b1obj.h"
        !            10: #include "b2exp.h"
        !            11: #include "b2nod.h"
        !            12: #include "b2gen.h" /* Must be after b2nod.h */
        !            13: #include "b3err.h"
        !            14: #include "b3env.h"
        !            15: #include "b3int.h"
        !            16: #include "b3sem.h"
        !            17: #include "b3sou.h"
        !            18: 
        !            19: Visible Procedure fix_nodes(pt, code) parsetree *pt; parsetree *code; {
        !            20:        context c; value *setup(), *su;
        !            21:        sv_context(&c);
        !            22:        curline= *pt; curlino= one;
        !            23:        su= setup(*pt);
        !            24:        if (su) analyze(*pt, su);
        !            25:        curline= *pt; curlino= one;
        !            26:        inithreads();
        !            27:        fix(pt, su ? 'x' : 'v');
        !            28:        endthreads(code);
        !            29:        cleanup();
        !            30: #ifdef TYPE_CHECK
        !            31:        if (cntxt != In_prmnv) type_check(*pt);
        !            32: #endif
        !            33:        set_context(&c);
        !            34: }
        !            35: 
        !            36: /* ******************************************************************** */
        !            37: 
        !            38: /* Utilities used by threading. */
        !            39: 
        !            40: /* A 'threaded tree' is, in our case, a fixed(*) parse tree with extra links
        !            41:    that are used by the interpreter to determine the execution order.
        !            42:    __________
        !            43:    (*) 'Fixed' means: processed by 'fix_nodes', which removes UNPARSED
        !            44:        nodes and distinguishes TAG nodes into local, global tags etc.
        !            45:        fix_nodes also creates the threads, but this is accidental, not
        !            46:        essential.  For UNPARSED nodes, the threads are actually laid
        !            47:        in a second pass through the subtree that was UNPARSED.
        !            48:    __________
        !            49: 
        !            50:    A small example: the parse tree for the expression  'a+b*c'  looks like
        !            51: 
        !            52:        (DYOP,
        !            53:                (TAGlocal, "a"),
        !            54:                "+",
        !            55:                (DYOP,
        !            56:                        (TAGlocal, "b"),
        !            57:                        "*",
        !            58:                        (TAGlocal, "c"))).
        !            59: 
        !            60:    The required execution order is here:
        !            61: 
        !            62:        1) (TAGlocal, "a")
        !            63:        2) (TAGlocal, "b")
        !            64:        3) (TAGlocal, "c")
        !            65:        4) (DYOP, ..., "*", ...)
        !            66:        5) (DYOP, ..., "+", ...)
        !            67: 
        !            68:    Of course, the result of each operation (if it has a result) is pushed
        !            69:    on a stack, and the operands are popped from this same stack.  Think of
        !            70:    reversed polish notation (well-known by owners of HP pocket calculators).
        !            71: 
        !            72:    The 'threads' are explicit links from each node to its successor in this
        !            73:    execution order.  Conditional operations like IF and AND have two threads,
        !            74:    one for success and one for failure.  Loops can be made by having the
        !            75:    thread from the last node of the loop body point to the head of the loop.
        !            76: 
        !            77:    Threading expressions, locations and simple-commands is easy: recursively
        !            78:    thread each of the subtrees, then lay a thread from the last threaded
        !            79:    to the current node.  Nodes occurring in a 'location' context are
        !            80:    marked, so that the interpreter knows when to push a 'location' on
        !            81:    the stack.
        !            82: 
        !            83:    Tests and looping commands cause most of the complexity of the threading
        !            84:    utilities.  The basic technique is 'backpatching'.
        !            85:    Nodes that need a conditional forward jump are chained together in a
        !            86:    linked list, and when their destination is reached, all nodes in the
        !            87:    chain get its 'address' patched into their secondary thread.  There is
        !            88:    one such chain, called 'bpchain', which at all times contains those nodes
        !            89:    whose secondary destination would be the next generated instruction.
        !            90:    This is used by IF, WHILE, test-suites, AND and OR.
        !            91: 
        !            92:    To generate a loop, both this chain and the last normal instruction
        !            93:    (if any) are diverted to the node where the loop continues.
        !            94: 
        !            95:    For test-suites, we also need to be capable of jumping unconditionally
        !            96:    forward (over the remainder of the SELECT-command).  This is done by
        !            97:    saving both the backpatch chain and the last node visited, and restoring
        !            98:    them after the remainder has been processed.
        !            99: */
        !           100: 
        !           101: /* Implementation tricks: in order not to show circular lists to 'release',
        !           102:    parse tree nodes are generated as compounds where there is room for two
        !           103:    more fields than their length indicates.
        !           104: */
        !           105: 
        !           106: #define Flag (MkSmallInt(1))
        !           107:        /* Flag used to indicate Location or TestRefinement node */
        !           108: 
        !           109: Hidden parsetree start; /* First instruction.  Picked up by endthreads() */
        !           110: 
        !           111: Hidden parsetree last; /* Last visited node */
        !           112: 
        !           113: Hidden parsetree bpchain; /* Backpatch chain for conditional goto's */
        !           114: Hidden parsetree *wanthere; /* Chain of requests to return next tree */
        !           115: 
        !           116: extern string opcodes[];
        !           117: 
        !           118: 
        !           119: /* Start threading */
        !           120: 
        !           121: Hidden Procedure inithreads() {
        !           122:        bpchain= NilTree;
        !           123:        wanthere= 0;
        !           124:        last= 0;
        !           125:        here(&start);
        !           126: }
        !           127: 
        !           128: /* Finish threading */
        !           129: 
        !           130: Hidden Procedure endthreads(code) parsetree *code; {
        !           131:        jumpto(Stop);
        !           132:        if (!still_ok) start= NilTree;
        !           133:        *code= start;
        !           134: }
        !           135: 
        !           136: 
        !           137: /* Fill 't' as secondary thread for all nodes in the backpatch chain,
        !           138:    leaving the chain empty. */
        !           139: 
        !           140: Hidden Procedure backpatch(t) parsetree t; {
        !           141:        parsetree u;
        !           142:        while (bpchain != NilTree) {
        !           143:                u= Thread2(bpchain);
        !           144:                Thread2(bpchain)= t;
        !           145:                bpchain= u;
        !           146:        }
        !           147: }
        !           148: 
        !           149: Visible Procedure jumpto(t) parsetree t; {
        !           150:        parsetree u;
        !           151:        if (!still_ok) return;
        !           152:        while (wanthere != 0) {
        !           153:                u= *wanthere;
        !           154:                *wanthere= t;
        !           155:                wanthere= (parsetree*)u;
        !           156:        }
        !           157:        while (last != NilTree) {
        !           158:                u= Thread(last);
        !           159:                Thread(last)= t;
        !           160:                last= u;
        !           161:        }
        !           162:        backpatch(t);
        !           163: }
        !           164: 
        !           165: Hidden parsetree seterr(n) int n; {
        !           166:        return (parsetree)MkSmallInt(n);
        !           167: }
        !           168: 
        !           169: /* Visit node 't', and set its secondary thread to 't2'. */
        !           170: 
        !           171: Hidden Procedure visit2(t, t2) parsetree t, t2; {
        !           172:        if (!still_ok) return;
        !           173:        jumpto(t);
        !           174:        Thread2(t)= t2;
        !           175: #ifdef DEBUG
        !           176:        fprintf(stderr, "\tvisit %s %s\n", opcodes[Nodetype(t)],
        !           177:                t2 == NilTree ? "" : "[*]");
        !           178: #endif DEBUG
        !           179:        Thread(t)= NilTree;
        !           180:        last= t;
        !           181: }
        !           182: 
        !           183: /* Visit node 't' */
        !           184: 
        !           185: Hidden Procedure visit(t) parsetree t; {
        !           186:        visit2(t, NilTree);
        !           187: }
        !           188: 
        !           189: /* Visit node 't' and flag it as a location (or test-refinement). */
        !           190: 
        !           191: Hidden Procedure lvisit(t) parsetree t; {
        !           192:        visit2(t, Flag);
        !           193: }
        !           194: 
        !           195: #ifdef NOT_USED
        !           196: Hidden Procedure jumphere(t) parsetree t; {
        !           197:        Thread(t)= last;
        !           198:        last= t;
        !           199: }
        !           200: #endif
        !           201: 
        !           202: /* Add node 't' to the backpatch chain. */
        !           203: 
        !           204: Hidden Procedure jump2here(t) parsetree t; {
        !           205:        if (!still_ok) return;
        !           206:        Thread2(t)= bpchain;
        !           207:        bpchain= t;
        !           208: }
        !           209: 
        !           210: Hidden Procedure here(pl) parsetree *pl; {
        !           211:        if (!still_ok) return;
        !           212:        *pl= (parsetree) wanthere;
        !           213:        wanthere= pl;
        !           214: }
        !           215: 
        !           216: Visible Procedure hold(pl) struct state *pl; {
        !           217:        if (!still_ok) return;
        !           218:        pl->h_last= last; pl->h_bpchain= bpchain; pl->h_wanthere= wanthere;
        !           219:        last= bpchain= NilTree; wanthere= 0;
        !           220: }
        !           221: 
        !           222: Visible Procedure let_go(pl) struct state *pl; {
        !           223:        parsetree p, *w;
        !           224:        if (!still_ok) return;
        !           225:        if (last) {
        !           226:                for (p= last; Thread(p) != NilTree; p= Thread(p))
        !           227:                        ;
        !           228:                Thread(p)= pl->h_last;
        !           229:        }
        !           230:        else last= pl->h_last;
        !           231:        if (bpchain) {
        !           232:                for (p= bpchain; Thread2(p) != NilTree; p= Thread2(p))
        !           233:                        ;
        !           234:                Thread2(p)= pl->h_bpchain;
        !           235:        }
        !           236:        else bpchain= pl->h_bpchain;
        !           237:        if (wanthere) {
        !           238:                for (w= wanthere; *w != 0; w= (parsetree*) *w)
        !           239:                        ;
        !           240:                *w= (parsetree) pl->h_wanthere;
        !           241:        }
        !           242:        else wanthere= pl->h_wanthere;
        !           243: }
        !           244: 
        !           245: Hidden bool reachable() {
        !           246:        return last != NilTree || bpchain != 0 || wanthere != 0;
        !           247: }
        !           248: 
        !           249: 
        !           250: /* ******************************************************************** */
        !           251: /* *********************** code generation **************************** */
        !           252: /* ******************************************************************** */
        !           253: 
        !           254: Forward bool is_variable();
        !           255: Forward bool is_cmd_ref();
        !           256: Forward value copydef();
        !           257: 
        !           258: Visible Procedure fix(pt, flag) parsetree *pt; char flag; {
        !           259:        struct state st; value v, function; parsetree t, l1= NilTree;
        !           260:        typenode nt; string s; char c; int n, k, len;
        !           261: 
        !           262:        t= *pt;
        !           263:        if (!Is_node(t) || !still_ok) return;
        !           264:        nt= Nodetype(t);
        !           265:        if (nt < 0 || nt >= NTYPES) syserr(MESS(2200, "fix bad tree"));
        !           266:        s= gentab[nt];
        !           267:        if (s == NULL) return;
        !           268:        n= First_fieldnr;
        !           269:        if (flag == 'x') curline= t;
        !           270:        while ((c= *s++) != '\0' && still_ok) {
        !           271:                switch (c) {
        !           272:                case '0':
        !           273:                case '1':
        !           274:                case '2':
        !           275:                case '3':
        !           276:                case '4':
        !           277:                case '5':
        !           278:                case '6':
        !           279:                case '7':
        !           280:                case '8':
        !           281:                case '9':
        !           282:                        n= (c - '0') + First_fieldnr;
        !           283:                        break;
        !           284:                case 'c':
        !           285:                        v= *Branch(t, n);
        !           286:                        if (v != Vnil) {
        !           287:                                len= Nfields(v);
        !           288:                                for (k= 0; k < len; ++k)
        !           289:                                        fix(Field(v, k), flag);
        !           290:                        }
        !           291:                        ++n;
        !           292:                        break;
        !           293:                case '#':
        !           294:                        curlino= *Branch(t, n);
        !           295:                        ++n;
        !           296:                        break;
        !           297:                case 'g':
        !           298:                case 'h':
        !           299:                        ++n;
        !           300:                        break;
        !           301:                case 'a':
        !           302:                case 'l':
        !           303:                        if (flag == 'v' || flag == 't')
        !           304:                                c= flag;
        !           305:                        /* Fall through */
        !           306:                case '!':
        !           307:                case 't':
        !           308:                case 'u':       
        !           309:                case 'v':
        !           310:                case 'x':
        !           311:                        fix(Branch(t, n), c);
        !           312:                        ++n;
        !           313:                        break;
        !           314:                case 'f':
        !           315:                        f_fpr_formals(*Branch(t, n));
        !           316:                        ++n;
        !           317:                        break;
        !           318: 
        !           319:                case '?':
        !           320:                        if (flag == 'v')
        !           321:                                f_eunparsed(pt);
        !           322:                        else if (flag == 't')
        !           323:                                f_cunparsed(pt);
        !           324:                        else
        !           325:                          syserr(MESS(2201, "fix unparsed with bad flag"));
        !           326:                        fix(pt, flag);
        !           327:                        break;
        !           328:                case 'C':
        !           329:                        v= *Branch(t, REL_LEFT);
        !           330:                        if (Comparison(Nodetype(v)))
        !           331:                                jump2here(v);
        !           332:                        break;
        !           333:                case 'D':
        !           334:                        v= (value)*Branch(t, DYA_NAME);
        !           335:                        if (!is_dyafun(v, &function))
        !           336:                          fixerr2(v, MESS(2202, " isn't a dyadic function"));
        !           337:                        else
        !           338:                                *Branch(t, DYA_FCT)= copydef(function);
        !           339:                        break;
        !           340:                case 'E':
        !           341:                        v= (value)*Branch(t, DYA_NAME);
        !           342:                        if (!is_dyaprd(v, &function))
        !           343:                          fixerr2(v, MESS(2203, " isn't a dyadic predicate"));
        !           344:                        else
        !           345:                                *Branch(t, DYA_FCT)= copydef(function);
        !           346:                        break;
        !           347:                case 'G':
        !           348:                        jumpto(l1);
        !           349:                        break;
        !           350:                case 'H':
        !           351:                        here(&l1);
        !           352:                        break;
        !           353:                case 'I':
        !           354:                        if (*Branch(t, n) == NilTree)
        !           355:                                break;
        !           356:                        /* Else fall through */
        !           357:                case 'J':
        !           358:                        jump2here(t);
        !           359:                        break;
        !           360:                case 'K':
        !           361:                        hold(&st);
        !           362:                        break;
        !           363:                case 'L':
        !           364:                        let_go(&st);
        !           365:                        break;
        !           366:                case 'M':
        !           367:                        v= (value)*Branch(t, MON_NAME);
        !           368:                        if (is_variable(v) || !is_monfun(v, &function))
        !           369:                          fixerr2(v, MESS(2204, " isn't a monadic function"));
        !           370:                        else
        !           371:                                *Branch(t, MON_FCT)= copydef(function);
        !           372:                        break;
        !           373:                case 'N':
        !           374:                        v= (value)*Branch(t, MON_NAME);
        !           375:                        if (is_variable(v) || !is_monprd(v, &function))
        !           376:                          fixerr2(v, MESS(2205, " isn't a monadic predicate"));
        !           377:                        else
        !           378:                                *Branch(t, MON_FCT)= copydef(function);
        !           379:                        break;
        !           380: #ifdef REACH
        !           381:                case 'R':
        !           382:                        if (*Branch(t, n) != NilTree && !reachable())
        !           383:                            fixerr(MESS(2206, "command cannot be reached"));
        !           384:                        break;
        !           385: #endif
        !           386:                case 'S':
        !           387:                        jumpto(Stop);
        !           388:                        break;
        !           389:                case 'T':
        !           390:                        if (flag == 't')
        !           391:                                f_ctag(pt);
        !           392:                        else if (flag == 'v' || flag == 'x')
        !           393:                                f_etag(pt);
        !           394:                        else
        !           395:                                f_ttag(pt);
        !           396:                        break;
        !           397:                case 'U':
        !           398:                        f_ucommand(pt);
        !           399:                        break;
        !           400:                case 'V':
        !           401:                        visit(t);
        !           402:                        break;
        !           403:                case 'X':
        !           404:                        if (flag == 'a' || flag == 'l' || flag == '!')
        !           405:                                lvisit(t);
        !           406:                        else
        !           407:                                visit(t);
        !           408:                        break;
        !           409:                case 'W':
        !           410: /*!*/                  visit2(t, seterr(1));
        !           411:                        break;
        !           412:                case 'Y':
        !           413:                        if (still_ok && reachable()) {
        !           414:                          if (nt == YIELD)
        !           415:                            fixerr(MESS(2207, "YIELD-unit returns no value"));
        !           416:                          else
        !           417:                            fixerr(MESS(2208, "TEST-unit reports no outcome"));
        !           418:                        }
        !           419:                        break;
        !           420:                case 'Z':
        !           421:                        if (!is_cmd_ref(t) && still_ok && reachable())
        !           422:   fixerr(MESS(2209, "refinement returns no value c.q. reports no outcome"));
        !           423:                        *Branch(t, REF_START)= copy(l1);
        !           424:                        break;
        !           425:                }
        !           426:        }
        !           427: }
        !           428: 
        !           429: /* ******************************************************************** */
        !           430: 
        !           431: Hidden bool is_cmd_ref(t) parsetree t; { /* HACK */
        !           432:        value name= *Branch(t, REF_NAME);
        !           433:        string s= strval(name);
        !           434:        /* return isupper(*s); */
        !           435:        return *s <= 'Z' && *s >= 'A';
        !           436: }
        !           437: 
        !           438: Visible value copydef(f) value f; {
        !           439:        funprd *fpr= Funprd(f);
        !           440:        if (fpr->pre == Use) return Vnil;
        !           441:        return copy(f);
        !           442: }
        !           443: 
        !           444: Hidden bool is_basic_target(v) value v; {
        !           445:        return envassoc(formals, v) ||
        !           446:                locals != Vnil && envassoc(locals, v) ||
        !           447:                envassoc(globals, v) ||
        !           448:                envassoc(mysteries, v);
        !           449: }
        !           450: 
        !           451: Hidden bool is_variable(v) value v; {
        !           452:        value f;
        !           453:        return is_basic_target(v) ||
        !           454:                envassoc(refinements, v) ||
        !           455:                is_zerfun(v, &f);
        !           456: }
        !           457: 
        !           458: Hidden bool is_target(p) parsetree p; {
        !           459:        value v= *Branch(p, First_fieldnr); int k, len;
        !           460:        switch (Nodetype(p)) {
        !           461: 
        !           462:        case TAG:
        !           463:                return is_basic_target(v);
        !           464: 
        !           465:        case SELECTION:
        !           466:        case BEHEAD:
        !           467:        case CURTAIL:
        !           468:        case COMPOUND:
        !           469:                return is_target(v);
        !           470: 
        !           471:        case COLLATERAL:
        !           472:                len= Nfields(v);
        !           473:                k_Overfields {
        !           474:                        if (!is_target(*Field(v, k))) return No;
        !           475:                }
        !           476:                return Yes;
        !           477: 
        !           478:        default:
        !           479:                return No;
        !           480: 
        !           481:        }
        !           482: }
        !           483: 
        !           484: /* ******************************************************************** */
        !           485: 
        !           486: Hidden Procedure f_actuals(formals, pactuals) parsetree formals, *pactuals; {
        !           487:        /* name, actual, next */
        !           488:        value actuals= *pactuals, act, form, next_a, next_f, kw, *pact;
        !           489:        kw= *Branch(actuals, ACT_KEYW);
        !           490:        pact= Branch(actuals, ACT_EXPR); act= *pact;
        !           491:        form= *Branch(formals, FML_TAG);
        !           492:        next_a= *Branch(actuals, ACT_NEXT); next_f= *Branch(formals, FML_NEXT);
        !           493:        if (compare(*Branch(formals, FML_KEYW), kw) != 0)
        !           494:                fixerr3(MESS(2210, "wrong keyword "), kw, 0);
        !           495:        else if (act == Vnil && form != Vnil)
        !           496:                fixerr3(MESS(2211, "missing actual after "), kw, 0);
        !           497:        else if (next_a == Vnil && next_f != Vnil)
        !           498:                fixerr3(MESS(2212, "can't find expected "),
        !           499:                        *Branch(next_f, FML_KEYW), 0);
        !           500:        else if (act != Vnil && form == Vnil)
        !           501:                fixerr3(MESS(2213, "unexpected actual after "), kw, 0);
        !           502:        else if (next_a != Vnil && next_f == Vnil)
        !           503:                fixerr3(MESS(2214, "unexpected keyword "),
        !           504:                        *Branch(next_a, ACT_KEYW), 0);
        !           505:        else {
        !           506:                if (act != Vnil) {
        !           507:                        parsetree st; struct state save;
        !           508:                        hold(&save); here(&st);
        !           509:                        if (is_target(act)) f_targ(pact);
        !           510:                        else f_expr(pact);
        !           511:                        jumpto(Stop); let_go(&save);
        !           512:                        *Branch(actuals, ACT_START)= copy(st);
        !           513:                }
        !           514:                if (still_ok && next_a != Vnil)
        !           515:                        f_actuals(next_f, Branch(actuals, ACT_NEXT));
        !           516:        }
        !           517: }
        !           518: 
        !           519: Hidden Procedure f_ucommand(pt) parsetree *pt; {
        !           520:        value t= *pt, *aa;
        !           521:        parsetree u, *f1= Branch(t, UCMD_NAME), *f2= Branch(t, UCMD_ACTUALS);
        !           522:        release(*Branch(t, UCMD_DEF));
        !           523:        *Branch(t, UCMD_DEF)= Vnil;
        !           524:        if ((aa= envassoc(refinements, *f1)) != Pnil) {
        !           525:                if (*Branch(*f2, ACT_EXPR) != Vnil
        !           526:                                || *Branch(*f2, ACT_NEXT) != Vnil)
        !           527:                        fixerr(MESS(2215, "refinement with parameters"));
        !           528:                else *Branch(t, UCMD_DEF)= copy(*aa);
        !           529:        }
        !           530:        else if (is_unit(*f1, How, &aa)) {
        !           531:                u= How_to(*aa)->unit;
        !           532:                f_actuals(*Branch(u, HOW_FORMALS), f2);
        !           533:        }
        !           534:        else if (still_ok)
        !           535:                fixerr3(MESS(2216, "you haven't told me HOW'TO "), *f1, 0);
        !           536: }
        !           537: 
        !           538: Hidden Procedure f_fpr_formals(t) parsetree t; {
        !           539:        switch (Nodetype(t)) {
        !           540:        case TAG:
        !           541:                break;
        !           542:        case MONF: case MONPRD:
        !           543:                f_targ(Branch(t, MON_RIGHT));
        !           544:                break;
        !           545:        case DYAF: case DYAPRD:
        !           546:                f_targ(Branch(t, DYA_LEFT));
        !           547:                f_targ(Branch(t, DYA_RIGHT));
        !           548:                break;
        !           549:        default:
        !           550:                syserr(MESS(2217, "f_fpr_formals"));
        !           551:        }
        !           552: }
        !           553: 
        !           554: Visible bool modify_tag(name, tag) parsetree *tag; value name; {
        !           555:        value *aa, function;
        !           556:        *tag= NilTree;
        !           557:        if (aa= envassoc(formals, name))
        !           558:                *tag= node3(TAGformal, name, copy(*aa));
        !           559:        else if (locals != Vnil && (aa= envassoc(locals, name)))
        !           560:                *tag= node3(TAGlocal, name, copy(*aa));
        !           561:        else if (aa= envassoc(globals, name))
        !           562:                *tag= node2(TAGglobal, name);
        !           563:        else if (aa= envassoc(mysteries, name))
        !           564:                *tag= node3(TAGmystery, name, copy(*aa));
        !           565:        else if (aa= envassoc(refinements, name))
        !           566:                *tag= node3(TAGrefinement, name, copy(*aa));
        !           567:        else if (is_zerfun(name, &function))
        !           568:                *tag= node3(TAGzerfun, name, copydef(function));
        !           569:        else if (is_zerprd(name, &function))
        !           570:                *tag= node3(TAGzerprd, name, copydef(function));
        !           571:        else return No;
        !           572:        return Yes;
        !           573: }
        !           574: 
        !           575: Hidden Procedure f_etag(pt) parsetree *pt; {
        !           576:        parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
        !           577:        if (modify_tag(name, &t)) {
        !           578:                release(*pt);
        !           579:                *pt= t;
        !           580:                if (Nodetype(t) == TAGzerprd)
        !           581:                        fixerr2(name, MESS(2218, " cannot be used in an expression"));
        !           582:                else
        !           583:                        visit(t);
        !           584:        } else {
        !           585:                fixerr2(name, MESS(2219, " has not yet received a value"));
        !           586:                release(name);
        !           587:        }
        !           588: }
        !           589: 
        !           590: Hidden Procedure f_ttag(pt) parsetree *pt; {
        !           591:        parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
        !           592:        if (modify_tag(name, &t)) {
        !           593:                release(*pt);
        !           594:                *pt= t;
        !           595:                switch (Nodetype(t)) {
        !           596:                case TAGrefinement:
        !           597:                        fixerr(MESS(2220, "a refinement may not be used as a target"));
        !           598:                        break;
        !           599:                case TAGzerfun:
        !           600:                case TAGzerprd:
        !           601:                        fixerr2(name, MESS(2221, " hasn't been initialised or defined"));
        !           602:                        break;
        !           603:                default:
        !           604:                        lvisit(t);
        !           605:                        break;
        !           606:                }
        !           607:        } else {
        !           608:                fixerr2(name, MESS(2222, " hasn't been initialised or defined"));
        !           609:                release(name);
        !           610:        }
        !           611: }
        !           612: 
        !           613: Hidden Procedure f_ctag(pt) parsetree *pt; {
        !           614:        parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
        !           615:        if (modify_tag(name, &t)) {
        !           616:                release(*pt);
        !           617:                *pt= t;
        !           618:                switch (Nodetype(t)) {
        !           619:                case TAGrefinement:
        !           620:                        lvisit(t); /* 'Loc' flag here means 'Test' */
        !           621:                        break;
        !           622:                case TAGzerprd:
        !           623:                        visit(t);
        !           624:                        break;
        !           625:                default:
        !           626:                        fixerr2(name, MESS(2223, " is neither a refined test nor a zeroadic predicate"));
        !           627:                        break;
        !           628:                }
        !           629:        } else {
        !           630:                fixerr2(name, MESS(2224, " is neither a refined test nor a zeroadic predicate"));
        !           631:                release(name);
        !           632:        }
        !           633: }

unix.superglobalmegacorp.com

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