code.c (10181B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include "hoc.h" 5 #include "y.tab.h" 6 7 #define NSTACK 256 8 9 static Datum stack[NSTACK]; /* the stack */ 10 static Datum *stackp; /* next free spot on stack */ 11 12 #define NPROG 2000 13 Inst prog[NPROG]; /* the machine */ 14 Inst *progp; /* next free spot for code generation */ 15 Inst *pc; /* program counter during execution */ 16 Inst *progbase = prog; /* start of current subprogram */ 17 int returning; /* 1 if return stmt seen */ 18 int indef; /* 1 if parsing a func or proc */ 19 20 typedef struct Frame { /* proc/func call stack frame */ 21 Symbol *sp; /* symbol table entry */ 22 Inst *retpc; /* where to resume after return */ 23 Datum *argn; /* n-th argument on stack */ 24 int nargs; /* number of arguments */ 25 } Frame; 26 #define NFRAME 100 27 Frame frame[NFRAME]; 28 Frame *fp; /* frame pointer */ 29 30 void 31 initcode(void) 32 { 33 progp = progbase; 34 stackp = stack; 35 fp = frame; 36 returning = 0; 37 indef = 0; 38 } 39 40 void 41 nop(void) 42 { 43 } 44 45 void 46 push(Datum d) 47 { 48 if (stackp >= &stack[NSTACK]) 49 execerror("stack too deep", 0); 50 *stackp++ = d; 51 } 52 53 Datum 54 pop(void) 55 { 56 if (stackp == stack) 57 execerror("stack underflow", 0); 58 return *--stackp; 59 } 60 61 void 62 xpop(void) /* for when no value is wanted */ 63 { 64 if (stackp == stack) 65 execerror("stack underflow", (char *)0); 66 --stackp; 67 } 68 69 void 70 constpush(void) 71 { 72 Datum d; 73 d.val = ((Symbol *)*pc++)->u.val; 74 push(d); 75 } 76 77 void 78 varpush(void) 79 { 80 Datum d; 81 d.sym = (Symbol *)(*pc++); 82 push(d); 83 } 84 85 void 86 whilecode(void) 87 { 88 Datum d; 89 Inst *savepc = pc; 90 91 execute(savepc+2); /* condition */ 92 d = pop(); 93 while (d.val) { 94 execute(*((Inst **)(savepc))); /* body */ 95 if (returning) 96 break; 97 execute(savepc+2); /* condition */ 98 d = pop(); 99 } 100 if (!returning) 101 pc = *((Inst **)(savepc+1)); /* next stmt */ 102 } 103 104 void 105 forcode(void) 106 { 107 Datum d; 108 Inst *savepc = pc; 109 110 execute(savepc+4); /* precharge */ 111 pop(); 112 execute(*((Inst **)(savepc))); /* condition */ 113 d = pop(); 114 while (d.val) { 115 execute(*((Inst **)(savepc+2))); /* body */ 116 if (returning) 117 break; 118 execute(*((Inst **)(savepc+1))); /* post loop */ 119 pop(); 120 execute(*((Inst **)(savepc))); /* condition */ 121 d = pop(); 122 } 123 if (!returning) 124 pc = *((Inst **)(savepc+3)); /* next stmt */ 125 } 126 127 void 128 ifcode(void) 129 { 130 Datum d; 131 Inst *savepc = pc; /* then part */ 132 133 execute(savepc+3); /* condition */ 134 d = pop(); 135 if (d.val) 136 execute(*((Inst **)(savepc))); 137 else if (*((Inst **)(savepc+1))) /* else part? */ 138 execute(*((Inst **)(savepc+1))); 139 if (!returning) 140 pc = *((Inst **)(savepc+2)); /* next stmt */ 141 } 142 143 void 144 define(Symbol* sp, Formal *f) /* put func/proc in symbol table */ 145 { 146 Fndefn *fd; 147 int n; 148 149 fd = emalloc(sizeof(Fndefn)); 150 fd->code = progbase; /* start of code */ 151 progbase = progp; /* next code starts here */ 152 fd->formals = f; 153 for(n=0; f; f=f->next) 154 n++; 155 fd->nargs = n; 156 sp->u.defn = fd; 157 } 158 159 void 160 call(void) /* call a function */ 161 { 162 Formal *f; 163 Datum *arg; 164 Saveval *s; 165 int i; 166 167 Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */ 168 /* for function */ 169 if (fp >= &frame[NFRAME]) 170 execerror(sp->name, "call nested too deeply"); 171 fp++; 172 fp->sp = sp; 173 fp->nargs = (int)(uintptr)pc[1]; 174 fp->retpc = pc + 2; 175 fp->argn = stackp - 1; /* last argument */ 176 if(fp->nargs != sp->u.defn->nargs) 177 execerror(sp->name, "called with wrong number of arguments"); 178 /* bind formals */ 179 f = sp->u.defn->formals; 180 arg = stackp - fp->nargs; 181 while(f){ 182 s = emalloc(sizeof(Saveval)); 183 s->val = f->sym->u; 184 s->type = f->sym->type; 185 s->next = f->save; 186 f->save = s; 187 f->sym->u.val = arg->val; 188 f->sym->type = VAR; 189 f = f->next; 190 arg++; 191 } 192 for (i = 0; i < fp->nargs; i++) 193 pop(); /* pop arguments; no longer needed */ 194 execute(sp->u.defn->code); 195 returning = 0; 196 } 197 198 void 199 restore(Symbol *sp) /* restore formals associated with symbol */ 200 { 201 Formal *f; 202 Saveval *s; 203 204 f = sp->u.defn->formals; 205 while(f){ 206 s = f->save; 207 if(s == 0) /* more actuals than formals */ 208 break; 209 f->sym->u = s->val; 210 f->sym->type = s->type; 211 f->save = s->next; 212 free(s); 213 f = f->next; 214 } 215 } 216 217 void 218 restoreall(void) /* restore all variables in case of error */ 219 { 220 while(fp>=frame && fp->sp){ 221 restore(fp->sp); 222 --fp; 223 } 224 fp = frame; 225 } 226 227 static void 228 ret(void) /* common return from func or proc */ 229 { 230 /* restore formals */ 231 restore(fp->sp); 232 pc = (Inst *)fp->retpc; 233 --fp; 234 returning = 1; 235 } 236 237 void 238 funcret(void) /* return from a function */ 239 { 240 Datum d; 241 if (fp->sp->type == PROCEDURE) 242 execerror(fp->sp->name, "(proc) returns value"); 243 d = pop(); /* preserve function return value */ 244 ret(); 245 push(d); 246 } 247 248 void 249 procret(void) /* return from a procedure */ 250 { 251 if (fp->sp->type == FUNCTION) 252 execerror(fp->sp->name, 253 "(func) returns no value"); 254 ret(); 255 } 256 257 void 258 bltin(void) 259 { 260 261 Datum d; 262 d = pop(); 263 d.val = (*(double (*)(double))*pc++)(d.val); 264 push(d); 265 } 266 267 void 268 add(void) 269 { 270 Datum d1, d2; 271 d2 = pop(); 272 d1 = pop(); 273 d1.val += d2.val; 274 push(d1); 275 } 276 277 void 278 sub(void) 279 { 280 Datum d1, d2; 281 d2 = pop(); 282 d1 = pop(); 283 d1.val -= d2.val; 284 push(d1); 285 } 286 287 void 288 mul(void) 289 { 290 Datum d1, d2; 291 d2 = pop(); 292 d1 = pop(); 293 d1.val *= d2.val; 294 push(d1); 295 } 296 297 void 298 div(void) 299 { 300 Datum d1, d2; 301 d2 = pop(); 302 if (d2.val == 0.0) 303 execerror("division by zero", (char *)0); 304 d1 = pop(); 305 d1.val /= d2.val; 306 push(d1); 307 } 308 309 void 310 mod(void) 311 { 312 Datum d1, d2; 313 d2 = pop(); 314 if (d2.val == 0.0) 315 execerror("division by zero", (char *)0); 316 d1 = pop(); 317 /* d1.val %= d2.val; */ 318 d1.val = fmod(d1.val, d2.val); 319 push(d1); 320 } 321 322 void 323 negate(void) 324 { 325 Datum d; 326 d = pop(); 327 d.val = -d.val; 328 push(d); 329 } 330 331 void 332 verify(Symbol* s) 333 { 334 if (s->type != VAR && s->type != UNDEF) 335 execerror("attempt to evaluate non-variable", s->name); 336 if (s->type == UNDEF) 337 execerror("undefined variable", s->name); 338 } 339 340 void 341 eval(void) /* evaluate variable on stack */ 342 { 343 Datum d; 344 d = pop(); 345 verify(d.sym); 346 d.val = d.sym->u.val; 347 push(d); 348 } 349 350 void 351 preinc(void) 352 { 353 Datum d; 354 d.sym = (Symbol *)(*pc++); 355 verify(d.sym); 356 d.val = d.sym->u.val += 1.0; 357 push(d); 358 } 359 360 void 361 predec(void) 362 { 363 Datum d; 364 d.sym = (Symbol *)(*pc++); 365 verify(d.sym); 366 d.val = d.sym->u.val -= 1.0; 367 push(d); 368 } 369 370 void 371 postinc(void) 372 { 373 Datum d; 374 double v; 375 d.sym = (Symbol *)(*pc++); 376 verify(d.sym); 377 v = d.sym->u.val; 378 d.sym->u.val += 1.0; 379 d.val = v; 380 push(d); 381 } 382 383 void 384 postdec(void) 385 { 386 Datum d; 387 double v; 388 d.sym = (Symbol *)(*pc++); 389 verify(d.sym); 390 v = d.sym->u.val; 391 d.sym->u.val -= 1.0; 392 d.val = v; 393 push(d); 394 } 395 396 void 397 gt(void) 398 { 399 Datum d1, d2; 400 d2 = pop(); 401 d1 = pop(); 402 d1.val = (double)(d1.val > d2.val); 403 push(d1); 404 } 405 406 void 407 lt(void) 408 { 409 Datum d1, d2; 410 d2 = pop(); 411 d1 = pop(); 412 d1.val = (double)(d1.val < d2.val); 413 push(d1); 414 } 415 416 void 417 ge(void) 418 { 419 Datum d1, d2; 420 d2 = pop(); 421 d1 = pop(); 422 d1.val = (double)(d1.val >= d2.val); 423 push(d1); 424 } 425 426 void 427 le(void) 428 { 429 Datum d1, d2; 430 d2 = pop(); 431 d1 = pop(); 432 d1.val = (double)(d1.val <= d2.val); 433 push(d1); 434 } 435 436 void 437 eq(void) 438 { 439 Datum d1, d2; 440 d2 = pop(); 441 d1 = pop(); 442 d1.val = (double)(d1.val == d2.val); 443 push(d1); 444 } 445 446 void 447 ne(void) 448 { 449 Datum d1, d2; 450 d2 = pop(); 451 d1 = pop(); 452 d1.val = (double)(d1.val != d2.val); 453 push(d1); 454 } 455 456 void 457 and(void) 458 { 459 Datum d1, d2; 460 d2 = pop(); 461 d1 = pop(); 462 d1.val = (double)(d1.val != 0.0 && d2.val != 0.0); 463 push(d1); 464 } 465 466 void 467 or(void) 468 { 469 Datum d1, d2; 470 d2 = pop(); 471 d1 = pop(); 472 d1.val = (double)(d1.val != 0.0 || d2.val != 0.0); 473 push(d1); 474 } 475 476 void 477 not(void) 478 { 479 Datum d; 480 d = pop(); 481 d.val = (double)(d.val == 0.0); 482 push(d); 483 } 484 485 void 486 power(void) 487 { 488 Datum d1, d2; 489 d2 = pop(); 490 d1 = pop(); 491 d1.val = Pow(d1.val, d2.val); 492 push(d1); 493 } 494 495 void 496 assign(void) 497 { 498 Datum d1, d2; 499 d1 = pop(); 500 d2 = pop(); 501 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 502 execerror("assignment to non-variable", 503 d1.sym->name); 504 d1.sym->u.val = d2.val; 505 d1.sym->type = VAR; 506 push(d2); 507 } 508 509 void 510 addeq(void) 511 { 512 Datum d1, d2; 513 d1 = pop(); 514 d2 = pop(); 515 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 516 execerror("assignment to non-variable", 517 d1.sym->name); 518 d2.val = d1.sym->u.val += d2.val; 519 d1.sym->type = VAR; 520 push(d2); 521 } 522 523 void 524 subeq(void) 525 { 526 Datum d1, d2; 527 d1 = pop(); 528 d2 = pop(); 529 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 530 execerror("assignment to non-variable", 531 d1.sym->name); 532 d2.val = d1.sym->u.val -= d2.val; 533 d1.sym->type = VAR; 534 push(d2); 535 } 536 537 void 538 muleq(void) 539 { 540 Datum d1, d2; 541 d1 = pop(); 542 d2 = pop(); 543 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 544 execerror("assignment to non-variable", 545 d1.sym->name); 546 d2.val = d1.sym->u.val *= d2.val; 547 d1.sym->type = VAR; 548 push(d2); 549 } 550 551 void 552 diveq(void) 553 { 554 Datum d1, d2; 555 d1 = pop(); 556 d2 = pop(); 557 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 558 execerror("assignment to non-variable", 559 d1.sym->name); 560 d2.val = d1.sym->u.val /= d2.val; 561 d1.sym->type = VAR; 562 push(d2); 563 } 564 565 void 566 ppush(Datum *d) 567 { 568 push(*d); 569 } 570 571 void 572 modeq(void) 573 { 574 Datum d1, d2; 575 long x; 576 577 d1 = pop(); 578 d2 = pop(); 579 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 580 execerror("assignment to non-variable", 581 d1.sym->name); 582 /* d2.val = d1.sym->u.val %= d2.val; */ 583 x = d1.sym->u.val; 584 x %= (long) d2.val; 585 d2.val = x; 586 d1.sym->u.val = x; 587 d1.sym->type = VAR; 588 589 /* push(d2) generates a compiler error on Linux w. gcc 2.95.4 */ 590 ppush(&d2); 591 } 592 593 void 594 printtop(void) /* pop top value from stack, print it */ 595 { 596 Datum d; 597 static Symbol *s; /* last value computed */ 598 if (s == 0) 599 s = install("_", VAR, 0.0); 600 d = pop(); 601 print("%.17g\n", d.val); 602 s->u.val = d.val; 603 } 604 605 void 606 prexpr(void) /* print numeric value */ 607 { 608 Datum d; 609 d = pop(); 610 print("%.17g ", d.val); 611 } 612 613 void 614 prstr(void) /* print string value */ 615 { 616 print("%s", (char *) *pc++); 617 } 618 619 void 620 varread(void) /* read into variable */ 621 { 622 Datum d; 623 extern Biobuf *bin; 624 Symbol *var = (Symbol *) *pc++; 625 int c; 626 627 Again: 628 do 629 c = Bgetc(bin); 630 while(c==' ' || c=='\t'); 631 if(c == Beof){ 632 Iseof: 633 if(moreinput()) 634 goto Again; 635 d.val = var->u.val = 0.0; 636 goto Return; 637 } 638 639 if(strchr("+-.0123456789", c) == 0) 640 execerror("non-number read into", var->name); 641 Bungetc(bin); 642 if(Bgetd(bin, &var->u.val) == Beof) 643 goto Iseof; 644 else 645 d.val = 1.0; 646 Return: 647 var->type = VAR; 648 push(d); 649 } 650 651 Inst* 652 code(Inst f) /* install one instruction or operand */ 653 { 654 Inst *oprogp = progp; 655 if (progp >= &prog[NPROG]) 656 execerror("program too big", (char *)0); 657 *progp++ = f; 658 return oprogp; 659 } 660 661 void 662 execute(Inst* p) 663 { 664 for (pc = p; *pc != STOP && !returning; ) 665 (*((++pc)[-1]))(); 666 }