xref: /csrg-svn/usr.bin/pascal/pdx/tree/eval.c (revision 5886)
15543Slinton /* Copyright (c) 1982 Regents of the University of California */
25543Slinton 
3*5886Slinton static char sccsid[] = "@(#)eval.c 1.4 02/17/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 {
315782Slinton     long r0, r1;
325782Slinton     double fr0, fr1;
335543Slinton 
345782Slinton     if (p == NULL) {
355782Slinton 	return;
365782Slinton     }
375782Slinton     switch(degree(p->op)) {
385782Slinton 	case BINARY:
395782Slinton 	    eval(p->right);
405782Slinton 	    if (isreal(p->op)) {
415782Slinton 		fr1 = pop(double);
425782Slinton 	    } else if (isint(p->op)) {
435782Slinton 		r1 = pop(long);
445782Slinton 	    }
455782Slinton 	    /* fall through */
465782Slinton 	case UNARY:
475782Slinton 	    eval(p->left);
485782Slinton 	    if (isreal(p->op)) {
495782Slinton 		fr0 = pop(double);
505782Slinton 	    } else if (isint(p->op)) {
515782Slinton 		r0 = pop(long);
525782Slinton 	    }
535782Slinton 	    break;
545782Slinton 
555782Slinton 	default:
565782Slinton 	    /* do nothing */;
575543Slinton 	}
585782Slinton     switch(p->op) {
595782Slinton 	case O_NAME: {
605782Slinton 	    SYM *s, *f;
615543Slinton 
625782Slinton 	    s = p->nameval;
63*5886Slinton 	    if (!isvariable(s)) {
64*5886Slinton 		error("cannot evaluate a %s", classname(s));
65*5886Slinton 	    } else {
66*5886Slinton 		f = container(s);
67*5886Slinton 		if (!isactive(f)) {
68*5886Slinton 		    error("\"%s\" is not active", name(f));
69*5886Slinton 		}
70*5886Slinton 		push(int, address(s, NIL));
715782Slinton 	    }
725782Slinton 	    break;
735782Slinton 	}
745543Slinton 
755782Slinton 	case O_LCON:
765782Slinton 	    switch (size(p->nodetype)) {
775782Slinton 		case sizeof(char):
785782Slinton 		    push(char, p->lconval);
795782Slinton 		    break;
805543Slinton 
815782Slinton 		case sizeof(short):
825782Slinton 		    push(short, p->lconval);
835782Slinton 		    break;
845543Slinton 
855782Slinton 		case sizeof(long):
865782Slinton 		    push(long, p->lconval);
875782Slinton 		    break;
885543Slinton 
895782Slinton 		default:
905782Slinton 		    panic("bad size %d for LCON", size(p->nodetype));
915782Slinton 	    }
925782Slinton 	    break;
935543Slinton 
945782Slinton 	case O_FCON:
955782Slinton 	    push(double, p->fconval);
965782Slinton 	    break;
975543Slinton 
985782Slinton 	case O_SCON: {
995782Slinton 	    int len;
1005543Slinton 
1015782Slinton 	    len = size(p->nodetype);
1025782Slinton 	    mov(p->sconval, sp, len);
1035782Slinton 	    sp += len;
1045782Slinton 	    break;
1055782Slinton 	}
1065543Slinton 
1075782Slinton 	case O_INDEX: {
1085782Slinton 	    int n;
1095782Slinton 	    long i;
1105543Slinton 
1115782Slinton 	    n = pop(int);
1125782Slinton 	    i = evalindex(p->left->nodetype, popsmall(p->right->nodetype));
1135782Slinton 	    push(int, n + i*size(p->nodetype));
1145782Slinton 	    break;
1155782Slinton 	}
1165543Slinton 
1175782Slinton 	case O_INDIR: {
1185782Slinton 	    ADDRESS a;
1195543Slinton 
1205782Slinton 	    a = pop(ADDRESS);
1215782Slinton 	    if (a == 0) {
1225782Slinton 		error("reference through nil pointer");
1235782Slinton 	    }
1245782Slinton 	    dread(sp, a, sizeof(ADDRESS));
1255782Slinton 	    sp += sizeof(ADDRESS);
1265782Slinton 	    break;
1275782Slinton 	}
1285543Slinton 
1295782Slinton 	/*
1305782Slinton 	 * Get the value of the expression addressed by the top of the stack.
1315782Slinton 	 * Push the result back on the stack.  Never push less than a long.
1325782Slinton 	 */
1335543Slinton 
1345782Slinton 	case O_RVAL: {
1355782Slinton 	    ADDRESS addr, len;
1365782Slinton 	    long i;
1375543Slinton 
1385782Slinton 	    addr = pop(int);
1395782Slinton 	    if (addr == 0) {
1405782Slinton 		error("reference through nil pointer");
1415782Slinton 	    }
1425782Slinton 	    len = size(p->nodetype);
1435782Slinton 	    if (!rpush(addr, len)) {
1445782Slinton 		error("expression too large to evaluate");
1455782Slinton 	    }
1465782Slinton 	    break;
1475782Slinton 	}
1485543Slinton 
1495782Slinton 	case O_COMMA:
1505782Slinton 	    break;
1515543Slinton 
1525782Slinton 	case O_ITOF:
1535782Slinton 	    push(double, (double) r0);
1545782Slinton 	    break;
1555543Slinton 
1565782Slinton 	case O_ADD:
1575782Slinton 	    push(long, r0+r1);
1585782Slinton 	    break;
1595543Slinton 
1605782Slinton 	case O_ADDF:
1615782Slinton 	    push(double, fr0+fr1);
1625782Slinton 	    break;
1635543Slinton 
1645782Slinton 	case O_SUB:
1655782Slinton 	    push(long, r0-r1);
1665782Slinton 	    break;
1675543Slinton 
1685782Slinton 	case O_SUBF:
1695782Slinton 	    push(double, fr0-fr1);
1705782Slinton 	    break;
1715543Slinton 
1725782Slinton 	case O_NEG:
1735782Slinton 	    push(long, -r0);
1745782Slinton 	    break;
1755543Slinton 
1765782Slinton 	case O_NEGF:
1775782Slinton 	    push(double, -fr0);
1785782Slinton 	    break;
1795543Slinton 
1805782Slinton 	case O_MUL:
1815782Slinton 	    push(long, r0*r1);
1825782Slinton 	    break;
1835543Slinton 
1845782Slinton 	case O_MULF:
1855782Slinton 	    push(double, fr0*fr1);
1865782Slinton 	    break;
1875543Slinton 
1885782Slinton 	case O_DIVF:
1895782Slinton 	    if (fr1 == 0) {
1905782Slinton 		error("error: division by 0");
1915782Slinton 	    }
1925782Slinton 	    push(double, fr0/fr1);
1935782Slinton 	    break;
1945543Slinton 
1955782Slinton 	case O_DIV:
1965782Slinton 	    if (r1 == 0) {
1975782Slinton 		error("error: div by 0");
1985782Slinton 	    }
1995782Slinton 	    push(long, r0/r1);
2005782Slinton 	    break;
2015543Slinton 
2025782Slinton 	case O_MOD:
2035782Slinton 	    if (r1 == 0) {
2045782Slinton 		error("error: mod by 0");
2055782Slinton 	    }
2065782Slinton 	    push(long, r0%r1);
2075782Slinton 	    break;
2085543Slinton 
2095782Slinton 	case O_LT:
2105782Slinton 	    push(BOOLEAN, r0 < r1);
2115782Slinton 	    break;
2125543Slinton 
2135782Slinton 	case O_LTF:
2145782Slinton 	    push(BOOLEAN, fr0 < fr1);
2155782Slinton 	    break;
2165543Slinton 
2175782Slinton 	case O_LE:
2185782Slinton 	    push(BOOLEAN, r0 <= r1);
2195782Slinton 	    break;
2205543Slinton 
2215782Slinton 	case O_LEF:
2225782Slinton 	    push(BOOLEAN, fr0 <= fr1);
2235782Slinton 	    break;
2245543Slinton 
2255782Slinton 	case O_GT:
2265782Slinton 	    push(BOOLEAN, r0 > r1);
2275782Slinton 	    break;
2285543Slinton 
2295782Slinton 	case O_GTF:
2305782Slinton 	    push(BOOLEAN, fr0 > fr1);
2315782Slinton 	    break;
2325543Slinton 
2335782Slinton 	case O_EQ:
2345782Slinton 	    push(BOOLEAN, r0 == r1);
2355782Slinton 	    break;
2365543Slinton 
2375782Slinton 	case O_EQF:
2385782Slinton 	    push(BOOLEAN, fr0 == fr1);
2395782Slinton 	    break;
2405543Slinton 
2415782Slinton 	case O_NE:
2425782Slinton 	    push(BOOLEAN, r0 != r1);
2435782Slinton 	    break;
2445543Slinton 
2455782Slinton 	case O_NEF:
2465782Slinton 	    push(BOOLEAN, fr0 != fr1);
2475782Slinton 	    break;
2485543Slinton 
2495782Slinton 	case O_AND:
2505782Slinton 	    push(BOOLEAN, r0 && r1);
2515782Slinton 	    break;
2525543Slinton 
2535782Slinton 	case O_OR:
2545782Slinton 	    push(BOOLEAN, r0 || r1);
2555782Slinton 	    break;
2565543Slinton 
2575782Slinton 	case O_ASSIGN:
2585782Slinton 	    assign(p->left, p->right);
2595782Slinton 	    break;
2605543Slinton 
2615782Slinton 	case O_CHFILE:
2625782Slinton 	    if (p->sconval == NIL) {
2635782Slinton 		printf("%s\n", cursource);
2645782Slinton 	    } else {
2655782Slinton 		skimsource(p->sconval);
2665782Slinton 	    }
2675782Slinton 	    break;
2685543Slinton 
2695782Slinton 	case O_CONT:
2705782Slinton 	    cont();
2715782Slinton 	    printnews();
2725782Slinton 	    break;
2735543Slinton 
2745782Slinton 	case O_LIST: {
2755782Slinton 	    SYM *b;
2765543Slinton 
2775782Slinton 	    if (p->left->op == O_NAME) {
2785782Slinton 		b = p->left->nameval;
2795782Slinton 		if (!isblock(b)) {
2805782Slinton 		    error("\"%s\" is not a procedure or function", name(b));
2815543Slinton 		}
2825782Slinton 		r0 = srcline(firstline(b));
2835782Slinton 		r1 = r0 + 5;
2845782Slinton 		if (r1 > lastlinenum) {
2855782Slinton 		    r1 = lastlinenum;
2865782Slinton 		}
2875782Slinton 		r0 = r0 - 5;
2885782Slinton 		if (r0 < 1) {
2895782Slinton 		    r0 = 1;
2905782Slinton 		}
2915782Slinton 	    } else {
2925782Slinton 		eval(p->left->right);
2935782Slinton 		eval(p->left->left);
2945782Slinton 		r0 = pop(long);
2955782Slinton 		r1 = pop(long);
2965782Slinton 	    }
2975782Slinton 	    printlines((LINENO) r0, (LINENO) r1);
2985782Slinton 	    break;
2995782Slinton 	}
3005543Slinton 
3015782Slinton 	case O_XI:
3025782Slinton 	case O_XD:
3035782Slinton 	{
3045782Slinton 	    SYM *b;
3055543Slinton 
3065782Slinton 	    if (p->left->op == O_CALL) {
3075782Slinton 		b = p->left->left->nameval;
3085782Slinton 		r0 = codeloc(b);
3095782Slinton 		r1 = firstline(b);
3105782Slinton 	    } else {
3115782Slinton 		eval(p->left->right);
3125782Slinton 		eval(p->left->left);
3135782Slinton 		r0 = pop(long);
3145782Slinton 		r1 = pop(long);
3155782Slinton 	    }
3165782Slinton 	    if (p->op == O_XI)  {
3175782Slinton 		printinst((ADDRESS) r0, (ADDRESS) r1);
3185782Slinton 	    } else {
3195782Slinton 		printdata((ADDRESS) r0, (ADDRESS) r1);
3205782Slinton 	    }
3215782Slinton 	    break;
3225782Slinton 	}
3235543Slinton 
3245782Slinton 	case O_NEXT:
3255782Slinton 	    next();
3265782Slinton 	    printnews();
3275782Slinton 	    break;
3285543Slinton 
3295782Slinton 	case O_PRINT: {
3305782Slinton 	    NODE *o;
3315543Slinton 
3325782Slinton 	    for (o = p->left; o != NIL; o = o->right) {
3335782Slinton 		eval(o->left);
3345782Slinton 		printval(o->left->nodetype);
3355782Slinton 		putchar(' ');
3365782Slinton 	    }
3375782Slinton 	    putchar('\n');
3385782Slinton 	    break;
3395782Slinton 	}
3405543Slinton 
3415782Slinton 	case O_STEP:
3425782Slinton 	    stepc();
3435782Slinton 	    printnews();
3445782Slinton 	    break;
3455543Slinton 
3465782Slinton 	case O_WHATIS:
3475782Slinton 	    if (p->left->op == O_NAME) {
3485782Slinton 		printdecl(p->left->nameval);
3495782Slinton 	    } else {
3505782Slinton 		printdecl(p->left->nodetype);
3515782Slinton 	    }
3525782Slinton 	    break;
3535543Slinton 
3545782Slinton 	case O_WHICH:
3555782Slinton 	    printwhich(p->nameval);
3565782Slinton 	    putchar('\n');
3575782Slinton 	    break;
3585543Slinton 
3595782Slinton 	case O_WHERE:
3605782Slinton 	    where();
3615782Slinton 	    break;
3625543Slinton 
3635782Slinton 	case O_ALIAS:
3645782Slinton 	    alias(p->left->sconval, p->right->sconval);
3655782Slinton 	    break;
3665543Slinton 
3675782Slinton 	case O_CALL:
3685782Slinton 	    callproc(p->left, p->right);
3695782Slinton 	    break;
3705543Slinton 
3715782Slinton 	case O_EDIT:
3725782Slinton 	    edit(p->sconval);
3735782Slinton 	    break;
3745543Slinton 
3755782Slinton 	case O_DUMP:
3765782Slinton 	    dump();
3775782Slinton 	    break;
3785543Slinton 
3795782Slinton 	case O_GRIPE:
3805782Slinton 	    gripe();
3815782Slinton 	    break;
3825562Slinton 
3835782Slinton 	case O_HELP:
3845782Slinton 	    help();
3855782Slinton 	    break;
3865543Slinton 
3875782Slinton 	case O_REMAKE:
3885782Slinton 	    remake();
3895782Slinton 	    break;
3905543Slinton 
3915782Slinton 	case O_RUN:
3925782Slinton 	    run();
3935782Slinton 	    break;
3945543Slinton 
3955782Slinton 	case O_SOURCE:
3965782Slinton 	    setinput(p->sconval);
3975782Slinton 	    break;
3985543Slinton 
3995782Slinton 	case O_STATUS:
4005782Slinton 	    status();
4015782Slinton 	    break;
4025543Slinton 
4035782Slinton 	case O_TRACE:
4045782Slinton 	case O_TRACEI:
4055782Slinton 	    trace(p->op, p->what, p->where, p->cond);
4065782Slinton 	    if (isstdin()) {
4075782Slinton 		status();
4085782Slinton 	    }
4095782Slinton 	    break;
4105543Slinton 
4115782Slinton 	case O_STOP:
4125782Slinton 	case O_STOPI:
4135782Slinton 	    stop(p->op, p->what, p->where, p->cond);
4145782Slinton 	    if (isstdin()) {
4155782Slinton 		status();
4165782Slinton 	    }
4175782Slinton 	    break;
4185543Slinton 
4195782Slinton 	case O_DELETE:
4205782Slinton 	    eval(p->left);
4215782Slinton 	    delbp((unsigned int) pop(long));
4225782Slinton 	    break;
4235543Slinton 
4245782Slinton 	default:
4255782Slinton 	    panic("eval: bad op %d", p->op);
4265782Slinton     }
4275543Slinton }
4285543Slinton 
4295543Slinton /*
4305562Slinton  * Push "len" bytes onto the expression stack from address "addr"
4315562Slinton  * in the process.  Normally TRUE is returned, however if there
4325562Slinton  * isn't enough room on the stack, rpush returns FALSE.
4335562Slinton  */
4345562Slinton 
4355562Slinton BOOLEAN rpush(addr, len)
4365562Slinton ADDRESS addr;
4375562Slinton int len;
4385562Slinton {
4395782Slinton     BOOLEAN success;
4405562Slinton 
4415782Slinton     if (sp + len >= &stack[STACKSIZE]) {
4425782Slinton 	success = FALSE;
4435782Slinton     } else {
4445782Slinton 	dread(sp, addr, len);
4455782Slinton 	sp += len;
4465782Slinton 	success = TRUE;
4475782Slinton     }
4485782Slinton     return success;
4495562Slinton }
4505562Slinton 
4515562Slinton /*
4525782Slinton  * Pop an item of the given type which is assumed to be no larger
4535782Slinton  * than a long and return it expanded into a long.
4545782Slinton  */
4555782Slinton 
4565782Slinton long popsmall(t)
4575782Slinton SYM *t;
4585782Slinton {
4595782Slinton     long r;
4605782Slinton 
4615782Slinton     switch (size(t)) {
4625782Slinton 	case sizeof(char):
4635782Slinton 	    r = (long) pop(char);
4645782Slinton 	    break;
4655782Slinton 
4665782Slinton 	case sizeof(short):
4675782Slinton 	    r = (long) pop(short);
4685782Slinton 	    break;
4695782Slinton 
4705782Slinton 	case sizeof(long):
4715782Slinton 	    r = pop(long);
4725782Slinton 	    break;
4735782Slinton 
4745782Slinton 	default:
4755782Slinton 	    panic("popsmall: size is %d", size(t));
4765782Slinton     }
4775782Slinton     return r;
4785782Slinton }
4795782Slinton 
4805782Slinton /*
4815543Slinton  * evaluate a conditional expression
4825543Slinton  */
4835543Slinton 
4845543Slinton BOOLEAN cond(p)
4855543Slinton NODE *p;
4865543Slinton {
4875782Slinton     if (p == NIL) {
4885782Slinton 	return(TRUE);
4895782Slinton     }
4905782Slinton     eval(p);
4915782Slinton     return(pop(BOOLEAN));
4925543Slinton }
4935543Slinton 
4945543Slinton /*
4955543Slinton  * Return the address corresponding to a given tree.
4965543Slinton  */
4975543Slinton 
4985543Slinton ADDRESS lval(p)
4995543Slinton NODE *p;
5005543Slinton {
5015782Slinton     eval(p);
5025782Slinton     return(pop(ADDRESS));
5035543Slinton }
504