diff --git a/src/cbaselib.c b/src/cbaselib.c index f8d29c5..983c230 100644 --- a/src/cbaselib.c +++ b/src/cbaselib.c @@ -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 diff --git a/src/cobj.c b/src/cobj.c index b70b13d..0c23296 100644 --- a/src/cobj.c +++ b/src/cobj.c @@ -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 diff --git a/src/cobj.h b/src/cobj.h index fd15cfe..a0b8f98 100644 --- a/src/cobj.h +++ b/src/cobj.h @@ -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); diff --git a/src/cvm.c b/src/cvm.c index 84dd60f..9b1b5e1 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -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);