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
initcode(void)31 initcode(void)
32 {
33 progp = progbase;
34 stackp = stack;
35 fp = frame;
36 returning = 0;
37 indef = 0;
38 }
39
40 void
nop(void)41 nop(void)
42 {
43 }
44
45 void
push(Datum d)46 push(Datum d)
47 {
48 if (stackp >= &stack[NSTACK])
49 execerror("stack too deep", 0);
50 *stackp++ = d;
51 }
52
53 Datum
pop(void)54 pop(void)
55 {
56 if (stackp == stack)
57 execerror("stack underflow", 0);
58 return *--stackp;
59 }
60
61 void
xpop(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
constpush(void)70 constpush(void)
71 {
72 Datum d;
73 d.val = ((Symbol *)*pc++)->u.val;
74 push(d);
75 }
76
77 void
varpush(void)78 varpush(void)
79 {
80 Datum d;
81 d.sym = (Symbol *)(*pc++);
82 push(d);
83 }
84
85 void
whilecode(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
forcode(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
ifcode(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
define(Symbol * sp,Formal * f)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
call(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
restore(Symbol * sp)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
restoreall(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
ret(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
funcret(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
procret(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
bltin(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
add(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
sub(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
mul(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
div(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
mod(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
negate(void)323 negate(void)
324 {
325 Datum d;
326 d = pop();
327 d.val = -d.val;
328 push(d);
329 }
330
331 void
verify(Symbol * s)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
eval(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
preinc(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
predec(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
postinc(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
postdec(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
gt(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
lt(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
ge(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
le(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
eq(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
ne(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
and(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
or(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
not(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
power(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
assign(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
addeq(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
subeq(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
muleq(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
diveq(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
ppush(Datum * d)566 ppush(Datum *d)
567 {
568 push(*d);
569 }
570
571 void
modeq(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
printtop(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
prexpr(void)606 prexpr(void) /* print numeric value */
607 {
608 Datum d;
609 d = pop();
610 print("%.17g ", d.val);
611 }
612
613 void
prstr(void)614 prstr(void) /* print string value */
615 {
616 print("%s", (char *) *pc++);
617 }
618
619 void
varread(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*
code(Inst f)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
execute(Inst * p)662 execute(Inst* p)
663 {
664 for (pc = p; *pc != STOP && !returning; )
665 (*((++pc)[-1]))();
666 }
667