*developing class, added reference, inheritance.

This commit is contained in:
paladin-t 2015-12-08 14:39:07 +08:00
parent 949baa2212
commit c6f819c82c
6 changed files with 303 additions and 180 deletions

View File

@ -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

View File

@ -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;

View File

@ -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,

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 206 KiB

View File

@ -61,8 +61,8 @@ extern "C" {
#endif /* __BORLANDC__ */
#ifdef __POCC__
# define unlink _unlink
# define strdup _strdup
# define unlink _unlink
#endif /* __POCC__ */
/*