Mercurial > vim
comparison src/eval.c @ 9686:8c2553beff0f v7.4.2119
commit https://github.com/vim/vim/commit/1e96d9bf98f9ab84d5af7f98d6a961d91b17364f
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jul 29 22:15:09 2016 +0200
patch 7.4.2119
Problem: Closures are not supported.
Solution: Capture variables in lambdas from the outer scope. (Yasuhiro
Matsumoto, Ken Takata)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 29 Jul 2016 22:30:08 +0200 |
parents | fd9727ae3c49 |
children | 2ea935bdd1a1 |
comparison
equal
deleted
inserted
replaced
9685:fee40b9f4989 | 9686:8c2553beff0f |
---|---|
235 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); | 235 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); |
236 | 236 |
237 | 237 |
238 static int get_env_len(char_u **arg); | 238 static int get_env_len(char_u **arg); |
239 static char_u * make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end); | 239 static char_u * make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end); |
240 static void check_vars(char_u *name, int len); | |
240 static typval_T *alloc_string_tv(char_u *string); | 241 static typval_T *alloc_string_tv(char_u *string); |
241 static hashtab_T *find_var_ht(char_u *name, char_u **varname); | |
242 static void delete_var(hashtab_T *ht, hashitem_T *hi); | 242 static void delete_var(hashtab_T *ht, hashitem_T *hi); |
243 static void list_one_var(dictitem_T *v, char_u *prefix, int *first); | 243 static void list_one_var(dictitem_T *v, char_u *prefix, int *first); |
244 static void list_one_var_a(char_u *prefix, char_u *name, int type, char_u *string, int *first); | 244 static void list_one_var_a(char_u *prefix, char_u *name, int type, char_u *string, int *first); |
245 static char_u *find_option_end(char_u **arg, int *opt_flags); | 245 static char_u *find_option_end(char_u **arg, int *opt_flags); |
246 | 246 |
4330 { | 4330 { |
4331 if (**arg == '(') /* recursive! */ | 4331 if (**arg == '(') /* recursive! */ |
4332 { | 4332 { |
4333 partial_T *partial; | 4333 partial_T *partial; |
4334 | 4334 |
4335 if (!evaluate) | |
4336 check_vars(s, len); | |
4337 | |
4335 /* If "s" is the name of a variable of type VAR_FUNC | 4338 /* If "s" is the name of a variable of type VAR_FUNC |
4336 * use its contents. */ | 4339 * use its contents. */ |
4337 s = deref_func_name(s, &len, &partial, !evaluate); | 4340 s = deref_func_name(s, &len, &partial, !evaluate); |
4338 | 4341 |
4339 /* Invoke the function. */ | 4342 /* Invoke the function. */ |
4361 } | 4364 } |
4362 } | 4365 } |
4363 else if (evaluate) | 4366 else if (evaluate) |
4364 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE); | 4367 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE); |
4365 else | 4368 else |
4369 { | |
4370 check_vars(s, len); | |
4366 ret = OK; | 4371 ret = OK; |
4372 } | |
4367 } | 4373 } |
4368 vim_free(alias); | 4374 vim_free(alias); |
4369 } | 4375 } |
4370 | 4376 |
4371 *arg = skipwhite(*arg); | 4377 *arg = skipwhite(*arg); |
5538 *list_stack = newitem; | 5544 *list_stack = newitem; |
5539 } | 5545 } |
5540 } | 5546 } |
5541 } | 5547 } |
5542 } | 5548 } |
5549 else if (tv->v_type == VAR_FUNC) | |
5550 { | |
5551 abort = set_ref_in_func(tv->vval.v_string, copyID); | |
5552 } | |
5543 else if (tv->v_type == VAR_PARTIAL) | 5553 else if (tv->v_type == VAR_PARTIAL) |
5544 { | 5554 { |
5545 partial_T *pt = tv->vval.v_partial; | 5555 partial_T *pt = tv->vval.v_partial; |
5546 int i; | 5556 int i; |
5547 | 5557 |
5548 /* A partial does not have a copyID, because it cannot contain itself. | 5558 /* A partial does not have a copyID, because it cannot contain itself. |
5549 */ | 5559 */ |
5550 if (pt != NULL) | 5560 if (pt != NULL) |
5551 { | 5561 { |
5562 abort = set_ref_in_func(pt->pt_name, copyID); | |
5563 | |
5552 if (pt->pt_dict != NULL) | 5564 if (pt->pt_dict != NULL) |
5553 { | 5565 { |
5554 typval_T dtv; | 5566 typval_T dtv; |
5555 | 5567 |
5556 dtv.v_type = VAR_DICT; | 5568 dtv.v_type = VAR_DICT; |
6786 copy_tv(tv, rettv); | 6798 copy_tv(tv, rettv); |
6787 | 6799 |
6788 name[len] = cc; | 6800 name[len] = cc; |
6789 | 6801 |
6790 return ret; | 6802 return ret; |
6803 } | |
6804 | |
6805 /* | |
6806 * Check if variable "name[len]" is a local variable or an argument. | |
6807 * If so, "*eval_lavars_used" is set to TRUE. | |
6808 */ | |
6809 static void | |
6810 check_vars(char_u *name, int len) | |
6811 { | |
6812 int cc; | |
6813 char_u *varname; | |
6814 hashtab_T *ht; | |
6815 | |
6816 if (eval_lavars_used == NULL) | |
6817 return; | |
6818 | |
6819 /* truncate the name, so that we can use strcmp() */ | |
6820 cc = name[len]; | |
6821 name[len] = NUL; | |
6822 | |
6823 ht = find_var_ht(name, &varname); | |
6824 if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) | |
6825 { | |
6826 if (find_var(name, NULL, TRUE) != NULL) | |
6827 *eval_lavars_used = TRUE; | |
6828 } | |
6829 | |
6830 name[len] = cc; | |
6791 } | 6831 } |
6792 | 6832 |
6793 /* | 6833 /* |
6794 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. | 6834 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. |
6795 * Also handle function call with Funcref variable: func(expr) | 6835 * Also handle function call with Funcref variable: func(expr) |
7272 dictitem_T * | 7312 dictitem_T * |
7273 find_var(char_u *name, hashtab_T **htp, int no_autoload) | 7313 find_var(char_u *name, hashtab_T **htp, int no_autoload) |
7274 { | 7314 { |
7275 char_u *varname; | 7315 char_u *varname; |
7276 hashtab_T *ht; | 7316 hashtab_T *ht; |
7317 dictitem_T *ret = NULL; | |
7277 | 7318 |
7278 ht = find_var_ht(name, &varname); | 7319 ht = find_var_ht(name, &varname); |
7279 if (htp != NULL) | 7320 if (htp != NULL) |
7280 *htp = ht; | 7321 *htp = ht; |
7281 if (ht == NULL) | 7322 if (ht == NULL) |
7282 return NULL; | 7323 return NULL; |
7283 return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); | 7324 ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); |
7325 if (ret != NULL) | |
7326 return ret; | |
7327 | |
7328 /* Search in parent scope for lambda */ | |
7329 return find_var_in_scoped_ht(name, varname ? &varname : NULL, | |
7330 no_autoload || htp != NULL); | |
7284 } | 7331 } |
7285 | 7332 |
7286 /* | 7333 /* |
7287 * Find variable "varname" in hashtab "ht" with name "htname". | 7334 * Find variable "varname" in hashtab "ht" with name "htname". |
7288 * Returns NULL if not found. | 7335 * Returns NULL if not found. |
7339 /* | 7386 /* |
7340 * Find the hashtab used for a variable name. | 7387 * Find the hashtab used for a variable name. |
7341 * Return NULL if the name is not valid. | 7388 * Return NULL if the name is not valid. |
7342 * Set "varname" to the start of name without ':'. | 7389 * Set "varname" to the start of name without ':'. |
7343 */ | 7390 */ |
7344 static hashtab_T * | 7391 hashtab_T * |
7345 find_var_ht(char_u *name, char_u **varname) | 7392 find_var_ht(char_u *name, char_u **varname) |
7346 { | 7393 { |
7347 hashitem_T *hi; | 7394 hashitem_T *hi; |
7348 hashtab_T *ht; | 7395 hashtab_T *ht; |
7349 | 7396 |
7614 { | 7661 { |
7615 EMSG2(_(e_illvar), name); | 7662 EMSG2(_(e_illvar), name); |
7616 return; | 7663 return; |
7617 } | 7664 } |
7618 v = find_var_in_ht(ht, 0, varname, TRUE); | 7665 v = find_var_in_ht(ht, 0, varname, TRUE); |
7666 | |
7667 /* Search in parent scope which is possible to reference from lambda */ | |
7668 if (v == NULL) | |
7669 v = find_var_in_scoped_ht(name, varname ? &varname : NULL, TRUE); | |
7619 | 7670 |
7620 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) | 7671 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) |
7621 && var_check_func_name(name, v == NULL)) | 7672 && var_check_func_name(name, v == NULL)) |
7622 return; | 7673 return; |
7623 | 7674 |