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 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
    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 }