diff --git a/HISTORY b/HISTORY index dd87b4f..6aba9df 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +Dec. 8 2015 +Developing class, added reference, inheritance + Dec. 7 2015 Improved TICKS function Initialized random number seed on start up diff --git a/core/my_basic.c b/core/my_basic.c index ee35a15..a0dc8a6 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -81,7 +81,7 @@ extern "C" { /** Macros */ #define _VER_MAJOR 1 #define _VER_MINOR 1 -#define _VER_REVISION 102 +#define _VER_REVISION 103 #define _VER_SUFFIX #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) #define _STRINGIZE(A) _MAKE_STRINGIZE(A) @@ -234,6 +234,7 @@ static const char* _ERR_DESC[] = { "Duplicate routine", "Invalid class", "Class expected", + "Wrong meta class", "Collection expected", "Iterator expected", "Collection or iterator expected", @@ -366,7 +367,9 @@ typedef struct _label_t { #ifdef MB_ENABLE_CLASS typedef struct _class_t { + _ref_t ref; char* name; + _ls_node_t* meta_list; struct _running_context_t* scope; } _class_t; #endif /* MB_ENABLE_CLASS */ @@ -1046,6 +1049,83 @@ static bool_t _is_number(void* obj); static bool_t _is_string(void* obj); static char* _extract_string(_object_t* obj); +#define _REF_USERTYPE_REF(__o) \ + case _DT_USERTYPE_REF: \ + _ref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \ + break; +#define _UNREF_USERTYPE_REF(__o) \ + case _DT_USERTYPE_REF: \ + _unref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \ + break; +#define _REF_ARRAY(__o) \ + case _DT_ARRAY: \ + if(!(__o)->ref) \ + _ref(&(__o)->data.array->ref, (__o)->data.array); \ + break; +#define _UNREF_ARRAY(__o) \ + case _DT_ARRAY: \ + if(!(__o)->ref) \ + _unref(&(__o)->data.array->ref, (__o)->data.array); \ + break; +#ifdef MB_ENABLE_COLLECTION_LIB +# define _REF_COLL(__o) \ + case _DT_LIST: \ + _ref(&(__o)->data.list->ref, (__o)->data.list); \ + break; \ + case _DT_DICT: \ + _ref(&(__o)->data.dict->ref, (__o)->data.dict); \ + break; +# define _UNREF_COLL(__o) \ + case _DT_LIST: \ + _unref(&(__o)->data.list->ref, (__o)->data.list); \ + break; \ + case _DT_DICT: \ + _unref(&(__o)->data.dict->ref, (__o)->data.dict); \ + break; +#else /* MB_ENABLE_COLLECTION_LIB */ +# define _REF_COLL(__o) ((void)(__o)); +# define _UNREF_COLL(__o) ((void)(__o)); +#endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS +# define _REF_CLASS(__o) \ + case _DT_CLASS: \ + _ref(&(__o)->data.instance->ref, (__o)->data.instance); \ + break; +# define _UNREF_CLASS(__o) \ + case _DT_CLASS: \ + if(!(__o)->ref) \ + _unref(&(__o)->data.instance->ref, (__o)->data.instance); \ + break; +#else /* MB_ENABLE_CLASS */ +# define _REF_CLASS(__o) ((void)(__o)); +# define _UNREF_CLASS(__o) ((void)(__o)); +#endif /* MB_ENABLE_CLASS */ +#define _REF(__o) \ + switch((__o)->type) { \ + _REF_USERTYPE_REF(__o) \ + _REF_ARRAY(__o) \ + _REF_COLL(__o) \ + _REF_CLASS(__o) \ + default: break; \ + } +#define _UNREF(__o) \ + switch((__o)->type) { \ + _UNREF_USERTYPE_REF(__o) \ + _UNREF_ARRAY(__o) \ + _UNREF_COLL(__o) \ + _UNREF_CLASS(__o) \ + default: break; \ + } + +static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj); +static bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj); +static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj); + +static unsigned _ref(_ref_t* ref, void* data); +static unsigned _unref(_ref_t* ref, void* data); +static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s); +static void _destroy_ref(_ref_t* ref); + #ifdef MB_ENABLE_GC static void _gc_add(_ref_t* ref, void* data); static void _gc_remove(_ref_t* ref, void* data); @@ -1106,71 +1186,15 @@ static int _clone_to_list(void* data, void* extra, _list_t* coll); static int _clone_to_dict(void* data, void* extra, _dict_t* coll); #endif /* MB_ENABLE_COLLECTION_LIB */ -#define _REF_USERTYPE_REF(__o) \ - case _DT_USERTYPE_REF: \ - _ref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \ - break; -#define _UNREF_USERTYPE_REF(__o) \ - case _DT_USERTYPE_REF: \ - _unref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \ - break; -#define _REF_ARRAY(__o) \ - case _DT_ARRAY: \ - if(!(__o)->ref) \ - _ref(&(__o)->data.array->ref, (__o)->data.array); \ - break; -#define _UNREF_ARRAY(__o) \ - case _DT_ARRAY: \ - if(!(__o)->ref) \ - _unref(&(__o)->data.array->ref, (__o)->data.array); \ - break; -#ifdef MB_ENABLE_COLLECTION_LIB -# define _REF_COLL(__o) \ - case _DT_LIST: \ - _ref(&(__o)->data.list->ref, (__o)->data.list); \ - break; \ - case _DT_DICT: \ - _ref(&(__o)->data.dict->ref, (__o)->data.dict); \ - break; -# define _UNREF_COLL(__o) \ - case _DT_LIST: \ - _unref(&(__o)->data.list->ref, (__o)->data.list); \ - break; \ - case _DT_DICT: \ - _unref(&(__o)->data.dict->ref, (__o)->data.dict); \ - break; -#else /* MB_ENABLE_COLLECTION_LIB */ -# define _REF_COLL(__o) ((void)(__o)); -# define _UNREF_COLL(__o) ((void)(__o)); -#endif /* MB_ENABLE_COLLECTION_LIB */ -#define _REF(__o) \ - switch((__o)->type) { \ - _REF_USERTYPE_REF(__o) \ - _REF_ARRAY(__o) \ - _REF_COLL(__o) \ - default: break; \ - } -#define _UNREF(__o) \ - switch((__o)->type) { \ - _UNREF_USERTYPE_REF(__o) \ - _UNREF_ARRAY(__o) \ - _UNREF_COLL(__o) \ - default: break; \ - } - -static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj); -static bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj); -static bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj); - -static unsigned _ref(_ref_t* ref, void* data); -static unsigned _unref(_ref_t* ref, void* data); -static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s); -static void _destroy_ref(_ref_t* ref); - #ifdef MB_ENABLE_CLASS static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n); static void _begin_class(mb_interpreter_t* s); static bool_t _end_class(mb_interpreter_t* s); +static void _unref_class(_ref_t* ref, void* data); +static void _destroy_class(_class_t* c); +static bool_t _link_meta_class(mb_interpreter_t* s, _class_t* derived, _class_t* base); +static void _unlink_meta_class(mb_interpreter_t* s, _class_t* derived); +static int _unlink_meta_instance(void* data, void* extra, _class_t* derived); #endif /* MB_ENABLE_CLASS */ static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n); static void _begin_routine(mb_interpreter_t* s); @@ -2739,6 +2763,9 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) { #ifdef MB_ENABLE_COLLECTION_LIB c->type == _DT_LIST || c->type == _DT_LIST_IT || c->type == _DT_DICT || c->type == _DT_DICT_IT || #endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS + c->type == _DT_CLASS || +#endif /* MB_ENABLE_CLASS */ c->type == _DT_VAR || c->type == _DT_USERTYPE || c->type == _DT_USERTYPE_REF || c->type == _DT_ARRAY)) { _set_current_error(s, SE_RN_INVALID_DATA_TYPE, 0); result = MB_FUNC_ERR; @@ -2769,17 +2796,19 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) { if(guard_val != c && _ls_try_remove(garbage, c, _ls_cmp_data, NULL)) { _try_clear_intermediate_value(c, 0, s); + if(c->type == _DT_USERTYPE_REF || #ifdef MB_ENABLE_COLLECTION_LIB - if(c->type == _DT_USERTYPE_REF || c->type == _DT_ARRAY || c->type == _DT_LIST || c->type == _DT_DICT || c->type == _DT_LIST_IT || c->type == _DT_DICT_IT) - _destroy_object_capsule_only(c, 0); - else - _destroy_object(c, 0); -#else /* MB_ENABLE_COLLECTION_LIB */ - if(c->type == _DT_USERTYPE_REF || c->type == _DT_ARRAY) - _destroy_object_capsule_only(c, 0); - else - _destroy_object(c, 0); + c->type == _DT_LIST || c->type == _DT_DICT || c->type == _DT_LIST_IT || c->type == _DT_DICT_IT || #endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS + c->type == _DT_CLASS || +#endif /* MB_ENABLE_CLASS */ + c->type == _DT_ARRAY + ) { + _destroy_object_capsule_only(c, 0); + } else { + _destroy_object(c, 0); + } } _exit: @@ -3960,6 +3989,96 @@ char* _extract_string(_object_t* obj) { return result; } +bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { + /* Lock an object */ + mb_assert(lk); + + _ref(ref, obj); + if(*lk >= 0) + ++(*lk); + else + --(*lk); + + return true; +} + +bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { + /* Unlock an object */ + bool_t result = true; + mb_assert(lk); + + if(*lk > 0) + --(*lk); + else if(*lk < 0) + ++(*lk); + else + result = false; + _unref(ref, obj); + + return result; +} + +bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { + /* Write operation on a collection */ + bool_t result = true; + mb_unrefvar(ref); + mb_unrefvar(obj); + + mb_assert(lk); + + if(*lk > 0) + *lk = -(*lk); + else + result = false; + + return result; +} + +unsigned _ref(_ref_t* ref, void* data) { + /* Add a referenct to a stub */ + mb_unrefvar(data); + + return ++(*(ref->count)); +} + +unsigned _unref(_ref_t* ref, void* data) { + /* Remove a reference to a stub */ + unsigned result = 0; + + result = --(*(ref->count)); +#ifdef MB_ENABLE_GC + _gc_add(ref, data); + ref->on_unref(ref, data); + if(!ref->count) + _gc_remove(ref, data); +#else /* MB_ENABLE_GC */ + ref->on_unref(ref, data); +#endif /* MB_ENABLE_GC */ + + return result; +} + +void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s) { + /* Create a reference stub */ + if(ref->count) + return; + + ref->count = (unsigned*)mb_malloc(sizeof(unsigned)); + *(ref->count) = 0; + ref->on_unref = dtor; + ref->type = t; + ref->s = s; +} + +void _destroy_ref(_ref_t* ref) { + /* Destroy a reference stub */ + if(!ref->count) + return; + + safe_free(ref->count); + ref->on_unref = 0; +} + #ifdef MB_ENABLE_GC void _gc_add(_ref_t* ref, void* data) { /* Add a referenced object to GC */ @@ -4043,6 +4162,15 @@ int _gc_add_reachable(void* data, void* extra, _ht_node_t* ht) { break; #endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS + case _DT_CLASS: + if(!_ht_find(ht, &obj->data.instance->ref)) { + _ht_set_or_insert(ht, &obj->data.instance->ref, obj->data.instance); + /* TODO */ + } + + break; +#endif /* MB_ENABLE_CLASS */ default: /* Do nothing */ break; } @@ -5028,96 +5156,6 @@ int _clone_to_dict(void* data, void* extra, _dict_t* coll) { } #endif /* MB_ENABLE_COLLECTION_LIB */ -bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { - /* Lock an object */ - mb_assert(lk); - - _ref(ref, obj); - if(*lk >= 0) - ++(*lk); - else - --(*lk); - - return true; -} - -bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { - /* Unlock an object */ - bool_t result = true; - mb_assert(lk); - - if(*lk > 0) - --(*lk); - else if(*lk < 0) - ++(*lk); - else - result = false; - _unref(ref, obj); - - return result; -} - -bool_t _write_on_ref_object(_lock_t* lk, _ref_t* ref, void* obj) { - /* Write operation on a collection */ - bool_t result = true; - mb_unrefvar(ref); - mb_unrefvar(obj); - - mb_assert(lk); - - if(*lk > 0) - *lk = -(*lk); - else - result = false; - - return result; -} - -unsigned _ref(_ref_t* ref, void* data) { - /* Add a referenct to a stub */ - mb_unrefvar(data); - - return ++(*(ref->count)); -} - -unsigned _unref(_ref_t* ref, void* data) { - /* Remove a reference to a stub */ - unsigned result = 0; - - result = --(*(ref->count)); -#ifdef MB_ENABLE_GC - _gc_add(ref, data); - ref->on_unref(ref, data); - if(!ref->count) - _gc_remove(ref, data); -#else /* MB_ENABLE_GC */ - ref->on_unref(ref, data); -#endif /* MB_ENABLE_GC */ - - return result; -} - -void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s) { - /* Create a reference stub */ - if(ref->count) - return; - - ref->count = (unsigned*)mb_malloc(sizeof(unsigned)); - *(ref->count) = 0; - ref->on_unref = dtor; - ref->type = t; - ref->s = s; -} - -void _destroy_ref(_ref_t* ref) { - /* Destroy a reference stub */ - if(!ref->count) - return; - - safe_free(ref->count); - ref->on_unref = 0; -} - #ifdef MB_ENABLE_CLASS void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) { /* Initialize a class */ @@ -5128,7 +5166,10 @@ void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) { running = s->running_context; memset(instance, 0, sizeof(_class_t)); + _create_ref(&instance->ref, _unref_class, _DT_CLASS, s); + _ref(&instance->ref, instance); instance->name = n; + instance->meta_list = _ls_create(); instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t)); memset(instance->scope, 0, sizeof(_running_context_t)); instance->scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0); @@ -5160,6 +5201,64 @@ bool_t _end_class(mb_interpreter_t* s) { return true; } + +void _unref_class(_ref_t* ref, void* data) { + /* Unreference a class instance */ + if(!(*(ref->count))) + _destroy_class((_class_t*)data); +} + +void _destroy_class(_class_t* c) { + /* Destroy a class instance */ + safe_free(c->name); + if(c->meta_list) { + _unlink_meta_class(c->ref.s, c); + _ls_destroy(c->meta_list); + } + if(c->scope->var_dict) { + _ht_foreach(c->scope->var_dict, _destroy_object); + _ht_destroy(c->scope->var_dict); + } + safe_free(c->scope); + _destroy_ref(&c->ref); + safe_free(c); +} + +bool_t _link_meta_class(mb_interpreter_t* s, _class_t* derived, _class_t* base) { + /* Link a class instance to another's meta list */ + mb_assert(s && derived && base); + + if(_ls_find(derived->meta_list, base, _ls_cmp_data)) { + _handle_error_now(s, SE_RN_WRONG_META_CLASS, 0, MB_FUNC_ERR); + + return false; + } + + _ls_pushback(derived->meta_list, base); + _ref(&base->ref, base); + + return true; +} + +void _unlink_meta_class(mb_interpreter_t* s, _class_t* derived) { + /* Unlink a class instance's all meta class instances */ + mb_assert(s && derived); + + _LS_FOREACH(derived->meta_list, _do_nothing_on_object, _unlink_meta_instance, derived); + _ls_clear(derived->meta_list); +} + +int _unlink_meta_instance(void* data, void* extra, _class_t* derived) { + /* Unlink a meta class instance */ + _class_t* base = 0; + + mb_assert(data && derived); + + base = (_class_t*)data; + _unref(&base->ref, base); + + return 0; +} #endif /* MB_ENABLE_CLASS */ void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) { @@ -5536,6 +5635,7 @@ int _clone_object(_object_t* obj, _object_t* tgt) { #ifdef MB_ENABLE_CLASS case _DT_CLASS: mb_assert(0 && "Not implemented"); + /* TODO */ break; #endif /* MB_ENABLE_CLASS */ @@ -5609,6 +5709,7 @@ int _dispose_object(_object_t* obj) { _UNREF_USERTYPE_REF(obj) _UNREF_ARRAY(obj) _UNREF_COLL(obj) + _UNREF_CLASS(obj) #ifdef MB_ENABLE_COLLECTION_LIB case _DT_LIST_IT: _destroy_list_it(obj->data.list_it); @@ -5626,18 +5727,6 @@ int _dispose_object(_object_t* obj) { } break; -#ifdef MB_ENABLE_CLASS - case _DT_CLASS: - if(!obj->ref) { - safe_free(obj->data.instance->name); - _ht_foreach(obj->data.instance->scope->var_dict, _destroy_object); - _ht_destroy(obj->data.instance->scope->var_dict); - safe_free(obj->data.instance->scope); - safe_free(obj->data.instance); - } - - break; -#endif /* MB_ENABLE_CLASS */ case _DT_ROUTINE: if(!obj->ref) { safe_free(obj->data.routine->name); @@ -7940,11 +8029,15 @@ int mb_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) { _MAKE_NIL(&obj); _public_value_to_internal_object(&val, &obj); + if(obj.type != _DT_USERTYPE_REF && #ifdef MB_ENABLE_COLLECTION_LIB - if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY && obj.type != _DT_LIST && obj.type != _DT_DICT) { -#else /* MB_ENABLE_COLLECTION_LIB */ - if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY) { + obj.type != _DT_LIST && obj.type != _DT_DICT && #endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS + obj.type != _DT_CLASS && +#endif /* MB_ENABLE_CLASS */ + obj.type != _DT_ARRAY + ) { _handle_error_on_obj(s, SE_RN_REFERENCED_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); } _REF(&obj); @@ -7962,11 +8055,15 @@ int mb_unref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) { _MAKE_NIL(&obj); _public_value_to_internal_object(&val, &obj); + if(obj.type != _DT_USERTYPE_REF && #ifdef MB_ENABLE_COLLECTION_LIB - if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY && obj.type != _DT_LIST && obj.type != _DT_DICT) { -#else /* MB_ENABLE_COLLECTION_LIB */ - if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY) { + obj.type != _DT_LIST && obj.type != _DT_DICT && #endif /* MB_ENABLE_COLLECTION_LIB */ +#ifdef MB_ENABLE_CLASS + obj.type != _DT_CLASS && +#endif /* MB_ENABLE_CLASS */ + obj.type != _DT_ARRAY + ) { _handle_error_on_obj(s, SE_RN_REFERENCED_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); } _UNREF(&obj); @@ -9729,6 +9826,7 @@ int _core_class(mb_interpreter_t* s, void** l) { _running_context_t* running = 0; _object_t* obj = 0; _class_t* instance = 0; + _class_t* inherit = 0; mb_assert(s && l); @@ -9745,6 +9843,27 @@ int _core_class(mb_interpreter_t* s, void** l) { } instance = (_class_t*)(((_object_t*)(ast->data))->data.instance); ast = ast->next; + obj = (_object_t*)(ast->data); + + if(_IS_FUNC(obj, _core_open_bracket)) { + /* Process meta_list */ + do { + ast = ast->next; + obj = (_object_t*)(ast->data); + if(!_IS_CLASS(obj)) { + _handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, obj, MB_FUNC_ERR, _exit, result); + } + inherit = obj->data.instance; + _link_meta_class(s, instance, inherit); + ast = ast->next; + obj = (_object_t*)(ast->data); + } while(_IS_CLASS(obj) || _IS_SEP(obj, ',')); + if(_IS_FUNC(obj, _core_close_bracket)) { + ast = ast->next; + } else { + _handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, 0, obj, MB_FUNC_ERR, _exit, result); + } + } *l = ast; diff --git a/core/my_basic.h b/core/my_basic.h index eee484d..2b42fc2 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -315,6 +315,7 @@ typedef enum mb_error_e { SE_RN_DUPLICATE_ROUTINE, SE_RN_INVALID_CLASS, SE_RN_CLASS_EXPECTED, + SE_RN_WRONG_META_CLASS, SE_RN_COLLECTION_EXPECTED, SE_RN_ITERATOR_EXPECTED, SE_RN_COLLECTION_OR_ITERATOR_EXPECTED, diff --git a/output/my_basic.exe b/output/my_basic.exe index ff7412b..74b2dd0 100755 Binary files a/output/my_basic.exe and b/output/my_basic.exe differ diff --git a/resource/icon.ico b/resource/icon.ico index 9d6d1ad..0e003ae 100755 Binary files a/resource/icon.ico and b/resource/icon.ico differ diff --git a/shell/main.c b/shell/main.c index fa72e61..e5303ea 100755 --- a/shell/main.c +++ b/shell/main.c @@ -61,8 +61,8 @@ extern "C" { #endif /* __BORLANDC__ */ #ifdef __POCC__ -# define unlink _unlink # define strdup _strdup +# define unlink _unlink #endif /* __POCC__ */ /*