mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
Added '__count' metamethod to objects
This commit is contained in:
parent
6b407534c0
commit
7c92749e0d
@ -1,4 +1,4 @@
|
|||||||
# Prototype Objects
|
# Objects & Protos
|
||||||
|
|
||||||
Cosmo supports an eccentric form of Object-Oriented Programming through the use of Objects and Proto-Objects. Under the hood, these are the same datatype, however they can be chained to describe behaviors in relation to other Objects, operators, and provide stateful functions.
|
Cosmo supports an eccentric form of Object-Oriented Programming through the use of Objects and Proto-Objects. Under the hood, these are the same datatype, however they can be chained to describe behaviors in relation to other Objects, operators, and provide stateful functions.
|
||||||
|
|
||||||
@ -64,7 +64,8 @@ Objects have two main ways of being declared, first was just shown in the above
|
|||||||
```
|
```
|
||||||
proto Test
|
proto Test
|
||||||
function __init(self)
|
function __init(self)
|
||||||
// __init is required for an object to be instantiated, the 'self' passed is the newly allocated object with it's proto already set to
|
// __init is required for an object to be instantiated, the 'self' passed is the
|
||||||
|
// newly allocated object with it's proto already set
|
||||||
end
|
end
|
||||||
|
|
||||||
function print(self)
|
function print(self)
|
||||||
@ -74,7 +75,8 @@ end
|
|||||||
|
|
||||||
var objTest = Test()
|
var objTest = Test()
|
||||||
|
|
||||||
// the ':' operator is used to invoke a method. if the '.' operator is used instead, the raw closure will be given meaning the 'self' parameter won't be populated
|
// the ':' operator is used to invoke a method. if the '.' operator is used instead, the
|
||||||
|
// raw closure will be given meaning the 'self' parameter won't be populated
|
||||||
objTest:print()
|
objTest:print()
|
||||||
|
|
||||||
objTest.print(objTest) // equivalent to invoking with ':'
|
objTest.print(objTest) // equivalent to invoking with ':'
|
||||||
@ -93,6 +95,7 @@ that are called on special operators.
|
|||||||
| __newindex | `(<object>, key, newValue)` | Called on new index using the '[] = ' operator |
|
| __newindex | `(<object>, key, newValue)` | Called on new index using the '[] = ' operator |
|
||||||
| __index | `(<object>, key)` -> `value` | Called on index using the '[]' operator |
|
| __index | `(<object>, key)` -> `value` | Called on index using the '[]' operator |
|
||||||
| __tostring | `(<object>)` -> `<string>` | Called when tostring() is called on an object |
|
| __tostring | `(<object>)` -> `<string>` | Called when tostring() is called on an object |
|
||||||
|
| __count | `(<object>)` -> `<number>` | Called when object is used with the '#' count operator |
|
||||||
| __iter | `(<object>)` -> `<object>` | Called when used in a for-each loop with the 'in' operator |
|
| __iter | `(<object>)` -> `<object>` | Called when used in a for-each loop with the 'in' operator |
|
||||||
| __next | `(<object>)` -> `...` | Called on each iteration in a for-each loop, return values are passed as parameters in the loop |
|
| __next | `(<object>)` -> `...` | Called on each iteration in a for-each loop, return values are passed as parameters in the loop |
|
||||||
| __getter | `[<string> fieldName : <function> getterMethod]` | Indexed & called on field get using the '.' operator |
|
| __getter | `[<string> fieldName : <function> getterMethod]` | Indexed & called on field get using the '.' operator |
|
||||||
|
36
src/cobj.c
36
src/cobj.c
@ -472,6 +472,42 @@ cosmo_Number cosmoO_toNumber(CState *state, CObj *obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cosmoO_count(CState *state, CObj *obj) {
|
||||||
|
CObjObject *proto = cosmoO_grabProto(obj);
|
||||||
|
CValue res;
|
||||||
|
|
||||||
|
if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_COUNT, &res)) {
|
||||||
|
cosmoV_pushValue(state, res);
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
||||||
|
if (!cosmoV_call(state, 1, 1) != COSMOVM_OK) // call ret, we expect 1 return value of type <number>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
StkPtr ret = cosmoV_getTop(state, 0);
|
||||||
|
if (!IS_NUMBER(*ret)) {
|
||||||
|
cosmoV_error(state, "__count expected to return <number>, got %s!", cosmoV_typeStr(*ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return number
|
||||||
|
cosmoV_pop(state);
|
||||||
|
return (int)cosmoV_readNumber(*ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (obj->type) {
|
||||||
|
case COBJ_TABLE: { // returns the # of entries in the hash table
|
||||||
|
CObjTable *tbl = (CObjTable*)obj;
|
||||||
|
return cosmoT_count(&tbl->tbl);
|
||||||
|
}
|
||||||
|
case COBJ_STRING: { // returns the length of the string
|
||||||
|
CObjString *str = (CObjString*)obj;
|
||||||
|
return str->length;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
cosmoV_error(state, "Couldn't get # (count) of %s!", cosmoO_typeStr(obj));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void printObject(CObj *o) {
|
void printObject(CObj *o) {
|
||||||
switch (o->type) {
|
switch (o->type) {
|
||||||
case COBJ_STRING: {
|
case COBJ_STRING: {
|
||||||
|
@ -195,5 +195,6 @@ const char *cosmoO_typeStr(CObj* obj);
|
|||||||
|
|
||||||
CObjString *cosmoO_toString(CState *state, CObj *obj);
|
CObjString *cosmoO_toString(CState *state, CObj *obj);
|
||||||
cosmo_Number cosmoO_toNumber(CState *state, CObj *obj);
|
cosmo_Number cosmoO_toNumber(CState *state, CObj *obj);
|
||||||
|
int cosmoO_count(CState *state, CObj *obj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,6 +50,7 @@ CState *cosmoV_newState() {
|
|||||||
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
||||||
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
||||||
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
||||||
|
state->iStrings[ISTRING_COUNT] = cosmoO_copyString(state, "__count", 7);
|
||||||
|
|
||||||
// getters/setters
|
// getters/setters
|
||||||
state->iStrings[ISTRING_GETTER] = cosmoO_copyString(state, "__getter", 8);
|
state->iStrings[ISTRING_GETTER] = cosmoO_copyString(state, "__getter", 8);
|
||||||
|
@ -17,6 +17,7 @@ typedef enum IStringEnum {
|
|||||||
ISTRING_TOSTRING, // __tostring
|
ISTRING_TOSTRING, // __tostring
|
||||||
ISTRING_INDEX, // __index
|
ISTRING_INDEX, // __index
|
||||||
ISTRING_NEWINDEX, // __newindex
|
ISTRING_NEWINDEX, // __newindex
|
||||||
|
ISTRING_COUNT, // __count
|
||||||
ISTRING_GETTER, // __getter
|
ISTRING_GETTER, // __getter
|
||||||
ISTRING_SETTER, // __setter
|
ISTRING_SETTER, // __setter
|
||||||
ISTRING_ITER, // __iter
|
ISTRING_ITER, // __iter
|
||||||
|
11
src/cvm.c
11
src/cvm.c
@ -979,17 +979,18 @@ int cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_COUNT: { // pop 1 value off the stack & if it's a table return the amount of active entries it has
|
case OP_COUNT: {
|
||||||
StkPtr temp = cosmoV_getTop(state, 0);
|
StkPtr temp = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
if (!IS_TABLE(*temp)) {
|
if (!IS_OBJ(*temp)) {
|
||||||
cosmoV_error(state, "Expected table, got %s!", cosmoV_typeStr(*temp));
|
cosmoV_error(state, "Expected non-primitive, got %s!", cosmoV_typeStr(*temp));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
|
int count = cosmoO_count(state, cosmoV_readObj(*temp));
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
cosmoV_pushNumber(state, cosmoT_count(&tbl->tbl)); // pushes the count onto the stack
|
|
||||||
|
cosmoV_pushNumber(state, count); // pushes the count onto the stack
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_CONCAT: {
|
case OP_CONCAT: {
|
||||||
|
Loading…
Reference in New Issue
Block a user