diff --git a/repl/main.c b/repl/main.c index 13f1f04..dff7bb7 100644 --- a/repl/main.c +++ b/repl/main.c @@ -1,6 +1,7 @@ #include "toy.h" #include +#include #include //utilities @@ -18,7 +19,7 @@ unsigned char* readFile(char* path, int* size) { rewind(file); //make some space - unsigned char* buffer = TOY_ALLOCATE(unsigned char, *size + 1); + unsigned char* buffer = malloc(*size + 1); if (buffer == NULL) { fclose(file); return NULL; @@ -127,14 +128,20 @@ CmdLine parseCmdLine(int argc, const char* argv[]) { } else { if (cmd.infile != NULL) { //don't leak - TOY_FREE_ARRAY(char, cmd.infile, strlen(cmd.infile)); + free(cmd.infile); } i++; //total space to reserve - it's actually longer than needed, due to the exe name being removed cmd.infileLength = strlen(argv[0]) + strlen(argv[i]); - cmd.infile = TOY_ALLOCATE(char, cmd.infileLength); + cmd.infile = malloc(cmd.infileLength); + + if (cmd.infile == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate space while parsing the command line, exiting\n" TOY_CC_RESET); + exit(-1); + } + dir(cmd.infile, argv[0]); APPEND(cmd.infile, argv[i]); FLIPSLASH(cmd.infile); @@ -167,7 +174,8 @@ int main(int argc, const char* argv[]) { int size; unsigned char* source = readFile(cmd.infile, &size); - TOY_FREE_ARRAY(char, cmd.infile, cmd.infileLength); //clean this up, since it's no longer needed + free(cmd.infile); + cmd.infile = NULL; cmd.infileLength = 0; @@ -195,15 +203,13 @@ int main(int argc, const char* argv[]) { Toy_Parser parser; Toy_bindParser(&parser, &lexer); - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); Toy_Ast* ast = Toy_scanParser(&bucket, &parser); Toy_Bytecode bc = Toy_compileBytecode(ast); //run the setup Toy_VM vm; - Toy_initVM(&vm); Toy_bindVM(&vm, bc.ptr, bc.capacity); //run @@ -211,8 +217,8 @@ int main(int argc, const char* argv[]) { //debugging result printf("printing the stack result\n\ntype\tvalue\n"); - for (int i = 0; i < vm.stack.count; i++) { - Toy_Value v = vm.stack.ptr[i]; + for (int i = 0; i < vm.stack->count; i++) { + Toy_Value v = ((Toy_Value*)(vm.stack + 1))[i]; printf(" %d\t ", v.type); @@ -247,8 +253,8 @@ int main(int argc, const char* argv[]) { //cleanup Toy_freeVM(&vm); - TOY_BUCKET_FREE(bucket); - TOY_FREE_ARRAY(unsigned char, source, size); + Toy_freeBucket(&bucket); + free(source); } else { usageCmdLine(argc, argv); diff --git a/source/toy.h b/source/toy.h index 96db27c..86a1de7 100644 --- a/source/toy.h +++ b/source/toy.h @@ -3,17 +3,21 @@ //general utilities #include "toy_common.h" #include "toy_console_colors.h" -#include "toy_memory.h" -//building blocks +//basic structures #include "toy_value.h" +#include "toy_array.h" +#include "toy_stack.h" +#include "toy_bucket.h" +#include "toy_string.h" +//TODO: hashtable + +//IR structures and other components #include "toy_ast.h" #include "toy_routine.h" -#include "toy_stack.h" //pipeline #include "toy_lexer.h" #include "toy_parser.h" #include "toy_bytecode.h" #include "toy_vm.h" - diff --git a/source/toy_array.c b/source/toy_array.c new file mode 100644 index 0000000..4bcaaa0 --- /dev/null +++ b/source/toy_array.c @@ -0,0 +1,25 @@ +#include "toy_array.h" +#include "toy_console_colors.h" + +#include +#include + +Toy_Array* Toy_resizeArray(Toy_Array* paramArray, size_t capacity) { + if (capacity == 0) { + free(paramArray); + return NULL; + } + + Toy_Array* array = realloc(paramArray, capacity + sizeof(Toy_Array)); + + if (array == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Array' of %d capacity\n" TOY_CC_RESET, (int)capacity); + exit(1); + } + + array->capacity = capacity; + array->count = paramArray == NULL ? 0 : + (array->count > capacity ? capacity : array->count); //truncate lost data + + return array; +} diff --git a/source/toy_array.h b/source/toy_array.h new file mode 100644 index 0000000..3e8105f --- /dev/null +++ b/source/toy_array.h @@ -0,0 +1,25 @@ +#pragma once + +#include "toy_common.h" + +//standard generic array +typedef struct Toy_Array { //32 | 64 BITNESS + size_t capacity; //4 | 4 + size_t count; //4 | 4 + char data[]; //- | - +} Toy_Array; //8 | 8 + +TOY_API Toy_Array* Toy_resizeArray(Toy_Array* array, size_t capacity); + +#define TOY_ALLOCATE_ARRAY(type, count) \ + Toy_resizeArray(NULL, sizeof(type)*(count)) + +#define TOY_FREE_ARRAY(type, array) \ + Toy_resizeArray(array, 0) + +#define TOY_ADJUST_ARRAY(type, array, newCapacity) \ + Toy_resizeArray(array, sizeof(type) * newCapacity) + +#define TOY_DOUBLE_ARRAY_CAPACITY(type, array) \ + Toy_resizeArray(array, sizeof(type) * array->capacity < 8 ? sizeof(type) * 8 : sizeof(type) * array->capacity * 2) + diff --git a/source/toy_ast.c b/source/toy_ast.c index 5d4a6de..266cf60 100644 --- a/source/toy_ast.c +++ b/source/toy_ast.c @@ -1,25 +1,25 @@ #include "toy_ast.h" void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle) { - (*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - (*handle)->block.type = TOY_AST_BLOCK; - (*handle)->block.child = NULL; - (*handle)->block.next = NULL; - (*handle)->block.tail = NULL; + tmp->type = TOY_AST_BLOCK; + tmp->block.child = NULL; + tmp->block.next = NULL; + tmp->block.tail = NULL; + + (*handle) = tmp; } -void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast* child) { - //type check - +void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast* block, Toy_Ast* child) { //first, check if we're an empty head - if ((*handle)->block.child == NULL) { - (*handle)->block.child = child; + if (block->block.child == NULL) { + block->block.child = child; return; //NOTE: first call on an empty head skips any memory allocations } //run (or jump) until we hit the current tail - Toy_Ast* iter = (*handle)->block.tail ? (*handle)->block.tail : (*handle); + Toy_Ast* iter = block->block.tail ? block->block.tail : block; while(iter->block.next != NULL) { iter = iter->block.next; @@ -30,21 +30,23 @@ void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast* //store the child in the new link, prep the tail pointer iter->block.next->block.child = child; - (*handle)->block.tail = iter->block.next; + block->block.tail = iter->block.next; } void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value) { - (*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - (*handle)->value.type = TOY_AST_VALUE; - (*handle)->value.value = value; + tmp->type = TOY_AST_VALUE; + tmp->value.value = value; + + (*handle) = tmp; } //TODO: flag range checks void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag) { - Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - tmp->unary.type = TOY_AST_UNARY; + tmp->type = TOY_AST_UNARY; tmp->unary.flag = flag; tmp->unary.child = *handle; @@ -52,9 +54,9 @@ void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag } void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag, Toy_Ast* right) { - Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - tmp->binary.type = TOY_AST_BINARY; + tmp->type = TOY_AST_BINARY; tmp->binary.flag = flag; tmp->binary.left = *handle; //left-recursive tmp->binary.right = right; @@ -63,28 +65,34 @@ void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFla } void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle) { - Toy_Ast* tmp = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - tmp->group.type = TOY_AST_GROUP; + tmp->type = TOY_AST_GROUP; tmp->group.child = (*handle); (*handle) = tmp; } void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle) { - (*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - (*handle)->pass.type = TOY_AST_PASS; + tmp->type = TOY_AST_PASS; + + (*handle) = tmp; } void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle) { - (*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - (*handle)->error.type = TOY_AST_ERROR; + tmp->type = TOY_AST_ERROR; + + (*handle) = tmp; } void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle) { - (*handle) = (Toy_Ast*)Toy_partBucket(bucket, sizeof(Toy_Ast)); + Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucket, sizeof(Toy_Ast)); - (*handle)->error.type = TOY_AST_END; + tmp->type = TOY_AST_END; + + (*handle) = tmp; } diff --git a/source/toy_ast.h b/source/toy_ast.h index e87253f..baad25c 100644 --- a/source/toy_ast.h +++ b/source/toy_ast.h @@ -1,8 +1,8 @@ #pragma once #include "toy_common.h" -#include "toy_memory.h" +#include "toy_bucket.h" #include "toy_value.h" //each major type @@ -55,18 +55,6 @@ typedef enum Toy_AstFlag { //the root AST type typedef union Toy_Ast Toy_Ast; -void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle); -void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Ast* child); - -void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value); -void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag); -void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle,Toy_AstFlag flag, Toy_Ast* right); -void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle); - -void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle); -void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle); -void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle); - typedef struct Toy_AstBlock { Toy_AstType type; Toy_Ast* child; //begin encoding the line @@ -121,3 +109,15 @@ union Toy_Ast { //32 | 64 BITNESS Toy_AstError error; //4 | 4 Toy_AstEnd end; //4 | 4 }; //16 | 32 + +void Toy_private_initAstBlock(Toy_Bucket** bucket, Toy_Ast** handle); +void Toy_private_appendAstBlock(Toy_Bucket** bucket, Toy_Ast* block, Toy_Ast* child); + +void Toy_private_emitAstValue(Toy_Bucket** bucket, Toy_Ast** handle, Toy_Value value); +void Toy_private_emitAstUnary(Toy_Bucket** bucket, Toy_Ast** handle, Toy_AstFlag flag); +void Toy_private_emitAstBinary(Toy_Bucket** bucket, Toy_Ast** handle,Toy_AstFlag flag, Toy_Ast* right); +void Toy_private_emitAstGroup(Toy_Bucket** bucket, Toy_Ast** handle); + +void Toy_private_emitAstPass(Toy_Bucket** bucket, Toy_Ast** handle); +void Toy_private_emitAstError(Toy_Bucket** bucket, Toy_Ast** handle); +void Toy_private_emitAstEnd(Toy_Bucket** bucket, Toy_Ast** handle); \ No newline at end of file diff --git a/source/toy_bucket.c b/source/toy_bucket.c new file mode 100644 index 0000000..7d3ca9e --- /dev/null +++ b/source/toy_bucket.c @@ -0,0 +1,68 @@ +#include "toy_bucket.h" +#include "toy_console_colors.h" + +#include +#include + +//buckets of fun +Toy_Bucket* Toy_allocateBucket(size_t capacity) { + if (capacity == 0) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Cannot allocate a 'Toy_Bucket' with zero capacity\n" TOY_CC_RESET); + exit(1); + } + + Toy_Bucket* bucket = malloc(sizeof(Toy_Bucket) + capacity); + + if (bucket == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Bucket' of %d capacity\n" TOY_CC_RESET, (int)capacity); + exit(1); + } + + //initialize the bucket + bucket->next = NULL; + bucket->capacity = capacity; + bucket->count = 0; + + return bucket; +} + +void* Toy_partitionBucket(Toy_Bucket** bucketHandle, size_t amount) { + if ((*bucketHandle) == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Expected a 'Toy_Bucket', received NULL\n" TOY_CC_RESET); + exit(1); + } + + //if you try to allocate too much space + if ((*bucketHandle)->capacity < amount) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to partition a 'Toy_Bucket': requested %d from a bucket of %d capacity\n" TOY_CC_RESET, (int)amount, (int)((*bucketHandle)->capacity)); + exit(1); + } + + //if you're out of space in this bucket + if ((*bucketHandle)->capacity < (*bucketHandle)->count + amount) { + //move to the next bucket + Toy_Bucket* tmp = Toy_allocateBucket((*bucketHandle)->capacity); + tmp->next = (*bucketHandle); //it's buckets all the way down + (*bucketHandle) = tmp; + } + + //track the new count, and return the specified memory space + (*bucketHandle)->count += amount; + return ((*bucketHandle)->data + (*bucketHandle)->count - amount); +} + +void Toy_freeBucket(Toy_Bucket** bucketHandle) { + Toy_Bucket* iter = (*bucketHandle); + + while (iter != NULL) { + //run down the chain + Toy_Bucket* last = iter; + iter = iter->next; + + //clear the previous bucket from memory + free(last); + } + + //for safety + (*bucketHandle) = NULL; +} diff --git a/source/toy_bucket.h b/source/toy_bucket.h new file mode 100644 index 0000000..30da803 --- /dev/null +++ b/source/toy_bucket.h @@ -0,0 +1,22 @@ +#pragma once + +#include "toy_common.h" + +//NOTE: this structure has restrictions on it's usage: +// - It can only expand until it is freed +// - It cannot be copied around within RAM +// - It cannot allocate more memory than it has capacity +// If each of these rules are followed, the bucket is actually more efficient than any other option + +//a custom allocator +typedef struct Toy_Bucket { //32 | 64 BITNESS + struct Toy_Bucket* next; //4 | 8 + size_t capacity; //4 | 4 + size_t count; //4 | 4 + char data[]; //- | - +} Toy_Bucket; //12 | 16 + +TOY_API Toy_Bucket* Toy_allocateBucket(size_t capacity); +TOY_API void* Toy_partitionBucket(Toy_Bucket** bucketHandle, size_t amount); +TOY_API void Toy_freeBucket(Toy_Bucket** bucketHandle); + diff --git a/source/toy_bytecode.c b/source/toy_bytecode.c index dcb4d01..580b418 100644 --- a/source/toy_bytecode.c +++ b/source/toy_bytecode.c @@ -1,21 +1,26 @@ #include "toy_bytecode.h" #include "toy_console_colors.h" -#include "toy_memory.h" #include "toy_routine.h" #include +#include #include //utils -static void expand(Toy_Bytecode* bc, int amount) { +static void expand(Toy_Bytecode* bc, size_t amount) { if (bc->count + amount > bc->capacity) { - int oldCapacity = bc->capacity; - while (bc->count + amount > bc->capacity) { - bc->capacity = TOY_GROW_CAPACITY(bc->capacity); + while (bc->count + amount > bc->capacity) { //expand as much as needed + bc->capacity = bc->capacity < 8 ? 8 : bc->capacity * 2; + } + + bc->ptr = realloc(bc->ptr, bc->capacity); + + if (bc->ptr == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Bytecode' of %d capacity\n" TOY_CC_RESET, (int)(bc->capacity)); + exit(1); } - bc->ptr = TOY_GROW_ARRAY(unsigned char, bc->ptr, oldCapacity, bc->capacity); } } @@ -32,7 +37,7 @@ static void writeBytecodeHeader(Toy_Bytecode* bc) { //check strlen for the build string const char* build = Toy_private_version_build(); - int len = (int)strlen(build) + 1; + size_t len = strlen(build) + 1; //BUGFIX: ensure the end of the header has 4-byte alignment if (len % 4 != 1) { //1 to fill the 4th byte above @@ -42,6 +47,8 @@ static void writeBytecodeHeader(Toy_Bytecode* bc) { expand(bc, len); memcpy(bc->ptr + bc->count, build, len); bc->count += len; + + bc->ptr[bc->count] = '\0'; } static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) { @@ -50,7 +57,7 @@ static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) { //eventually, the bytecode may support multiple modules packed into one file void* module = Toy_compileRoutine(ast); - int len = ((int*)module)[0]; + size_t len = (size_t)(((int*)module)[0]); expand(bc, len); memcpy(bc->ptr + bc->count, module, len); @@ -74,5 +81,5 @@ Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast) { } void Toy_freeBytecode(Toy_Bytecode bc) { - TOY_FREE_ARRAY(unsigned char, bc.ptr, bc.capacity); + free(bc.ptr); } diff --git a/source/toy_bytecode.h b/source/toy_bytecode.h index bbfe4e4..038e8ab 100644 --- a/source/toy_bytecode.h +++ b/source/toy_bytecode.h @@ -5,8 +5,8 @@ typedef struct Toy_Bytecode { unsigned char* ptr; - int capacity; - int count; + size_t capacity; + size_t count; } Toy_Bytecode; TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast); diff --git a/source/toy_lexer.c b/source/toy_lexer.c index 309df59..478b852 100644 --- a/source/toy_lexer.c +++ b/source/toy_lexer.c @@ -312,7 +312,7 @@ Toy_Token Toy_private_scanLexer(Toy_Lexer* lexer) { } } -static void trim(char** s, int* l) { //util +static void trim(char** s, size_t* l) { //util while( isspace(( (*((unsigned char**)(s)))[(*l) - 1] )) ) (*l)--; while(**s && isspace( **(unsigned char**)(s)) ) { (*s)++; (*l)--; } } @@ -321,22 +321,22 @@ static void trim(char** s, int* l) { //util void Toy_private_printToken(Toy_Token* token) { //print errors if (token->type == TOY_TOKEN_ERROR) { - printf(TOY_CC_ERROR "ERROR: \t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme); + printf(TOY_CC_ERROR "ERROR: \t%d\t%.*s\n" TOY_CC_RESET, (int)token->line, (int)token->length, token->lexeme); return; } //read pass token, even though it isn't generated if (token->type == TOY_TOKEN_PASS) { - printf(TOY_CC_NOTICE "PASS: \t%d\t%.*s\n" TOY_CC_RESET, token->line, token->length, token->lexeme); + printf(TOY_CC_NOTICE "PASS: \t%d\t%.*s\n" TOY_CC_RESET, (int)token->line, (int)token->length, token->lexeme); return; } //print the line number - printf("\t%d\t%d\t", token->type, token->line); + printf("\t%d\t%d\t", token->type, (int)token->line); //print based on type if (token->type == TOY_TOKEN_IDENTIFIER || token->type == TOY_TOKEN_LITERAL_INTEGER || token->type == TOY_TOKEN_LITERAL_FLOAT || token->type == TOY_TOKEN_LITERAL_STRING) { - printf("%.*s\t", token->length, token->lexeme); + printf("%.*s\t", (int)token->length, token->lexeme); } else { const char* keyword = Toy_private_findKeywordByType(token->type); @@ -344,9 +344,9 @@ void Toy_private_printToken(Toy_Token* token) { printf("%s", keyword); } else { char* str = (char*)token->lexeme; //strip const-ness for trimming - int length = token->length; + size_t length = token->length; trim(&str, &length); - printf("%.*s", length, str); + printf("%.*s", (int)length, str); } } diff --git a/source/toy_lexer.h b/source/toy_lexer.h index 9fe985b..083ba6a 100644 --- a/source/toy_lexer.h +++ b/source/toy_lexer.h @@ -5,17 +5,17 @@ //lexers are bound to a string of code typedef struct { - int start; //start of the current token - int current; //current position of the lexer - int line; //track this for error handling + size_t start; //start of the current token + size_t current; //current position of the lexer + size_t line; //track this for error handling const char* source; } Toy_Lexer; //tokens are intermediaries between lexers and parsers typedef struct { Toy_TokenType type; - int length; - int line; + size_t length; + size_t line; const char* lexeme; } Toy_Token; diff --git a/source/toy_memory.c b/source/toy_memory.c deleted file mode 100644 index 2bcfe5a..0000000 --- a/source/toy_memory.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "toy_memory.h" - -#include "toy_console_colors.h" - -#include -#include - -void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize) { - if (newSize == 0) { - free(pointer); - return NULL; - } - - void* result = realloc(pointer, newSize); - - if (result == NULL) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Memory allocation error (requested %d, replacing %d)\n" TOY_CC_RESET, (int)newSize, (int)oldSize); - exit(1); - } - - return result; -} - -//buckets of fun -void Toy_initBucket(Toy_Bucket** bucketHandle, size_t capacity) { - if (capacity == 0) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Cannot init a bucket with zero capacity\n" TOY_CC_RESET); - exit(1); - } - - (*bucketHandle) = malloc(sizeof(Toy_Bucket)); //TODO: rework the bucket, so there's only one malloc() call instead of two when partitioning - - if ((*bucketHandle) == NULL) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to allocate space for a bucket\n" TOY_CC_RESET); - exit(1); - } - - //initialize the bucket - (*bucketHandle)->next = NULL; - (*bucketHandle)->contents = NULL; //leave until the first partition - (*bucketHandle)->capacity = capacity; - (*bucketHandle)->count = 0; -} - -void* Toy_partBucket(Toy_Bucket** bucketHandle, size_t space) { - if ((*bucketHandle) == NULL) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Expected bucket, received NULL\n" TOY_CC_RESET); - exit(1); - } - - //if you try to allocate too much space - if ((*bucketHandle)->capacity < space) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to partition bucket memory, not enough capacity: needed %d, only %d available\n" TOY_CC_RESET, (int)space, (int)((*bucketHandle)->capacity)); - exit(1); - } - - //if out of space in the current bucket - if ((*bucketHandle)->capacity < (*bucketHandle)->count + space) { - //move to the next bucket - Toy_Bucket* tmp = NULL; - Toy_initBucket(&tmp, (*bucketHandle)->capacity); - tmp->next = (*bucketHandle); - (*bucketHandle) = tmp; - } - - //if no space allocated for the current bucket - if ((*bucketHandle)->contents == NULL) { - //allocate space for the current bucket - (*bucketHandle)->contents = malloc((*bucketHandle)->capacity); - - //double check - if ((*bucketHandle)->contents == NULL) { - fprintf(stderr, TOY_CC_ERROR "[internal] ERROR: Failed to allocate space for bucket contents\n" TOY_CC_RESET); - exit(1); - } - } - - //track the new count, and return the specified memory space - (*bucketHandle)->count += space; - return ((*bucketHandle)->contents + (*bucketHandle)->count - space); -} - -void Toy_freeBucket(Toy_Bucket** bucketHandle) { - while ((*bucketHandle) != NULL) { - //run down the chain - Toy_Bucket* ptr = (*bucketHandle); - (*bucketHandle) = (*bucketHandle)->next; - - //clear the previous bucket from memory - free(ptr->contents); - free(ptr); - } -} diff --git a/source/toy_memory.h b/source/toy_memory.h deleted file mode 100644 index 4ca56c6..0000000 --- a/source/toy_memory.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "toy_common.h" - -//standard movable array for general use -#define TOY_GROW_CAPACITY(capacity) \ - ((capacity) < 8 ? 8 : (capacity) * 2) - -#define TOY_ALLOCATE(type, count) \ - (type*)Toy_reallocate(NULL, 0, sizeof(type)*(count)) - -#define TOY_FREE(type, pointer) \ - (type*)Toy_reallocate(pointer, sizeof(type), 0) - -#define TOY_GROW_ARRAY(type, pointer, oldSize, newSize) \ - (type*)Toy_reallocate(pointer, sizeof(type)*oldSize, sizeof(type)*newSize) - -#define TOY_SHRINK_ARRAY(type, pointer, oldCount, count) \ - (type*)Toy_reallocate((type*)pointer, sizeof(type)*(oldCount), sizeof(type)*(count)) - -#define TOY_FREE_ARRAY(type, pointer, oldSize) \ - (type*)Toy_reallocate(pointer, sizeof(type)*oldSize, 0) - -TOY_API void* Toy_reallocate(void* pointer, size_t oldSize, size_t newSize); - -//immobile "bucket" memory structure for custom allocators -#define TOY_BUCKET_INIT(type, bucket, count) \ - Toy_initBucket(&(bucket), sizeof(type)*(count)) - -#define TOY_BUCKET_PART(type, bucket) \ - (type*)Toy_partBucket(&(bucket), sizeof(type)) - -#define TOY_BUCKET_FREE(bucket) \ - Toy_freeBucket(&(bucket)) - -typedef struct Toy_Bucket { - struct Toy_Bucket* next; - void* contents; - size_t capacity; - size_t count; -} Toy_Bucket; - -TOY_API void Toy_initBucket(Toy_Bucket** bucketHandle, size_t capacity); -TOY_API void* Toy_partBucket(Toy_Bucket** bucketHandle, size_t space); -TOY_API void Toy_freeBucket(Toy_Bucket** bucketHandle); diff --git a/source/toy_parser.c b/source/toy_parser.c index bce779f..50068d8 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -10,14 +10,14 @@ static void printError(Toy_Parser* parser, Toy_Token token, const char* errorMsg return; } - fprintf(stderr, TOY_CC_ERROR "[Line %d] Error ", token.line); + fprintf(stderr, TOY_CC_ERROR "[Line %d] Error ", (int)token.line); //check type if (token.type == TOY_TOKEN_EOF) { fprintf(stderr, "at end"); } else { - fprintf(stderr, "at '%.*s'", token.length, token.lexeme); + fprintf(stderr, "at '%.*s'", (int)token.length, token.lexeme); } //finally @@ -232,7 +232,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo //filter the '_' character char buffer[parser->previous.length]; - int i = 0, o = 0; + size_t i = 0, o = 0; do { buffer[i] = parser->previous.lexeme[o]; if (buffer[i] != '_') i++; @@ -249,7 +249,7 @@ static Toy_AstFlag atomic(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo //filter the '_' character char buffer[parser->previous.length]; - int i = 0, o = 0; + size_t i = 0, o = 0; do { buffer[i] = parser->previous.lexeme[o]; if (buffer[i] != '_') i++; @@ -542,11 +542,11 @@ static void makeBlockStmt(Toy_Bucket** bucket, Toy_Parser* parser, Toy_Ast** roo Toy_Ast* err = NULL; Toy_private_emitAstError(bucket, &err); - Toy_private_appendAstBlock(bucket, root, err); + Toy_private_appendAstBlock(bucket, *root, err); continue; } - Toy_private_appendAstBlock(bucket, root, stmt); + Toy_private_appendAstBlock(bucket, *root, stmt); } } diff --git a/source/toy_parser.h b/source/toy_parser.h index bdcf9b1..55177da 100644 --- a/source/toy_parser.h +++ b/source/toy_parser.h @@ -1,7 +1,7 @@ #pragma once #include "toy_common.h" -#include "toy_memory.h" + #include "toy_lexer.h" #include "toy_ast.h" diff --git a/source/toy_routine.c b/source/toy_routine.c index d9d20cf..a91c490 100644 --- a/source/toy_routine.c +++ b/source/toy_routine.c @@ -1,7 +1,6 @@ #include "toy_routine.h" #include "toy_console_colors.h" -#include "toy_memory.h" #include "toy_opcodes.h" #include "toy_value.h" @@ -10,23 +9,26 @@ #include //utils -static void expand(void** handle, int* capacity, int* count, int amount) { +static void expand(void** handle, size_t* capacity, size_t* count, size_t amount) { if ((*count) + amount > (*capacity)) { - int oldCapacity = (*capacity); - while ((*count) + amount > (*capacity)) { - (*capacity) = TOY_GROW_CAPACITY(*capacity); + (*capacity) = (*capacity) < 8 ? 8 : (*capacity) * 2; + } + (*handle) = realloc((*handle), (*capacity)); + + if ((*handle) == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Routine' of %d capacity\n" TOY_CC_RESET, (int)(*capacity)); + exit(1); } - (*handle) = TOY_GROW_ARRAY(unsigned char, (*handle), oldCapacity, (*capacity)); } } -static void emitByte(void** handle, int* capacity, int* count, unsigned char byte) { +static void emitByte(void** handle, size_t* capacity, size_t* count, unsigned char byte) { expand(handle, capacity, count, 1); ((unsigned char*)(*handle))[(*count)++] = byte; } -static void emitInt(void** handle, int* capacity, int* count, int bytes) { +static void emitInt(void** handle, size_t* capacity, size_t* count, size_t bytes) { char* ptr = (char*)&bytes; emitByte(handle, capacity, count, *(ptr++)); emitByte(handle, capacity, count, *(ptr++)); @@ -34,7 +36,7 @@ static void emitInt(void** handle, int* capacity, int* count, int bytes) { emitByte(handle, capacity, count, *(ptr++)); } -static void emitFloat(void** handle, int* capacity, int* count, float bytes) { +static void emitFloat(void** handle, size_t* capacity, size_t* count, float bytes) { char* ptr = (char*)&bytes; emitByte(handle, capacity, count, *(ptr++)); emitByte(handle, capacity, count, *(ptr++)); @@ -281,8 +283,8 @@ static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) { //TODO: data //write the header and combine the parts - void* buffer = TOY_ALLOCATE(unsigned char, 16); - int capacity = 0, count = 0; + void* buffer = NULL; + size_t capacity = 0, count = 0; // int paramAddr = 0, codeAddr = 0, jumpsAddr = 0, dataAddr = 0, subsAddr = 0; int codeAddr = 0; @@ -357,12 +359,13 @@ void* Toy_compileRoutine(Toy_Ast* ast) { //build void * buffer = writeRoutine(&rt, ast); + //cleanup the temp object - TOY_FREE_ARRAY(unsigned char, rt.param, rt.paramCapacity); - TOY_FREE_ARRAY(unsigned char, rt.code, rt.codeCapacity); - TOY_FREE_ARRAY(int, rt.jumps, rt.jumpsCapacity); - TOY_FREE_ARRAY(unsigned char, rt.data, rt.dataCapacity); - TOY_FREE_ARRAY(unsigned char, rt.subs, rt.subsCapacity); + free(rt.param); + free(rt.code); + free(rt.jumps); + free(rt.data); + free(rt.subs); return buffer; } diff --git a/source/toy_routine.h b/source/toy_routine.h index 90ac882..85d36e4 100644 --- a/source/toy_routine.h +++ b/source/toy_routine.h @@ -6,24 +6,24 @@ //internal structure that holds the individual parts of a compiled routine typedef struct Toy_Routine { unsigned char* param; //c-string params in sequence (could be moved below the jump table?) - int paramCapacity; - int paramCount; + size_t paramCapacity; + size_t paramCount; unsigned char* code; //the instruction set - int codeCapacity; - int codeCount; + size_t codeCapacity; + size_t codeCount; - int* jumps; //each 'jump' is the starting address of an element within 'data' - int jumpsCapacity; - int jumpsCount; + size_t* jumps; //each 'jump' is the starting address of an element within 'data' + size_t jumpsCapacity; + size_t jumpsCount; unsigned char* data; //{type,val} tuples of data - int dataCapacity; - int dataCount; + size_t dataCapacity; + size_t dataCount; unsigned char* subs; //subroutines, recursively - int subsCapacity; - int subsCount; + size_t subsCapacity; + size_t subsCount; } Toy_Routine; TOY_API void* Toy_compileRoutine(Toy_Ast* ast); \ No newline at end of file diff --git a/source/toy_stack.c b/source/toy_stack.c index 7d35155..af2a2ad 100644 --- a/source/toy_stack.c +++ b/source/toy_stack.c @@ -1,72 +1,86 @@ #include "toy_stack.h" #include "toy_console_colors.h" -#include "toy_memory.h" - #include #include -//a good chunk of space -#define MIN_SIZE 64 +//a good chunk of space - 'count' actually tracks the number of values +#define MIN_CAPACITY 64 -TOY_API void Toy_initStack(Toy_Stack* stack) { - stack->ptr = NULL; - stack->capacity = 0; - stack->count = 0; -} +Toy_Stack* Toy_allocateStack() { + Toy_Stack* stack = malloc(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack)); -void Toy_preallocateStack(Toy_Stack* stack) { - stack->capacity = MIN_SIZE; + if (stack == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, MIN_CAPACITY, (int)(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack))); + exit(1); + } + + stack->capacity = MIN_CAPACITY; stack->count = 0; - stack->ptr = TOY_ALLOCATE(Toy_Value, stack->capacity); + return stack; } void Toy_freeStack(Toy_Stack* stack) { //TODO: slip in a call to free the complex values here - TOY_FREE_ARRAY(Toy_Value, stack->ptr, stack->capacity); - - Toy_initStack(stack); + free(stack); } -void Toy_pushStack(Toy_Stack* stack, Toy_Value value) { - //don't go overboard - limit to 1mb - if (stack->count >= 1024 * 1024 / sizeof(Toy_Value)) { - fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow, exiting\n" TOY_CC_RESET); +void Toy_pushStack(Toy_Stack** stack, Toy_Value value) { + //don't go overboard - limit to 1mb of capacity used + if ((*stack)->count >= 1024 * 1024 / sizeof(Toy_Value)) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow\n" TOY_CC_RESET); exit(-1); } //expand the capacity if needed - if (stack->count + 1 > stack->capacity) { - int oldCapacity = stack->capacity; - stack->capacity = stack->capacity < MIN_SIZE ? MIN_SIZE : stack->capacity * 2; //similar to TOY_GROW_CAPACITY, with a bigger initial size - stack->ptr = TOY_GROW_ARRAY(Toy_Value, stack->ptr, oldCapacity, stack->capacity); + if ((*stack)->count + 1 > (*stack)->capacity) { + while ((*stack)->count + 1 > (*stack)->capacity) { + (*stack)->capacity = (*stack)->capacity < MIN_CAPACITY ? MIN_CAPACITY : (*stack)->capacity * 2; + } + + size_t newCapacity = (*stack)->capacity; + + (*stack) = realloc((*stack), newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack)); + + if ((*stack) == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to reallocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, (int)newCapacity, (int)(newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack))); + exit(1); + } } - stack->ptr[stack->count++] = value; + //Note: "pointer arithmetic in C/C++ is type-relative" + ((Toy_Value*)((*stack) + 1))[(*stack)->count++] = value; } -Toy_Value Toy_peekStack(Toy_Stack* stack) { - if (stack->count <= 0) { - fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow, exiting\n" TOY_CC_RESET); +Toy_Value Toy_peekStack(Toy_Stack** stack) { + if ((*stack)->count == 0) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow\n" TOY_CC_RESET); exit(-1); } - return stack->ptr[stack->count - 1]; + return ((Toy_Value*)((*stack) + 1))[(*stack)->count - 1]; } -Toy_Value Toy_popStack(Toy_Stack* stack) { - if (stack->count <= 0) { - fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow, exiting\n" TOY_CC_RESET); +Toy_Value Toy_popStack(Toy_Stack** stack) { + if ((*stack)->count == 0) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Stack underflow\n" TOY_CC_RESET); exit(-1); } //shrink if possible - if (stack->count > MIN_SIZE && stack->count < stack->capacity / 4) { - stack->ptr = TOY_SHRINK_ARRAY(Toy_Value, stack->ptr, stack->capacity, stack->capacity / 2); - stack->capacity /= 2; + if ((*stack)->count > MIN_CAPACITY && (*stack)->count < (*stack)->capacity / 4) { + (*stack)->capacity /= 2; + size_t newCapacity = (*stack)->capacity; + + (*stack) = realloc((*stack), (*stack)->capacity * sizeof(Toy_Value) + sizeof(Toy_Stack)); + + if ((*stack) == NULL) { + fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to reallocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, (int)newCapacity, (int)(newCapacity * sizeof(Toy_Value) + sizeof(Toy_Stack))); + exit(1); + } } - return stack->ptr[--stack->count]; + return ((Toy_Value*)((*stack) + 1))[--(*stack)->count]; } diff --git a/source/toy_stack.h b/source/toy_stack.h index 0efc123..634168d 100644 --- a/source/toy_stack.h +++ b/source/toy_stack.h @@ -3,16 +3,15 @@ #include "toy_common.h" #include "toy_value.h" -typedef struct Toy_Stack { - Toy_Value* ptr; - int capacity; - int count; -} Toy_Stack; +typedef struct Toy_Stack { //32 | 64 BITNESS + size_t capacity; //4 | 4 + size_t count; //4 | 4 + char data[]; //- | - +} Toy_Stack; //8 | 8 -TOY_API void Toy_initStack(Toy_Stack* stack); //null memory -TOY_API void Toy_preallocateStack(Toy_Stack* stack); //non-null memory, ready to go +TOY_API Toy_Stack* Toy_allocateStack(); TOY_API void Toy_freeStack(Toy_Stack* stack); -TOY_API void Toy_pushStack(Toy_Stack* stack, Toy_Value value); -TOY_API Toy_Value Toy_peekStack(Toy_Stack* stack); -TOY_API Toy_Value Toy_popStack(Toy_Stack* stack); +TOY_API void Toy_pushStack(Toy_Stack** stack, Toy_Value value); +TOY_API Toy_Value Toy_peekStack(Toy_Stack** stack); +TOY_API Toy_Value Toy_popStack(Toy_Stack** stack); diff --git a/source/toy_string.c b/source/toy_string.c index beb6866..89b0dcd 100644 --- a/source/toy_string.c +++ b/source/toy_string.c @@ -42,7 +42,7 @@ Toy_String* Toy_createString(Toy_Bucket** bucket, const char* cstring) { } Toy_String* Toy_createStringLength(Toy_Bucket** bucket, const char* cstring, int length) { - Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String) + length + 1); //TODO: compensate for partitioning more space than bucket capacity + Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String) + length + 1); //TODO: compensate for partitioning more space than bucket capacity ret->type = TOY_STRING_LEAF; ret->length = length; @@ -67,7 +67,7 @@ Toy_String* Toy_deepCopyString(Toy_Bucket** bucket, Toy_String* str) { fprintf(stderr, TOY_CC_ERROR "ERROR: Can't deep copy a string with refcount below or equal to zero\n" TOY_CC_RESET); exit(-1); } - Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String) + str->length + 1); //TODO: compensate for partitioning more space than bucket capacity + Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String) + str->length + 1); //TODO: compensate for partitioning more space than bucket capacity //TODO ret->type = TOY_STRING_LEAF; @@ -85,7 +85,7 @@ Toy_String* Toy_concatString(Toy_Bucket** bucket, Toy_String* left, Toy_String* exit(-1); } - Toy_String* ret = (Toy_String*)Toy_partBucket(bucket, sizeof(Toy_String)); + Toy_String* ret = (Toy_String*)Toy_partitionBucket(bucket, sizeof(Toy_String)); ret->type = TOY_STRING_NODE; ret->length = left->length + right->length; @@ -117,7 +117,7 @@ char* Toy_getStringRawBuffer(Toy_String* str) { exit(-1); } - char* buffer = TOY_ALLOCATE(char, str->length + 1); + char* buffer = malloc(str->length + 1); deepCopyUtil(buffer, str); buffer[str->length] = '\0'; diff --git a/source/toy_string.h b/source/toy_string.h index 0244bd8..57bd34b 100644 --- a/source/toy_string.h +++ b/source/toy_string.h @@ -1,6 +1,6 @@ #include "toy_common.h" -#include "toy_memory.h" +#include "toy_bucket.h" //rope pattern typedef struct Toy_String { //32 | 64 BITNESS diff --git a/source/toy_value.c b/source/toy_value.c index 94ed704..d8fcae1 100644 --- a/source/toy_value.c +++ b/source/toy_value.c @@ -1,5 +1,4 @@ #include "toy_value.h" - #include "toy_console_colors.h" #include diff --git a/source/toy_vm.c b/source/toy_vm.c index 9d8c24b..5ff1585 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -1,7 +1,6 @@ #include "toy_vm.h" #include "toy_console_colors.h" -#include "toy_memory.h" #include "toy_opcodes.h" #include "toy_value.h" @@ -278,30 +277,6 @@ static void process(Toy_VM* vm) { } //exposed functions -void Toy_initVM(Toy_VM* vm) { - vm->bc = NULL; - vm->bcSize = 0; - - vm->routine = NULL; - vm->routineSize = 0; - - vm->paramCount = 0; - vm->jumpsCount = 0; - vm->dataCount = 0; - vm->subsCount = 0; - - vm->paramAddr = 0; - vm->codeAddr = 0; - vm->jumpsAddr = 0; - vm->dataAddr = 0; - vm->subsAddr = 0; - - vm->routineCounter = 0; - - //init the scope & stack - Toy_initStack(&vm->stack); -} - void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize) { if (bytecode[0] != TOY_VERSION_MAJOR || bytecode[1] > TOY_VERSION_MINOR) { fprintf(stderr, TOY_CC_ERROR "ERROR: Wrong bytecode version found: expected %d.%d.%d found %d.%d.%d, exiting\n" TOY_CC_RESET, TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, bytecode[0], bytecode[1], bytecode[2]); @@ -331,7 +306,7 @@ void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize) { } void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) { - Toy_initVM(vm); + Toy_resetVM(vm); vm->routine = routine; @@ -362,7 +337,7 @@ void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine) { } //preallocate the scope & stack - Toy_preallocateStack(&vm->stack); + vm->stack = Toy_allocateStack(); } void Toy_runVM(Toy_VM* vm) { @@ -377,11 +352,36 @@ void Toy_runVM(Toy_VM* vm) { void Toy_freeVM(Toy_VM* vm) { //clear the stack - Toy_freeStack(&vm->stack); + Toy_freeStack(vm->stack); //TODO: clear the scope //free the bytecode - TOY_FREE_ARRAY(unsigned char, vm->bc, vm->bcSize); - Toy_initVM(vm); + + free(vm->bc); + Toy_resetVM(vm); } + +void Toy_resetVM(Toy_VM* vm) { + vm->bc = NULL; + vm->bcSize = 0; + + vm->routine = NULL; + vm->routineSize = 0; + + vm->paramCount = 0; + vm->jumpsCount = 0; + vm->dataCount = 0; + vm->subsCount = 0; + + vm->paramAddr = 0; + vm->codeAddr = 0; + vm->jumpsAddr = 0; + vm->dataAddr = 0; + vm->subsAddr = 0; + + vm->routineCounter = 0; + + //init the scope & stack + vm->stack = NULL; +} \ No newline at end of file diff --git a/source/toy_vm.h b/source/toy_vm.h index 3f20da3..0ac6669 100644 --- a/source/toy_vm.h +++ b/source/toy_vm.h @@ -30,15 +30,14 @@ typedef struct Toy_VM { //TODO: needs string util for identifiers //stack - immediate-level values only - Toy_Stack stack; + Toy_Stack* stack; } Toy_VM; -TOY_API void Toy_initVM(Toy_VM* vm); - TOY_API void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, int bytecodeSize); //process the version data TOY_API void Toy_bindVMToRoutine(Toy_VM* vm, unsigned char* routine); //process the routine only TOY_API void Toy_runVM(Toy_VM* vm); TOY_API void Toy_freeVM(Toy_VM* vm); +TOY_API void Toy_resetVM(Toy_VM* vm); //TODO: inject extra data diff --git a/tests/cases/test_array.c b/tests/cases/test_array.c new file mode 100644 index 0000000..a47abc2 --- /dev/null +++ b/tests/cases/test_array.c @@ -0,0 +1,52 @@ +#include "toy_array.h" +#include "toy_console_colors.h" + +#include + +int test_resizeArray() { + //test single pointer + { + Toy_Array* array = TOY_ALLOCATE_ARRAY(int, 1); + TOY_FREE_ARRAY(int, array); + } + + //test single pointer array + { + Toy_Array* array = TOY_ALLOCATE_ARRAY(int, 10); + + //check you can access the memory + array->data[1] = 42; + + TOY_FREE_ARRAY(int, array); + } + + //test multiple pointer arrays + { + Toy_Array* array1 = TOY_ALLOCATE_ARRAY(int, 10); + Toy_Array* array2 = TOY_ALLOCATE_ARRAY(int, 10); + + array1->data[1] = 42; //access the given memory + array2->data[1] = 42; //access the given memory + + TOY_FREE_ARRAY(int, array1); + TOY_FREE_ARRAY(int, array2); + } + + return 0; +} + +int main() { + //run each test set, returning the total errors given + int total = 0, res = 0; + + { + res = test_resizeArray(); + total += res; + + if (res == 0) { + printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); + } + } + + return total; +} diff --git a/tests/cases/test_ast.c b/tests/cases/test_ast.c index 0d4da76..dd76c80 100644 --- a/tests/cases/test_ast.c +++ b/tests/cases/test_ast.c @@ -162,7 +162,7 @@ int test_type_emission(Toy_Bucket** bucket) { Toy_private_emitAstBinary(bucket, &ast, TOY_AST_FLAG_ADD, right); Toy_private_emitAstGroup(bucket, &ast); - Toy_private_appendAstBlock(bucket, &block, ast); + Toy_private_appendAstBlock(bucket, block, ast); } //check if it worked @@ -216,10 +216,9 @@ int main() { #endif { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_type_emission(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } diff --git a/tests/cases/test_memory.c b/tests/cases/test_bucket.c similarity index 52% rename from tests/cases/test_memory.c rename to tests/cases/test_bucket.c index 137960b..d9753d7 100644 --- a/tests/cases/test_memory.c +++ b/tests/cases/test_bucket.c @@ -1,46 +1,13 @@ -#include "toy_memory.h" +#include "toy_bucket.h" #include "toy_console_colors.h" #include -int test_reallocate() { - //test single pointer - { - int* integer = TOY_ALLOCATE(int, 1); - TOY_FREE(int, integer); - } - - //test single pointer array - { - int* array = TOY_ALLOCATE(int, 10); - - //check you can access the memory - array[1] = 42; - - TOY_FREE_ARRAY(int, array, 10); - } - - //test multiple pointer arrays - { - int* array1 = TOY_ALLOCATE(int, 10); - int* array2 = TOY_ALLOCATE(int, 10); - - array1[1] = 42; //access the given memory - array2[1] = 42; //access the given memory - - TOY_FREE_ARRAY(int, array1, 10); - TOY_FREE_ARRAY(int, array2, 10); - } - - return 0; -} - int test_buckets() { //test initializing and freeing a bucket { //init - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(int, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 32); //check if (bucket == NULL || bucket->capacity != 32 * sizeof(int)) { @@ -49,20 +16,19 @@ int test_buckets() { } //cleanup - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); } //test partitioning a bucket, several times { //init - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(int, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 32); //grab some memory - int* a = TOY_BUCKET_PART(int, bucket); - int* b = TOY_BUCKET_PART(int, bucket); - int* c = TOY_BUCKET_PART(int, bucket); - int* d = TOY_BUCKET_PART(int, bucket); + int* a = Toy_partitionBucket(&bucket, sizeof(int)); + int* b = Toy_partitionBucket(&bucket, sizeof(int)); + int* c = Toy_partitionBucket(&bucket, sizeof(int)); + int* d = Toy_partitionBucket(&bucket, sizeof(int)); //check if (bucket == NULL || bucket->count != 4 * sizeof(int)) { @@ -71,22 +37,21 @@ int test_buckets() { } //cleanup - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); } //test partitioning a bucket, several times, with an internal expansion { //init - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(int, bucket, 4); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(int) * 4); //grab some memory - int* a = TOY_BUCKET_PART(int, bucket); - int* b = TOY_BUCKET_PART(int, bucket); - int* c = TOY_BUCKET_PART(int, bucket); - int* d = TOY_BUCKET_PART(int, bucket); - int* e = TOY_BUCKET_PART(int, bucket); - int* f = TOY_BUCKET_PART(int, bucket); + int* a = Toy_partitionBucket(&bucket, sizeof(int)); + int* b = Toy_partitionBucket(&bucket, sizeof(int)); + int* c = Toy_partitionBucket(&bucket, sizeof(int)); + int* d = Toy_partitionBucket(&bucket, sizeof(int)); + int* e = Toy_partitionBucket(&bucket, sizeof(int)); + int* f = Toy_partitionBucket(&bucket, sizeof(int)); //checks - please note that the top-most bucket is what is being filled - older buckets are further along if ( @@ -101,20 +66,19 @@ int test_buckets() { } //cleanup - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); } //test partitioning a bucket, several times, with an internal expansion, and awkward sizes { //init - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(32); //grab some memory - void* a = Toy_partBucket(&bucket, 16); - void* b = Toy_partBucket(&bucket, 10); - void* c = Toy_partBucket(&bucket, 10); - void* d = Toy_partBucket(&bucket, 10); + void* a = Toy_partitionBucket(&bucket, 16); + void* b = Toy_partitionBucket(&bucket, 10); + void* c = Toy_partitionBucket(&bucket, 10); + void* d = Toy_partitionBucket(&bucket, 10); //checks - awkward and mismatched sizes is not officially supported, but it should work if ( @@ -129,7 +93,7 @@ int test_buckets() { } //cleanup - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); } return 0; @@ -139,18 +103,13 @@ int main() { //run each test set, returning the total errors given int total = 0, res = 0; - res = test_reallocate(); - total += res; + { + res = test_buckets(); + total += res; - if (res == 0) { - printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); - } - - res = test_buckets(); - total += res; - - if (res == 0) { - printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); + if (res == 0) { + printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); + } } return total; diff --git a/tests/cases/test_bytecode.c b/tests/cases/test_bytecode.c index ce69ad9..478842b 100644 --- a/tests/cases/test_bytecode.c +++ b/tests/cases/test_bytecode.c @@ -26,7 +26,7 @@ int test_bytecode_header(Toy_Bucket** bucket) { 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, bc.ptr[0], bc.ptr[1], bc.ptr[2], (char*)(bc.ptr + 3)); + 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 @@ -35,7 +35,7 @@ int test_bytecode_header(Toy_Bucket** bucket) { } 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, bc.count); + 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); @@ -65,7 +65,7 @@ int test_bytecode_from_source(Toy_Bucket** bucket) { //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, bc.count, source); + 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); @@ -175,10 +175,9 @@ int main() { int total = 0, res = 0; { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_bytecode_header(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -186,10 +185,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_bytecode_from_source(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } diff --git a/tests/cases/test_parser.c b/tests/cases/test_parser.c index 3719897..3d33eab 100644 --- a/tests/cases/test_parser.c +++ b/tests/cases/test_parser.c @@ -578,10 +578,9 @@ int main() { int total = 0, res = 0; { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_simple_empty_parsers(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -589,10 +588,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_values(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -600,10 +598,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_unary(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -611,10 +608,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_binary(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -622,10 +618,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_precedence(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } diff --git a/tests/cases/test_routine.c b/tests/cases/test_routine.c index 9a5d486..76fca12 100644 --- a/tests/cases/test_routine.c +++ b/tests/cases/test_routine.c @@ -6,6 +6,7 @@ #include "toy_parser.h" #include +#include #include //tests @@ -32,7 +33,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, ast: PASS\n" TOY_CC_RESET); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -46,12 +47,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, ast: PASS\n" TOY_CC_RESET); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //rerun the test with a more complex ast, derived from a snippet of source @@ -81,7 +82,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -95,12 +96,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a null value @@ -130,7 +131,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -148,12 +149,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a boolean value @@ -183,7 +184,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -201,12 +202,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce an integer value @@ -236,7 +237,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -255,12 +256,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a float value @@ -290,7 +291,7 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -309,12 +310,12 @@ int test_routine_header_and_values(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } return 0; @@ -352,7 +353,7 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -383,12 +384,12 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a simple comparison @@ -418,7 +419,7 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -449,12 +450,12 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a simple comparison @@ -484,7 +485,7 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -520,12 +521,12 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } //produce a more complex algorithm @@ -555,7 +556,7 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } @@ -612,12 +613,12 @@ int test_routine_binary(Toy_Bucket** bucket) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source); //cleanup and return - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); return -1; } //cleanup - TOY_FREE_ARRAY(unsigned char, buffer, len); + free(buffer); } return 0; @@ -628,10 +629,9 @@ int main() { int total = 0, res = 0; { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_routine_header_and_values(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -639,10 +639,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_routine_binary(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } diff --git a/tests/cases/test_stack.c b/tests/cases/test_stack.c index 13b2f2b..23b5836 100644 --- a/tests/cases/test_stack.c +++ b/tests/cases/test_stack.c @@ -3,40 +3,40 @@ #include -int test_stack_with_init() { - //init and free the stack +int test_stack_basics() { + //allocate and free the stack { - Toy_Stack stack; - Toy_initStack(&stack); + Toy_Stack* stack = Toy_allocateStack(); //check if it worked if ( - stack.ptr != NULL || - stack.capacity != 0 || - stack.count != 0) + stack == NULL || + stack->capacity != 64 || + stack->count != 0) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to init Toy_Stack\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to allocate Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } - Toy_freeStack(&stack); + Toy_freeStack(stack); } //push, peek and pop stack { - Toy_Stack stack; - Toy_initStack(&stack); + Toy_Stack* stack = Toy_allocateStack(); //check if it worked (push) Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42)); Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69)); Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420)); if ( - stack.ptr == NULL || - stack.capacity != 64 || - stack.count != 3) + stack == NULL || + stack->capacity != 64 || + stack->count != 3) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } @@ -47,19 +47,21 @@ int test_stack_with_init() { TOY_VALUE_AS_INTEGER(top1) != 420) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } //check if it worked (pop) Toy_Value top2 = Toy_popStack(&stack); if ( - stack.ptr == NULL || - stack.capacity != 64 || - stack.count != 2 || + stack == NULL || + stack->capacity != 64 || + stack->count != 2 || TOY_VALUE_IS_INTEGER(top2) != true || TOY_VALUE_AS_INTEGER(top2) != 420) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } @@ -70,86 +72,38 @@ int test_stack_with_init() { TOY_VALUE_AS_INTEGER(top3) != 69) { fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } - Toy_freeStack(&stack); + Toy_freeStack(stack); } return 0; } -int test_stack_with_preallocate() { - //preallocate and free the stack +int test_stack_stress() { + //stress the stack's contents { - Toy_Stack stack; - Toy_preallocateStack(&stack); + Toy_Stack* stack = Toy_allocateStack(); + + //allocate 500 values + for (int i = 0; i < 500; i++) { + Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(i)); + } //check if it worked if ( - stack.ptr == NULL || - stack.capacity != 64 || - stack.count != 0) + stack == NULL || + stack->capacity != 512 || + stack->count != 500) { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to preallocate Toy_Stack\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: failed to stress the Toy_Stack\n" TOY_CC_RESET); + Toy_freeStack(stack); return -1; } - Toy_freeStack(&stack); - } - - //push, peek and pop stack - { - Toy_Stack stack; - Toy_initStack(&stack); - - //check if it worked (push) - Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(42)); - Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(69)); - Toy_pushStack(&stack, TOY_VALUE_TO_INTEGER(420)); - if ( - stack.ptr == NULL || - stack.capacity != 64 || - stack.count != 3) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET); - return -1; - } - - //check if it worked (peek) - Toy_Value top1 = Toy_peekStack(&stack); - if ( - TOY_VALUE_IS_INTEGER(top1) != true || - TOY_VALUE_AS_INTEGER(top1) != 420) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to peek Toy_Stack\n" TOY_CC_RESET); - return -1; - } - - //check if it worked (pop) - Toy_Value top2 = Toy_popStack(&stack); - if ( - stack.ptr == NULL || - stack.capacity != 64 || - stack.count != 2 || - TOY_VALUE_IS_INTEGER(top2) != true || - TOY_VALUE_AS_INTEGER(top2) != 420) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop Toy_Stack\n" TOY_CC_RESET); - return -1; - } - - //check if it worked (post-pop peek) - Toy_Value top3 = Toy_peekStack(&stack); - if ( - TOY_VALUE_IS_INTEGER(top3) != true || - TOY_VALUE_AS_INTEGER(top3) != 69) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: failed to pop then peek Toy_Stack\n" TOY_CC_RESET); - return -1; - } - - Toy_freeStack(&stack); + Toy_freeStack(stack); } return 0; @@ -160,7 +114,7 @@ int main() { int total = 0, res = 0; { - res = test_stack_with_init(); + res = test_stack_basics(); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -168,7 +122,7 @@ int main() { } { - res = test_stack_with_preallocate(); + res = test_stack_stress(); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } diff --git a/tests/cases/test_string.c b/tests/cases/test_string.c index 2ad279a..5fcbb6c 100644 --- a/tests/cases/test_string.c +++ b/tests/cases/test_string.c @@ -1,9 +1,10 @@ #include "toy_string.h" #include "toy_console_colors.h" -#include "toy_memory.h" +#include "toy_bucket.h" #include +#include #include int test_sizeof_string_64bit() { @@ -34,8 +35,7 @@ int test_string_allocation() { //allocate a single string from a c-string { //setup - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 1024); + Toy_Bucket* bucket = Toy_allocateBucket(1024); const char* cstring = "Hello world"; Toy_String* str = Toy_createString(&bucket, cstring); @@ -77,8 +77,7 @@ int test_string_allocation() { //copy and deep copy a string { //setup - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 1024); + Toy_Bucket* bucket = Toy_allocateBucket(1024); const char* cstring = "Hello world"; Toy_String* str = Toy_createString(&bucket, cstring); @@ -104,8 +103,7 @@ int test_string_allocation() { //allocate a zero-length string { //setup - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 1024); + Toy_Bucket* bucket = Toy_allocateBucket(1024); const char* cstring = ""; Toy_String* str = Toy_createString(&bucket, cstring); @@ -133,8 +131,7 @@ int test_string_allocation() { int test_string_concatenation() { //one big bucket o' fun - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 1024); + Toy_Bucket* bucket = Toy_allocateBucket(1024); //concatenate two strings, and check the refcounts { @@ -191,12 +188,12 @@ int test_string_concatenation() { strcmp(buffer, "Hello world") != 0) { fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to get the raw buffer from concatenated string\n" TOY_CC_RESET); - TOY_FREE_ARRAY(char, buffer, result->length + 1); + free(buffer); Toy_freeBucket(&bucket); return -1; } - TOY_FREE_ARRAY(char, buffer, result->length + 1); + free(buffer); Toy_freeString(result); Toy_freeString(first); Toy_freeString(second); @@ -224,8 +221,7 @@ int test_string_with_stressed_bucket() { }; //setup - Toy_Bucket* bucket = NULL; - Toy_initBucket(&bucket, 128); //deliberately too short for one bucket + Toy_Bucket* bucket = Toy_allocateBucket(128);//deliberately too much data for one bucket //stress Toy_String* str = Toy_createString(&bucket, testData[0]); @@ -250,7 +246,7 @@ int test_string_with_stressed_bucket() { strlen(buffer) != 36) { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the raw buffer after string stress test: '%s'\n" TOY_CC_RESET, buffer); - Toy_reallocate(buffer, 0, 0); //direct call to free, regardless of size + free(buffer); Toy_freeBucket(&bucket); return -1; } @@ -258,13 +254,13 @@ int test_string_with_stressed_bucket() { if (bucket->next == NULL) //just to make sure { fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected state of the bucket after string stress test\n" TOY_CC_RESET); - Toy_reallocate(buffer, 0, 0); //direct call to free, regardless of size + free(buffer); Toy_freeBucket(&bucket); return -1; } //clean up - TOY_FREE_ARRAY(char, buffer, str->length); + free(buffer); Toy_freeBucket(&bucket); } diff --git a/tests/cases/test_vm.c b/tests/cases/test_vm.c index 82c728b..a8e7893 100644 --- a/tests/cases/test_vm.c +++ b/tests/cases/test_vm.c @@ -41,7 +41,6 @@ int test_setup_and_teardown(Toy_Bucket** bucket) { //run the setup Toy_VM vm; - Toy_initVM(&vm); Toy_bindVM(&vm, bc.ptr, bc.capacity); //check the header size @@ -93,14 +92,14 @@ int test_simple_execution(Toy_Bucket** bucket) { //run the setup Toy_VM vm; - Toy_initVM(&vm); Toy_bindVM(&vm, bc.ptr, bc.capacity); //run Toy_runVM(&vm); //check the final state of the stack - if (vm.stack.count != 1 || + if (vm.stack == NULL || + vm.stack->count != 1 || TOY_VALUE_IS_INTEGER( Toy_peekStack(&vm.stack) ) != true || TOY_VALUE_AS_INTEGER( Toy_peekStack(&vm.stack) ) != 21 ) @@ -124,10 +123,9 @@ int main() { int total = 0, res = 0; { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_setup_and_teardown(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); } @@ -135,10 +133,9 @@ int main() { } { - Toy_Bucket* bucket = NULL; - TOY_BUCKET_INIT(Toy_Ast, bucket, 32); + Toy_Bucket* bucket = Toy_allocateBucket(sizeof(Toy_Ast) * 32); res = test_simple_execution(&bucket); - TOY_BUCKET_FREE(bucket); + Toy_freeBucket(&bucket); if (res == 0) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); }