removed 'roots', replaced with a registry table

- removed cosmoM_addRoot
- removed cosmoM_removeRoot
- renamed cosmoV_register to cosmoV_addGlobals
- added cosmoV_addRegistry
- added cosmoV_getRegistry
- added cosmoV_setProto
- added cosmoV_isValueUserType
This commit is contained in:
CPunch 2023-09-05 14:35:29 -05:00 committed by cpunch
parent 6701a63a63
commit bf36412699
9 changed files with 121 additions and 93 deletions

4
main.c
View File

@ -75,7 +75,7 @@ static void repl(CState *state)
cosmoV_pushString(state, "input"); cosmoV_pushString(state, "input");
cosmoV_pushCFunction(state, cosmoB_input); cosmoV_pushCFunction(state, cosmoB_input);
cosmoV_register(state, 2); cosmoV_addGlobals(state, 2);
while (_ACTIVE) { while (_ACTIVE) {
if (!(line = linenoise("> "))) { // better than gets() if (!(line = linenoise("> "))) { // better than gets()
@ -130,7 +130,7 @@ static bool runFile(CState *state, const char *fileName)
cosmoV_pushString(state, "input"); cosmoV_pushString(state, "input");
cosmoV_pushCFunction(state, cosmoB_input); cosmoV_pushCFunction(state, cosmoB_input);
cosmoV_register(state, 1); cosmoV_addGlobals(state, 1);
ret = interpret(state, script, fileName); ret = interpret(state, script, fileName);

View File

@ -6,6 +6,7 @@
#include "cstate.h" #include "cstate.h"
#include "ctable.h" #include "ctable.h"
#include "cvalue.h" #include "cvalue.h"
#include "cvm.h"
// realloc wrapper // realloc wrapper
void *cosmoM_reallocate(CState *state, void *buf, size_t oldSize, size_t newSize) void *cosmoM_reallocate(CState *state, void *buf, size_t oldSize, size_t newSize)
@ -246,22 +247,23 @@ static void sweep(CState *state)
prev->next = object; prev->next = object;
} }
// call __gc on the object
CObjObject *protoObject = cosmoO_grabProto(oldObj);
CValue res;
// use user-defined __gc
if (protoObject != NULL && cosmoO_getIString(state, protoObject, ISTRING_GC, &res)) {
cosmoV_pushValue(state, res);
cosmoV_pushRef(state, (CObj *)oldObj);
cosmoV_call(state, 1, 0);
}
cosmoO_free(state, oldObj); cosmoO_free(state, oldObj);
} }
} }
} }
static void markUserRoots(CState *state)
{
CObj *root = state->userRoots;
// traverse userRoots and mark all the object
while (root != NULL) {
markObject(state, root);
root = root->nextRoot;
}
}
static void markRoots(CState *state) static void markRoots(CState *state)
{ {
// mark all values on the stack // mark all values on the stack
@ -285,8 +287,7 @@ static void markRoots(CState *state)
for (int i = 0; i < ISTRING_MAX; i++) for (int i = 0; i < ISTRING_MAX; i++)
markObject(state, (CObj *)state->iStrings[i]); markObject(state, (CObj *)state->iStrings[i]);
// mark the user defined roots markTable(state, &state->registry);
markUserRoots(state);
for (int i = 0; i < COBJ_MAX; i++) for (int i = 0; i < COBJ_MAX; i++)
markObject(state, (CObj *)state->protoObjects[i]); markObject(state, (CObj *)state->protoObjects[i]);
@ -323,44 +324,3 @@ COSMO_API void cosmoM_updateThreshhold(CState *state)
{ {
state->nextGC = state->allocatedBytes * HEAP_GROW_FACTOR; state->nextGC = state->allocatedBytes * HEAP_GROW_FACTOR;
} }
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot)
{
// first, check and make sure this root doesn't already exist in the list
CObj *root = state->userRoots;
while (root != NULL) {
if (root == newRoot) // found in the list, abort
return;
root = root->nextRoot;
}
// adds root to userRoot linked list
newRoot->nextRoot = state->userRoots;
state->userRoots = newRoot;
}
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot)
{
CObj *prev = NULL;
CObj *root = state->userRoots;
// traverse the userRoot linked list
while (root != NULL) {
if (root == oldRoot) { // found root in list
// remove from the linked list
if (prev == NULL) {
state->userRoots = root->nextRoot;
} else {
prev->nextRoot = root->nextRoot;
}
root->nextRoot = NULL;
break;
}
prev = root;
root = root->nextRoot;
}
}

View File

@ -67,13 +67,6 @@ COSMO_API bool cosmoM_checkGarbage(CState *state,
COSMO_API void cosmoM_collectGarbage(CState *state); COSMO_API void cosmoM_collectGarbage(CState *state);
COSMO_API void cosmoM_updateThreshhold(CState *state); COSMO_API void cosmoM_updateThreshhold(CState *state);
// lets the VM know you are holding a reference to a CObj and to not free it
// NOTE: prefer to use the stack when possible
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot);
// lets the VM know this root is no longer held in a reference and is able to be freed
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot);
// wrapper for cosmoM_reallocate so we can track our memory usage // wrapper for cosmoM_reallocate so we can track our memory usage
static inline void *cosmoM_xmalloc(CState *state, size_t sz) static inline void *cosmoM_xmalloc(CState *state, size_t sz)
{ {

View File

@ -31,7 +31,6 @@ CObj *cosmoO_allocateBase(CState *state, size_t sz, CObjType type)
obj->next = state->objects; obj->next = state->objects;
state->objects = obj; state->objects = obj;
obj->nextRoot = NULL;
#ifdef GC_DEBUG #ifdef GC_DEBUG
printf("allocated %s %p\n", cosmoO_typeStr(obj), obj); printf("allocated %s %p\n", cosmoO_typeStr(obj), obj);
#endif #endif
@ -51,9 +50,9 @@ void cosmoO_free(CState *state, CObj *obj)
break; break;
} }
case COBJ_OBJECT: { case COBJ_OBJECT: {
CObjObject *objTbl = (CObjObject *)obj; CObjObject *objObj = (CObjObject *)obj;
cosmoT_clearTable(state, &objTbl->tbl); cosmoT_clearTable(state, &objObj->tbl);
cosmoM_free(state, CObjObject, objTbl); cosmoM_free(state, CObjObject, objObj);
break; break;
} }
case COBJ_TABLE: { case COBJ_TABLE: {
@ -492,6 +491,7 @@ void cosmoO_unlock(CObjObject *object)
object->isLocked = false; object->isLocked = false;
} }
bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val) bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val)
{ {
if (readFlag(object->istringFlags, flag)) if (readFlag(object->istringFlags, flag))
@ -511,6 +511,8 @@ bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val)
CObjObject *obj = object; CObjObject *obj = object;
do { do {
printf("getting flag %d from obj: %p\n", flag, obj);
fflush(stdout);
if (rawgetIString(state, obj, flag, val)) if (rawgetIString(state, obj, flag, val))
return true; return true;
} while ((obj = obj->_obj.proto) != NULL); // sets obj to it's proto and compares it to NULL } while ((obj = obj->_obj.proto) != NULL); // sets obj to it's proto and compares it to NULL

View File

@ -34,7 +34,6 @@ typedef int (*CosmoCFunction)(CState *state, int argCount, CValue *args);
struct CObj struct CObj
{ {
struct CObj *next; struct CObj *next;
struct CObj *nextRoot; // for the root linked list
struct CObjObject *proto; // protoobject, describes the behavior of the object struct CObjObject *proto; // protoobject, describes the behavior of the object
CObjType type; CObjType type;
bool isMarked; // for the GC bool isMarked; // for the GC

View File

@ -42,7 +42,6 @@ CState *cosmoV_newState()
// GC // GC
state->objects = NULL; state->objects = NULL;
state->userRoots = NULL;
state->grayStack.count = 0; state->grayStack.count = 0;
state->grayStack.capacity = 2; state->grayStack.capacity = 2;
state->grayStack.array = NULL; state->grayStack.array = NULL;
@ -62,11 +61,13 @@ CState *cosmoV_newState()
state->iStrings[i] = NULL; state->iStrings[i] = NULL;
cosmoT_initTable(state, &state->strings, 16); // init string table cosmoT_initTable(state, &state->strings, 16); // init string table
cosmoT_initTable(state, &state->registry, 16);
state->globals = cosmoO_newTable(state); // init global table state->globals = cosmoO_newTable(state); // init global table
// setup all strings used by the VM // setup all strings used by the VM
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6); state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
state->iStrings[ISTRING_GC] = cosmoO_copyString(state, "__gc", 4);
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10); state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10); state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10);
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7); state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
@ -120,6 +121,8 @@ void cosmoV_freeState(CState *state)
// free our string table (the string table includes the internal VM strings) // free our string table (the string table includes the internal VM strings)
cosmoT_clearTable(state, &state->strings); cosmoT_clearTable(state, &state->strings);
cosmoT_clearTable(state, &state->registry);
// free our gray stack & finally free the state structure // free our gray stack & finally free the state structure
cosmoM_freeArray(state, CObj *, state->grayStack.array, state->grayStack.capacity); cosmoM_freeArray(state, CObj *, state->grayStack.array, state->grayStack.capacity);
@ -133,7 +136,7 @@ void cosmoV_freeState(CState *state)
} }
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value // expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
void cosmoV_register(CState *state, int pairs) void cosmoV_addGlobals(CState *state, int pairs)
{ {
for (int i = 0; i < pairs; i++) { for (int i = 0; i < pairs; i++) {
StkPtr key = cosmoV_getTop(state, 1); StkPtr key = cosmoV_getTop(state, 1);
@ -146,6 +149,51 @@ void cosmoV_register(CState *state, int pairs)
} }
} }
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
void cosmoV_addRegistry(CState *state, int pairs)
{
for (int i = 0; i < pairs; i++) {
StkPtr key = cosmoV_getTop(state, 1);
StkPtr val = cosmoV_getTop(state, 0);
CValue *oldVal = cosmoT_insert(state, &state->registry, *key);
*oldVal = *val;
cosmoV_setTop(state, 2); // pops the 2 values off the stack
}
}
// expects 1 key on the stack, pushes result
void cosmoV_getRegistry(CState *state) {
CValue key = *cosmoV_pop(state);
CValue val;
if (!cosmoT_get(state, &state->registry, key, &val)) {
cosmoV_error(state, "failed to grab %s from registry", cosmoV_typeStr(key));
}
printf("got %s from registry - ", cosmoV_typeStr(val));
printValue(val);
printf("\n");
cosmoV_pushValue(state, val);
}
void cosmoV_setProto(CState *state) {
StkPtr objVal = cosmoV_getTop(state, 1);
StkPtr protoVal = cosmoV_getTop(state, 0);
if (!IS_REF(*objVal) || !IS_OBJECT(*protoVal)) {
cosmoV_error(state, "cannot set %s to proto of type %s", cosmoV_typeStr(*objVal), cosmoV_typeStr(*protoVal));
}
// actually set the protos
CObj *obj = cosmoV_readRef(*objVal);
CObjObject *proto = cosmoV_readObject(*protoVal);
obj->proto = proto;
cosmoV_setTop(state, 2);
}
void cosmoV_printStack(CState *state) void cosmoV_printStack(CState *state)
{ {
printf("==== [[ stack dump ]] ====\n"); printf("==== [[ stack dump ]] ====\n");

View File

@ -18,6 +18,7 @@ struct CCallFrame
typedef enum IStringEnum typedef enum IStringEnum
{ {
ISTRING_INIT, // __init ISTRING_INIT, // __init
ISTRING_GC, // __gc
ISTRING_TOSTRING, // __tostring ISTRING_TOSTRING, // __tostring
ISTRING_TONUMBER, // __tonumber ISTRING_TONUMBER, // __tonumber
ISTRING_EQUAL, // __equals ISTRING_EQUAL, // __equals
@ -56,6 +57,7 @@ struct CState
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto] CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
CTable strings; CTable strings;
CTable registry;
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but
// *have been* found // *have been* found
@ -63,14 +65,12 @@ struct CState
CObjTable *globals; CObjTable *globals;
CValue *top; // top of the stack CValue *top; // top of the stack
CObj *objects; // tracks all of our allocated objects CObj *objects; // tracks all of our allocated objects
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots",
// lets the VM know you are holding a reference to a CObj in your code
CPanic *panic; CPanic *panic;
int freezeGC; // when > 0, GC events will be ignored (for internal use)
int frameCount;
size_t allocatedBytes; size_t allocatedBytes;
size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event
int freezeGC; // when > 0, GC events will be ignored (for internal use)
int frameCount;
}; };
CPanic *cosmoV_newPanic(CState *state); CPanic *cosmoV_newPanic(CState *state);
@ -80,7 +80,16 @@ COSMO_API CState *cosmoV_newState();
COSMO_API void cosmoV_freeState(CState *state); COSMO_API void cosmoV_freeState(CState *state);
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value // expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
COSMO_API void cosmoV_register(CState *state, int pairs); COSMO_API void cosmoV_addGlobals(CState *state, int pairs);
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
COSMO_API void cosmoV_addRegistry(CState *state, int pairs);
// expects 1 key on the stack, pushes result
COSMO_API void cosmoV_getRegistry(CState *state);
// expects <object>->proto = <object> (2 total) to be on the stack
COSMO_API void cosmoV_setProto(CState *state);
COSMO_API void cosmoV_printStack(CState *state); COSMO_API void cosmoV_printStack(CState *state);

View File

@ -12,7 +12,7 @@
#define cosmoV_protect(panic) setjmp(panic->jmp) == 0 #define cosmoV_protect(panic) setjmp(panic->jmp) == 0
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...) void cosmoV_pushFString(CState *state, const char *format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
@ -21,7 +21,7 @@ COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...)
} }
// inserts val at state->top - indx - 1, moving everything else up // inserts val at state->top - indx - 1, moving everything else up
COSMO_API void cosmo_insert(CState *state, int indx, CValue val) void cosmoV_insert(CState *state, int indx, CValue val)
{ {
StkPtr tmp = cosmoV_getTop(state, indx); StkPtr tmp = cosmoV_getTop(state, indx);
@ -33,7 +33,7 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val)
state->top++; state->top++;
} }
COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud) bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
{ {
CObjFunction *func; CObjFunction *func;
@ -54,7 +54,7 @@ COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
// returns false if failed, error will be on the top of the stack. true if successful, closure will // returns false if failed, error will be on the top of the stack. true if successful, closure will
// be on the top of the stack // be on the top of the stack
COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name) bool cosmoV_compileString(CState *state, const char *src, const char *name)
{ {
CObjFunction *func; CObjFunction *func;
CPanic *panic = cosmoV_newPanic(state); CPanic *panic = cosmoV_newPanic(state);
@ -77,7 +77,7 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
return false; return false;
} }
COSMO_API void cosmoV_printError(CState *state, CObjError *err) void cosmoV_printError(CState *state, CObjError *err)
{ {
// print stack trace // print stack trace
for (int i = 0; i < err->frameCount; i++) { for (int i = 0; i < err->frameCount; i++) {
@ -439,7 +439,7 @@ static inline bool isFalsey(StkPtr val)
return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val)); return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val));
} }
COSMO_API CObjObject *cosmoV_makeObject(CState *state, int pairs) CObjObject *cosmoV_makeObject(CState *state, int pairs)
{ {
StkPtr key, val; StkPtr key, val;
CObjObject *newObj = cosmoO_newObject(state); CObjObject *newObj = cosmoO_newObject(state);
@ -460,7 +460,7 @@ COSMO_API CObjObject *cosmoV_makeObject(CState *state, int pairs)
return newObj; return newObj;
} }
COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj) bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj)
{ {
bool replaced = state->protoObjects[objType] != NULL; bool replaced = state->protoObjects[objType] != NULL;
state->protoObjects[objType] = obj; state->protoObjects[objType] = obj;
@ -469,7 +469,7 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
CObj *curr = state->objects; CObj *curr = state->objects;
while (curr != NULL) { while (curr != NULL) {
// update the proto // update the proto
if (curr->type == objType && curr->proto != NULL) { if (curr != (CObj *)obj && curr->type == objType && curr->proto != NULL) {
curr->proto = obj; curr->proto = obj;
} }
curr = curr->next; curr = curr->next;
@ -478,7 +478,7 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
return replaced; return replaced;
} }
COSMO_API void cosmoV_makeTable(CState *state, int pairs) void cosmoV_makeTable(CState *state, int pairs)
{ {
StkPtr key, val; StkPtr key, val;
CObjTable *newObj = cosmoO_newTable(state); CObjTable *newObj = cosmoO_newTable(state);
@ -530,7 +530,7 @@ void cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val)
cosmoO_setRawObject(state, object, key, val, _obj); cosmoO_setRawObject(state, object, key, val, _obj);
} }
COSMO_API void cosmoV_get(CState *state) 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
@ -548,7 +548,7 @@ COSMO_API void cosmoV_get(CState *state)
} }
// 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) 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
@ -564,7 +564,7 @@ COSMO_API void cosmoV_set(CState *state)
cosmoV_setTop(state, 3); cosmoV_setTop(state, 3);
} }
COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val) void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
{ {
cosmoV_rawget(state, obj, key, val); cosmoV_rawget(state, obj, key, val);
@ -578,6 +578,19 @@ COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *va
} }
} }
bool cosmoV_isValueUserType(CState *state, CValue val, int userType) {
if (!IS_OBJECT(val)) {
return false;
}
CObjObject *obj = cosmoV_readObject(val);
if (obj->userT != userType) {
return false;
}
return true;
}
int _tbl__next(CState *state, int nargs, CValue *args) int _tbl__next(CState *state, int nargs, CValue *args)
{ {
if (nargs != 1) { if (nargs != 1) {
@ -836,7 +849,8 @@ int cosmoV_execute(CState *state)
CObj *obj = cosmoV_readRef(*temp); CObj *obj = cosmoV_readRef(*temp);
CObjObject *proto = cosmoO_grabProto(obj); CObjObject *proto = cosmoO_grabProto(obj);
CValue val; // to hold our value CValue val = cosmoV_newNil(); // to hold our value
if (proto != NULL) { if (proto != NULL) {
// check for __index metamethod // check for __index metamethod
@ -907,7 +921,7 @@ int cosmoV_execute(CState *state)
} }
CASE(OP_GETOBJECT) : CASE(OP_GETOBJECT) :
{ {
CValue val; // to hold our value CValue val = cosmoV_newNil(); // to hold our value
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
uint16_t ident = READUINT(frame); // use for the key uint16_t ident = READUINT(frame); // use for the key
@ -925,7 +939,7 @@ int cosmoV_execute(CState *state)
} }
CASE(OP_GETMETHOD) : CASE(OP_GETMETHOD) :
{ {
CValue val; // to hold our value CValue val = cosmoV_newNil(); // to hold our value
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
uint16_t ident = READUINT(frame); // use for the key uint16_t ident = READUINT(frame); // use for the key

View File

@ -36,11 +36,11 @@ COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
COSMO_API void cosmoV_printError(CState *state, CObjError *err); COSMO_API void cosmoV_printError(CState *state, CObjError *err);
COSMO_API void cosmoV_throw(CState *state); COSMO_API void cosmoV_throw(CState *state);
COSMO_API void cosmoV_error(CState *state, const char *format, ...); COSMO_API void cosmoV_error(CState *state, const char *format, ...);
COSMO_API void cosmo_insert(CState *state, int indx, CValue val); COSMO_API void cosmoV_insert(CState *state, int indx, CValue val);
/* /*
Sets the default proto objects for the passed objType. Also walks through the object heap and Sets the default proto objects for the passed objType. Also walks through the object heap and
updates protos for the passed objType if that CObj* has no proto. updates protos for the passed objType if that CObj* has no proto.
returns true if replacing a previously registered proto object for this type returns true if replacing a previously registered proto object for this type
*/ */
@ -72,13 +72,16 @@ COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
COSMO_API void cosmoV_get(CState *state); COSMO_API void 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. pops the object, key & value
*/ */
COSMO_API void 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 void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val); COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val);
// check if the value at the top of the stack is a <obj> user type
COSMO_API bool cosmoV_isValueUserType(CState *state, CValue val, int userType);
// nice to have wrappers // nice to have wrappers
// pushes a raw CValue to the stack, might throw an error if the stack is overflowed (with the // pushes a raw CValue to the stack, might throw an error if the stack is overflowed (with the