diff --git a/src/wren_compiler.c b/src/wren_compiler.c index 3d44ea80..6313c72a 100644 --- a/src/wren_compiler.c +++ b/src/wren_compiler.c @@ -44,9 +44,6 @@ // extra spaces added to handle arity, and another byte to terminate the string. #define MAX_METHOD_SIGNATURE (MAX_METHOD_NAME + MAX_PARAMETERS + 1) -// TODO: Get rid of this and use a growable buffer. -#define MAX_STRING (1024) - typedef enum { TOKEN_LEFT_PAREN, @@ -885,7 +882,8 @@ static int declareVariable(Compiler* compiler) { SymbolTable* symbols = &compiler->parser->vm->globalSymbols; - int symbol = addSymbol(symbols, token->start, token->length); + int symbol = addSymbol(compiler->parser->vm, symbols, + token->start, token->length); if (symbol == -1) { error(compiler, "Global variable is already defined."); @@ -1282,7 +1280,8 @@ static void methodCall(Compiler* compiler, Code instruction, consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments."); } - int symbol = ensureSymbol(&compiler->parser->vm->methods, name, length); + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, name, length); emit1(compiler, instruction + numArgs, symbol); } @@ -1307,7 +1306,8 @@ static void namedCall(Compiler* compiler, bool allowAssignment, // Compile the assigned value. expression(compiler); - int symbol = ensureSymbol(&compiler->parser->vm->methods, name, length); + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, name, length); emit1(compiler, instruction + 1, symbol); } else @@ -1363,7 +1363,8 @@ static void unaryOp(Compiler* compiler, bool allowAssignment) parsePrecedence(compiler, false, PREC_UNARY + 1); // Call the operator method on the left-hand side. - int symbol = ensureSymbol(&compiler->parser->vm->methods, rule->name, 1); + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, rule->name, 1); emit1(compiler, CODE_CALL_0, symbol); } @@ -1405,7 +1406,7 @@ static void field(Compiler* compiler, bool allowAssignment) if (compiler->fields != NULL) { // Look up the field, or implicitly define it. - field = ensureSymbol(compiler->fields, + field = ensureSymbol(compiler->parser->vm, compiler->fields, compiler->parser->previous.start, compiler->parser->previous.length); } @@ -1641,7 +1642,8 @@ static void subscript(Compiler* compiler, bool allowAssignment) expression(compiler); } - int symbol = ensureSymbol(&compiler->parser->vm->methods, name, length); + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, name, length); // Compile the method call. emit1(compiler, CODE_CALL_0 + numArgs, symbol); @@ -1684,7 +1686,8 @@ void infixOp(Compiler* compiler, bool allowAssignment) parsePrecedence(compiler, false, rule->precedence + 1); // Call the operator method on the left-hand side. - int symbol = ensureSymbol(&compiler->parser->vm->methods, + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, rule->name, strlen(rule->name)); emit1(compiler, CODE_CALL_1, symbol); } @@ -1860,7 +1863,8 @@ void method(Compiler* compiler, Code instruction, bool isConstructor, // Compile the method signature. signature(&methodCompiler, name, &length); - int symbol = ensureSymbol(&compiler->parser->vm->methods, name, length); + int symbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, name, length); consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' to begin method body."); @@ -2038,7 +2042,8 @@ static void forStatement(Compiler* compiler) emit1(compiler, CODE_LOAD_LOCAL, seqSlot); emit1(compiler, CODE_LOAD_LOCAL, iterSlot); - int iterateSymbol = ensureSymbol(&compiler->parser->vm->methods, + int iterateSymbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, "iterate ", 8); emit1(compiler, CODE_CALL_1, iterateSymbol); @@ -2056,7 +2061,8 @@ static void forStatement(Compiler* compiler) emit1(compiler, CODE_LOAD_LOCAL, seqSlot); emit1(compiler, CODE_LOAD_LOCAL, iterSlot); - int iteratorValueSymbol = ensureSymbol(&compiler->parser->vm->methods, + int iteratorValueSymbol = ensureSymbol(compiler->parser->vm, + &compiler->parser->vm->methods, "iteratorValue ", 14); emit1(compiler, CODE_CALL_1, iteratorValueSymbol); diff --git a/src/wren_core.c b/src/wren_core.c index 5ded7786..5c073407 100644 --- a/src/wren_core.c +++ b/src/wren_core.c @@ -11,7 +11,7 @@ // [fn] to `ObjClass` [cls]. #define NATIVE(cls, name, fn) \ { \ - int symbol = ensureSymbol(&vm->methods, name, strlen(name)); \ + int symbol = ensureSymbol(vm, &vm->methods, name, strlen(name)); \ cls->methods[symbol].type = METHOD_PRIMITIVE; \ cls->methods[symbol].primitive = native_##fn; \ } @@ -22,7 +22,7 @@ // pushing callframes. #define FIBER_NATIVE(cls, name, fn) \ { \ - int symbol = ensureSymbol(&vm->methods, name, strlen(name)); \ + int symbol = ensureSymbol(vm, &vm->methods, name, strlen(name)); \ cls->methods[symbol].type = METHOD_FIBER; \ cls->methods[symbol].fiberPrimitive = native_##fn; \ } @@ -477,7 +477,7 @@ DEF_NATIVE(os_clock) static ObjClass* defineClass(WrenVM* vm, const char* name) { ObjClass* classObj = wrenNewClass(vm, vm->objectClass, 0); - int symbol = addSymbol(&vm->globalSymbols, name, strlen(name)); + int symbol = addSymbol(vm, &vm->globalSymbols, name, strlen(name)); vm->globals[symbol] = OBJ_VAL(classObj); return classObj; } @@ -487,7 +487,8 @@ void wrenInitializeCore(WrenVM* vm) // Define the root Object class. This has to be done a little specially // because it has no superclass and an unusual metaclass (Class). vm->objectClass = wrenNewSingleClass(vm, 0); - int objectSymbol = addSymbol(&vm->globalSymbols, "Object", strlen("Object")); + int objectSymbol = addSymbol(vm, &vm->globalSymbols, + "Object", strlen("Object")); vm->globals[objectSymbol] = OBJ_VAL(vm->objectClass); NATIVE(vm->objectClass, "== ", object_eqeq); @@ -499,7 +500,8 @@ void wrenInitializeCore(WrenVM* vm) // Now we can define Class, which is a subclass of Object, but Object's // metaclass. vm->classClass = wrenNewSingleClass(vm, 0); - int classSymbol = addSymbol(&vm->globalSymbols, "Class", strlen("Class")); + int classSymbol = addSymbol(vm, &vm->globalSymbols, + "Class", strlen("Class")); vm->globals[classSymbol] = OBJ_VAL(vm->classClass); // Now that Object and Class are defined, we can wire them up to each other. diff --git a/src/wren_vm.c b/src/wren_vm.c index e634c9e5..7237af41 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -70,10 +70,9 @@ WrenVM* wrenNewVM(WrenConfiguration* configuration) void wrenFreeVM(WrenVM* vm) { - clearSymbolTable(&vm->methods); - clearSymbolTable(&vm->globalSymbols); - // TODO: Use VM's allocate fn. - free(vm); + clearSymbolTable(vm, &vm->methods); + clearSymbolTable(vm, &vm->globalSymbols); + wrenReallocate(vm, vm, 0, 0); } static void collectGarbage(WrenVM* vm); @@ -416,52 +415,42 @@ void initSymbolTable(SymbolTable* symbols) symbols->count = 0; } -void clearSymbolTable(SymbolTable* symbols) +void clearSymbolTable(WrenVM* vm, SymbolTable* symbols) { for (int i = 0; i < symbols->count; i++) { - // TODO: Use VM's allocate fn. - free(symbols->names[i]); + wrenReallocate(vm, symbols->names[i], 0, 0); } } -void truncateSymbolTable(SymbolTable* symbols, int count) +static int addSymbolUnchecked(WrenVM* vm, SymbolTable* symbols, + const char* name, size_t length) { - ASSERT(count <= symbols->count, "Cannot truncate to larger size."); - for (int i = count; i < symbols->count; i++) - { - // TODO: Use VM's allocate fn. - free(symbols->names[i]); - } - symbols->count = count; -} - -int addSymbolUnchecked(SymbolTable* symbols, const char* name, size_t length) -{ - // TODO: Get rid of explicit malloc here. - symbols->names[symbols->count] = malloc(length + 1); + symbols->names[symbols->count] = wrenReallocate(vm, NULL, 0, + sizeof(char) * (length + 1)); strncpy(symbols->names[symbols->count], name, length); symbols->names[symbols->count][length] = '\0'; return symbols->count++; } -int addSymbol(SymbolTable* symbols, const char* name, size_t length) +int addSymbol(WrenVM* vm, SymbolTable* symbols, const char* name, size_t length) { // If already present, return an error. if (findSymbol(symbols, name, length) != -1) return -1; - return addSymbolUnchecked(symbols, name, length); + return addSymbolUnchecked(vm, symbols, name, length); } -int ensureSymbol(SymbolTable* symbols, const char* name, size_t length) +int ensureSymbol(WrenVM* vm, SymbolTable* symbols, + const char* name, size_t length) { // See if the symbol is already defined. int existing = findSymbol(symbols, name, length); if (existing != -1) return existing; // New symbol, so add it. - return addSymbolUnchecked(symbols, name, length); + return addSymbolUnchecked(vm, symbols, name, length); } int findSymbol(SymbolTable* symbols, const char* name, size_t length) diff --git a/src/wren_vm.h b/src/wren_vm.h index dc76d30b..70dcd913 100644 --- a/src/wren_vm.h +++ b/src/wren_vm.h @@ -284,20 +284,19 @@ void unpinObj(WrenVM* vm); // Initializes the symbol table. void initSymbolTable(SymbolTable* symbols); -// Removes any symbols added after [count] symbols were defined. -void truncateSymbolTable(SymbolTable* symbols, int count); - // Frees all dynamically allocated memory used by the symbol table, but not the // SymbolTable itself. -void clearSymbolTable(SymbolTable* symbols); +void clearSymbolTable(WrenVM* vm, SymbolTable* symbols); // Adds name to the symbol table. Returns the index of it in the table. Returns // -1 if the symbol is already present. -int addSymbol(SymbolTable* symbols, const char* name, size_t length); +int addSymbol(WrenVM* vm, SymbolTable* symbols, + const char* name, size_t length); // Adds name to the symbol table. Returns the index of it in the table. Will // use an existing symbol if already present. -int ensureSymbol(SymbolTable* symbols, const char* name, size_t length); +int ensureSymbol(WrenVM* vm, SymbolTable* symbols, + const char* name, size_t length); // Looks up name in the symbol table. Returns its index if found or -1 if not. int findSymbol(SymbolTable* symbols, const char* name, size_t length);