code.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
code.c (10181B) | |
--- | |
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 nop(void) | |
42 { | |
43 } | |
44 | |
45 void | |
46 push(Datum d) | |
47 { | |
48 if (stackp >= &stack[NSTACK]) | |
49 execerror("stack too deep", 0); | |
50 *stackp++ = d; | |
51 } | |
52 | |
53 Datum | |
54 pop(void) | |
55 { | |
56 if (stackp == stack) | |
57 execerror("stack underflow", 0); | |
58 return *--stackp; | |
59 } | |
60 | |
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 } | |
68 | |
69 void | |
70 constpush(void) | |
71 { | |
72 Datum d; | |
73 d.val = ((Symbol *)*pc++)->u.val; | |
74 push(d); | |
75 } | |
76 | |
77 void | |
78 varpush(void) | |
79 { | |
80 Datum d; | |
81 d.sym = (Symbol *)(*pc++); | |
82 push(d); | |
83 } | |
84 | |
85 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 | |
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 | |
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 | |
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 | |
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 argumen… | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
323 negate(void) | |
324 { | |
325 Datum d; | |
326 d = pop(); | |
327 d.val = -d.val; | |
328 push(d); | |
329 } | |
330 | |
331 void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
566 ppush(Datum *d) | |
567 { | |
568 push(*d); | |
569 } | |
570 | |
571 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 | |
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 | |
606 prexpr(void) /* print numeric value */ | |
607 { | |
608 Datum d; | |
609 d = pop(); | |
610 print("%.17g ", d.val); | |
611 } | |
612 | |
613 void | |
614 prstr(void) /* print string value */ | |
615 { | |
616 print("%s", (char *) *pc++); | |
617 } | |
618 | |
619 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* | |
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 | |
662 execute(Inst* p) | |
663 { | |
664 for (pc = p; *pc != STOP && !returning; ) | |
665 (*((++pc)[-1]))(); | |
666 } |