henesyinit from p9f47575dc5 years agoHistory
667 lines · 10.0 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include "hoc.h"#include "y.tab.h" #define	NSTACK	256 static Datum stack[NSTACK];	/* the stack */static Datum *stackp;		/* next free spot on stack */ #define	NPROG	2000Inst	prog[NPROG];	/* the machine */Inst	*progp;		/* next free spot for code generation */Inst	*pc;		/* program counter during execution */Inst	*progbase = prog; /* start of current subprogram */int	returning;	/* 1 if return stmt seen */ typedef struct Frame {	/* proc/func call stack frame */	Symbol	*sp;	/* symbol table entry */	Inst	*retpc;	/* where to resume after return */	Datum	*argn;	/* n-th argument on stack */	int	nargs;	/* number of arguments */} Frame;#define	NFRAME	100Frame	frame[NFRAME];Frame	*fp;		/* frame pointer */ voidinitcode(void){	progp = progbase;	stackp = stack;	fp = frame;	returning = 0;} voidpush(Datum d){	if (stackp >= &stack[NSTACK])		execerror("stack too deep", 0);	*stackp++ = d;} Datumpop(void){	if (stackp == stack)		execerror("stack underflow", 0);	return *--stackp;} voidxpop(void)	/* for when no value is wanted */{	if (stackp == stack)		execerror("stack underflow", (char *)0);	--stackp;} voidconstpush(void){	Datum d;	d.val = ((Symbol *)*pc++)->u.val;	push(d);} voidvarpush(void){	Datum d;	d.sym = (Symbol *)(*pc++);	push(d);} voidwhilecode(void){	Datum d;	Inst *savepc = pc; 	execute(savepc+2);	/* condition */	d = pop();	while (d.val) {		execute(*((Inst **)(savepc)));	/* body */		if (returning)			break;		execute(savepc+2);	/* condition */		d = pop();	}	if (!returning)		pc = *((Inst **)(savepc+1)); /* next stmt */} voidforcode(void){	Datum d;	Inst *savepc = pc; 	execute(savepc+4);		/* precharge */	pop();	execute(*((Inst **)(savepc)));	/* condition */	d = pop();	while (d.val) {		execute(*((Inst **)(savepc+2)));	/* body */		if (returning)			break;		execute(*((Inst **)(savepc+1)));	/* post loop */		pop();		execute(*((Inst **)(savepc)));	/* condition */		d = pop();	}	if (!returning)		pc = *((Inst **)(savepc+3)); /* next stmt */} voidifcode(void) {	Datum d;	Inst *savepc = pc;	/* then part */ 	execute(savepc+3);	/* condition */	d = pop();	if (d.val)		execute(*((Inst **)(savepc)));		else if (*((Inst **)(savepc+1))) /* else part? */		execute(*((Inst **)(savepc+1)));	if (!returning)		pc = *((Inst **)(savepc+2)); /* next stmt */} voiddefine(Symbol* sp)	/* put func/proc in symbol table */{	sp->u.defn = progbase;	/* start of code */	progbase = progp;	/* next code starts here */} voidcall(void) 		/* call a function */{	Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */				      /* for function */	if (fp++ >= &frame[NFRAME-1])		execerror(sp->name, "call nested too deeply");	fp->sp = sp;	fp->nargs = (int)pc[1];	fp->retpc = pc + 2;	fp->argn = stackp - 1;	/* last argument */	execute(sp->u.defn);	returning = 0;} static voidret(void) 		/* common return from func or proc */{	int i;	for (i = 0; i < fp->nargs; i++)		pop();	/* pop arguments */	pc = (Inst *)fp->retpc;	--fp;	returning = 1;} voidfuncret(void) 	/* return from a function */{	Datum d;	if (fp->sp->type == PROCEDURE)		execerror(fp->sp->name, "(proc) returns value");	d = pop();	/* preserve function return value */	ret();	push(d);} voidprocret(void) 	/* return from a procedure */{	if (fp->sp->type == FUNCTION)		execerror(fp->sp->name,			"(func) returns no value");	ret();} double*getarg(void) 	/* return pointer to argument */{	int nargs = (int) *pc++;	if (nargs > fp->nargs)	    execerror(fp->sp->name, "not enough arguments");	return &fp->argn[nargs - fp->nargs].val;} voidarg(void) 	/* push argument onto stack */{	Datum d;	d.val = *getarg();	push(d);} voidargassign(void) 	/* store top of stack in argument */{	Datum d;	d = pop();	push(d);	/* leave value on stack */	*getarg() = d.val;} voidargaddeq(void) 	/* store top of stack in argument */{	Datum d;	d = pop();	d.val = *getarg() += d.val;	push(d);	/* leave value on stack */} voidargsubeq(void) 	/* store top of stack in argument */{	Datum d;	d = pop();	d.val = *getarg() -= d.val;	push(d);	/* leave value on stack */} voidargmuleq(void) 	/* store top of stack in argument */{	Datum d;	d = pop();	d.val = *getarg() *= d.val;	push(d);	/* leave value on stack */} voidargdiveq(void) 	/* store top of stack in argument */{	Datum d;	d = pop();	d.val = *getarg() /= d.val;	push(d);	/* leave value on stack */} voidargmodeq(void) 	/* store top of stack in argument */{	Datum d;	double *x;	long y;	d = pop();	/* d.val = *getarg() %= d.val; */	x = getarg();	y = *x;	d.val = *x = y % (long) d.val;	push(d);	/* leave value on stack */} voidbltin(void) { 	Datum d;	d = pop();	d.val = (*(double (*)(double))*pc++)(d.val);	push(d);} voidadd(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val += d2.val;	push(d1);} voidsub(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val -= d2.val;	push(d1);} voidmul(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val *= d2.val;	push(d1);} voiddiv(void){	Datum d1, d2;	d2 = pop();	if (d2.val == 0.0)		execerror("division by zero", (char *)0);	d1 = pop();	d1.val /= d2.val;	push(d1);} voidmod(void){	Datum d1, d2;	long x;	d2 = pop();	if (d2.val == 0.0)		execerror("division by zero", (char *)0);	d1 = pop();	/* d1.val %= d2.val; */	x = d1.val;	x %= (long) d2.val;	d1.val = d2.val = x;	push(d1);} voidnegate(void){	Datum d;	d = pop();	d.val = -d.val;	push(d);} voidverify(Symbol* s){	if (s->type != VAR && s->type != UNDEF)		execerror("attempt to evaluate non-variable", s->name);	if (s->type == UNDEF)		execerror("undefined variable", s->name);} voideval(void)		/* evaluate variable on stack */{	Datum d;	d = pop();	verify(d.sym);	d.val = d.sym->u.val;	push(d);} voidpreinc(void){	Datum d;	d.sym = (Symbol *)(*pc++);	verify(d.sym);	d.val = d.sym->u.val += 1.0;	push(d);} voidpredec(void){	Datum d;	d.sym = (Symbol *)(*pc++);	verify(d.sym);	d.val = d.sym->u.val -= 1.0;	push(d);} voidpostinc(void){	Datum d;	double v;	d.sym = (Symbol *)(*pc++);	verify(d.sym);	v = d.sym->u.val;	d.sym->u.val += 1.0;	d.val = v;	push(d);} voidpostdec(void){	Datum d;	double v;	d.sym = (Symbol *)(*pc++);	verify(d.sym);	v = d.sym->u.val;	d.sym->u.val -= 1.0;	d.val = v;	push(d);} voidgt(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val > d2.val);	push(d1);} voidlt(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val < d2.val);	push(d1);} voidge(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val >= d2.val);	push(d1);} voidle(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val <= d2.val);	push(d1);} voideq(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val == d2.val);	push(d1);} voidne(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val != d2.val);	push(d1);} voidand(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val != 0.0 && d2.val != 0.0);	push(d1);} voidor(void){	Datum d1, d2;	d2 = pop();	d1 = pop();	d1.val = (double)(d1.val != 0.0 || d2.val != 0.0);	push(d1);} voidnot(void){	Datum d;	d = pop();	d.val = (double)(d.val == 0.0);	push(d);} voidpower(void){	Datum d1, d2;	d2 = pop();

Lines 1–500 of 667.