Compare commits

..

No commits in common. "1544332b9039d5c8e214efbbe0d80964453362ff" and "5a00d6164607d0eaec63c0145d16203868ce8125" have entirely different histories.

5 changed files with 122 additions and 50 deletions

View File

@ -19,9 +19,9 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: CMake - name: CMake
run: cmake -B build -DCMAKE_BUILD_TYPE=Release run: cmake -B build
- name: Build - name: Build
run: cmake --build build --config Release run: cmake --build build
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:

View File

@ -397,7 +397,7 @@ bool cosmoO_isDescendant(CObj *obj, CObjObject *proto)
} }
// returns false if error thrown // returns false if error thrown
void cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj) bool 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,17 +407,18 @@ void 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; return true;
} }
// maybe the field is defined in the proto? if (proto->_obj.proto != NULL &&
if (proto->_obj.proto != NULL) { cosmoO_getRawObject(state, proto->_obj.proto, key, val, obj))
cosmoO_getRawObject(state, proto->_obj.proto, key, val, obj); return true;
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)
@ -518,7 +519,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
} }
void cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val) bool 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
@ -526,12 +527,15 @@ void 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
} else { // there's no __index function defined! return true;
} 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;
} }
void cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val) bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val)
{ {
CValue ret; // return value for cosmoO_getIString CValue ret; // return value for cosmoO_getIString
@ -541,9 +545,12 @@ void 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,8 +3,6 @@
#include "cosmo.h" #include "cosmo.h"
#include <stdarg.h>
typedef enum CObjType typedef enum CObjType
{ {
COBJ_STRING, COBJ_STRING,
@ -174,10 +172,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;
} }
void cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj); bool 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);
void cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val); bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
void cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val); bool 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);
} }
void cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val) bool cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val)
{ {
CObjObject *object = cosmoO_grabProto(_obj); CObjObject *object = cosmoO_grabProto(_obj);
@ -506,16 +506,23 @@ void 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);
cosmoO_getRawObject(state, object, key, val, _obj); if (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;
} }
void cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val) bool cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val)
{ {
CObjObject *object = cosmoO_grabProto(_obj); CObjObject *object = cosmoO_grabProto(_obj);
@ -524,12 +531,14 @@ void 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 void cosmoV_get(CState *state) COSMO_API bool 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
@ -537,17 +546,20 @@ COSMO_API void 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;
} }
cosmoV_rawget(state, cosmoV_readRef(*obj), *key, &val); if (!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 void cosmoV_set(CState *state) COSMO_API bool 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
@ -555,17 +567,21 @@ COSMO_API void 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;
} }
cosmoV_rawset(state, cosmoV_readRef(*obj), *key, *val); if (!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 void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val) COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
{ {
cosmoV_rawget(state, obj, key, val); if (!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)) {
@ -575,6 +591,8 @@ COSMO_API void 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)
@ -678,7 +696,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
@ -831,6 +849,7 @@ 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);
@ -839,7 +858,9 @@ int cosmoV_execute(CState *state)
if (proto != NULL) { if (proto != NULL) {
// check for __index metamethod // check for __index metamethod
cosmoO_indexObject(state, proto, *key, &val); if (!cosmoO_indexObject(state, proto, *key,
&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;
@ -847,6 +868,7 @@ 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
@ -861,13 +883,17 @@ 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) {
cosmoO_newIndexObject(state, proto, *key, *value); if (!cosmoO_newIndexObject(
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);
@ -876,6 +902,7 @@ 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
@ -894,11 +921,13 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
cosmoV_rawset(state, cosmoV_readRef(*temp), constants[ident], *value); if (!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
@ -912,11 +941,13 @@ int cosmoV_execute(CState *state)
// sanity check // sanity check
if (IS_REF(*temp)) { if (IS_REF(*temp)) {
cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val); if (!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
@ -931,11 +962,13 @@ 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)) {
cosmoV_getMethod(state, cosmoV_readRef(*temp), constants[ident], &val); if (!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
@ -952,12 +985,14 @@ 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
cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val); if (!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) :
@ -967,6 +1002,7 @@ 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);
@ -990,6 +1026,7 @@ 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
@ -997,6 +1034,7 @@ 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;
@ -1021,6 +1059,7 @@ 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) :
@ -1032,6 +1071,7 @@ 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);
@ -1074,6 +1114,7 @@ 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) :
@ -1087,6 +1128,7 @@ 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) :
@ -1102,6 +1144,7 @@ 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) :
@ -1110,6 +1153,7 @@ 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));
@ -1134,6 +1178,7 @@ 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) :
@ -1149,6 +1194,7 @@ 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) :
@ -1163,6 +1209,7 @@ 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) :
@ -1174,6 +1221,7 @@ 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);
@ -1182,23 +1230,27 @@ 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) {
cosmoO_indexObject(state, proto, *key, &val); if (cosmoO_indexObject(state, proto, *key, &val)) {
if (!IS_NUMBER(val)) {
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
return -1;
}
if (!IS_NUMBER(val)) { cosmoV_pushValue(state, val); // pushes old value onto the stack :)
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
}
cosmoV_pushValue(state, val); // pushes old value onto the stack :) // call __newindex
if (!cosmoO_newIndexObject(state, proto, *key,
// call __newindex cosmoV_newNumber(cosmoV_readNumber(val) + inc)))
cosmoO_newIndexObject(state, proto, *key, return -1;
cosmoV_newNumber(cosmoV_readNumber(val) + inc)); } else
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
@ -1208,6 +1260,7 @@ 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) :
@ -1222,7 +1275,8 @@ int cosmoV_execute(CState *state)
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
CValue val; CValue val;
cosmoV_rawget(state, obj, ident, &val); if (!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);
@ -1230,13 +1284,16 @@ 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 :)
cosmoV_rawset(state, obj, ident, if (!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,17 +67,27 @@ 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. pops the key & object and pushes the value expects object to be pushed, then the key.
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 void cosmoV_get(CState *state); COSMO_API bool cosmoV_get(CState *state);
/* /*
expects object to be pushed, then the key, and finally the new value. pops the key & object expects object to be pushed, then the key, and finally the new value.
returns false if an error was thrown, returns true if the value was set and the object key, and
value were popped
*/ */
COSMO_API void cosmoV_set(CState *state); COSMO_API bool 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 void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val); COSMO_API bool 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