comparison src/list.c @ 20649:1fa0ace0ba65 v8.2.0878

patch 8.2.0878: no reduce() function Commit: https://github.com/vim/vim/commit/85629985b71035608a37ba3bde86968481490d46 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jun 1 18:39:20 2020 +0200 patch 8.2.0878: no reduce() function Problem: No reduce() function. Solution: Add a reduce() function. (closes https://github.com/vim/vim/issues/5481)
author Bram Moolenaar <Bram@vim.org>
date Mon, 01 Jun 2020 18:45:03 +0200
parents 09143ab0fbbd
children a1e6d9353736
comparison
equal deleted inserted replaced
20648:78db823f74d0 20649:1fa0ace0ba65
2303 rettv_list_set(rettv, l); 2303 rettv_list_set(rettv, l);
2304 l->lv_u.mat.lv_idx = l->lv_len - l->lv_u.mat.lv_idx - 1; 2304 l->lv_u.mat.lv_idx = l->lv_len - l->lv_u.mat.lv_idx - 1;
2305 } 2305 }
2306 } 2306 }
2307 2307
2308 /*
2309 * "reduce(list, { accumlator, element -> value } [, initial])" function
2310 */
2311 void
2312 f_reduce(typval_T *argvars, typval_T *rettv)
2313 {
2314 typval_T accum;
2315 char_u *func_name;
2316 partial_T *partial = NULL;
2317 funcexe_T funcexe;
2318 typval_T argv[3];
2319
2320 if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB)
2321 {
2322 emsg(_(e_listblobreq));
2323 return;
2324 }
2325
2326 if (argvars[1].v_type == VAR_FUNC)
2327 func_name = argvars[1].vval.v_string;
2328 else if (argvars[1].v_type == VAR_PARTIAL)
2329 {
2330 partial = argvars[1].vval.v_partial;
2331 func_name = partial_name(partial);
2332 }
2333 else
2334 func_name = tv_get_string(&argvars[1]);
2335 if (*func_name == NUL)
2336 return; // type error or empty name
2337
2338 vim_memset(&funcexe, 0, sizeof(funcexe));
2339 funcexe.evaluate = TRUE;
2340 funcexe.partial = partial;
2341
2342 if (argvars[0].v_type == VAR_LIST)
2343 {
2344 list_T *l = argvars[0].vval.v_list;
2345 listitem_T *li = NULL;
2346
2347 CHECK_LIST_MATERIALIZE(l);
2348 if (argvars[2].v_type == VAR_UNKNOWN)
2349 {
2350 if (l == NULL || l->lv_first == NULL)
2351 {
2352 semsg(_(e_reduceempty), "List");
2353 return;
2354 }
2355 accum = l->lv_first->li_tv;
2356 li = l->lv_first->li_next;
2357 }
2358 else
2359 {
2360 accum = argvars[2];
2361 if (l != NULL)
2362 li = l->lv_first;
2363 }
2364
2365 copy_tv(&accum, rettv);
2366 for ( ; li != NULL; li = li->li_next)
2367 {
2368 argv[0] = accum;
2369 argv[1] = li->li_tv;
2370 if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL)
2371 return;
2372 accum = *rettv;
2373 }
2374 }
2375 else
2376 {
2377 blob_T *b = argvars[0].vval.v_blob;
2378 int i;
2379
2380 if (argvars[2].v_type == VAR_UNKNOWN)
2381 {
2382 if (b == NULL || b->bv_ga.ga_len == 0)
2383 {
2384 semsg(_(e_reduceempty), "Blob");
2385 return;
2386 }
2387 accum.v_type = VAR_NUMBER;
2388 accum.vval.v_number = blob_get(b, 0);
2389 i = 1;
2390 }
2391 else
2392 {
2393 accum = argvars[2];
2394 i = 0;
2395 }
2396
2397 copy_tv(&accum, rettv);
2398 if (b != NULL)
2399 {
2400 for ( ; i < b->bv_ga.ga_len; i++)
2401 {
2402 argv[0] = accum;
2403 argv[1].v_type = VAR_NUMBER;
2404 argv[1].vval.v_number = blob_get(b, i);
2405 if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL)
2406 return;
2407 accum = *rettv;
2408 }
2409 }
2410 }
2411 }
2412
2308 #endif // defined(FEAT_EVAL) 2413 #endif // defined(FEAT_EVAL)