+added lazy evaluation for ranged list.

This commit is contained in:
Wang Renxin 2016-01-23 17:22:16 +08:00
parent 3fcef23970
commit 296fda75f7
3 changed files with 93 additions and 21 deletions

View File

@ -1,3 +1,6 @@
Jan. 23 2016
Added lazy evaluation for ranged list
Jan. 22 2016
Added an IN keyword
Added support to loop on collections by using FOR-IN statement

View File

@ -376,23 +376,27 @@ typedef struct _array_t {
#ifdef MB_ENABLE_COLLECTION_LIB
typedef struct _list_t {
_ref_t ref;
_ls_node_t* list;
_lock_t lock;
_ls_node_t* list;
_ls_node_t* cached_node;
int cached_index;
unsigned int count;
int_t count;
int_t* range_begin;
} _list_t;
typedef struct _list_it_t {
_list_t* list;
bool_t locking;
_ls_node_t* curr;
union {
_ls_node_t* node;
int_t ranging;
} curr;
} _list_it_t;
typedef struct _dict_t {
_ref_t ref;
_ht_node_t* dict;
_lock_t lock;
_ht_node_t* dict;
} _dict_t;
typedef struct _dict_it_t {
@ -1445,6 +1449,7 @@ static bool_t _find_list(_list_t* coll, mb_value_t* val);
static void _clear_list(_list_t* coll);
static void _sort_list(_list_t* coll);
static void _invalidate_list_cache(_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 _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);
@ -5784,6 +5789,7 @@ _list_t* _create_list(mb_interpreter_t* s) {
void _destroy_list(_list_t* c) {
/* Destroy a list */
if(c->range_begin) { safe_free(c->range_begin); }
_ls_foreach(c->list, _destroy_object);
_ls_destroy(c->list);
_destroy_ref(&c->ref);
@ -5818,7 +5824,10 @@ _list_it_t* _create_list_it(_list_t* coll, bool_t lock) {
memset(result, 0, sizeof(_list_it_t));
result->list = coll;
result->locking = lock;
result->curr = coll->list;
if(coll->range_begin)
result->curr.ranging = *coll->range_begin - sgn(coll->count);
else
result->curr.node = coll->list;
if(lock)
_lock_ref_object(&coll->lock, &coll->ref, coll);
@ -5841,14 +5850,24 @@ _list_it_t* _move_list_it_next(_list_it_t* it) {
/* Move an iterator of a list to next step */
_list_it_t* result = 0;
if(!it || !it->list || !it->list->list || !it->curr)
if(!it || !it->list || !it->list->list || (!it->curr.node && !it->list->range_begin))
goto _exit;
if(it->list->lock)
it->curr = it->curr->next;
if(it->list->range_begin) {
if(it->list->lock)
it->curr.ranging += sgn(it->list->count);
if(it->curr)
result = it;
if(it->list->count > 0 && it->curr.ranging < *it->list->range_begin + it->list->count)
result = it;
else if(it->list->count < 0 && it->curr.ranging > *it->list->range_begin + it->list->count)
result = it;
} else {
if(it->list->lock)
it->curr.node = it->curr.node->next;
if(it->curr.node)
result = it;
}
_exit:
return result;
@ -5933,6 +5952,8 @@ void _push_list(_list_t* coll, mb_value_t* val, _object_t* oarg) {
/* Push a value to a list */
mb_assert(coll && (val || oarg));
_fill_ranged(coll);
if(val && !oarg)
_create_internal_object_from_public_value(val, &oarg);
_ls_pushback(coll->list, oarg);
@ -5948,6 +5969,8 @@ bool_t _pop_list(_list_t* coll, mb_value_t* val, mb_interpreter_t* s) {
mb_assert(coll && val && s);
_fill_ranged(coll);
oval = (_object_t*)_ls_popback(coll->list);
if(oval) {
_internal_object_to_public_value(oval, val);
@ -5974,6 +5997,8 @@ bool_t _insert_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval)
mb_assert(coll && val);
_fill_ranged(coll);
_create_internal_object_from_public_value(val, &oarg);
if(oval)
*oval = oarg;
@ -5996,6 +6021,8 @@ bool_t _set_list(_list_t* coll, int_t idx, mb_value_t* val, _object_t** oval) {
mb_assert(coll && (val || (oval && *oval)));
_fill_ranged(coll);
result = _node_at_list(coll, (int)idx);
if(result) {
if(result->data)
@ -6023,6 +6050,8 @@ bool_t _remove_at_list(_list_t* coll, int_t idx) {
mb_assert(coll);
_fill_ranged(coll);
node = _node_at_list(coll, (int)idx);
if(node) {
if(node->data) {
@ -6047,6 +6076,8 @@ _ls_node_t* _node_at_list(_list_t* coll, int index) {
mb_assert(coll);
_fill_ranged(coll);
/* TODO: Optimize me */
if(index >= 0 && index < (int)coll->count) {
if(coll->cached_node && !(index < coll->cached_index / 2)) {
@ -6083,6 +6114,8 @@ bool_t _at_list(_list_t* coll, int_t idx, mb_value_t* oval) {
mb_assert(coll && oval);
_fill_ranged(coll);
result = _node_at_list(coll, (int)idx);
if(oval && result && result->data)
_internal_object_to_public_value((_object_t*)result->data, oval);
@ -6097,6 +6130,8 @@ bool_t _find_list(_list_t* coll, mb_value_t* val) {
mb_assert(coll && val);
_fill_ranged(coll);
_create_internal_object_from_public_value(val, &oarg);
result = !!_ls_find(coll->list, oarg, (_ls_compare)_ht_cmp_object);
_destroy_object(oarg, 0);
@ -6108,6 +6143,8 @@ void _clear_list(_list_t* coll) {
/* Clear a list */
mb_assert(coll);
if(coll->range_begin) { safe_free(coll->range_begin); }
_ls_foreach(coll->list, _destroy_object);
_ls_clear(coll->list);
coll->count = 0;
@ -6134,6 +6171,32 @@ void _invalidate_list_cache(_list_t* coll) {
coll->cached_index = 0;
}
void _fill_ranged(_list_t* coll) {
/* Fill a ranged list with numbers */
_object_t* obj = 0;
mb_assert(coll);
if(coll->range_begin) {
mb_value_t arg;
int_t begin = *coll->range_begin;
int_t end = *coll->range_begin + coll->count;
int_t step = sgn(coll->count);
do {
mb_make_int(arg, begin);
_create_internal_object_from_public_value(&arg, &obj);
_ls_pushback(coll->list, obj);
begin += step;
} while(begin != end);
safe_free(coll->range_begin);
_write_on_ref_object(&coll->lock, &coll->ref, coll);
_invalidate_list_cache(coll);
}
}
void _set_dict(_dict_t* coll, mb_value_t* key, mb_value_t* val, _object_t* okey, _object_t* oval) {
/* Set an element to a dictionary with a key-value pair */
_ls_node_t* exist = 0;
@ -6265,6 +6328,8 @@ int _clone_to_list(void* data, void* extra, _list_t* coll) {
mb_assert(data && coll);
_fill_ranged(coll);
tgt = _create_object();
obj = (_object_t*)data;
_clone_object(coll->ref.s, obj, tgt);
@ -8806,10 +8871,14 @@ _to:
goto _exit;
} else {
/* Assign loop variable */
if(lit && lit->curr && lit->curr->data)
var_loop->data = (_object_t*)lit->curr->data;
else if(dit && dit->curr_node && dit->curr_node->extra)
if(lit && !lit->list->range_begin && lit->curr.node && lit->curr.node->data) {
var_loop->data = (_object_t*)lit->curr.node->data;
} else if(lit && lit->list->range_begin) {
var_loop->data->type = _DT_INT;
var_loop->data->data.integer = lit->curr.ranging;
} else if(dit && dit->curr_node && dit->curr_node->extra) {
var_loop->data = (_object_t*)dit->curr_node->extra;
}
/* Keep looping */
_common_keep_looping(s, &ast, var_loop);
@ -14013,8 +14082,10 @@ int _std_get(mb_interpreter_t* s, void** l) {
break;
case MB_DT_LIST_IT:
_public_value_to_internal_object(&coi, &ocoi);
if(ocoi.data.list_it && ocoi.data.list_it->curr && ocoi.data.list_it->curr->data) {
_internal_object_to_public_value((_object_t*)ocoi.data.list_it->curr->data, &ret);
if(ocoi.data.list_it && !ocoi.data.list_it->list->range_begin && ocoi.data.list_it->curr.node && ocoi.data.list_it->curr.node->data) {
_internal_object_to_public_value((_object_t*)ocoi.data.list_it->curr.node->data, &ret);
} else if(ocoi.data.list_it && ocoi.data.list_it->list->range_begin) {
mb_make_int(ret, ocoi.data.list_it->curr.ranging);
} else {
_handle_error_on_obj(s, SE_RN_INVALID_ITERATOR, s->source_file, TON(l), MB_FUNC_ERR, _exit, result);
}
@ -14301,12 +14372,10 @@ int _coll_list(mb_interpreter_t* s, void** l) {
ast = ast->next;
_mb_check_mark(mb_pop_int(s, (void**)&ast, &end), result, _error);
step = sgn(end - begin);
end += step;
do {
mb_make_int(arg, begin);
_push_list(coll, &arg, 0);
begin += step;
} while(begin != end);
coll->range_begin = (int_t*)mb_malloc(sizeof(int_t));
*coll->range_begin = begin;
coll->count = end - begin + step;
if(!coll->count) coll->count = 1;
*l = ast;
} else {
/* Push arguments */

Binary file not shown.