/* ParseFor - parse the 'FOR' statement */ static void ParseFor(ParseContext *c) { ParseTreeNode *var, *step; int test, body, inst; Token tkn; PVAL pv; PushBlock(c); c->bptr->type = BLOCK_FOR; /* get the control variable */ FRequire(c, T_IDENTIFIER); var = GetSymbolRef(c, c->token); code_lvalue(c, var, &pv); FRequire(c, '='); /* parse the starting value expression */ ParseRValue(c); /* parse the TO expression and generate the loop termination test */ test = codeaddr(c); (*pv.fcn)(c, PV_STORE, &pv); (*pv.fcn)(c, PV_LOAD, &pv); FRequire(c, T_TO); ParseRValue(c); putcbyte(c, OP_LE); putcbyte(c, OP_BRT); body = putcword(c, 0); /* branch to the end if the termination test fails */ putcbyte(c, OP_BR); c->bptr->u.ForBlock.end = putcword(c, 0); /* update the for variable after an iteration of the loop */ c->bptr->u.ForBlock.nxt = codeaddr(c); (*pv.fcn)(c, PV_LOAD, &pv); /* get the STEP expression */ if ((tkn = GetToken(c)) == T_STEP) { step = ParseExpr(c); code_rvalue(c, step); tkn = GetToken(c); } /* no step so default to one */ else { putcbyte(c, OP_LIT); putcword(c, 1); } /* generate the increment code */ putcbyte(c, OP_ADD); inst = putcbyte(c, OP_BR); putcword(c, test - inst - 1 - sizeof(VMUVALUE)); /* branch to the loop body */ fixupbranch(c, body, codeaddr(c)); Require(c, tkn, T_EOL); }
/* ParseImpliedLetOrFunctionCall - parse an implied let statement or a function call */ static void ParseImpliedLetOrFunctionCall(ParseContext *c) { ParseTreeNode *expr; Token tkn; PVAL pv; expr = ParsePrimary(c); switch (tkn = GetToken(c)) { case '=': code_lvalue(c, expr, &pv); ParseRValue(c); (*pv.fcn)(c, PV_STORE, &pv); break; default: SaveToken(c, tkn); code_rvalue(c, expr); putcbyte(c, OP_DROP); break; } FRequire(c, T_EOL); }
/* CallHandler - compile a call to a runtime print function */ static void CallHandler(ParseContext *c, char *name, ParseTreeNode *expr) { Symbol *sym; /* find the built-in function */ if (!(sym = FindSymbol(&c->globals, name))) ParseError(c, "undefined print function: %s", name); /* compile the function symbol reference */ putcbyte(c, OP_LIT); putcword(c, sym->value); /* compile the argument */ if (expr) code_rvalue(c, expr); /* call the function */ putcbyte(c, OP_CALL); putcbyte(c, (expr ? 1 : 0)); putcbyte(c, OP_DROP); }
/* ParseRValue - parse and generate code for an r-value */ void ParseRValue(ParseContext *c) { ParseTreeNode *expr; expr = ParseExpr(c); code_rvalue(c, expr); }