mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-22 07:20:05 +00:00
added support for __newindex
This commit is contained in:
parent
d2093098a4
commit
bb11b3b309
21
src/cobj.c
21
src/cobj.c
@ -228,9 +228,26 @@ bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val) {
|
void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val) {
|
||||||
|
CValue ret;
|
||||||
|
|
||||||
|
// first check for __newindex in the prototype
|
||||||
|
if (object->proto != NULL && cosmoO_getIString(state, object->proto, ISTRING_NEWINDEX, &ret)) {
|
||||||
|
cosmoV_pushValue(state, ret); // push function
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||||
|
cosmoV_pushValue(state, key); // push key & value pair
|
||||||
|
cosmoV_pushValue(state, val);
|
||||||
|
cosmoV_call(state, 3);
|
||||||
|
cosmoV_pop(state); // pop return value
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
object->istringFlags = 0; // reset cache
|
object->istringFlags = 0; // reset cache
|
||||||
CValue *newVal = cosmoT_insert(state, &object->tbl, key);
|
if (IS_NIL(val)) { // if we're setting an index to nil, we can safely mark that as a tombstone
|
||||||
*newVal = val;
|
cosmoT_remove(state, &object->tbl, key);
|
||||||
|
} else {
|
||||||
|
CValue *newVal = cosmoT_insert(state, &object->tbl, key);
|
||||||
|
*newVal = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val) {
|
bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val) {
|
||||||
|
@ -42,6 +42,8 @@ CState *cosmoV_newState() {
|
|||||||
// setup all strings used by the VM
|
// setup all strings used by the VM
|
||||||
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
|
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
|
||||||
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
||||||
|
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ typedef struct CCallFrame {
|
|||||||
typedef enum IStringEnum {
|
typedef enum IStringEnum {
|
||||||
ISTRING_INIT, // __init
|
ISTRING_INIT, // __init
|
||||||
ISTRING_EQUAL, // __equal
|
ISTRING_EQUAL, // __equal
|
||||||
ISTRING_INDEX,
|
ISTRING_INDEX, // __index
|
||||||
|
ISTRING_NEWINDEX, // __newindex
|
||||||
ISTRING_MAX
|
ISTRING_MAX
|
||||||
} IStringEnum;
|
} IStringEnum;
|
||||||
|
|
||||||
|
@ -108,6 +108,9 @@ static CTableEntry *findEntry(CTableEntry *entries, int mask, CValue key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) {
|
static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) {
|
||||||
|
if (cosmoT_checkShrink(state, tbl))
|
||||||
|
return;
|
||||||
|
|
||||||
size_t size = sizeof(CTableEntry) * newCapacity;
|
size_t size = sizeof(CTableEntry) * newCapacity;
|
||||||
int cachedCount = tbl->count;
|
int cachedCount = tbl->count;
|
||||||
cosmoM_checkGarbage(state, size); // if this allocation would cause a GC, run the GC
|
cosmoM_checkGarbage(state, size); // if this allocation would cause a GC, run the GC
|
||||||
@ -148,7 +151,9 @@ static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) {
|
|||||||
|
|
||||||
bool cosmoT_checkShrink(CState *state, CTable *tbl) {
|
bool cosmoT_checkShrink(CState *state, CTable *tbl) {
|
||||||
// if count > 8 and active entries < tombstones
|
// if count > 8 and active entries < tombstones
|
||||||
if (tbl->count > MIN_TABLE_CAPACITY && tbl->count - tbl->tombstones < tbl->tombstones) {
|
if (tbl->count > MIN_TABLE_CAPACITY && (tbl->count - tbl->tombstones < tbl->tombstones || tbl->tombstones > 50)) {
|
||||||
|
printf("shrinking table!\n");
|
||||||
|
getchar();
|
||||||
resizeTbl(state, tbl, nextPow2((tbl->count - tbl->tombstones) * GROW_FACTOR)); // shrink based on active entries to the next pow of 2
|
resizeTbl(state, tbl, nextPow2((tbl->count - tbl->tombstones) * GROW_FACTOR)); // shrink based on active entries to the next pow of 2
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user