diff --git a/scripts/small.toy b/scripts/small.toy new file mode 100644 index 0000000..54b8f52 --- /dev/null +++ b/scripts/small.toy @@ -0,0 +1,2 @@ +print "hello world"; + diff --git a/source/compiler.c b/source/compiler.c index 8ca01f9..56d1865 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -19,6 +19,10 @@ void initCompiler(Compiler* compiler) { //separated out, so it can be recursive static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal literal, bool skipDuplicationOptimisation) { + printf(WARN); + printLiteral(literal); + printf(RESET); + //if it's a compound type, recurse and store the results if (AS_TYPE(literal).typeOf == LITERAL_ARRAY || AS_TYPE(literal).typeOf == LITERAL_DICTIONARY) { //I don't like storing types in an array, but it's the easiest and most straight forward method @@ -31,6 +35,7 @@ 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); + Literal lit = TO_INTEGER_LITERAL(subIndex); pushLiteralArray(store, lit); freeLiteral(lit); @@ -46,12 +51,15 @@ static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal litera int index = findLiteralIndex(literalCache, literal); if (index < 0) { index = pushLiteralArray(literalCache, literal); + freeLiteral(literal); } return index; } else { - return pushLiteralArray(literalCache, literal); + int index = pushLiteralArray(literalCache, literal); + freeLiteral(literal); + return index; } } @@ -131,7 +139,8 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { //push the store to the cache, with instructions about how pack it Literal literal = TO_DICTIONARY_LITERAL(store); - index = pushLiteralArray(&compiler->literalCache, literal); //WARNING: pushed as a dictionary, so below can recognize it + literal.type = LITERAL_DICTIONARY_INTERMEDIATE; //god damn it + index = pushLiteralArray(&compiler->literalCache, literal); freeLiteral(literal); } else if (node->compound.literalType == LITERAL_ARRAY) { @@ -257,7 +266,7 @@ static int writeLiteralToCompiler(Compiler* compiler, Literal literal) { static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAddressesPtr, void* continueAddressesPtr) { //grow if the bytecode space is too small - if (compiler->capacity < compiler->count + 1) { + if (compiler->count + 32 > compiler->capacity) { int oldCapacity = compiler->capacity; compiler->capacity = GROW_CAPACITY_FAST(oldCapacity); @@ -844,13 +853,10 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo for (int i = 0; i < ptr->count; i++) { emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values } - - freeLiteralArray(ptr); - FREE(LiteralArray, ptr); } break; - case LITERAL_DICTIONARY: { + case LITERAL_DICTIONARY_INTERMEDIATE: { emitByte(&collation, &capacity, &count, LITERAL_DICTIONARY); LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above @@ -862,9 +868,6 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo for (int i = 0; i < ptr->count; i++) { emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values } - - freeLiteralArray(ptr); - FREE(LiteralArray, ptr); } break; @@ -892,7 +895,8 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo emitShort(&collation, &capacity, &count, (unsigned short)(fnIndex++)); freeCompiler((Compiler*)fnCompiler); - FREE(Compiler, fnCompiler); + FREE(compiler, fnCompiler); + FREE_ARRAY(unsigned char, bytes, size); } break; @@ -927,7 +931,7 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above //the base literal - Literal typeLiteral = ptr->literals[0]; + Literal typeLiteral = copyLiteral(ptr->literals[0]); //what type this literal represents emitByte(&collation, &capacity, &count, AS_TYPE(typeLiteral).typeOf); @@ -941,8 +945,7 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo } } - freeLiteralArray(ptr); - FREE(LiteralArray, ptr); + freeLiteral(typeLiteral); } break; @@ -980,7 +983,7 @@ static unsigned char* collateCompilerHeaderOpt(Compiler* compiler, int* size, bo *size = count; - return collation; + return collation; } unsigned char* collateCompiler(Compiler* compiler, int* size) { diff --git a/source/interpreter.c b/source/interpreter.c index 549be87..b2a1f9d 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -42,6 +42,8 @@ bool injectNativeFn(Interpreter* interpreter, char* name, NativeFn func) { setLiteralDictionary(&interpreter->scope->variables, identifier, fn); setLiteralDictionary(&interpreter->scope->types, identifier, type); + freeLiteral(identifier); + return true; } @@ -526,7 +528,9 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) { //concat the strings char buffer[MAX_STRING_LENGTH]; snprintf(buffer, MAX_STRING_LENGTH, "%s%s", AS_STRING(lhs), AS_STRING(rhs)); - pushLiteralArray(&interpreter->stack, TO_STRING_LITERAL( copyString(buffer, strlen(buffer)), strlen(buffer) )); + Literal literal = TO_STRING_LITERAL( copyString(buffer, strlen(buffer)), strlen(buffer) ); + pushLiteralArray(&interpreter->stack, literal); + freeLiteral(literal); return true; } @@ -1451,7 +1455,9 @@ static void readInterpreterSections(Interpreter* interpreter) { case LITERAL_BOOLEAN: { //read the booleans const bool b = readByte(interpreter->bytecode, &interpreter->count); - pushLiteralArray(&interpreter->literalCache, TO_BOOLEAN_LITERAL(b)); + Literal literal = TO_BOOLEAN_LITERAL(b); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); if (command.verbose) { printf("(boolean %s)\n", b ? "true" : "false"); @@ -1461,7 +1467,9 @@ static void readInterpreterSections(Interpreter* interpreter) { case LITERAL_INTEGER: { const int d = readInt(interpreter->bytecode, &interpreter->count); - pushLiteralArray(&interpreter->literalCache, TO_INTEGER_LITERAL(d)); + Literal literal = TO_INTEGER_LITERAL(d); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); if (command.verbose) { printf("(integer %d)\n", d); @@ -1471,7 +1479,9 @@ static void readInterpreterSections(Interpreter* interpreter) { case LITERAL_FLOAT: { const float f = readFloat(interpreter->bytecode, &interpreter->count); - pushLiteralArray(&interpreter->literalCache, TO_FLOAT_LITERAL(f)); + Literal literal = TO_FLOAT_LITERAL(f); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); if (command.verbose) { printf("(float %f)\n", f); @@ -1481,7 +1491,9 @@ static void readInterpreterSections(Interpreter* interpreter) { case LITERAL_STRING: { char* s = readString(interpreter->bytecode, &interpreter->count); - pushLiteralArray(&interpreter->literalCache, TO_STRING_LITERAL( copyString(s, strlen(s)), strlen(s) )); + Literal literal = TO_STRING_LITERAL( copyString(s, strlen(s)), strlen(s) ); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); if (command.verbose) { printf("(string \"%s\")\n", s); @@ -1503,12 +1515,16 @@ static void readInterpreterSections(Interpreter* interpreter) { if (command.verbose) { printf("(array "); - printLiteral(TO_ARRAY_LITERAL(array)); + Literal literal = TO_ARRAY_LITERAL(array); + printLiteral(literal); + freeLiteral(literal); printf(")\n"); } //finally, push the array proper - pushLiteralArray(&interpreter->literalCache, TO_ARRAY_LITERAL(array)); + Literal literal = TO_ARRAY_LITERAL(array); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); } break; @@ -1527,12 +1543,16 @@ static void readInterpreterSections(Interpreter* interpreter) { if (command.verbose) { printf("(dictionary "); - printLiteral(TO_DICTIONARY_LITERAL(dictionary)); + Literal literal = TO_DICTIONARY_LITERAL(dictionary); + printLiteral(literal); + freeLiteral(literal); printf(")\n"); } //finally, push the dictionary proper - pushLiteralArray(&interpreter->literalCache, TO_DICTIONARY_LITERAL(dictionary)); + Literal literal = TO_DICTIONARY_LITERAL(dictionary); + pushLiteralArray(&interpreter->literalCache, literal); + freeLiteral(literal); } break; @@ -1563,6 +1583,8 @@ static void readInterpreterSections(Interpreter* interpreter) { if (command.verbose) { printf("(identifier %s (hash: %x))\n", AS_IDENTIFIER(identifier), identifier.as.identifier.hash); } + + freeLiteral(identifier); } break; @@ -1581,6 +1603,8 @@ static void readInterpreterSections(Interpreter* interpreter) { printLiteral(typeLiteral); printf(")\n"); } + + freeLiteral(typeLiteral); } break; @@ -1614,6 +1638,8 @@ static void readInterpreterSections(Interpreter* interpreter) { printLiteral(typeLiteral); printf(")\n"); } + + freeLiteral(typeLiteral); } break; } diff --git a/source/literal.c b/source/literal.c index 0aadff9..740976e 100644 --- a/source/literal.c +++ b/source/literal.c @@ -34,13 +34,15 @@ void freeLiteral(Literal literal) { return; } - if (IS_ARRAY(literal)) { + if (IS_ARRAY(literal) || literal.type == LITERAL_DICTIONARY_INTERMEDIATE || literal.type == LITERAL_TYPE_INTERMEDIATE) { freeLiteralArray(AS_ARRAY(literal)); + FREE(LiteralArray, AS_ARRAY(literal)); return; } if (IS_DICTIONARY(literal)) { freeLiteralDictionary(AS_DICTIONARY(literal)); + FREE(LiteralDictionary, AS_DICTIONARY(literal)); return; } diff --git a/source/literal.h b/source/literal.h index 0d152c5..1f873ef 100644 --- a/source/literal.h +++ b/source/literal.h @@ -18,6 +18,7 @@ typedef enum { LITERAL_IDENTIFIER, LITERAL_TYPE, LITERAL_TYPE_INTERMEDIATE, //used to process types in the compiler only + LITERAL_DICTIONARY_INTERMEDIATE, //used to process dictionaries in the compiler only LITERAL_FUNCTION_INTERMEDIATE, //used to process functions in the compiler only LITERAL_FUNCTION_ARG_REST, //used to process function rest parameters LITERAL_FUNCTION_NATIVE, //for handling native functions diff --git a/source/literal_util.c b/source/literal_util.c index bcff0c9..65bc97c 100644 --- a/source/literal_util.c +++ b/source/literal_util.c @@ -72,7 +72,7 @@ Literal copyLiteral(Literal original) { return lit; } - case LITERAL_TYPE_INTERMEDIATE: { + case LITERAL_DICTIONARY_INTERMEDIATE: { LiteralArray* array = ALLOCATE(LiteralArray, 1); initLiteralArray(array); @@ -81,6 +81,22 @@ Literal copyLiteral(Literal original) { pushLiteralArray(array, copyLiteral(AS_ARRAY(original)->literals[i])); } + Literal ret = TO_ARRAY_LITERAL(array); + ret.type = LITERAL_DICTIONARY_INTERMEDIATE; + return ret; + } + + case LITERAL_TYPE_INTERMEDIATE: { + LiteralArray* array = ALLOCATE(LiteralArray, 1); + initLiteralArray(array); + + //copy each element + for (int i = 0; i < AS_ARRAY(original)->count; i++) { + Literal literal = copyLiteral(AS_ARRAY(original)->literals[i]); + pushLiteralArray(array, literal ); + freeLiteral(literal); + } + Literal ret = TO_ARRAY_LITERAL(array); ret.type = LITERAL_TYPE_INTERMEDIATE; return ret; @@ -141,6 +157,7 @@ bool literalsAreEqual(Literal lhs, Literal rhs) { return !strncmp(AS_STRING(lhs), AS_STRING(rhs), strlen(AS_STRING(lhs))); case LITERAL_ARRAY: + case LITERAL_DICTIONARY_INTERMEDIATE: //BUGFIX case LITERAL_TYPE_INTERMEDIATE: //BUGFIX: used for storing types as an array //mismatched sizes if (AS_ARRAY(lhs)->count != AS_ARRAY(rhs)->count) { @@ -304,7 +321,7 @@ int hashLiteral(Literal lit) { //utils static void stdoutWrapper(const char* output) { - fprintf(stdout, "%s", output); + printf("%s", output); } //buffer the prints @@ -323,7 +340,7 @@ static void printToBuffer(const char* str) { globalPrintBuffer = GROW_ARRAY(char, globalPrintBuffer, oldCapacity, globalPrintCapacity); } - snprintf(globalPrintBuffer + globalPrintCount, strlen(str) + 1, "%s", str); + snprintf(globalPrintBuffer + globalPrintCount, strlen(str), "%s", str); globalPrintCount += strlen(str); } diff --git a/source/parser.c b/source/parser.c index 532d4d3..1f0049c 100644 --- a/source/parser.c +++ b/source/parser.c @@ -1370,7 +1370,6 @@ static void varDecl(Parser* parser, Node** nodeHandle) { //TODO: static type checking? //declare it - freeNode(*nodeHandle); //free the initial node emitNodeVarDecl(nodeHandle, identifier, typeLiteral, expressionNode); consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of var declaration"); @@ -1515,7 +1514,6 @@ static void fnDecl(Parser* parser, Node** nodeHandle) { blockStmt(parser, &blockNode); //declare it - freeNode(*nodeHandle); //free the initial node, because WTF? emitNodeFnDecl(nodeHandle, identifier, argumentNode, returnNode, blockNode); } diff --git a/test/makefile b/test/makefile index 359b517..47274cf 100644 --- a/test/makefile +++ b/test/makefile @@ -16,7 +16,7 @@ all: $(OBJ) $(TESTS:%.c=../$(OUTDIR)/%.exe) ../$(OUTDIR)/%.exe: $(ODIR)/%.o @$(CC) -o $@ $< $(TARGETS:../source/%.c=$(ODIR)/%.o) $(CFLAGS) $(LIBS) ifeq ($(shell uname),Linux) - valgrind $@ + valgrind --leak-check=full $@ else @echo please run these tests with valgrind on linux endif diff --git a/test/sample_code.toy b/test/sample_code.toy index 65d122e..c5b6211 100644 --- a/test/sample_code.toy +++ b/test/sample_code.toy @@ -1,1018 +1,7 @@ -//single line comment -/* -multi line comment -*/ -//test primitive literals -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print 2 + (3 * 3); -//test operators (integers) -print 1 + 1; -print 1 - 1; -print 2 * 2; -print 1 / 2; -print 4 % 2; -//test operators (floats) -print 1.0 + 1.0; -print 1.0 - 1.0; -print 2.0 * 2.0; -print 1.0 / 2.0; - -//test scopes -{ - print "This statement is within a scope."; - { - print "This is a deeper scope."; - } -} -print "Back to the outer scope."; - -//test scope will delegate to higher scope -var a = 1; -{ - a = 2; - print a; -} -print a; - -//test scope will shadow higher scope on redefine -var b: int = 3; -{ - var b = 4; - print b; -} -print b; - -//test compounds, repeatedly -print [1, 2, 3]; -print [4, 5]; -print ["key":"value"]; -print [1, 2, 3]; -print [4, 5]; -print ["key":"value"]; - -//test empties -print []; -print [:]; - -//test nested compounds -print [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; - -//var declarations -var x = 31; -var y : int = 42; -var arr : [int] = [1, 2, 3, 42]; -var dict : [string, int] = ["hello": 1, "world":2]; - -//printing expressions -print x; -print x + y; -print arr; -print dict; - -//test asserts at the end of the file -assert x, "This won't be seen"; -assert true, "This won't be seen"; -assert false, "This is a failed assert, and will end execution"; - -print "This will not be printed because of the above assert"; - -//test operators (integers) -assert 1 + 1 == 2, "1 + 1 == 2"; -assert 1 - 1 == 0, "1 - 1 == 0"; -assert 2 * 2 == 4, "2 * 2 == 4"; -assert 1 / 2 == 0, "1 / 2 == 0"; //integer division -assert 5 % 2 == 1, "5 % 2 == 1"; - -//test operators (floats) -assert 1.0 + 1.0 == 2.0, "1.0 + 1.0 == 2.0"; -assert 1.0 - 1.0 == 0.0, "1.0 - 1.0 == 0.0"; -assert 2.0 * 2.0 == 4.0, "2.0 * 2.0 == 4.0"; -assert 1.0 / 2.0 == 0.5, "1.0 / 2.0 == 0.5"; - - -var a = 10; - -a += 20; -a -= 25; - -assert a == 5, "+= or -= failed"; - -a *= 5; -a /= 2; - -assert a == 12, "*= or /= failed"; - -a %= 8; - -assert a == 4, "%= failed"; - -print "All good";//test numbers -assert 1 < 2, "1 < 2"; -assert 1 == 1, "1 == 1"; -assert 2 > 1, "2 > 1"; -assert 1 <= 2, "1 <= 2"; -assert 2 >= 1, "2 >= 1"; - - -//test variables -var a = 1; -var b = 2; - -assert a < b, "a < b"; -assert a == a, "a == a"; -assert b > a, "b > a"; -assert a <= b, "a <= b"; -assert b >= a, "b >= a"; - - -//test negation -assert !false, "!false"; - -var c = false; -assert !c, "!c"; - - -print "All good"; -//test true jump -if (true) { - assert true, "if-then failed (1)"; -} -else { - assert false, "if-then failed (2)"; -} - - -//test false jump -if (false) { - assert false, "if-then failed (3)"; -} -else { - assert true, "if-then failed (4)"; -} - - -//test while loop -var whileCounter = 0; -while (whileCounter < 10) { - whileCounter = whileCounter + 1; -} - -assert whileCounter == 10, "while-loop failed"; - - -//test for loop -var forCache = 0; -for (var i = 0; i < 20; i++) { - forCache = i; -} - -assert forCache == 19, "for-loop failed"; - - -//test break - while -var breakWhileCache = 0; -while(true) { - breakWhileCache = breakWhileCache + 1; - - if (breakWhileCache >= 7) { - break; - } -} - -assert breakWhileCache == 7, "break-while failed"; - - -//test continue - while -var continueWhileCache = 0; -while (continueWhileCache < 10) { - continueWhileCache = continueWhileCache + 1; - - if (continueWhileCache >= 7) { - continue; - } - - assert continueWhileCache < 7, "continue-while failed"; -} - - -//test break - for -for (var i = 0; i < 10; i++) { - if (i >= 7) { - break; - } - - assert i < 7, "break-for failed"; -} - - -//test break - continue -for (var i = 0; i < 10; i++) { - if (i >= 7) { - continue; - } - - assert i < 7, "continue-for failed"; -} - -print "All good"; - -var arr: [string] = [ - -"0", -"1", -"2", -"3", -"4", -"5", -"6", -"7", -"8", -"9", - -"10", -"11", -"12", -"13", -"14", -"15", -"16", -"17", -"18", -"19", - -"20", -"21", -"22", -"23", -"24", -"25", -"26", -"27", -"28", -"29", - -"30", -"31", -"32", -"33", -"34", -"35", -"36", -"37", -"38", -"39", - -"40", -"41", -"42", -"43", -"44", -"45", -"46", -"47", -"48", -"49", - -"50", -"51", -"52", -"53", -"54", -"55", -"56", -"57", -"58", -"59", - -"60", -"61", -"62", -"63", -"64", -"65", -"66", -"67", -"68", -"69", - -"70", -"71", -"72", -"73", -"74", -"75", -"76", -"77", -"78", -"79", - -"80", -"81", -"82", -"83", -"84", -"85", -"86", -"87", -"88", -"89", - -"90", -"91", -"92", -"93", -"94", -"95", -"96", -"97", -"98", -"99", - -//------------------------- - -"100", -"101", -"102", -"103", -"104", -"105", -"106", -"107", -"108", -"109", - -"110", -"111", -"112", -"113", -"114", -"115", -"116", -"117", -"118", -"119", - -"120", -"121", -"122", -"123", -"124", -"125", -"126", -"127", -"128", -"129", - -"130", -"131", -"132", -"133", -"134", -"135", -"136", -"137", -"138", -"139", - -"140", -"141", -"142", -"143", -"144", -"145", -"146", -"147", -"148", -"149", - -"150", -"151", -"152", -"153", -"154", -"155", -"156", -"157", -"158", -"159", - -"160", -"161", -"162", -"163", -"164", -"165", -"166", -"167", -"168", -"169", - -"170", -"171", -"172", -"173", -"174", -"175", -"176", -"177", -"178", -"179", - -"180", -"181", -"182", -"183", -"184", -"185", -"186", -"187", -"188", -"189", - -"190", -"191", -"192", -"193", -"194", -"195", -"196", -"197", -"198", -"199", - -//------------------------- - -"200", -"201", -"202", -"203", -"204", -"205", -"206", -"207", -"208", -"209", - -"210", -"211", -"212", -"213", -"214", -"215", -"216", -"217", -"218", -"219", - -"220", -"221", -"222", -"223", -"224", -"225", -"226", -"227", -"228", -"229", - -"230", -"231", -"232", -"233", -"234", -"235", -"236", -"237", -"238", -"239", - -"240", -"241", -"242", -"243", -"244", -"245", -"246", -"247", -"248", -"249", - -"250", -"251", -"252", -"253", -"254", -"255", -"256", -"257", -"258", -"259", - -"260", -"261", -"262", -"263", -"264", -"265", -"266", -"267", -"268", -"269", - -"270", -"271", -"272", -"273", -"274", -"275", -"276", -"277", -"278", -"279", - -"280", -"281", -"282", -"283", -"284", -"285", -"286", -"287", -"288", -"289", - -"290", -"291", -"292", -"293", -"294", -"295", -"296", -"297", -"298", -"299" - -]; - -print arr; - -print 0; -print 1; -print 2; -print 3; -print 4; -print 5; -print 6; -print 7; -print 8; -print 9; - -print 10; -print 11; -print 12; -print 13; -print 14; -print 15; -print 16; -print 17; -print 18; -print 19; - -print 20; -print 21; -print 22; -print 23; -print 24; -print 25; -print 26; -print 27; -print 28; -print 29; - -print 30; -print 31; -print 32; -print 33; -print 34; -print 35; -print 36; -print 37; -print 38; -print 39; - -print 40; -print 41; -print 42; -print 43; -print 44; -print 45; -print 46; -print 47; -print 48; -print 49; - -print 50; -print 51; -print 52; -print 53; -print 54; -print 55; -print 56; -print 57; -print 58; -print 59; - -print 60; -print 61; -print 62; -print 63; -print 64; -print 65; -print 66; -print 67; -print 68; -print 69; - -print 70; -print 71; -print 72; -print 73; -print 74; -print 75; -print 76; -print 77; -print 78; -print 79; - -print 80; -print 81; -print 82; -print 83; -print 84; -print 85; -print 86; -print 87; -print 88; -print 89; - -print 90; -print 91; -print 92; -print 93; -print 94; -print 95; -print 96; -print 97; -print 98; -print 99; - -//------------------------- - -print 100; -print 101; -print 102; -print 103; -print 104; -print 105; -print 106; -print 107; -print 108; -print 109; - -print 110; -print 111; -print 112; -print 113; -print 114; -print 115; -print 116; -print 117; -print 118; -print 119; - -print 120; -print 121; -print 122; -print 123; -print 124; -print 125; -print 126; -print 127; -print 128; -print 129; - -print 130; -print 131; -print 132; -print 133; -print 134; -print 135; -print 136; -print 137; -print 138; -print 139; - -print 140; -print 141; -print 142; -print 143; -print 144; -print 145; -print 146; -print 147; -print 148; -print 149; - -print 150; -print 151; -print 152; -print 153; -print 154; -print 155; -print 156; -print 157; -print 158; -print 159; - -print 160; -print 161; -print 162; -print 163; -print 164; -print 165; -print 166; -print 167; -print 168; -print 169; - -print 170; -print 171; -print 172; -print 173; -print 174; -print 175; -print 176; -print 177; -print 178; -print 179; - -print 180; -print 181; -print 182; -print 183; -print 184; -print 185; -print 186; -print 187; -print 188; -print 189; - -print 190; -print 191; -print 192; -print 193; -print 194; -print 195; -print 196; -print 197; -print 198; -print 199; - -//------------------------- - -print 200; -print 201; -print 202; -print 203; -print 204; -print 205; -print 206; -print 207; -print 208; -print 209; - -print 210; -print 211; -print 212; -print 213; -print 214; -print 215; -print 216; -print 217; -print 218; -print 219; - -print 220; -print 221; -print 222; -print 223; -print 224; -print 225; -print 226; -print 227; -print 228; -print 229; - -print 230; -print 231; -print 232; -print 233; -print 234; -print 235; -print 236; -print 237; -print 238; -print 239; - -print 240; -print 241; -print 242; -print 243; -print 244; -print 245; -print 246; -print 247; -print 248; -print 249; - -print 250; -print 251; -print 252; -print 253; -print 254; -print 255; -print 256; -print 257; -print 258; -print 259; - -print 260; -print 261; -print 262; -print 263; -print 264; -print 265; -print 266; -print 267; -print 268; -print 269; - -print 270; -print 271; -print 272; -print 273; -print 274; -print 275; -print 276; -print 277; -print 278; -print 279; - -print 280; -print 281; -print 282; -print 283; -print 284; -print 285; -print 286; -print 287; -print 288; -print 289; - -print 290; -print 291; -print 292; -print 293; -print 294; -print 295; -print 296; -print 297; -print 298; -print 299; - -//------------------------- - -//boolean origin -var b: bool = true; - -assert (int)b == 1, "bool -> int"; -assert (float)b == 1, "bool -> float"; -assert (string)b == "true", "bool -> string"; - - -//integer origin -var i: int = 42; - -assert (bool)i == true, "int -> bool"; -assert (float)i == 42, "int -> float"; -assert (string)i == "42", "int -> string"; - - -//float origin -var f: float = 3.14; - -assert (bool)f == true, "float -> bool"; -assert (int)f == 3, "float -> int"; -assert (string)f == "3.14", "float -> string"; - - -//string origin -var s: string = "78.9"; - -assert (bool)s == true, "string -> bool"; -assert (int)s == 78, "string -> int"; -assert (float)s == 78.9, "string -> float"; - - -print "All good"; -//test function return -fn testFourtyTwo() { - return 42; -} - -assert testFourtyTwo() == 42, "function returns failed"; - - -//test function parameters -fn identity(x) { - return x; -} - -assert identity("hello world") == "hello world", "identity function failed"; - - -//test closures -fn make() { - var counter = 0; - - fn count() { - return ++counter; - } - - return count; -} - -var tally = make(); - -assert tally() == 1 && tally() == 2, "Closures failed"; - - -//test expressions as arguments -fn argFn() { - return 42; -} - -fn outerFn(val) { - assert val == 42, "expression as argument failed"; -} - -outerFn(argFn()); - - -//test extra parameters -fn extra(one, two, ...rest) { - assert rest == ["three", "four", "five", "six", "seven"], "rest parameters failed"; -} - -extra("one", "two", "three", "four", "five", "six", "seven"); - - - - -print "All good";assert true && true, "boolean and failed"; -assert true || true, "boolean or failed"; - -assert false || true && true, "boolen precedence failed"; - -print "All good"; -//basic types -var t: type = int; -var u: t = 42; - -assert t == int, "types are not first class"; -assert u == 42, "first-class types are screwing with values"; - - -//differentiate by the "type" value -var v: type = type [int]; -var w = [int]; -var x = v; - -assert w == [int], "defining an array of types failed"; -assert x == type [int], "re-assigning a type value failed"; - -//complex type var complex: type = type [string, [int]]; var dict: complex = [ "first array": [1, 2, 3], @@ -1020,4 +9,9 @@ var dict: complex = [ "third array": [7, 8, 9] ]; -print "All good"; + +var deep: type = type [[[ int ]]]; + + + + diff --git a/test/test_compiler.c b/test/test_compiler.c index 0fc720d..949bec4 100644 --- a/test/test_compiler.c +++ b/test/test_compiler.c @@ -96,9 +96,18 @@ int main() { initCompiler(&compiler); Node* node = scanParser(&parser); + while (node != NULL) { + if (node->type == NODE_ERROR) { + fprintf(stderr, ERROR "ERROR: Error node found" RESET); + return -1; + } - //write - writeCompiler(&compiler, node); + //write + writeCompiler(&compiler, node); + freeNode(node); + + node = scanParser(&parser); + } //collate int size = 0; @@ -107,7 +116,6 @@ int main() { //cleanup FREE_ARRAY(char, source, sourceLength); FREE_ARRAY(unsigned char, bytecode, size); - freeNode(node); freeParser(&parser); freeCompiler(&compiler); } diff --git a/test/test_interpreter.c b/test/test_interpreter.c new file mode 100644 index 0000000..7c89aac --- /dev/null +++ b/test/test_interpreter.c @@ -0,0 +1,129 @@ +#include "lexer.h" +#include "parser.h" +#include "compiler.h" +#include "interpreter.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 + Interpreter interpreter; + initInterpreter(&interpreter); + freeInterpreter(&interpreter); + } + + { + //source + char* source = "print null;"; + + //test basic compilation & collation + Lexer lexer; + Parser parser; + Compiler compiler; + Interpreter interpreter; + + initLexer(&lexer, source); + initParser(&parser, &lexer); + initCompiler(&compiler); + initInterpreter(&interpreter); + + Node* node = scanParser(&parser); + + //write + writeCompiler(&compiler, node); + + //collate + int size = 0; + unsigned char* bytecode = collateCompiler(&compiler, &size); + + //run + runInterpreter(&interpreter, bytecode, size); + + //cleanup + freeNode(node); + freeParser(&parser); + freeCompiler(&compiler); + freeInterpreter(&interpreter); + } + + { + //source + size_t sourceLength = 0; + char* source = readFile("sample_code.toy", &sourceLength); + + //test basic compilation & collation + Lexer lexer; + Parser parser; + Compiler compiler; + Interpreter interpreter; + + initLexer(&lexer, source); + initParser(&parser, &lexer); + initCompiler(&compiler); + initInterpreter(&interpreter); + + Node* node = scanParser(&parser); + + //write + writeCompiler(&compiler, node); + + //collate + int size = 0; + unsigned char* bytecode = collateCompiler(&compiler, &size); + + //run + runInterpreter(&interpreter, bytecode, size); + + //cleanup + FREE_ARRAY(char, source, sourceLength); + freeNode(node); + freeParser(&parser); + freeCompiler(&compiler); + freeInterpreter(&interpreter); + } + + printf(NOTICE "All good\n" RESET); + return 0; +} +