xref: /csrg-svn/usr.bin/pascal/pdx/tree/eval.c (revision 5562)
15543Slinton /* Copyright (c) 1982 Regents of the University of California */
25543Slinton 
3*5562Slinton static char sccsid[] = "@(#)eval.c 1.2 01/18/82";
45543Slinton 
55543Slinton /*
6*5562Slinton  * 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 
23*5562Slinton #define STACKSIZE 2000
24*5562Slinton 
25*5562Slinton STACK stack[STACKSIZE];
265543Slinton STACK *sp = &stack[0];
275543Slinton 
285543Slinton eval(p)
295543Slinton register NODE *p;
305543Slinton {
315543Slinton 	long r0, r1;
325543Slinton 	double fr0, fr1;
335543Slinton 
345543Slinton 	if (p == NULL) {
355543Slinton 		return;
365543Slinton 	}
375543Slinton 	switch(degree(p->op)) {
385543Slinton 		case BINARY:
395543Slinton 			eval(p->right);
405543Slinton 			if (isreal(p->op)) {
415543Slinton 				fr1 = pop(double);
425543Slinton 			} else if (isint(p->op)) {
435543Slinton 				r1 = pop(long);
445543Slinton 			}
455543Slinton 			/* fall through */
465543Slinton 		case UNARY:
475543Slinton 			eval(p->left);
485543Slinton 			if (isreal(p->op)) {
495543Slinton 				fr0 = pop(double);
505543Slinton 			} else if (isint(p->op)) {
515543Slinton 				r0 = pop(long);
525543Slinton 			}
535543Slinton 			break;
545543Slinton 
555543Slinton 		default:
565543Slinton 			/* do nothing */;
575543Slinton 		}
585543Slinton 	switch(p->op) {
595543Slinton 		case O_NAME: {
605543Slinton 			SYM *s, *f;
615543Slinton 
625543Slinton 			s = p->nameval;
635543Slinton 			f = container(s);
645543Slinton 			if (!isactive(f)) {
655543Slinton 				error("\"%s\" is not active", name(f));
665543Slinton 			}
675543Slinton 			push(int, address(s, NIL));
685543Slinton 			break;
695543Slinton 		}
705543Slinton 
715543Slinton 		case O_LCON:
725543Slinton 			push(long, p->lconval);
735543Slinton 			break;
745543Slinton 
755543Slinton 		case O_FCON:
765543Slinton 			push(double, p->fconval);
775543Slinton 			break;
785543Slinton 
795543Slinton 		case O_SCON: {
805543Slinton 			int len;
815543Slinton 
825543Slinton 			len = size(p->nodetype);
835543Slinton 			mov(p->sconval, sp, len);
845543Slinton 			sp += len;
855543Slinton 			break;
865543Slinton 		}
875543Slinton 
885543Slinton 		case O_INDEX: {
895543Slinton 			int n;
905543Slinton 			long i;
915543Slinton 
925543Slinton 			n = pop(int);
935543Slinton 			i = evalindex(p->left->nodetype);
945543Slinton 			push(int, n + i*size(p->nodetype));
955543Slinton 			break;
965543Slinton 		}
975543Slinton 
985543Slinton 		case O_INDIR: {
995543Slinton 			ADDRESS a;
1005543Slinton 
1015543Slinton 			a = pop(ADDRESS);
1025543Slinton 			if (a == 0) {
1035543Slinton 				error("reference through nil pointer");
1045543Slinton 			}
1055543Slinton 			dread(sp, a, sizeof(ADDRESS));
1065543Slinton 			sp += sizeof(ADDRESS);
1075543Slinton 			break;
1085543Slinton 		}
1095543Slinton 
1105543Slinton 		/*
1115543Slinton 		 * Get the value of the expression addressed by the top of the stack.
1125543Slinton 		 * Push the result back on the stack.  Never push less than a long.
1135543Slinton 		 */
1145543Slinton 
1155543Slinton 		case O_RVAL: {
1165543Slinton 			ADDRESS addr, len;
1175543Slinton 			long i;
1185543Slinton 
1195543Slinton 			addr = pop(int);
1205543Slinton 			if (addr == 0) {
1215543Slinton 				error("reference through nil pointer");
1225543Slinton 			}
1235543Slinton 			len = size(p->nodetype);
124*5562Slinton 			if (!rpush(addr, len)) {
125*5562Slinton 				error("expression too large to evaluate");
126*5562Slinton 			}
1275543Slinton 			if (len < sizeof(long)) {
1285543Slinton 				switch (len) {
1295543Slinton 					case sizeof(char):
1305543Slinton 						i = pop(char);
1315543Slinton 						break;
1325543Slinton 
1335543Slinton 					case sizeof(short):
1345543Slinton 						i = pop(short);
1355543Slinton 						break;
1365543Slinton 
1375543Slinton 					default:
1385543Slinton 						panic("bad size in RVAL");
1395543Slinton 				}
1405543Slinton 				push(long, i);
1415543Slinton 			}
1425543Slinton 			break;
1435543Slinton 		}
1445543Slinton 
1455543Slinton 		case O_COMMA:
1465543Slinton 			break;
1475543Slinton 
1485543Slinton 		case O_ITOF:
1495543Slinton 			push(double, (double) r0);
1505543Slinton 			break;
1515543Slinton 
1525543Slinton 		case O_ADD:
1535543Slinton 			push(long, r0+r1);
1545543Slinton 			break;
1555543Slinton 
1565543Slinton 		case O_ADDF:
1575543Slinton 			push(double, fr0+fr1);
1585543Slinton 			break;
1595543Slinton 
1605543Slinton 		case O_SUB:
1615543Slinton 			push(long, r0-r1);
1625543Slinton 			break;
1635543Slinton 
1645543Slinton 		case O_SUBF:
1655543Slinton 			push(double, fr0-fr1);
1665543Slinton 			break;
1675543Slinton 
1685543Slinton 		case O_NEG:
1695543Slinton 			push(long, -r0);
1705543Slinton 			break;
1715543Slinton 
1725543Slinton 		case O_NEGF:
1735543Slinton 			push(double, -fr0);
1745543Slinton 			break;
1755543Slinton 
1765543Slinton 		case O_MUL:
1775543Slinton 			push(long, r0*r1);
1785543Slinton 			break;
1795543Slinton 
1805543Slinton 		case O_MULF:
1815543Slinton 			push(double, fr0*fr1);
1825543Slinton 			break;
1835543Slinton 
1845543Slinton 		case O_DIVF:
1855543Slinton 			if (fr1 == 0) {
1865543Slinton 				error("error: division by 0");
1875543Slinton 			}
1885543Slinton 			push(double, fr0/fr1);
1895543Slinton 			break;
1905543Slinton 
1915543Slinton 		case O_DIV:
1925543Slinton 			if (r1 == 0) {
1935543Slinton 				error("error: div by 0");
1945543Slinton 			}
1955543Slinton 			push(long, r0/r1);
1965543Slinton 			break;
1975543Slinton 
1985543Slinton 		case O_MOD:
1995543Slinton 			if (r1 == 0) {
2005543Slinton 				error("error: mod by 0");
2015543Slinton 			}
2025543Slinton 			push(long, r0%r1);
2035543Slinton 			break;
2045543Slinton 
2055543Slinton 		case O_LT:
2065543Slinton 			push(BOOLEAN, r0 < r1);
2075543Slinton 			break;
2085543Slinton 
2095543Slinton 		case O_LTF:
2105543Slinton 			push(BOOLEAN, fr0 < fr1);
2115543Slinton 			break;
2125543Slinton 
2135543Slinton 		case O_LE:
2145543Slinton 			push(BOOLEAN, r0 <= r1);
2155543Slinton 			break;
2165543Slinton 
2175543Slinton 		case O_LEF:
2185543Slinton 			push(BOOLEAN, fr0 <= fr1);
2195543Slinton 			break;
2205543Slinton 
2215543Slinton 		case O_GT:
2225543Slinton 			push(BOOLEAN, r0 > r1);
2235543Slinton 			break;
2245543Slinton 
2255543Slinton 		case O_GTF:
2265543Slinton 			push(BOOLEAN, fr0 > fr1);
2275543Slinton 			break;
2285543Slinton 
2295543Slinton 		case O_EQ:
2305543Slinton 			push(BOOLEAN, r0 == r1);
2315543Slinton 			break;
2325543Slinton 
2335543Slinton 		case O_EQF:
2345543Slinton 			push(BOOLEAN, fr0 == fr1);
2355543Slinton 			break;
2365543Slinton 
2375543Slinton 		case O_NE:
2385543Slinton 			push(BOOLEAN, r0 != r1);
2395543Slinton 			break;
2405543Slinton 
2415543Slinton 		case O_NEF:
2425543Slinton 			push(BOOLEAN, fr0 != fr1);
2435543Slinton 			break;
2445543Slinton 
2455543Slinton 		case O_AND:
2465543Slinton 			push(BOOLEAN, r0 && r1);
2475543Slinton 			break;
2485543Slinton 
2495543Slinton 		case O_OR:
2505543Slinton 			push(BOOLEAN, r0 || r1);
2515543Slinton 			break;
2525543Slinton 
2535543Slinton 		case O_ASSIGN:
2545543Slinton 			assign(p->left, p->right);
2555543Slinton 			break;
2565543Slinton 
2575543Slinton 		case O_CHFILE:
2585543Slinton 			if (p->sconval == NIL) {
2595543Slinton 				printf("%s\n", cursource);
2605543Slinton 			} else {
2615543Slinton 				skimsource(p->sconval);
2625543Slinton 			}
2635543Slinton 			break;
2645543Slinton 
2655543Slinton 		case O_CONT:
2665543Slinton 			cont();
2675543Slinton 			printnews();
2685543Slinton 			break;
2695543Slinton 
2705543Slinton 		case O_LIST: {
2715543Slinton 			SYM *b;
2725543Slinton 
2735543Slinton 			if (p->left->op == O_NAME) {
2745543Slinton 				b = p->left->nameval;
2755543Slinton 				if (!isblock(b)) {
2765543Slinton 					error("\"%s\" is not a procedure or function", name(b));
2775543Slinton 				}
2785543Slinton 				r0 = srcline(firstline(b));
2795543Slinton 				r1 = r0 + 5;
2805543Slinton 				if (r1 > lastlinenum) {
2815543Slinton 					r1 = lastlinenum;
2825543Slinton 				}
2835543Slinton 				r0 = r0 - 5;
2845543Slinton 				if (r0 < 1) {
2855543Slinton 					r0 = 1;
2865543Slinton 				}
2875543Slinton 			} else {
2885543Slinton 				eval(p->left->right);
2895543Slinton 				eval(p->left->left);
2905543Slinton 				r0 = pop(long);
2915543Slinton 				r1 = pop(long);
2925543Slinton 			}
2935543Slinton 			printlines((LINENO) r0, (LINENO) r1);
2945543Slinton 			break;
2955543Slinton 		}
2965543Slinton 
2975543Slinton 		case O_XI:
2985543Slinton 		case O_XD:
2995543Slinton 		{
3005543Slinton 			SYM *b;
3015543Slinton 
3025543Slinton 			if (p->left->op == O_CALL) {
3035543Slinton 				b = p->left->left->nameval;
3045543Slinton 				r0 = codeloc(b);
3055543Slinton 				r1 = firstline(b);
3065543Slinton 			} else {
3075543Slinton 				eval(p->left->right);
3085543Slinton 				eval(p->left->left);
3095543Slinton 				r0 = pop(long);
3105543Slinton 				r1 = pop(long);
3115543Slinton 			}
3125543Slinton 			if (p->op == O_XI)  {
3135543Slinton 				printinst((ADDRESS) r0, (ADDRESS) r1);
3145543Slinton 			} else {
3155543Slinton 				printdata((ADDRESS) r0, (ADDRESS) r1);
3165543Slinton 			}
3175543Slinton 			break;
3185543Slinton 		}
3195543Slinton 
3205543Slinton 		case O_NEXT:
3215543Slinton 			next();
3225543Slinton 			printnews();
3235543Slinton 			break;
3245543Slinton 
3255543Slinton 		case O_PRINT: {
3265543Slinton 			NODE *o;
3275543Slinton 
3285543Slinton 			for (o = p->left; o != NIL; o = o->right) {
3295543Slinton 				eval(o->left);
3305543Slinton 				printval(o->left->nodetype);
3315543Slinton 				putchar(' ');
3325543Slinton 			}
3335543Slinton 			putchar('\n');
3345543Slinton 			break;
3355543Slinton 		}
3365543Slinton 
3375543Slinton 		case O_STEP:
3385543Slinton 			stepc();
3395543Slinton 			printnews();
3405543Slinton 			break;
3415543Slinton 
3425543Slinton 		case O_WHATIS:
3435543Slinton 			if (p->left->op == O_NAME) {
3445543Slinton 				printdecl(p->left->nameval);
3455543Slinton 			} else {
3465543Slinton 				printdecl(p->left->nodetype);
3475543Slinton 			}
3485543Slinton 			break;
3495543Slinton 
3505543Slinton 		case O_WHICH:
3515543Slinton 			printwhich(p->nameval);
3525543Slinton 			putchar('\n');
3535543Slinton 			break;
3545543Slinton 
3555543Slinton 		case O_WHERE:
3565543Slinton 			where();
3575543Slinton 			break;
3585543Slinton 
3595543Slinton 		case O_ALIAS:
3605543Slinton 			alias(p->left->sconval, p->right->sconval);
3615543Slinton 			break;
3625543Slinton 
3635543Slinton 		case O_CALL:
3645543Slinton 			callproc(p->left, p->right);
3655543Slinton 			break;
3665543Slinton 
3675543Slinton 		case O_EDIT:
3685543Slinton 			edit(p->sconval);
3695543Slinton 			break;
3705543Slinton 
3715543Slinton 		case O_DUMP:
3725543Slinton 			dump();
3735543Slinton 			break;
3745543Slinton 
375*5562Slinton 		case O_GRIPE:
376*5562Slinton 			gripe();
377*5562Slinton 			break;
378*5562Slinton 
3795543Slinton 		case O_HELP:
3805543Slinton 			help();
3815543Slinton 			break;
3825543Slinton 
3835543Slinton 		case O_REMAKE:
3845543Slinton 			remake();
3855543Slinton 			break;
3865543Slinton 
3875543Slinton 		case O_RUN:
3885543Slinton 			run();
3895543Slinton 			break;
3905543Slinton 
3915543Slinton 		case O_SOURCE:
3925543Slinton 			setinput(p->sconval);
3935543Slinton 			break;
3945543Slinton 
3955543Slinton 		case O_STATUS:
3965543Slinton 			status();
3975543Slinton 			break;
3985543Slinton 
3995543Slinton 		case O_TRACE:
4005543Slinton 		case O_TRACEI:
4015543Slinton 			trace(p->op, p->what, p->where, p->cond);
4025543Slinton 			if (isstdin()) {
4035543Slinton 				status();
4045543Slinton 			}
4055543Slinton 			break;
4065543Slinton 
4075543Slinton 		case O_STOP:
4085543Slinton 		case O_STOPI:
4095543Slinton 			stop(p->op, p->what, p->where, p->cond);
4105543Slinton 			if (isstdin()) {
4115543Slinton 				status();
4125543Slinton 			}
4135543Slinton 			break;
4145543Slinton 
4155543Slinton 		case O_DELETE:
4165543Slinton 			eval(p->left);
4175543Slinton 			delbp((unsigned int) pop(long));
4185543Slinton 			break;
4195543Slinton 
4205543Slinton 		default:
4215543Slinton 			panic("eval: bad op %d", p->op);
4225543Slinton 	}
4235543Slinton }
4245543Slinton 
4255543Slinton /*
426*5562Slinton  * Push "len" bytes onto the expression stack from address "addr"
427*5562Slinton  * in the process.  Normally TRUE is returned, however if there
428*5562Slinton  * isn't enough room on the stack, rpush returns FALSE.
429*5562Slinton  *
430*5562Slinton  */
431*5562Slinton 
432*5562Slinton BOOLEAN rpush(addr, len)
433*5562Slinton ADDRESS addr;
434*5562Slinton int len;
435*5562Slinton {
436*5562Slinton 	BOOLEAN success;
437*5562Slinton 
438*5562Slinton 	if (sp + len >= &stack[STACKSIZE]) {
439*5562Slinton 		success = FALSE;
440*5562Slinton 	} else {
441*5562Slinton 		dread(sp, addr, len);
442*5562Slinton 		sp += len;
443*5562Slinton 		success = TRUE;
444*5562Slinton 	}
445*5562Slinton 	return success;
446*5562Slinton }
447*5562Slinton 
448*5562Slinton /*
4495543Slinton  * evaluate a conditional expression
4505543Slinton  */
4515543Slinton 
4525543Slinton BOOLEAN cond(p)
4535543Slinton NODE *p;
4545543Slinton {
4555543Slinton 	if (p == NIL) {
4565543Slinton 		return(TRUE);
4575543Slinton 	}
4585543Slinton 	eval(p);
4595543Slinton 	return(pop(BOOLEAN));
4605543Slinton }
4615543Slinton 
4625543Slinton /*
4635543Slinton  * Return the address corresponding to a given tree.
4645543Slinton  */
4655543Slinton 
4665543Slinton ADDRESS lval(p)
4675543Slinton NODE *p;
4685543Slinton {
4695543Slinton 	eval(p);
4705543Slinton 	return(pop(ADDRESS));
4715543Slinton }
472