diff --git a/HISTORY b/HISTORY index 0253cf7..bec2b45 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +May. 8 2017 +Added a global alive object checker + May. 7 2017 Fixed a wrong context processing bug when evaluating a routine manually, thanks to Diederik for pointing it out diff --git a/MY-BASIC Quick Reference.pdf b/MY-BASIC Quick Reference.pdf index f482385..0444c6c 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 567b7cc..6fd54b5 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -411,7 +411,7 @@ typedef struct _usertype_ref_t { mb_cmp_func_t cmp; mb_fmt_func_t fmt; #ifdef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF - mb_alive_checker alive_checker; + mb_alive_value_checker alive_checker; #endif /* MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF */ _calculation_operator_info_t* calc_operators; mb_meta_func_t coll_func; @@ -869,6 +869,7 @@ typedef struct mb_interpreter_t { unsigned short last_error_row; unsigned short last_error_col; /** Handlers */ + mb_alive_checker alive_check_handler; mb_debug_stepped_handler_t debug_stepped_handler; mb_error_handler_t error_handler; mb_print_func_t printer; @@ -6537,6 +6538,8 @@ static void _gc_collect_garbage(mb_interpreter_t* s, int depth) { if(depth != -1) gc->valid_table = valid; _gc_get_reachable(s, valid); + if(s->alive_check_handler) + s->alive_check_handler(s, valid, _gc_alive_marker); /* Get unreachable information */ _HT_FOREACH(valid, _do_nothing_on_object, _ht_remove_exist, gc->table); @@ -12727,8 +12730,20 @@ _exit: return result; } +/* Set the global alive checker */ +int mb_set_alive_checker(struct mb_interpreter_t* s, mb_alive_checker f) { + int result = MB_FUNC_OK; + + if(!s) + result = MB_FUNC_ERR; + else + s->alive_check_handler = f; + + 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) { +int mb_set_alive_checker_of_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_alive_value_checker f) { #ifdef MB_ENABLE_ALIVE_CHECKING_ON_USERTYPE_REF int result = MB_FUNC_OK; _object_t obj; @@ -17737,6 +17752,7 @@ static int _coll_move_next(mb_interpreter_t* s, void** l) { mb_value_t it; _object_t oit; mb_value_t ret; + mb_meta_status_u os = MB_MS_NONE; mb_assert(s && l); @@ -17746,43 +17762,47 @@ static int _coll_move_next(mb_interpreter_t* s, void** l) { mb_check(mb_attempt_open_bracket(s, l)); mb_check(mb_pop_value(s, l, &it)); + os = _try_overridden(s, l, &it, _COLL_ID_MOVE_NEXT, MB_MF_COLL); + if((os & MB_MS_DONE) == MB_MS_NONE) { + _MAKE_NIL(&oit); + switch(it.type) { + case MB_DT_LIST_IT: + _public_value_to_internal_object(&it, &oit); + oit.data.list_it = _move_list_it_next(oit.data.list_it); + if(_invalid_list_it(oit.data.list_it)) { + _handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + } else if(oit.data.list_it) { + mb_make_bool(ret, true); + } else { + mb_make_nil(ret); + } + + break; + case MB_DT_DICT_IT: + _public_value_to_internal_object(&it, &oit); + oit.data.dict_it = _move_dict_it_next(oit.data.dict_it); + if(_invalid_dict_it(oit.data.dict_it)) { + _handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + } else if(oit.data.dict_it) { + mb_make_bool(ret, true); + } else { + mb_make_nil(ret); + } + + break; + default: + _handle_error_on_obj(s, SE_RN_ITERATOR_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + + break; + } + } mb_check(mb_attempt_close_bracket(s, l)); - _MAKE_NIL(&oit); - switch(it.type) { - case MB_DT_LIST_IT: - _public_value_to_internal_object(&it, &oit); - oit.data.list_it = _move_list_it_next(oit.data.list_it); - if(_invalid_list_it(oit.data.list_it)) { - _handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); - } else if(oit.data.list_it) { - mb_make_bool(ret, true); - } else { - mb_make_nil(ret); - } - - break; - case MB_DT_DICT_IT: - _public_value_to_internal_object(&it, &oit); - oit.data.dict_it = _move_dict_it_next(oit.data.dict_it); - if(_invalid_dict_it(oit.data.dict_it)) { - _handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); - } else if(oit.data.dict_it) { - mb_make_bool(ret, true); - } else { - mb_make_nil(ret); - } - - break; - default: - _handle_error_on_obj(s, SE_RN_ITERATOR_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); - - break; + if((os & MB_MS_RETURNED) == MB_MS_NONE) { + mb_check(mb_push_value(s, l, ret)); } - mb_check(mb_push_value(s, l, ret)); - _exit: return result; } diff --git a/core/my_basic.h b/core/my_basic.h index d5f20a9..903c08c 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -563,7 +563,8 @@ 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 void (* mb_alive_checker)(struct mb_interpreter_t*, void*, mb_alive_marker); +typedef void (* mb_alive_value_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); @@ -623,7 +624,8 @@ 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_set_alive_checker(struct mb_interpreter_t* s, mb_alive_checker f); +MBAPI int mb_set_alive_checker_of_value(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_alive_value_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);