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