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, Formal *f) /* put func/proc in symbol table */ 140 { 141 Fndefn *fd; 142 int n; 143 144 fd = emalloc(sizeof(Fndefn)); 145 fd->code = progbase; /* start of code */ 146 progbase = progp; /* next code starts here */ 147 fd->formals = f; 148 for(n=0; f; f=f->next) 149 n++; 150 fd->nargs = n; 151 sp->u.defn = fd; 152 } 153 154 void 155 call(void) /* call a function */ 156 { 157 Formal *f; 158 Datum *arg; 159 Saveval *s; 160 int i; 161 162 Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */ 163 /* for function */ 164 if (fp >= &frame[NFRAME-1]) 165 execerror(sp->name, "call nested too deeply"); 166 fp++; 167 fp->sp = sp; 168 fp->nargs = (int)(uintptr)pc[1]; 169 fp->retpc = pc + 2; 170 fp->argn = stackp - 1; /* last argument */ 171 if(fp->nargs != sp->u.defn->nargs) 172 execerror(sp->name, "called with wrong number of arguments"); 173 /* bind formals */ 174 f = sp->u.defn->formals; 175 arg = stackp - fp->nargs; 176 while(f){ 177 s = emalloc(sizeof(Saveval)); 178 s->val = f->sym->u; 179 s->type = f->sym->type; 180 s->next = f->save; 181 f->save = s; 182 f->sym->u.val = arg->val; 183 f->sym->type = VAR; 184 f = f->next; 185 arg++; 186 } 187 for (i = 0; i < fp->nargs; i++) 188 pop(); /* pop arguments; no longer needed */ 189 execute(sp->u.defn->code); 190 returning = 0; 191 } 192 193 void 194 restore(Symbol *sp) /* restore formals associated with symbol */ 195 { 196 Formal *f; 197 Saveval *s; 198 199 f = sp->u.defn->formals; 200 while(f){ 201 s = f->save; 202 if(s == 0) /* more actuals than formals */ 203 break; 204 f->sym->u = s->val; 205 f->sym->type = s->type; 206 f->save = s->next; 207 free(s); 208 f = f->next; 209 } 210 } 211 212 void 213 restoreall(void) /* restore all variables in case of error */ 214 { 215 while(fp>=frame && fp->sp){ 216 restore(fp->sp); 217 --fp; 218 } 219 fp = frame; 220 } 221 222 static void 223 ret(void) /* common return from func or proc */ 224 { 225 /* restore formals */ 226 restore(fp->sp); 227 pc = (Inst *)fp->retpc; 228 --fp; 229 returning = 1; 230 } 231 232 void 233 funcret(void) /* return from a function */ 234 { 235 Datum d; 236 if (fp->sp->type == PROCEDURE) 237 execerror(fp->sp->name, "(proc) returns value"); 238 d = pop(); /* preserve function return value */ 239 ret(); 240 push(d); 241 } 242 243 void 244 procret(void) /* return from a procedure */ 245 { 246 if (fp->sp->type == FUNCTION) 247 execerror(fp->sp->name, 248 "(func) returns no value"); 249 ret(); 250 } 251 252 void 253 bltin(void) 254 { 255 256 Datum d; 257 d = pop(); 258 d.val = (*(double (*)(double))*pc++)(d.val); 259 push(d); 260 } 261 262 void 263 add(void) 264 { 265 Datum d1, d2; 266 d2 = pop(); 267 d1 = pop(); 268 d1.val += d2.val; 269 push(d1); 270 } 271 272 void 273 sub(void) 274 { 275 Datum d1, d2; 276 d2 = pop(); 277 d1 = pop(); 278 d1.val -= d2.val; 279 push(d1); 280 } 281 282 void 283 mul(void) 284 { 285 Datum d1, d2; 286 d2 = pop(); 287 d1 = pop(); 288 d1.val *= d2.val; 289 push(d1); 290 } 291 292 void 293 div(void) 294 { 295 Datum d1, d2; 296 d2 = pop(); 297 if (d2.val == 0.0) 298 execerror("division by zero", (char *)0); 299 d1 = pop(); 300 d1.val /= d2.val; 301 push(d1); 302 } 303 304 void 305 mod(void) 306 { 307 Datum d1, d2; 308 d2 = pop(); 309 if (d2.val == 0.0) 310 execerror("division by zero", (char *)0); 311 d1 = pop(); 312 /* d1.val %= d2.val; */ 313 d1.val = fmod(d1.val, d2.val); 314 push(d1); 315 } 316 317 void 318 negate(void) 319 { 320 Datum d; 321 d = pop(); 322 d.val = -d.val; 323 push(d); 324 } 325 326 void 327 verify(Symbol* s) 328 { 329 if (s->type != VAR && s->type != UNDEF) 330 execerror("attempt to evaluate non-variable", s->name); 331 if (s->type == UNDEF) 332 execerror("undefined variable", s->name); 333 } 334 335 void 336 eval(void) /* evaluate variable on stack */ 337 { 338 Datum d; 339 d = pop(); 340 verify(d.sym); 341 d.val = d.sym->u.val; 342 push(d); 343 } 344 345 void 346 preinc(void) 347 { 348 Datum d; 349 d.sym = (Symbol *)(*pc++); 350 verify(d.sym); 351 d.val = d.sym->u.val += 1.0; 352 push(d); 353 } 354 355 void 356 predec(void) 357 { 358 Datum d; 359 d.sym = (Symbol *)(*pc++); 360 verify(d.sym); 361 d.val = d.sym->u.val -= 1.0; 362 push(d); 363 } 364 365 void 366 postinc(void) 367 { 368 Datum d; 369 double v; 370 d.sym = (Symbol *)(*pc++); 371 verify(d.sym); 372 v = d.sym->u.val; 373 d.sym->u.val += 1.0; 374 d.val = v; 375 push(d); 376 } 377 378 void 379 postdec(void) 380 { 381 Datum d; 382 double v; 383 d.sym = (Symbol *)(*pc++); 384 verify(d.sym); 385 v = d.sym->u.val; 386 d.sym->u.val -= 1.0; 387 d.val = v; 388 push(d); 389 } 390 391 void 392 gt(void) 393 { 394 Datum d1, d2; 395 d2 = pop(); 396 d1 = pop(); 397 d1.val = (double)(d1.val > d2.val); 398 push(d1); 399 } 400 401 void 402 lt(void) 403 { 404 Datum d1, d2; 405 d2 = pop(); 406 d1 = pop(); 407 d1.val = (double)(d1.val < d2.val); 408 push(d1); 409 } 410 411 void 412 ge(void) 413 { 414 Datum d1, d2; 415 d2 = pop(); 416 d1 = pop(); 417 d1.val = (double)(d1.val >= d2.val); 418 push(d1); 419 } 420 421 void 422 le(void) 423 { 424 Datum d1, d2; 425 d2 = pop(); 426 d1 = pop(); 427 d1.val = (double)(d1.val <= d2.val); 428 push(d1); 429 } 430 431 void 432 eq(void) 433 { 434 Datum d1, d2; 435 d2 = pop(); 436 d1 = pop(); 437 d1.val = (double)(d1.val == d2.val); 438 push(d1); 439 } 440 441 void 442 ne(void) 443 { 444 Datum d1, d2; 445 d2 = pop(); 446 d1 = pop(); 447 d1.val = (double)(d1.val != d2.val); 448 push(d1); 449 } 450 451 void 452 and(void) 453 { 454 Datum d1, d2; 455 d2 = pop(); 456 d1 = pop(); 457 d1.val = (double)(d1.val != 0.0 && d2.val != 0.0); 458 push(d1); 459 } 460 461 void 462 or(void) 463 { 464 Datum d1, d2; 465 d2 = pop(); 466 d1 = pop(); 467 d1.val = (double)(d1.val != 0.0 || d2.val != 0.0); 468 push(d1); 469 } 470 471 void 472 not(void) 473 { 474 Datum d; 475 d = pop(); 476 d.val = (double)(d.val == 0.0); 477 push(d); 478 } 479 480 void 481 power(void) 482 { 483 Datum d1, d2; 484 d2 = pop(); 485 d1 = pop(); 486 d1.val = Pow(d1.val, d2.val); 487 push(d1); 488 } 489 490 void 491 assign(void) 492 { 493 Datum d1, d2; 494 d1 = pop(); 495 d2 = pop(); 496 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 497 execerror("assignment to non-variable", 498 d1.sym->name); 499 d1.sym->u.val = d2.val; 500 d1.sym->type = VAR; 501 push(d2); 502 } 503 504 void 505 addeq(void) 506 { 507 Datum d1, d2; 508 d1 = pop(); 509 d2 = pop(); 510 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 511 execerror("assignment to non-variable", 512 d1.sym->name); 513 d2.val = d1.sym->u.val += d2.val; 514 d1.sym->type = VAR; 515 push(d2); 516 } 517 518 void 519 subeq(void) 520 { 521 Datum d1, d2; 522 d1 = pop(); 523 d2 = pop(); 524 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 525 execerror("assignment to non-variable", 526 d1.sym->name); 527 d2.val = d1.sym->u.val -= d2.val; 528 d1.sym->type = VAR; 529 push(d2); 530 } 531 532 void 533 muleq(void) 534 { 535 Datum d1, d2; 536 d1 = pop(); 537 d2 = pop(); 538 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 539 execerror("assignment to non-variable", 540 d1.sym->name); 541 d2.val = d1.sym->u.val *= d2.val; 542 d1.sym->type = VAR; 543 push(d2); 544 } 545 546 void 547 diveq(void) 548 { 549 Datum d1, d2; 550 d1 = pop(); 551 d2 = pop(); 552 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 553 execerror("assignment to non-variable", 554 d1.sym->name); 555 d2.val = d1.sym->u.val /= d2.val; 556 d1.sym->type = VAR; 557 push(d2); 558 } 559 560 void 561 modeq(void) 562 { 563 Datum d1, d2; 564 long x; 565 d1 = pop(); 566 d2 = pop(); 567 if (d1.sym->type != VAR && d1.sym->type != UNDEF) 568 execerror("assignment to non-variable", 569 d1.sym->name); 570 /* d2.val = d1.sym->u.val %= d2.val; */ 571 x = d1.sym->u.val; 572 x %= (long) d2.val; 573 d2.val = d1.sym->u.val = x; 574 d1.sym->type = VAR; 575 push(d2); 576 } 577 578 void 579 printtop(void) /* pop top value from stack, print it */ 580 { 581 Datum d; 582 static Symbol *s; /* last value computed */ 583 if (s == 0) 584 s = install("_", VAR, 0.0); 585 d = pop(); 586 print("%.12g\n", d.val); 587 s->u.val = d.val; 588 } 589 590 void 591 prexpr(void) /* print numeric value */ 592 { 593 Datum d; 594 d = pop(); 595 print("%.12g ", d.val); 596 } 597 598 void 599 prstr(void) /* print string value */ 600 { 601 print("%s", (char *) *pc++); 602 } 603 604 void 605 varread(void) /* read into variable */ 606 { 607 Datum d; 608 extern Biobuf *bin; 609 Symbol *var = (Symbol *) *pc++; 610 int c; 611 612 Again: 613 do 614 c = Bgetc(bin); 615 while(c==' ' || c=='\t' || c=='\n'); 616 if(c == Beof){ 617 Iseof: 618 if(moreinput()) 619 goto Again; 620 d.val = var->u.val = 0.0; 621 goto Return; 622 } 623 624 if(strchr("+-.0123456789", c) == 0) 625 execerror("non-number read into", var->name); 626 Bungetc(bin); 627 if(Bgetd(bin, &var->u.val) == Beof) 628 goto Iseof; 629 else 630 d.val = 1.0; 631 Return: 632 var->type = VAR; 633 push(d); 634 } 635 636 Inst* 637 code(Inst f) /* install one instruction or operand */ 638 { 639 Inst *oprogp = progp; 640 if (progp >= &prog[NPROG]) 641 execerror("program too big", (char *)0); 642 *progp++ = f; 643 return oprogp; 644 } 645 646 void 647 execute(Inst* p) 648 { 649 for (pc = p; *pc != STOP && !returning; ) 650 (*((++pc)[-1]))(); 651 } 652