From 08c8e7e3e63b9d069f298e9f5fe63d9954efd686 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Mon, 29 Aug 2022 16:25:53 +1000 Subject: [PATCH] Another one bites the dust! --- source/compiler.c | 77 +++++++++++++++++++-------- source/literal_util.c | 15 ++++++ test/test_compiler.c | 118 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 21 deletions(-) create mode 100644 test/test_compiler.c diff --git a/source/compiler.c b/source/compiler.c index 217c2e0..8ca01f9 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -31,7 +31,9 @@ static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal litera for (int i = 0; i < AS_TYPE(literal).count; i++) { //write the values to the cache, and the indexes to the store int subIndex = writeLiteralTypeToCacheOpt(literalCache, ((Literal*)(AS_TYPE(literal).subtypes))[i], false); - pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex)); + Literal lit = TO_INTEGER_LITERAL(subIndex); + pushLiteralArray(store, lit); + freeLiteral(lit); } //push the store to the cache, tweaking the type @@ -77,14 +79,18 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { key = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal); } - pushLiteralArray(store, TO_INTEGER_LITERAL(key)); + Literal literal = TO_INTEGER_LITERAL(key); + pushLiteralArray(store, literal); + freeLiteral(literal); } break; case NODE_COMPOUND: { int key = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.left); - pushLiteralArray(store, TO_INTEGER_LITERAL(key)); + Literal literal = TO_INTEGER_LITERAL(key); + pushLiteralArray(store, literal); + freeLiteral(literal); } break; @@ -102,14 +108,18 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal); } - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + Literal literal = TO_INTEGER_LITERAL(val); + pushLiteralArray(store, literal); + freeLiteral(literal); } break; case NODE_COMPOUND: { int val = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.right); - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + Literal literal = TO_INTEGER_LITERAL(val); + pushLiteralArray(store, literal); + freeLiteral(literal); } break; @@ -120,7 +130,9 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { } //push the store to the cache, with instructions about how pack it - index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store)); //WARNING: pushed as a dictionary, so below can recognize it + Literal literal = TO_DICTIONARY_LITERAL(store); + index = pushLiteralArray(&compiler->literalCache, literal); //WARNING: pushed as a dictionary, so below can recognize it + freeLiteral(literal); } else if (node->compound.literalType == LITERAL_ARRAY) { //ensure each literal value is in the cache, individually @@ -133,14 +145,18 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].atomic.literal); } - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + Literal literal = TO_INTEGER_LITERAL(val); + pushLiteralArray(store, literal); + freeLiteral(literal); } break; case NODE_COMPOUND: { int val = writeNodeCompoundToCache(compiler, &node->compound.nodes[i]); - index = pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + Literal literal = TO_INTEGER_LITERAL(val); + index = pushLiteralArray(store, literal); + freeLiteral(literal); } break; @@ -151,7 +167,9 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { } //push the store to the cache, with instructions about how pack it - index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); + Literal literal = TO_ARRAY_LITERAL(store); + index = pushLiteralArray(&compiler->literalCache, literal); + freeLiteral(literal); } else { fprintf(stderr, ERROR "[Internal] Unrecognized compound type in writeNodeCompoundToCache()" RESET); @@ -172,8 +190,13 @@ static int writeNodeCollectionToCache(Compiler* compiler, Node* node) { int identifierIndex = pushLiteralArray(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.identifier); //store without duplication optimisation int typeIndex = writeLiteralTypeToCacheOpt(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.typeLiteral, false); - pushLiteralArray(store, TO_INTEGER_LITERAL(identifierIndex)); - pushLiteralArray(store, TO_INTEGER_LITERAL(typeIndex)); + Literal identifierLiteral = TO_INTEGER_LITERAL(identifierIndex); + pushLiteralArray(store, identifierLiteral); + freeLiteral(identifierLiteral); + + Literal typeLiteral = TO_INTEGER_LITERAL(typeIndex); + pushLiteralArray(store, typeLiteral); + freeLiteral(typeLiteral); } break; @@ -181,7 +204,9 @@ static int writeNodeCollectionToCache(Compiler* compiler, Node* node) { //write each piece of the declaration to the cache int typeIndex = writeLiteralTypeToCacheOpt(&compiler->literalCache, node->fnCollection.nodes[i].atomic.literal, false); - pushLiteralArray(store, TO_INTEGER_LITERAL(typeIndex)); + Literal typeLiteral = TO_INTEGER_LITERAL(typeIndex); + pushLiteralArray(store, typeLiteral); + freeLiteral(typeLiteral); } break; @@ -192,7 +217,11 @@ static int writeNodeCollectionToCache(Compiler* compiler, Node* node) { } //store the store - return pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); + Literal literal = TO_ARRAY_LITERAL(store); + int storeIndex = pushLiteralArray(&compiler->literalCache, literal); + freeLiteral(literal); + + return storeIndex; } static int writeLiteralToCompiler(Compiler* compiler, Literal literal) { @@ -414,22 +443,24 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd } //push the argument COUNT to the top of the stack - int argumentsCount = findLiteralIndex(&compiler->literalCache, TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count)); - if (argumentsCount < 0) { - argumentsCount = pushLiteralArray(&compiler->literalCache, TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count)); + Literal argumentsCountLiteral = TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count); + int argumentsCountIndex = findLiteralIndex(&compiler->literalCache, argumentsCountLiteral); + if (argumentsCountIndex < 0) { + argumentsCountIndex = pushLiteralArray(&compiler->literalCache, argumentsCountLiteral); } + freeLiteral(argumentsCountLiteral); - if (argumentsCount >= 256) { + if (argumentsCountIndex >= 256) { //push a "long" index compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte - *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)argumentsCount; //2 bytes + *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)argumentsCountIndex; //2 bytes compiler->count += sizeof(unsigned short); } else { //push the index compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte - compiler->bytecode[compiler->count++] = (unsigned char)argumentsCount; //1 byte + compiler->bytecode[compiler->count++] = (unsigned char)argumentsCountIndex; //1 byte } //call the function @@ -586,7 +617,9 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte //push to the breakAddresses array - pushLiteralArray((LiteralArray*)breakAddressesPtr, TO_INTEGER_LITERAL(compiler->count)); + Literal literal = TO_INTEGER_LITERAL(compiler->count); + pushLiteralArray((LiteralArray*)breakAddressesPtr, literal); + freeLiteral(literal); compiler->count += sizeof(unsigned short); //2 bytes } @@ -602,7 +635,9 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte //push to the continueAddresses array - pushLiteralArray((LiteralArray*)continueAddressesPtr, TO_INTEGER_LITERAL(compiler->count)); + Literal literal = TO_INTEGER_LITERAL(compiler->count); + pushLiteralArray((LiteralArray*)continueAddressesPtr, literal); + freeLiteral(literal); compiler->count += sizeof(unsigned short); //2 bytes } diff --git a/source/literal_util.c b/source/literal_util.c index 2e7083e..bcff0c9 100644 --- a/source/literal_util.c +++ b/source/literal_util.c @@ -72,6 +72,21 @@ Literal copyLiteral(Literal original) { return lit; } + case LITERAL_TYPE_INTERMEDIATE: { + LiteralArray* array = ALLOCATE(LiteralArray, 1); + initLiteralArray(array); + + //copy each element + for (int i = 0; i < AS_ARRAY(original)->count; i++) { + pushLiteralArray(array, copyLiteral(AS_ARRAY(original)->literals[i])); + } + + Literal ret = TO_ARRAY_LITERAL(array); + ret.type = LITERAL_TYPE_INTERMEDIATE; + return ret; + } + + case LITERAL_FUNCTION_INTERMEDIATE: //caries a compiler case LITERAL_FUNCTION_NATIVE: //no copying possible return original; diff --git a/test/test_compiler.c b/test/test_compiler.c new file mode 100644 index 0000000..0fc720d --- /dev/null +++ b/test/test_compiler.c @@ -0,0 +1,118 @@ +#include "lexer.h" +#include "parser.h" +#include "compiler.h" + +#include "console_colors.h" + +#include "memory.h" + +#include +#include +#include + +//IO functions +char* readFile(char* path, size_t* fileSize) { + FILE* file = fopen(path, "rb"); + + if (file == NULL) { + fprintf(stderr, ERROR "Could not open file \"%s\"\n" RESET, path); + exit(-1); + } + + fseek(file, 0L, SEEK_END); + *fileSize = ftell(file); + rewind(file); + + char* buffer = (char*)malloc(*fileSize + 1); + + if (buffer == NULL) { + fprintf(stderr, ERROR "Not enough memory to read \"%s\"\n" RESET, path); + exit(-1); + } + + size_t bytesRead = fread(buffer, sizeof(char), *fileSize, file); + + buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this + + if (bytesRead < *fileSize) { + fprintf(stderr, ERROR "Could not read file \"%s\"\n" RESET, path); + exit(-1); + } + + fclose(file); + + return buffer; +} + +int main() { + { + //test init & free + Compiler compiler; + initCompiler(&compiler); + freeCompiler(&compiler); + } + + { + //source + char* source = "print null;"; + + //test basic compilation & collation + Lexer lexer; + Parser parser; + Compiler compiler; + + initLexer(&lexer, source); + initParser(&parser, &lexer); + initCompiler(&compiler); + + Node* node = scanParser(&parser); + + //write + writeCompiler(&compiler, node); + + //collate + int size = 0; + unsigned char* bytecode = collateCompiler(&compiler, &size); + + //cleanup + FREE_ARRAY(unsigned char, bytecode, size); + freeNode(node); + freeParser(&parser); + freeCompiler(&compiler); + } + + { + //source + size_t sourceLength = 0; + char* source = readFile("sample_code.toy", &sourceLength); + + //test basic compilation & collation + Lexer lexer; + Parser parser; + Compiler compiler; + + initLexer(&lexer, source); + initParser(&parser, &lexer); + initCompiler(&compiler); + + Node* node = scanParser(&parser); + + //write + writeCompiler(&compiler, node); + + //collate + int size = 0; + unsigned char* bytecode = collateCompiler(&compiler, &size); + + //cleanup + FREE_ARRAY(char, source, sourceLength); + FREE_ARRAY(unsigned char, bytecode, size); + freeNode(node); + freeParser(&parser); + freeCompiler(&compiler); + } + + printf(NOTICE "All good\n" RESET); + return 0; +} +