forked from Mirror/wren
Merge branch 'unify_string' of https://github.com/mhermier/wren into mhermier-unify_string
This commit is contained in:
@ -52,9 +52,7 @@ void metaGetModuleVariables(WrenVM* vm) {
|
||||
|
||||
for (int i = 0; i < names->elements.count; i++)
|
||||
{
|
||||
String* name = &module->variableNames.data[i];
|
||||
names->elements.data[i] = wrenNewStringLength(vm,
|
||||
name->buffer, name->length);
|
||||
names->elements.data[i] = OBJ_VAL(module->variableNames.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -199,4 +199,17 @@
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct sObjClass ObjClass;
|
||||
typedef struct sObjClosure ObjClosure;
|
||||
typedef struct sObjFiber ObjFiber;
|
||||
typedef struct sObjForeign ObjForeign;
|
||||
typedef struct sObjFn ObjFn;
|
||||
typedef struct sObjInstance ObjInstance;
|
||||
typedef struct sObjList ObjList;
|
||||
typedef struct sObjMap ObjMap;
|
||||
typedef struct sObjModule ObjModule;
|
||||
typedef struct sObjRange ObjRange;
|
||||
typedef struct sObjString ObjString;
|
||||
typedef struct sObjUpvalue ObjUpvalue;
|
||||
|
||||
#endif
|
||||
|
||||
@ -3487,8 +3487,8 @@ ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
|
||||
{
|
||||
// Synthesize a token for the original use site.
|
||||
parser.previous.type = TOKEN_NAME;
|
||||
parser.previous.start = parser.module->variableNames.data[i].buffer;
|
||||
parser.previous.length = parser.module->variableNames.data[i].length;
|
||||
parser.previous.start = parser.module->variableNames.data[i]->value;
|
||||
parser.previous.length = parser.module->variableNames.data[i]->length;
|
||||
parser.previous.line = (int)AS_NUM(parser.module->variables.data[i]);
|
||||
error(&compiler, "Variable is used but not defined.");
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int slot = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "LOAD_MODULE_VAR", slot,
|
||||
fn->module->variableNames.data[slot].buffer);
|
||||
fn->module->variableNames.data[slot]->value);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int slot = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "STORE_MODULE_VAR", slot,
|
||||
fn->module->variableNames.data[slot].buffer);
|
||||
fn->module->variableNames.data[slot]->value);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
int numArgs = bytecode[i - 1] - CODE_CALL_0;
|
||||
int symbol = READ_SHORT();
|
||||
printf("CALL_%-11d %5d '%s'\n", numArgs, symbol,
|
||||
vm->methodNames.data[symbol].buffer);
|
||||
vm->methodNames.data[symbol]->value);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
int symbol = READ_SHORT();
|
||||
int superclass = READ_SHORT();
|
||||
printf("SUPER_%-10d %5d '%s' %5d\n", numArgs, symbol,
|
||||
vm->methodNames.data[symbol].buffer, superclass);
|
||||
vm->methodNames.data[symbol]->value, superclass);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int symbol = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "METHOD_INSTANCE", symbol,
|
||||
vm->methodNames.data[symbol].buffer);
|
||||
vm->methodNames.data[symbol]->value);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -309,7 +309,7 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int symbol = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "METHOD_STATIC", symbol,
|
||||
vm->methodNames.data[symbol].buffer);
|
||||
vm->methodNames.data[symbol]->value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
DEFINE_BUFFER(Byte, uint8_t);
|
||||
DEFINE_BUFFER(Int, int);
|
||||
DEFINE_BUFFER(String, String);
|
||||
DEFINE_BUFFER(String, ObjString*);
|
||||
|
||||
void wrenSymbolTableInit(SymbolTable* symbols)
|
||||
{
|
||||
@ -14,24 +14,18 @@ void wrenSymbolTableInit(SymbolTable* symbols)
|
||||
|
||||
void wrenSymbolTableClear(WrenVM* vm, SymbolTable* symbols)
|
||||
{
|
||||
for (int i = 0; i < symbols->count; i++)
|
||||
{
|
||||
DEALLOCATE(vm, symbols->data[i].buffer);
|
||||
}
|
||||
|
||||
wrenStringBufferClear(vm, symbols);
|
||||
}
|
||||
|
||||
int wrenSymbolTableAdd(WrenVM* vm, SymbolTable* symbols,
|
||||
const char* name, size_t length)
|
||||
{
|
||||
String symbol;
|
||||
symbol.buffer = ALLOCATE_ARRAY(vm, char, length + 1);
|
||||
memcpy(symbol.buffer, name, length);
|
||||
symbol.buffer[length] = '\0';
|
||||
symbol.length = (int)length;
|
||||
|
||||
ObjString* symbol = AS_STRING(wrenNewStringLength(vm, name, length));
|
||||
|
||||
wrenPushRoot(vm, &symbol->obj);
|
||||
wrenStringBufferWrite(vm, symbols, symbol);
|
||||
wrenPopRoot(vm); // symbol
|
||||
|
||||
return symbols->count - 1;
|
||||
}
|
||||
|
||||
@ -46,20 +40,30 @@ int wrenSymbolTableEnsure(WrenVM* vm, SymbolTable* symbols,
|
||||
return wrenSymbolTableAdd(vm, symbols, name, length);
|
||||
}
|
||||
|
||||
int wrenSymbolTableFind(const SymbolTable* symbols,
|
||||
const char* name, size_t length)
|
||||
int wrenSymbolTableFind(const SymbolTable* symbols,
|
||||
const char* name, size_t length)
|
||||
{
|
||||
// See if the symbol is already defined.
|
||||
// TODO: O(n). Do something better.
|
||||
for (int i = 0; i < symbols->count; i++)
|
||||
{
|
||||
if (symbols->data[i].length == length &&
|
||||
memcmp(symbols->data[i].buffer, name, length) == 0) return i;
|
||||
if(wrenStringEqualStrLength(symbols->data[i], name, length)) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void wrenBlackenSymbolTable(WrenVM* vm, SymbolTable* symbolTable)
|
||||
{
|
||||
for (int i = 0; i < symbolTable->count; i++)
|
||||
{
|
||||
wrenGrayObj(vm, &symbolTable->data[i]->obj);
|
||||
}
|
||||
|
||||
// Keep track of how much memory is still in use.
|
||||
vm->bytesAllocated += symbolTable->capacity * sizeof(*symbolTable->data);
|
||||
}
|
||||
|
||||
int wrenUtf8EncodeNumBytes(int value)
|
||||
{
|
||||
ASSERT(value >= 0, "Cannot encode a negative value.");
|
||||
|
||||
@ -6,13 +6,6 @@
|
||||
|
||||
// Reusable data structures and other utility functions.
|
||||
|
||||
// A simple structure to keep track of a string and its length (including the
|
||||
// null-terminator).
|
||||
typedef struct {
|
||||
char* buffer;
|
||||
uint32_t length;
|
||||
} String;
|
||||
|
||||
// We need buffers of a few different types. To avoid lots of casting between
|
||||
// void* and back, we'll use the preprocessor as a poor man's generics and let
|
||||
// it generate a few type-specific ones.
|
||||
@ -68,7 +61,7 @@ typedef struct {
|
||||
|
||||
DECLARE_BUFFER(Byte, uint8_t);
|
||||
DECLARE_BUFFER(Int, int);
|
||||
DECLARE_BUFFER(String, String);
|
||||
DECLARE_BUFFER(String, ObjString*);
|
||||
|
||||
// TODO: Change this to use a map.
|
||||
typedef StringBuffer SymbolTable;
|
||||
@ -90,8 +83,10 @@ int wrenSymbolTableEnsure(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 wrenSymbolTableFind(const SymbolTable* symbols,
|
||||
const char* name, size_t length);
|
||||
int wrenSymbolTableFind(const SymbolTable* symbols,
|
||||
const char* name, size_t length);
|
||||
|
||||
void wrenBlackenSymbolTable(WrenVM* vm, SymbolTable* symbolTable);
|
||||
|
||||
// Returns the number of bytes needed to encode [value] in UTF-8.
|
||||
//
|
||||
|
||||
@ -1141,11 +1141,12 @@ static void blackenModule(WrenVM* vm, ObjModule* module)
|
||||
wrenGrayValue(vm, module->variables.data[i]);
|
||||
}
|
||||
|
||||
wrenBlackenSymbolTable(vm, &module->variableNames);
|
||||
|
||||
wrenGrayObj(vm, (Obj*)module->name);
|
||||
|
||||
// Keep track of how much memory is still in use.
|
||||
vm->bytesAllocated += sizeof(ObjModule);
|
||||
// TODO: Track memory for symbol table and buffer.
|
||||
}
|
||||
|
||||
static void blackenRange(WrenVM* vm, ObjRange* range)
|
||||
@ -1298,11 +1299,7 @@ bool wrenValuesEqual(Value a, Value b)
|
||||
|
||||
case OBJ_STRING:
|
||||
{
|
||||
ObjString* aString = (ObjString*)aObj;
|
||||
ObjString* bString = (ObjString*)bObj;
|
||||
return aString->length == bString->length &&
|
||||
aString->hash == bString->hash &&
|
||||
memcmp(aString->value, bString->value, aString->length) == 0;
|
||||
return wrenStringsEqual((ObjString*)aObj, (ObjString*)bObj);
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define wren_value_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wren_common.h"
|
||||
#include "wren_utils.h"
|
||||
@ -99,10 +100,9 @@ typedef enum {
|
||||
OBJ_UPVALUE
|
||||
} ObjType;
|
||||
|
||||
typedef struct sObjClass ObjClass;
|
||||
|
||||
// Base struct for all heap-allocated objects.
|
||||
typedef struct sObj
|
||||
typedef struct sObj Obj;
|
||||
struct sObj
|
||||
{
|
||||
ObjType type;
|
||||
bool isDark;
|
||||
@ -112,7 +112,7 @@ typedef struct sObj
|
||||
|
||||
// The next object in the linked list of all currently allocated objects.
|
||||
struct sObj* next;
|
||||
} Obj;
|
||||
};
|
||||
|
||||
#if WREN_NAN_TAGGING
|
||||
|
||||
@ -145,7 +145,7 @@ typedef struct
|
||||
DECLARE_BUFFER(Value, Value);
|
||||
|
||||
// A heap-allocated string object.
|
||||
typedef struct
|
||||
struct sObjString
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -157,7 +157,7 @@ typedef struct
|
||||
|
||||
// Inline array of the string's bytes followed by a null terminator.
|
||||
char value[FLEXIBLE_ARRAY];
|
||||
} ObjString;
|
||||
};
|
||||
|
||||
// The dynamically allocated data structure for a variable that has been used
|
||||
// by a closure. Whenever a function accesses a variable declared in an
|
||||
@ -171,7 +171,7 @@ typedef struct
|
||||
// be closed. When that happens, the value gets copied off the stack into the
|
||||
// upvalue itself. That way, it can have a longer lifetime than the stack
|
||||
// variable.
|
||||
typedef struct sUpvalue
|
||||
struct sObjUpvalue
|
||||
{
|
||||
// The object header. Note that upvalues have this because they are garbage
|
||||
// collected, but they are not first class Wren objects.
|
||||
@ -187,8 +187,8 @@ typedef struct sUpvalue
|
||||
|
||||
// Open upvalues are stored in a linked list by the fiber. This points to the
|
||||
// next upvalue in that list.
|
||||
struct sUpvalue* next;
|
||||
} ObjUpvalue;
|
||||
struct sObjUpvalue* next;
|
||||
};
|
||||
|
||||
// The type of a primitive function.
|
||||
//
|
||||
@ -217,7 +217,7 @@ typedef struct
|
||||
//
|
||||
// While this is an Obj and is managed by the GC, it never appears as a
|
||||
// first-class object in Wren.
|
||||
typedef struct
|
||||
struct sObjModule
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -230,7 +230,7 @@ typedef struct
|
||||
|
||||
// The name of the module.
|
||||
ObjString* name;
|
||||
} ObjModule;
|
||||
};
|
||||
|
||||
// A function object. It wraps and owns the bytecode and other debug information
|
||||
// for a callable chunk of code.
|
||||
@ -240,7 +240,7 @@ typedef struct
|
||||
// representation of a function. This isn't strictly necessary if they function
|
||||
// has no upvalues, but lets the rest of the VM assume all called objects will
|
||||
// be closures.
|
||||
typedef struct
|
||||
struct sObjFn
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -261,11 +261,11 @@ typedef struct
|
||||
// only be set for fns, and not ObjFns that represent methods or scripts.
|
||||
int arity;
|
||||
FnDebug* debug;
|
||||
} ObjFn;
|
||||
};
|
||||
|
||||
// An instance of a first-class function and the environment it has closed over.
|
||||
// Unlike [ObjFn], this has captured the upvalues that the function accesses.
|
||||
typedef struct
|
||||
struct sObjClosure
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -274,7 +274,7 @@ typedef struct
|
||||
|
||||
// The upvalues this function has closed over.
|
||||
ObjUpvalue* upvalues[FLEXIBLE_ARRAY];
|
||||
} ObjClosure;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -291,7 +291,7 @@ typedef struct
|
||||
Value* stackStart;
|
||||
} CallFrame;
|
||||
|
||||
typedef struct sObjFiber
|
||||
struct sObjFiber
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -333,7 +333,7 @@ typedef struct sObjFiber
|
||||
// In that case, if this fiber fails with an error, the error will be given
|
||||
// to the caller.
|
||||
bool callerIsTrying;
|
||||
} ObjFiber;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -395,25 +395,25 @@ struct sObjClass
|
||||
ObjString* name;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct sObjForeign
|
||||
{
|
||||
Obj obj;
|
||||
uint8_t data[FLEXIBLE_ARRAY];
|
||||
} ObjForeign;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct sObjInstance
|
||||
{
|
||||
Obj obj;
|
||||
Value fields[FLEXIBLE_ARRAY];
|
||||
} ObjInstance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct sObjList
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
// The elements in the list.
|
||||
ValueBuffer elements;
|
||||
} ObjList;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -443,7 +443,7 @@ typedef struct
|
||||
// for a key, we will continue past tombstones, because the desired key may be
|
||||
// found after them if the key that was removed was part of a prior collision.
|
||||
// When the array gets resized, all tombstones are discarded.
|
||||
typedef struct
|
||||
struct sObjMap
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -455,9 +455,9 @@ typedef struct
|
||||
|
||||
// Pointer to a contiguous array of [capacity] entries.
|
||||
MapEntry* entries;
|
||||
} ObjMap;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct sObjRange
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
@ -469,7 +469,7 @@ typedef struct
|
||||
|
||||
// True if [to] is included in the range.
|
||||
bool isInclusive;
|
||||
} ObjRange;
|
||||
};
|
||||
|
||||
// An IEEE 754 double-precision float is a 64-bit value with bits laid out like:
|
||||
//
|
||||
@ -782,6 +782,22 @@ static inline bool wrenValuesSame(Value a, Value b)
|
||||
// other values are equal if they are identical objects.
|
||||
bool wrenValuesEqual(Value a, Value b);
|
||||
|
||||
// Returns true is [a] and [str] represent the same string.
|
||||
static inline bool wrenStringEqualStrLength(const ObjString* a,
|
||||
const char* str, size_t length)
|
||||
{
|
||||
return a->length == length &&
|
||||
memcmp(a->value, str, length) == 0;
|
||||
}
|
||||
|
||||
// Returns true is [a] and [b] represent the same string.
|
||||
static inline bool wrenStringsEqual(const ObjString* a, const ObjString* b)
|
||||
{
|
||||
return a == b ||
|
||||
(a->hash == b->hash &&
|
||||
wrenStringEqualStrLength(a, b->value, b->length));
|
||||
}
|
||||
|
||||
// Returns true if [value] is a bool. Do not call this directly, instead use
|
||||
// [IS_BOOL].
|
||||
static inline bool wrenIsBool(Value value)
|
||||
|
||||
@ -150,6 +150,9 @@ void wrenCollectGarbage(WrenVM* vm)
|
||||
// Any object the compiler is using (if there is one).
|
||||
if (vm->compiler != NULL) wrenMarkCompiler(vm, vm->compiler);
|
||||
|
||||
// Method names.
|
||||
wrenBlackenSymbolTable(vm, &vm->methodNames);
|
||||
|
||||
// Now that we have grayed the roots, do a depth-first search over all of the
|
||||
// reachable objects.
|
||||
wrenBlackenObjects(vm);
|
||||
@ -420,7 +423,7 @@ static void runtimeError(WrenVM* vm)
|
||||
static void methodNotFound(WrenVM* vm, ObjClass* classObj, int symbol)
|
||||
{
|
||||
vm->fiber->error = wrenStringFormat(vm, "@ does not implement '$'.",
|
||||
OBJ_VAL(classObj->name), vm->methodNames.data[symbol].buffer);
|
||||
OBJ_VAL(classObj->name), vm->methodNames.data[symbol]->value);
|
||||
}
|
||||
|
||||
// Checks that [value], which must be a closure, does not require more
|
||||
@ -492,8 +495,8 @@ static ObjClosure* compileInModule(WrenVM* vm, Value name, const char* source,
|
||||
for (int i = 0; i < coreModule->variables.count; i++)
|
||||
{
|
||||
wrenDefineVariable(vm, module,
|
||||
coreModule->variableNames.data[i].buffer,
|
||||
coreModule->variableNames.data[i].length,
|
||||
coreModule->variableNames.data[i]->value,
|
||||
coreModule->variableNames.data[i]->length,
|
||||
coreModule->variables.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user