comparison src/vim9compile.c @ 22975:a943b175586a v8.2.2034

patch 8.2.2034: Vim9: list unpack in for statement not compiled yet Commit: https://github.com/vim/vim/commit/792f786aad8409ca9ab895392742643a5b6aed8f Author: Bram Moolenaar <Bram@vim.org> Date: Mon Nov 23 08:31:18 2020 +0100 patch 8.2.2034: Vim9: list unpack in for statement not compiled yet Problem: Vim9: list unpack in for statement not compiled yet. Solution: Compile list unpack. (closes https://github.com/vim/vim/issues/7345)
author Bram Moolenaar <Bram@vim.org>
date Mon, 23 Nov 2020 08:45:04 +0100
parents 4c97c0747017
children b98003d73150
comparison
equal deleted inserted replaced
22974:3f8025537dd9 22975:a943b175586a
1883 isn_T *isn; 1883 isn_T *isn;
1884 1884
1885 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL) 1885 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1886 return FAIL; 1886 return FAIL;
1887 isn->isn_arg.number = count; 1887 isn->isn_arg.number = count;
1888 return OK;
1889 }
1890
1891 static int
1892 generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
1893 {
1894 isn_T *isn;
1895
1896 RETURN_OK_IF_SKIP(cctx);
1897 if ((isn = generate_instr(cctx, ISN_UNPACK)) == NULL)
1898 return FAIL;
1899 isn->isn_arg.unpack.unp_count = var_count;
1900 isn->isn_arg.unpack.unp_semicolon = semicolon;
1888 return OK; 1901 return OK;
1889 } 1902 }
1890 1903
1891 /* 1904 /*
1892 * Generate an instruction for any command modifiers. 1905 * Generate an instruction for any command modifiers.
6321 drop_scope(cctx); 6334 drop_scope(cctx);
6322 return arg; 6335 return arg;
6323 } 6336 }
6324 6337
6325 /* 6338 /*
6326 * compile "for var in expr" 6339 * Compile "for var in expr":
6327 * 6340 *
6328 * Produces instructions: 6341 * Produces instructions:
6329 * PUSHNR -1 6342 * PUSHNR -1
6330 * STORE loop-idx Set index to -1 6343 * STORE loop-idx Set index to -1
6331 * EVAL expr Push result of "expr" 6344 * EVAL expr result of "expr" on top of stack
6332 * top: FOR loop-idx, end Increment index, use list on bottom of stack 6345 * top: FOR loop-idx, end Increment index, use list on bottom of stack
6333 * - if beyond end, jump to "end" 6346 * - if beyond end, jump to "end"
6334 * - otherwise get item from list and push it 6347 * - otherwise get item from list and push it
6335 * STORE var Store item in "var" 6348 * STORE var Store item in "var"
6336 * ... body ... 6349 * ... body ...
6337 * JUMP top Jump back to repeat 6350 * JUMP top Jump back to repeat
6338 * end: DROP Drop the result of "expr" 6351 * end: DROP Drop the result of "expr"
6339 * 6352 *
6353 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
6354 * UNPACK 2 Split item in 2
6355 * STORE var1 Store item in "var1"
6356 * STORE var2 Store item in "var2"
6340 */ 6357 */
6341 static char_u * 6358 static char_u *
6342 compile_for(char_u *arg, cctx_T *cctx) 6359 compile_for(char_u *arg_start, cctx_T *cctx)
6343 { 6360 {
6361 char_u *arg;
6362 char_u *arg_end;
6344 char_u *p; 6363 char_u *p;
6364 int var_count = 0;
6365 int semicolon = FALSE;
6345 size_t varlen; 6366 size_t varlen;
6346 garray_T *instr = &cctx->ctx_instr; 6367 garray_T *instr = &cctx->ctx_instr;
6347 garray_T *stack = &cctx->ctx_type_stack; 6368 garray_T *stack = &cctx->ctx_type_stack;
6348 scope_T *scope; 6369 scope_T *scope;
6349 lvar_T *loop_lvar; // loop iteration variable 6370 lvar_T *loop_lvar; // loop iteration variable
6350 lvar_T *var_lvar; // variable for "var" 6371 lvar_T *var_lvar; // variable for "var"
6351 type_T *vartype; 6372 type_T *vartype;
6352 6373 type_T *item_type = &t_any;
6353 // TODO: list of variables: "for [key, value] in dict" 6374 int idx;
6354 // parse "var" 6375
6355 for (p = arg; eval_isnamec1(*p); ++p) 6376 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
6356 ; 6377 if (var_count == 0)
6357 varlen = p - arg; 6378 var_count = 1;
6358 var_lvar = lookup_local(arg, varlen, cctx);
6359 if (var_lvar != NULL)
6360 {
6361 semsg(_(e_variable_already_declared), arg);
6362 return NULL;
6363 }
6364 6379
6365 // consume "in" 6380 // consume "in"
6366 p = skipwhite(p); 6381 p = skipwhite(p);
6367 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2])) 6382 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
6368 { 6383 {
6369 emsg(_(e_missing_in)); 6384 emsg(_(e_missing_in));
6370 return NULL; 6385 return NULL;
6371 } 6386 }
6372 p = skipwhite(p + 2); 6387 p = skipwhite(p + 2);
6373 6388
6374
6375 scope = new_scope(cctx, FOR_SCOPE); 6389 scope = new_scope(cctx, FOR_SCOPE);
6376 if (scope == NULL) 6390 if (scope == NULL)
6377 return NULL; 6391 return NULL;
6378 6392
6379 // Reserve a variable to store the loop iteration counter. 6393 // Reserve a variable to store the loop iteration counter and initialize it
6394 // to -1.
6380 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number); 6395 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
6381 if (loop_lvar == NULL) 6396 if (loop_lvar == NULL)
6382 { 6397 {
6383 // out of memory 6398 // out of memory
6384 drop_scope(cctx); 6399 drop_scope(cctx);
6385 return NULL; 6400 return NULL;
6386 } 6401 }
6387
6388 // Reserve a variable to store "var"
6389 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
6390 if (var_lvar == NULL)
6391 {
6392 // out of memory or used as an argument
6393 drop_scope(cctx);
6394 return NULL;
6395 }
6396
6397 generate_STORENR(cctx, loop_lvar->lv_idx, -1); 6402 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
6398 6403
6399 // compile "expr", it remains on the stack until "endfor" 6404 // compile "expr", it remains on the stack until "endfor"
6400 arg = p; 6405 arg = p;
6401 if (compile_expr0(&arg, cctx) == FAIL) 6406 if (compile_expr0(&arg, cctx) == FAIL)
6402 { 6407 {
6403 drop_scope(cctx); 6408 drop_scope(cctx);
6404 return NULL; 6409 return NULL;
6405 } 6410 }
6411 arg_end = arg;
6406 6412
6407 // Now that we know the type of "var", check that it is a list, now or at 6413 // Now that we know the type of "var", check that it is a list, now or at
6408 // runtime. 6414 // runtime.
6409 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 6415 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6410 if (need_type(vartype, &t_list_any, -1, cctx, FALSE, FALSE) == FAIL) 6416 if (need_type(vartype, &t_list_any, -1, cctx, FALSE, FALSE) == FAIL)
6411 { 6417 {
6412 drop_scope(cctx); 6418 drop_scope(cctx);
6413 return NULL; 6419 return NULL;
6414 } 6420 }
6421
6415 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY) 6422 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
6416 var_lvar->lv_type = vartype->tt_member; 6423 {
6424 if (var_count == 1)
6425 item_type = vartype->tt_member;
6426 else if (vartype->tt_member->tt_type == VAR_LIST
6427 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
6428 item_type = vartype->tt_member->tt_member;
6429 }
6417 6430
6418 // "for_end" is set when ":endfor" is found 6431 // "for_end" is set when ":endfor" is found
6419 scope->se_u.se_for.fs_top_label = instr->ga_len; 6432 scope->se_u.se_for.fs_top_label = instr->ga_len;
6420
6421 generate_FOR(cctx, loop_lvar->lv_idx); 6433 generate_FOR(cctx, loop_lvar->lv_idx);
6422 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL); 6434
6423 6435 arg = arg_start;
6424 return arg; 6436 if (var_count > 1)
6437 {
6438 generate_UNPACK(cctx, var_count, semicolon);
6439 arg = skipwhite(arg + 1); // skip white after '['
6440
6441 // the list item is replaced by a number of items
6442 if (ga_grow(stack, var_count - 1) == FAIL)
6443 {
6444 drop_scope(cctx);
6445 return NULL;
6446 }
6447 --stack->ga_len;
6448 for (idx = 0; idx < var_count; ++idx)
6449 {
6450 ((type_T **)stack->ga_data)[stack->ga_len] =
6451 (semicolon && idx == 0) ? vartype : item_type;
6452 ++stack->ga_len;
6453 }
6454 }
6455
6456 for (idx = 0; idx < var_count; ++idx)
6457 {
6458 // TODO: use skip_var_one, also assign to @r, $VAR, etc.
6459 p = arg;
6460 while (eval_isnamec(*p))
6461 ++p;
6462 varlen = p - arg;
6463 var_lvar = lookup_local(arg, varlen, cctx);
6464 if (var_lvar != NULL)
6465 {
6466 semsg(_(e_variable_already_declared), arg);
6467 drop_scope(cctx);
6468 return NULL;
6469 }
6470
6471 // Reserve a variable to store "var".
6472 // TODO: check for type
6473 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
6474 if (var_lvar == NULL)
6475 {
6476 // out of memory or used as an argument
6477 drop_scope(cctx);
6478 return NULL;
6479 }
6480
6481 if (semicolon && idx == var_count - 1)
6482 var_lvar->lv_type = vartype;
6483 else
6484 var_lvar->lv_type = item_type;
6485 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
6486
6487 if (*p == ',' || *p == ';')
6488 ++p;
6489 arg = skipwhite(p);
6490 }
6491
6492 return arg_end;
6425 } 6493 }
6426 6494
6427 /* 6495 /*
6428 * compile "endfor" 6496 * compile "endfor"
6429 */ 6497 */
7955 case ISN_STOREV: 8023 case ISN_STOREV:
7956 case ISN_STRINDEX: 8024 case ISN_STRINDEX:
7957 case ISN_STRSLICE: 8025 case ISN_STRSLICE:
7958 case ISN_THROW: 8026 case ISN_THROW:
7959 case ISN_TRY: 8027 case ISN_TRY:
8028 case ISN_UNPACK:
7960 // nothing allocated 8029 // nothing allocated
7961 break; 8030 break;
7962 } 8031 }
7963 } 8032 }
7964 8033