Mercurial > vim
comparison src/list.c @ 23037:4ba6c5eebb28 v8.2.2065
patch 8.2.2065: using map() and filter() on a range() is inefficient
Commit: https://github.com/vim/vim/commit/f8ca03bf9161ab9ee1a29db1d13c02b317c10029
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 28 20:32:29 2020 +0100
patch 8.2.2065: using map() and filter() on a range() is inefficient
Problem: Using map() and filter() on a range() is inefficient.
Solution: Do not materialize the range. (closes https://github.com/vim/vim/issues/7388)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 28 Nov 2020 20:45:04 +0100 |
parents | 6426acc72539 |
children | 77f181975381 |
comparison
equal
deleted
inserted
replaced
23036:58487aedb0c3 | 23037:4ba6c5eebb28 |
---|---|
2171 l_ret = rettv->vval.v_list; | 2171 l_ret = rettv->vval.v_list; |
2172 } | 2172 } |
2173 // set_vim_var_nr() doesn't set the type | 2173 // set_vim_var_nr() doesn't set the type |
2174 set_vim_var_type(VV_KEY, VAR_NUMBER); | 2174 set_vim_var_type(VV_KEY, VAR_NUMBER); |
2175 | 2175 |
2176 CHECK_LIST_MATERIALIZE(l); | |
2177 if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0) | 2176 if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0) |
2178 l->lv_lock = VAR_LOCKED; | 2177 l->lv_lock = VAR_LOCKED; |
2179 for (li = l->lv_first; li != NULL; li = nli) | 2178 |
2180 { | 2179 if (l->lv_first == &range_list_item) |
2181 typval_T newtv; | 2180 { |
2182 | 2181 varnumber_T val = l->lv_u.nonmat.lv_start; |
2183 if (filtermap != FILTERMAP_FILTER | 2182 int len = l->lv_len; |
2184 && value_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) | 2183 int stride = l->lv_u.nonmat.lv_stride; |
2185 break; | 2184 |
2186 nli = li->li_next; | 2185 // List from range(): loop over the numbers |
2187 set_vim_var_nr(VV_KEY, idx); | 2186 l->lv_first = NULL; |
2188 if (filter_map_one(&li->li_tv, expr, filtermap, | 2187 l->lv_u.mat.lv_last = NULL; |
2189 &newtv, &rem) == FAIL) | 2188 l->lv_len = 0; |
2190 break; | 2189 l->lv_u.mat.lv_idx_item = NULL; |
2191 if (did_emsg) | 2190 |
2191 for (idx = 0; idx < len; ++idx) | |
2192 { | 2192 { |
2193 clear_tv(&newtv); | 2193 typval_T tv; |
2194 break; | 2194 typval_T newtv; |
2195 | |
2196 tv.v_type = VAR_NUMBER; | |
2197 tv.v_lock = 0; | |
2198 tv.vval.v_number = val; | |
2199 set_vim_var_nr(VV_KEY, idx); | |
2200 if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) | |
2201 == FAIL) | |
2202 break; | |
2203 if (did_emsg) | |
2204 { | |
2205 clear_tv(&newtv); | |
2206 break; | |
2207 } | |
2208 if (filtermap != FILTERMAP_FILTER) | |
2209 { | |
2210 // map(), mapnew(): always append the new value to the | |
2211 // list | |
2212 if (list_append_tv_move(filtermap == FILTERMAP_MAP | |
2213 ? l : l_ret, &newtv) == FAIL) | |
2214 break; | |
2215 } | |
2216 else if (!rem) | |
2217 { | |
2218 // filter(): append the list item value when not rem | |
2219 if (list_append_tv_move(l, &tv) == FAIL) | |
2220 break; | |
2221 } | |
2222 | |
2223 val += stride; | |
2195 } | 2224 } |
2196 if (filtermap == FILTERMAP_MAP) | 2225 } |
2226 else | |
2227 { | |
2228 // Materialized list from range(): loop over the items | |
2229 for (li = l->lv_first; li != NULL; li = nli) | |
2197 { | 2230 { |
2198 // map(): replace the list item value | 2231 typval_T newtv; |
2199 clear_tv(&li->li_tv); | 2232 |
2200 newtv.v_lock = 0; | 2233 if (filtermap != FILTERMAP_FILTER && value_check_lock( |
2201 li->li_tv = newtv; | 2234 li->li_tv.v_lock, arg_errmsg, TRUE)) |
2235 break; | |
2236 nli = li->li_next; | |
2237 set_vim_var_nr(VV_KEY, idx); | |
2238 if (filter_map_one(&li->li_tv, expr, filtermap, | |
2239 &newtv, &rem) == FAIL) | |
2240 break; | |
2241 if (did_emsg) | |
2242 { | |
2243 clear_tv(&newtv); | |
2244 break; | |
2245 } | |
2246 if (filtermap == FILTERMAP_MAP) | |
2247 { | |
2248 // map(): replace the list item value | |
2249 clear_tv(&li->li_tv); | |
2250 newtv.v_lock = 0; | |
2251 li->li_tv = newtv; | |
2252 } | |
2253 else if (filtermap == FILTERMAP_MAPNEW) | |
2254 { | |
2255 // mapnew(): append the list item value | |
2256 if (list_append_tv_move(l_ret, &newtv) == FAIL) | |
2257 break; | |
2258 } | |
2259 else if (filtermap == FILTERMAP_FILTER && rem) | |
2260 listitem_remove(l, li); | |
2261 ++idx; | |
2202 } | 2262 } |
2203 else if (filtermap == FILTERMAP_MAPNEW) | 2263 } |
2204 { | 2264 |
2205 // mapnew(): append the list item value | |
2206 if (list_append_tv_move(l_ret, &newtv) == FAIL) | |
2207 break; | |
2208 } | |
2209 else if (filtermap == FILTERMAP_FILTER && rem) | |
2210 listitem_remove(l, li); | |
2211 ++idx; | |
2212 } | |
2213 l->lv_lock = prev_lock; | 2265 l->lv_lock = prev_lock; |
2214 } | 2266 } |
2215 | 2267 |
2216 restore_vimvar(VV_KEY, &save_key); | 2268 restore_vimvar(VV_KEY, &save_key); |
2217 restore_vimvar(VV_VAL, &save_val); | 2269 restore_vimvar(VV_VAL, &save_val); |