mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-12-22 22:40:03 +00:00
refactored cosmoV_set & cosmoV_get, renamed COSMO_TOBJ->COSMO_TREF
also changed print() to print raw primitives instead of generating a <string> needlessly. helped performance immensely in scripts like `examples/increment.cosmo`
This commit is contained in:
parent
0d344f65df
commit
78e21a0f28
@ -10,8 +10,12 @@
|
||||
|
||||
int cosmoB_print(CState *state, int nargs, CValue *args) {
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
CObjString *str = cosmoV_toString(state, args[i]);
|
||||
printf("%s", cosmoO_readCString(str));
|
||||
if (IS_REF(args[i])) { // if its a CObj*, generate the CObjString
|
||||
CObjString *str = cosmoV_toString(state, args[i]);
|
||||
printf("%s", cosmoO_readCString(str));
|
||||
} else { // else, thats pretty expensive for primitives, just print the raw value
|
||||
printValue(args[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@ -173,7 +177,7 @@ int cosmoB_oisChild(CState *state, int nargs, CValue *args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!IS_OBJ(args[0]) || !IS_OBJECT(args[1])) {
|
||||
if (!IS_REF(args[0]) || !IS_OBJECT(args[1])) {
|
||||
cosmoV_typeError(state, "object.ischild()", "<reference obj>, <object>", "%s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void tableRemoveWhite(CState *state, CTable *tbl) {
|
||||
int cap = tbl->capacityMask + 1;
|
||||
for (int i = 0; i < cap; i++) {
|
||||
CTableEntry *entry = &tbl->table[i];
|
||||
if (IS_OBJ(entry->key) && !(cosmoV_readRef(entry->key))->isMarked) { // if the key is a object and it's white (unmarked), remove it from the table
|
||||
if (IS_REF(entry->key) && !(cosmoV_readRef(entry->key))->isMarked) { // if the key is a object and it's white (unmarked), remove it from the table
|
||||
cosmoT_remove(state, tbl, entry->key);
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,7 @@ void markObject(CState *state, CObj *obj) {
|
||||
}
|
||||
|
||||
void markValue(CState *state, CValue val) {
|
||||
if (IS_OBJ(val))
|
||||
if (IS_REF(val))
|
||||
markObject(state, cosmoV_readRef(val));
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ typedef struct CObjUpval {
|
||||
#define cosmoO_readCString(x) ((CObjString*)x)->str
|
||||
|
||||
static inline bool isObjType(CValue val, CObjType type) {
|
||||
return IS_OBJ(val) && cosmoV_readRef(val)->type == type;
|
||||
return IS_REF(val) && cosmoV_readRef(val)->type == type;
|
||||
}
|
||||
|
||||
// just protects against macro expansion
|
||||
|
@ -66,7 +66,7 @@ uint32_t getObjectHash(CObj *obj) {
|
||||
|
||||
uint32_t getValueHash(CValue *val) {
|
||||
switch (GET_TYPE(*val)) {
|
||||
case COSMO_TOBJ:
|
||||
case COSMO_TREF:
|
||||
return getObjectHash(cosmoV_readRef(*val));
|
||||
case COSMO_TNUMBER: {
|
||||
uint32_t buf[sizeof(cosmo_Number)/sizeof(uint32_t)];
|
||||
|
10
src/cvalue.c
10
src/cvalue.c
@ -27,7 +27,7 @@ bool cosmoV_equal(CValue valA, CValue valB) {
|
||||
switch (GET_TYPE(valA)) {
|
||||
case COSMO_TBOOLEAN: return cosmoV_readBoolean(valA) == cosmoV_readBoolean(valB);
|
||||
case COSMO_TNUMBER: return cosmoV_readNumber(valA) == cosmoV_readNumber(valB);
|
||||
case COSMO_TOBJ: return cosmoO_equal(cosmoV_readRef(valA), cosmoV_readRef(valB));
|
||||
case COSMO_TREF: return cosmoO_equal(cosmoV_readRef(valA), cosmoV_readRef(valB));
|
||||
case COSMO_TNIL: return true;
|
||||
default:
|
||||
return false;
|
||||
@ -44,7 +44,7 @@ CObjString *cosmoV_toString(CState *state, CValue val) {
|
||||
case COSMO_TBOOLEAN: {
|
||||
return cosmoV_readBoolean(val) ? cosmoO_copyString(state, "true", 4) : cosmoO_copyString(state, "false", 5);
|
||||
}
|
||||
case COSMO_TOBJ: {
|
||||
case COSMO_TREF: {
|
||||
return cosmoO_toString(state, cosmoV_readRef(val));
|
||||
}
|
||||
case COSMO_TNIL: {
|
||||
@ -63,7 +63,7 @@ cosmo_Number cosmoV_toNumber(CState *state, CValue val) {
|
||||
case COSMO_TBOOLEAN: {
|
||||
return cosmoV_readBoolean(val) ? 1 : 0;
|
||||
}
|
||||
case COSMO_TOBJ: {
|
||||
case COSMO_TREF: {
|
||||
return cosmoO_toNumber(state, cosmoV_readRef(val));
|
||||
}
|
||||
case COSMO_TNIL: // fall through
|
||||
@ -77,7 +77,7 @@ const char *cosmoV_typeStr(CValue val) {
|
||||
case COSMO_TNIL: return "<nil>";
|
||||
case COSMO_TBOOLEAN: return "<bool>";
|
||||
case COSMO_TNUMBER: return "<number>";
|
||||
case COSMO_TOBJ: return cosmoO_typeStr(cosmoV_readRef(val));
|
||||
case COSMO_TREF: return cosmoO_typeStr(cosmoV_readRef(val));
|
||||
|
||||
default:
|
||||
return "<unkn val>";
|
||||
@ -92,7 +92,7 @@ void printValue(CValue val) {
|
||||
case COSMO_TBOOLEAN:
|
||||
printf(cosmoV_readBoolean(val) ? "true" : "false");
|
||||
break;
|
||||
case COSMO_TOBJ: {
|
||||
case COSMO_TREF: {
|
||||
printObject(cosmoV_readRef(val));
|
||||
break;
|
||||
}
|
||||
|
10
src/cvalue.h
10
src/cvalue.h
@ -6,7 +6,7 @@
|
||||
typedef enum {
|
||||
COSMO_TNUMBER, // number has to be 0 because NaN box
|
||||
COSMO_TBOOLEAN,
|
||||
COSMO_TOBJ,
|
||||
COSMO_TREF,
|
||||
COSMO_TNIL,
|
||||
} CosmoType;
|
||||
|
||||
@ -47,7 +47,7 @@ typedef union CValue {
|
||||
|
||||
#define SIG_MASK (MASK_QUIETNAN | MASK_TYPE)
|
||||
#define BOOL_SIG (MASK_QUIETNAN | ((uint64_t)(COSMO_TBOOLEAN) << 48))
|
||||
#define OBJ_SIG (MASK_QUIETNAN | ((uint64_t)(COSMO_TOBJ) << 48))
|
||||
#define OBJ_SIG (MASK_QUIETNAN | ((uint64_t)(COSMO_TREF) << 48))
|
||||
#define NIL_SIG (MASK_QUIETNAN | ((uint64_t)(COSMO_TNIL) << 48))
|
||||
|
||||
#define cosmoV_newNumber(x) ((CValue){.num = x})
|
||||
@ -62,7 +62,7 @@ typedef union CValue {
|
||||
#define IS_NUMBER(x) (((x).data & MASK_QUIETNAN) != MASK_QUIETNAN)
|
||||
#define IS_BOOLEAN(x) (((x).data & SIG_MASK) == BOOL_SIG)
|
||||
#define IS_NIL(x) (((x).data & SIG_MASK) == NIL_SIG)
|
||||
#define IS_OBJ(x) (((x).data & SIG_MASK) == OBJ_SIG)
|
||||
#define IS_REF(x) (((x).data & SIG_MASK) == OBJ_SIG)
|
||||
|
||||
#else
|
||||
/*
|
||||
@ -83,7 +83,7 @@ typedef struct CValue {
|
||||
|
||||
#define cosmoV_newNumber(x) ((CValue){COSMO_TNUMBER, {.num = (x)}})
|
||||
#define cosmoV_newBoolean(x) ((CValue){COSMO_TBOOLEAN, {.b = (x)}})
|
||||
#define cosmoV_newRef(x) ((CValue){COSMO_TOBJ, {.obj = (CObj*)(x)}})
|
||||
#define cosmoV_newRef(x) ((CValue){COSMO_TREF, {.obj = (CObj*)(x)}})
|
||||
#define cosmoV_newNil() ((CValue){COSMO_TNIL, {.num = 0}})
|
||||
|
||||
// read CValues
|
||||
@ -97,7 +97,7 @@ typedef struct CValue {
|
||||
#define IS_NUMBER(x) (GET_TYPE(x) == COSMO_TNUMBER)
|
||||
#define IS_BOOLEAN(x) (GET_TYPE(x) == COSMO_TBOOLEAN)
|
||||
#define IS_NIL(x) (GET_TYPE(x) == COSMO_TNIL)
|
||||
#define IS_OBJ(x) (GET_TYPE(x) == COSMO_TOBJ)
|
||||
#define IS_REF(x) (GET_TYPE(x) == COSMO_TREF)
|
||||
|
||||
#endif
|
||||
|
||||
|
76
src/cvm.c
76
src/cvm.c
@ -306,7 +306,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset)
|
||||
printf("(%d args)\n", args);
|
||||
#endif
|
||||
|
||||
if (!IS_OBJ(func)) {
|
||||
if (!IS_REF(func)) {
|
||||
cosmoV_error(state, "Cannot call non-callable type %s!", cosmoV_typeStr(func));
|
||||
return false;
|
||||
}
|
||||
@ -449,7 +449,7 @@ COSMO_API void cosmoV_makeTable(CState *state, int pairs) {
|
||||
cosmoV_pushRef(state, (CObj*)newObj);
|
||||
}
|
||||
|
||||
COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) {
|
||||
bool cosmoV_rawget(CState *state, CObj *_obj, CValue key, CValue *val) {
|
||||
CObjObject *object = cosmoO_grabProto(_obj);
|
||||
|
||||
// no proto to get from
|
||||
@ -472,7 +472,7 @@ COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) {
|
||||
return false;
|
||||
}
|
||||
|
||||
COSMO_API bool cosmoV_set(CState *state, CObj *_obj, CValue key, CValue val) {
|
||||
bool cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val) {
|
||||
CObjObject *object = cosmoO_grabProto(_obj);
|
||||
|
||||
// no proto to set to
|
||||
@ -486,8 +486,46 @@ COSMO_API bool cosmoV_set(CState *state, CObj *_obj, CValue key, CValue val) {
|
||||
return true;
|
||||
}
|
||||
|
||||
COSMO_API bool cosmoV_get(CState *state) {
|
||||
CValue val;
|
||||
StkPtr obj = cosmoV_getTop(state, 1); // object was pushed first
|
||||
StkPtr key = cosmoV_getTop(state, 0); // then the key
|
||||
|
||||
if (!IS_REF(*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))
|
||||
return false;
|
||||
|
||||
// pop the obj & key, push the value
|
||||
cosmoV_setTop(state, 2);
|
||||
cosmoV_pushValue(state, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
// yes, this would technically make it possible to set fields of types other than <string>. go crazy
|
||||
COSMO_API bool cosmoV_set(CState *state) {
|
||||
StkPtr obj = cosmoV_getTop(state, 2); // object was pushed first
|
||||
StkPtr key = cosmoV_getTop(state, 1); // then the key
|
||||
StkPtr val = cosmoV_getTop(state, 0); // and finally the value
|
||||
|
||||
if (!IS_REF(*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))
|
||||
return false;
|
||||
|
||||
// pop the obj, key & value
|
||||
cosmoV_setTop(state, 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val) {
|
||||
if (!cosmoV_get(state, obj, key, val))
|
||||
if (!cosmoV_rawget(state, obj, key, val))
|
||||
return false;
|
||||
|
||||
// if the result is callable, wrap it in an method
|
||||
@ -701,7 +739,7 @@ int cosmoV_execute(CState *state) {
|
||||
StkPtr temp = cosmoV_getTop(state, 1); // after that should be the table
|
||||
|
||||
// sanity check
|
||||
if (!IS_OBJ(*temp)) {
|
||||
if (!IS_REF(*temp)) {
|
||||
cosmoV_error(state, "Couldn't index type %s!", cosmoV_typeStr(*temp));
|
||||
return -1;
|
||||
}
|
||||
@ -733,7 +771,7 @@ int cosmoV_execute(CState *state) {
|
||||
StkPtr temp = cosmoV_getTop(state, 2); // table is after the key
|
||||
|
||||
// sanity check
|
||||
if (!IS_OBJ(*temp)) {
|
||||
if (!IS_REF(*temp)) {
|
||||
cosmoV_error(state, "Couldn't set index with type %s!", cosmoV_typeStr(*temp));
|
||||
return -1;
|
||||
}
|
||||
@ -769,8 +807,8 @@ int cosmoV_execute(CState *state) {
|
||||
uint16_t ident = READUINT(); // use for the key
|
||||
|
||||
// sanity check
|
||||
if (IS_OBJ(*temp)) {
|
||||
if (!cosmoV_set(state, cosmoV_readRef(*temp), constants[ident], *value))
|
||||
if (IS_REF(*temp)) {
|
||||
if (!cosmoV_rawset(state, cosmoV_readRef(*temp), constants[ident], *value))
|
||||
return -1;
|
||||
} else {
|
||||
CObjString *field = cosmoV_toString(state, constants[ident]);
|
||||
@ -788,8 +826,8 @@ int cosmoV_execute(CState *state) {
|
||||
uint16_t ident = READUINT(); // use for the key
|
||||
|
||||
// sanity check
|
||||
if (IS_OBJ(*temp)) {
|
||||
if (!cosmoV_get(state, cosmoV_readRef(*temp), constants[ident], &val))
|
||||
if (IS_REF(*temp)) {
|
||||
if (!cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val))
|
||||
return -1;
|
||||
} else {
|
||||
CObjString *field = cosmoV_toString(state, constants[ident]);
|
||||
@ -807,7 +845,7 @@ int cosmoV_execute(CState *state) {
|
||||
uint16_t ident = READUINT(); // use for the key
|
||||
|
||||
// this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead of just cosmoV_get
|
||||
if (IS_OBJ(*temp)) {
|
||||
if (IS_REF(*temp)) {
|
||||
if (!cosmoV_getMethod(state, cosmoV_readRef(*temp), constants[ident], &val))
|
||||
return -1;
|
||||
} else {
|
||||
@ -828,9 +866,9 @@ int cosmoV_execute(CState *state) {
|
||||
CValue val; // to hold our value
|
||||
|
||||
// sanity check
|
||||
if (IS_OBJ(*temp)) {
|
||||
if (IS_REF(*temp)) {
|
||||
// get the field from the object
|
||||
if (!cosmoV_get(state, cosmoV_readRef(*temp), constants[ident], &val))
|
||||
if (!cosmoV_rawget(state, cosmoV_readRef(*temp), constants[ident], &val))
|
||||
return -1;
|
||||
|
||||
// now invoke the method!
|
||||
@ -845,7 +883,7 @@ int cosmoV_execute(CState *state) {
|
||||
case OP_ITER: {
|
||||
StkPtr temp = cosmoV_getTop(state, 0); // should be the object/table
|
||||
|
||||
if (!IS_OBJ(*temp)) {
|
||||
if (!IS_REF(*temp)) {
|
||||
cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_typeStr(*temp));
|
||||
return -1;
|
||||
}
|
||||
@ -968,7 +1006,7 @@ int cosmoV_execute(CState *state) {
|
||||
case OP_COUNT: {
|
||||
StkPtr temp = cosmoV_getTop(state, 0);
|
||||
|
||||
if (!IS_OBJ(*temp)) {
|
||||
if (!IS_REF(*temp)) {
|
||||
cosmoV_error(state, "Expected non-primitive, got %s!", cosmoV_typeStr(*temp));
|
||||
return -1;
|
||||
}
|
||||
@ -1038,7 +1076,7 @@ int cosmoV_execute(CState *state) {
|
||||
StkPtr temp = cosmoV_getTop(state, 1); // object should be above the key
|
||||
StkPtr key = cosmoV_getTop(state, 0); // grabs key
|
||||
|
||||
if (!IS_OBJ(*temp)) {
|
||||
if (!IS_REF(*temp)) {
|
||||
cosmoV_error(state, "Couldn't index non-indexable type %s!", cosmoV_typeStr(*temp));
|
||||
return -1;
|
||||
}
|
||||
@ -1089,11 +1127,11 @@ int cosmoV_execute(CState *state) {
|
||||
CValue ident = constants[indx]; // grabs identifier
|
||||
|
||||
// sanity check
|
||||
if (IS_OBJ(*temp)) {
|
||||
if (IS_REF(*temp)) {
|
||||
CObj *obj = cosmoV_readRef(*temp);
|
||||
CValue val;
|
||||
|
||||
if (!cosmoV_get(state, obj, ident, &val))
|
||||
if (!cosmoV_rawget(state, obj, ident, &val))
|
||||
return -1;
|
||||
|
||||
// pop the object off the stack
|
||||
@ -1102,7 +1140,7 @@ int cosmoV_execute(CState *state) {
|
||||
// check that it's a number value
|
||||
if (IS_NUMBER(val)) {
|
||||
cosmoV_pushValue(state, val); // pushes old value onto the stack :)
|
||||
if (!cosmoV_set(state, obj, ident, cosmoV_newNumber(cosmoV_readNumber(val) + inc)))
|
||||
if (!cosmoV_rawset(state, obj, ident, cosmoV_newNumber(cosmoV_readNumber(val) + inc)))
|
||||
return -1;
|
||||
} else {
|
||||
cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(val));
|
||||
|
16
src/cvm.h
16
src/cvm.h
@ -40,8 +40,20 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
|
||||
*/
|
||||
COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name);
|
||||
|
||||
COSMO_API bool cosmoV_get(CState *state, CObj *obj, CValue key, CValue *val);
|
||||
COSMO_API bool cosmoV_set(CState *state, CObj *obj, CValue key, CValue val);
|
||||
/*
|
||||
expects object to be pushed, then the key.
|
||||
|
||||
if returns false an error was thrown, if returns true the value was pushed onto the stack and the object and key were popped
|
||||
*/
|
||||
COSMO_API bool cosmoV_get(CState *state);
|
||||
|
||||
/*
|
||||
expects object to be pushed, then the key, and finally the new value.
|
||||
|
||||
if returns false an error was thrown, if returns true the value was set and the object key, and value were popped
|
||||
*/
|
||||
COSMO_API bool cosmoV_set(CState *state);
|
||||
|
||||
// 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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user