|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ ! 2: /* $Header: b2uni.c,v 1.1 84/06/28 00:49:27 timo Exp $ */ ! 3: ! 4: /* B units */ ! 5: #include "b.h" ! 6: #include "b1obj.h" ! 7: #include "b1mem.h" /* for ptr */ ! 8: #include "b2fil.h" ! 9: #include "b2env.h" ! 10: #include "b2scr.h" ! 11: #include "b2err.h" ! 12: #include "b2key.h" ! 13: #include "b2syn.h" ! 14: #include "b2sou.h" ! 15: #include "b2sem.h" ! 16: ! 17: Forward loc fopnd(), fop(), basfop(); ! 18: ! 19: value resval; outcome resout; ! 20: bool terminated; ! 21: value global; ! 22: value formlist, sharelist; envtab reftab; ! 23: bool forming; ! 24: ! 25: Visible Procedure get_unit(filed) bool filed; { ! 26: bool xeq0= xeq, hu= No, yu= No, tu= No; ! 27: txptr fux= tx, lux; ! 28: value u; literal adic; ! 29: if ((hu= atkw(HOW_TO)) || (yu= atkw(YIELD)) || (tu= atkw(TEST))) { ! 30: lino= 1; uname= aster; ! 31: if (cur_ilev != 0) parerr("unit starts with indentation", ""); ! 32: cntxt= In_unit; ! 33: Skipsp(tx); ! 34: formlist= mk_elt(); ! 35: if (hu) { ! 36: txptr utx, vtx; value f; ! 37: uname= keyword(ceol); utype= FHW; ! 38: req(":", ceol, &utx, &vtx); ! 39: Skipsp(tx); ! 40: while (tx < utx) { ! 41: if (Cap(Char(tx))) goto nxt_kw; ! 42: if (!Letter(Char(tx))) ! 43: parerr("no formal parameter where expected", ""); ! 44: f= tag(); ! 45: if (in(f, formlist)) ! 46: pprerr("multiple use of formal parameter", ""); ! 47: insert(f, &formlist); ! 48: release(f); ! 49: Skipsp(tx); ! 50: nxt_kw: if (tx < utx) { ! 51: release(keyword(utx)); ! 52: Skipsp(tx); ! 53: } ! 54: } ! 55: tx= vtx; ! 56: } else { ! 57: ytu_heading(&uname, &adic, ceol, Yes); ! 58: utype= adic == Zer ? FZR : adic == Mon ? FMN : FDY; ! 59: } ! 60: xeq= No; ! 61: sharelist= mk_elt(); ! 62: unicomm_suite(); ! 63: Mark_unit_end(tx); ! 64: reftab= mk_elt(); ! 65: ref_suite(); ! 66: lux= tx+1; ! 67: adjust_unit(&fux, &lux, &reftab); ! 68: u= hu ? mk_how(fux, lux, reftab, filed) : ! 69: yu ? mk_fun(1, 8, adic, Use, fux, lux, reftab, filed) ! 70: : mk_prd(adic, Use, fux, lux, reftab, filed); ! 71: def_unit(u, uname, utype); ! 72: release(sharelist); release(u); release(formlist); release(uname); ! 73: xeq= xeq0; ! 74: } else parerr("no HOW'TO, YIELD or TEST where expected", ""); ! 75: } ! 76: ! 77: Visible Procedure ytu_heading(name, adic, wtx, form) ! 78: value *name; literal *adic; txptr wtx; bool form; { ! 79: /* xeq == No */ ! 80: intlet ad= 0; value t1= Vnil, t2= Vnil, t3= Vnil; ! 81: forming= form; /*should be a parameter to fopnd()*/ ! 82: Skipsp(tx); ! 83: if (Montormark(Char(tx))) ! 84: parerr("user defined functions or predicates must be tags", ""); ! 85: if (Letter(Char(tx))) *name= t1= tag(); ! 86: else if (Char(tx) == '(') { ! 87: if (fopnd(wtx) == Vnil) /* ignore */; ! 88: } else parerr("something unexpected instead of formal formula", ""); ! 89: Skipsp(tx); ! 90: if (Char(tx) == ':') goto postff; ! 91: if (Dyatormark(Char(tx))) ! 92: parerr("user defined functions or predicates must be tags", ""); ! 93: if (Letter(Char(tx))) { ! 94: t2= tag(); ! 95: if (t1 == Vnil) *name= t2; ! 96: } else if (Char(tx) == '(') { ! 97: if (t1 == Vnil) parerr("no function name where expected", ""); ! 98: if (fopnd(wtx) == Vnil) /* ignore */; ! 99: } else parerr("no function name or formal operand where expected", ""); ! 100: ad= 1; ! 101: Skipsp(tx); ! 102: if (Char(tx) == ':') { ! 103: if (t1 == Vnil) nothing(tx, "second formal operand"); ! 104: goto postff; ! 105: } ! 106: if (t2 == Vnil) ! 107: parerr("something unexpected following monadic formal formula", ""); ! 108: *name= t2; ! 109: if (forming && t1 != Vnil) insert(t1, &formlist); ! 110: if (Letter(Char(tx))) { ! 111: t3= tag(); ! 112: if (forming) insert(t3, &formlist); ! 113: } else if (Char(tx) == '(') { ! 114: if (fopnd(wtx) == Vnil) /* ignore */; ! 115: } else parerr("no formal operand where expected", ""); ! 116: ad= 2; ! 117: Skipsp(tx); ! 118: if (Char(tx) != ':') ! 119: parerr("something unexpected following dyadic formal formula", ""); ! 120: postff: if (t1 != Vnil && t1 != *name) release(t1); ! 121: if (t2 != Vnil && t2 != *name) release(t2); ! 122: if (t3 != Vnil) release(t3); ! 123: *adic= ad == 0 ? Zer : ad == 1 ? Mon : Dya; ! 124: tx++; ! 125: } ! 126: ! 127: Hidden value mk_formal(ftx) txptr ftx; { /* Move */ ! 128: value f= grab_for(); formal *fp= Formal(f); ! 129: sv_context(&(fp->con)); fp->ftx= ftx; ! 130: return f; ! 131: } ! 132: ! 133: Visible bool udc() { ! 134: value un, *aa; context ic, hc; envchain nw_envchain; ! 135: txptr tx0= tx, uux, vux, wux; bool formals= No; ! 136: if (!Cap(Char(tx))) return No; ! 137: if (!xeq) { ! 138: tx= ceol; ! 139: if (skipping) parerr("X", ""); /* to prevent skipping= No; */ ! 140: return Yes; ! 141: } ! 142: un= keyword(ceol); ! 143: debug("udc^ called"); ! 144: sv_context(&ic); ! 145: if (!is_unit(un, FHW, &aa)) { ! 146: release(un); ! 147: tx= tx0; ! 148: return No; ! 149: } ! 150: if (!Is_howto(*aa)) syserr("no howto associated with keyword"); ! 151: curnv= &nw_envchain; ! 152: curnv->tab= mk_elt(); curnv->inv_env= Enil; ! 153: cntxt= In_unit; resexp= Voi; uname= un; utype= FHW; ! 154: cur_ilev= 0; lino= 1; ! 155: tx= (How_to(*aa))->fux; ! 156: terminated= No; ! 157: debug("ready to howto"); ! 158: findceol(); ! 159: wux= ceol; req(":", wux, &uux, &vux); ! 160: if (!atkw(HOW_TO) || (compare(uname= keyword(uux), un) != 0)) ! 161: syserr("out of phase in udc"); ! 162: release(un); ! 163: Skipsp(tx); ! 164: while (tx < uux) { ! 165: txptr ftx, ttx, fux, tux; ! 166: value fp, ap, kw; ! 167: kw= findkw(uux, &fux, &tux); ! 168: if (Letter(Char(tx))) fp= bastarg(fux); ! 169: else if (tx < fux) { ! 170: release(kw); ! 171: parerr("no formal parameter where expected", ""); ! 172: } else fp= Vnil; ! 173: sv_context(&hc); set_context(&ic); ! 174: if (fux == uux) ftx= ttx= ceol; ! 175: else reqkw(strval(kw), &ftx, &ttx); /*dangerous use of strval*/ ! 176: release(kw); ! 177: if (fp != Vnil) { ! 178: Skipsp(tx); ! 179: nothing(ftx, "actual parameter"); ! 180: ap= mk_formal(ftx); formals= Yes; ! 181: } else { ! 182: Skipsp(tx); ! 183: if (tx < ftx) ! 184: parerr("actual parameter without formal", ""); ! 185: } ! 186: tx= ttx; ! 187: sv_context(&ic); set_context(&hc); ! 188: if (fp != Vnil) { ! 189: put(ap, fp); release(fp); release(ap); ! 190: } ! 191: tx= tux; Skipsp(tx); ! 192: } ! 193: tx= vux; ! 194: add_reftab((How_to(*aa))->reftab); ! 195: if (formals) curnv->inv_env= ic.curnv; ! 196: unicomm_suite(); terminated= No; ! 197: release(curnv->tab); release(uname); ! 198: set_context(&ic); ! 199: return Yes; ! 200: } ! 201: ! 202: Visible value eva_formal(f) value f; { ! 203: value v; formal *ff= Formal(f); context cc; ! 204: if (!Is_formal(f)) syserr("eva_formal has wrong argument"); ! 205: sv_context(&cc); if (cntxt != In_formal) how_context= cc; ! 206: set_context(&ff->con); cntxt= In_formal; ! 207: v= expr(ff->ftx); ! 208: set_context(&cc); ! 209: return v; ! 210: } ! 211: ! 212: Visible loc loc_formal(f) value f; { ! 213: loc l; formal *ff= Formal(f); context cc; ! 214: if (!Is_formal(f)) syserr("loc_formal has wrong argument"); ! 215: sv_context(&cc); if (cntxt != In_formal) how_context= cc; ! 216: set_context(&ff->con); cntxt= In_formal; ! 217: l= targ(ff->ftx); ! 218: set_context(&cc); ! 219: return l; ! 220: } ! 221: ! 222: Visible bool ref_com() { ! 223: /* if !xeq, ref_com always returns Yes unless skipping */ ! 224: value rn, *aa, rname; context ic; ! 225: txptr tx0= tx, wux; ! 226: if (!Cap(Char(tx))) return No; ! 227: debug("ref_com^ called"); ! 228: if (!xeq) { ! 229: tx= ceol; ! 230: if (skipping) parerr("X", ""); /* to prevent skipping= No; */ ! 231: return Yes; ! 232: } ! 233: rn= keyword(ceol); ! 234: aa= lookup(rn); ! 235: if (aa == Pnil) { ! 236: release(rn); ! 237: tx= tx0; ! 238: return No; ! 239: } ! 240: if (!Is_refinement(*aa)) syserr("no refinement associated with keyword"); ! 241: upto(ceol, "refined-command"); ! 242: sv_context(&ic); ! 243: cntxt= In_unit; resexp= Voi; ! 244: cur_ilev= 0; ! 245: lino= (Refinement(*aa))->rlino; ! 246: tx= (Refinement(*aa))->rp; ! 247: terminated= No; ! 248: debug("ready to execute refinement"); ! 249: findceol(); ! 250: wux= ceol; ! 251: if (compare(rname= keyword(wux), rn) != 0) ! 252: syserr("out of phase in ref_com"); ! 253: thought(':'); ! 254: comm_suite(); terminated= No; ! 255: release(rn); release(rname); ! 256: set_context(&ic); ! 257: return Yes; ! 258: } ! 259: ! 260: Visible Procedure udfpr(nd1, fpr, nd2, re) value nd1, nd2; funprd *fpr; literal re; { ! 261: context ic; envchain nw_envchain; value f; ! 262: txptr uux, vux, wux; ! 263: debug("udfpr^ called"); ! 264: sv_context(&ic); ! 265: curnv= &nw_envchain; ! 266: curnv->tab= mk_elt(); curnv->inv_env= Enil; ! 267: cntxt= In_unit; resexp= re; uname= aster; ! 268: cur_ilev= 0; lino= 1; ! 269: tx= fpr->fux; ! 270: resval= Vnil; resout= Und; terminated= No; ! 271: debug("ready to Yield/Test"); ! 272: findceol(); ! 273: wux= ceol; req(":", wux, &uux, &vux); ! 274: if (!atkw(YIELD) && !atkw(TEST)) syserr("out of phase in udfpr"); ! 275: Skipsp(tx); ! 276: switch (fpr->adic) { ! 277: case Zer: ! 278: uname= tag(); utype= FZR; ! 279: break; ! 280: case Mon: ! 281: uname= tag(); utype= FMN; ! 282: put(nd2, f= fopnd(uux)); release(f); ! 283: break; ! 284: case Dya: ! 285: put(nd1, f= fopnd(uux)); release(f); ! 286: uname= tag(); utype= FDY; ! 287: put(nd2, f= fopnd(uux)); release(f); ! 288: break; ! 289: } ! 290: thought(':'); ! 291: tx= vux; ! 292: add_reftab(fpr->reftab); ! 293: unicomm_suite(); terminated= No; ! 294: if (xeq) { ! 295: if (re == Ret && resval == Vnil) ! 296: error("command-suite of YIELD-unit returns no value"); ! 297: if (re == Rep && resout == Und) ! 298: error("command-suite of TEST-unit reports no outcome"); ! 299: } ! 300: terminated= No; ! 301: release(curnv->tab); release(uname); ! 302: set_context(&ic); ! 303: } ! 304: ! 305: #define NET 8 ! 306: ! 307: Visible Procedure ref_et(rfv, re) value rfv; literal re; { ! 308: context ic; value bndtglist, rname; env ee; bool prmnv_saved= No; ! 309: envtab svperm_envtab= Vnil, et0, envtabs[NET], *et, *etp; intlet etl; ! 310: txptr uux, vux, wux; ! 311: debug("ref_et^ called"); ! 312: if (!Is_refinement(rfv)) syserr("ref_et called with non-refinement"); ! 313: sv_context(&ic); ! 314: ee= curnv; etl= 0; ! 315: while (ee != Enil) { ! 316: if (ee == prmnv) break; ! 317: etl++; ! 318: ee= ee->inv_env; ! 319: } ! 320: if (etl <= NET) et= envtabs; ! 321: else et= (envtab *) getmem((unsigned)etl*sizeof(value)); ! 322: ee= curnv; etp= et; ! 323: while (ee != Enil) { ! 324: if (ee == prmnv) { ! 325: if (prmnvtab == Vnil) { ! 326: /* the original permanent environment */ ! 327: prmnvtab= prmnv->tab; ! 328: prmnv->tab= copy(prmnvtab); ! 329: } else svperm_envtab= copy(prmnv->tab); ! 330: prmnv_saved= Yes; ! 331: break; ! 332: } ! 333: *etp++= copy(ee->tab); ! 334: ee= ee->inv_env; ! 335: } ! 336: if (resexp == Voi && !prmnv_saved) { ! 337: /* possible access through SHARE */ ! 338: if (prmnvtab == Vnil) { ! 339: prmnvtab= prmnv->tab; ! 340: prmnv->tab= copy(prmnvtab); ! 341: } else svperm_envtab= copy(prmnv->tab); ! 342: prmnv_saved= Yes; ! 343: } ! 344: bndtglist= mk_elt(); bndtgs= &bndtglist; ! 345: cntxt= In_unit; resexp= re; ! 346: cur_ilev= 0; ! 347: lino= (Refinement(rfv))->rlino; ! 348: tx= (Refinement(rfv))->rp; ! 349: resval= Vnil; resout= Und; terminated= No; ! 350: debug("ready to eval/test refinement"); ! 351: findceol(); ! 352: wux= ceol; req(":", wux, &uux, &vux); ! 353: rname= tag(); thought(':'); ! 354: comm_suite(); ! 355: if (xeq) { ! 356: if (re == Ret && resval == Vnil) ! 357: error("refinement returns no value"); ! 358: if (re == Rep && resout == Und) ! 359: error("refinement reports no outcome"); ! 360: } ! 361: terminated= No; ! 362: release (rname); ! 363: ee= curnv; etp= et; ! 364: while (ee != Enil) { ! 365: if (ee == prmnv) break; ! 366: if (ee == curnv) et0= ee->tab; else release(ee->tab); ! 367: ee->tab= *etp++; ! 368: ee= ee->inv_env; ! 369: } ! 370: if (prmnv_saved) { ! 371: release(prmnv->tab); ! 372: if (svperm_envtab == Vnil) { ! 373: prmnv->tab= prmnvtab; ! 374: prmnvtab= Vnil; ! 375: } else prmnv->tab= svperm_envtab; ! 376: } ! 377: set_context(&ic); ! 378: if (curnv != prmnv) { ! 379: if (re == Rep) extbnd_tags(bndtglist, &(curnv->tab), et0); ! 380: release(et0); ! 381: } ! 382: release(bndtglist); ! 383: if (etl > NET) freemem((ptr) et); ! 384: } ! 385: ! 386: Hidden loc fopnd(q) txptr q; { ! 387: txptr ttx; ! 388: Skipsp(tx); ! 389: if (tx >= q) syserr("fopnd called when it should not be"); ! 390: if (Letter(Char(tx))) { ! 391: ttx= tx+1; while(Tagmark(Char(ttx))) ttx++; ! 392: } else if (Char(tx) == '(') { ! 393: txptr tx0= tx++, ftx; ! 394: req(")", q, &ftx, &ttx); ! 395: tx= tx0; ! 396: } else syserr("fopnd does not see formal operand"); ! 397: return basfop(ttx); ! 398: } ! 399: ! 400: Hidden loc fop(q) txptr q; { ! 401: value c=Vnil; loc l; txptr i, j; intlet len, k; ! 402: if ((len= 1+count(",", q)) == 1) return basfop(q); ! 403: if (xeq) c= mk_compound(len); ! 404: k_Overfields { ! 405: if (!Lastfield(k)) req(",", q, &i, &j); ! 406: else i= q; ! 407: l= basfop(i); ! 408: if (xeq) put_in_field(l, &c, k); ! 409: if (!Lastfield(k)) tx= j; ! 410: } ! 411: return (loc) c; ! 412: } ! 413: ! 414: Hidden loc basfop(q) txptr q; { ! 415: loc l= Vnil; txptr i, j; ! 416: Skipsp(tx); ! 417: nothing(q, "formal operand"); ! 418: if (Char(tx) == '(') { ! 419: tx++; req(")", q, &i, &j); ! 420: l= fop(i); tx= j; ! 421: } else if (Letter(Char(tx))) { ! 422: value t= tag(); ! 423: if (forming && !xeq) insert(t, &formlist); ! 424: else l= local_loc(t); ! 425: release(t); ! 426: } else parerr("no formal operand where expected", ""); ! 427: return l; ! 428: } ! 429: ! 430: Hidden Procedure unicomm_suite() { ! 431: if (ateol()) { ! 432: while (ilev(Yes) > 0 && atkw(SHARE)) { ! 433: findceol(); ! 434: share(ceol); ! 435: To_eol(tx); ! 436: } ! 437: veli(); ! 438: if (cur_ilev > 0) { ! 439: cur_ilev= 0; ! 440: comm_suite(); ! 441: } ! 442: } else command(); ! 443: } ! 444: ! 445: Hidden Procedure share(q) txptr q; { ! 446: intlet n, k; ! 447: Skipsp(tx); ! 448: n= 1+count(",", q); ! 449: for (k= 0; k < n; k++) { ! 450: txptr i, j; ! 451: if (k < n-1) req(",", q, &i, &j); ! 452: else i= q; ! 453: sharebas(i); ! 454: if (k < n-1) need(","); ! 455: } ! 456: upto(q, "SHAREd identifier"); ! 457: } ! 458: ! 459: #define SH_IN_USE "SHAREd identifier is already in use as formal parameter or operand" ! 460: ! 461: Hidden Procedure sharebas(q) txptr q; { ! 462: Skipsp(tx); ! 463: nothing(q, "SHAREd identifier"); ! 464: if (Char(tx) == '(') { ! 465: txptr i, j; ! 466: tx++; req(")", q, &i, &j); ! 467: share(i); tx= j; ! 468: } else if (Letter(Char(tx))) { ! 469: value t= tag(); ! 470: if (!xeq) { ! 471: if (in(t, formlist)) pprerr(SH_IN_USE, ""); ! 472: insert(t, &sharelist); ! 473: } else if (resexp == Voi) { /*ie we're in a HOW'TO*/ ! 474: loc l; value *aa= lookup(t); ! 475: if (aa == Pnil) { ! 476: put(global, l= local_loc(t)); ! 477: release(l); ! 478: } ! 479: } else { /*we're in a TEST or YIELD*/ ! 480: loc l= global_loc(t); ! 481: value g= content(l); ! 482: release(l); ! 483: put(g, l= local_loc(t)); ! 484: release(l); release(g); ! 485: /* can this be achieved by scratch-pad copying? */ ! 486: } ! 487: release(t); ! 488: upto(q, "SHAREd identifier"); ! 489: } else parerr("no identifier where expected", ""); ! 490: } ! 491: ! 492: #define REF_IN_USE "refinement-tag is already in use as formal parameter or operand" ! 493: ! 494: Hidden Procedure ref_suite() { ! 495: txptr rp; intlet rlino; value r, kt, *aa; ! 496: rref: if (ilev(Yes) > 0) parerr("indentation where not allowed", ""); ! 497: findceol(); ! 498: if (Cap(Char(tx)) && !atkw(SELECT)) { ! 499: kt= findkw(lcol(), &rp, &tx); ! 500: Skipsp(tx); ! 501: if (Char(tx) != ':') { ! 502: release(kt); ! 503: veli(); return; ! 504: } ! 505: rlino= lino; ! 506: } else if (Letter(Char(tx))) { ! 507: rp= tx; ! 508: while(Tagmark(Char(tx))) tx++; ! 509: Skipsp(tx); ! 510: if (Char(tx) != ':') { ! 511: veli(); return; ! 512: } ! 513: tx= rp; rlino= lino; kt= tag(); ! 514: if (in(kt, formlist)) pprerr(REF_IN_USE, ""); ! 515: if (in(kt, sharelist)) pprerr( ! 516: "refinement-tag is already in use as SHAREd identifier", ""); ! 517: } else { ! 518: veli(); return; ! 519: } ! 520: if (in_env(reftab, kt, &aa)) error("redefinition of refinement"); ! 521: thought(':'); ! 522: r= mk_ref(rp, rlino); ! 523: e_replace(r, &reftab, kt); ! 524: comm_suite(); ! 525: if (!Eol(tx)) syserr("comm_suite does not leave tx at Eol"); ! 526: Mark_unit_end(tx); ! 527: release(r); release(kt); ! 528: goto rref; ! 529: } ! 530: ! 531: Hidden Procedure add_reftab(rt) envtab rt; { ! 532: int k, len; ! 533: if (!Is_table(rt)) syserr("add_reftab called with non_table"); ! 534: len= length(rt); ! 535: k_Over_len { ! 536: e_replace(*assoc(rt, k), &(curnv->tab), *key(rt, k)); ! 537: } ! 538: } ! 539: ! 540: Visible Procedure inithow() { ! 541: aster= mk_text("***"); ! 542: global= grab_glo(); ! 543: } ! 544: ! 545: Hidden Procedure adjust_unit(fux, lux, reftb) txptr *fux, *lux; value *reftb; { ! 546: /* The text of the unit still resides in the text buffer. ! 547: It is moved to an allocated area and the text pointers ! 548: are adjusted accordingly. */ ! 549: txptr tm, ta; int adj, k, len= length(*reftb); ! 550: ! 551: ta= (txptr) getmem((unsigned)(*lux-*fux)*sizeof(*tx)); ! 552: tm= *fux; adj= ta-tm; ! 553: while (tm <= tx) *ta++= *tm++; ! 554: *fux+= adj; *lux+= adj; ! 555: k_Over_len { ! 556: Refinement(*assoc(*reftb, k))->rp+= adj; /*Change*/ ! 557: } ! 558: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.