|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: /* $Header: b2exp.c,v 1.1 84/06/28 00:49:08 timo Exp $ */
3:
4: /* B expression evaluation */
5: #include "b.h"
6: #include "b0con.h"
7: #include "b1obj.h"
8: #include "b1mem.h" /* for ptr */
9: #include "b2env.h"
10: #include "b2syn.h"
11: #include "b2sem.h"
12: #include "b2sou.h"
13:
14: /*************************************************************/
15: /* */
16: /* The operand and operator stacks are modelled as compounds */
17: /* whose first field is the top and whose second field is */
18: /* the remainder of the stack (i.e., linked lists). */
19: /* A cleaner and more efficient implementation of */
20: /* these heavily used stacks would be in order. */
21: /* */
22: /*************************************************************/
23:
24: /* nd = operand, tor = operator (function) */
25:
26: value ndstack, torstack;
27: #define Bot Vnil
28: fun Bra, Ket;
29:
30: Visible Procedure inittors() {
31: ndstack= torstack= Vnil;
32: Bra= mk_fun(-1, -1, Mon, (literal)Dummy, (txptr)Dummy, (txptr)Dummy, (value)Dummy, (bool)Dummy);
33: Ket= mk_fun( 0, 0, Dya, (literal)Dummy, (txptr)Dummy, (txptr)Dummy, (value)Dummy, (bool)Dummy);
34: }
35:
36: Hidden Procedure pop_stack(stack) value *stack; {
37: value oldstack= *stack;
38: *stack= *field(*stack, 1);
39: put_in_field(Vnil, &oldstack, 0); put_in_field(Vnil, &oldstack, 1);
40: release(oldstack);
41: }
42:
43: Hidden value popnd() {
44: value r;
45: if (ndstack == Vnil) syserr("operand stack underflow");
46: r= *field(ndstack, 0);
47: pop_stack(&ndstack);
48: return r;
49: }
50:
51: Hidden Procedure pushnd(nd) value nd; {
52: value s= ndstack;
53: ndstack= mk_compound(2);
54: put_in_field(nd, &ndstack, 0); put_in_field(s, &ndstack, 1);
55: }
56:
57: Hidden Procedure pushmontor(tor) value tor; {
58: value s= torstack;
59: torstack= mk_compound(2);
60: put_in_field(tor, &torstack, 0); put_in_field(s, &torstack, 1);
61: }
62:
63: Hidden Procedure pushdyator(tor2) value tor2; {
64: value tor1; funprd *t1, *t2= Funprd(tor2);
65: intlet L1, H1, L2= t2->L, H2= t2->H;
66: prio: if (torstack == Vnil) syserr("operator stack underflow");
67: tor1= *field(torstack, 0); t1= Funprd(tor1),
68: L1= t1->L; H1= t1->H;
69: if (L2 > H1)
70: if (tor2 == Ket) {
71: if (tor1 != Bra)
72: syserr("local operator stack underflow");
73: pop_stack(&torstack);
74: }
75: else pushmontor(tor2);
76: else if (L1 >= H2) {
77: value nd1= Vnil, nd2= popnd();
78: if (t1->adic == Dya) nd1= popnd();
79: pushnd(formula(nd1, tor1, nd2));
80: if (xeq) {
81: release(nd2);
82: release(nd1);
83: }
84: pop_stack(&torstack);
85: goto prio;
86: } else pprerr("priorities? use ( and ) to resolve", "");
87: }
88:
89: Forward value basexpr();
90: Forward value text_dis();
91: Forward value tl_dis();
92:
93: Hidden value statabsel(t, k) value t, k; {
94: /* temporary, while no static type check */
95: return mk_elt();
96: }
97:
98: Visible value expr(q) txptr q; {
99: value c, v; txptr i, j; intlet len, k;
100: if ((len= 1+count(",", q)) == 1) return basexpr(q);
101: c= mk_compound(len);
102: k_Overfields {
103: if (Lastfield(k)) i= q;
104: else req(",", q, &i, &j);
105: v= basexpr(i);
106: put_in_field(v, &c, k);
107: if (!Lastfield(k)) tx= j;
108: }
109: return c;
110: }
111:
112: Hidden value basexpr(q) txptr q; {
113: value v= obasexpr(q);
114: Skipsp(tx);
115: if (tx < q && Char(tx) == ',')
116: parerr("no commas allowed in this context", "");
117: upto(q, "expression");
118: return v;
119: }
120:
121: Forward bool primary(), clocondis();
122:
123: #define Pbot {pushnd(Bot); pushmontor(Bra);}
124: #define Ipush if (!pushing) {Pbot; pushing= Yes;}
125: #define Fpush if (pushing) { \
126: pushnd(v); pushdyator(Ket); v= popnd(); \
127: if (popnd() != Bot) syserr( \
128: xeq ? "formula evaluation awry" : \
129: "formula parsing awry"); \
130: }
131:
132: Visible value obasexpr(q) txptr q; {
133: value v, t; bool pushing= No;
134: nxtnd: Skipsp(tx);
135: nothing(q, "expression");
136: t= tag();
137: if (primary(q, t, &v, Yes)) /* then t is released */;
138: else if (t != Vnil) {
139: value f;
140: if (is_monfun(t, &f)) {
141: release(t);
142: Ipush;
143: pushmontor(f);
144: goto nxtnd;
145: } else {
146: release(t);
147: error("target has not yet received a value");
148: }
149: } else if (Montormark(Char(tx))) {
150: Ipush;
151: pushmontor(montor());
152: goto nxtnd;
153: } else parerr("no expression where expected", "");
154: /* We are past an operand and look for an operator */
155: Skipsp(tx);
156: if (tx < q) {
157: txptr tx0= tx; bool lt, eq, gt;
158: if (Letter(Char(tx))) {
159: fun f;
160: t= tag();
161: if (is_dyafun(t, &f)) {
162: release(t);
163: Ipush;
164: pushnd(v);
165: pushdyator(f);
166: goto nxtnd;
167: }
168: release(t);
169: } else if (relop(<, &eq, >));
170: else if (Dyatormark(Char(tx))) {
171: Ipush;
172: pushnd(v);
173: pushdyator(dyator());
174: goto nxtnd;
175: }
176: tx= tx0;
177: }
178: Fpush;
179: return v;
180: }
181:
182: Hidden bool clocondis(q, p) txptr q; value *p; {
183: txptr i, j;
184: Skipsp(tx);
185: nothing(q, "expression");
186: if (Char(tx) == '(') {
187: tx++; req(")", q, &i, &j);
188: *p= expr(i); tx= j;
189: return Yes;
190: }
191: if (Dig(Char(tx)) || Char(tx) == '.' || Char(tx) == 'E' &&
192: (Dig(Char(tx+1)) || Char(tx+1)=='+' || Char(tx+1)=='-')) {
193: *p= constant(q);
194: return Yes;
195: }
196: if (Char(tx) == '\'' || Char(tx) == '"') {
197: *p= text_dis(q);
198: return Yes;
199: }
200: if (Char(tx) == '{') {
201: *p= tl_dis(q);
202: return Yes;
203: }
204: return No;
205: }
206:
207: Hidden bool primary(q, t, p, tri) txptr q; value t, *p; bool tri; {
208: /* If a tag has been seen, it is held in t.
209: Releasing t is a task of primary, but only if the call succeeds. */
210: fun f; value tt, relt= Vnil; value *aa= &t;
211: if (t != Vnil) /* tag */ {
212: if (xeq) {
213: tt= t;
214: aa= lookup(t);
215: if (aa == Pnil) {
216: if (is_zerfun(t, &f)) {
217: t= formula(Vnil, f, Vnil);
218: aa= &t;
219: } else return No;
220: } else if (Is_refinement(*aa)) {
221: ref_et(*aa, Ret); t= resval; resval= Vnil;
222: aa= &t;
223: } else if (Is_formal(*aa)) {
224: t= eva_formal(*aa);
225: aa= &t;
226: } else if (Is_shared(*aa)) {
227: if (!in_env(prmnv->tab, t, &aa)) return No;
228: if (Is_filed(*aa))
229: if (!is_tloaded(t, &aa)) return No;
230: t= Vnil;
231: } else if (Is_filed(*aa)) {
232: if (!is_tloaded(t, &aa)) return No;
233: t= Vnil;
234: } else t= Vnil;
235: release(tt);
236: }
237: } else if (clocondis(q, &t)) aa= &t;
238: else return No;
239: Skipsp(tx);
240: while (tx < q && Char(tx) == '[') {
241: txptr i, j; value s;
242: tx++; req("]", q, &i, &j);
243: s= expr(i); tx= j;
244: /* don't copy table for selection */
245: if (xeq) {
246: aa= adrassoc(*aa, s);
247: release(s);
248: relt= t;
249: if (aa == Pnil) error("key not in table");
250: } else {
251: t= statabsel(tt= t, s);
252: release(tt); release(s);
253: }
254: Skipsp(tx);
255: }
256: if (tri && tx < q && (Char(tx) == '@' || Char(tx) == '|')) {
257: intlet B, C;
258: if (xeq && !Is_text(*aa))
259: parerr("in t@p or t|p, t is not a text", "");
260: trimbc(q, xeq ? length(*aa) : 0, &B, &C);
261: if (xeq) {
262: relt= t;
263: t= trim(*aa, B, C);
264: aa= &t;
265: }
266: }
267: *p= t == Vnil || relt != Vnil ? copy(*aa) : t;
268: release(relt);
269: return Yes;
270: }
271:
272: Forward intlet trimi();
273:
274: Visible Procedure trimbc(q, len, B, C) txptr q; intlet len, *B, *C; {
275: char bc; intlet N;
276: *B= *C= 0;
277: while (tx < q && (Char(tx) == '@' || Char(tx) == '|')) {
278: bc= Char(tx++);
279: N= trimi(q);
280: if (bc == '@') *B+= N-1;
281: else *C+= (len-*B-*C)-N;
282: if (*B < 0 || *C < 0 || *B+*C > len)
283: error("in t@p or t|p, p is out of bounds");
284: Skipsp(tx);
285: }
286: }
287:
288: Hidden intlet trimi(q) txptr q; {
289: value v, t; bool pushing= No;
290: nxtnd: Skipsp(tx);
291: nothing(q, "expression");
292: t= tag();
293: if (primary(q, t, &v, No)); /* then t is released */
294: else if (t != Vnil) {
295: value f;
296: if (is_monfun(t, &f)) {
297: release(t);
298: Ipush;
299: pushmontor(f);
300: goto nxtnd;
301: } else {
302: release(t);
303: error("target has not yet received a value");
304: }
305: } else if (Montormark(Char(tx))) {
306: Ipush;
307: pushmontor(montor());
308: goto nxtnd;
309: } else parerr("no expression where expected", "");
310: Fpush;
311: {int ii; intlet i= 0;
312: if (xeq) {
313: ii= intval(v);
314: if (ii < 0) error("in t@p or t|p, p is negative");
315: if (ii > Maxintlet)
316: error("in t@p or t|p, p is excessive");
317: i= ii;
318: }
319: release(v);
320: return i;
321: }
322: }
323:
324: Visible value constant(q) txptr q; {
325: bool dig= No; txptr first= tx;
326: while (tx < q && Dig(Char(tx))) {
327: ++tx;
328: dig= Yes;
329: }
330: if (tx < q && Char(tx) == '.') {
331: tx++;
332: while (tx < q && Dig(Char(tx))) {
333: dig= Yes;
334: ++tx;
335: }
336: if (!dig) pprerr("point without digits", "");
337: }
338: if (tx < q && Char(tx) == 'E') {
339: tx++;
340: if (!(Dig(Char(tx))) && Keymark(Char(tx))) {
341: tx--;
342: goto done;
343: }
344: if (tx < q && (Char(tx) == '+' || Char(tx) == '-')) ++tx;
345: dig= No;
346: while (tx < q && Dig(Char(tx))) {
347: dig= Yes;
348: ++tx;
349: }
350: if (!dig) parerr("E not followed by exponent", "");
351: }
352: done: return numconst(first, tx);
353: }
354:
355: char txdbuf[TXDBUFSIZE];
356: txptr txdbufend= &txdbuf[TXDBUFSIZE];
357:
358: Visible Procedure concat_to(v, s) value* v; string s; { /*TEMPORARY*/
359: value v1, v2;
360: if (*v == Vnil) *v= mk_text(s);
361: else {
362: *v= concat(v1= *v, v2= mk_text(s));
363: release(v1); release(v2);
364: }
365: }
366:
367: Hidden value text_dis(q) txptr q; {
368: char aq[2]; txptr tp= txdbuf; value t= Vnil, t1, t2;
369: aq[1]= '\0'; *aq= Char(tx++);
370: fbuf: while (tx < q && Char(tx) != *aq) {
371: if (Char(tx) == '`') {
372: if (Char(tx+1) == '`') tx++;
373: else {
374: *tp= '\0';
375: concat_to(&t, txdbuf);
376: t= concat(t1= t, t2= conversion(q));
377: release(t1); release(t2);
378: tp= txdbuf; goto fbuf;
379: }
380: }
381: *tp++= Char(tx++);
382: if (tp+1 >= txdbufend) {
383: *(txdbufend-1)= '\0';
384: concat_to(&t, txdbuf);
385: tp= txdbuf;
386: }
387: }
388: if (tx >= q) parerr("cannot find matching ", aq);
389: if (++tx < q && Char(tx) == *aq) {
390: *tp++= Char(tx++);
391: goto fbuf;
392: }
393: *tp= '\0';
394: concat_to(&t, txdbuf);
395: return t;
396: }
397:
398: Visible value conversion(q) txptr q; {
399: txptr f, t; value v, c;
400: thought('`');
401: req("`", q, &f, &t);
402: v= expr(f); c= Ifxeq(convert(v, Yes, Yes));
403: if (xeq) release(v);
404: tx= t; return c;
405: }
406:
407: Hidden value tl_dis(q) txptr q; {
408: txptr f, t, ff, tt;
409: intlet len, k;
410: thought('{');
411: Skipsp(tx);
412: if (Char(tx) == '}') {
413: tx++;
414: return Ifxeq(mk_elt());
415: }
416: req("}", q, &f, &t);
417: if (find("..", f, &ff, &tt)) {
418: value enu, lo, hi;
419: lo= basexpr(ff);
420: if (!xeq || Is_number(lo)) {
421: tx= tt; while (Char(tx) == '.') tx++;
422: hi= basexpr(f);
423: if (xeq) {
424: value entries;
425: if (!integral(lo))
426: error("in {p..q}, p is a number but not an integer");
427: if (!Is_number(hi))
428: error("in {p..q}, p is a number but q is not");
429: if (!integral(hi))
430: error("in {p..q}, q is a number but not an integer");
431: entries= diff(lo, hi);
432: if (compare(entries, one)>0)
433: error("in {p..q}, integer q < x < p");
434: enu= mk_numrange(lo, hi);
435: release(entries);
436: } else enu= mk_elt();
437: release(hi); release(lo);
438: } else if (Is_text(lo)) {
439: char a, z;
440: if (!character(lo))
441: error("in {p..q}, p is a text but not a character");
442: tx= tt; hi= basexpr(f);
443: if (!Is_text(hi))
444: error("in {p..q}, p is a text but q is not");
445: if (!character(hi))
446: error("in {p..q}, q is a text but not a character");
447: a= charval(lo); z= charval(hi);
448: if (z < a-1) error("in {p..q}, character q < x < p");
449: enu= mk_charrange(lo, hi);
450: release(lo); release(hi);
451: } else error("in {p..q}, p is neither a number nor a text");
452: tx= t; return enu;
453: }
454: len= 1+count(";", f);
455: Skipsp(tx);
456: if (Char(tx) == '[') {
457: value ta, ke, a;
458: ta= mk_elt();
459: k_Over_len {
460: Skipsp(tx);
461: need("[");
462: req("]", f, &ff, &tt);
463: ke= expr(ff); tx= tt;
464: need(":");
465: if (Last(k)) {ff= f; tt= t;}
466: else req(";", f, &ff, &tt);
467: a= basexpr(ff); tx= tt;
468: replace(a, &ta, ke);
469: release(ke); release(a);
470: }
471: return ta;
472: }
473: {value l, v;
474: l= mk_elt();
475: k_Over_len {
476: if (Last(k)) {ff= f; tt= t;}
477: else req(";", f, &ff, &tt);
478: v= basexpr(ff); tx= tt;
479: insert(v, &l);
480: release(v);
481: }
482: return l;
483: }
484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.