mirror of
				https://github.com/CPunch/Cosmo.git
				synced 2025-11-03 22:40:16 +00:00 
			
		
		
		
	Added '__count' metamethod to objects
This commit is contained in:
		@@ -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.
 | 
			
		||||
 | 
			
		||||
@@ -64,7 +64,8 @@ Objects have two main ways of being declared, first was just shown in the above
 | 
			
		||||
```
 | 
			
		||||
proto Test
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    function print(self)
 | 
			
		||||
@@ -74,7 +75,8 @@ end
 | 
			
		||||
 | 
			
		||||
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) // 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              |
 | 
			
		||||
| __index      | `(<object>, key)` -> `value`                     | Called on index using the '[]' operator                     |
 | 
			
		||||
| __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  |
 | 
			
		||||
| __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        |
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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) {
 | 
			
		||||
    switch (o->type) {
 | 
			
		||||
        case COBJ_STRING: {
 | 
			
		||||
 
 | 
			
		||||
@@ -195,5 +195,6 @@ const char *cosmoO_typeStr(CObj* obj);
 | 
			
		||||
 | 
			
		||||
CObjString *cosmoO_toString(CState *state, CObj *obj);
 | 
			
		||||
cosmo_Number cosmoO_toNumber(CState *state, CObj *obj);
 | 
			
		||||
int cosmoO_count(CState *state, CObj *obj);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ CState *cosmoV_newState() {
 | 
			
		||||
    state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
 | 
			
		||||
    state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
 | 
			
		||||
    state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
 | 
			
		||||
    state->iStrings[ISTRING_COUNT] = cosmoO_copyString(state, "__count", 7);
 | 
			
		||||
 | 
			
		||||
    // getters/setters
 | 
			
		||||
    state->iStrings[ISTRING_GETTER] = cosmoO_copyString(state, "__getter", 8);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ typedef enum IStringEnum {
 | 
			
		||||
    ISTRING_TOSTRING,   // __tostring
 | 
			
		||||
    ISTRING_INDEX,      // __index
 | 
			
		||||
    ISTRING_NEWINDEX,   // __newindex
 | 
			
		||||
    ISTRING_COUNT,      // __count
 | 
			
		||||
    ISTRING_GETTER,     // __getter
 | 
			
		||||
    ISTRING_SETTER,     // __setter
 | 
			
		||||
    ISTRING_ITER,       // __iter
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								src/cvm.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/cvm.c
									
									
									
									
									
								
							@@ -979,17 +979,18 @@ int cosmoV_execute(CState *state) {
 | 
			
		||||
                }
 | 
			
		||||
                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);
 | 
			
		||||
 | 
			
		||||
                if (!IS_TABLE(*temp)) {
 | 
			
		||||
                    cosmoV_error(state, "Expected table, got %s!", cosmoV_typeStr(*temp));
 | 
			
		||||
                if (!IS_OBJ(*temp)) {
 | 
			
		||||
                    cosmoV_error(state, "Expected non-primitive, got %s!", cosmoV_typeStr(*temp));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
 | 
			
		||||
                int count = cosmoO_count(state, cosmoV_readObj(*temp));
 | 
			
		||||
                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;
 | 
			
		||||
            }
 | 
			
		||||
            case OP_CONCAT: {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user