diff --git a/scripts/test/long-array.toy b/scripts/test/long-array.toy index f56bcee..6bb7adc 100644 --- a/scripts/test/long-array.toy +++ b/scripts/test/long-array.toy @@ -336,4 +336,4 @@ var arr: [string] = [ ]; -print arr; \ No newline at end of file +print arr; diff --git a/scripts/test/native-functions.toy b/scripts/test/native-functions.toy index 4a82652..59503e0 100644 --- a/scripts/test/native-functions.toy +++ b/scripts/test/native-functions.toy @@ -3,13 +3,15 @@ //test arrays without types var array = []; + assert _length(array) == 0, "_length failed with array"; + _push(array, 1); _push(array, 2); _push(array, 3); _push(array, 4); _push(array, "foo"); - assert _length(array) == 5, "_push or _length failed with array"; + assert _length(array) == 5, "_push failed with array"; assert _pop(array) == "foo", "_pop failed with array"; _set(array, 2, "bar"); @@ -43,13 +45,15 @@ //test arrays with types var array: [int] = []; + assert _length(array) == 0, "_length failed with array (+ types)"; + _push(array, 1); _push(array, 2); _push(array, 3); _push(array, 4); _push(array, 10); - assert _length(array) == 5, "_push or _length failed with array (+ types)"; + assert _length(array) == 5, "_push or failed with array (+ types)"; assert _pop(array) == 10, "_pop failed with array (+ types)"; _set(array, 2, 70); diff --git a/source/compiler.c b/source/compiler.c index 4f19ad0..cbeb60d 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -19,6 +19,8 @@ void initCompiler(Compiler* compiler) { //separated out, so it can be recursive static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal literal, bool skipDuplicationOptimisation) { + bool shouldFree = false; + //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 @@ -38,6 +40,7 @@ static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal litera } //push the store to the cache, tweaking the type + shouldFree = true; literal = TO_ARRAY_LITERAL(store); literal.type = LITERAL_TYPE_INTERMEDIATE; //NOTE: tweaking the type usually isn't a good idea } @@ -49,12 +52,16 @@ static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal litera index = pushLiteralArray(literalCache, literal); } - freeLiteral(literal); + if (shouldFree) { + freeLiteral(literal); + } return index; } else { int index = pushLiteralArray(literalCache, literal); - freeLiteral(literal); + if (shouldFree) { + freeLiteral(literal); + } return index; } } @@ -411,7 +418,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd //embed these in the bytecode... int index = writeNodeCollectionToCache(compiler, node); - compiler->bytecode[compiler->count] = (unsigned short)index; //2 bytes + AS_USHORT(compiler->bytecode[compiler->count]) = (unsigned short)index; //2 bytes compiler->count += sizeof(unsigned short); } break; diff --git a/source/interpreter.c b/source/interpreter.c index bc54c5b..c434043 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -75,6 +75,7 @@ int _set(Interpreter* interpreter, LiteralArray* arguments) { Literal val = arguments->literals[2]; parseIdentifierToValue(interpreter, &obj); + parseIdentifierToValue(interpreter, &key); switch(obj.type) { case LITERAL_ARRAY: { @@ -99,17 +100,8 @@ int _set(Interpreter* interpreter, LiteralArray* arguments) { return -1; } - parseIdentifierToValue(interpreter, &val); - - //if it's a string or an identifier, make a local copy - if (IS_STRING(val)) { - val = TO_STRING_LITERAL(copyString(AS_STRING(val), strlen(AS_STRING(val)) ), strlen(AS_STRING(val))); - } - if (IS_IDENTIFIER(val)) { - val = TO_IDENTIFIER_LITERAL(copyString(AS_IDENTIFIER(val), strlen(AS_IDENTIFIER(val)) ), strlen(AS_STRING(val))); - } - - //TODO: proper copy function for literals + //don't use pushLiteralArray, since we're setting + val = copyLiteral(val); AS_ARRAY(obj)->literals[AS_INTEGER(key)] = val; return 0; @@ -197,6 +189,7 @@ int _push(Interpreter* interpreter, LiteralArray* arguments) { Literal val = arguments->literals[1]; parseIdentifierToValue(interpreter, &obj); + parseIdentifierToValue(interpreter, &val); switch(obj.type) { case LITERAL_ARRAY: { @@ -211,8 +204,6 @@ int _push(Interpreter* interpreter, LiteralArray* arguments) { } } - parseIdentifierToValue(interpreter, &val); - pushLiteralArray(AS_ARRAY(obj), val); return 0; } @@ -261,17 +252,25 @@ int _length(Interpreter* interpreter, LiteralArray* arguments) { switch(obj.type) { case LITERAL_ARRAY: { - pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( AS_ARRAY(obj)->count )); + Literal lit = TO_INTEGER_LITERAL( AS_ARRAY(obj)->count ); + pushLiteralArray(&interpreter->stack, lit); + freeLiteral(lit); return 1; } - case LITERAL_DICTIONARY: - pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( AS_DICTIONARY(obj)->count )); + case LITERAL_DICTIONARY: { + Literal lit = TO_INTEGER_LITERAL( AS_DICTIONARY(obj)->count ); + pushLiteralArray(&interpreter->stack, lit); + freeLiteral(lit); return 1; + } - case LITERAL_STRING: - pushLiteralArray(&interpreter->stack, TO_INTEGER_LITERAL( strlen(AS_STRING(obj)) )); + case LITERAL_STRING: { + Literal lit = TO_INTEGER_LITERAL( strlen(AS_STRING(obj)) ); + pushLiteralArray(&interpreter->stack, lit); + freeLiteral(lit); return 1; + } default: (interpreter->printOutput)("Incorrect compound type in _length"); @@ -703,7 +702,6 @@ static bool execVarDecl(Interpreter* interpreter, bool lng) { return false; } - freeLiteral(type); freeLiteral(val); return true; @@ -727,7 +725,7 @@ static bool execFnDecl(Interpreter* interpreter, bool lng) { Literal identifier = interpreter->literalCache.literals[identifierIndex]; Literal function = interpreter->literalCache.literals[functionIndex]; - function.as.function.scope = scope; //hacked in + function.as.function.scope = pushScope(scope); //hacked in Literal type = TO_TYPE_LITERAL(LITERAL_FUNCTION, true); @@ -1153,6 +1151,7 @@ static bool execFnCall(Interpreter* interpreter) { inner.bytecode = AS_FUNCTION(func).bytecode; inner.length = func.as.function.length; inner.count = 0; + inner.panic = false; initLiteralArray(&inner.stack); setInterpreterPrint(&inner, interpreter->printOutput); setInterpreterAssert(&inner, interpreter->assertOutput); @@ -1178,6 +1177,7 @@ static bool execFnCall(Interpreter* interpreter) { //free, and skip out freeLiteralArray(&arguments); + popScope(inner.scope); freeInterpreter(&inner); return false; @@ -1190,6 +1190,7 @@ static bool execFnCall(Interpreter* interpreter) { printf(ERROR "[internal] Could not re-declare parameter\n" RESET); //free, and skip out freeLiteralArray(&arguments); + popScope(inner.scope); freeInterpreter(&inner); return false; } @@ -1198,6 +1199,7 @@ static bool execFnCall(Interpreter* interpreter) { printf(ERROR "[internal] Could not define parameter (bad type?)\n" RESET); //free, and skip out freeLiteralArray(&arguments); + popScope(inner.scope); freeInterpreter(&inner); return false; } @@ -1222,6 +1224,7 @@ static bool execFnCall(Interpreter* interpreter) { freeLiteral(restType); freeLiteralArray(&rest); freeLiteralArray(&arguments); + popScope(inner.scope); freeInterpreter(&inner); return false; } @@ -1232,6 +1235,7 @@ static bool execFnCall(Interpreter* interpreter) { freeLiteral(restType); freeLiteralArray(&rest); freeLiteralArray(&arguments); + popScope(inner.scope); freeInterpreter(&inner); return false; } @@ -1249,7 +1253,9 @@ static bool execFnCall(Interpreter* interpreter) { //unpack the results while (inner.stack.count > 0) { - pushLiteralArray(&returns, popLiteralArray(&inner.stack)); //NOTE: also reverses the order + Literal lit = popLiteralArray(&inner.stack); + pushLiteralArray(&returns, lit); //NOTE: also reverses the order + freeLiteral(lit); } //TODO: remove this when multiple assignment is enabled - note the BUGFIX that balances the stack @@ -1281,6 +1287,7 @@ static bool execFnCall(Interpreter* interpreter) { } pushLiteralArray(&interpreter->stack, ret); //NOTE: reverses again + freeLiteral(ret); } //free @@ -1306,7 +1313,9 @@ static bool execFnReturn(Interpreter* interpreter) { //and back again while (returns.count > 0) { - pushLiteralArray(&interpreter->stack, popLiteralArray(&returns)); + Literal lit = popLiteralArray(&returns); + pushLiteralArray(&interpreter->stack, lit); + freeLiteral(lit); } freeLiteralArray(&returns); @@ -1700,7 +1709,7 @@ static void readInterpreterSections(Interpreter* interpreter) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY) { unsigned short vt = readShort(interpreter->bytecode, &interpreter->count); - TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[vt]); + TYPE_PUSH_SUBTYPE(&typeLiteral, copyLiteral(interpreter->literalCache.literals[vt])); } if (AS_TYPE(typeLiteral).typeOf == LITERAL_DICTIONARY) { @@ -1720,7 +1729,7 @@ static void readInterpreterSections(Interpreter* interpreter) { printf(")\n"); } - freeLiteral(typeLiteral); + // freeLiteral(typeLiteral); } break; } diff --git a/source/literal_util.c b/source/literal_util.c index 65bc97c..7ef897e 100644 --- a/source/literal_util.c +++ b/source/literal_util.c @@ -78,7 +78,9 @@ Literal copyLiteral(Literal original) { //copy each element for (int i = 0; i < AS_ARRAY(original)->count; i++) { - pushLiteralArray(array, copyLiteral(AS_ARRAY(original)->literals[i])); + Literal literal = copyLiteral(AS_ARRAY(original)->literals[i]); + pushLiteralArray(array, literal); + freeLiteral(literal); } Literal ret = TO_ARRAY_LITERAL(array); @@ -93,7 +95,7 @@ Literal copyLiteral(Literal original) { //copy each element for (int i = 0; i < AS_ARRAY(original)->count; i++) { Literal literal = copyLiteral(AS_ARRAY(original)->literals[i]); - pushLiteralArray(array, literal ); + pushLiteralArray(array, literal); freeLiteral(literal); } diff --git a/source/memory.c b/source/memory.c index 9e9acb2..0a444da 100644 --- a/source/memory.c +++ b/source/memory.c @@ -6,6 +6,11 @@ #include void* reallocate(void* pointer, size_t oldSize, size_t newSize) { + if (newSize == 0 && oldSize == 0) { + //causes issues, so just skip out with a NO-OP + return NULL; + } + if (newSize == 0) { free(pointer); diff --git a/source/scope.c b/source/scope.c index d907292..00dd039 100644 --- a/source/scope.c +++ b/source/scope.c @@ -121,6 +121,10 @@ Scope* pushScope(Scope* ancestor) { } Scope* popScope(Scope* scope) { + if (scope == NULL) { //CAN pop a null + return NULL; + } + Scope* ret = scope->ancestor; freeAncestorChain(scope); diff --git a/test/makefile b/test/makefile index 47274cf..d171f9e 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 --leak-check=full $@ + valgrind --leak-check=full --track-origins=yes $@ else @echo please run these tests with valgrind on linux endif