From 481d17f040738303290b6d9d71f87e8783714c32 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 31 Jan 2025 13:51:53 +1100 Subject: [PATCH] Tests are passing, added preserveScope to VM API --- repl/main.c | 8 +- source/toy_module.c | 2 +- source/toy_module_bundle.c | 4 +- source/toy_module_bundle.h | 2 +- source/toy_vm.c | 22 +- source/toy_vm.h | 4 +- tests/cases/test_bytecode.c | 198 ---------------- .../{test_routine.c => test_module_builder.c} | 186 +++++++-------- tests/cases/test_module_bundle.c | 127 +++++++++++ tests/cases/test_vm.c | 213 ++++++++++-------- 10 files changed, 360 insertions(+), 406 deletions(-) delete mode 100644 tests/cases/test_bytecode.c rename tests/cases/{test_routine.c => test_module_builder.c} (87%) create mode 100644 tests/cases/test_module_bundle.c diff --git a/repl/main.c b/repl/main.c index 581c8b9..98ba962 100644 --- a/repl/main.c +++ b/repl/main.c @@ -298,6 +298,8 @@ int repl(const char* filepath) { printf("%s> ", prompt); //shows the terminal prompt and begin + unsigned int runCount = 0; //used for initial preserveScope + //read from the terminal while(fgets(inputBuffer, INPUT_BUFFER_SIZE, stdin)) { //work around fgets() adding a newline @@ -332,13 +334,13 @@ int repl(const char* filepath) { void* buffer = Toy_compileModuleBuilder(ast); Toy_Module module = Toy_parseModule(buffer); - Toy_bindVM(&vm, &module); + Toy_bindVM(&vm, &module, runCount++ > 0); //run Toy_runVM(&vm); //free the memory, and leave the VM ready for the next loop - Toy_resetVM(&vm); + Toy_resetVM(&vm, true); free(buffer); printf("%s> ", prompt); //shows the terminal prompt @@ -488,7 +490,7 @@ int main(int argc, const char* argv[]) { Toy_initVM(&vm); Toy_Module module = Toy_parseModule(buffer); - Toy_bindVM(&vm, &module); + Toy_bindVM(&vm, &module, false); Toy_runVM(&vm); diff --git a/source/toy_module.c b/source/toy_module.c index 781d0cb..950d147 100644 --- a/source/toy_module.c +++ b/source/toy_module.c @@ -20,7 +20,7 @@ Toy_Module Toy_parseModule(unsigned char* ptr) { //header readUnsignedInt(&ptr); - // module.codeCount = readUnsignedInt(&ptr); NOTE: note used + module.jumpsCount = readUnsignedInt(&ptr); module.paramCount = readUnsignedInt(&ptr); module.dataCount = readUnsignedInt(&ptr); diff --git a/source/toy_module_bundle.c b/source/toy_module_bundle.c index 525f4a4..58ed043 100644 --- a/source/toy_module_bundle.c +++ b/source/toy_module_bundle.c @@ -10,10 +10,10 @@ //utils static void expand(Toy_ModuleBundle* bundle, unsigned int amount) { if (bundle->count + amount > bundle->capacity) { - bundle->capacity = 0; + bundle->capacity = 8; //DON'T bitshift zero while (bundle->count + amount > bundle->capacity) { //expand as much as needed - bundle->capacity >>= 2; + bundle->capacity <<= 2; } bundle->ptr = realloc(bundle->ptr, bundle->capacity); diff --git a/source/toy_module_bundle.h b/source/toy_module_bundle.h index e1b713f..c00d209 100644 --- a/source/toy_module_bundle.h +++ b/source/toy_module_bundle.h @@ -12,7 +12,7 @@ typedef struct Toy_ModuleBundle { //create a bundle TOY_API void Toy_initModuleBundle(Toy_ModuleBundle* bundle); -TOY_API void Toy_appendModuleBundle(Toy_ModuleBundle* bundle, Toy_Ast* ast); +TOY_API void Toy_appendModuleBundle(Toy_ModuleBundle* bundle, Toy_Ast* ast); //TODO: raw bytes TOY_API void Toy_freeModuleBundle(Toy_ModuleBundle* bundle); //load module bundle with external data (makes an internal copy) diff --git a/source/toy_vm.c b/source/toy_vm.c index 8218d63..3825bc7 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -939,7 +939,7 @@ static void process(Toy_VM* vm) { } //exposed functions -void Toy_resetVM(Toy_VM* vm) { +void Toy_resetVM(Toy_VM* vm, bool preserveScope) { vm->code = NULL; vm->jumpsCount = 0; @@ -957,7 +957,11 @@ void Toy_resetVM(Toy_VM* vm) { Toy_resetStack(&vm->stack); - //NOTE: scope and buckets are not altered during resets + if (preserveScope == false) { + vm->scope = Toy_popScope(vm->scope); + } + + //NOTE: buckets are not altered during resets } void Toy_initVM(Toy_VM* vm) { @@ -967,7 +971,7 @@ void Toy_initVM(Toy_VM* vm) { vm->stringBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); vm->scopeBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - Toy_resetVM(vm); + Toy_resetVM(vm, true); } void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent) { @@ -979,10 +983,10 @@ void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent) { //TODO: parent bucket pointers are updated after function calls - Toy_resetVM(vm); + Toy_resetVM(vm, true); } -void Toy_bindVM(Toy_VM* vm, Toy_Module* module) { +void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope) { vm->code = module->code; vm->jumpsCount = module->jumpsCount; @@ -996,7 +1000,9 @@ void Toy_bindVM(Toy_VM* vm, Toy_Module* module) { vm->dataAddr = module->dataAddr; vm->subsAddr = module->subsAddr; - vm->scope = Toy_pushScope(&vm->scopeBucket, module->scopePtr); //new scope for the upcoming run + if (preserveScope == false) { + vm->scope = Toy_pushScope(&vm->scopeBucket, module->scopePtr); + } } void Toy_runVM(Toy_VM* vm) { @@ -1017,9 +1023,7 @@ void Toy_runVM(Toy_VM* vm) { } void Toy_freeVM(Toy_VM* vm) { - Toy_resetVM(vm); - - Toy_popScope(vm->scope); + Toy_resetVM(vm, false); //clear the persistent memory Toy_freeStack(vm->stack); diff --git a/source/toy_vm.h b/source/toy_vm.h index e40e20b..c2418a3 100644 --- a/source/toy_vm.h +++ b/source/toy_vm.h @@ -42,12 +42,12 @@ typedef struct Toy_VM { Toy_Bucket* scopeBucket; //stores the scope instances TODO: is this separation needed? } Toy_VM; -TOY_API void Toy_resetVM(Toy_VM* vm); //persists memory +TOY_API void Toy_resetVM(Toy_VM* vm, bool preserveScope); TOY_API void Toy_initVM(Toy_VM* vm); //creates memory TOY_API void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent); //inherits memory -TOY_API void Toy_bindVM(Toy_VM* vm, Toy_Module* module); +TOY_API void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope); TOY_API void Toy_runVM(Toy_VM* vm); TOY_API void Toy_freeVM(Toy_VM* vm); diff --git a/tests/cases/test_bytecode.c b/tests/cases/test_bytecode.c deleted file mode 100644 index 155e075..0000000 --- a/tests/cases/test_bytecode.c +++ /dev/null @@ -1,198 +0,0 @@ -#include "toy_bytecode.h" -#include "toy_console_colors.h" - -#include "toy_opcodes.h" -#include "toy_lexer.h" -#include "toy_parser.h" - -#include -#include - -//tests -int test_bytecode_header(Toy_Bucket** bucketHandle) { - //simple test to ensure the header looks right - { - //setup - Toy_Ast* ast = NULL; - Toy_private_emitAstPass(bucketHandle, &ast); - - //run - Toy_Bytecode bc = Toy_compileBytecode(ast); - - //check - if (bc.ptr[0] != TOY_VERSION_MAJOR || - bc.ptr[1] != TOY_VERSION_MINOR || - bc.ptr[2] != TOY_VERSION_PATCH || - strcmp((char*)(bc.ptr + 3), TOY_VERSION_BUILD) != 0) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the bytecode header correctly:\n" TOY_CC_RESET); - fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, (int)(bc.ptr[0]), (int)(bc.ptr[1]), (int)(bc.ptr[2]), (char*)(bc.ptr + 3)); - fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - if (bc.count % 4 != 0) { - fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode size is not a multiple of 4, size is: %d\n" TOY_CC_RESET, (int)bc.count); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - //cleanup - Toy_freeBytecode(bc); - } - - return 0; -} - -int test_bytecode_from_source(Toy_Bucket** bucketHandle) { - { - //setup - const char* source = "(1 + 2) * (3 + 4);"; - Toy_Lexer lexer; - Toy_Parser parser; - - Toy_bindLexer(&lexer, source); - Toy_bindParser(&parser, &lexer); - Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - //run - Toy_Bytecode bc = Toy_compileBytecode(ast); - - //check bytecode alignment - if (bc.count % 4 != 0) { - fprintf(stderr, TOY_CC_ERROR "ERROR: bytecode alignment is not a multiple of 4 (size is %d), source: %s\n" TOY_CC_RESET, (int)bc.count, source); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - //check bytecode header - if (bc.ptr[0] != TOY_VERSION_MAJOR || - bc.ptr[1] != TOY_VERSION_MINOR || - bc.ptr[2] != TOY_VERSION_PATCH || - strcmp((char*)(bc.ptr + 3), TOY_VERSION_BUILD) != 0) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the bytecode header, source: %s\n" TOY_CC_RESET, source); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - //check contents of the routine (this is copy/pasted from test_routine.c, and tweaked with the offset) - int offset = 3 + strlen(TOY_VERSION_BUILD) + 1; - if (offset % 4 != 0) { - offset += 4 - (offset % 4); //ceil - } - - int* ptr = (int*)(bc.ptr + offset); - - if ((ptr++)[0] != 72 || //total size - (ptr++)[0] != 0 || //param count - (ptr++)[0] != 0 || //jump count - (ptr++)[0] != 0 || //data count - (ptr++)[0] != 0) //subs count - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header within bytecode, source: %s\n" TOY_CC_RESET, source); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - //check code - if ( - //left hand side - *((unsigned char*)(offset + bc.ptr + 24)) != TOY_OPCODE_READ || - *((unsigned char*)(offset + bc.ptr + 25)) != TOY_VALUE_INTEGER || - *((unsigned char*)(offset + bc.ptr + 26)) != 0 || - *((unsigned char*)(offset + bc.ptr + 27)) != 0 || - *(int*)(offset + bc.ptr + 28) != 1 || - - *((unsigned char*)(offset + bc.ptr + 32)) != TOY_OPCODE_READ || - *((unsigned char*)(offset + bc.ptr + 33)) != TOY_VALUE_INTEGER || - *((unsigned char*)(offset + bc.ptr + 34)) != 0 || - *((unsigned char*)(offset + bc.ptr + 35)) != 0 || - *(int*)(offset + bc.ptr + 36) != 2 || - - *((unsigned char*)(offset + bc.ptr + 40)) != TOY_OPCODE_ADD || - *((unsigned char*)(offset + bc.ptr + 41)) != TOY_OPCODE_PASS || - *((unsigned char*)(offset + bc.ptr + 42)) != 0 || - *((unsigned char*)(offset + bc.ptr + 43)) != 0 || - - //right hand side - *((unsigned char*)(offset + bc.ptr + 44)) != TOY_OPCODE_READ || - *((unsigned char*)(offset + bc.ptr + 45)) != TOY_VALUE_INTEGER || - *((unsigned char*)(offset + bc.ptr + 46)) != 0 || - *((unsigned char*)(offset + bc.ptr + 47)) != 0 || - *(int*)(offset + bc.ptr + 48) != 3 || - - *((unsigned char*)(offset + bc.ptr + 52)) != TOY_OPCODE_READ || - *((unsigned char*)(offset + bc.ptr + 53)) != TOY_VALUE_INTEGER || - *((unsigned char*)(offset + bc.ptr + 54)) != 0 || - *((unsigned char*)(offset + bc.ptr + 55)) != 0 || - *(int*)(offset + bc.ptr + 56) != 4 || - - *((unsigned char*)(offset + bc.ptr + 60)) != TOY_OPCODE_ADD || - *((unsigned char*)(offset + bc.ptr + 61)) != TOY_OPCODE_PASS || - *((unsigned char*)(offset + bc.ptr + 62)) != 0 || - *((unsigned char*)(offset + bc.ptr + 63)) != 0 || - - //multiply the two values - *((unsigned char*)(offset + bc.ptr + 64)) != TOY_OPCODE_MULTIPLY || - *((unsigned char*)(offset + bc.ptr + 65)) != TOY_OPCODE_PASS || - *((unsigned char*)(offset + bc.ptr + 66)) != 0 || - *((unsigned char*)(offset + bc.ptr + 67)) != 0 || - - *((unsigned char*)(offset + bc.ptr + 68)) != TOY_OPCODE_RETURN || - *((unsigned char*)(offset + bc.ptr + 69)) != 0 || - *((unsigned char*)(offset + bc.ptr + 70)) != 0 || - *((unsigned char*)(offset + bc.ptr + 71)) != 0 - ) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code within bytecode, source: %s\n" TOY_CC_RESET, source); - - //cleanup and return - Toy_freeBytecode(bc); - return -1; - } - - //cleanup - Toy_freeBytecode(bc); - } - - return 0; -} - -int main(void) { - //run each test set, returning the total errors given - int total = 0, res = 0; - - { - Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_bytecode_header(&bucket); - Toy_freeBucket(&bucket); - if (res == 0) { - printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); - } - total += res; - } - - { - Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_bytecode_from_source(&bucket); - Toy_freeBucket(&bucket); - if (res == 0) { - printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); - } - total += res; - } - - return total; -} diff --git a/tests/cases/test_routine.c b/tests/cases/test_module_builder.c similarity index 87% rename from tests/cases/test_routine.c rename to tests/cases/test_module_builder.c index 6479249..4c98f4d 100644 --- a/tests/cases/test_routine.c +++ b/tests/cases/test_module_builder.c @@ -1,4 +1,4 @@ -#include "toy_routine.h" +#include "toy_module_builder.h" #include "toy_console_colors.h" #include "toy_opcodes.h" @@ -9,8 +9,10 @@ #include #include +//NOTE: This set of tests also covers 'Toy_Module' + //tests -int test_routine_expressions(Toy_Bucket** bucketHandle) { +int test_builder_expressions(Toy_Bucket** bucketHandle) { //simple test to ensure the header looks right with an empty ast { //setup @@ -18,18 +20,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_private_emitAstPass(bucketHandle, &ast); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 28 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, ast: PASS\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, ast: PASS\n" TOY_CC_RESET); //cleanup and return free(buffer); @@ -43,7 +45,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 27)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, ast: PASS\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, ast: PASS\n" TOY_CC_RESET); //cleanup and return free(buffer); @@ -66,18 +68,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 28 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -91,7 +93,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 27)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -114,18 +116,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 32 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -143,7 +145,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 31)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -166,18 +168,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 32 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -195,7 +197,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 31)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -218,18 +220,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 36 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -248,7 +250,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 35)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -271,18 +273,18 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 36 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -301,7 +303,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 35)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -324,26 +326,26 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* header = (int*)buffer; if (header[0] != 64 || //total size - header[1] != 0 || //param size - header[2] != 4 || //jumps size + header[1] != 4 || //jump size + header[2] != 0 || //param size header[3] != 16 || //data size header[4] != 0 || //subs size // header[??] != ?? || //params address header[5] != 32 || //code address - header[6] != 44 || //jumps address + header[6] != 44 || //jump address header[7] != 48 || //data address // header[??] != ?? || //subs address false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -367,7 +369,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -383,7 +385,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine jumps, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder jumps, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -399,7 +401,7 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine data, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder data, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -413,11 +415,11 @@ int test_routine_expressions(Toy_Bucket** bucketHandle) { return 0; } -// int test_routine_unary(Toy_Bucket** bucketHandle) { +// int test_builder_unary(Toy_Bucket** bucketHandle) { // //Nothing produces a unary instruction yet // } -int test_routine_binary(Toy_Bucket** bucketHandle) { +int test_builder_binary(Toy_Bucket** bucketHandle) { //produce a simple algorithm { //setup @@ -430,18 +432,18 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 48 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -472,7 +474,7 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 47)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -495,18 +497,18 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 48 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -537,7 +539,7 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 47)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -560,18 +562,18 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 48 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -602,7 +604,7 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 47)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -625,18 +627,18 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 72 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -693,7 +695,7 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 71)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -707,7 +709,7 @@ int test_routine_binary(Toy_Bucket** bucketHandle) { return 0; } -int test_routine_keywords(Toy_Bucket** bucketHandle) { +int test_builder_keywords(Toy_Bucket** bucketHandle) { //assert { //setup @@ -720,18 +722,18 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 36 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -755,7 +757,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 35)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -778,18 +780,18 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 40 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -818,7 +820,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 39)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -841,14 +843,14 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 76 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 4 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 12 || //data count (ptr++)[0] != 0 || //subs count @@ -860,7 +862,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -908,7 +910,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -931,14 +933,14 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 116 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 8 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 28 || //data count (ptr++)[0] != 0 || //subs count @@ -950,7 +952,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1022,7 +1024,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1045,18 +1047,18 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* ptr = (int*)buffer; if ((ptr++)[0] != 40 || //total size - (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //jump count + (ptr++)[0] != 0 || //param count (ptr++)[0] != 0 || //data count (ptr++)[0] != 0) //subs count { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1079,7 +1081,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { *((unsigned char*)(buffer + 39)) != 0 ) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1102,26 +1104,26 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* header = (int*)buffer; if (header[0] != 64 || //total size - header[1] != 0 || //param size - header[2] != 4 || //jumps size + header[1] != 4 || //jump size + header[2] != 0 || //param size header[3] != 8 || //data size header[4] != 0 || //subs size // header[??] != ?? || //params address header[5] != 32 || //code address - header[6] != 52 || //jumps address + header[6] != 52 || //jump address header[7] != 56 || //data address // header[??] != ?? || //subs address false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1154,7 +1156,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1170,7 +1172,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine jumps, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder jumps, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1186,7 +1188,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine data, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder data, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1209,26 +1211,26 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); //run - unsigned char* buffer = Toy_compileRoutine(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); //check header int* header = (int*)buffer; if (header[0] != 64 || //total size - header[1] != 0 || //param size - header[2] != 4 || //jumps size + header[1] != 4 || //jump size + header[2] != 0 || //param size header[3] != 8 || //data size header[4] != 0 || //subs size // header[??] != ?? || //params address header[5] != 32 || //code address - header[6] != 52 || //jumps address + header[6] != 52 || //jump address header[7] != 56 || //data address // header[??] != ?? || //subs address false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder header, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1261,7 +1263,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder code, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1277,7 +1279,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine jumps, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder jumps, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1293,7 +1295,7 @@ int test_routine_keywords(Toy_Bucket** bucketHandle) { false) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine data, source: %s\n" TOY_CC_RESET, source); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected module builder data, source: %s\n" TOY_CC_RESET, source); //cleanup and return free(buffer); @@ -1313,7 +1315,7 @@ int main(void) { { Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_routine_expressions(&bucket); + res = test_builder_expressions(&bucket); Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); @@ -1323,7 +1325,7 @@ int main(void) { { Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_routine_binary(&bucket); + res = test_builder_binary(&bucket); Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); @@ -1333,7 +1335,7 @@ int main(void) { { Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - res = test_routine_keywords(&bucket); + res = test_builder_keywords(&bucket); Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); diff --git a/tests/cases/test_module_bundle.c b/tests/cases/test_module_bundle.c new file mode 100644 index 0000000..fae4a1c --- /dev/null +++ b/tests/cases/test_module_bundle.c @@ -0,0 +1,127 @@ +#include "toy_module_bundle.h" +#include "toy_console_colors.h" + +#include "toy_opcodes.h" +#include "toy_lexer.h" +#include "toy_parser.h" + +#include +#include + +//tests +int test_bundle_header(Toy_Bucket** bucketHandle) { + //simple test to ensure the header looks right + { + //setup + Toy_Ast* ast = NULL; + Toy_private_emitAstPass(bucketHandle, &ast); + + //run + Toy_ModuleBundle bundle; + Toy_initModuleBundle(&bundle); + Toy_appendModuleBundle(&bundle, ast); + + if (bundle.count % 4 != 0) { + fprintf(stderr, TOY_CC_ERROR "ERROR: module bundle size is not a multiple of 4, size is: %d\n" TOY_CC_RESET, (int)bundle.count); + + //cleanup and return + Toy_freeModuleBundle(&bundle); + return -1; + } + + //check + if (bundle.ptr[0] != TOY_VERSION_MAJOR || + bundle.ptr[1] != TOY_VERSION_MINOR || + bundle.ptr[2] != TOY_VERSION_PATCH || + bundle.ptr[3] != 1 || //only one module + strcmp((char*)(bundle.ptr + 4), TOY_VERSION_BUILD) != 0) + { + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the module bundle header correctly:\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s, %d modules found\n" TOY_CC_RESET, (int)(bundle.ptr[0]), (int)(bundle.ptr[1]), (int)(bundle.ptr[2]), (char*)(bundle.ptr + 4), (int)(bundle.ptr[2])); + fprintf(stderr, TOY_CC_ERROR "\t%d.%d.%d.%s, %d modules expected\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD, 1); + + //cleanup and return + Toy_freeModuleBundle(&bundle); + return -1; + } + + //cleanup + Toy_freeModuleBundle(&bundle); + } + + return 0; +} + +int test_bundle_from_source(Toy_Bucket** bucketHandle) { + { + //setup + const char* source = "(1 + 2) * (3 + 4);"; + Toy_Lexer lexer; + Toy_Parser parser; + + Toy_bindLexer(&lexer, source); + Toy_bindParser(&parser, &lexer); + Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); + + //run + Toy_ModuleBundle bundle; + Toy_initModuleBundle(&bundle); + Toy_appendModuleBundle(&bundle, ast); + + //check bytecode alignment + if (bundle.count % 4 != 0) { + fprintf(stderr, TOY_CC_ERROR "ERROR: module bundle size is not a multiple of 4 (size is %d), source: %s\n" TOY_CC_RESET, (int)bundle.count, source); + + //cleanup and return + Toy_freeModuleBundle(&bundle); + return -1; + } + + //check bytecode header + //check + if (bundle.ptr[0] != TOY_VERSION_MAJOR || + bundle.ptr[1] != TOY_VERSION_MINOR || + bundle.ptr[2] != TOY_VERSION_PATCH || + bundle.ptr[3] != 1 || //only one module + strcmp((char*)(bundle.ptr + 4), TOY_VERSION_BUILD) != 0) + { + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to write the module bundle header, source: %s\n" TOY_CC_RESET, source); + + //cleanup and return + Toy_freeModuleBundle(&bundle); + return -1; + } + + //cleanup + Toy_freeModuleBundle(&bundle); + } + + return 0; +} + +int main(void) { + //run each test set, returning the total errors given + int total = 0, res = 0; + + { + Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); + res = test_bundle_header(&bucket); + Toy_freeBucket(&bucket); + if (res == 0) { + printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); + } + total += res; + } + + { + Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); + res = test_bundle_from_source(&bucket); + Toy_freeBucket(&bucket); + if (res == 0) { + printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); + } + total += res; + } + + return total; +} diff --git a/tests/cases/test_vm.c b/tests/cases/test_vm.c index ea5d869..1fb6eee 100644 --- a/tests/cases/test_vm.c +++ b/tests/cases/test_vm.c @@ -3,7 +3,7 @@ #include "toy_lexer.h" #include "toy_parser.h" -#include "toy_bytecode.h" +#include "toy_module_builder.h" #include "toy_print.h" #include @@ -11,7 +11,7 @@ #include //utils -Toy_Bytecode makeBytecodeFromSource(Toy_Bucket** bucketHandle, const char* source) { //did I forget this? +unsigned char* makeCodeFromSource(Toy_Bucket** bucketHandle, const char* source) { Toy_Lexer lexer; Toy_bindLexer(&lexer, source); @@ -19,16 +19,14 @@ Toy_Bytecode makeBytecodeFromSource(Toy_Bucket** bucketHandle, const char* sourc Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); - - return bc; + return Toy_compileModuleBuilder(ast); } //tests int test_setup_and_teardown(Toy_Bucket** bucketHandle) { //basic init & quit { - //generate bytecode for testing + //generate module for testing const char* source = "(1 + 2) * (3 + 4);"; Toy_Lexer lexer; @@ -38,41 +36,34 @@ int test_setup_and_teardown(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); - - //check the header size - int headerSize = 3 + strlen(TOY_VERSION_BUILD) + 1; - if (headerSize % 4 != 0) { - headerSize += 4 - (headerSize % 4); //ceil - } + Toy_bindVM(&vm, &module, false); //check the module was loaded correctly if ( - vm.module - bc.ptr != headerSize || - vm.moduleSize != 72 || - vm.paramSize != 0 || - vm.jumpsSize != 0 || - vm.dataSize != 0 || - vm.subsSize != 0 + vm.codeAddr != 24 || // module header is: total, jumps, prams, data, subs, codeAddr + vm.jumpsCount != 0 || + vm.paramCount != 0 || + vm.dataCount != 0 || + vm.subsCount != 0 ) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to setup and teadown Toy_VM, source: %s\n" TOY_CC_RESET, source); //cleanup and return Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } //don't run it this time, simply teadown Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -91,13 +82,13 @@ int test_simple_execution(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -113,13 +104,13 @@ int test_simple_execution(Toy_Bucket** bucketHandle) { //cleanup and return Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } //teadown Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -138,13 +129,13 @@ int test_opcode_not_equal(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -160,13 +151,13 @@ int test_opcode_not_equal(Toy_Bucket** bucketHandle) { //cleanup and return Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } //teadown Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -195,11 +186,13 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -213,7 +206,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_resetAssertFailureCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -222,7 +215,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test assert false @@ -238,11 +231,13 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -257,7 +252,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_resetAssertFailureCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -266,7 +261,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test assert false with message @@ -282,11 +277,13 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -301,7 +298,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { Toy_resetAssertFailureCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -310,7 +307,7 @@ int test_keyword_assert(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -330,11 +327,13 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -349,7 +348,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -358,7 +357,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test print with a string @@ -374,11 +373,13 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -393,7 +394,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -402,7 +403,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test print with a string concat @@ -418,11 +419,13 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -437,7 +440,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -446,7 +449,7 @@ int test_keyword_print(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -466,11 +469,13 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -485,7 +490,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -494,7 +499,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test if-then (falsy) @@ -510,11 +515,13 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -528,7 +535,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -537,7 +544,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test if-then-else (truthy) @@ -553,11 +560,13 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -572,7 +581,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -581,7 +590,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test if-then-else (falsy) @@ -597,11 +606,13 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); + //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -616,7 +627,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { Toy_resetPrintCallback(); free(callbackUtilReceived); Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } @@ -625,7 +636,7 @@ int test_keyword_ifThenElse(Toy_Bucket** bucketHandle) { free(callbackUtilReceived); callbackUtilReceived = NULL; Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -644,13 +655,13 @@ int test_scope(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -672,13 +683,13 @@ int test_scope(Toy_Bucket** bucketHandle) { //cleanup and return Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } //teadown Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } //test declaration with absent value @@ -693,13 +704,13 @@ int test_scope(Toy_Bucket** bucketHandle) { Toy_bindParser(&parser, &lexer); Toy_Ast* ast = Toy_scanParser(bucketHandle, &parser); - - Toy_Bytecode bc = Toy_compileBytecode(ast); + unsigned char* buffer = Toy_compileModuleBuilder(ast); + Toy_Module module = Toy_parseModule(buffer); //run the setup Toy_VM vm; Toy_initVM(&vm); - Toy_bindVM(&vm, &bc); + Toy_bindVM(&vm, &module, false); //run Toy_runVM(&vm); @@ -719,13 +730,13 @@ int test_scope(Toy_Bucket** bucketHandle) { //cleanup and return Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); return -1; } //teadown Toy_freeVM(&vm); - Toy_freeBytecode(bc); + free(buffer); } return 0; @@ -740,10 +751,12 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) { Toy_initVM(&vm); //run 1 - Toy_Bytecode bc1 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";"); - Toy_bindVM(&vm, &bc1); + unsigned char* buffer1 = makeCodeFromSource(bucketHandle, "print \"Hello world!\";"); + Toy_Module module1 = Toy_parseModule(buffer1); + Toy_bindVM(&vm, &module1, false); + Toy_runVM(&vm); - Toy_resetVM(&vm); + Toy_resetVM(&vm, true); if (callbackUtilReceived == NULL || strcmp(callbackUtilReceived, "Hello world!") != 0) { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' found in VM reuse run 1\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL"); @@ -751,18 +764,20 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) { //cleanup and return free(callbackUtilReceived); callbackUtilReceived = NULL; - Toy_freeBytecode(bc1); + free(buffer1); Toy_freeVM(&vm); Toy_resetPrintCallback(); return -1; } - Toy_freeBytecode(bc1); + free(buffer1); //run 2 - Toy_Bytecode bc2 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";"); - Toy_bindVM(&vm, &bc2); + unsigned char* buffer2 = makeCodeFromSource(bucketHandle, "print \"Hello world!\";"); + Toy_Module module2 = Toy_parseModule(buffer2); + Toy_bindVM(&vm, &module2, true); //preserve during repeated calls + Toy_runVM(&vm); - Toy_resetVM(&vm); + Toy_resetVM(&vm, true); if (callbackUtilReceived == NULL || strcmp(callbackUtilReceived, "Hello world!") != 0) { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' found in VM reuse run 2\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL"); @@ -770,18 +785,20 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) { //cleanup and return free(callbackUtilReceived); callbackUtilReceived = NULL; - Toy_freeBytecode(bc2); + free(buffer2); Toy_freeVM(&vm); Toy_resetPrintCallback(); return -1; } - Toy_freeBytecode(bc2); + free(buffer2); //run 3 - Toy_Bytecode bc3 = makeBytecodeFromSource(bucketHandle, "print \"Hello world!\";"); - Toy_bindVM(&vm, &bc3); + unsigned char* buffer3 = makeCodeFromSource(bucketHandle, "print \"Hello world!\";"); + Toy_Module module3 = Toy_parseModule(buffer3); + Toy_bindVM(&vm, &module3, true); //preserve during repeated calls + Toy_runVM(&vm); - Toy_resetVM(&vm); + Toy_resetVM(&vm, true); if (callbackUtilReceived == NULL || strcmp(callbackUtilReceived, "Hello world!") != 0) { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected value '%s' found in VM reuse run 3\n" TOY_CC_RESET, callbackUtilReceived != NULL ? callbackUtilReceived : "NULL"); @@ -789,12 +806,12 @@ int test_vm_reuse(Toy_Bucket** bucketHandle) { //cleanup and return free(callbackUtilReceived); callbackUtilReceived = NULL; - Toy_freeBytecode(bc3); + free(buffer3); Toy_freeVM(&vm); Toy_resetPrintCallback(); return -1; } - Toy_freeBytecode(bc3); + free(buffer3); //cleanup Toy_freeVM(&vm);