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