Mercurial > vim
comparison src/userfunc.c @ 20397:c225be44692a v8.2.0753
patch 8.2.0753: Vim9: expressions are evaluated in the discovery phase
Commit: https://github.com/vim/vim/commit/32e351179eacfc84f64cd5029e221582d400bb38
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu May 14 22:41:15 2020 +0200
patch 8.2.0753: Vim9: expressions are evaluated in the discovery phase
Problem: Vim9: expressions are evaluated in the discovery phase.
Solution: Bail out if an expression is not a constant. Require a type for
declared constants.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 14 May 2020 22:45:04 +0200 |
parents | 4c317d8c1051 |
children | 5950284a517f |
comparison
equal
deleted
inserted
replaced
20396:89228c88b5c4 | 20397:c225be44692a |
---|---|
237 any_default = TRUE; | 237 any_default = TRUE; |
238 p = skipwhite(p) + 1; | 238 p = skipwhite(p) + 1; |
239 whitep = p; | 239 whitep = p; |
240 p = skipwhite(p); | 240 p = skipwhite(p); |
241 expr = p; | 241 expr = p; |
242 if (eval1(&p, &rettv, FALSE) != FAIL) | 242 if (eval1(&p, &rettv, 0) != FAIL) |
243 { | 243 { |
244 if (ga_grow(default_args, 1) == FAIL) | 244 if (ga_grow(default_args, 1) == FAIL) |
245 goto err_ret; | 245 goto err_ret; |
246 | 246 |
247 // trim trailing whitespace | 247 // trim trailing whitespace |
570 : funcexe->partial->pt_argc)) | 570 : funcexe->partial->pt_argc)) |
571 { | 571 { |
572 argp = skipwhite(argp + 1); // skip the '(' or ',' | 572 argp = skipwhite(argp + 1); // skip the '(' or ',' |
573 if (*argp == ')' || *argp == ',' || *argp == NUL) | 573 if (*argp == ')' || *argp == ',' || *argp == NUL) |
574 break; | 574 break; |
575 if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) | 575 if (eval1(&argp, &argvars[argcount], |
576 funcexe->evaluate ? EVAL_EVALUATE : 0) == FAIL) | |
576 { | 577 { |
577 ret = FAIL; | 578 ret = FAIL; |
578 break; | 579 break; |
579 } | 580 } |
580 ++argcount; | 581 ++argcount; |
1221 def_rettv.v_type = VAR_NUMBER; | 1222 def_rettv.v_type = VAR_NUMBER; |
1222 def_rettv.vval.v_number = -1; | 1223 def_rettv.vval.v_number = -1; |
1223 | 1224 |
1224 default_expr = ((char_u **)(fp->uf_def_args.ga_data)) | 1225 default_expr = ((char_u **)(fp->uf_def_args.ga_data)) |
1225 [ai + fp->uf_def_args.ga_len]; | 1226 [ai + fp->uf_def_args.ga_len]; |
1226 if (eval1(&default_expr, &def_rettv, TRUE) == FAIL) | 1227 if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL) |
1227 { | 1228 { |
1228 default_arg_err = 1; | 1229 default_arg_err = 1; |
1229 break; | 1230 break; |
1230 } | 1231 } |
1231 } | 1232 } |
1366 char_u *p = *(char_u **)fp->uf_lines.ga_data + 7; | 1367 char_u *p = *(char_u **)fp->uf_lines.ga_data + 7; |
1367 | 1368 |
1368 // A Lambda always has the command "return {expr}". It is much faster | 1369 // A Lambda always has the command "return {expr}". It is much faster |
1369 // to evaluate {expr} directly. | 1370 // to evaluate {expr} directly. |
1370 ++ex_nesting_level; | 1371 ++ex_nesting_level; |
1371 (void)eval1(&p, rettv, TRUE); | 1372 (void)eval1(&p, rettv, EVAL_EVALUATE); |
1372 --ex_nesting_level; | 1373 --ex_nesting_level; |
1373 } | 1374 } |
1374 else | 1375 else |
1375 // call do_cmdline() to execute the lines | 1376 // call do_cmdline() to execute the lines |
1376 do_cmdline(NULL, get_func_line, (void *)fc, | 1377 do_cmdline(NULL, get_func_line, (void *)fc, |
3621 if (eap->skip) | 3622 if (eap->skip) |
3622 ++emsg_skip; | 3623 ++emsg_skip; |
3623 | 3624 |
3624 eap->nextcmd = NULL; | 3625 eap->nextcmd = NULL; |
3625 if ((*arg != NUL && *arg != '|' && *arg != '\n') | 3626 if ((*arg != NUL && *arg != '|' && *arg != '\n') |
3626 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) | 3627 && eval0(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE) |
3628 != FAIL) | |
3627 { | 3629 { |
3628 if (!eap->skip) | 3630 if (!eap->skip) |
3629 returning = do_return(eap, FALSE, TRUE, &rettv); | 3631 returning = do_return(eap, FALSE, TRUE, &rettv); |
3630 else | 3632 else |
3631 clear_tv(&rettv); | 3633 clear_tv(&rettv); |
3678 { | 3680 { |
3679 // trans_function_name() doesn't work well when skipping, use eval0() | 3681 // trans_function_name() doesn't work well when skipping, use eval0() |
3680 // instead to skip to any following command, e.g. for: | 3682 // instead to skip to any following command, e.g. for: |
3681 // :if 0 | call dict.foo().bar() | endif | 3683 // :if 0 | call dict.foo().bar() | endif |
3682 ++emsg_skip; | 3684 ++emsg_skip; |
3683 if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL) | 3685 if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL) |
3684 clear_tv(&rettv); | 3686 clear_tv(&rettv); |
3685 --emsg_skip; | 3687 --emsg_skip; |
3686 return; | 3688 return; |
3687 } | 3689 } |
3688 | 3690 |
3766 } | 3768 } |
3767 if (has_watchexpr()) | 3769 if (has_watchexpr()) |
3768 dbg_check_breakpoint(eap); | 3770 dbg_check_breakpoint(eap); |
3769 | 3771 |
3770 // Handle a function returning a Funcref, Dictionary or List. | 3772 // Handle a function returning a Funcref, Dictionary or List. |
3771 if (handle_subscript(&arg, &rettv, !eap->skip, TRUE, | 3773 if (handle_subscript(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE, |
3772 name, &name) == FAIL) | 3774 TRUE, name, &name) == FAIL) |
3773 { | 3775 { |
3774 failed = TRUE; | 3776 failed = TRUE; |
3775 break; | 3777 break; |
3776 } | 3778 } |
3777 | 3779 |