comparison src/eval.c @ 17964:6d4d3bce365d v8.1.1978

patch 8.1.1978: the eval.c file is too big Commit: https://github.com/vim/vim/commit/1e1d30048e722906a13665bd6c3c24c87eb2fe25 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Sep 4 14:41:14 2019 +0200 patch 8.1.1978: the eval.c file is too big Problem: The eval.c file is too big. Solution: Move filter() and map() to list.c.
author Bram Moolenaar <Bram@vim.org>
date Wed, 04 Sep 2019 14:45:04 +0200
parents 7f3283683d97
children 46f95606b9ec
comparison
equal deleted inserted replaced
17963:5de9b5831cd4 17964:6d4d3bce365d
7133 free_string_option(save_cpo); 7133 free_string_option(save_cpo);
7134 7134
7135 return ret; 7135 return ret;
7136 } 7136 }
7137 7137
7138 static int
7139 filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
7140 {
7141 typval_T rettv;
7142 typval_T argv[3];
7143 int retval = FAIL;
7144
7145 copy_tv(tv, get_vim_var_tv(VV_VAL));
7146 argv[0] = *get_vim_var_tv(VV_KEY);
7147 argv[1] = *get_vim_var_tv(VV_VAL);
7148 if (eval_expr_typval(expr, argv, 2, &rettv) == FAIL)
7149 goto theend;
7150 if (map)
7151 {
7152 /* map(): replace the list item value */
7153 clear_tv(tv);
7154 rettv.v_lock = 0;
7155 *tv = rettv;
7156 }
7157 else
7158 {
7159 int error = FALSE;
7160
7161 /* filter(): when expr is zero remove the item */
7162 *remp = (tv_get_number_chk(&rettv, &error) == 0);
7163 clear_tv(&rettv);
7164 /* On type error, nothing has been removed; return FAIL to stop the
7165 * loop. The error message was given by tv_get_number_chk(). */
7166 if (error)
7167 goto theend;
7168 }
7169 retval = OK;
7170 theend:
7171 clear_tv(get_vim_var_tv(VV_VAL));
7172 return retval;
7173 }
7174
7175 /*
7176 * Implementation of map() and filter().
7177 */
7178 void
7179 filter_map(typval_T *argvars, typval_T *rettv, int map)
7180 {
7181 typval_T *expr;
7182 listitem_T *li, *nli;
7183 list_T *l = NULL;
7184 dictitem_T *di;
7185 hashtab_T *ht;
7186 hashitem_T *hi;
7187 dict_T *d = NULL;
7188 blob_T *b = NULL;
7189 int rem;
7190 int todo;
7191 char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
7192 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
7193 : N_("filter() argument"));
7194 int save_did_emsg;
7195 int idx = 0;
7196
7197 if (argvars[0].v_type == VAR_BLOB)
7198 {
7199 if ((b = argvars[0].vval.v_blob) == NULL)
7200 return;
7201 }
7202 else if (argvars[0].v_type == VAR_LIST)
7203 {
7204 if ((l = argvars[0].vval.v_list) == NULL
7205 || (!map && var_check_lock(l->lv_lock, arg_errmsg, TRUE)))
7206 return;
7207 }
7208 else if (argvars[0].v_type == VAR_DICT)
7209 {
7210 if ((d = argvars[0].vval.v_dict) == NULL
7211 || (!map && var_check_lock(d->dv_lock, arg_errmsg, TRUE)))
7212 return;
7213 }
7214 else
7215 {
7216 semsg(_(e_listdictarg), ermsg);
7217 return;
7218 }
7219
7220 expr = &argvars[1];
7221 /* On type errors, the preceding call has already displayed an error
7222 * message. Avoid a misleading error message for an empty string that
7223 * was not passed as argument. */
7224 if (expr->v_type != VAR_UNKNOWN)
7225 {
7226 typval_T save_val;
7227 typval_T save_key;
7228
7229 prepare_vimvar(VV_VAL, &save_val);
7230 prepare_vimvar(VV_KEY, &save_key);
7231
7232 // We reset "did_emsg" to be able to detect whether an error
7233 // occurred during evaluation of the expression.
7234 save_did_emsg = did_emsg;
7235 did_emsg = FALSE;
7236
7237 if (argvars[0].v_type == VAR_DICT)
7238 {
7239 ht = &d->dv_hashtab;
7240 hash_lock(ht);
7241 todo = (int)ht->ht_used;
7242 for (hi = ht->ht_array; todo > 0; ++hi)
7243 {
7244 if (!HASHITEM_EMPTY(hi))
7245 {
7246 int r;
7247
7248 --todo;
7249 di = HI2DI(hi);
7250 if (map && (var_check_lock(di->di_tv.v_lock,
7251 arg_errmsg, TRUE)
7252 || var_check_ro(di->di_flags,
7253 arg_errmsg, TRUE)))
7254 break;
7255 set_vim_var_string(VV_KEY, di->di_key, -1);
7256 r = filter_map_one(&di->di_tv, expr, map, &rem);
7257 clear_tv(get_vim_var_tv(VV_KEY));
7258 if (r == FAIL || did_emsg)
7259 break;
7260 if (!map && rem)
7261 {
7262 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE)
7263 || var_check_ro(di->di_flags, arg_errmsg, TRUE))
7264 break;
7265 dictitem_remove(d, di);
7266 }
7267 }
7268 }
7269 hash_unlock(ht);
7270 }
7271 else if (argvars[0].v_type == VAR_BLOB)
7272 {
7273 int i;
7274 typval_T tv;
7275
7276 // set_vim_var_nr() doesn't set the type
7277 set_vim_var_type(VV_KEY, VAR_NUMBER);
7278
7279 for (i = 0; i < b->bv_ga.ga_len; i++)
7280 {
7281 tv.v_type = VAR_NUMBER;
7282 tv.vval.v_number = blob_get(b, i);
7283 set_vim_var_nr(VV_KEY, idx);
7284 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg)
7285 break;
7286 if (tv.v_type != VAR_NUMBER)
7287 {
7288 emsg(_(e_invalblob));
7289 break;
7290 }
7291 tv.v_type = VAR_NUMBER;
7292 blob_set(b, i, tv.vval.v_number);
7293 if (!map && rem)
7294 {
7295 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
7296
7297 mch_memmove(p + idx, p + i + 1,
7298 (size_t)b->bv_ga.ga_len - i - 1);
7299 --b->bv_ga.ga_len;
7300 --i;
7301 }
7302 }
7303 }
7304 else // argvars[0].v_type == VAR_LIST
7305 {
7306 // set_vim_var_nr() doesn't set the type
7307 set_vim_var_type(VV_KEY, VAR_NUMBER);
7308
7309 for (li = l->lv_first; li != NULL; li = nli)
7310 {
7311 if (map && var_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE))
7312 break;
7313 nli = li->li_next;
7314 set_vim_var_nr(VV_KEY, idx);
7315 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
7316 || did_emsg)
7317 break;
7318 if (!map && rem)
7319 listitem_remove(l, li);
7320 ++idx;
7321 }
7322 }
7323
7324 restore_vimvar(VV_KEY, &save_key);
7325 restore_vimvar(VV_VAL, &save_val);
7326
7327 did_emsg |= save_did_emsg;
7328 }
7329
7330 copy_tv(&argvars[0], rettv);
7331 }
7332
7333 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */ 7138 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */