mirror of
				https://github.com/CPunch/Cosmo.git
				synced 2025-10-30 20:40:19 +00:00 
			
		
		
		
	added IStrings, added __index functionality
This commit is contained in:
		| @@ -1,26 +1,14 @@ | |||||||
| class test | -- crafts a dummy class | ||||||
|     function __init(self, str) | class test end | ||||||
|         self.hello = str |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     function print(self, i) | -- instance of test | ||||||
|         var str = self.hello | var obj = test() | ||||||
|  |  | ||||||
|         for (var x = i; x > 0; x=x-1) do | test.__index = function(self, key) | ||||||
|             str = str .. "!" |     print("__index called!") | ||||||
|         end |     if (key == "lol") then | ||||||
|  |         return 9001 | ||||||
|         print(str) |  | ||||||
|     end |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| var obj = test("Hello world") | print(obj["lol"]) -- should print 9001? | ||||||
| for (var i = 1; i <= 1; i=i+1) do |  | ||||||
|     obj.print(i) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| test.debug = function(self) |  | ||||||
|     print("hi from " .. self) |  | ||||||
| end |  | ||||||
|  |  | ||||||
| obj.debug() |  | ||||||
| @@ -211,8 +211,8 @@ void markRoots(CState *state) { | |||||||
|     markTable(state, &state->globals); |     markTable(state, &state->globals); | ||||||
|  |  | ||||||
|     // mark all internal strings |     // mark all internal strings | ||||||
|     for (int i = 0; i < INTERNALSTRING_MAX; i++) |     for (int i = 0; i < ISTRING_MAX; i++) | ||||||
|         markObject(state, (CObj*)state->internalStrings[i]); |         markObject(state, (CObj*)state->iStrings[i]); | ||||||
|  |  | ||||||
|     // mark our proto object |     // mark our proto object | ||||||
|     markObject(state, (CObj*)state->protoObj); |     markObject(state, (CObj*)state->protoObj); | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/cobj.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/cobj.c
									
									
									
									
									
								
							| @@ -2,6 +2,7 @@ | |||||||
| #include "ctable.h" | #include "ctable.h" | ||||||
| #include "cobj.h" | #include "cobj.h" | ||||||
| #include "cmem.h" | #include "cmem.h" | ||||||
|  | #include "cvm.h" | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| @@ -95,6 +96,7 @@ bool cosmoO_equal(CObj* obj1, CObj* obj2) { | |||||||
| CObjObject *cosmoO_newObject(CState *state) { | CObjObject *cosmoO_newObject(CState *state) { | ||||||
|     CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT); |     CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT); | ||||||
|     obj->proto = state->protoObj; |     obj->proto = state->protoObj; | ||||||
|  |     obj->istringFlags = 0; | ||||||
|     obj->user = NULL; // reserved for C API |     obj->user = NULL; // reserved for C API | ||||||
|     cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of it |     cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of it | ||||||
|     cosmoT_initTable(state, &obj->tbl, ARRAY_START); |     cosmoT_initTable(state, &obj->tbl, ARRAY_START); | ||||||
| @@ -204,18 +206,46 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin | |||||||
| } | } | ||||||
|  |  | ||||||
| bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val) { | bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val) { | ||||||
|     if (!cosmoT_get(&object->tbl, key, val) && object->proto != NULL) { // if the field doesn't exist in the object, check the proto |     if (!cosmoT_get(&object->tbl, key, val)) { // if the field doesn't exist in the object, check the proto | ||||||
|         return cosmoO_getObject(state, object->proto, key, val); |         if (object->proto != NULL) { // sanity check | ||||||
|  |             // first though, check for __index, if that exists, call it | ||||||
|  |             if (cosmoO_getIString(state, object->proto, ISTRING_INDEX, val)) { | ||||||
|  |                 cosmoV_pushValue(state, *val); // push function | ||||||
|  |                 cosmoV_pushValue(state, cosmoV_newObj(object)); // push object | ||||||
|  |                 cosmoV_pushValue(state, key); // push key | ||||||
|  |                 cosmoV_call(state, 2); // call the function with the 2 arguments | ||||||
|  |                 *val = *cosmoV_pop(state); // set value to the return value of __index | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return cosmoO_getObject(state, object->proto, key, val); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         return false; // no protoobject to check against | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val) { | void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val) { | ||||||
|  |     object->istringFlags = 0; // reset cache | ||||||
|     CValue *newVal = cosmoT_insert(state, &object->tbl, key); |     CValue *newVal = cosmoT_insert(state, &object->tbl, key); | ||||||
|     *newVal = val; |     *newVal = val; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val) { | ||||||
|  |     if (readFlag(object->istringFlags, flag)) | ||||||
|  |         return false; // it's been cached as bad | ||||||
|  |          | ||||||
|  |     if (!cosmoO_getObject(state, object, cosmoV_newObj(state->iStrings[flag]), val)) { | ||||||
|  |         // mark it bad! | ||||||
|  |         setFlagOn(object->istringFlags, flag); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return true; // :) | ||||||
|  | } | ||||||
|  |  | ||||||
| CObjString *cosmoO_toString(CState *state, CObj *obj) { | CObjString *cosmoO_toString(CState *state, CObj *obj) { | ||||||
|     switch (obj->type) { |     switch (obj->type) { | ||||||
|         case COBJ_STRING: { |         case COBJ_STRING: { | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/cobj.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/cobj.h
									
									
									
									
									
								
							| @@ -2,11 +2,13 @@ | |||||||
| #define COBJ_H | #define COBJ_H | ||||||
|  |  | ||||||
| #include "cosmo.h" | #include "cosmo.h" | ||||||
|  | #include "cstate.h" | ||||||
| #include "cchunk.h" | #include "cchunk.h" | ||||||
| #include "cvalue.h" | #include "cvalue.h" | ||||||
| #include "ctable.h" | #include "ctable.h" | ||||||
|  |  | ||||||
| typedef struct CState CState; | typedef struct CState CState; | ||||||
|  | typedef uint32_t cosmo_Flag; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|     COBJ_STRING, |     COBJ_STRING, | ||||||
| @@ -20,6 +22,8 @@ typedef enum { | |||||||
| } CObjType; | } CObjType; | ||||||
|  |  | ||||||
| #define CommonHeader CObj _obj; | #define CommonHeader CObj _obj; | ||||||
|  | #define readFlag(x, flag)   (x & (1u << flag)) | ||||||
|  | #define setFlagOn(x, flag)  (x |= (1u << flag)) | ||||||
|  |  | ||||||
| typedef CValue (*CosmoCFunction)(CState *state, int argCount, CValue *args); | typedef CValue (*CosmoCFunction)(CState *state, int argCount, CValue *args); | ||||||
|  |  | ||||||
| @@ -38,6 +42,7 @@ typedef struct CObjString { | |||||||
|  |  | ||||||
| typedef struct CObjObject { | typedef struct CObjObject { | ||||||
|     CommonHeader; // "is a" CObj |     CommonHeader; // "is a" CObj | ||||||
|  |     cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.) | ||||||
|     CTable tbl; |     CTable tbl; | ||||||
|     void *user; // userdata (NULL by default) |     void *user; // userdata (NULL by default) | ||||||
|     struct CObjObject *proto; // protoobject, describes the behavior of the object |     struct CObjObject *proto; // protoobject, describes the behavior of the object | ||||||
| @@ -80,6 +85,8 @@ typedef struct CObjUpval { | |||||||
|     struct CObjUpval *next; |     struct CObjUpval *next; | ||||||
| } CObjUpval; | } CObjUpval; | ||||||
|  |  | ||||||
|  | #undef CommonHeader | ||||||
|  |  | ||||||
| #define IS_STRING(x)    isObjType(x, COBJ_STRING) | #define IS_STRING(x)    isObjType(x, COBJ_STRING) | ||||||
| #define IS_TABLE(x)     isObjType(x, COBJ_OBJECT) | #define IS_TABLE(x)     isObjType(x, COBJ_OBJECT) | ||||||
| #define IS_FUNCTION(x)  isObjType(x, COBJ_FUNCTION) | #define IS_FUNCTION(x)  isObjType(x, COBJ_FUNCTION) | ||||||
| @@ -115,6 +122,9 @@ CObjUpval *cosmoO_newUpvalue(CState *state, CValue *val); | |||||||
| bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val); | bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val); | ||||||
| void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val); | void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val); | ||||||
|  |  | ||||||
|  | // internal string | ||||||
|  | bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val); | ||||||
|  |  | ||||||
| // copies the *str buffer to the heap and returns a CObjString struct which is also on the heap | // copies the *str buffer to the heap and returns a CObjString struct which is also on the heap | ||||||
| CObjString *cosmoO_copyString(CState *state, const char *str, size_t sz); | CObjString *cosmoO_copyString(CState *state, const char *str, size_t sz); | ||||||
| // pass an already allocated str buffer! | // pass an already allocated str buffer! | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ typedef struct CObjUpval CObjUpval; | |||||||
| typedef struct CObjFunction CObjFunction; | typedef struct CObjFunction CObjFunction; | ||||||
| typedef struct CObjCFunction CObjCFunction; | typedef struct CObjCFunction CObjCFunction; | ||||||
| typedef struct CObjMethod CObjMethod; | typedef struct CObjMethod CObjMethod; | ||||||
|  | typedef struct CObjObject CObjObject; | ||||||
| typedef struct CObjClass CObjClass; | typedef struct CObjClass CObjClass; | ||||||
| typedef struct CObjClosure CObjClosure; | typedef struct CObjClosure CObjClosure; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								src/cstate.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/cstate.c
									
									
									
									
									
								
							| @@ -36,11 +36,12 @@ CState *cosmoV_newState() { | |||||||
|     cosmoT_initTable(state, &state->globals, 8); // init global table |     cosmoT_initTable(state, &state->globals, 8); // init global table | ||||||
|  |  | ||||||
|     // first, set all strings to NULL so our GC doesn't read garbage data |     // first, set all strings to NULL so our GC doesn't read garbage data | ||||||
|     for (int i = 0; i < INTERNALSTRING_MAX; i++) |     for (int i = 0; i < ISTRING_MAX; i++) | ||||||
|         state->internalStrings[i] = NULL; |         state->iStrings[i] = NULL; | ||||||
|  |  | ||||||
|     // setup all strings used by the VM |     // setup all strings used by the VM | ||||||
|     state->internalStrings[INTERNALSTRING_INIT] = cosmoO_copyString(state, "__init", 6); |     state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6); | ||||||
|  |     state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7); | ||||||
|     return state; |     return state; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -57,8 +58,8 @@ void cosmoV_freeState(CState *state) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // mark our internal VM strings NULL |     // mark our internal VM strings NULL | ||||||
|     for (int i = 0; i < INTERNALSTRING_MAX; i++) |     for (int i = 0; i < ISTRING_MAX; i++) | ||||||
|         state->internalStrings[i] = NULL; |         state->iStrings[i] = NULL; | ||||||
|  |  | ||||||
|     // free our string & global table (the string table includes the internal VM strings) |     // free our string & global table (the string table includes the internal VM strings) | ||||||
|     cosmoT_clearTable(state, &state->strings); |     cosmoT_clearTable(state, &state->strings); | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/cstate.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/cstate.h
									
									
									
									
									
								
							| @@ -12,11 +12,12 @@ typedef struct CCallFrame { | |||||||
|     CValue* base; |     CValue* base; | ||||||
| } CCallFrame; | } CCallFrame; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum IStringEnum { | ||||||
|     INTERNALSTRING_INIT, // __init |     ISTRING_INIT, // __init | ||||||
|     INTERNALSTRING_EQUAL, // __equal |     ISTRING_EQUAL, // __equal | ||||||
|     INTERNALSTRING_MAX |     ISTRING_INDEX, | ||||||
| } InternalStringEnum; |     ISTRING_MAX | ||||||
|  | } IStringEnum; | ||||||
|  |  | ||||||
| typedef struct CState { | typedef struct CState { | ||||||
|     bool panic; |     bool panic; | ||||||
| @@ -37,7 +38,7 @@ typedef struct CState { | |||||||
|     CCallFrame callFrame[FRAME_MAX]; // call frames |     CCallFrame callFrame[FRAME_MAX]; // call frames | ||||||
|     int frameCount; |     int frameCount; | ||||||
|  |  | ||||||
|     CObjString *internalStrings[INTERNALSTRING_MAX]; // strings used internally by the VM, eg. __init |     CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index & friends | ||||||
|     CObjObject *protoObj; // start met obj for all objects (NULL by default) |     CObjObject *protoObj; // start met obj for all objects (NULL by default) | ||||||
| } CState; | } CState; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -191,7 +191,7 @@ COSMOVMRESULT cosmoV_call(CState *state, int args) { | |||||||
|             CValue ret; |             CValue ret; | ||||||
|  |  | ||||||
|             // check if they defined an initalizer |             // check if they defined an initalizer | ||||||
|             if (cosmoV_getObject(state, protoObj, cosmoV_newObj(state->internalStrings[INTERNALSTRING_INIT]), &ret) && IS_METHOD(ret)) { |             if (cosmoV_getObject(state, protoObj, cosmoV_newObj(state->iStrings[ISTRING_INIT]), &ret) && IS_METHOD(ret)) { | ||||||
|                 callMethod(state, cosmoV_readMethod(ret), args); |                 callMethod(state, cosmoV_readMethod(ret), args); | ||||||
|                 cosmoV_pop(state); |                 cosmoV_pop(state); | ||||||
|             } else { |             } else { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user