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" #include "cstate.h"
#define GC_STRESS //#define GC_STRESS
//#define GC_DEBUG //#define GC_DEBUG
// arrays will grow by a factor of 2 // arrays will grow by a factor of 2
#define GROW_FACTOR 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 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 // returns false if error thrown
if (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getRawObject(state, cosmoV_readObject(*val), key, val)) { 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, *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 if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call the function with the 1 argument
return false; return false;
*val = *cosmoV_pop(state); // set value to the return value of __index *val = *cosmoV_pop(state); // set value to the return value of __index
return true; 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; return true;
*val = cosmoV_newNil(); *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; 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; CValue ret;
// first check for __setters // 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, 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_pushValue(state, val); // push new value
cosmoV_call(state, 2, 0); cosmoV_call(state, 2, 0);
return; 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 the key is an IString, we need to reset the cache
if (IS_STRING(key) && cosmoV_readString(key)->isIString) 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 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 { } else {
CValue *newVal = cosmoT_insert(state, &object->tbl, key); CValue *newVal = cosmoT_insert(state, &proto->tbl, key);
*newVal = val; *newVal = val;
} }
} }

View File

@ -119,6 +119,7 @@ typedef struct CObjUpval {
#define cosmoV_readString(x) ((CObjString*)cosmoV_readObj(x)) #define cosmoV_readString(x) ((CObjString*)cosmoV_readObj(x))
#define cosmoV_readObject(x) ((CObjObject*)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_readFunction(x) ((CObjFunction*)cosmoV_readObj(x))
#define cosmoV_readCFunction(x) (((CObjCFunction*)cosmoV_readObj(x))->cfunc) #define cosmoV_readCFunction(x) (((CObjCFunction*)cosmoV_readObj(x))->cfunc)
#define cosmoV_readMethod(x) ((CObjMethod*)cosmoV_readObj(x)) #define cosmoV_readMethod(x) ((CObjMethod*)cosmoV_readObj(x))
@ -158,8 +159,8 @@ static inline CObjObject *cosmoO_grabProto(CObj *obj) {
return object; return object;
} }
bool cosmoO_getRawObject(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 *object, CValue key, CValue val); 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_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
bool cosmoO_newIndexObject(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 // no proto to get from
if (object == NULL) { 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(); *val = cosmoV_newNil();
return false; return false;
} }
// push the object onto the stack so the GC can find it // push the object onto the stack so the GC can find it
cosmoV_pushValue(state, cosmoV_newObj(object)); 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 // *val now equals the response, pop the object
cosmoV_pop(state); cosmoV_pop(state);
return true; return true;
@ -456,11 +457,12 @@ COSMO_API bool cosmoV_set(CState *state, CObj *_obj, CValue key, CValue val) {
// no proto to set to // no proto to set to
if (object == NULL) { 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; return false;
} }
cosmoO_setRawObject(state, object, key, val); cosmoO_setRawObject(state, object, key, val, _obj);
return true; return true;
} }