Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "hoc.h"
5 #include "y.tab.h"
7 #define NSTACK 256
9 static Datum stack[NSTACK]; /* the stack */
10 static Datum *stackp; /* next free spot on stack */
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 */
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 */
30 void
31 initcode(void)
32 {
33 progp = progbase;
34 stackp = stack;
35 fp = frame;
36 returning = 0;
37 indef = 0;
38 }
40 void
41 nop(void)
42 {
43 }
45 void
46 push(Datum d)
47 {
48 if (stackp >= &stack[NSTACK])
49 execerror("stack too deep", 0);
50 *stackp++ = d;
51 }
53 Datum
54 pop(void)
55 {
56 if (stackp == stack)
57 execerror("stack underflow", 0);
58 return *--stackp;
59 }
61 void
62 xpop(void) /* for when no value is wanted */
63 {
64 if (stackp == stack)
65 execerror("stack underflow", (char *)0);
66 --stackp;
67 }
69 void
70 constpush(void)
71 {
72 Datum d;
73 d.val = ((Symbol *)*pc++)->u.val;
74 push(d);
75 }
77 void
78 varpush(void)
79 {
80 Datum d;
81 d.sym = (Symbol *)(*pc++);
82 push(d);
83 }
85 void
86 whilecode(void)
87 {
88 Datum d;
89 Inst *savepc = pc;
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 */
104 void
105 forcode(void)
107 Datum d;
108 Inst *savepc = pc;
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();
123 if (!returning)
124 pc = *((Inst **)(savepc+3)); /* next stmt */
127 void
128 ifcode(void)
130 Datum d;
131 Inst *savepc = pc; /* then part */
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 */
143 void
144 define(Symbol* sp, Formal *f) /* put func/proc in symbol table */
146 Fndefn *fd;
147 int n;
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;
159 void
160 call(void) /* call a function */
162 Formal *f;
163 Datum *arg;
164 Saveval *s;
165 int i;
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++;
192 for (i = 0; i < fp->nargs; i++)
193 pop(); /* pop arguments; no longer needed */
194 execute(sp->u.defn->code);
195 returning = 0;
198 void
199 restore(Symbol *sp) /* restore formals associated with symbol */
201 Formal *f;
202 Saveval *s;
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;
217 void
218 restoreall(void) /* restore all variables in case of error */
220 while(fp>=frame && fp->sp){
221 restore(fp->sp);
222 --fp;
224 fp = frame;
227 static void
228 ret(void) /* common return from func or proc */
230 /* restore formals */
231 restore(fp->sp);
232 pc = (Inst *)fp->retpc;
233 --fp;
234 returning = 1;
237 void
238 funcret(void) /* return from a function */
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);
248 void
249 procret(void) /* return from a procedure */
251 if (fp->sp->type == FUNCTION)
252 execerror(fp->sp->name,
253 "(func) returns no value");
254 ret();
257 void
258 bltin(void)
261 Datum d;
262 d = pop();
263 d.val = (*(double (*)(double))*pc++)(d.val);
264 push(d);
267 void
268 add(void)
270 Datum d1, d2;
271 d2 = pop();
272 d1 = pop();
273 d1.val += d2.val;
274 push(d1);
277 void
278 sub(void)
280 Datum d1, d2;
281 d2 = pop();
282 d1 = pop();
283 d1.val -= d2.val;
284 push(d1);
287 void
288 mul(void)
290 Datum d1, d2;
291 d2 = pop();
292 d1 = pop();
293 d1.val *= d2.val;
294 push(d1);
297 void
298 div(void)
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);
309 void
310 mod(void)
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);
322 void
323 negate(void)
325 Datum d;
326 d = pop();
327 d.val = -d.val;
328 push(d);
331 void
332 verify(Symbol* s)
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);
340 void
341 eval(void) /* evaluate variable on stack */
343 Datum d;
344 d = pop();
345 verify(d.sym);
346 d.val = d.sym->u.val;
347 push(d);
350 void
351 preinc(void)
353 Datum d;
354 d.sym = (Symbol *)(*pc++);
355 verify(d.sym);
356 d.val = d.sym->u.val += 1.0;
357 push(d);
360 void
361 predec(void)
363 Datum d;
364 d.sym = (Symbol *)(*pc++);
365 verify(d.sym);
366 d.val = d.sym->u.val -= 1.0;
367 push(d);
370 void
371 postinc(void)
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);
383 void
384 postdec(void)
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);
396 void
397 gt(void)
399 Datum d1, d2;
400 d2 = pop();
401 d1 = pop();
402 d1.val = (double)(d1.val > d2.val);
403 push(d1);
406 void
407 lt(void)
409 Datum d1, d2;
410 d2 = pop();
411 d1 = pop();
412 d1.val = (double)(d1.val < d2.val);
413 push(d1);
416 void
417 ge(void)
419 Datum d1, d2;
420 d2 = pop();
421 d1 = pop();
422 d1.val = (double)(d1.val >= d2.val);
423 push(d1);
426 void
427 le(void)
429 Datum d1, d2;
430 d2 = pop();
431 d1 = pop();
432 d1.val = (double)(d1.val <= d2.val);
433 push(d1);
436 void
437 eq(void)
439 Datum d1, d2;
440 d2 = pop();
441 d1 = pop();
442 d1.val = (double)(d1.val == d2.val);
443 push(d1);
446 void
447 ne(void)
449 Datum d1, d2;
450 d2 = pop();
451 d1 = pop();
452 d1.val = (double)(d1.val != d2.val);
453 push(d1);
456 void
457 and(void)
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);
466 void
467 or(void)
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);
476 void
477 not(void)
479 Datum d;
480 d = pop();
481 d.val = (double)(d.val == 0.0);
482 push(d);
485 void
486 power(void)
488 Datum d1, d2;
489 d2 = pop();
490 d1 = pop();
491 d1.val = Pow(d1.val, d2.val);
492 push(d1);
495 void
496 assign(void)
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);
509 void
510 addeq(void)
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);
523 void
524 subeq(void)
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);
537 void
538 muleq(void)
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);
551 void
552 diveq(void)
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);
565 void
566 ppush(Datum *d)
568 push(*d);
571 void
572 modeq(void)
574 Datum d1, d2;
575 long x;
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;
589 /* push(d2) generates a compiler error on Linux w. gcc 2.95.4 */
590 ppush(&d2);
593 void
594 printtop(void) /* pop top value from stack, print it */
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;
605 void
606 prexpr(void) /* print numeric value */
608 Datum d;
609 d = pop();
610 print("%.17g ", d.val);
613 void
614 prstr(void) /* print string value */
616 print("%s", (char *) *pc++);
619 void
620 varread(void) /* read into variable */
622 Datum d;
623 extern Biobuf *bin;
624 Symbol *var = (Symbol *) *pc++;
625 int c;
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;
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);
651 Inst*
652 code(Inst f) /* install one instruction or operand */
654 Inst *oprogp = progp;
655 if (progp >= &prog[NPROG])
656 execerror("program too big", (char *)0);
657 *progp++ = f;
658 return oprogp;
661 void
662 execute(Inst* p)
664 for (pc = p; *pc != STOP && !returning; )
665 (*((++pc)[-1]))();