*fixed a memory leak with a hanged value.
*fixed some crash.
This commit is contained in:
parent
23e29abb45
commit
c3dfe71c9c
3
HISTORY
3
HISTORY
@ -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
|
||||||
|
|
||||||
|
158
core/my_basic.c
158
core/my_basic.c
@ -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);
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user