xref: /csrg-svn/usr.bin/pascal/pdx/tree/eval.c (revision 5543)
1*5543Slinton /* Copyright (c) 1982 Regents of the University of California */
2*5543Slinton 
3*5543Slinton static char sccsid[] = "@(#)eval.c 1.1 01/18/82";
4*5543Slinton 
5*5543Slinton /*
6*5543Slinton  * parse tree evaluation
7*5543Slinton  */
8*5543Slinton 
9*5543Slinton #include "defs.h"
10*5543Slinton #include "tree.h"
11*5543Slinton #include "sym.h"
12*5543Slinton #include "process.h"
13*5543Slinton #include "source.h"
14*5543Slinton #include "mappings.h"
15*5543Slinton #include "breakpoint.h"
16*5543Slinton #include "machine.h"
17*5543Slinton #include "tree.rep"
18*5543Slinton 
19*5543Slinton /*
20*5543Slinton  * Evaluate a parse tree using a stack; value is left at top.
21*5543Slinton  */
22*5543Slinton 
23*5543Slinton STACK *sp = &stack[0];
24*5543Slinton 
25*5543Slinton eval(p)
26*5543Slinton register NODE *p;
27*5543Slinton {
28*5543Slinton 	long r0, r1;
29*5543Slinton 	double fr0, fr1;
30*5543Slinton 
31*5543Slinton 	if (p == NULL) {
32*5543Slinton 		return;
33*5543Slinton 	}
34*5543Slinton 	switch(degree(p->op)) {
35*5543Slinton 		case BINARY:
36*5543Slinton 			eval(p->right);
37*5543Slinton 			if (isreal(p->op)) {
38*5543Slinton 				fr1 = pop(double);
39*5543Slinton 			} else if (isint(p->op)) {
40*5543Slinton 				r1 = pop(long);
41*5543Slinton 			}
42*5543Slinton 			/* fall through */
43*5543Slinton 		case UNARY:
44*5543Slinton 			eval(p->left);
45*5543Slinton 			if (isreal(p->op)) {
46*5543Slinton 				fr0 = pop(double);
47*5543Slinton 			} else if (isint(p->op)) {
48*5543Slinton 				r0 = pop(long);
49*5543Slinton 			}
50*5543Slinton 			break;
51*5543Slinton 
52*5543Slinton 		default:
53*5543Slinton 			/* do nothing */;
54*5543Slinton 		}
55*5543Slinton 	switch(p->op) {
56*5543Slinton 		case O_NAME: {
57*5543Slinton 			SYM *s, *f;
58*5543Slinton 
59*5543Slinton 			s = p->nameval;
60*5543Slinton 			f = container(s);
61*5543Slinton 			if (!isactive(f)) {
62*5543Slinton 				error("\"%s\" is not active", name(f));
63*5543Slinton 			}
64*5543Slinton 			push(int, address(s, NIL));
65*5543Slinton 			break;
66*5543Slinton 		}
67*5543Slinton 
68*5543Slinton 		case O_LCON:
69*5543Slinton 			push(long, p->lconval);
70*5543Slinton 			break;
71*5543Slinton 
72*5543Slinton 		case O_FCON:
73*5543Slinton 			push(double, p->fconval);
74*5543Slinton 			break;
75*5543Slinton 
76*5543Slinton 		case O_SCON: {
77*5543Slinton 			int len;
78*5543Slinton 
79*5543Slinton 			len = size(p->nodetype);
80*5543Slinton 			mov(p->sconval, sp, len);
81*5543Slinton 			sp += len;
82*5543Slinton 			break;
83*5543Slinton 		}
84*5543Slinton 
85*5543Slinton 		case O_INDEX: {
86*5543Slinton 			int n;
87*5543Slinton 			long i;
88*5543Slinton 
89*5543Slinton 			n = pop(int);
90*5543Slinton 			i = evalindex(p->left->nodetype);
91*5543Slinton 			push(int, n + i*size(p->nodetype));
92*5543Slinton 			break;
93*5543Slinton 		}
94*5543Slinton 
95*5543Slinton 		case O_INDIR: {
96*5543Slinton 			ADDRESS a;
97*5543Slinton 
98*5543Slinton 			a = pop(ADDRESS);
99*5543Slinton 			if (a == 0) {
100*5543Slinton 				error("reference through nil pointer");
101*5543Slinton 			}
102*5543Slinton 			dread(sp, a, sizeof(ADDRESS));
103*5543Slinton 			sp += sizeof(ADDRESS);
104*5543Slinton 			break;
105*5543Slinton 		}
106*5543Slinton 
107*5543Slinton 		/*
108*5543Slinton 		 * Get the value of the expression addressed by the top of the stack.
109*5543Slinton 		 * Push the result back on the stack.  Never push less than a long.
110*5543Slinton 		 */
111*5543Slinton 
112*5543Slinton 		case O_RVAL: {
113*5543Slinton 			ADDRESS addr, len;
114*5543Slinton 			long i;
115*5543Slinton 
116*5543Slinton 			addr = pop(int);
117*5543Slinton 			if (addr == 0) {
118*5543Slinton 				error("reference through nil pointer");
119*5543Slinton 			}
120*5543Slinton 			len = size(p->nodetype);
121*5543Slinton 			dread(sp, addr, len);
122*5543Slinton 			sp += len;
123*5543Slinton 			if (len < sizeof(long)) {
124*5543Slinton 				switch (len) {
125*5543Slinton 					case sizeof(char):
126*5543Slinton 						i = pop(char);
127*5543Slinton 						break;
128*5543Slinton 
129*5543Slinton 					case sizeof(short):
130*5543Slinton 						i = pop(short);
131*5543Slinton 						break;
132*5543Slinton 
133*5543Slinton 					default:
134*5543Slinton 						panic("bad size in RVAL");
135*5543Slinton 				}
136*5543Slinton 				push(long, i);
137*5543Slinton 			}
138*5543Slinton 			break;
139*5543Slinton 		}
140*5543Slinton 
141*5543Slinton 		case O_COMMA:
142*5543Slinton 			break;
143*5543Slinton 
144*5543Slinton 		case O_ITOF:
145*5543Slinton 			push(double, (double) r0);
146*5543Slinton 			break;
147*5543Slinton 
148*5543Slinton 		case O_ADD:
149*5543Slinton 			push(long, r0+r1);
150*5543Slinton 			break;
151*5543Slinton 
152*5543Slinton 		case O_ADDF:
153*5543Slinton 			push(double, fr0+fr1);
154*5543Slinton 			break;
155*5543Slinton 
156*5543Slinton 		case O_SUB:
157*5543Slinton 			push(long, r0-r1);
158*5543Slinton 			break;
159*5543Slinton 
160*5543Slinton 		case O_SUBF:
161*5543Slinton 			push(double, fr0-fr1);
162*5543Slinton 			break;
163*5543Slinton 
164*5543Slinton 		case O_NEG:
165*5543Slinton 			push(long, -r0);
166*5543Slinton 			break;
167*5543Slinton 
168*5543Slinton 		case O_NEGF:
169*5543Slinton 			push(double, -fr0);
170*5543Slinton 			break;
171*5543Slinton 
172*5543Slinton 		case O_MUL:
173*5543Slinton 			push(long, r0*r1);
174*5543Slinton 			break;
175*5543Slinton 
176*5543Slinton 		case O_MULF:
177*5543Slinton 			push(double, fr0*fr1);
178*5543Slinton 			break;
179*5543Slinton 
180*5543Slinton 		case O_DIVF:
181*5543Slinton 			if (fr1 == 0) {
182*5543Slinton 				error("error: division by 0");
183*5543Slinton 			}
184*5543Slinton 			push(double, fr0/fr1);
185*5543Slinton 			break;
186*5543Slinton 
187*5543Slinton 		case O_DIV:
188*5543Slinton 			if (r1 == 0) {
189*5543Slinton 				error("error: div by 0");
190*5543Slinton 			}
191*5543Slinton 			push(long, r0/r1);
192*5543Slinton 			break;
193*5543Slinton 
194*5543Slinton 		case O_MOD:
195*5543Slinton 			if (r1 == 0) {
196*5543Slinton 				error("error: mod by 0");
197*5543Slinton 			}
198*5543Slinton 			push(long, r0%r1);
199*5543Slinton 			break;
200*5543Slinton 
201*5543Slinton 		case O_LT:
202*5543Slinton 			push(BOOLEAN, r0 < r1);
203*5543Slinton 			break;
204*5543Slinton 
205*5543Slinton 		case O_LTF:
206*5543Slinton 			push(BOOLEAN, fr0 < fr1);
207*5543Slinton 			break;
208*5543Slinton 
209*5543Slinton 		case O_LE:
210*5543Slinton 			push(BOOLEAN, r0 <= r1);
211*5543Slinton 			break;
212*5543Slinton 
213*5543Slinton 		case O_LEF:
214*5543Slinton 			push(BOOLEAN, fr0 <= fr1);
215*5543Slinton 			break;
216*5543Slinton 
217*5543Slinton 		case O_GT:
218*5543Slinton 			push(BOOLEAN, r0 > r1);
219*5543Slinton 			break;
220*5543Slinton 
221*5543Slinton 		case O_GTF:
222*5543Slinton 			push(BOOLEAN, fr0 > fr1);
223*5543Slinton 			break;
224*5543Slinton 
225*5543Slinton 		case O_EQ:
226*5543Slinton 			push(BOOLEAN, r0 == r1);
227*5543Slinton 			break;
228*5543Slinton 
229*5543Slinton 		case O_EQF:
230*5543Slinton 			push(BOOLEAN, fr0 == fr1);
231*5543Slinton 			break;
232*5543Slinton 
233*5543Slinton 		case O_NE:
234*5543Slinton 			push(BOOLEAN, r0 != r1);
235*5543Slinton 			break;
236*5543Slinton 
237*5543Slinton 		case O_NEF:
238*5543Slinton 			push(BOOLEAN, fr0 != fr1);
239*5543Slinton 			break;
240*5543Slinton 
241*5543Slinton 		case O_AND:
242*5543Slinton 			push(BOOLEAN, r0 && r1);
243*5543Slinton 			break;
244*5543Slinton 
245*5543Slinton 		case O_OR:
246*5543Slinton 			push(BOOLEAN, r0 || r1);
247*5543Slinton 			break;
248*5543Slinton 
249*5543Slinton 		case O_ASSIGN:
250*5543Slinton 			assign(p->left, p->right);
251*5543Slinton 			break;
252*5543Slinton 
253*5543Slinton 		case O_CHFILE:
254*5543Slinton 			if (p->sconval == NIL) {
255*5543Slinton 				printf("%s\n", cursource);
256*5543Slinton 			} else {
257*5543Slinton 				skimsource(p->sconval);
258*5543Slinton 			}
259*5543Slinton 			break;
260*5543Slinton 
261*5543Slinton 		case O_CONT:
262*5543Slinton 			cont();
263*5543Slinton 			printnews();
264*5543Slinton 			break;
265*5543Slinton 
266*5543Slinton 		case O_LIST: {
267*5543Slinton 			SYM *b;
268*5543Slinton 
269*5543Slinton 			if (p->left->op == O_NAME) {
270*5543Slinton 				b = p->left->nameval;
271*5543Slinton 				if (!isblock(b)) {
272*5543Slinton 					error("\"%s\" is not a procedure or function", name(b));
273*5543Slinton 				}
274*5543Slinton 				r0 = srcline(firstline(b));
275*5543Slinton 				r1 = r0 + 5;
276*5543Slinton 				if (r1 > lastlinenum) {
277*5543Slinton 					r1 = lastlinenum;
278*5543Slinton 				}
279*5543Slinton 				r0 = r0 - 5;
280*5543Slinton 				if (r0 < 1) {
281*5543Slinton 					r0 = 1;
282*5543Slinton 				}
283*5543Slinton 			} else {
284*5543Slinton 				eval(p->left->right);
285*5543Slinton 				eval(p->left->left);
286*5543Slinton 				r0 = pop(long);
287*5543Slinton 				r1 = pop(long);
288*5543Slinton 			}
289*5543Slinton 			printlines((LINENO) r0, (LINENO) r1);
290*5543Slinton 			break;
291*5543Slinton 		}
292*5543Slinton 
293*5543Slinton 		case O_XI:
294*5543Slinton 		case O_XD:
295*5543Slinton 		{
296*5543Slinton 			SYM *b;
297*5543Slinton 
298*5543Slinton 			if (p->left->op == O_CALL) {
299*5543Slinton 				b = p->left->left->nameval;
300*5543Slinton 				r0 = codeloc(b);
301*5543Slinton 				r1 = firstline(b);
302*5543Slinton 			} else {
303*5543Slinton 				eval(p->left->right);
304*5543Slinton 				eval(p->left->left);
305*5543Slinton 				r0 = pop(long);
306*5543Slinton 				r1 = pop(long);
307*5543Slinton 			}
308*5543Slinton 			if (p->op == O_XI)  {
309*5543Slinton 				printinst((ADDRESS) r0, (ADDRESS) r1);
310*5543Slinton 			} else {
311*5543Slinton 				printdata((ADDRESS) r0, (ADDRESS) r1);
312*5543Slinton 			}
313*5543Slinton 			break;
314*5543Slinton 		}
315*5543Slinton 
316*5543Slinton 		case O_NEXT:
317*5543Slinton 			next();
318*5543Slinton 			printnews();
319*5543Slinton 			break;
320*5543Slinton 
321*5543Slinton 		case O_PRINT: {
322*5543Slinton 			NODE *o;
323*5543Slinton 
324*5543Slinton 			for (o = p->left; o != NIL; o = o->right) {
325*5543Slinton 				eval(o->left);
326*5543Slinton 				printval(o->left->nodetype);
327*5543Slinton 				putchar(' ');
328*5543Slinton 			}
329*5543Slinton 			putchar('\n');
330*5543Slinton 			break;
331*5543Slinton 		}
332*5543Slinton 
333*5543Slinton 		case O_STEP:
334*5543Slinton 			stepc();
335*5543Slinton 			printnews();
336*5543Slinton 			break;
337*5543Slinton 
338*5543Slinton 		case O_WHATIS:
339*5543Slinton 			if (p->left->op == O_NAME) {
340*5543Slinton 				printdecl(p->left->nameval);
341*5543Slinton 			} else {
342*5543Slinton 				printdecl(p->left->nodetype);
343*5543Slinton 			}
344*5543Slinton 			break;
345*5543Slinton 
346*5543Slinton 		case O_WHICH:
347*5543Slinton 			printwhich(p->nameval);
348*5543Slinton 			putchar('\n');
349*5543Slinton 			break;
350*5543Slinton 
351*5543Slinton 		case O_WHERE:
352*5543Slinton 			where();
353*5543Slinton 			break;
354*5543Slinton 
355*5543Slinton 		case O_ALIAS:
356*5543Slinton 			alias(p->left->sconval, p->right->sconval);
357*5543Slinton 			break;
358*5543Slinton 
359*5543Slinton 		case O_CALL:
360*5543Slinton 			callproc(p->left, p->right);
361*5543Slinton 			break;
362*5543Slinton 
363*5543Slinton 		case O_EDIT:
364*5543Slinton 			edit(p->sconval);
365*5543Slinton 			break;
366*5543Slinton 
367*5543Slinton 		case O_DUMP:
368*5543Slinton 			dump();
369*5543Slinton 			break;
370*5543Slinton 
371*5543Slinton 		case O_HELP:
372*5543Slinton 			help();
373*5543Slinton 			break;
374*5543Slinton 
375*5543Slinton 		case O_REMAKE:
376*5543Slinton 			remake();
377*5543Slinton 			break;
378*5543Slinton 
379*5543Slinton 		case O_RUN:
380*5543Slinton 			run();
381*5543Slinton 			break;
382*5543Slinton 
383*5543Slinton 		case O_SOURCE:
384*5543Slinton 			setinput(p->sconval);
385*5543Slinton 			break;
386*5543Slinton 
387*5543Slinton 		case O_STATUS:
388*5543Slinton 			status();
389*5543Slinton 			break;
390*5543Slinton 
391*5543Slinton 		case O_TRACE:
392*5543Slinton 		case O_TRACEI:
393*5543Slinton 			trace(p->op, p->what, p->where, p->cond);
394*5543Slinton 			if (isstdin()) {
395*5543Slinton 				status();
396*5543Slinton 			}
397*5543Slinton 			break;
398*5543Slinton 
399*5543Slinton 		case O_STOP:
400*5543Slinton 		case O_STOPI:
401*5543Slinton 			stop(p->op, p->what, p->where, p->cond);
402*5543Slinton 			if (isstdin()) {
403*5543Slinton 				status();
404*5543Slinton 			}
405*5543Slinton 			break;
406*5543Slinton 
407*5543Slinton 		case O_DELETE:
408*5543Slinton 			eval(p->left);
409*5543Slinton 			delbp((unsigned int) pop(long));
410*5543Slinton 			break;
411*5543Slinton 
412*5543Slinton 		default:
413*5543Slinton 			panic("eval: bad op %d", p->op);
414*5543Slinton 	}
415*5543Slinton }
416*5543Slinton 
417*5543Slinton /*
418*5543Slinton  * evaluate a conditional expression
419*5543Slinton  */
420*5543Slinton 
421*5543Slinton BOOLEAN cond(p)
422*5543Slinton NODE *p;
423*5543Slinton {
424*5543Slinton 	if (p == NIL) {
425*5543Slinton 		return(TRUE);
426*5543Slinton 	}
427*5543Slinton 	eval(p);
428*5543Slinton 	return(pop(BOOLEAN));
429*5543Slinton }
430*5543Slinton 
431*5543Slinton /*
432*5543Slinton  * Return the address corresponding to a given tree.
433*5543Slinton  */
434*5543Slinton 
435*5543Slinton ADDRESS lval(p)
436*5543Slinton NODE *p;
437*5543Slinton {
438*5543Slinton 	eval(p);
439*5543Slinton 	return(pop(ADDRESS));
440*5543Slinton }
441