Fixed OP_INCOBJECT to properly handle dicts

minor refactoring in OP_INCINDEX
This commit is contained in:
CPunch 2021-01-01 22:52:54 -06:00
parent c96b155412
commit bccabdebd7

113
src/cvm.c
View File

@ -912,39 +912,44 @@ int cosmoV_execute(CState *state) {
StkPtr key = cosmoV_getTop(state, 0); // grabs key StkPtr key = cosmoV_getTop(state, 0); // grabs key
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
if (cosmoV_readObj(*temp)->type == COBJ_DICT) { switch (cosmoV_readObj(*temp)->type) {
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); case COBJ_DICT: {
CValue *val = cosmoT_insert(state, &dict->tbl, *key); CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
CValue *val = cosmoT_insert(state, &dict->tbl, *key);
// pops dict & key from stack // pops dict & key from stack
cosmoV_setTop(state, 2); cosmoV_setTop(state, 2);
if (IS_NUMBER(*val)) { if (IS_NUMBER(*val)) {
cosmoV_pushValue(state, *val); // pushes old value onto the stack :) cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
*val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc); *val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc);
} else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
return -1;
}
} else if (cosmoV_readObj(*temp)->type == COBJ_OBJECT) { // check for __newindex!
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
CValue val;
// call __index
if (cosmoO_indexObject(state, object, *key, &val)) {
if (IS_NUMBER(val)) {
cosmoV_pushValue(state, val); // pushes old value onto the stack :)
// call __newindex
cosmoO_newIndexObject(state, object, *key, cosmoV_newNumber(cosmoV_readNumber(val) + inc));
} else { } else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val)); cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
return -1; return -1;
} }
break;
} }
} else { case COBJ_OBJECT: {
cosmoV_error(state, "Couldn't set index with type %s!", cosmoV_typeStr(*temp)); CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
return -1; CValue val;
// call __index
if (cosmoO_indexObject(state, object, *key, &val)) {
if (IS_NUMBER(val)) {
cosmoV_pushValue(state, val); // pushes old value onto the stack :)
// call __newindex
cosmoO_newIndexObject(state, object, *key, cosmoV_newNumber(cosmoV_readNumber(val) + inc));
} else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
return -1;
}
}
break;
}
default:
cosmoV_error(state, "Couldn't set index with type %s!", cosmoV_typeStr(*temp));
return -1;
} }
} else { } else {
cosmoV_error(state, "Couldn't set index with type %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Couldn't set index with type %s!", cosmoV_typeStr(*temp));
@ -960,25 +965,49 @@ int cosmoV_execute(CState *state) {
CValue ident = constants[indx]; // grabs identifier CValue ident = constants[indx]; // grabs identifier
// sanity check // sanity check
if (!IS_OBJ(*temp) || cosmoV_readObj(*temp)->type != COBJ_OBJECT) { if (IS_OBJ(*temp)) {
cosmoV_error(state, "Couldn't set a field on non-object type %s!", cosmoV_typeStr(*temp)); switch (cosmoV_readObj(*temp)->type) {
return -1; case COBJ_OBJECT: {
} CObjObject *object = (CObjObject*)cosmoV_readObj(*temp);
CValue val;
cosmoO_getRawObject(state, object, ident, &val);
CObjObject *object = (CObjObject*)cosmoV_readObj(*temp); // pop the object off the stack
CValue val; cosmoV_pop(state);
cosmoO_getRawObject(state, object, ident, &val);
// pop the object off the stack // check that it's a number value
cosmoV_pop(state); if (IS_NUMBER(val)) {
cosmoV_pushValue(state, val); // pushes old value onto the stack :)
cosmoO_setRawObject(state, object, ident, cosmoV_newNumber(cosmoV_readNumber(val) + inc));
} else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
return -1;
}
break;
}
case COBJ_DICT: {
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
CValue *val = cosmoT_insert(state, &dict->tbl, ident);
// check that it's a number value // pops dict from stack
if (IS_NUMBER(val)) { cosmoV_pop(state);
cosmoV_pushValue(state, val); // pushes old value onto the stack :)
cosmoO_setRawObject(state, object, ident, cosmoV_newNumber(cosmoV_readNumber(val) + inc)); if (IS_NUMBER(*val)) {
cosmoV_pushValue(state, *val); // pushes old value onto the stack :)
*val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc);
} else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
return -1;
}
break;
}
default:
cosmoV_error(state, "Couldn't set a field on type %s!", cosmoV_typeStr(*temp));
return -1;
}
} else { } else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val)); cosmoV_error(state, "Couldn't set a field on type %s!", cosmoV_typeStr(*temp));
return -1; return -1;
} }