Minor CObj* refactor, added cosmoO_lock and cosmoO_unlock

- cosmoO_getUser* and cosmoO_setUser* no longer take the `CState*` argument
- if a set is performed on a locked object an error is thrown
This commit is contained in:
CPunch 2021-02-06 18:51:47 -06:00
parent 8151cde6f3
commit 5faa40bdef
4 changed files with 64 additions and 24 deletions

View File

@ -223,6 +223,7 @@ COSMO_API void cosmoB_loadObjLib(CState *state) {
// make the object and set the protoobject for all runtime-allocated objects
CObjObject *obj = cosmoV_makeObject(state, i + 2); // + 2 for the getter/setter tables
cosmoO_lock(obj); // lock so pesky people don't mess with it (feel free to remove if debugging)
cosmoV_registerProtoObject(state, COBJ_OBJECT, obj);
// register "object" to the global table
@ -431,6 +432,7 @@ void cosmoB_loadStrLib(CState *state) {
// make the object and set the protoobject for all strings
CObjObject *obj = cosmoV_makeObject(state, i);
cosmoO_lock(obj); // lock so pesky people don't mess with it (feel free to remove if debugging)
cosmoV_registerProtoObject(state, COBJ_STRING, obj);
// register "string" to the global table

View File

@ -114,6 +114,8 @@ CObjObject *cosmoO_newObject(CState *state) {
CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT);
obj->istringFlags = 0;
obj->userP = NULL; // reserved for C API
obj->userT = 0;
obj->isLocked = false;
cosmoV_pushObj(state, (CObj*)obj); // so our GC can keep track of it
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
cosmoV_pop(state);
@ -332,7 +334,13 @@ bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *v
void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj) {
CValue ret;
// first check for __setters
// if the object is locked, throw an error
if (proto->isLocked) {
cosmoV_error(state, "Couldn't set on a locked object!");
return;
}
// check for __setters
if (cosmoO_getIString(state, proto, ISTRING_SETTER, &ret) && IS_TABLE(ret) && cosmoT_get(&cosmoV_readTable(ret)->tbl, key, &ret)) {
cosmoV_pushValue(state, ret); // push function
cosmoV_pushObj(state, (CObj*)obj); // push object
@ -353,22 +361,38 @@ void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue va
}
}
void cosmoO_setUserP(CState *state, CObjObject *object, void *p) {
void cosmoO_setUserP(CObjObject *object, void *p) {
object->userP = p;
}
void *cosmoO_getUserP(CState *state, CObjObject *object) {
void *cosmoO_getUserP(CObjObject *object) {
return object->userP;
}
void cosmoO_setUserI(CState *state, CObjObject *object, int i) {
void cosmoO_setUserI(CObjObject *object, int i) {
object->userI = i;
}
int cosmoO_getUserI(CState *state, CObjObject *object) {
int cosmoO_getUserI(CObjObject *object) {
return object->userI;
}
void cosmoO_setUserT(CObjObject *object, int t) {
object->userT = t;
}
int cosmoO_getUserT(CObjObject *object) {
return object->userT;
}
void cosmoO_lock(CObjObject *object) {
object->isLocked = true;
}
void cosmoO_unlock(CObjObject *object) {
object->isLocked = false;
}
bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val) {
if (readFlag(object->istringFlags, flag))
return false; // it's been cached as bad

View File

@ -33,38 +33,40 @@ typedef uint32_t cosmo_Flag;
typedef int (*CosmoCFunction)(CState *state, int argCount, CValue *args);
typedef struct CObj {
CObjType type;
bool isMarked; // for the GC
struct CObj *next;
struct CObj *nextRoot; // for the root linked list
struct CObjObject *proto; // protoobject, describes the behavior of the object
CObjType type;
bool isMarked; // for the GC
} CObj;
typedef struct CObjString {
CommonHeader; // "is a" CObj
bool isIString;
int length;
char *str; // NULL termincated string
uint32_t hash; // for hashtable lookup
int length;
bool isIString;
} CObjString;
typedef struct CObjError {
CommonHeader; // "is a" CObj
bool parserError; // if true, cosmoV_printError will format the error to the lexer
int frameCount;
int line; // reserved for parser errors
CValue err; // error string
CCallFrame *frames;
int frameCount;
int line; // reserved for parser errors
bool parserError; // if true, cosmoV_printError will format the error to the lexer
} CObjError;
typedef struct CObjObject {
CommonHeader; // "is a" CObj
cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.)
CTable tbl;
cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.)
union { // userdata (NULL by default)
void *userP;
int userI;
};
int userT; // user-defined type (for describing the userdata pointer/integer)
bool isLocked;
} CObjObject;
typedef struct CObjTable { // table, a wrapper for CTable
@ -75,11 +77,11 @@ typedef struct CObjTable { // table, a wrapper for CTable
typedef struct CObjFunction {
CommonHeader; // "is a" CObj
CChunk chunk;
CObjString *name;
CObjString *module; // name of the "module"
int args;
int upvals;
bool variadic;
CObjString *name;
CObjString *module; // name of the "module"
} CObjFunction;
typedef struct CObjCFunction {
@ -96,14 +98,14 @@ typedef struct CObjClosure {
typedef struct CObjMethod {
CommonHeader; // "is a " CObj
CObj *obj; // obj this method is bound too
CValue func;
CObj *obj; // obj this method is bound too
} CObjMethod;
typedef struct CObjUpval {
CommonHeader; // "is a" CObj
CValue *val;
CValue closed;
CValue *val;
struct CObjUpval *next;
} CObjUpval;
@ -161,10 +163,22 @@ void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue va
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val);
void cosmoO_setUserP(CState *state, CObjObject *object, void *p);
void *cosmoO_getUserP(CState *state, CObjObject *object);
void cosmoO_setUserI(CState *state, CObjObject *object, int i);
int cosmoO_getUserI(CState *state, CObjObject *object);
// sets the user-defined pointer, if a user-define integer is already defined it will be over written
void cosmoO_setUserP(CObjObject *object, void *p);
// gets the user-defined pointer
void *cosmoO_getUserP(CObjObject *object);
// sets the user-defined integer, if a user-define pointer is already defined it will be over written
void cosmoO_setUserI(CObjObject *object, int i);
// gets the user-defined integer
int cosmoO_getUserI(CObjObject *object);
// sets the user-defined type
void cosmoO_setUserT(CObjObject *object, int t);
// gets the user type
int cosmoO_getUserT(CObjObject *object);
// locks the object
void cosmoO_lock(CObjObject *object);
// unlocks the object
void cosmoO_unlock(CObjObject *object);
// internal string
bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val);

View File

@ -514,7 +514,7 @@ int _tbl__next(CState *state, int nargs, CValue *args) {
}
CObjObject *obj = cosmoV_readObject(args[0]);
int index = cosmoO_getUserI(state, obj); // we store the index in the userdata
int index = cosmoO_getUserI(obj); // we store the index in the userdata
CValue val;
cosmoO_getIString(state, obj, ISTRING_RESERVED, &val);
@ -531,7 +531,7 @@ int _tbl__next(CState *state, int nargs, CValue *args) {
do {
entry = &table->tbl.table[index++];
} while (IS_NIL(entry->key) && index < cap);
cosmoO_setUserI(state, obj, index); // update the userdata
cosmoO_setUserI(obj, index); // update the userdata
if (index < cap && !IS_NIL(entry->key)) { // if the entry is valid, return it's key and value pair
cosmoV_pushValue(state, entry->key);
@ -887,7 +887,7 @@ int cosmoV_execute(CState *state) {
cosmoV_pushObj(state, (CObj*)tbl_next); // value
CObjObject *obj = cosmoV_makeObject(state, 2); // pushes the new object to the stack
cosmoO_setUserI(state, obj, 0); // increment for iterator
cosmoO_setUserI(obj, 0); // increment for iterator
// make our CObjMethod for OP_NEXT to call
CObjMethod *method = cosmoO_newMethod(state, cosmoV_newObj(tbl_next), (CObj*)obj);