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
push(Datum d)41 push(Datum d)
42 {
43 if (stackp >= &stack[NSTACK])
44 execerror("stack too deep", 0);
45 *stackp++ = d;
46 }
47
48 Datum
pop(void)49 pop(void)
50 {
51 if (stackp == stack)
52 execerror("stack underflow", 0);
53 return *--stackp;
54 }
55
56 void
xpop(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
constpush(void)65 constpush(void)
66 {
67 Datum d;
68 d.val = ((Symbol *)*pc++)->u.val;
69 push(d);
70 }
71
72 void
varpush(void)73 varpush(void)
74 {
75 Datum d;
76 d.sym = (Symbol *)(*pc++);
77 push(d);
78 }
79
80 void
whilecode(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
forcode(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
ifcode(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
define(Symbol * sp,Formal * f)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
call(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
restore(Symbol * sp)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
restoreall(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
ret(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
funcret(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
procret(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
bltin(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
add(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
sub(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
mul(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
div(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
mod(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
negate(void)318 negate(void)
319 {
320 Datum d;
321 d = pop();
322 d.val = -d.val;
323 push(d);
324 }
325
326 void
verify(Symbol * s)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
eval(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
preinc(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
predec(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
postinc(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
postdec(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
gt(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
lt(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
ge(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
le(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
eq(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
ne(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
and(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
or(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
not(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
power(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
assign(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
addeq(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
subeq(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
muleq(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
diveq(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
modeq(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
printtop(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
prexpr(void)591 prexpr(void) /* print numeric value */
592 {
593 Datum d;
594 d = pop();
595 print("%.12g ", d.val);
596 }
597
598 void
prstr(void)599 prstr(void) /* print string value */
600 {
601 print("%s", (char *) *pc++);
602 }
603
604 void
varread(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*
code(Inst f)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
execute(Inst * p)647 execute(Inst* p)
648 {
649 for (pc = p; *pc != STOP && !returning; )
650 (*((++pc)[-1]))();
651 }
652