diff --git a/HISTORY b/HISTORY index 998920e..5241d0f 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +Mar. 29 2017 +Added an alive object checker of referenced usertype + Mar. 17 2017 Added storing of different types support for array diff --git a/MY-BASIC Quick Reference.pdf b/MY-BASIC Quick Reference.pdf index 6cc5632..76462cb 100644 Binary files a/MY-BASIC Quick Reference.pdf and b/MY-BASIC Quick Reference.pdf differ diff --git a/core/my_basic.c b/core/my_basic.c index 455d6a9..0dd0f45 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -299,6 +299,7 @@ MBCONST static const char* const _ERR_DESC[] = { "Collection or iterator or class expected", "Invalid iterator", "Empty collection", + "Referenced usertype expected", "Referenced type expected", "Reference count overflow", "Weak reference count overflow", @@ -398,6 +399,9 @@ typedef struct _usertype_ref_t { mb_hash_func_t hash; mb_cmp_func_t cmp; mb_fmt_func_t fmt; +#ifdef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF + mb_alive_checker alive_checker; +#endif /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ _calculation_operator_info_t* calc_operators; mb_meta_func_t coll_func; mb_meta_func_t generic_func; @@ -1638,6 +1642,7 @@ static void _gc_remove(_ref_t* ref, void* data, _gc_t* gc); static int _gc_add_reachable(void* data, void* extra, void* h); static int _gc_add_reachable_both(void* data, void* extra, void* h); static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht); +static void _gc_alive_marker(mb_interpreter_t* s, void* h, mb_value_t val); static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc); static int _gc_destroy_garbage_in_dict(void* data, void* extra, _gc_t* gc); #ifdef MB_ENABLE_CLASS @@ -6123,6 +6128,14 @@ static int _gc_add_reachable(void* data, void* extra, void* h) { case _DT_USERTYPE_REF: if(!_ht_find(ht, &obj->data.usertype_ref->ref)) _ht_set_or_insert(ht, &obj->data.usertype_ref->ref, obj->data.usertype_ref); +#ifdef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF + if(obj->data.usertype_ref->alive_checker) { + mb_value_t val; + mb_make_nil(val); + _internal_object_to_public_value(obj, &val); + obj->data.usertype_ref->alive_checker(obj->data.usertype_ref->ref.s, h, val, _gc_alive_marker); + } +#endif /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ break; #endif /* MB_ENABLE_USERTYPE_REF */ @@ -6219,6 +6232,18 @@ static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht) { } } +/* Alive marker functor of a value */ +static void _gc_alive_marker(mb_interpreter_t* s, void* h, mb_value_t val) { + _ht_node_t* ht = 0; + _object_t obj; + mb_unrefvar(s); + + ht = (_ht_node_t*)h; + _MAKE_NIL(&obj); + _public_value_to_internal_object(&val, &obj); + _gc_add_reachable(&obj, 0, h); +} + /* Destroy only the capsule (wrapper) of an object, leave the data behind, and add it to GC if possible */ static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc) { int result = _OP_RESULT_DEL_NODE; @@ -12579,6 +12604,38 @@ _exit: return result; } +/* Set the alive checker of a value */ +int mb_set_alive_checker_of_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_alive_checker f) { +#ifdef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF + int result = MB_FUNC_OK; + _object_t obj; + + if(!s) { + result = MB_FUNC_ERR; + + goto _exit; + } + + if(val.type != MB_DT_USERTYPE_REF) { + _handle_error_on_obj(s, SE_RN_REFERENCED_USERTYPE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + } + + _MAKE_NIL(&obj); + _public_value_to_internal_object(&val, &obj); + obj.data.usertype_ref->alive_checker = f; + +_exit: + return result; +#else /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ + mb_unrefvar(s); + mb_unrefvar(l); + mb_unrefvar(val); + mb_unrefvar(f); + + return MB_FUNC_ERR; +#endif /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ +} + /* Override a meta function of a value */ int mb_override_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_meta_func_u m, void* f) { int result = MB_FUNC_OK; diff --git a/core/my_basic.h b/core/my_basic.h index e75c874..851909b 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -120,6 +120,12 @@ extern "C" { # define MB_ENABLE_USERTYPE_REF #endif /* MB_ENABLE_USERTYPE_REF */ +#ifdef MB_ENABLE_USERTYPE_REF +# ifndef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF +# define MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF +# endif /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ +#endif /* MB_ENABLE_USERTYPE_REF */ + #ifndef MB_ENABLE_CLASS # define MB_ENABLE_CLASS #endif /* MB_ENABLE_CLASS */ @@ -451,6 +457,7 @@ typedef enum mb_error_e { SE_RN_COLLECTION_OR_ITERATOR_OR_CLASS_EXPECTED, SE_RN_INVALID_ITERATOR, SE_RN_EMPTY_COLLECTION, + SE_RN_REFERENCED_USERTYPE_EXPECTED, SE_RN_REFERENCED_TYPE_EXPECTED, SE_RN_REFERENCE_COUNT_OVERFLOW, SE_RN_WEAK_REFERENCE_COUNT_OVERFLOW, @@ -555,6 +562,8 @@ typedef void* (* mb_clone_func_t)(struct mb_interpreter_t*, void*); typedef unsigned (* mb_hash_func_t)(struct mb_interpreter_t*, void*); typedef int (* mb_cmp_func_t)(struct mb_interpreter_t*, void*, void*); typedef int (* mb_fmt_func_t)(struct mb_interpreter_t*, void*, char*, unsigned); +typedef void (* mb_alive_marker)(struct mb_interpreter_t*, void*, mb_value_t); +typedef void (* mb_alive_checker)(struct mb_interpreter_t*, void*, mb_value_t, mb_alive_marker); typedef int (* mb_meta_operator_t)(struct mb_interpreter_t*, void**, mb_value_t*, mb_value_t*, mb_value_t*); typedef mb_meta_status_u (* mb_meta_func_t)(struct mb_interpreter_t*, void**, mb_value_t*, const char*); typedef char* (* mb_memory_allocate_func_t)(unsigned); @@ -614,6 +623,7 @@ MBAPI int mb_make_ref_value(struct mb_interpreter_t* s, void* val, mb_value_t* o MBAPI int mb_get_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val, void** out); MBAPI int mb_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val); MBAPI int mb_unref_value(struct mb_interpreter_t* s, void** l, mb_value_t val); +MBAPI int mb_set_alive_checker_of_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_alive_checker f); MBAPI int mb_override_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_meta_func_u m, void* f); MBAPI int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val);