even more error handling refactoring

removing all of these useless checks has actually made cosmoV_execute just a
lil bit faster :)
This commit is contained in:
CPunch 2023-09-04 20:14:53 -05:00
parent 5a00d61646
commit b73d865447
4 changed files with 48 additions and 120 deletions

View File

@ -397,7 +397,7 @@ bool cosmoO_isDescendant(CObj *obj, CObjObject *proto)
} }
// returns false if error thrown // returns false if error thrown
bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj) void cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj)
{ {
if (!cosmoT_get(state, &proto->tbl, key, if (!cosmoT_get(state, &proto->tbl, key,
val)) { // if the field doesn't exist in the object, check the proto val)) { // if the field doesn't exist in the object, check the proto
@ -407,18 +407,17 @@ bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *v
cosmoV_pushRef(state, (CObj *)obj); // push object cosmoV_pushRef(state, (CObj *)obj); // push object
cosmoV_call(state, 1, 1); // call the function with the 1 argument cosmoV_call(state, 1, 1); // call the function with the 1 argument
*val = *cosmoV_pop(state); // set value to the return value of __index *val = *cosmoV_pop(state); // set value to the return value of __index
return true; return;
} }
if (proto->_obj.proto != NULL && // maybe the field is defined in the proto?
cosmoO_getRawObject(state, proto->_obj.proto, key, val, obj)) if (proto->_obj.proto != NULL) {
return true; cosmoO_getRawObject(state, proto->_obj.proto, key, val, obj);
return;
}
*val = cosmoV_newNil(); *val = cosmoV_newNil();
return true; // no protoobject to check against / key not found
} }
return true;
} }
void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj) void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj)
@ -519,7 +518,7 @@ bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val)
return false; // obj->proto was false, the istring doesn't exist in this object chain return false; // obj->proto was false, the istring doesn't exist in this object chain
} }
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val) void cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val)
{ {
if (cosmoO_getIString(state, object, ISTRING_INDEX, val)) { if (cosmoO_getIString(state, object, ISTRING_INDEX, val)) {
cosmoV_pushValue(state, *val); // push function cosmoV_pushValue(state, *val); // push function
@ -527,15 +526,12 @@ bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *v
cosmoV_pushValue(state, key); // push key cosmoV_pushValue(state, key); // push key
cosmoV_call(state, 2, 1); // call the function with the 2 arguments cosmoV_call(state, 2, 1); // call the function with the 2 arguments
*val = *cosmoV_pop(state); // set value to the return value of __index *val = *cosmoV_pop(state); // set value to the return value of __index
return true; } else { // there's no __index function defined!
} else { // there's no __index function defined!
cosmoV_error(state, "Couldn't index object without __index function!"); cosmoV_error(state, "Couldn't index object without __index function!");
} }
return false;
} }
bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val) void cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val)
{ {
CValue ret; // return value for cosmoO_getIString CValue ret; // return value for cosmoO_getIString
@ -545,12 +541,9 @@ bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue
cosmoV_pushValue(state, key); // push key & value pair cosmoV_pushValue(state, key); // push key & value pair
cosmoV_pushValue(state, val); cosmoV_pushValue(state, val);
cosmoV_call(state, 3, 0); cosmoV_call(state, 3, 0);
return true;
} else { // there's no __newindex function defined } else { // there's no __newindex function defined
cosmoV_error(state, "Couldn't set index on object without __newindex function!"); cosmoV_error(state, "Couldn't set index on object without __newindex function!");
} }
return false;
} }
CObjString *cosmoO_toString(CState *state, CObj *obj) CObjString *cosmoO_toString(CState *state, CObj *obj)

View File

@ -3,6 +3,8 @@
#include "cosmo.h" #include "cosmo.h"
#include <stdarg.h>
typedef enum CObjType typedef enum CObjType
{ {
COBJ_STRING, COBJ_STRING,
@ -172,10 +174,10 @@ static inline CObjObject *cosmoO_grabProto(CObj *obj)
return obj->type == COBJ_OBJECT ? (CObjObject *)obj : obj->proto; return obj->type == COBJ_OBJECT ? (CObjObject *)obj : obj->proto;
} }
bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj); void cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj);
void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj); void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj);
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val); void cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val); void cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val);
// sets the user-defined pointer, if a user-define integer is already defined it will be over // sets the user-defined pointer, if a user-define integer is already defined it will be over
// written // written

113
src/cvm.c
View File

@ -497,7 +497,7 @@ COSMO_API void cosmoV_makeTable(CState *state, int pairs)
cosmoV_pushRef(state, (CObj *)newObj); cosmoV_pushRef(state, (CObj *)newObj);
} }
bool cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val) void cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val)
{ {
CObjObject *object = cosmoO_grabProto(_obj); CObjObject *object = cosmoO_grabProto(_obj);
@ -506,23 +506,16 @@ bool cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val)
CObjString *field = cosmoV_toString(state, key); CObjString *field = cosmoV_toString(state, key);
cosmoV_error(state, "No proto defined! Couldn't get field '%s' from type %s", field->str, cosmoV_error(state, "No proto defined! Couldn't get field '%s' from type %s", field->str,
cosmoO_typeStr(_obj)); cosmoO_typeStr(_obj));
*val = cosmoV_newNil();
return false;
} }
// push the object onto the stack so the GC can find it // push the object onto the stack so the GC can find it
cosmoV_pushRef(state, (CObj *)object); cosmoV_pushRef(state, (CObj *)object);
if (cosmoO_getRawObject(state, object, key, val, _obj)) { cosmoO_getRawObject(state, object, key, val, _obj);
// *val now equals the response, pop the object
cosmoV_pop(state);
return true;
}
cosmoV_pop(state); cosmoV_pop(state);
return false;
} }
bool cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val) void cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val)
{ {
CObjObject *object = cosmoO_grabProto(_obj); CObjObject *object = cosmoO_grabProto(_obj);
@ -531,14 +524,12 @@ bool cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val)
CObjString *field = cosmoV_toString(state, key); CObjString *field = cosmoV_toString(state, key);
cosmoV_error(state, "No proto defined! Couldn't set field '%s' to type %s", field->str, cosmoV_error(state, "No proto defined! Couldn't set field '%s' to type %s", field->str,
cosmoO_typeStr(_obj)); cosmoO_typeStr(_obj));
return false;
} }
cosmoO_setRawObject(state, object, key, val, _obj); cosmoO_setRawObject(state, object, key, val, _obj);
return true;
} }
COSMO_API bool cosmoV_get(CState *state) COSMO_API void cosmoV_get(CState *state)
{ {
CValue val; CValue val;
StkPtr obj = cosmoV_getTop(state, 1); // object was pushed first StkPtr obj = cosmoV_getTop(state, 1); // object was pushed first
@ -546,20 +537,17 @@ COSMO_API bool cosmoV_get(CState *state)
if (!IS_REF(*obj)) { if (!IS_REF(*obj)) {
cosmoV_error(state, "Couldn't get field from type %s!", cosmoV_typeStr(*obj)); cosmoV_error(state, "Couldn't get field from type %s!", cosmoV_typeStr(*obj));
return false;
} }
if (!cosmoV_rawget(state, cosmoV_readRef(*obj), *key, &val)) cosmoV_rawget(state, cosmoV_readRef(*obj), *key, &val);
return false;
// pop the obj & key, push the value // pop the obj & key, push the value
cosmoV_setTop(state, 2); cosmoV_setTop(state, 2);
cosmoV_pushValue(state, val); cosmoV_pushValue(state, val);
return true;
} }
// yes, this would technically make it possible to set fields of types other than <string>. go crazy // yes, this would technically make it possible to set fields of types other than <string>. go crazy
COSMO_API bool cosmoV_set(CState *state) COSMO_API void cosmoV_set(CState *state)
{ {
StkPtr obj = cosmoV_getTop(state, 2); // object was pushed first StkPtr obj = cosmoV_getTop(state, 2); // object was pushed first
StkPtr key = cosmoV_getTop(state, 1); // then the key StkPtr key = cosmoV_getTop(state, 1); // then the key
@ -567,21 +555,17 @@ COSMO_API bool cosmoV_set(CState *state)
if (!IS_REF(*obj)) { if (!IS_REF(*obj)) {
cosmoV_error(state, "Couldn't set field on type %s!", cosmoV_typeStr(*obj)); cosmoV_error(state, "Couldn't set field on type %s!", cosmoV_typeStr(*obj));
return false;
} }
if (!cosmoV_rawset(state, cosmoV_readRef(*obj), *key, *val)) cosmoV_rawset(state, cosmoV_readRef(*obj), *key, *val);
return false;
// pop the obj, key & value // pop the obj, key & value
cosmoV_setTop(state, 3); cosmoV_setTop(state, 3);
return true;
} }
COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val) COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
{ {
if (!cosmoV_rawget(state, obj, key, val)) cosmoV_rawget(state, obj, key, val);
return false;
// if the result is callable, wrap it in an method // if the result is callable, wrap it in an method
if (IS_CALLABLE(*val)) { if (IS_CALLABLE(*val)) {
@ -591,8 +575,6 @@ COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *va
cosmoV_pop(state); // pop the object cosmoV_pop(state); // pop the object
*val = cosmoV_newRef(method); *val = cosmoV_newRef(method);
} }
return true;
} }
int _tbl__next(CState *state, int nargs, CValue *args) int _tbl__next(CState *state, int nargs, CValue *args)
@ -696,7 +678,7 @@ static inline uint16_t READUINT(CCallFrame *frame)
# define SWITCH switch (READBYTE(frame)) # define SWITCH switch (READBYTE(frame))
# define DEFAULT \ # define DEFAULT \
default: \ default: \
printf("[ERROR] unknown opcode!"); \ printf("[ERROR] unknown opcode!"); \
exit(0) exit(0)
#endif #endif
@ -849,7 +831,6 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (!IS_REF(*temp)) { if (!IS_REF(*temp)) {
cosmoV_error(state, "Couldn't index type %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Couldn't index type %s!", cosmoV_typeStr(*temp));
return -1;
} }
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
@ -858,9 +839,7 @@ int cosmoV_execute(CState *state)
if (proto != NULL) { if (proto != NULL) {
// check for __index metamethod // check for __index metamethod
if (!cosmoO_indexObject(state, proto, *key, cosmoO_indexObject(state, proto, *key, &val);
&val)) // if returns false, cosmoV_error was called
return -1;
} else if (obj->type == COBJ_TABLE) { } else if (obj->type == COBJ_TABLE) {
CObjTable *tbl = (CObjTable *)obj; CObjTable *tbl = (CObjTable *)obj;
@ -868,7 +847,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "No proto defined! Couldn't __index from type %s", cosmoV_error(state, "No proto defined! Couldn't __index from type %s",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
cosmoV_setTop(state, 2); // pops the table & the key cosmoV_setTop(state, 2); // pops the table & the key
@ -883,17 +861,13 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (!IS_REF(*temp)) { if (!IS_REF(*temp)) {
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));
return -1;
} }
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
CObjObject *proto = cosmoO_grabProto(obj); CObjObject *proto = cosmoO_grabProto(obj);
if (proto != NULL) { if (proto != NULL) {
if (!cosmoO_newIndexObject( cosmoO_newIndexObject(state, proto, *key, *value);
state, proto, *key,
*value)) // if it returns false, cosmoV_error was called
return -1;
} else if (obj->type == COBJ_TABLE) { } else if (obj->type == COBJ_TABLE) {
CObjTable *tbl = (CObjTable *)obj; CObjTable *tbl = (CObjTable *)obj;
CValue *newVal = cosmoT_insert(state, &tbl->tbl, *key); CValue *newVal = cosmoT_insert(state, &tbl->tbl, *key);
@ -902,7 +876,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "No proto defined! Couldn't __newindex from type %s", cosmoV_error(state, "No proto defined! Couldn't __newindex from type %s",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
// pop everything off the stack // pop everything off the stack
@ -921,13 +894,11 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
if (!cosmoV_rawset(state, cosmoV_readRef(*temp), constants[ident], *value)) cosmoV_rawset(state, cosmoV_readRef(*temp), constants[ident], *value);
return -1;
} else { } else {
CObjString *field = cosmoV_toString(state, constants[ident]); CObjString *field = cosmoV_toString(state, constants[ident]);
cosmoV_error(state, "Couldn't set field '%s' on type %s!", field->str, cosmoV_error(state, "Couldn't set field '%s' on type %s!", field->str,
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
// pop everything off the stack // pop everything off the stack
@ -941,13 +912,11 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
if (!cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val)) cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val);
return -1;
} else { } else {
CObjString *field = cosmoV_toString(state, constants[ident]); CObjString *field = cosmoV_toString(state, constants[ident]);
cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str, cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str,
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
cosmoV_setTop(state, 1); // pops the object cosmoV_setTop(state, 1); // pops the object
@ -962,13 +931,11 @@ int cosmoV_execute(CState *state)
// this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead // this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead
// of just cosmoV_get // of just cosmoV_get
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
if (!cosmoV_getMethod(state, cosmoV_readRef(*temp), constants[ident], &val)) cosmoV_getMethod(state, cosmoV_readRef(*temp), constants[ident], &val);
return -1;
} else { } else {
CObjString *field = cosmoV_toString(state, constants[ident]); CObjString *field = cosmoV_toString(state, constants[ident]);
cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str, cosmoV_error(state, "Couldn't get field '%s' from type %s!", field->str,
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
cosmoV_setTop(state, 1); // pops the object cosmoV_setTop(state, 1); // pops the object
@ -985,14 +952,12 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
// get the field from the object // get the field from the object
if (!cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val)) cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val);
return -1;
// now invoke the method! // now invoke the method!
invokeMethod(state, cosmoV_readRef(*temp), val, args, nres, 1); invokeMethod(state, cosmoV_readRef(*temp), val, args, nres, 1);
} else { } else {
cosmoV_error(state, "Couldn't get from type %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Couldn't get from type %s!", cosmoV_typeStr(*temp));
return -1;
} }
} }
CASE(OP_ITER) : CASE(OP_ITER) :
@ -1002,7 +967,6 @@ int cosmoV_execute(CState *state)
if (!IS_REF(*temp)) { if (!IS_REF(*temp)) {
cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_error(state, "Couldn't iterate over non-iterator type %s!",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
@ -1026,7 +990,6 @@ int cosmoV_execute(CState *state)
"Expected iterable object! '__iter' returned %s, expected " "Expected iterable object! '__iter' returned %s, expected "
"<object>!", "<object>!",
cosmoV_typeStr(*iObj)); cosmoV_typeStr(*iObj));
return -1;
} }
// get __next method and place it at the top of the stack // get __next method and place it at the top of the stack
@ -1034,7 +997,6 @@ int cosmoV_execute(CState *state)
cosmoV_newRef(state->iStrings[ISTRING_NEXT]), iObj); cosmoV_newRef(state->iStrings[ISTRING_NEXT]), iObj);
} else { } else {
cosmoV_error(state, "Expected iterable object! '__iter' not defined!"); cosmoV_error(state, "Expected iterable object! '__iter' not defined!");
return -1;
} }
} else if (obj->type == COBJ_TABLE) { } else if (obj->type == COBJ_TABLE) {
CObjTable *tbl = (CObjTable *)obj; CObjTable *tbl = (CObjTable *)obj;
@ -1059,7 +1021,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "No proto defined! Couldn't get from type %s", cosmoV_error(state, "No proto defined! Couldn't get from type %s",
cosmoO_typeStr(obj)); cosmoO_typeStr(obj));
return -1;
} }
} }
CASE(OP_NEXT) : CASE(OP_NEXT) :
@ -1071,7 +1032,6 @@ int cosmoV_execute(CState *state)
if (!IS_METHOD(*temp)) { if (!IS_METHOD(*temp)) {
cosmoV_error(state, "Expected '__next' to be a method, got type %s!", cosmoV_error(state, "Expected '__next' to be a method, got type %s!",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
cosmoV_pushValue(state, *temp); cosmoV_pushValue(state, *temp);
@ -1114,7 +1074,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA), cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA),
cosmoV_typeStr(*valB)); cosmoV_typeStr(*valB));
return -1;
} }
} }
CASE(OP_POW) : CASE(OP_POW) :
@ -1128,7 +1087,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA), cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA),
cosmoV_typeStr(*valB)); cosmoV_typeStr(*valB));
return -1;
} }
} }
CASE(OP_NOT) : CASE(OP_NOT) :
@ -1144,7 +1102,6 @@ int cosmoV_execute(CState *state)
cosmoV_pushNumber(state, -(cosmoV_readNumber(*val))); cosmoV_pushNumber(state, -(cosmoV_readNumber(*val)));
} else { } else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val)); cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
return -1;
} }
} }
CASE(OP_COUNT) : CASE(OP_COUNT) :
@ -1153,7 +1110,6 @@ int cosmoV_execute(CState *state)
if (!IS_REF(*temp)) { if (!IS_REF(*temp)) {
cosmoV_error(state, "Expected non-primitive, got %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Expected non-primitive, got %s!", cosmoV_typeStr(*temp));
return -1;
} }
int count = cosmoO_count(state, cosmoV_readRef(*temp)); int count = cosmoO_count(state, cosmoV_readRef(*temp));
@ -1178,7 +1134,6 @@ int cosmoV_execute(CState *state)
*val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc); *val = 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;
} }
} }
CASE(OP_INCGLOBAL) : CASE(OP_INCGLOBAL) :
@ -1194,7 +1149,6 @@ int cosmoV_execute(CState *state)
*val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc); *val = 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;
} }
} }
CASE(OP_INCUPVAL) : CASE(OP_INCUPVAL) :
@ -1209,7 +1163,6 @@ int cosmoV_execute(CState *state)
*val = cosmoV_newNumber(cosmoV_readNumber(*val) + inc); *val = 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;
} }
} }
CASE(OP_INCINDEX) : CASE(OP_INCINDEX) :
@ -1221,7 +1174,6 @@ int cosmoV_execute(CState *state)
if (!IS_REF(*temp)) { if (!IS_REF(*temp)) {
cosmoV_error(state, "Couldn't index non-indexable type %s!", cosmoV_error(state, "Couldn't index non-indexable type %s!",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
@ -1230,27 +1182,23 @@ int cosmoV_execute(CState *state)
// call __index if the proto was found // call __index if the proto was found
if (proto != NULL) { if (proto != NULL) {
if (cosmoO_indexObject(state, proto, *key, &val)) { cosmoO_indexObject(state, proto, *key, &val);
if (!IS_NUMBER(val)) {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
return -1;
}
cosmoV_pushValue(state, val); // pushes old value onto the stack :) if (!IS_NUMBER(val)) {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
}
// call __newindex cosmoV_pushValue(state, val); // pushes old value onto the stack :)
if (!cosmoO_newIndexObject(state, proto, *key,
cosmoV_newNumber(cosmoV_readNumber(val) + inc))) // call __newindex
return -1; cosmoO_newIndexObject(state, proto, *key,
} else cosmoV_newNumber(cosmoV_readNumber(val) + inc));
return -1; // cosmoO_indexObject failed and threw an error
} else if (obj->type == COBJ_TABLE) { } else if (obj->type == COBJ_TABLE) {
CObjTable *tbl = (CObjTable *)obj; CObjTable *tbl = (CObjTable *)obj;
CValue *val = cosmoT_insert(state, &tbl->tbl, *key); CValue *val = cosmoT_insert(state, &tbl->tbl, *key);
if (!IS_NUMBER(*val)) { if (!IS_NUMBER(*val)) {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val)); cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
return -1;
} }
// pops tbl & key from stack // pops tbl & key from stack
@ -1260,7 +1208,6 @@ int cosmoV_execute(CState *state)
} else { } else {
cosmoV_error(state, "No proto defined! Couldn't __index from type %s", cosmoV_error(state, "No proto defined! Couldn't __index from type %s",
cosmoV_typeStr(*temp)); cosmoV_typeStr(*temp));
return -1;
} }
} }
CASE(OP_INCOBJECT) : CASE(OP_INCOBJECT) :
@ -1275,8 +1222,7 @@ int cosmoV_execute(CState *state)
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
CValue val; CValue val;
if (!cosmoV_rawget(state, obj, ident, &val)) cosmoV_rawget(state, obj, ident, &val);
return -1;
// pop the object off the stack // pop the object off the stack
cosmoV_pop(state); cosmoV_pop(state);
@ -1284,16 +1230,13 @@ int cosmoV_execute(CState *state)
// check that it's a number value // check that it's a number value
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 :)
if (!cosmoV_rawset(state, obj, ident, cosmoV_rawset(state, obj, ident,
cosmoV_newNumber(cosmoV_readNumber(val) + inc))) cosmoV_newNumber(cosmoV_readNumber(val) + inc));
return -1;
} else { } else {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val)); cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
return -1;
} }
} else { } else {
cosmoV_error(state, "Couldn't set a field on type %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Couldn't set a field on type %s!", cosmoV_typeStr(*temp));
return -1;
} }
} }
CASE(OP_EQUAL) : CASE(OP_EQUAL) :

View File

@ -67,27 +67,17 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud); COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud);
/* /*
expects object to be pushed, then the key. expects object to be pushed, then the key. pops the key & object and pushes the value
returns false if an error was thrown, returns true if the value was pushed onto the stack and
the object and key were popped
*/ */
COSMO_API bool cosmoV_get(CState *state); COSMO_API void cosmoV_get(CState *state);
/* /*
expects object to be pushed, then the key, and finally the new value. expects object to be pushed, then the key, and finally the new value. pops the key & object
returns false if an error was thrown, returns true if the value was set and the object key, and
value were popped
*/ */
COSMO_API bool cosmoV_set(CState *state); COSMO_API void cosmoV_set(CState *state);
// wraps the closure into a CObjMethod, so the function is called as an invoked method // wraps the closure into a CObjMethod, so the function is called as an invoked method
COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val); COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val);
// clears the stack, callstack and restores the state into a usable state after a calloverflow or
// another hard to recover error (keeps the global table intact)
COSMO_API bool cosmoV_restore(CState *state);
// nice to have wrappers // nice to have wrappers