From 8cd0112c48e7f0082fd829e5dd5f21d4d3abde31 Mon Sep 17 00:00:00 2001 From: CPunch Date: Tue, 12 Jan 2021 18:27:29 -0600 Subject: [PATCH] fixed __getter and __setter tables --- examples/getters_setters.cosmo | 20 ++++++++++++++++++++ src/cmem.h | 2 +- src/cobj.c | 26 ++++++++++++++------------ src/cobj.h | 5 +++-- src/cvm.c | 10 ++++++---- 5 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 examples/getters_setters.cosmo diff --git a/examples/getters_setters.cosmo b/examples/getters_setters.cosmo new file mode 100644 index 0000000..3ec1f0a --- /dev/null +++ b/examples/getters_setters.cosmo @@ -0,0 +1,20 @@ +var object = { + __setter = [ + "field1" = function(self, val) + print("setter for field1 called!") + self.x = val + end + ], + + __getter = [ + "field1" = function(self) + print("getter for field1 called!") + + return self.x + 1 + end + ] +} + +object.field1 = 1337 + +print("got field: " .. object.field1) \ No newline at end of file diff --git a/src/cmem.h b/src/cmem.h index ca0eb0e..7e65b94 100644 --- a/src/cmem.h +++ b/src/cmem.h @@ -5,7 +5,7 @@ #include "cstate.h" -#define GC_STRESS +//#define GC_STRESS //#define GC_DEBUG // arrays will grow by a factor of 2 #define GROW_FACTOR 2 diff --git a/src/cobj.c b/src/cobj.c index 08a960d..76099a4 100644 --- a/src/cobj.c +++ b/src/cobj.c @@ -288,34 +288,36 @@ CObjString *cosmoO_pushVFString(CState *state, const char *format, va_list args) return cosmoV_readString(*start); // start should be state->top - 1 } -bool cosmoO_getRawObject(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 (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getRawObject(state, cosmoV_readObject(*val), key, val)) { + +// returns false if error thrown +bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj) { + if (!cosmoT_get(&proto->tbl, key, val)) { // if the field doesn't exist in the object, check the proto + if (cosmoO_getIString(state, proto, ISTRING_GETTER, val) && IS_TABLE(*val) && cosmoT_get(&cosmoV_readTable(*val)->tbl, key, val)) { cosmoV_pushValue(state, *val); // push function - cosmoV_pushValue(state, cosmoV_newObj(object)); // push object + cosmoV_pushValue(state, cosmoV_newObj(obj)); // push object if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call the function with the 1 argument return false; *val = *cosmoV_pop(state); // set value to the return value of __index return true; } - if (object->_obj.proto != NULL && cosmoO_getRawObject(state, object->_obj.proto, key, val)) + if (proto->_obj.proto != NULL && cosmoO_getRawObject(state, proto->_obj.proto, key, val, obj)) return true; *val = cosmoV_newNil(); - return false; // no protoobject to check against / key not found + return true; // no protoobject to check against / key not found } return true; } -void cosmoO_setRawObject(CState *state, CObjObject *object, CValue key, CValue val) { +void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj) { CValue ret; // first check for __setters - if (cosmoO_getIString(state, object, ISTRING_SETTER, &ret) && IS_OBJECT(ret) && cosmoO_getRawObject(state, cosmoV_readObject(ret), key, &ret)) { + 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_pushValue(state, cosmoV_newObj(object)); // push object + cosmoV_pushValue(state, cosmoV_newObj(obj)); // push object cosmoV_pushValue(state, val); // push new value cosmoV_call(state, 2, 0); return; @@ -323,12 +325,12 @@ void cosmoO_setRawObject(CState *state, CObjObject *object, CValue key, CValue v // if the key is an IString, we need to reset the cache if (IS_STRING(key) && cosmoV_readString(key)->isIString) - object->istringFlags = 0; // reset cache + proto->istringFlags = 0; // reset cache if (IS_NIL(val)) { // if we're setting an index to nil, we can safely mark that as a tombstone - cosmoT_remove(state, &object->tbl, key); + cosmoT_remove(state, &proto->tbl, key); } else { - CValue *newVal = cosmoT_insert(state, &object->tbl, key); + CValue *newVal = cosmoT_insert(state, &proto->tbl, key); *newVal = val; } } diff --git a/src/cobj.h b/src/cobj.h index 01dd1f7..2790797 100644 --- a/src/cobj.h +++ b/src/cobj.h @@ -119,6 +119,7 @@ typedef struct CObjUpval { #define cosmoV_readString(x) ((CObjString*)cosmoV_readObj(x)) #define cosmoV_readObject(x) ((CObjObject*)cosmoV_readObj(x)) +#define cosmoV_readTable(x) ((CObjTable*)cosmoV_readObj(x)) #define cosmoV_readFunction(x) ((CObjFunction*)cosmoV_readObj(x)) #define cosmoV_readCFunction(x) (((CObjCFunction*)cosmoV_readObj(x))->cfunc) #define cosmoV_readMethod(x) ((CObjMethod*)cosmoV_readObj(x)) @@ -158,8 +159,8 @@ static inline CObjObject *cosmoO_grabProto(CObj *obj) { return object; } -bool cosmoO_getRawObject(CState *state, CObjObject *object, CValue key, CValue *val); -void cosmoO_setRawObject(CState *state, CObjObject *object, CValue key, CValue val); +bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *val, CObj *obj); +void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue val, CObj *obj); bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val); bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val); diff --git a/src/cvm.c b/src/cvm.c index 11819e1..db640fb 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -434,14 +434,15 @@ COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) { // no proto to get from if (object == NULL) { - cosmoV_error(state, "No proto defined! Couldn't get from type %s", cosmoO_typeStr(_obj)); + CObjString *field = cosmoV_toString(state, key); + cosmoV_error(state, "No proto defined! Couldn't get field '%s' from type %s", field->str, cosmoO_typeStr(_obj)); *val = cosmoV_newNil(); return false; } // push the object onto the stack so the GC can find it cosmoV_pushValue(state, cosmoV_newObj(object)); - if (cosmoO_getRawObject(state, object, key, val)) { + if (cosmoO_getRawObject(state, object, key, val, _obj)) { // *val now equals the response, pop the object cosmoV_pop(state); return true; @@ -456,11 +457,12 @@ COSMO_API bool cosmoV_set(CState *state, CObj *_obj, CValue key, CValue val) { // no proto to set to if (object == NULL) { - cosmoV_error(state, "No proto defined! Couldn't set to type %s", cosmoO_typeStr(_obj)); + CObjString *field = cosmoV_toString(state, key); + cosmoV_error(state, "No proto defined! Couldn't set field '%s' to type %s", field->str, cosmoO_typeStr(_obj)); return false; } - cosmoO_setRawObject(state, object, key, val); + cosmoO_setRawObject(state, object, key, val, _obj); return true; }