📄 code.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include "hoc.h"#include "y.tab.h"#define NSTACK 256static 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)(uintptr)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; push(d2);}voidaddeq(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); d2.val = d1.sym->u.val += d2.val; d1.sym->type = VAR; push(d2);}voidsubeq(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); d2.val = d1.sym->u.val -= d2.val; d1.sym->type = VAR; push(d2);}voidmuleq(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); d2.val = d1.sym->u.val *= d2.val; d1.sym->type = VAR; push(d2);}voiddiveq(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); d2.val = d1.sym->u.val /= d2.val; d1.sym->type = VAR; push(d2);}voidmodeq(void){ Datum d1, d2; long x; d1 = pop(); d2 = pop(); if (d1.sym->type != VAR && d1.sym->type != UNDEF) execerror("assignment to non-variable", d1.sym->name); /* d2.val = d1.sym->u.val %= d2.val; */ x = d1.sym->u.val; x %= (long) d2.val; d2.val = d1.sym->u.val = x; d1.sym->type = VAR; push(d2);}voidprinttop(void) /* pop top value from stack, print it */{ Datum d; static Symbol *s; /* last value computed */ if (s == 0) s = install("_", VAR, 0.0); d = pop(); print("%.12g\n", d.val); s->u.val = d.val;}voidprexpr(void) /* print numeric value */{ Datum d; d = pop(); print("%.12g ", d.val);}voidprstr(void) /* print string value */ { print("%s", (char *) *pc++);}voidvarread(void) /* read into variable */{ Datum d; extern Biobuf *bin; Symbol *var = (Symbol *) *pc++; int c; Again: do c = Bgetc(bin); while(c==' ' || c=='\t'); if(c == Beof){ Iseof: if(moreinput()) goto Again; d.val = var->u.val = 0.0; goto Return; } if(strchr("+-.0123456789", c) == 0) execerror("non-number read into", var->name); Bungetc(bin); if(Bgetd(bin, &var->u.val) == Beof) goto Iseof; else d.val = 1.0; Return: var->type = VAR; push(d);}Inst*code(Inst f) /* install one instruction or operand */{ Inst *oprogp = progp; if (progp >= &prog[NPROG]) execerror("program too big", (char *)0); *progp++ = f; return oprogp;}voidexecute(Inst* p){ for (pc = p; *pc != STOP && !returning; ) (*((++pc)[-1]))();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -