mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
added __setter and __getter
This commit is contained in:
parent
005e2acd1e
commit
d00b803e6f
@ -42,14 +42,24 @@ CValue cosmoB_dgetProto(CState *state, int nargs, CValue *args) {
|
||||
}
|
||||
|
||||
void cosmoB_loadDebug(CState *state) {
|
||||
cosmoV_pushString(state, "getProto"); // key
|
||||
// make __getter object for debug proto
|
||||
cosmoV_pushString(state, "__getter");
|
||||
|
||||
// key & value pair
|
||||
cosmoV_pushString(state, "__proto"); // key
|
||||
cosmoV_pushCFunction(state, cosmoB_dgetProto); // value
|
||||
|
||||
// another key & value
|
||||
cosmoV_pushString(state, "setProto");
|
||||
cosmoV_makeObject(state, 1);
|
||||
|
||||
// make __setter object
|
||||
cosmoV_pushString(state, "__setter");
|
||||
|
||||
cosmoV_pushString(state, "__proto");
|
||||
cosmoV_pushCFunction(state, cosmoB_dsetProto);
|
||||
|
||||
// we call makeObject leting it know there are 2 sets of key & value pairs on the stack (4 values total)
|
||||
cosmoV_makeObject(state, 1);
|
||||
|
||||
// we call makeObject leting it know there are 2 sets of key & value pairs on the stack
|
||||
cosmoV_makeObject(state, 2);
|
||||
|
||||
// set debug proto to the debug object
|
||||
|
27
src/cobj.c
27
src/cobj.c
@ -206,10 +206,19 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin
|
||||
bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val) {
|
||||
if (!cosmoT_get(&object->tbl, key, val)) { // if the field doesn't exist in the object, check the proto
|
||||
if (object->proto != NULL) { // sanity check
|
||||
// first though, check for a member of the proto object, if it fails then lookup __index
|
||||
// first though, check for a member of the proto object, if it fails then lookup __getters
|
||||
if (cosmoO_getObject(state, object->proto, key, val))
|
||||
return true;
|
||||
|
||||
// if this fails or the key isn't in that table then we default to __index
|
||||
if (cosmoO_getIString(state, object->proto, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getObject(state, cosmoV_readObject(*val), key, val)) {
|
||||
cosmoV_pushValue(state, *val); // push function
|
||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||
cosmoV_call(state, 1); // call the function with the 1 argument
|
||||
*val = *cosmoV_pop(state); // set value to the return value of __index
|
||||
return true;
|
||||
}
|
||||
|
||||
// then check for __index, if that exists, call it
|
||||
if (cosmoO_getIString(state, object->proto, ISTRING_INDEX, val)) {
|
||||
cosmoV_pushValue(state, *val); // push function
|
||||
@ -230,8 +239,19 @@ bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val
|
||||
void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val) {
|
||||
CValue ret;
|
||||
|
||||
// first check for __newindex in the prototype
|
||||
if (object->proto != NULL && cosmoO_getIString(state, object->proto, ISTRING_NEWINDEX, &ret)) {
|
||||
// if there's a prototype, check for the tag methods!
|
||||
if (object->proto != NULL) {
|
||||
// first check for __setters
|
||||
if (cosmoO_getIString(state, object->proto, ISTRING_SETTER, &ret) && IS_OBJECT(ret) && cosmoO_getObject(state, cosmoV_readObject(ret), key, &ret)) {
|
||||
cosmoV_pushValue(state, ret); // push function
|
||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||
cosmoV_pushValue(state, val); // push new value
|
||||
cosmoV_call(state, 2);
|
||||
cosmoV_pop(state); // pop return value
|
||||
}
|
||||
|
||||
// then check for __newindex in the prototype
|
||||
if (cosmoO_getIString(state, object->proto, ISTRING_NEWINDEX, &ret)) {
|
||||
cosmoV_pushValue(state, ret); // push function
|
||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
||||
cosmoV_pushValue(state, key); // push key & value pair
|
||||
@ -240,6 +260,7 @@ void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val)
|
||||
cosmoV_pop(state); // pop return value
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
object->istringFlags = 0; // reset cache
|
||||
if (IS_NIL(val)) { // if we're setting an index to nil, we can safely mark that as a tombstone
|
||||
|
@ -84,7 +84,7 @@ typedef struct CObjUpval {
|
||||
#undef CommonHeader
|
||||
|
||||
#define IS_STRING(x) isObjType(x, COBJ_STRING)
|
||||
#define IS_TABLE(x) isObjType(x, COBJ_OBJECT)
|
||||
#define IS_OBJECT(x) isObjType(x, COBJ_OBJECT)
|
||||
#define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION)
|
||||
#define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION)
|
||||
#define IS_METHOD(x) isObjType(x, COBJ_METHOD)
|
||||
|
@ -44,6 +44,10 @@ CState *cosmoV_newState() {
|
||||
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
||||
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
||||
|
||||
// getters/setters
|
||||
state->iStrings[ISTRING_GETTER] = cosmoO_copyString(state, "__getter", 8);
|
||||
state->iStrings[ISTRING_SETTER] = cosmoO_copyString(state, "__setter", 8);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@ typedef enum IStringEnum {
|
||||
ISTRING_EQUAL, // __equal
|
||||
ISTRING_INDEX, // __index
|
||||
ISTRING_NEWINDEX, // __newindex
|
||||
ISTRING_GETTER, // __getter
|
||||
ISTRING_SETTER, // __setter
|
||||
ISTRING_MAX
|
||||
} IStringEnum;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user