/* Compile - compile a program */ ImageHdr *Compile(ParseContext *c) { System *sys = c->sys; ImageHdr *image = c->image; size_t maxHeapUsed = c->maxHeapUsed; VMVALUE *variables; VMUVALUE totalSize; Symbol *sym; /* setup an error target */ if (setjmp(c->errorTarget) != 0) return NULL; /* initialize the scratch buffer */ BufRewind(); /* allocate space for the object table */ image->objectCount = 0; image->objectDataSize = 0; /* use the rest of the free space for the compiler heap */ c->nextGlobal = sys->freeNext; c->nextLocal = sys->freeTop; c->heapSize = sys->freeTop - sys->freeNext; c->maxHeapUsed = 0; /* initialize the global variable count */ image->variableCount = 0; /* initialize block nesting table */ c->btop = (Block *)((char *)c->blockBuf + sizeof(c->blockBuf)); c->bptr = c->blockBuf - 1; /* initialize the code staging buffer */ c->ctop = c->codeBuf + sizeof(c->codeBuf); c->cptr = c->codeBuf; /* initialize the string and label tables */ c->strings = NULL; c->labels = NULL; /* start in the main code */ c->codeType = CODE_TYPE_MAIN; /* initialize the global symbol table */ InitSymbolTable(&c->globals); /* add the intrinsic functions */ AddIntrinsic(c, "ABS", FN_ABS); AddIntrinsic(c, "RND", FN_RND); AddIntrinsic(c, "printStr", FN_printStr); AddIntrinsic(c, "printInt", FN_printInt); AddIntrinsic(c, "printTab", FN_printTab); AddIntrinsic(c, "printNL", FN_printNL); AddIntrinsic(c, "printFlush", FN_printFlush); #ifdef PROPELLER AddIntrinsic(c, "IN", FN_IN); AddIntrinsic(c, "OUT", FN_OUT); AddIntrinsic(c, "HIGH", FN_HIGH); AddIntrinsic(c, "LOW", FN_LOW); AddIntrinsic(c, "TOGGLE", FN_TOGGLE); AddIntrinsic(c, "DIR", FN_DIR); AddIntrinsic(c, "GETDIR", FN_GETDIR); AddIntrinsic(c, "CNT", FN_CNT); AddIntrinsic(c, "PAUSE", FN_PAUSE); AddIntrinsic(c, "PULSEIN", FN_PULSEIN); AddIntrinsic(c, "PULSEOUT", FN_PULSEOUT); #endif /* initialize scanner */ c->inComment = VMFALSE; /* get the next line */ while (GetLine(c)) { Token tkn; if ((tkn = GetToken(c)) != T_EOL) ParseStatement(c, tkn); } /* end the main code with a halt */ putcbyte(c, OP_HALT); /* write the main code */ StartCode(c, "main", CODE_TYPE_MAIN); image->mainCode = c->code; StoreCode(c); /* allocate the global variable table */ if (!(variables = (VMVALUE *)AllocateFreeSpace(sys, image->variableCount * sizeof(VMVALUE)))) ParseError(c, "insufficient space for variable table"); /* store the initial values of the global variables */ for (sym = c->globals.head; sym != NULL; sym = sym->next) { if (!(sym->value & INTRINSIC_FLAG)) variables[sym->value] = sym->initialValue; } /* write out the variable and object tables */ if (!BufWriteWords(variables, image->variableCount) || !BufWriteWords(image->objects, image->objectCount)) ParseError(c, "insufficient scratch space"); /* free up the space the compiler was consuming */ sys->freeNext = c->freeMark; /* allocate space for the object data and variables */ totalSize = (image->objectDataSize + image->variableCount + image->objectCount) * sizeof(VMVALUE); if (!(image->objectData = (VMVALUE *)AllocateFreeSpace(sys, totalSize))) ParseError(c, "insufficient space for objects and variables"); image->variables = image->objectData + image->objectDataSize; image->objects = image->variables + image->variableCount; /* read the object data and variables from the scratch buffer */ BufRewind(); if (!BufReadWords(image->objectData, totalSize)) ParseError(c, "error reading objects and variables"); { int objectTableSize = image->objectCount * sizeof(VMVALUE); int objectDataSize = image->objectDataSize * sizeof(VMVALUE); int dataSize = objectTableSize + objectDataSize + image->variableCount * sizeof(VMVALUE); #if 0 DumpSymbols(&c->globals, "symbols"); #endif VM_printf("H:%d", maxHeapUsed); VM_printf(" O:%d", image->objectCount); VM_printf(" D:%d", objectDataSize); VM_printf(" V:%d", image->variableCount); VM_printf(" T:%d\n", dataSize); } /* return the image */ return image; }
/* ParseEndDef - parse the 'END DEF' statement */ static void ParseEndDef(ParseContext *c) { if (c->codeType != CODE_TYPE_FUNCTION) ParseError(c, "not in a function definition"); StoreCode(c); }
/* Compile - compile a program */ int Compile(ParseContext *c, uint8_t *imageSpace, size_t imageSize, size_t textMax, size_t dataMax) { ImageHdr *image = (ImageHdr *)imageSpace; VMUVALUE textSize; /* setup an error target */ if (setjmp(c->errorTarget) != 0) return -1; /* initialize the image */ if (imageSize < sizeof(ImageHdr) + textMax + dataMax) return -1; memset(image, 0, sizeof(ImageHdr)); c->image = image; /* empty the heap */ c->localFree = c->heapBase; c->globalFree = c->heapTop; /* initialize the image */ c->textBase = c->textFree = imageSpace + sizeof(ImageHdr); c->textTop = c->textBase + textMax; c->dataBase = c->dataFree = c->textBase + textMax; c->dataTop = c->dataBase + dataMax; /* initialize the code buffer */ c->codeFree = c->codeBuf; c->codeTop = c->codeBuf + sizeof(c->codeBuf); /* initialize block nesting table */ c->btop = (Block *)((char *)c->blockBuf + sizeof(c->blockBuf)); c->bptr = c->blockBuf - 1; /* initialize the global symbol table and string table */ InitSymbolTable(&c->globals); /* enter the built-in functions */ EnterBuiltInFunction(c, "delayMs", bi_delayms, sizeof(bi_delayms)); EnterBuiltInFunction(c, "updateLeds", bi_updateleds, sizeof(bi_updateleds)); /* enter the built-in variables */ /* typedef struct { int32_t triggerTop; int32_t triggerBottom; int32_t numLeds; int32_t led[RGB_SIZE]; int32_t patternnum; } VM_variables; */ EnterBuiltInVariable(c, "triggerTop", sizeof(VMVALUE)); EnterBuiltInVariable(c, "triggerBottom", sizeof(VMVALUE)); EnterBuiltInVariable(c, "numLeds", sizeof(VMVALUE)); EnterBuiltInVariable(c, "led", sizeof(VMVALUE) * RGB_SIZE); EnterBuiltInVariable(c, "patternNum", sizeof(VMVALUE)); /* initialize the string table */ c->strings = NULL; /* initialize the label table */ c->labels = NULL; /* start in the main code */ c->codeType = CODE_TYPE_MAIN; /* initialize scanner */ c->inComment = VMFALSE; c->lineNumber = 0; /* compile each line */ while (GetLine(c)) { int tkn; if ((tkn = GetToken(c)) != T_EOL) ParseStatement(c, tkn); } /* end the main code with a halt */ putcbyte(c, OP_HALT); /* write the main code */ StartCode(c, CODE_TYPE_MAIN); image->entry = StoreCode(c); /* determine the text size */ textSize = c->textFree - c->textBase; /* fill in the image header */ image->dataOffset = sizeof(ImageHdr) + textSize; image->dataSize = c->dataFree - c->dataBase; image->imageSize = image->dataOffset + image->dataSize; /* make the data contiguous with the code */ memcpy(&imageSpace[image->dataOffset], c->dataBase, image->dataSize); #ifdef COMPILER_DEBUG VM_printf("entry "); PrintValue(image->entry); VM_printf("\n"); VM_printf("imageSize "); PrintValue(image->imageSize); VM_printf("\n"); VM_printf("textSize "); PrintValue(textSize); VM_printf("\n"); VM_printf("dataOffset "); PrintValue(image->dataOffset); VM_printf("\n"); VM_printf("dataSize "); PrintValue(image->dataSize); VM_printf("\n"); DumpSymbols(&c->globals, "symbols"); #endif /* return successfully */ return 0; }