xref: /plan9/sys/src/cmd/hoc/code.c (revision 7c70c028d2d46a27a61ae88e6df0eb0935d9da7a)
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