+added support to apply the FOR statement to an iterable referenced usertype.

This commit is contained in:
Wang Renxin 2017-07-04 15:05:55 +08:00
parent 283b7aa593
commit 3fd45e45fd
2 changed files with 75 additions and 3 deletions

View File

@ -1,5 +1,6 @@
Jul. 4 2017 Jul. 4 2017
Added function overriding support of the ITERATOR statement Added function overriding support of the ITERATOR statement
Added support to apply the FOR statement to an iterable referenced usertype
Jul. 3 2017 Jul. 3 2017
Fixed a disposing bug with non-referenced array Fixed a disposing bug with non-referenced array

View File

@ -10658,20 +10658,29 @@ _exit:
static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t* var_loop) { static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t* var_loop) {
int result = MB_FUNC_ERR; int result = MB_FUNC_ERR;
_ls_node_t* ast = 0; _ls_node_t* ast = 0;
_running_context_t* running = 0;
_object_t* old_val = 0; _object_t* old_val = 0;
_object_t range;
_ls_node_t* to_node = 0; _ls_node_t* to_node = 0;
_object_t range;
_object_t* range_ptr = 0; _object_t* range_ptr = 0;
_list_it_t* lit = 0; _list_it_t* lit = 0;
_dict_it_t* dit = 0; _dict_it_t* dit = 0;
_list_it_t* tlit = 0; _list_it_t* tlit = 0;
_dict_it_t* tdit = 0; _dict_it_t* tdit = 0;
mb_value_t ref_val;
mb_value_t ref_it;
#ifdef MB_ENABLE_USERTYPE_REF
mb_meta_status_e os = MB_MS_NONE;
#endif /* MB_ENABLE_USERTYPE_REF */
mb_assert(s && l && var_loop); mb_assert(s && l && var_loop);
running = s->running_context;
old_val = var_loop->data; old_val = var_loop->data;
range_ptr = ⦥ range_ptr = ⦥
_MAKE_NIL(range_ptr); _MAKE_NIL(range_ptr);
mb_make_nil(ref_val);
mb_make_nil(ref_it);
ast = *l; ast = *l;
ast = ast->next; ast = ast->next;
@ -10687,6 +10696,15 @@ static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t*
/* Create iterator */ /* Create iterator */
switch(range_ptr->type) { switch(range_ptr->type) {
#ifdef MB_ENABLE_USERTYPE_REF
case _DT_USERTYPE_REF:
_internal_object_to_public_value(range_ptr, &ref_val);
os = _try_overridden(s, l, &ref_val, _COLL_ID_ITERATOR, MB_MF_COLL);
if((os & MB_MS_DONE) != MB_MS_NONE && (os & MB_MS_RETURNED) != MB_MS_NONE)
_swap_public_value(&ref_it, &running->intermediate_value);
break;
#endif /* MB_ENABLE_USERTYPE_REF */
case _DT_LIST: case _DT_LIST:
tlit = lit = _create_list_it(range_ptr->data.list, true); tlit = lit = _create_list_it(range_ptr->data.list, true);
@ -10701,12 +10719,56 @@ static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_t*
break; break;
} }
to_node = ast; to_node = ast;
switch(range_ptr->type) { _REF_COLL(range_ptr) default: /* Do nothing */ break; } switch(range_ptr->type) { _REF_COLL(range_ptr) _REF_USERTYPE_REF(range_ptr) default: /* Do nothing */ break; }
_to: _to:
ast = to_node; ast = to_node;
/* Move next */ /* Move next */
#ifdef MB_ENABLE_USERTYPE_REF
if(ref_it.type != MB_DT_NIL) {
mb_value_t moved_next;
mb_value_t curr_val;
_object_t curr_obj;
mb_make_nil(moved_next);
mb_make_nil(curr_val);
_MAKE_NIL(&curr_obj);
/* Move next */
os = _try_overridden(s, l, &ref_it, _COLL_ID_MOVE_NEXT, MB_MF_COLL);
if((os & MB_MS_DONE) != MB_MS_NONE && (os & MB_MS_RETURNED) != MB_MS_NONE)
_swap_public_value(&moved_next, &running->intermediate_value);
if(moved_next.type == MB_DT_INT && moved_next.value.integer) {
/* Get current value */
os = _try_overridden(s, l, &ref_it, _STD_ID_GET, MB_MF_FUNC);
if((os & MB_MS_DONE) != MB_MS_NONE && (os & MB_MS_RETURNED) != MB_MS_NONE)
_swap_public_value(&curr_val, &running->intermediate_value);
/* Assign loop variable */
_public_value_to_internal_object(&curr_val, &curr_obj);
var_loop->data = &curr_obj;
/* Keep looping */
result = _common_keep_looping(s, &ast, var_loop);
_UNREF(&curr_obj)
if(result == MB_LOOP_BREAK) {
result = MB_FUNC_OK;
goto _exit;
} else if(result != MB_FUNC_OK || result == MB_SUB_RETURN) {
goto _exit;
}
goto _to;
} else {
/* End looping */
result = _common_end_looping(s, &ast);
goto _exit;
}
}
#endif /* MB_ENABLE_USERTYPE_REF */
if(lit) lit = _move_list_it_next(lit); if(lit) lit = _move_list_it_next(lit);
else if(dit) dit = _move_dict_it_next(dit); else if(dit) dit = _move_dict_it_next(dit);
if((lit && _invalid_list_it(lit)) || (dit && _invalid_dict_it(dit))) { if((lit && _invalid_list_it(lit)) || (dit && _invalid_dict_it(dit))) {
@ -10741,9 +10803,18 @@ _to:
} }
_exit: _exit:
#ifdef MB_ENABLE_USERTYPE_REF
if(ref_it.type != MB_DT_NIL) {
_object_t it_obj;
_MAKE_NIL(&it_obj);
_public_value_to_internal_object(&ref_it, &it_obj);
_UNREF(&it_obj)
}
#endif /* MB_ENABLE_USERTYPE_REF */
if(tlit) _destroy_list_it(tlit); if(tlit) _destroy_list_it(tlit);
else if(tdit) _destroy_dict_it(tdit); else if(tdit) _destroy_dict_it(tdit);
switch(range_ptr->type) { _UNREF_COLL(range_ptr) default: /* Do nothing */ break; } switch(range_ptr->type) { _UNREF_COLL(range_ptr) _UNREF_USERTYPE_REF(range_ptr) default: /* Do nothing */ break; }
*l = ast; *l = ast;