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