/* StoreCode - store the function or method under construction */ void StoreCode(ParseContext *c) { int codeSize; /* check for unterminated blocks */ switch (CurrentBlockType(c)) { case BLOCK_IF: case BLOCK_ELSE: ParseError(c, "expecting END IF"); case BLOCK_FOR: ParseError(c, "expecting NEXT"); case BLOCK_DO: ParseError(c, "expecting LOOP"); case BLOCK_NONE: break; } /* fixup the RESERVE instruction at the start of the code */ if (c->codeType != CODE_TYPE_MAIN) { c->codeBuf[1] = c->localOffset; putcbyte(c, OP_RETURN); } /* make sure all referenced labels were defined */ CheckLabels(c); /* place string literals defined in this function */ PlaceStrings(c); /* determine the code size */ codeSize = (int)(c->cptr - c->codeBuf); #if 0 VM_printf("%s:\n", c->codeName); DecodeFunction((uint8_t *)c->image, (c->image->objectDataSize + GetObjSizeInWords(sizeof(VectorObjectHdr))) * sizeof(VMVALUE), c->codeBuf, codeSize); DumpSymbols(&c->arguments, "arguments"); DumpSymbols(&c->locals, "locals"); VM_printf("\n"); #endif /* store the vector object */ StoreBVectorData(c, c->code, PROTO_CODE, c->codeBuf, codeSize); /* empty the local heap */ c->nextLocal = c->sys->freeTop; InitSymbolTable(&c->arguments); InitSymbolTable(&c->locals); c->labels = NULL; /* reset to compile the next code */ c->codeType = CODE_TYPE_MAIN; c->cptr = c->codeBuf; }
/* ParseLoop - parse the 'LOOP' statement */ static void ParseLoop(ParseContext *c) { int inst; switch (CurrentBlockType(c)) { case BLOCK_DO: inst = putcbyte(c, OP_BR); putcword(c, c->bptr->u.DoBlock.nxt - inst - 1 - sizeof(VMUVALUE)); fixupbranch(c, c->bptr->u.DoBlock.end, codeaddr(c)); PopBlock(c); break; default: ParseError(c, "LOOP without a matching DO"); break; } FRequire(c, T_EOL); }
/* ParseElse - parse the 'ELSE' statement */ static void ParseElse(ParseContext *c) { int end; switch (CurrentBlockType(c)) { case BLOCK_IF: putcbyte(c, OP_BR); end = putcword(c, c->bptr->u.IfBlock.end); fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c)); c->bptr->type = BLOCK_ELSE; c->bptr->u.ElseBlock.end = end; break; default: ParseError(c, "ELSE without a matching IF"); break; } FRequire(c, T_EOL); }
/* ParseEndIf - parse the 'END IF' statement */ static void ParseEndIf(ParseContext *c) { switch (CurrentBlockType(c)) { case BLOCK_IF: fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c)); fixupbranch(c, c->bptr->u.IfBlock.end, codeaddr(c)); PopBlock(c); break; case BLOCK_ELSE: fixupbranch(c, c->bptr->u.ElseBlock.end, codeaddr(c)); PopBlock(c); break; default: ParseError(c, "END IF without a matching IF/ELSE IF/ELSE"); break; } FRequire(c, T_EOL); }
/* ParseElseIf - parse the 'ELSE IF' statement */ static void ParseElseIf(ParseContext *c) { switch (CurrentBlockType(c)) { case BLOCK_IF: putcbyte(c, OP_BR); c->bptr->u.IfBlock.end = putcword(c, c->bptr->u.IfBlock.end); fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c)); c->bptr->u.IfBlock.nxt = 0; ParseRValue(c); FRequire(c, T_THEN); putcbyte(c, OP_BRF); c->bptr->u.IfBlock.nxt = putcword(c, 0); FRequire(c, T_EOL); break; default: ParseError(c, "ELSE IF without a matching IF"); break; } }
/* ParseNext - parse the 'NEXT' statement */ static void ParseNext(ParseContext *c) { ParseTreeNode *var; int inst; switch (CurrentBlockType(c)) { case BLOCK_FOR: FRequire(c, T_IDENTIFIER); var = GetSymbolRef(c, c->token); /* BUG: check to make sure it matches the symbol used in the FOR */ inst = putcbyte(c, OP_BR); putcword(c, c->bptr->u.ForBlock.nxt - inst - 1 - sizeof(VMUVALUE)); fixupbranch(c, c->bptr->u.ForBlock.end, codeaddr(c)); PopBlock(c); break; default: ParseError(c, "NEXT without a matching FOR"); break; } FRequire(c, T_EOL); }
/* StoreCode - store the function or method under construction */ VMVALUE StoreCode(ParseContext *c) { size_t codeSize; VMVALUE code; uint8_t *p; /* check for unterminated blocks */ switch (CurrentBlockType(c)) { case BLOCK_IF: case BLOCK_ELSE: ParseError(c, "expecting END IF"); case BLOCK_FOR: ParseError(c, "expecting NEXT"); case BLOCK_DO: ParseError(c, "expecting LOOP"); case BLOCK_NONE: break; } /* fixup the RESERVE instruction at the start of the code */ if (c->codeType != CODE_TYPE_MAIN) { c->codeBuf[1] = 2 + c->localOffset; putcbyte(c, OP_RETURN); } /* make sure all referenced labels were defined */ CheckLabels(c); /* allocate code space */ codeSize = (int)(c->codeFree - c->codeBuf); p = (uint8_t *)ImageTextAlloc(c, codeSize); memcpy(p, c->codeBuf, codeSize); /* get the address of the compiled code */ code = (VMVALUE)(p - (uint8_t *)c->image); #ifdef COMPILER_DEBUG { VM_printf("%s:\n", c->codeSymbol ? c->codeSymbol->name : "<main>"); DecodeFunction((uint8_t *)c->image, (uint8_t *)c->image + code, codeSize); DumpSymbols(&c->arguments, "arguments"); DumpSymbols(&c->locals, "locals"); VM_printf("\n"); } #endif /* prepare the buffer for the next function */ c->codeFree = c->codeBuf; /* empty the local heap */ c->localFree = c->heapBase; InitSymbolTable(&c->arguments); InitSymbolTable(&c->locals); c->labels = NULL; /* reset to compile the next code */ c->codeType = CODE_TYPE_MAIN; /* return the code vector */ return code; }