*fixed a memory leak with a hanged value.

*fixed some crash.
This commit is contained in:
Wang Renxin 2017-10-24 20:52:51 +08:00
parent 23e29abb45
commit c3dfe71c9c
3 changed files with 135 additions and 27 deletions

View File

@ -1,3 +1,6 @@
Oct. 24 2017
Fixed a memory leak with a hanged value
Oct. 23 2017 Oct. 23 2017
Added support to apply the CLONE statement to a referenced usertype Added support to apply the CLONE statement to a referenced usertype

View File

@ -337,6 +337,7 @@ MBCONST static const char* const _ERR_DESC[] = {
"Collection or iterator expected", "Collection or iterator expected",
"Iterator expected", "Iterator expected",
"Invalid iterator", "Invalid iterator",
"Invalid iterator usage",
"Iterable expected", "Iterable expected",
"Referenced usertype expected", "Referenced usertype expected",
"Referenced type expected", "Referenced type expected",
@ -1756,7 +1757,7 @@ static bool_t _destroy_dict_it(_dict_it_t* it);
static _dict_it_t* _move_dict_it_next(_dict_it_t* it); static _dict_it_t* _move_dict_it_next(_dict_it_t* it);
static void _unref_list(_ref_t* ref, void* data); static void _unref_list(_ref_t* ref, void* data);
static void _unref_dict(_ref_t* ref, void* data); static void _unref_dict(_ref_t* ref, void* data);
static void _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg); static bool_t _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg);
static bool_t _pop_list(_list_t* coll, mb_value_t* val, mb_interpreter_t* s); static bool_t _pop_list(_list_t* coll, mb_value_t* val, mb_interpreter_t* s);
static bool_t _insert_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval); static bool_t _insert_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval);
static bool_t _set_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval); static bool_t _set_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval);
@ -1768,7 +1769,7 @@ static void _clear_list(_list_t* coll);
static void _sort_list(_list_t* coll); static void _sort_list(_list_t* coll);
static void _invalidate_list_cache(_list_t* coll); static void _invalidate_list_cache(_list_t* coll);
static void _fill_ranged(_list_t* coll); static void _fill_ranged(_list_t* coll);
static void _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t* okey, _object_t* oval); static bool_t _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t* okey, _object_t* oval);
static bool_t _remove_dict(_dict_t* coll, mb_value_t* key); static bool_t _remove_dict(_dict_t* coll, mb_value_t* key);
static bool_t _find_dict(_dict_t* coll, mb_value_t* val, mb_value_t* oval); static bool_t _find_dict(_dict_t* coll, mb_value_t* val, mb_value_t* oval);
static void _clear_dict(_dict_t* coll); static void _clear_dict(_dict_t* coll);
@ -1863,7 +1864,7 @@ static int _destroy_object_with_extra(void* data, void* extra);
static int _destroy_object_not_compile_time(void* data, void* extra); static int _destroy_object_not_compile_time(void* data, void* extra);
static int _destroy_object_capsule_only(void* data, void* extra); static int _destroy_object_capsule_only(void* data, void* extra);
static int _do_nothing_on_object(void* data, void* extra); static int _do_nothing_on_object(void* data, void* extra);
static int _lose_object(void* data, void* extra); static int _lose_object(void* data, void* extra, _running_context_t* running);
static int _remove_source_object(void* data, void* extra); static int _remove_source_object(void* data, void* extra);
static int _destroy_memory(void* data, void* extra); static int _destroy_memory(void* data, void* extra);
static int _compare_numbers(const _object_t* first, const _object_t* second); static int _compare_numbers(const _object_t* first, const _object_t* second);
@ -1886,7 +1887,8 @@ static void _swap_public_value(mb_value_t* tgt, mb_value_t* src);
static int _clear_scope_chain(mb_interpreter_t* s); static int _clear_scope_chain(mb_interpreter_t* s);
static int _dispose_scope_chain(mb_interpreter_t* s); static int _dispose_scope_chain(mb_interpreter_t* s);
static void _tidy_scope_chain(mb_interpreter_t* s); static void _tidy_scope_chain(mb_interpreter_t* s);
static void _tidy_intermediate_value(_ref_t* ref, void* data); static void _collect_intermediate_value(_ref_t* ref, void* data);
static void _mark_hanged_intermediate_value(mb_interpreter_t* s, _running_context_t* running);
static _object_t* _eval_var_in_print(mb_interpreter_t* s, _object_t** val_ptr, _ls_node_t** ast, _object_t* obj); static _object_t* _eval_var_in_print(mb_interpreter_t* s, _object_t** val_ptr, _ls_node_t** ast, _object_t* obj);
/** Interpretation */ /** Interpretation */
@ -3667,9 +3669,13 @@ static int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val
int bracket_count = 0; int bracket_count = 0;
bool_t hack = false; bool_t hack = false;
_ls_node_t* errn = 0; _ls_node_t* errn = 0;
bool_t gce = true;
mb_assert(s && l); mb_assert(s && l);
gce = mb_get_gc_enabled(s);
mb_set_gc_enabled(s, false);
running = s->running_context; running = s->running_context;
ast = *l; ast = *l;
@ -3856,7 +3862,7 @@ _routine:
s->calling = calling; s->calling = calling;
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
obj = (_object_t*)ast->data; obj = ast ? (_object_t*)ast->data : 0;
if(_IS_VAR(obj) && _is_valid_class_accessor_following_routine(s, obj->data.variable, ast, &fn)) { if(_IS_VAR(obj) && _is_valid_class_accessor_following_routine(s, obj->data.variable, ast, &fn)) {
if(fn) { if(fn) {
if(ast) ast = ast->next; if(ast) ast = ast->next;
@ -4157,6 +4163,7 @@ _exit:
mb_free(_ls_popback(s->in_neg_expr)); mb_free(_ls_popback(s->in_neg_expr));
} }
*l = ast; *l = ast;
mb_set_gc_enabled(s, gce);
return result; return result;
#undef _LAZY_INIT_GLIST #undef _LAZY_INIT_GLIST
@ -6157,7 +6164,7 @@ static bool_t _unref(_ref_t* ref, void* data) {
mb_assert(*ref->count >= _NONE_REF); mb_assert(*ref->count >= _NONE_REF);
_gc_add(ref, data, &ref->s->gc); _gc_add(ref, data, &ref->s->gc);
if(ref->count && *ref->count == _NONE_REF) if(ref->count && *ref->count == _NONE_REF)
_tidy_intermediate_value(ref, data); _collect_intermediate_value(ref, data);
ref->on_unref(ref, data); ref->on_unref(ref, data);
if(result) if(result)
_gc_remove(ref, data, gc); _gc_remove(ref, data, gc);
@ -7363,6 +7370,8 @@ static _dict_it_t* _move_dict_it_next(_dict_it_t* it) {
++it->curr_bucket; ++it->curr_bucket;
} }
if(!it->curr_node || it->curr_node == _INVALID_DICT_IT) { if(!it->curr_node || it->curr_node == _INVALID_DICT_IT) {
if(!it->dict->dict->array)
goto _exit;
for( ; it->curr_bucket < it->dict->dict->array_size; ++it->curr_bucket) { for( ; it->curr_bucket < it->dict->dict->array_size; ++it->curr_bucket) {
it->curr_node = it->dict->dict->array[it->curr_bucket]; it->curr_node = it->dict->dict->array[it->curr_bucket];
if(it->curr_node && it->curr_node->next) { if(it->curr_node && it->curr_node->next) {
@ -7397,7 +7406,7 @@ static void _unref_dict(_ref_t* ref, void* data) {
} }
/* Push a value to a list */ /* Push a value to a list */
static void _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg) { static bool_t _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg) {
mb_assert(coll && (val || oarg)); mb_assert(coll && (val || oarg));
_fill_ranged(coll); _fill_ranged(coll);
@ -7409,6 +7418,8 @@ static void _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg) {
_write_on_ref_object(&coll->lock, &coll->ref, coll); _write_on_ref_object(&coll->lock, &coll->ref, coll);
_invalidate_list_cache(coll); _invalidate_list_cache(coll);
return true;
} }
/* Pop a value from a list */ /* Pop a value from a list */
@ -7682,7 +7693,7 @@ static void _fill_ranged(_list_t* coll) {
} }
/* Set an element to a dictionary with a key-value pair */ /* Set an element to a dictionary with a key-value pair */
static void _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t* okey, _object_t* oval) { static bool_t _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t* okey, _object_t* oval) {
_ls_node_t* exists = 0; _ls_node_t* exists = 0;
mb_assert(coll && (key || okey) && (val || oval)); mb_assert(coll && (key || okey) && (val || oval));
@ -7697,6 +7708,8 @@ static void _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t
_ht_set_or_insert(coll->dict, okey, oval); _ht_set_or_insert(coll->dict, okey, oval);
_write_on_ref_object(&coll->lock, &coll->ref, coll); _write_on_ref_object(&coll->lock, &coll->ref, coll);
return true;
} }
/* Remove an element to a dictionary with a specific key */ /* Remove an element to a dictionary with a specific key */
@ -9034,7 +9047,7 @@ static void _out_of_scope(mb_interpreter_t* s, _running_context_t* running, void
if(lose) { if(lose) {
if(running->var_dict) if(running->var_dict)
_ht_foreach(running->var_dict, _lose_object); _HT_FOREACH(running->var_dict, _do_nothing_on_object, _lose_object, running);
} }
} }
@ -9506,8 +9519,8 @@ static int _dispose_object(_object_t* obj) {
_UNREF_USERTYPE_REF(obj) _UNREF_USERTYPE_REF(obj)
_UNREF_ARRAY(obj) _UNREF_ARRAY(obj)
_UNREF_COLL(obj) _UNREF_COLL(obj)
_UNREF_CLASS(obj)
_UNREF_COLL_IT(obj) _UNREF_COLL_IT(obj)
_UNREF_CLASS(obj)
_UNREF_ROUTINE(obj) _UNREF_ROUTINE(obj)
case _DT_LABEL: case _DT_LABEL:
if(!obj->is_ref) { if(!obj->is_ref) {
@ -9640,7 +9653,7 @@ static int _do_nothing_on_object(void* data, void* extra) {
} }
/* Lose an object in a scope */ /* Lose an object in a scope */
static int _lose_object(void* data, void* extra) { static int _lose_object(void* data, void* extra, _running_context_t* running) {
int result = _OP_RESULT_NORMAL; int result = _OP_RESULT_NORMAL;
_object_t* obj = 0; _object_t* obj = 0;
bool_t make_nil = true; bool_t make_nil = true;
@ -9652,9 +9665,24 @@ static int _lose_object(void* data, void* extra) {
if(obj->type == _DT_ROUTINE && obj->data.routine->type == MB_RT_LAMBDA) if(obj->type == _DT_ROUTINE && obj->data.routine->type == MB_RT_LAMBDA)
obj->is_ref = false; obj->is_ref = false;
#endif /* MB_ENABLE_LAMBDA */ #endif /* MB_ENABLE_LAMBDA */
#ifdef MB_ENABLE_COLLECTION_LIB
if(obj->type == _DT_LIST_IT) {
if((!obj->is_ref || !obj->data.list_it->locking) && running->intermediate_value.value.list_it != obj->data.list_it) {
_destroy_list_it(obj->data.list_it); /* Process hanged value */
}
goto _exit;
} else if(obj->type == _DT_DICT_IT) {
if((!obj->is_ref || !obj->data.dict_it->locking) && running->intermediate_value.value.dict_it != obj->data.dict_it) {
_destroy_dict_it(obj->data.dict_it); /* Process hanged value */
}
goto _exit;
}
#endif /* MB_ENABLE_COLLECTION_LIB */
switch(obj->type) { switch(obj->type) {
case _DT_VAR: case _DT_VAR:
_lose_object(obj->data.variable->data, extra); _lose_object(obj->data.variable->data, extra, running);
make_nil = false; make_nil = false;
break; break;
@ -9669,6 +9697,9 @@ static int _lose_object(void* data, void* extra) {
break; break;
} }
#ifdef MB_ENABLE_COLLECTION_LIB
_exit:
#endif /* MB_ENABLE_COLLECTION_LIB */
if(make_nil) { if(make_nil) {
_MAKE_NIL(obj); _MAKE_NIL(obj);
} }
@ -10317,8 +10348,8 @@ static void _tidy_scope_chain(mb_interpreter_t* s) {
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
} }
/* Tidy the intermediate value */ /* Collect the intermediate value */
static void _tidy_intermediate_value(_ref_t* ref, void* data) { static void _collect_intermediate_value(_ref_t* ref, void* data) {
_object_t tmp; _object_t tmp;
mb_assert(ref && data); mb_assert(ref && data);
@ -10328,8 +10359,11 @@ static void _tidy_intermediate_value(_ref_t* ref, void* data) {
_MAKE_NIL(&tmp); _MAKE_NIL(&tmp);
_public_value_to_internal_object(&ref->s->running_context->intermediate_value, &tmp); _public_value_to_internal_object(&ref->s->running_context->intermediate_value, &tmp);
if(tmp.data.usertype == data) { if(tmp.data.pointer == data) {
switch(tmp.type) { switch(tmp.type) {
#ifdef MB_ENABLE_USERTYPE_REF
case _DT_USERTYPE_REF: /* Fall through */
#endif /* MB_ENABLE_USERTYPE_REF */
#ifdef MB_ENABLE_COLLECTION_LIB #ifdef MB_ENABLE_COLLECTION_LIB
case _DT_LIST: /* Fall through */ case _DT_LIST: /* Fall through */
case _DT_DICT: /* Fall through */ case _DT_DICT: /* Fall through */
@ -10337,9 +10371,6 @@ static void _tidy_intermediate_value(_ref_t* ref, void* data) {
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
case _DT_CLASS: /* Fall through */ case _DT_CLASS: /* Fall through */
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
#ifdef MB_ENABLE_USERTYPE_REF
case _DT_USERTYPE_REF: /* Fall through */
#endif /* MB_ENABLE_USERTYPE_REF */
case _DT_ARRAY: case _DT_ARRAY:
mb_make_nil(ref->s->running_context->intermediate_value); mb_make_nil(ref->s->running_context->intermediate_value);
@ -10350,6 +10381,39 @@ static void _tidy_intermediate_value(_ref_t* ref, void* data) {
} }
} }
/* Mark the intermediate value to be collected if it's hanged */
static void _mark_hanged_intermediate_value(mb_interpreter_t* s, _running_context_t* running) {
mb_assert(s && running);
switch(running->intermediate_value.type) {
#ifdef MB_ENABLE_USERTYPE_REF
case MB_DT_USERTYPE_REF: /* Fall through */
#endif /* MB_ENABLE_USERTYPE_REF */
#ifdef MB_ENABLE_COLLECTION_LIB
case MB_DT_LIST: /* Fall through */
case MB_DT_DICT: /* Fall through */
case MB_DT_LIST_IT: /* Fall through */
case MB_DT_DICT_IT: /* Fall through */
#endif /* MB_ENABLE_COLLECTION_LIB */
case MB_DT_ROUTINE: {
_object_t tmp;
_MAKE_NIL(&tmp);
_public_value_to_internal_object(&running->intermediate_value, &tmp);
#ifdef MB_ENABLE_COLLECTION_LIB
if(tmp.type == _DT_LIST_IT && tmp.data.list_it->locking)
break;
else if(tmp.type == _DT_DICT_IT && tmp.data.dict_it->locking)
break;
#endif /* MB_ENABLE_COLLECTION_LIB */
_ADDGC(&tmp, &s->gc) /* Process hanged value */
}
break;
default: /* Do nothing */
break;
}
}
/* Evaluate a variable, this is a helper function for the PRINT statement */ /* Evaluate a variable, this is a helper function for the PRINT statement */
static _object_t* _eval_var_in_print(mb_interpreter_t* s, _object_t** val_ptr, _ls_node_t** ast, _object_t* obj) { static _object_t* _eval_var_in_print(mb_interpreter_t* s, _object_t** val_ptr, _ls_node_t** ast, _object_t* obj) {
_object_t tmp; _object_t tmp;
@ -10448,6 +10512,7 @@ _retry:
#ifdef MB_ENABLE_STACK_TRACE #ifdef MB_ENABLE_STACK_TRACE
_ls_popback(s->stack_frames); _ls_popback(s->stack_frames);
#endif /* MB_ENABLE_STACK_TRACE */ #endif /* MB_ENABLE_STACK_TRACE */
_mark_hanged_intermediate_value(s, running);
} }
if(result == MB_FUNC_IGNORE) { if(result == MB_FUNC_IGNORE) {
result = MB_FUNC_OK; result = MB_FUNC_OK;
@ -10517,6 +10582,7 @@ _retry:
case _DT_ROUTINE: case _DT_ROUTINE:
ast = ast->prev; ast = ast->prev;
result = _core_call(s, (void**)&ast); result = _core_call(s, (void**)&ast);
_mark_hanged_intermediate_value(s, running);
break; break;
#ifdef MB_ENABLE_SOURCE_TRACE #ifdef MB_ENABLE_SOURCE_TRACE
@ -14848,12 +14914,16 @@ static int _core_let(mb_interpreter_t* s, void** l) {
switch(var->data->type) { switch(var->data->type) {
case _DT_LIST: case _DT_LIST:
if(!_set_list(var->data->data.list, idx, 0, &val)) { if(!_set_list(var->data->data.list, idx, 0, &val)) {
safe_free(val);
_handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
} }
break; break;
case _DT_DICT: case _DT_DICT:
_set_dict(var->data->data.dict, &key, 0, 0, val); if(!_set_dict(var->data->data.dict, &key, 0, 0, val)) {
safe_free(val);
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}
break; break;
default: /* Do nothing */ default: /* Do nothing */
@ -17106,6 +17176,9 @@ static int _std_val(mb_interpreter_t* s, void** l) {
#endif /* MB_ENABLE_COLLECTION_LIB */ #endif /* MB_ENABLE_COLLECTION_LIB */
mb_value_t ret; mb_value_t ret;
mb_meta_status_e os = MB_MS_NONE; mb_meta_status_e os = MB_MS_NONE;
#ifdef MB_ENABLE_COLLECTION_LIB
_ls_node_t* ast = 0;
#endif /* MB_ENABLE_COLLECTION_LIB */
mb_assert(s && l); mb_assert(s && l);
@ -17114,6 +17187,12 @@ static int _std_val(mb_interpreter_t* s, void** l) {
mb_check(mb_attempt_open_bracket(s, l)); mb_check(mb_attempt_open_bracket(s, l));
#ifdef MB_ENABLE_COLLECTION_LIB
ast = (_ls_node_t*)*l;
if(ast && _IS_FUNC(ast->data, _coll_iterator)) {
_handle_error_on_obj(s, SE_RN_INVALID_ITERATOR_USAGE, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}
#endif /* MB_ENABLE_COLLECTION_LIB */
mb_check(mb_pop_value(s, l, &arg)); mb_check(mb_pop_value(s, l, &arg));
os = _try_overridden(s, l, &arg, _STD_ID_VAL, MB_MF_FUNC); os = _try_overridden(s, l, &arg, _STD_ID_VAL, MB_MF_FUNC);
if((os & MB_MS_DONE) == MB_MS_NONE) { if((os & MB_MS_DONE) == MB_MS_NONE) {
@ -17137,10 +17216,16 @@ static int _std_val(mb_interpreter_t* s, void** l) {
break; break;
#ifdef MB_ENABLE_COLLECTION_LIB #ifdef MB_ENABLE_COLLECTION_LIB
case MB_DT_LIST_IT:
_MAKE_NIL(&ocoi);
_public_value_to_internal_object(&arg, &ocoi);
_handle_error_on_obj(s, SE_RN_TYPE_NOT_MATCH, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
break;
case MB_DT_DICT_IT: case MB_DT_DICT_IT:
_MAKE_NIL(&ocoi); _MAKE_NIL(&ocoi);
_public_value_to_internal_object(&arg, &ocoi); _public_value_to_internal_object(&arg, &ocoi);
if(ocoi.data.dict_it && ocoi.data.dict_it->curr_node && ocoi.data.dict_it->curr_node->data) { if(ocoi.data.dict_it && ocoi.data.dict_it->curr_node && ocoi.data.dict_it->curr_node != _INVALID_DICT_IT && ocoi.data.dict_it->curr_node->data) {
_internal_object_to_public_value((_object_t*)ocoi.data.dict_it->curr_node->data, &ret); _internal_object_to_public_value((_object_t*)ocoi.data.dict_it->curr_node->data, &ret);
mb_check(mb_push_value(s, l, ret)); mb_check(mb_push_value(s, l, ret));
} else { } else {
@ -17401,7 +17486,9 @@ static int _std_set(mb_interpreter_t* s, void** l) {
mb_make_nil(val); mb_make_nil(val);
_mb_check_mark_exit(mb_pop_value(s, l, &key), result, _exit); _mb_check_mark_exit(mb_pop_value(s, l, &key), result, _exit);
_mb_check_mark_exit(mb_pop_value(s, l, &val), result, _exit); _mb_check_mark_exit(mb_pop_value(s, l, &val), result, _exit);
_set_dict(obj.data.dict, &key, &val, 0, 0); if(!_set_dict(obj.data.dict, &key, &val, 0, 0)) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}
} }
break; break;
@ -17747,11 +17834,15 @@ static int _coll_list(mb_interpreter_t* s, void** l) {
*l = ast; *l = ast;
} else { } else {
/* Push arguments */ /* Push arguments */
_push_list(coll, &arg, 0); if(!_push_list(coll, &arg, 0)) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _error, result);
}
while(mb_has_arg(s, l)) { while(mb_has_arg(s, l)) {
mb_make_nil(arg); mb_make_nil(arg);
_mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _error); _mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _error);
_push_list(coll, &arg, 0); if(!_push_list(coll, &arg, 0)) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _error, result);
}
} }
} }
} }
@ -17790,7 +17881,9 @@ static int _coll_dict(mb_interpreter_t* s, void** l) {
mb_make_nil(val); mb_make_nil(val);
_mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _error); _mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _error);
_mb_check_mark_exit(mb_pop_value(s, l, &val), result, _error); _mb_check_mark_exit(mb_pop_value(s, l, &val), result, _error);
_set_dict(coll, &arg, &val, 0, 0); if(!_set_dict(coll, &arg, &val, 0, 0)) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _error, result);
}
} }
_mb_check_mark_exit(mb_attempt_close_bracket(s, l), result, _error); _mb_check_mark_exit(mb_attempt_close_bracket(s, l), result, _error);
@ -17836,7 +17929,9 @@ static int _coll_push(mb_interpreter_t* s, void** l) {
while(mb_has_arg(s, l)) { while(mb_has_arg(s, l)) {
mb_make_nil(arg); mb_make_nil(arg);
_mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _exit); _mb_check_mark_exit(mb_pop_value(s, l, &arg), result, _exit);
_push_list(olst.data.list, &arg, 0); if(!_push_list(olst.data.list, &arg, 0)) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}
} }
} }
@ -17988,9 +18083,10 @@ static int _coll_insert(mb_interpreter_t* s, void** l) {
_public_value_to_internal_object(&coll, &olst); _public_value_to_internal_object(&coll, &olst);
if(!_insert_list(olst.data.list, idx, &arg, &oval)) { if(!_insert_list(olst.data.list, idx, &arg, &oval)) {
_destroy_object(oval, 0); if(oval)
_destroy_object(oval, 0);
_handle_error_on_obj(s, SE_RN_INDEX_OUT_OF_BOUND, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
} }
_mb_check_mark_exit(mb_push_value(s, l, coll), result, _exit); _mb_check_mark_exit(mb_push_value(s, l, coll), result, _exit);
@ -18430,6 +18526,7 @@ static int _coll_move_next(mb_interpreter_t* s, void** l) {
_object_t oit; _object_t oit;
mb_value_t ret; mb_value_t ret;
mb_meta_status_e os = MB_MS_NONE; mb_meta_status_e os = MB_MS_NONE;
_ls_node_t* ast = 0;
mb_assert(s && l); mb_assert(s && l);
@ -18438,6 +18535,10 @@ static int _coll_move_next(mb_interpreter_t* s, void** l) {
_mb_check_mark_exit(mb_attempt_open_bracket(s, l), result, _exit); _mb_check_mark_exit(mb_attempt_open_bracket(s, l), result, _exit);
ast = (_ls_node_t*)*l;
if(ast && _IS_FUNC(ast->data, _coll_iterator)) {
_handle_error_on_obj(s, SE_RN_INVALID_ITERATOR_USAGE, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);
}
_mb_check_mark_exit(mb_pop_value(s, l, &it), result, _exit); _mb_check_mark_exit(mb_pop_value(s, l, &it), result, _exit);
os = _try_overridden(s, l, &it, _COLL_ID_MOVE_NEXT, MB_MF_COLL); os = _try_overridden(s, l, &it, _COLL_ID_MOVE_NEXT, MB_MF_COLL);
if((os & MB_MS_DONE) == MB_MS_NONE) { if((os & MB_MS_DONE) == MB_MS_NONE) {
@ -18457,6 +18558,9 @@ static int _coll_move_next(mb_interpreter_t* s, void** l) {
break; break;
case MB_DT_DICT_IT: case MB_DT_DICT_IT:
_public_value_to_internal_object(&it, &oit); _public_value_to_internal_object(&it, &oit);
if(oit.data.dict_it && oit.data.dict_it->curr_node == _INVALID_DICT_IT && _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);
}
oit.data.dict_it = _move_dict_it_next(oit.data.dict_it); oit.data.dict_it = _move_dict_it_next(oit.data.dict_it);
if(_invalid_dict_it(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); _handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result);

View File

@ -471,6 +471,7 @@ typedef enum mb_error_e {
SE_RN_COLLECTION_OR_ITERATOR_EXPECTED, SE_RN_COLLECTION_OR_ITERATOR_EXPECTED,
SE_RN_ITERATOR_EXPECTED, SE_RN_ITERATOR_EXPECTED,
SE_RN_INVALID_ITERATOR, SE_RN_INVALID_ITERATOR,
SE_RN_INVALID_ITERATOR_USAGE,
SE_RN_ITERABLE_EXPECTED, SE_RN_ITERABLE_EXPECTED,
SE_RN_REFERENCED_USERTYPE_EXPECTED, SE_RN_REFERENCED_USERTYPE_EXPECTED,
SE_RN_REFERENCED_TYPE_EXPECTED, SE_RN_REFERENCED_TYPE_EXPECTED,