From 8009f410a440bc4f375afaed980a1d7b65d4056f Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 8 Jan 2023 12:43:25 +0000 Subject: [PATCH] Added mustfail test, fixed compound type decl bug --- scripts/small.toy | 19 +-- source/scope.c | 21 ++- test/scripts/mustfail/declare-types-array.toy | 7 + .../mustfail/declare-types-dictionary.toy | 7 + test/test_mustfail.c | 159 ++++++++++++++++++ 5 files changed, 200 insertions(+), 13 deletions(-) create mode 100644 test/scripts/mustfail/declare-types-array.toy create mode 100644 test/scripts/mustfail/declare-types-dictionary.toy create mode 100644 test/test_mustfail.c diff --git a/scripts/small.toy b/scripts/small.toy index 1ec8735..722d8d8 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1,13 +1,10 @@ -import timer; -var a = createTimer(1, 0); -var b = createTimer(2, 0); +{ + var t = astype [int]; + var arr: t = [1, 2, 3.14]; +} -print a.compareTimer(b).timerToString(); -print b.compareTimer(a).timerToString(); - -var c = createTimer(0, 1); -var d = createTimer(0, 2); - -print c.compareTimer(d).timerToString(); -print d.compareTimer(c).timerToString(); +{ + var t = astype [string:int]; + var dict: t = ["one": 1, "two": 2, "pi": 3.14]; +} diff --git a/source/scope.c b/source/scope.c index a2c349e..745c1e2 100644 --- a/source/scope.c +++ b/source/scope.c @@ -70,8 +70,14 @@ static bool checkType(Literal typeLiteral, Literal original, Literal value, bool return false; } - //if null, assume it's a new entry + //if null, assume it's a new array variable that needs checking if (IS_NULL(original)) { + for (int i = 0; i < AS_ARRAY(value)->count; i++) { + if (!checkType( ((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], TO_NULL_LITERAL, AS_ARRAY(value)->literals[i], constCheck)) { + return false; + } + } + return true; } @@ -97,8 +103,19 @@ static bool checkType(Literal typeLiteral, Literal original, Literal value, bool return false; } - //if null, assume it's a new entry to a parent + //if null, assume it's a new dictionary variable that needs checking if (IS_NULL(original)) { + for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) { + //check the type of key and value + if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], TO_NULL_LITERAL, AS_DICTIONARY(value)->entries[i].key, constCheck)) { + return false; + } + + if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[1], TO_NULL_LITERAL, AS_DICTIONARY(value)->entries[i].value, constCheck)) { + return false; + } + } + return true; } diff --git a/test/scripts/mustfail/declare-types-array.toy b/test/scripts/mustfail/declare-types-array.toy new file mode 100644 index 0000000..cdb50bb --- /dev/null +++ b/test/scripts/mustfail/declare-types-array.toy @@ -0,0 +1,7 @@ +{ + var t = astype [int]; + var arr: t = [1, 2, 3.14]; +} + + +print "All good"; diff --git a/test/scripts/mustfail/declare-types-dictionary.toy b/test/scripts/mustfail/declare-types-dictionary.toy new file mode 100644 index 0000000..10fbd93 --- /dev/null +++ b/test/scripts/mustfail/declare-types-dictionary.toy @@ -0,0 +1,7 @@ +{ + var t = astype [string:int]; + var dict: t = ["one": 1, "two": 2, "pi": 3.14]; +} + + +print "All good"; diff --git a/test/test_mustfail.c b/test/test_mustfail.c new file mode 100644 index 0000000..81fe171 --- /dev/null +++ b/test/test_mustfail.c @@ -0,0 +1,159 @@ +#include "lexer.h" +#include "parser.h" +#include "compiler.h" +#include "interpreter.h" + +#include "console_colors.h" + +#include "memory.h" + +#include +#include +#include + +//suppress the print output +static void noPrintFn(const char* output) { + //NO OP +} + +int errorsTriggered = 0; +static void noErrorFn(const char* output) { + errorsTriggered++; +} + +//compilation 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; +} + +unsigned char* compileString(char* source, size_t* size) { + Lexer lexer; + Parser parser; + Compiler compiler; + + initLexer(&lexer, source); + initParser(&parser, &lexer); + initCompiler(&compiler); + + //run the parser until the end of the source + ASTNode* node = scanParser(&parser); + while(node != NULL) { + //pack up and leave + if (node->type == AST_NODE_ERROR) { + printf(ERROR "error node detected\n" RESET); + freeASTNode(node); + freeCompiler(&compiler); + freeParser(&parser); + return NULL; + } + + writeCompiler(&compiler, node); + freeASTNode(node); + node = scanParser(&parser); + } + + //get the bytecode dump + unsigned char* tb = collateCompiler(&compiler, (int*)(size)); + + //cleanup + freeCompiler(&compiler); + freeParser(&parser); + //no lexer to clean up + + //finally + return tb; +} + +void runBinary(unsigned char* tb, size_t size) { + Interpreter interpreter; + initInterpreter(&interpreter); + + //NOTE: suppress print output for testing + setInterpreterPrint(&interpreter, noPrintFn); + setInterpreterError(&interpreter, noErrorFn); + + runInterpreter(&interpreter, tb, size); + freeInterpreter(&interpreter); +} + +void runSource(char* source) { + size_t size = 0; + unsigned char* tb = compileString(source, &size); + if (!tb) { + return; + } + runBinary(tb, size); +} + +void runSourceFile(char* fname) { + size_t size = 0; //not used + char* source = readFile(fname, &size); + runSource(source); + free((void*)source); +} + +int main() { + bool success = true; + + { + //run each file in tests/scripts/ + char* filenames[] = { + "declare-types-array.toy", + "declare-types-dictionary.toy", + NULL + }; + + for (int i = 0; filenames[i]; i++) { + printf("Running %s\n", filenames[i]); + + char buffer[128]; + snprintf(buffer, 128, "scripts/mustfail/%s", filenames[i]); + + runSourceFile(buffer); + + if (errorsTriggered == 0) { + printf(ERROR "Expected error did not occur in %s\n" RESET, filenames[i]); + success = false; + } + + errorsTriggered = 0; + } + } + + if (!success) { + return -1; + } + + printf(NOTICE "All good\n" RESET); + return 0; +} +