xref: /csrg-svn/usr.bin/pascal/pdx/tree/eval.c (revision 5782)
15543Slinton /* Copyright (c) 1982 Regents of the University of California */
25543Slinton 
3*5782Slinton static char sccsid[] = "@(#)eval.c 1.3 02/13/82";
45543Slinton 
55543Slinton /*
65562Slinton  * Parse tree evaluation.
75543Slinton  */
85543Slinton 
95543Slinton #include "defs.h"
105543Slinton #include "tree.h"
115543Slinton #include "sym.h"
125543Slinton #include "process.h"
135543Slinton #include "source.h"
145543Slinton #include "mappings.h"
155543Slinton #include "breakpoint.h"
165543Slinton #include "machine.h"
175543Slinton #include "tree.rep"
185543Slinton 
195543Slinton /*
205543Slinton  * Evaluate a parse tree using a stack; value is left at top.
215543Slinton  */
225543Slinton 
235562Slinton #define STACKSIZE 2000
245562Slinton 
255562Slinton STACK stack[STACKSIZE];
265543Slinton STACK *sp = &stack[0];
275543Slinton 
285543Slinton eval(p)
295543Slinton register NODE *p;
305543Slinton {
31*5782Slinton     long r0, r1;
32*5782Slinton     double fr0, fr1;
335543Slinton 
34*5782Slinton     if (p == NULL) {
35*5782Slinton 	return;
36*5782Slinton     }
37*5782Slinton     switch(degree(p->op)) {
38*5782Slinton 	case BINARY:
39*5782Slinton 	    eval(p->right);
40*5782Slinton 	    if (isreal(p->op)) {
41*5782Slinton 		fr1 = pop(double);
42*5782Slinton 	    } else if (isint(p->op)) {
43*5782Slinton 		r1 = pop(long);
44*5782Slinton 	    }
45*5782Slinton 	    /* fall through */
46*5782Slinton 	case UNARY:
47*5782Slinton 	    eval(p->left);
48*5782Slinton 	    if (isreal(p->op)) {
49*5782Slinton 		fr0 = pop(double);
50*5782Slinton 	    } else if (isint(p->op)) {
51*5782Slinton 		r0 = pop(long);
52*5782Slinton 	    }
53*5782Slinton 	    break;
54*5782Slinton 
55*5782Slinton 	default:
56*5782Slinton 	    /* do nothing */;
575543Slinton 	}
58*5782Slinton     switch(p->op) {
59*5782Slinton 	case O_NAME: {
60*5782Slinton 	    SYM *s, *f;
615543Slinton 
62*5782Slinton 	    s = p->nameval;
63*5782Slinton 	    f = container(s);
64*5782Slinton 	    if (!isactive(f)) {
65*5782Slinton 		error("\"%s\" is not active", name(f));
66*5782Slinton 	    }
67*5782Slinton 	    push(int, address(s, NIL));
68*5782Slinton 	    break;
69*5782Slinton 	}
705543Slinton 
71*5782Slinton 	case O_LCON:
72*5782Slinton 	    switch (size(p->nodetype)) {
73*5782Slinton 		case sizeof(char):
74*5782Slinton 		    push(char, p->lconval);
75*5782Slinton 		    break;
765543Slinton 
77*5782Slinton 		case sizeof(short):
78*5782Slinton 		    push(short, p->lconval);
79*5782Slinton 		    break;
805543Slinton 
81*5782Slinton 		case sizeof(long):
82*5782Slinton 		    push(long, p->lconval);
83*5782Slinton 		    break;
845543Slinton 
85*5782Slinton 		default:
86*5782Slinton 		    panic("bad size %d for LCON", size(p->nodetype));
87*5782Slinton 	    }
88*5782Slinton 	    break;
895543Slinton 
90*5782Slinton 	case O_FCON:
91*5782Slinton 	    push(double, p->fconval);
92*5782Slinton 	    break;
935543Slinton 
94*5782Slinton 	case O_SCON: {
95*5782Slinton 	    int len;
965543Slinton 
97*5782Slinton 	    len = size(p->nodetype);
98*5782Slinton 	    mov(p->sconval, sp, len);
99*5782Slinton 	    sp += len;
100*5782Slinton 	    break;
101*5782Slinton 	}
1025543Slinton 
103*5782Slinton 	case O_INDEX: {
104*5782Slinton 	    int n;
105*5782Slinton 	    long i;
1065543Slinton 
107*5782Slinton 	    n = pop(int);
108*5782Slinton 	    i = evalindex(p->left->nodetype, popsmall(p->right->nodetype));
109*5782Slinton 	    push(int, n + i*size(p->nodetype));
110*5782Slinton 	    break;
111*5782Slinton 	}
1125543Slinton 
113*5782Slinton 	case O_INDIR: {
114*5782Slinton 	    ADDRESS a;
1155543Slinton 
116*5782Slinton 	    a = pop(ADDRESS);
117*5782Slinton 	    if (a == 0) {
118*5782Slinton 		error("reference through nil pointer");
119*5782Slinton 	    }
120*5782Slinton 	    dread(sp, a, sizeof(ADDRESS));
121*5782Slinton 	    sp += sizeof(ADDRESS);
122*5782Slinton 	    break;
123*5782Slinton 	}
1245543Slinton 
125*5782Slinton 	/*
126*5782Slinton 	 * Get the value of the expression addressed by the top of the stack.
127*5782Slinton 	 * Push the result back on the stack.  Never push less than a long.
128*5782Slinton 	 */
1295543Slinton 
130*5782Slinton 	case O_RVAL: {
131*5782Slinton 	    ADDRESS addr, len;
132*5782Slinton 	    long i;
1335543Slinton 
134*5782Slinton 	    addr = pop(int);
135*5782Slinton 	    if (addr == 0) {
136*5782Slinton 		error("reference through nil pointer");
137*5782Slinton 	    }
138*5782Slinton 	    len = size(p->nodetype);
139*5782Slinton 	    if (!rpush(addr, len)) {
140*5782Slinton 		error("expression too large to evaluate");
141*5782Slinton 	    }
142*5782Slinton 	    break;
143*5782Slinton 	}
1445543Slinton 
145*5782Slinton 	case O_COMMA:
146*5782Slinton 	    break;
1475543Slinton 
148*5782Slinton 	case O_ITOF:
149*5782Slinton 	    push(double, (double) r0);
150*5782Slinton 	    break;
1515543Slinton 
152*5782Slinton 	case O_ADD:
153*5782Slinton 	    push(long, r0+r1);
154*5782Slinton 	    break;
1555543Slinton 
156*5782Slinton 	case O_ADDF:
157*5782Slinton 	    push(double, fr0+fr1);
158*5782Slinton 	    break;
1595543Slinton 
160*5782Slinton 	case O_SUB:
161*5782Slinton 	    push(long, r0-r1);
162*5782Slinton 	    break;
1635543Slinton 
164*5782Slinton 	case O_SUBF:
165*5782Slinton 	    push(double, fr0-fr1);
166*5782Slinton 	    break;
1675543Slinton 
168*5782Slinton 	case O_NEG:
169*5782Slinton 	    push(long, -r0);
170*5782Slinton 	    break;
1715543Slinton 
172*5782Slinton 	case O_NEGF:
173*5782Slinton 	    push(double, -fr0);
174*5782Slinton 	    break;
1755543Slinton 
176*5782Slinton 	case O_MUL:
177*5782Slinton 	    push(long, r0*r1);
178*5782Slinton 	    break;
1795543Slinton 
180*5782Slinton 	case O_MULF:
181*5782Slinton 	    push(double, fr0*fr1);
182*5782Slinton 	    break;
1835543Slinton 
184*5782Slinton 	case O_DIVF:
185*5782Slinton 	    if (fr1 == 0) {
186*5782Slinton 		error("error: division by 0");
187*5782Slinton 	    }
188*5782Slinton 	    push(double, fr0/fr1);
189*5782Slinton 	    break;
1905543Slinton 
191*5782Slinton 	case O_DIV:
192*5782Slinton 	    if (r1 == 0) {
193*5782Slinton 		error("error: div by 0");
194*5782Slinton 	    }
195*5782Slinton 	    push(long, r0/r1);
196*5782Slinton 	    break;
1975543Slinton 
198*5782Slinton 	case O_MOD:
199*5782Slinton 	    if (r1 == 0) {
200*5782Slinton 		error("error: mod by 0");
201*5782Slinton 	    }
202*5782Slinton 	    push(long, r0%r1);
203*5782Slinton 	    break;
2045543Slinton 
205*5782Slinton 	case O_LT:
206*5782Slinton 	    push(BOOLEAN, r0 < r1);
207*5782Slinton 	    break;
2085543Slinton 
209*5782Slinton 	case O_LTF:
210*5782Slinton 	    push(BOOLEAN, fr0 < fr1);
211*5782Slinton 	    break;
2125543Slinton 
213*5782Slinton 	case O_LE:
214*5782Slinton 	    push(BOOLEAN, r0 <= r1);
215*5782Slinton 	    break;
2165543Slinton 
217*5782Slinton 	case O_LEF:
218*5782Slinton 	    push(BOOLEAN, fr0 <= fr1);
219*5782Slinton 	    break;
2205543Slinton 
221*5782Slinton 	case O_GT:
222*5782Slinton 	    push(BOOLEAN, r0 > r1);
223*5782Slinton 	    break;
2245543Slinton 
225*5782Slinton 	case O_GTF:
226*5782Slinton 	    push(BOOLEAN, fr0 > fr1);
227*5782Slinton 	    break;
2285543Slinton 
229*5782Slinton 	case O_EQ:
230*5782Slinton 	    push(BOOLEAN, r0 == r1);
231*5782Slinton 	    break;
2325543Slinton 
233*5782Slinton 	case O_EQF:
234*5782Slinton 	    push(BOOLEAN, fr0 == fr1);
235*5782Slinton 	    break;
2365543Slinton 
237*5782Slinton 	case O_NE:
238*5782Slinton 	    push(BOOLEAN, r0 != r1);
239*5782Slinton 	    break;
2405543Slinton 
241*5782Slinton 	case O_NEF:
242*5782Slinton 	    push(BOOLEAN, fr0 != fr1);
243*5782Slinton 	    break;
2445543Slinton 
245*5782Slinton 	case O_AND:
246*5782Slinton 	    push(BOOLEAN, r0 && r1);
247*5782Slinton 	    break;
2485543Slinton 
249*5782Slinton 	case O_OR:
250*5782Slinton 	    push(BOOLEAN, r0 || r1);
251*5782Slinton 	    break;
2525543Slinton 
253*5782Slinton 	case O_ASSIGN:
254*5782Slinton 	    assign(p->left, p->right);
255*5782Slinton 	    break;
2565543Slinton 
257*5782Slinton 	case O_CHFILE:
258*5782Slinton 	    if (p->sconval == NIL) {
259*5782Slinton 		printf("%s\n", cursource);
260*5782Slinton 	    } else {
261*5782Slinton 		skimsource(p->sconval);
262*5782Slinton 	    }
263*5782Slinton 	    break;
2645543Slinton 
265*5782Slinton 	case O_CONT:
266*5782Slinton 	    cont();
267*5782Slinton 	    printnews();
268*5782Slinton 	    break;
2695543Slinton 
270*5782Slinton 	case O_LIST: {
271*5782Slinton 	    SYM *b;
2725543Slinton 
273*5782Slinton 	    if (p->left->op == O_NAME) {
274*5782Slinton 		b = p->left->nameval;
275*5782Slinton 		if (!isblock(b)) {
276*5782Slinton 		    error("\"%s\" is not a procedure or function", name(b));
2775543Slinton 		}
278*5782Slinton 		r0 = srcline(firstline(b));
279*5782Slinton 		r1 = r0 + 5;
280*5782Slinton 		if (r1 > lastlinenum) {
281*5782Slinton 		    r1 = lastlinenum;
282*5782Slinton 		}
283*5782Slinton 		r0 = r0 - 5;
284*5782Slinton 		if (r0 < 1) {
285*5782Slinton 		    r0 = 1;
286*5782Slinton 		}
287*5782Slinton 	    } else {
288*5782Slinton 		eval(p->left->right);
289*5782Slinton 		eval(p->left->left);
290*5782Slinton 		r0 = pop(long);
291*5782Slinton 		r1 = pop(long);
292*5782Slinton 	    }
293*5782Slinton 	    printlines((LINENO) r0, (LINENO) r1);
294*5782Slinton 	    break;
295*5782Slinton 	}
2965543Slinton 
297*5782Slinton 	case O_XI:
298*5782Slinton 	case O_XD:
299*5782Slinton 	{
300*5782Slinton 	    SYM *b;
3015543Slinton 
302*5782Slinton 	    if (p->left->op == O_CALL) {
303*5782Slinton 		b = p->left->left->nameval;
304*5782Slinton 		r0 = codeloc(b);
305*5782Slinton 		r1 = firstline(b);
306*5782Slinton 	    } else {
307*5782Slinton 		eval(p->left->right);
308*5782Slinton 		eval(p->left->left);
309*5782Slinton 		r0 = pop(long);
310*5782Slinton 		r1 = pop(long);
311*5782Slinton 	    }
312*5782Slinton 	    if (p->op == O_XI)  {
313*5782Slinton 		printinst((ADDRESS) r0, (ADDRESS) r1);
314*5782Slinton 	    } else {
315*5782Slinton 		printdata((ADDRESS) r0, (ADDRESS) r1);
316*5782Slinton 	    }
317*5782Slinton 	    break;
318*5782Slinton 	}
3195543Slinton 
320*5782Slinton 	case O_NEXT:
321*5782Slinton 	    next();
322*5782Slinton 	    printnews();
323*5782Slinton 	    break;
3245543Slinton 
325*5782Slinton 	case O_PRINT: {
326*5782Slinton 	    NODE *o;
3275543Slinton 
328*5782Slinton 	    for (o = p->left; o != NIL; o = o->right) {
329*5782Slinton 		eval(o->left);
330*5782Slinton 		printval(o->left->nodetype);
331*5782Slinton 		putchar(' ');
332*5782Slinton 	    }
333*5782Slinton 	    putchar('\n');
334*5782Slinton 	    break;
335*5782Slinton 	}
3365543Slinton 
337*5782Slinton 	case O_STEP:
338*5782Slinton 	    stepc();
339*5782Slinton 	    printnews();
340*5782Slinton 	    break;
3415543Slinton 
342*5782Slinton 	case O_WHATIS:
343*5782Slinton 	    if (p->left->op == O_NAME) {
344*5782Slinton 		printdecl(p->left->nameval);
345*5782Slinton 	    } else {
346*5782Slinton 		printdecl(p->left->nodetype);
347*5782Slinton 	    }
348*5782Slinton 	    break;
3495543Slinton 
350*5782Slinton 	case O_WHICH:
351*5782Slinton 	    printwhich(p->nameval);
352*5782Slinton 	    putchar('\n');
353*5782Slinton 	    break;
3545543Slinton 
355*5782Slinton 	case O_WHERE:
356*5782Slinton 	    where();
357*5782Slinton 	    break;
3585543Slinton 
359*5782Slinton 	case O_ALIAS:
360*5782Slinton 	    alias(p->left->sconval, p->right->sconval);
361*5782Slinton 	    break;
3625543Slinton 
363*5782Slinton 	case O_CALL:
364*5782Slinton 	    callproc(p->left, p->right);
365*5782Slinton 	    break;
3665543Slinton 
367*5782Slinton 	case O_EDIT:
368*5782Slinton 	    edit(p->sconval);
369*5782Slinton 	    break;
3705543Slinton 
371*5782Slinton 	case O_DUMP:
372*5782Slinton 	    dump();
373*5782Slinton 	    break;
3745543Slinton 
375*5782Slinton 	case O_GRIPE:
376*5782Slinton 	    gripe();
377*5782Slinton 	    break;
3785562Slinton 
379*5782Slinton 	case O_HELP:
380*5782Slinton 	    help();
381*5782Slinton 	    break;
3825543Slinton 
383*5782Slinton 	case O_REMAKE:
384*5782Slinton 	    remake();
385*5782Slinton 	    break;
3865543Slinton 
387*5782Slinton 	case O_RUN:
388*5782Slinton 	    run();
389*5782Slinton 	    break;
3905543Slinton 
391*5782Slinton 	case O_SOURCE:
392*5782Slinton 	    setinput(p->sconval);
393*5782Slinton 	    break;
3945543Slinton 
395*5782Slinton 	case O_STATUS:
396*5782Slinton 	    status();
397*5782Slinton 	    break;
3985543Slinton 
399*5782Slinton 	case O_TRACE:
400*5782Slinton 	case O_TRACEI:
401*5782Slinton 	    trace(p->op, p->what, p->where, p->cond);
402*5782Slinton 	    if (isstdin()) {
403*5782Slinton 		status();
404*5782Slinton 	    }
405*5782Slinton 	    break;
4065543Slinton 
407*5782Slinton 	case O_STOP:
408*5782Slinton 	case O_STOPI:
409*5782Slinton 	    stop(p->op, p->what, p->where, p->cond);
410*5782Slinton 	    if (isstdin()) {
411*5782Slinton 		status();
412*5782Slinton 	    }
413*5782Slinton 	    break;
4145543Slinton 
415*5782Slinton 	case O_DELETE:
416*5782Slinton 	    eval(p->left);
417*5782Slinton 	    delbp((unsigned int) pop(long));
418*5782Slinton 	    break;
4195543Slinton 
420*5782Slinton 	default:
421*5782Slinton 	    panic("eval: bad op %d", p->op);
422*5782Slinton     }
4235543Slinton }
4245543Slinton 
4255543Slinton /*
4265562Slinton  * Push "len" bytes onto the expression stack from address "addr"
4275562Slinton  * in the process.  Normally TRUE is returned, however if there
4285562Slinton  * isn't enough room on the stack, rpush returns FALSE.
4295562Slinton  */
4305562Slinton 
4315562Slinton BOOLEAN rpush(addr, len)
4325562Slinton ADDRESS addr;
4335562Slinton int len;
4345562Slinton {
435*5782Slinton     BOOLEAN success;
4365562Slinton 
437*5782Slinton     if (sp + len >= &stack[STACKSIZE]) {
438*5782Slinton 	success = FALSE;
439*5782Slinton     } else {
440*5782Slinton 	dread(sp, addr, len);
441*5782Slinton 	sp += len;
442*5782Slinton 	success = TRUE;
443*5782Slinton     }
444*5782Slinton     return success;
4455562Slinton }
4465562Slinton 
4475562Slinton /*
448*5782Slinton  * Pop an item of the given type which is assumed to be no larger
449*5782Slinton  * than a long and return it expanded into a long.
450*5782Slinton  */
451*5782Slinton 
452*5782Slinton long popsmall(t)
453*5782Slinton SYM *t;
454*5782Slinton {
455*5782Slinton     long r;
456*5782Slinton 
457*5782Slinton     switch (size(t)) {
458*5782Slinton 	case sizeof(char):
459*5782Slinton 	    r = (long) pop(char);
460*5782Slinton 	    break;
461*5782Slinton 
462*5782Slinton 	case sizeof(short):
463*5782Slinton 	    r = (long) pop(short);
464*5782Slinton 	    break;
465*5782Slinton 
466*5782Slinton 	case sizeof(long):
467*5782Slinton 	    r = pop(long);
468*5782Slinton 	    break;
469*5782Slinton 
470*5782Slinton 	default:
471*5782Slinton 	    panic("popsmall: size is %d", size(t));
472*5782Slinton     }
473*5782Slinton     return r;
474*5782Slinton }
475*5782Slinton 
476*5782Slinton /*
4775543Slinton  * evaluate a conditional expression
4785543Slinton  */
4795543Slinton 
4805543Slinton BOOLEAN cond(p)
4815543Slinton NODE *p;
4825543Slinton {
483*5782Slinton     if (p == NIL) {
484*5782Slinton 	return(TRUE);
485*5782Slinton     }
486*5782Slinton     eval(p);
487*5782Slinton     return(pop(BOOLEAN));
4885543Slinton }
4895543Slinton 
4905543Slinton /*
4915543Slinton  * Return the address corresponding to a given tree.
4925543Slinton  */
4935543Slinton 
4945543Slinton ADDRESS lval(p)
4955543Slinton NODE *p;
4965543Slinton {
497*5782Slinton     eval(p);
498*5782Slinton     return(pop(ADDRESS));
4995543Slinton }
500