autoformatting
This commit is contained in:
502
src/vm.c
502
src/vm.c
@@ -4,154 +4,154 @@
|
||||
#include <stdio.h>
|
||||
|
||||
const noomV_Value noomV_nil = {
|
||||
.tag = NOOMV_VNIL,
|
||||
.isptr = 0,
|
||||
.autoclose = 0,
|
||||
.tag = NOOMV_VNIL,
|
||||
.isptr = 0,
|
||||
.autoclose = 0,
|
||||
};
|
||||
|
||||
noomV_DisInfo noomV_disInfo[NOOMV_INSTR_NOP2] = {
|
||||
[NOOMV_INSTR_PUSHVAL] = {
|
||||
.name = "PUSHVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHCONST] = {
|
||||
.name = "PUSHCONST",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHGLOBAL] = {
|
||||
.name = "PUSHGLOBAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHINT] = {
|
||||
.name = "PUSHINT",
|
||||
.arg = NOOMV_DIS_sD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHNIL] = {
|
||||
.name = "PUSHNIL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHBOOLS] = {
|
||||
.name = "PUSHBOOLS",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHUPVAL] = {
|
||||
.name = "PUSHUPVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHARGS] = {
|
||||
.name = "PUSHARGS",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CREATETABLE] = {
|
||||
.name = "CREATETABLE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHCLOSURE] = {
|
||||
.name = "PUSHCLOSURE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CALL] = {
|
||||
.name = "CALL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_GETTABLE] = {
|
||||
.name = "GETTABLE",
|
||||
.arg = NOOMV_DIS_NONE,
|
||||
},
|
||||
// pops (table, field, value), and sets `table[field] = value`
|
||||
[NOOMV_INSTR_SETTABLE] = {
|
||||
.name = "SETTABLE",
|
||||
.arg = NOOMV_DIS_NONE,
|
||||
},
|
||||
[NOOMV_INSTR_SETLIST] = {
|
||||
.name = "SETLIST",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
// pops table, pushes `table[consts[op.uD]]`, an optimization for indexing fields
|
||||
[NOOMV_INSTR_GETFIELD] = {
|
||||
.name = "GETFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETFIELD] = {
|
||||
.name = "SETFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_GETUPFIELD] = {
|
||||
.name = "GETUPFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_ISNTR_SETUPFIELD] = {
|
||||
.name = "SETUPFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHVAL] = {
|
||||
.name = "PUSHVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHCONST] = {
|
||||
.name = "PUSHCONST",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHGLOBAL] = {
|
||||
.name = "PUSHGLOBAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHINT] = {
|
||||
.name = "PUSHINT",
|
||||
.arg = NOOMV_DIS_sD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHNIL] = {
|
||||
.name = "PUSHNIL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHBOOLS] = {
|
||||
.name = "PUSHBOOLS",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHUPVAL] = {
|
||||
.name = "PUSHUPVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHARGS] = {
|
||||
.name = "PUSHARGS",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CREATETABLE] = {
|
||||
.name = "CREATETABLE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_PUSHCLOSURE] = {
|
||||
.name = "PUSHCLOSURE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CALL] = {
|
||||
.name = "CALL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_GETTABLE] = {
|
||||
.name = "GETTABLE",
|
||||
.arg = NOOMV_DIS_NONE,
|
||||
},
|
||||
// pops (table, field, value), and sets `table[field] = value`
|
||||
[NOOMV_INSTR_SETTABLE] = {
|
||||
.name = "SETTABLE",
|
||||
.arg = NOOMV_DIS_NONE,
|
||||
},
|
||||
[NOOMV_INSTR_SETLIST] = {
|
||||
.name = "SETLIST",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
// pops table, pushes `table[consts[op.uD]]`, an optimization for indexing fields
|
||||
[NOOMV_INSTR_GETFIELD] = {
|
||||
.name = "GETFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETFIELD] = {
|
||||
.name = "SETFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_GETUPFIELD] = {
|
||||
.name = "GETUPFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_ISNTR_SETUPFIELD] = {
|
||||
.name = "SETUPFIELD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_OP] = {
|
||||
.name = "OP",
|
||||
.arg = NOOMV_DIS_BC,
|
||||
},
|
||||
[NOOMV_INSTR_OP] = {
|
||||
.name = "OP",
|
||||
.arg = NOOMV_DIS_BC,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_SETVAL] = {
|
||||
.name = "SETVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETUPVAL] = {
|
||||
.name = "SETUPVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETGLOBAL] = {
|
||||
.name = "SETGLOBAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETVAL] = {
|
||||
.name = "SETVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETUPVAL] = {
|
||||
.name = "SETUPVAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETGLOBAL] = {
|
||||
.name = "SETGLOBAL",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_RET] = {
|
||||
.name = "RET",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_RET] = {
|
||||
.name = "RET",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_JMP] = {
|
||||
.name = "JMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CJMP] = {
|
||||
.name = "CJMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CNJMP] = {
|
||||
.name = "CNJMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_JMP] = {
|
||||
.name = "JMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CJMP] = {
|
||||
.name = "CJMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CNJMP] = {
|
||||
.name = "CNJMP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
// For bullshit
|
||||
// For bullshit
|
||||
|
||||
// Take the top value without popping it, push `value[consts[op.uD]]` like GETFIELD would, then swap the top 2 values.
|
||||
// This is for a:foo() and such
|
||||
[NOOMV_INSTR_GETMETHOD] = {
|
||||
.name = "GETMETHOD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
// rotate the the top op.a items by op.sD
|
||||
[NOOMV_INSTR_ROTATE] = {
|
||||
.name = "ROTATE",
|
||||
.arg = NOOMV_DIS_sD,
|
||||
},
|
||||
[NOOMV_INSTR_POP] = {
|
||||
.name = "POP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETSTACK] = {
|
||||
.name = "SETSTACK",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
// Take the top value without popping it, push `value[consts[op.uD]]` like GETFIELD would, then swap the top 2 values.
|
||||
// This is for a:foo() and such
|
||||
[NOOMV_INSTR_GETMETHOD] = {
|
||||
.name = "GETMETHOD",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
// rotate the the top op.a items by op.sD
|
||||
[NOOMV_INSTR_ROTATE] = {
|
||||
.name = "ROTATE",
|
||||
.arg = NOOMV_DIS_sD,
|
||||
},
|
||||
[NOOMV_INSTR_POP] = {
|
||||
.name = "POP",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_SETSTACK] = {
|
||||
.name = "SETSTACK",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_CONCAT] = {
|
||||
.name = "CONCAT",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CONCAT] = {
|
||||
.name = "CONCAT",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
|
||||
[NOOMV_INSTR_CLOSE] = {
|
||||
.name = "CLOSE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
[NOOMV_INSTR_CLOSE] = {
|
||||
.name = "CLOSE",
|
||||
.arg = NOOMV_DIS_uD,
|
||||
},
|
||||
};
|
||||
|
||||
noomV_Object* noomV_allocObj(noom_LuaVM* vm, noomV_ObjTag tag, noom_uint_t size) {
|
||||
@@ -199,9 +199,9 @@ noomV_Function* noomV_allocFunc(noom_LuaVM* vm, noomV_String* chunkname) {
|
||||
return f;
|
||||
}
|
||||
|
||||
noomV_Table *noomV_allocTable(noom_LuaVM *vm, noom_uint_t arraylen, noom_uint_t fields) {
|
||||
noomV_Table *t = (noomV_Table *)noomV_allocObj(vm, NOOMV_OTABLE, sizeof(noomV_Table));
|
||||
if(t == 0) return 0;
|
||||
noomV_Table* noomV_allocTable(noom_LuaVM* vm, noom_uint_t arraylen, noom_uint_t fields) {
|
||||
noomV_Table* t = (noomV_Table*)noomV_allocObj(vm, NOOMV_OTABLE, sizeof(noomV_Table));
|
||||
if (t == 0) return 0;
|
||||
// not computed
|
||||
t->len = 0;
|
||||
// no metatable
|
||||
@@ -213,38 +213,38 @@ noomV_Table *noomV_allocTable(noom_LuaVM *vm, noom_uint_t arraylen, noom_uint_t
|
||||
t->entries = 0;
|
||||
t->entrydata = noom_alloc(sizeof(noomV_Value) * 2 * cap);
|
||||
// dw about freeing t, its in the VM heap so it'll get GC'd out
|
||||
if(t->entrydata == 0) return 0;
|
||||
if (t->entrydata == 0) return 0;
|
||||
t->entries = cap;
|
||||
for(size_t i = 0; i < cap*2; i++) {
|
||||
for (size_t i = 0; i < cap * 2; i++) {
|
||||
t->entrydata[i].tag = NOOMV_VNIL;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
noom_uint_t noomV_rawhashValue(noomV_Value v) {
|
||||
switch(v.tag) {
|
||||
case NOOMV_VNIL:
|
||||
return 0;
|
||||
case NOOMV_VINT:
|
||||
return v.integer;
|
||||
case NOOMV_VBOOL:
|
||||
return v.boolean ? 1 : 0;
|
||||
case NOOMV_VNUM:
|
||||
// TODO: see if we should bitcast instead
|
||||
return v.number;
|
||||
case NOOMV_VCFUNC:
|
||||
return (noom_uint_t)v.cfunc;
|
||||
case NOOMV_VLUSER:
|
||||
return (noom_uint_t)v.lightuserdata;
|
||||
case NOOMV_VOBJ: {
|
||||
noomV_Object *o = v.obj;
|
||||
if(o->tag != NOOMV_OSTR) return (noom_uint_t)o;
|
||||
switch (v.tag) {
|
||||
case NOOMV_VNIL:
|
||||
return 0;
|
||||
case NOOMV_VINT:
|
||||
return v.integer;
|
||||
case NOOMV_VBOOL:
|
||||
return v.boolean ? 1 : 0;
|
||||
case NOOMV_VNUM:
|
||||
// TODO: see if we should bitcast instead
|
||||
return v.number;
|
||||
case NOOMV_VCFUNC:
|
||||
return (noom_uint_t)v.cfunc;
|
||||
case NOOMV_VLUSER:
|
||||
return (noom_uint_t)v.lightuserdata;
|
||||
case NOOMV_VOBJ: {
|
||||
noomV_Object* o = v.obj;
|
||||
if (o->tag != NOOMV_OSTR) return (noom_uint_t)o;
|
||||
|
||||
noomV_String *s = (noomV_String *)o;
|
||||
if(s->hash == 0) {
|
||||
noomV_String* s = (noomV_String*)o;
|
||||
if (s->hash == 0) {
|
||||
// https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time
|
||||
noom_uint_t hash = 0;
|
||||
for(noom_uint_t i = 0; i < s->len; i++) {
|
||||
for (noom_uint_t i = 0; i < s->len; i++) {
|
||||
hash += (unsigned char)s->data[i];
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
@@ -262,8 +262,8 @@ noom_uint_t noomV_rawhashValue(noomV_Value v) {
|
||||
noom_bool_t noomV_isNil(noomV_Value key) { return key.tag == NOOMV_VNIL; }
|
||||
|
||||
noom_bool_t noomV_isLegalKey(noomV_Value key) {
|
||||
if(key.tag == NOOMV_VNIL) return 0;
|
||||
if(key.tag == NOOMV_VNUM) {
|
||||
if (key.tag == NOOMV_VNIL) return 0;
|
||||
if (key.tag == NOOMV_VNUM) {
|
||||
noom_float_t n = key.number;
|
||||
// true for all except NaN, which is an illegal key!
|
||||
return n == n;
|
||||
@@ -273,76 +273,76 @@ noom_bool_t noomV_isLegalKey(noomV_Value key) {
|
||||
|
||||
noom_bool_t noomV_rawequalValue(noomV_Value a, noomV_Value b) {
|
||||
// special case: integers and numbers
|
||||
if(a.tag == NOOMV_VINT && b.tag == NOOMV_VNUM) {
|
||||
if (a.tag == NOOMV_VINT && b.tag == NOOMV_VNUM) {
|
||||
return a.integer == b.number;
|
||||
}
|
||||
if(a.tag == NOOMV_VNUM && b.tag == NOOMV_VINT) {
|
||||
if (a.tag == NOOMV_VNUM && b.tag == NOOMV_VINT) {
|
||||
return a.number == b.integer;
|
||||
}
|
||||
if(a.tag != b.tag) return 0;
|
||||
switch(a.tag) {
|
||||
case NOOMV_VNIL:
|
||||
return 1;
|
||||
case NOOMV_VINT:
|
||||
return a.integer == b.integer;
|
||||
case NOOMV_VBOOL:
|
||||
return (a.boolean != 0) == (b.boolean != 0);
|
||||
case NOOMV_VNUM:
|
||||
return a.number == b.number;
|
||||
case NOOMV_VCFUNC:
|
||||
return a.cfunc == b.cfunc;
|
||||
case NOOMV_VLUSER:
|
||||
return a.lightuserdata == b.lightuserdata;
|
||||
case NOOMV_VOBJ: {
|
||||
noomV_Object *aObj = a.obj;
|
||||
noomV_Object *bObj = b.obj;
|
||||
if(aObj == bObj) return 1;
|
||||
if(aObj->tag != bObj->tag) return 0;
|
||||
if(aObj->tag != NOOMV_OSTR) return aObj == bObj;
|
||||
if (a.tag != b.tag) return 0;
|
||||
switch (a.tag) {
|
||||
case NOOMV_VNIL:
|
||||
return 1;
|
||||
case NOOMV_VINT:
|
||||
return a.integer == b.integer;
|
||||
case NOOMV_VBOOL:
|
||||
return (a.boolean != 0) == (b.boolean != 0);
|
||||
case NOOMV_VNUM:
|
||||
return a.number == b.number;
|
||||
case NOOMV_VCFUNC:
|
||||
return a.cfunc == b.cfunc;
|
||||
case NOOMV_VLUSER:
|
||||
return a.lightuserdata == b.lightuserdata;
|
||||
case NOOMV_VOBJ: {
|
||||
noomV_Object* aObj = a.obj;
|
||||
noomV_Object* bObj = b.obj;
|
||||
if (aObj == bObj) return 1;
|
||||
if (aObj->tag != bObj->tag) return 0;
|
||||
if (aObj->tag != NOOMV_OSTR) return aObj == bObj;
|
||||
|
||||
noomV_String *strA = (noomV_String *)aObj;
|
||||
noomV_String *strB = (noomV_String *)bObj;
|
||||
if(strA->len != strB->len) return 0;
|
||||
if(strA->hash != 0 && strB->hash != 0 && strA->hash != strB->hash) return 0;
|
||||
for(noom_uint_t i = 0; i < strA->len; i++) {
|
||||
if(strA->data[i] != strB->data[i]) return 0;
|
||||
noomV_String* strA = (noomV_String*)aObj;
|
||||
noomV_String* strB = (noomV_String*)bObj;
|
||||
if (strA->len != strB->len) return 0;
|
||||
if (strA->hash != 0 && strB->hash != 0 && strA->hash != strB->hash) return 0;
|
||||
for (noom_uint_t i = 0; i < strA->len; i++) {
|
||||
if (strA->data[i] != strB->data[i]) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
noomV_Value noomV_rawgetTable(noomV_Table *t, noomV_Value key) {
|
||||
if(!noomV_isLegalKey(key)) return noomV_nil;
|
||||
noomV_Value noomV_rawgetTable(noomV_Table* t, noomV_Value key) {
|
||||
if (!noomV_isLegalKey(key)) return noomV_nil;
|
||||
noom_uint_t hash = noomV_rawhashValue(key);
|
||||
noom_uint_t start = hash % t->entries;
|
||||
for(noom_uint_t i = 0; i < t->entries; i++) {
|
||||
for (noom_uint_t i = 0; i < t->entries; i++) {
|
||||
noom_uint_t idx = (start + i) % t->entries;
|
||||
// unallocated entry, bye-bye
|
||||
if(t->entrydata[idx].tag == NOOMV_VNIL) break;
|
||||
if (t->entrydata[idx].tag == NOOMV_VNIL) break;
|
||||
// isptr on a key means its a tombstone
|
||||
if(t->entrydata[idx].isptr) continue;
|
||||
if(noomV_rawequalValue(t->entrydata[idx], key)) {
|
||||
if (t->entrydata[idx].isptr) continue;
|
||||
if (noomV_rawequalValue(t->entrydata[idx], key)) {
|
||||
return t->entrydata[idx + t->entries];
|
||||
}
|
||||
}
|
||||
return noomV_nil;
|
||||
}
|
||||
|
||||
noomV_Value noomV_rawgetiTable(noomV_Table *t, noom_int_t idx) {
|
||||
return noomV_rawgetTable(t, (noomV_Value) { .tag = NOOMV_VINT, .integer = idx });
|
||||
noomV_Value noomV_rawgetiTable(noomV_Table* t, noom_int_t idx) {
|
||||
return noomV_rawgetTable(t, (noomV_Value){.tag = NOOMV_VINT, .integer = idx});
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
// used should be at most ~80% of entrydata because
|
||||
// that's standard practice and we're not computer scientists
|
||||
noom_Exit noomV_rawsetTable(noom_LuaVM *vm, noomV_Table *t, noomV_Value key, noomV_Value val) {
|
||||
if(!noomV_isLegalKey(key)) {
|
||||
noom_Exit noomV_rawsetTable(noom_LuaVM* vm, noomV_Table* t, noomV_Value key, noomV_Value val) {
|
||||
if (!noomV_isLegalKey(key)) {
|
||||
noomV_setErrorStr(vm, vm->currentThread, "illegal key");
|
||||
return NOOM_ERUNTIME;
|
||||
}
|
||||
noom_uint_t target = t->entries * 80 / 100;
|
||||
if(t->used > target) {
|
||||
if (t->used > target) {
|
||||
// TODO: resize hashtable
|
||||
}
|
||||
// prevent awkward bugs
|
||||
@@ -352,15 +352,15 @@ noom_Exit noomV_rawsetTable(noom_LuaVM *vm, noomV_Table *t, noomV_Value key, noo
|
||||
val.autoclose = 0;
|
||||
noom_uint_t hash = noomV_rawhashValue(key);
|
||||
noom_uint_t idx = hash % t->entries;
|
||||
while(1) {
|
||||
while (1) {
|
||||
noomV_Value key2 = t->entrydata[idx];
|
||||
// tombstone!
|
||||
if(key2.isptr) {
|
||||
if (key2.isptr) {
|
||||
t->entrydata[idx] = key;
|
||||
t->entrydata[idx + t->entries] = val;
|
||||
return NOOM_OK;
|
||||
}
|
||||
if(noomV_rawequalValue(key, key2)) {
|
||||
if (noomV_rawequalValue(key, key2)) {
|
||||
// HOLY SHIET!!!!!
|
||||
t->entrydata[idx + t->entries] = val;
|
||||
return NOOM_OK;
|
||||
@@ -371,20 +371,20 @@ noom_Exit noomV_rawsetTable(noom_LuaVM *vm, noomV_Table *t, noomV_Value key, noo
|
||||
return NOOM_OK;
|
||||
}
|
||||
|
||||
noom_uint_t noomV_rawlenTable(noomV_Table *t) {
|
||||
noom_uint_t noomV_rawlenTable(noomV_Table* t) {
|
||||
noom_uint_t guess = t->len;
|
||||
// TODO: optimize with a bsearch
|
||||
while(1) {
|
||||
if(!noomV_isNil(noomV_rawgetiTable(t, guess+1))) guess++;
|
||||
if(guess == 0) break;
|
||||
if(noomV_isNil(noomV_rawgetiTable(t, guess))) guess--;
|
||||
while (1) {
|
||||
if (!noomV_isNil(noomV_rawgetiTable(t, guess + 1))) guess++;
|
||||
if (guess == 0) break;
|
||||
if (noomV_isNil(noomV_rawgetiTable(t, guess))) guess--;
|
||||
}
|
||||
return t->len = guess;
|
||||
}
|
||||
|
||||
noomV_Thread *noomV_allocCoroutine(noom_LuaVM *vm) {
|
||||
noomV_Thread *thrd = (noomV_Thread *)noomV_allocObj(vm, NOOMV_OTHREAD, sizeof(noomV_Thread));
|
||||
if(thrd == 0) return 0;
|
||||
noomV_Thread* noomV_allocCoroutine(noom_LuaVM* vm) {
|
||||
noomV_Thread* thrd = (noomV_Thread*)noomV_allocObj(vm, NOOMV_OTHREAD, sizeof(noomV_Thread));
|
||||
if (thrd == 0) return 0;
|
||||
thrd->resumedBy = 0;
|
||||
thrd->resuming = 0;
|
||||
thrd->calldepth = 0;
|
||||
@@ -394,16 +394,16 @@ noomV_Thread *noomV_allocCoroutine(noom_LuaVM *vm) {
|
||||
thrd->errObj = noomV_nil;
|
||||
|
||||
thrd->calls = noom_alloc(sizeof(noomV_CallFrame) * thrd->callcap);
|
||||
if(thrd->calls == 0) return 0;
|
||||
if (thrd->calls == 0) return 0;
|
||||
thrd->stack = noom_alloc(sizeof(noomV_Value) * thrd->stackcap);
|
||||
if(thrd->stack == 0) return 0;
|
||||
if (thrd->stack == 0) return 0;
|
||||
|
||||
return thrd;
|
||||
}
|
||||
|
||||
void noomV_setErrorStr(noom_LuaVM *vm, noomV_Thread *coro, const char *str) {
|
||||
noomV_String *s = noomV_allocStr(vm, str, noom_strlen(str));
|
||||
if(s == 0) {
|
||||
void noomV_setErrorStr(noom_LuaVM* vm, noomV_Thread* coro, const char* str) {
|
||||
noomV_String* s = noomV_allocStr(vm, str, noom_strlen(str));
|
||||
if (s == 0) {
|
||||
coro->errObj = vm->oomVal;
|
||||
return;
|
||||
}
|
||||
@@ -411,8 +411,8 @@ void noomV_setErrorStr(noom_LuaVM *vm, noomV_Thread *coro, const char *str) {
|
||||
coro->errObj.obj = &s->obj;
|
||||
}
|
||||
|
||||
noom_Exit noomV_setErrorFromExit(noom_LuaVM *vm, noomV_Thread *coro, noom_Exit exit) {
|
||||
switch(exit) {
|
||||
noom_Exit noomV_setErrorFromExit(noom_LuaVM* vm, noomV_Thread* coro, noom_Exit exit) {
|
||||
switch (exit) {
|
||||
case NOOM_OK:
|
||||
coro->errObj = noomV_nil;
|
||||
break;
|
||||
@@ -445,20 +445,20 @@ noom_Exit noomV_setErrorFromExit(noom_LuaVM *vm, noomV_Thread *coro, noom_Exit e
|
||||
return exit;
|
||||
}
|
||||
|
||||
void noomV_freeObj(noom_LuaVM *vm, noomV_Object* obj) {
|
||||
if(obj->tag == NOOMV_OFUNC) {
|
||||
noomV_Function *f = (noomV_Function *)obj;
|
||||
void noomV_freeObj(noom_LuaVM* vm, noomV_Object* obj) {
|
||||
if (obj->tag == NOOMV_OFUNC) {
|
||||
noomV_Function* f = (noomV_Function*)obj;
|
||||
noom_free(f->consts);
|
||||
noom_free(f->upvals);
|
||||
noom_free(f->locals);
|
||||
noom_free(f->code);
|
||||
}
|
||||
if(obj->tag == NOOMV_OTABLE) {
|
||||
noomV_Table *t = (noomV_Table *)obj;
|
||||
if (obj->tag == NOOMV_OTABLE) {
|
||||
noomV_Table* t = (noomV_Table*)obj;
|
||||
noom_free(t->entrydata);
|
||||
}
|
||||
if(obj->tag == NOOMV_OTHREAD) {
|
||||
noomV_Thread *thrd = (noomV_Thread *)obj;
|
||||
if (obj->tag == NOOMV_OTHREAD) {
|
||||
noomV_Thread* thrd = (noomV_Thread*)obj;
|
||||
noom_free(thrd->stack);
|
||||
noom_free(thrd->calls);
|
||||
}
|
||||
@@ -466,32 +466,32 @@ void noomV_freeObj(noom_LuaVM *vm, noomV_Object* obj) {
|
||||
vm->objCount--;
|
||||
}
|
||||
|
||||
noom_Exit noomV_pushCallFrame(noom_LuaVM *vm, noomV_Thread *coro, noomV_CallFrame cf);
|
||||
noom_Exit noomV_pushCallFrame(noom_LuaVM* vm, noomV_Thread* coro, noomV_CallFrame cf);
|
||||
|
||||
noomV_CallFrame *noomV_topCallFrame(noomV_Thread *coro) {
|
||||
if(coro->calldepth == 0) return 0;
|
||||
noomV_CallFrame* noomV_topCallFrame(noomV_Thread* coro) {
|
||||
if (coro->calldepth == 0) return 0;
|
||||
return &coro->calls[coro->calldepth - 1];
|
||||
}
|
||||
|
||||
noom_Exit noomV_setThreadStackSize(noom_LuaVM *vm, noomV_Thread *coro, noom_int_t stack) {
|
||||
if(stack < 0) {
|
||||
noom_Exit noomV_setThreadStackSize(noom_LuaVM* vm, noomV_Thread* coro, noom_int_t stack) {
|
||||
if (stack < 0) {
|
||||
noomV_setErrorStr(vm, coro, "stack underflow");
|
||||
return NOOM_ERUNTIME;
|
||||
}
|
||||
if(stack > NOOM_MAXSTACK) return NOOM_ELIMIT;
|
||||
if(stack > coro->stackcap) {
|
||||
if (stack > NOOM_MAXSTACK) return NOOM_ELIMIT;
|
||||
if (stack > coro->stackcap) {
|
||||
noom_uint_t newCap = coro->stackcap;
|
||||
while(newCap < stack) newCap *= 2;
|
||||
while (newCap < stack) newCap *= 2;
|
||||
|
||||
noomV_Value *newStack = noom_realloc(coro->stack, sizeof(noomV_Value) * coro->stackcap);
|
||||
if(newStack == 0) return NOOM_ENOMEM;
|
||||
noomV_Value* newStack = noom_realloc(coro->stack, sizeof(noomV_Value) * coro->stackcap);
|
||||
if (newStack == 0) return NOOM_ENOMEM;
|
||||
coro->stack = newStack;
|
||||
coro->stackcap = newCap;
|
||||
}
|
||||
|
||||
// NIL-ify
|
||||
if(coro->stacklen < stack) {
|
||||
for(int i = coro->stacklen; i < stack; i++) {
|
||||
if (coro->stacklen < stack) {
|
||||
for (int i = coro->stacklen; i < stack; i++) {
|
||||
coro->stack[i] = noomV_nil;
|
||||
}
|
||||
return NOOM_OK;
|
||||
@@ -519,28 +519,28 @@ noom_LuaVM* noom_createVM(noom_LuaVersion version) {
|
||||
vm->gcTarget = 100;
|
||||
vm->gcRatio = 2;
|
||||
|
||||
const char *oomStr = "out of memory";
|
||||
vm->oomVal.obj = (noomV_Object *)noomV_allocStr(vm, oomStr, noom_strlen(oomStr));
|
||||
if(vm->oomVal.obj == 0) goto rip;
|
||||
const char* oomStr = "out of memory";
|
||||
vm->oomVal.obj = (noomV_Object*)noomV_allocStr(vm, oomStr, noom_strlen(oomStr));
|
||||
if (vm->oomVal.obj == 0) goto rip;
|
||||
vm->registry = noomV_allocTable(vm, 0, 1);
|
||||
if(vm->registry == 0) goto rip;
|
||||
if (vm->registry == 0) goto rip;
|
||||
vm->globals = noomV_allocTable(vm, 0, 32);
|
||||
if(vm->globals == 0) goto rip;
|
||||
if (vm->globals == 0) goto rip;
|
||||
|
||||
vm->mainThread = noomV_allocCoroutine(vm);
|
||||
if(vm->mainThread == 0) goto rip;
|
||||
if (vm->mainThread == 0) goto rip;
|
||||
|
||||
vm->currentThread = vm->mainThread;
|
||||
|
||||
// goal: put _G in the registry as the _G key
|
||||
noomV_String *_G = noomV_allocStr(vm, "_G", 2);
|
||||
if(_G == 0) goto rip;
|
||||
noomV_String* _G = noomV_allocStr(vm, "_G", 2);
|
||||
if (_G == 0) goto rip;
|
||||
|
||||
noomV_Value _GKey = { .tag = NOOMV_VOBJ, .obj = &_G->obj, .isptr = 0, .autoclose = 0 };
|
||||
noomV_Value _GVal = { .tag = NOOMV_VOBJ, .obj = &vm->globals->obj, .isptr = 0, .autoclose = 0 };
|
||||
noomV_Value _GKey = {.tag = NOOMV_VOBJ, .obj = &_G->obj, .isptr = 0, .autoclose = 0};
|
||||
noomV_Value _GVal = {.tag = NOOMV_VOBJ, .obj = &vm->globals->obj, .isptr = 0, .autoclose = 0};
|
||||
|
||||
noom_Exit err = noomV_rawsetTable(vm, vm->registry, _GKey, _GVal);
|
||||
if(err) goto rip;
|
||||
if (err) goto rip;
|
||||
|
||||
assert(noomV_rawequalValue(noomV_rawgetTable(vm->registry, _GKey), _GVal));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user