void statement() { enreg dreg; bool isjumpn; tokattr *pair; level++; trace("statement"); switch(current.token) { case rd: match(rd); genread(true); break; case wr: match(wr); genwrite(true); break; case alu: match(alu); genenc(false); match(assignop); exp(); break; case mar: match(mar); genmar(true); match(assignop); dreg = matchreg(); genbreg(dreg); break; case iconst: case reg: dreg = matchreg(); gencreg(dreg); if (dreg != r_mbr) genenc(true); match(assignop); exp(); break; case IF: match(IF); isjumpn = choice(); gencond(isjumpn ? 1 : 2 ); match(THEN); match(GOTO); pair = match(iconst); genaddr(pair->attr.num); break; case GOTO: match(GOTO); gencond(3); pair = match(iconst); genaddr(pair->attr.num); break; case halt: match(halt); genhalt(); break; default: break; } level--; }
static void genn(Error_printer *err, Frag *frag, Node * n) { switch(n->what) { case nPAREN: { genn(err, frag, n->r); break; } case nQUOTE: { error_2(err, "\"%s\" %d: `used incorrectly", n->loc->name, n->loc->line); break; } case nLABEL: { frag->looplvls->name = strdup(n->s); break; } case nLOCAL: { if (n->r->what == nSEMI && n->r->l->what == nPAREN) { int amnt; mklooplvl(frag, lvlSCOPE, 0, 0); amnt = genll(err, frag, n->r->l->r); push_lst(frag); emitn(frag, amnt); emitc(frag, iLOC); fixlooplvl(frag, amnt + 1); genla(err, frag, n->r->l->r); genn(err, frag, n->r->r); rmlooplvl(frag, lvlSCOPE, 0, 0); } else if (n->r->what == nSEMI && last_is_paren(n->r)) { // Handles with a b [f] Node *r; int amnt; n->r = extract_last_is_paren(n->r, &r); mklooplvl(frag, lvlSCOPE, 0, 0); amnt = genll(err, frag, n->r); push_lst(frag); emitn(frag, amnt); emitc(frag, iLOC); fixlooplvl(frag, amnt + 1); genla(err, frag, n->r); genn(err, frag, r); rmlooplvl(frag, lvlSCOPE, 0, 0); } else { int amnt = genll(err, frag, n->r); /* Create variables */ push_lst(frag); emitn(frag, amnt); emitc(frag, iLOC); fixlooplvl(frag, amnt + 1); genla(err, frag, n->r); /* Initialize them */ } break; } case nFOR: { int top, cont; Node *name; Node *args = extract_loop_name(n->r, &name); if (args->what != nSEMI) { /* One arg */ genn(err, frag, args); /* Initializer */ } else if (args->r->what != nSEMI) { /* Two args */ genn(err, frag, args->l); /* Initializer */ emitc(frag, iBRA); emitn(frag, 0); mklooplvl(frag, lvlLOOP, frag->code-sizeof(int), 0); if (name) frag->looplvls->name = strdup(name->r->s); top = frag->code; cont = frag->code; setlist(frag,genbra(err, frag, args->r, 0), top); /* Test */ rmlooplvl(frag, lvlLOOP, cont, frag->code); } else if (args->r->r->what != nSEMI) { /* Three args */ genn(err, frag, args->l); /* Initializer */ emitc(frag, iBRA); emitn(frag, 0); mklooplvl(frag, lvlLOOP, frag->code-sizeof(int), 0); if (name) frag->looplvls->name = strdup(name->r->s); top = frag->code; genn(err, frag, args->r->r); /* Increment */ cont = frag->code; setlist(frag,genbra(err, frag, args->r->l, 0), top); /* Test */ rmlooplvl(frag, lvlLOOP, cont, frag->code); } else { /* Four args */ genn(err, frag, args->l); /* Initializer */ emitc(frag, iBRA); emitn(frag, 0); mklooplvl(frag, lvlLOOP, frag->code-sizeof(int), 0); if (name) frag->looplvls->name = strdup(name->r->s); top = frag->code; mklooplvl(frag, lvlSCOPE, 0, 0); genn(err, frag, args->r->r->r); /* Body */ rmlooplvl(frag, lvlSCOPE, 0, 0); genn(err, frag, args->r->r->l); /* Increment */ cont = frag->code; setlist(frag,genbra(err, frag, args->r->l, 0), top); /* Test */ rmlooplvl(frag, lvlLOOP, cont, frag->code); } break; } case nFOREACH: case nFORINDEX: { int top, cont; Node *name; Node *args = extract_loop_name(n->r, &name); if (args->what != nSEMI) { /* One arg */ error_2(err,"\"%s\" %d: No args for foreach?", n->loc->name, n->loc->line); } else if (args->r->what != nSEMI) { /* Two args */ error_2(err,"\"%s\" %d: Only two args for foreach?", n->loc->name, n->loc->line); } else { /* Three args */ if (args->l->what != nNAM) { error_2(err, "\"%s\" %d: First arg to foreach must be a variable", n->loc->name, n->loc->line); } mklooplvl(frag, lvlSCOPE, 0, 0); /* Scope for args */ gen(err, frag, args->l); /* Variable (check that it really is at runtime) */ gen(err, frag, args->r->l); /* Array/object */ push_num(frag); emitl(frag, 0); /* Temp vars for iFOREACH */ push_num(frag); emitl(frag, -1); emitc(frag, iBRA); emitn(frag, 0); mklooplvl(frag, lvlLOOP, frag->code-sizeof(int), 0); /* Start loop */ if (name) frag->looplvls->name = strdup(name->r->s); top = frag->code; mklooplvl(frag, lvlSCOPE, 0, 0); /* Scope for body */ genn(err, frag, args->r->r); rmlooplvl(frag, lvlSCOPE, 0, 0); /* Body scope done */ cont = frag->code; if (n->what == nFOREACH) emitc(frag, iFOREACH); else emitc(frag, iFORINDEX); align_frag(frag, sizeof(int)); emitn(frag, top - (frag->code)); rmlooplvl(frag, lvlLOOP, cont, frag->code); /* Complete loop */ emitc(frag, iPOP); emitc(frag, iPOP); emitc(frag, iPOP); emitc(frag, iPOP); fixlooplvl(frag, 4); /* POP temp vars */ rmlooplvl(frag, lvlSCOPE, 0, 0); /* POP args scope */ } break; } case nWHILE: { int top, cont; Node *name; Node *args = extract_loop_name(n->r, &name); if (args->what==nEMPTY) { error_2(err,"\"%s\" %d: No args for while", n->loc->name, n->loc->line); break; } emitc(frag, iBRA); emitn(frag, 0); mklooplvl(frag, lvlLOOP, frag->code-sizeof(int), 0); if (name) frag->looplvls->name = strdup(name->r->s); top = frag->code; mklooplvl(frag, lvlSCOPE, 0, 0); if (args->what==nSEMI) genn(err, frag, args->r); rmlooplvl(frag, lvlSCOPE, 0, 0); cont = frag->code; if (args->what==nSEMI) setlist(frag, genbra(err, frag, args->l, 0), top); else setlist(frag, genbra(err, frag, args, 0), top); rmlooplvl(frag, lvlLOOP, cont, frag->code); break; } case nRETURN: { int z; if (n->r) gen(err, frag, n->r); else push_void(frag); emitc(frag, iSTASH); rmlooplvl(frag, lvlVALUE, 0, 0); poploops(frag, NULL); emitc(frag, iBRA); z = emitn(frag, 0); if (frag->rtn) addlist(frag, frag->rtn, z); else frag->rtn = z; break; } case nLOOP: { int cont; Node *name; Node *args = extract_loop_name(n->r, &name); cont = frag->code; mklooplvl(frag, lvlLOOP, 0, 0); if (name) frag->looplvls->name = strdup(name->r->s); mklooplvl(frag, lvlSCOPE, 0, 0); genn(err, frag, args); rmlooplvl(frag, lvlSCOPE, 0, 0); emitc(frag, iBRA); align_frag(frag, sizeof(int)); emitn(frag, cont - (frag->code)); rmlooplvl(frag, lvlLOOP, cont, frag->code); break; } case nBREAK: { struct looplvl *ll = findlvl(frag, NULL); if (n->r) { // printf("looking... %s %p %p\n",n->r->s,frag,ll); if (n->r->what == nNAM) ll = findlvl(frag, n->r->s); else if (n->r->what != nEMPTY) error_2(err, "\"%s\" %d: Invalid argument to break", n->r->loc->name, n->r->loc->line); } if (ll) { int z; // printf("break %d %d\n", ll->scopelvl, frag->scopelvl); poploops(frag, ll); emitc(frag, iBRA); z = emitn(frag, 0); if (ll->brk) addlist(frag, ll->brk, z); else ll->brk = z; } else error_2(err, "\"%s\" %d: break with no loop", n->loc->name, n->loc->line); break; } case nCONT: { struct looplvl *ll = findlvl(frag, NULL); if (n->r) { if (n->r->what == nNAM) ll = findlvl(frag, n->r->s); else if (n->r->what != nEMPTY) error_2(err, "\"%s\" %d: Invalid argument to continue", n->r->loc->name, n->r->loc->line); } if (ll) { int z; poploops(frag, ll); emitc(frag, iBRA); z = emitn(frag, 0); if (ll->cont) addlist(frag, ll->cont, z); else ll->cont = z; } else error_2(err, "\"%s\" %d: continue with no loop", n->loc->name, n->loc->line); break; } case nUNTIL: { int els = genbra(err, frag, n->r, 1); struct looplvl *ll = findlvl(frag, NULL); if (ll) { int z; // printf("break %d %d\n", ll->scopelvl, frag->scopelvl); poploops(frag, ll); emitc(frag, iBRA); z = emitn(frag, 0); if (ll->brk) addlist(frag, ll->brk, z); else ll->brk = z; } else { error_2(err, "\"%s\" %d: until with no loop", n->loc->name, n->loc->line); } setlist(frag, els, frag->code); break; } case nIF: { gencond(err, frag, n->r, 0); break; } case nELSE: { error_2(err, "\"%s\" %d: else with no if", n->loc->name, n->loc->line); break; } case nSEMI: { if (n->r->what == nELSE) { int done = genelif(err, frag, n->l, 0); if (!done) error_2(err, "\"%s\" %d: else with no if", n->r->loc->name, n->r->loc->line); if (n->r->r->what == nIF) { addlist(frag, done, genbra(err, frag, n->r->r->l, 1)); n = n->r; } mklooplvl(frag, lvlSCOPE, 0, 0); genn(err, frag, n->r->r); rmlooplvl(frag, lvlSCOPE, 0, 0); setlist(frag, done, frag->code); } else { genn(err, frag, n->l); genn(err, frag, n->r); } break; } case nEMPTY: { break; } default: { gen(err, frag, n); emitc(frag, iPOP); rmlooplvl(frag, lvlVALUE, 0, 0); break; } } }
static void gen(Error_printer *err, Frag *frag, Node * n) { switch(n->what) { case nCOMMA: { genn(err, frag, n->l), gen(err, frag, n->r); break; } case nPAREN: { gen(err, frag, n->r); break; } case nLIST: { int amnt = genl(err, frag, n->r); push_lst(frag); emitn(frag, amnt); emitc(frag, iFIX); fixlooplvl(frag, amnt); break; } case nVOID: { push_void(frag); break; } case nTHIS: { push_this(frag); break; } case nNUM: { push_num(frag); emitl(frag, n->n); break; } case nFP: { push_fp(frag); emitd(frag, n->fp); break; } case nSTR: { push_str(frag); emits(frag, n->s, n->n); break; } case nNAM: { push_nam(frag); emitp(frag, n->s); emitc(frag, iGET_ATOM); break; } case nSET: { gen(err, frag, n->r); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); break; } case nIF: { gencond(err, frag, n->r, 1); break; } case nPOST: { gen(err, frag, n->l); gen(err, frag, n->r); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); emitc(frag, iPOP); rmlooplvl(frag, lvlVALUE, 0, 0); break; } case nADDR: { /* Generate a code snippet */ genfunc(err, frag, consempty(n->loc), n->r); break; } case nDEFUN: { if (n->r->what==nSEMI) { if (n->r->l->what==nCALL && n->r->l->l->what==nNAM) { /* fn sq(x) x*x */ genfunc(err, frag, n->r->l->r, n->r->r); push_nam(frag); emitp(frag, n->r->l->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nNAM && n->r->r->what==nSEMI && n->r->r->l->what==nPAREN) { /* fn sq (x) x*x */ genfunc(err, frag, n->r->r->l, n->r->r->r); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nNAM && n->r->r->what==nPAREN) { /* fn sq (x) */ genfunc(err, frag, n->r->r, consempty(n->loc)); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nPAREN) { /* fn (x) x*x */ genfunc(err, frag, n->r->l, n->r->r); } else { error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line); push_void(frag); } } else if(n->r->what==nCALL && n->r->l->what==nNAM) { /* fn sq(x) */ genfunc(err, frag, n->r->r, consempty(n->loc)); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if(n->r->what==nPAREN) { /* fn () */ genfunc(err,frag, n->r, consempty(n->loc)); } else { error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line); push_void(frag); } break; } case nLAMBDA: { genfunc(err, frag, n->r->l, n->r->r); break; } case nSEMI: { if (n->r->what == nELSE) { int done = genelif(err, frag, n->l, 1); if (!done) error_2(err, "\"%s\" %d: else w/o if error", n->r->loc->name, n->r->loc->line); if (n->r->r->what == nIF) { addlist(frag, done, genbra(err, frag, n->r->r->l, 1)); n = n->r; } mklooplvl(frag, lvlSCOPE, 0, 0); gen(err, frag, n->r->r); rmlooplvl(frag, lvlSCOPE, 0, 0); setlist(frag, done, frag->code); } else { genn(err, frag, n->l); gen(err, frag, n->r); } break; } case nEQ: case nNE: case nGT: case nLT: case nGE: case nLE: case nLAND: case nLOR: case nNOT: { int b = genbra(err, frag, n, 1); int link; push_num(frag); emitl(frag, 1); emitc(frag, iBRA); link=emitn(frag, 0); setlist(frag, b, frag->code); push_num(frag); emitl(frag, 0); *(int *)(frag->begcode+link)=frag->code-link; break; } case nCALL: { // int nargs = genl(err, frag, n->r); /* By value */ int nargs = gencl(err, frag, n->r); /* Functionalize */ push_lst(frag); emitn(frag, nargs); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iCALL); fixlooplvl(frag, nargs + 1); break; } case nCALL1: { /* Ends up being the same as above */ // if (n->r->what != nNAM) // error_2(err, "\"%s\" %d: Invalid member name", n->r->loc->name, n->r->loc->line); if (n->r->what == nNAM) { /* Turn it into a string .x -> ."x" */ n->r->what = nSTR; } int nargs = gencl(err, frag, n->r); // push_str(frag); // emits(frag, n->r->s, n->r->n); push_lst(frag); emitn(frag, nargs); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iCALL); fixlooplvl(frag, nargs + 1); break; } case nCOM: case nNEG: case nSHL: case nSHR: case nMUL: case nDIV: case nMOD: case nAND: case nADD: case nSUB: case nOR: case nXOR: case nAT: { if (n->l) gen(err, frag, n->l); if (n->r) gen(err, frag, n->r); emitc(frag, what_tab[n->what].i); if (n->r && n->l) rmlooplvl(frag, lvlVALUE, 0, 0); break; } default: { genn(err, frag, n); push_void(frag); } } }