|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ ! 2: ! 3: /* ! 4: $Header: b3loc.c,v 1.4 85/08/27 10:56:45 timo Exp $ ! 5: */ ! 6: ! 7: /* B locations and environments */ ! 8: #include "b.h" ! 9: #include "b0con.h" ! 10: #include "b1obj.h" ! 11: #include "b3env.h" /* for bndtgs */ ! 12: #include "b3sem.h" ! 13: #include "b3sou.h" /* for tarvalue() */ ! 14: #include "b3err.h" /* for still_ok */ ! 15: ! 16: Hidden value* location(l) loc l; { ! 17: value *ll; ! 18: if (Is_locloc(l)) { ! 19: if (!in_env(curnv->tab, l, &ll)) ! 20: error(MESS(3600, "target not initialised")); ! 21: return ll; ! 22: } else if (Is_simploc(l)) { ! 23: simploc *sl= Simploc(l); ! 24: if (!in_env(sl->e->tab, sl->i, &ll)) ! 25: if (Is_locloc(sl->i)) ! 26: error(MESS(3601, "target not initialised")); ! 27: else error3(0, sl->i, ! 28: MESS(3602, " hasn't been initialised")); ! 29: return ll; ! 30: } else if (Is_tbseloc(l)) { ! 31: tbseloc *tl= Tbseloc(l); ! 32: ll= location(tl->R); ! 33: if (still_ok) { ! 34: ll= adrassoc(*ll, tl->K); ! 35: if (ll == Pnil && still_ok) error(MESS(3603, "key not in table")); ! 36: } ! 37: return ll; ! 38: } else { ! 39: syserr(MESS(3604, "call of location with improper type")); ! 40: return (value *) Dummy; ! 41: } ! 42: } ! 43: ! 44: Hidden Procedure uniquify(l) loc l; { ! 45: if (Is_simploc(l)) { ! 46: simploc *sl= Simploc(l); ! 47: value *ta= &(sl->e->tab), ke= sl->i; ! 48: uniql(ta); ! 49: check_location(l); ! 50: if (still_ok) { ! 51: if (Is_compound(*ta)) uniql(Field(*ta, intval(ke))); ! 52: else { value *aa, v; ! 53: VOID uniq_assoc(*ta, ke); ! 54: aa= adrassoc(*ta, ke); ! 55: v= copy(tarvalue(ke, *aa)); ! 56: release(*aa); ! 57: *aa= v; ! 58: uniql(aa); ! 59: } ! 60: } ! 61: } else if (Is_tbseloc(l)) { ! 62: tbseloc *tl= Tbseloc(l); ! 63: value t, ke; ! 64: uniquify(tl->R); ! 65: if (still_ok) { t= *location(tl->R); ke= tl->K; } ! 66: if (still_ok) { ! 67: if (!Is_table(t)) error(MESS(3605, "selection on non-table")); ! 68: else if (empty(t)) error(MESS(3606, "selection on empty table")); ! 69: else { ! 70: check_location(l); ! 71: if (still_ok) VOID uniq_assoc(t, ke); ! 72: } ! 73: } ! 74: } else if (Is_trimloc(l)) { syserr(MESS(3607, "uniquifying trimloc")); ! 75: } else if (Is_compound(l)) { syserr(MESS(3608, "uniquifying comploc")); ! 76: } else syserr(MESS(3609, "uniquifying non-location")); ! 77: } ! 78: ! 79: Visible Procedure check_location(l) loc l; { ! 80: VOID location(l); ! 81: /* location may produce an error message */ ! 82: } ! 83: ! 84: Visible value content(l) loc l; { ! 85: value *ll= location(l); ! 86: return still_ok ? copy(*ll) : Vnil; ! 87: } ! 88: ! 89: Visible loc trim_loc(l, v, sign) loc l; value v; char sign; { ! 90: loc root, res; value text, B, C; ! 91: if (Is_simploc(l) || Is_tbseloc(l)) { ! 92: uniquify(l); /* Call tarvalue at proper time */ ! 93: root= l; ! 94: B= zero; C= zero; ! 95: } else if (Is_trimloc(l)) { ! 96: trimloc *rr= Trimloc(l); ! 97: root= rr->R; ! 98: B= rr->B; C= rr->C; ! 99: } else { ! 100: error(MESS(3610, "trim (@ or |) on target of improper type")); ! 101: return Lnil; ! 102: } ! 103: text= content(root); ! 104: if (!still_ok); ! 105: else if (!Is_text(text)) { ! 106: error(MESS(3611, "in the target t@p or t|p, t does not contain a text")); ! 107: } else { ! 108: value s= size(text), w, x, b_plus_c; ! 109: if (sign == '@') B= sum(B, w=diff(v, one)); ! 110: else { C= sum(C, w=diff(x= diff(s, B), v)); release(x); } ! 111: release(w); ! 112: b_plus_c= sum(B, C); ! 113: if (still_ok && (compare(B,zero)<0 || compare(C,zero)<0 ! 114: || compare(b_plus_c,s)>0)) ! 115: error(MESS(3612, "in the target t@p or t|p, p is out of bounds")); ! 116: else res= mk_trimloc(root, B, C); ! 117: if (sign == '@') release(B); ! 118: else release(C); ! 119: release(s); release(b_plus_c); ! 120: } ! 121: release(text); ! 122: if (still_ok) return res; else return Lnil; ! 123: } ! 124: ! 125: Visible loc tbsel_loc(R, K) loc R; value K; { ! 126: if (Is_simploc(R) || Is_tbseloc(R)) return mk_tbseloc(R, K); ! 127: else error(MESS(3613, "selection on target of improper type")); ! 128: return Lnil; ! 129: } ! 130: ! 131: Visible loc local_loc(i) basidf i; { return mk_simploc(i, curnv); } ! 132: ! 133: Visible loc global_loc(i) basidf i; { return mk_simploc(i, prmnv); } ! 134: ! 135: Hidden Procedure put_trim(v, tl) value v; trimloc *tl; { ! 136: value rr, nn, head, tail, part; ! 137: value B= tl->B, C= tl->C, len, len_minus_c, tail_start; ! 138: rr= *location(tl->R); ! 139: len= size(rr); ! 140: len_minus_c= diff(len, C); release(len); ! 141: tail_start= sum(len_minus_c, one); release(len_minus_c); ! 142: if (compare(B, zero)<0 || compare(C, zero)<0 ! 143: || compare(B, tail_start)>=0) ! 144: error(MESS(3614, "trim (@ or |) on text location out of bounds")); ! 145: else { ! 146: head= curtail(rr, B); /* rr|B */ ! 147: tail= behead(rr, tail_start); /* rr@(#rr-C+1) */ ! 148: part= concat(head, v); release(head); ! 149: nn= concat(part, tail); release(part); release(tail); ! 150: put(nn, tl->R); release(nn); ! 151: } ! 152: release(tail_start); ! 153: } ! 154: ! 155: Visible Procedure put(v, l) value v; loc l; { ! 156: if (Is_locloc(l)) { ! 157: e_replace(v, &curnv->tab, l); ! 158: } else if (Is_simploc(l)) { ! 159: simploc *sl= Simploc(l); ! 160: e_replace(v, &(sl->e->tab), sl->i); ! 161: } else if (Is_trimloc(l)) { ! 162: if (!Is_text(v)) error(MESS(3615, "putting non-text in trim (@ or |)")); ! 163: else put_trim(v, Trimloc(l)); ! 164: } else if (Is_compound(l)) { ! 165: intlet k, len= Nfields(l); ! 166: if (!Is_compound(v)) ! 167: error(MESS(3616, "putting non-compound in compound location")); ! 168: else if (Nfields(v) != Nfields(l)) ! 169: error(MESS(3617, "putting compound in compound location of different length")); ! 170: else k_Overfields { put(*Field(v, k), *Field(l, k)); } ! 171: } else if (Is_tbseloc(l)) { ! 172: tbseloc *tl= Tbseloc(l); value *rootloc; ! 173: uniquify(tl->R); ! 174: if (still_ok) { ! 175: rootloc= location(tl->R); ! 176: if (still_ok && !Is_table(*rootloc)) ! 177: error(MESS(3621, "selection on non-table")); ! 178: if (still_ok) replace(v, rootloc, tl->K); ! 179: } ! 180: } else error(MESS(3618, "putting in non-target")); ! 181: } ! 182: ! 183: /* Check for correct effect of multiple put-command: catches PUT 1, 2 IN x, x. ! 184: The assignment cannot be undone, but this is not considered a problem. ! 185: For trimmed-texts, no checks are made because the language definition ! 186: itself causes problem (try PUT "abc", "" IN x@2|1, x@3|1). */ ! 187: ! 188: Hidden bool putck(v, l) value v; loc l; { ! 189: intlet k, len; value w; ! 190: if (!still_ok) return No; ! 191: if (Is_compound(l)) { ! 192: if (!Is_compound(v) || Nfields(v) != (len= Nfields(l))) ! 193: return No; /* Severe type error */ ! 194: k_Overfields ! 195: { if (!putck(*Field(v, k), *Field(l, k))) return No; } ! 196: return Yes; ! 197: } ! 198: if (Is_trimloc(l)) return Yes; /* Don't check trim locations */ ! 199: w= *location(l); ! 200: /* Unfortunately, this may already cause an error, e.g. after ! 201: PUT 1, {} IN t[1], t. This can't be helped unless we introduce ! 202: a flag so that location will shut up. */ ! 203: return still_ok && compare(v, w) == 0; ! 204: } ! 205: ! 206: /* The check can't be called from within put because put is recursive, ! 207: and so is the check: then, for the inner levels the check would be done ! 208: twice. Moreover, we don't want to clutter up put, which is called ! 209: internally in, many places. */ ! 210: ! 211: Visible Procedure put_with_check(v, l) value v; loc l; { ! 212: intlet i, k, len; bool ok; ! 213: put(v, l); ! 214: if (!still_ok || !Is_compound(l)) ! 215: return; /* Single target can't be wrong */ ! 216: len= Nfields(l); ok= Yes; ! 217: /* Quick check for putting in all different local targets: */ ! 218: k_Overfields { ! 219: if (!IsSmallInt(*Field(l, k))) { ok= No; break; } ! 220: for (i= k-1; i >= 0; --i) { ! 221: if (*Field(l, i) == *Field(l, k)) { ok= No; break; } ! 222: } ! 223: if (!ok) break; ! 224: } ! 225: if (ok) return; /* All different local basic-targets */ ! 226: if (!putck(v, l)) ! 227: error(MESS(3619, "putting different values in same location")); ! 228: } ! 229: ! 230: ! 231: Hidden bool l_exists(l) loc l; { ! 232: if (Is_simploc(l)) { ! 233: simploc *sl= Simploc(l); ! 234: return envassoc(sl->e->tab, sl->i) != Pnil; ! 235: } else if (Is_trimloc(l)) { ! 236: error(MESS(3620, "deleting trimmed (@ or |) target")); ! 237: return No; ! 238: } else if (Is_compound(l)) { ! 239: intlet k, len= Nfields(l); ! 240: k_Overfields { if (!l_exists(*Field(l, k))) return No; } ! 241: return Yes; ! 242: } else if (Is_tbseloc(l)) { ! 243: tbseloc *tl= Tbseloc(l); value *ll; ! 244: uniquify(tl->R); /* call tarvalue() at proper place */ ! 245: if (still_ok) ll= location(tl->R); ! 246: if (still_ok && !Is_table(*ll)) ! 247: error(MESS(3621, "selection on non-table")); ! 248: return still_ok && in_keys(tl->K, *ll); ! 249: } else { ! 250: error(MESS(3622, "deleting non-target")); ! 251: return No; ! 252: } ! 253: } ! 254: ! 255: /* Delete a location if it exists */ ! 256: ! 257: Hidden Procedure l_del(l) loc l; { ! 258: if (Is_simploc(l)) { ! 259: simploc *sl= Simploc(l); ! 260: e_delete(&(sl->e->tab), sl->i); ! 261: } else if (Is_trimloc(l)) { ! 262: error(MESS(3623, "deleting trimmed (@ or |) target")); ! 263: } else if (Is_compound(l)) { ! 264: intlet k, len= Nfields(l); ! 265: k_Overfields { l_del(*Field(l, k)); } ! 266: } else if (Is_tbseloc(l)) { ! 267: tbseloc *tl= Tbseloc(l); ! 268: value *lc; ! 269: uniquify(tl->R); ! 270: if (still_ok) { ! 271: lc= location(tl->R); ! 272: if (in_keys(tl->K, *lc)) delete(lc, tl->K); ! 273: } ! 274: } else error(MESS(3624, "deleting non-target")); ! 275: } ! 276: ! 277: Visible Procedure l_delete(l) loc l; { ! 278: if (l_exists(l)) l_del(l); ! 279: else if (still_ok) error(MESS(3625, "deleting non-existent target")); ! 280: } ! 281: ! 282: Visible Procedure l_insert(v, l) value v; loc l; { ! 283: value *ll; ! 284: uniquify(l); ! 285: if (still_ok) { ! 286: ll= location(l); ! 287: if (!Is_list(*ll)) error(MESS(3626, "inserting in non-list")); ! 288: else insert(v, ll); ! 289: } ! 290: } ! 291: ! 292: Visible Procedure l_remove(v, l) value v; loc l; { ! 293: value *ll; ! 294: uniquify(l); ! 295: if (still_ok) { ! 296: ll= location(l); ! 297: if (!Is_list(*ll)) error(MESS(3627, "removing from non-list")); ! 298: else if (empty(*ll)) error(MESS(3628, "removing from empty list")); ! 299: else remove(v, ll); ! 300: } ! 301: } ! 302: ! 303: /* Warning: choose is only as good as the accuracy of the random-number */ ! 304: /* generator. In particular, for very large values of v, elements will */ ! 305: /* be chosen unfairly. Choose should be rewritten to cope with this */ ! 306: ! 307: Visible Procedure choose(l, v) loc l; value v; { ! 308: value w, s, r; ! 309: if (!Is_tlt(v)) error(MESS(3629, "choosing from non-text, -list or -table")); ! 310: else if (empty(v)) error(MESS(3630, "choosing from empty text, list or table")); ! 311: else { ! 312: /* PUT (floor(random*#v) + 1) th'of v IN l */ ! 313: s= size(v); ! 314: r= prod(w= random(), s); release(w); release(s); ! 315: w= floorf(r); release(r); ! 316: r= sum(w, one); release(w); ! 317: put(w= th_of(r, v), l); release(w); release(r); ! 318: } ! 319: } ! 320: ! 321: Visible Procedure draw(l) loc l; { ! 322: value r= random(); ! 323: put(r, l); ! 324: release(r); ! 325: } ! 326: ! 327: Visible Procedure bind(l) loc l; { ! 328: if (*bndtgs != Vnil) { ! 329: if (Is_simploc(l)) { ! 330: simploc *ll= Simploc(l); ! 331: if (!in(ll->i, *bndtgs)) /* kludge */ /* what for? */ ! 332: insert(ll->i, bndtgs); ! 333: } else if (Is_compound(l)) { ! 334: intlet k, len= Nfields(l); ! 335: k_Overfields { bind(*Field(l, k)); } ! 336: } else error(MESS(3631, "binding non-identifier")); ! 337: } ! 338: l_del(l); ! 339: } ! 340: ! 341: Visible Procedure unbind(l) loc l; { ! 342: if (*bndtgs != Vnil) { ! 343: if (Is_simploc(l)) { ! 344: simploc *ll= Simploc(l); ! 345: if (in(ll->i, *bndtgs)) ! 346: remove(ll->i, bndtgs); ! 347: } else if (Is_compound(l)) { ! 348: intlet k, len= Nfields(l); ! 349: k_Overfields { unbind(*Field(l, k)); } ! 350: } else error(MESS(3632, "unbinding non-identifier")); ! 351: } ! 352: l_del(l); ! 353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.