mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-10 18:30:05 +00:00
fixed __getter and __setter tables
This commit is contained in:
parent
32162ce50c
commit
8cd0112c48
20
examples/getters_setters.cosmo
Normal file
20
examples/getters_setters.cosmo
Normal 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)
|
@ -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
|
||||
|
26
src/cobj.c
26
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
10
src/cvm.c
10
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user