fixed __getter and __setter tables

This commit is contained in:
CPunch 2021-01-12 18:27:29 -06:00
parent 32162ce50c
commit 8cd0112c48
5 changed files with 44 additions and 19 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}