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