henesyinit from p9fd787fda5 years agoHistory
651 lines · 9.8 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 */int	indef;	/* 1 if parsing a func or proc */ 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;	indef = 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, Formal *f)	/* put func/proc in symbol table */{	Fndefn *fd;	int n; 	fd = emalloc(sizeof(Fndefn));	fd->code = progbase;	/* start of code */	progbase = progp;	/* next code starts here */	fd->formals = f;	for(n=0; f; f=f->next)		n++;	fd->nargs = n;	sp->u.defn = fd;} voidcall(void) 		/* call a function */{	Formal *f;	Datum *arg;	Saveval *s;	int i; 	Symbol *sp = (Symbol *)pc[0]; /* symbol table entry */				      /* for function */	if (fp >= &frame[NFRAME])		execerror(sp->name, "call nested too deeply");	fp++;	fp->sp = sp;	fp->nargs = (int)pc[1];	fp->retpc = pc + 2;	fp->argn = stackp - 1;	/* last argument */	if(fp->nargs != sp->u.defn->nargs)		execerror(sp->name, "called with wrong number of arguments");	/* bind formals */	f = sp->u.defn->formals;	arg = stackp - fp->nargs;	while(f){		s = emalloc(sizeof(Saveval));		s->val = f->sym->u;		s->type = f->sym->type;		s->next = f->save;		f->save = s;		f->sym->u.val = arg->val;		f->sym->type = VAR;		f = f->next;		arg++;	}	for (i = 0; i < fp->nargs; i++)		pop();	/* pop arguments; no longer needed */	execute(sp->u.defn->code);	returning = 0;} voidrestore(Symbol *sp)	/* restore formals associated with symbol */{	Formal *f;	Saveval *s; 	f = sp->u.defn->formals;	while(f){		s = f->save;		if(s == 0)	/* more actuals than formals */			break;		f->sym->u = s->val;		f->sym->type = s->type;		f->save = s->next;		free(s);		f = f->next;	}} voidrestoreall(void)	/* restore all variables in case of error */{	while(fp>=frame && fp->sp){		restore(fp->sp);		--fp;	}	fp = frame;} static voidret(void) 		/* common return from func or proc */{	/* restore formals */	restore(fp->sp);	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();} 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;	d2 = pop();	if (d2.val == 0.0)		execerror("division by zero", (char *)0);	d1 = pop();	/* d1.val %= d2.val; */	d1.val = fmod(d1.val, d2.val);	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();	d1 = pop();	d1.val = Pow(d1.val, d2.val);	push(d1);} voidassign(void){	Datum d1, d2;	d1 = pop();	d2 = pop();	if (d1.sym->type != VAR && d1.sym->type != UNDEF)		execerror("assignment to non-variable",			d1.sym->name);	d1.sym->u.val = d2.val;	d1.sym->type = VAR;

Lines 1–500 of 651.