Mercurial > vim
comparison src/vim9compile.c @ 20279:49b50843e725 v8.2.0695
patch 8.2.0695: Vim9: cannot define a function inside a function
Commit: https://github.com/vim/vim/commit/04b12697838b232b8b17c553ccc74cf1f1bdb81c
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon May 4 23:24:44 2020 +0200
patch 8.2.0695: Vim9: cannot define a function inside a function
Problem: Vim9: cannot define a function inside a function.
Solution: Initial support for :def inside :def.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 04 May 2020 23:30:04 +0200 |
parents | 350bb78345ba |
children | ab8c8fd0f868 |
comparison
equal
deleted
inserted
replaced
20278:4148ba869078 | 20279:49b50843e725 |
---|---|
99 type_T *lv_type; | 99 type_T *lv_type; |
100 int lv_idx; // index of the variable on the stack | 100 int lv_idx; // index of the variable on the stack |
101 int lv_from_outer; // when TRUE using ctx_outer scope | 101 int lv_from_outer; // when TRUE using ctx_outer scope |
102 int lv_const; // when TRUE cannot be assigned to | 102 int lv_const; // when TRUE cannot be assigned to |
103 int lv_arg; // when TRUE this is an argument | 103 int lv_arg; // when TRUE this is an argument |
104 int lv_func_idx; // for nested function | |
104 } lvar_T; | 105 } lvar_T; |
105 | 106 |
106 /* | 107 /* |
107 * Context for compiling lines of Vim script. | 108 * Context for compiling lines of Vim script. |
108 * Stores info about the local variables and condition stack. | 109 * Stores info about the local variables and condition stack. |
2613 char_u fname_buf[FLEN_FIXED + 1]; | 2614 char_u fname_buf[FLEN_FIXED + 1]; |
2614 char_u *tofree = NULL; | 2615 char_u *tofree = NULL; |
2615 int error = FCERR_NONE; | 2616 int error = FCERR_NONE; |
2616 ufunc_T *ufunc; | 2617 ufunc_T *ufunc; |
2617 int res = FAIL; | 2618 int res = FAIL; |
2619 lvar_T *lvar; | |
2618 | 2620 |
2619 if (varlen >= sizeof(namebuf)) | 2621 if (varlen >= sizeof(namebuf)) |
2620 { | 2622 { |
2621 semsg(_("E1011: name too long: %s"), name); | 2623 semsg(_("E1011: name too long: %s"), name); |
2622 return FAIL; | 2624 return FAIL; |
2636 idx = find_internal_func(name); | 2638 idx = find_internal_func(name); |
2637 if (idx >= 0) | 2639 if (idx >= 0) |
2638 res = generate_BCALL(cctx, idx, argcount); | 2640 res = generate_BCALL(cctx, idx, argcount); |
2639 else | 2641 else |
2640 semsg(_(e_unknownfunc), namebuf); | 2642 semsg(_(e_unknownfunc), namebuf); |
2643 goto theend; | |
2644 } | |
2645 | |
2646 // Check if the name is a nested function. | |
2647 lvar = lookup_local(namebuf, varlen, cctx); | |
2648 if (lvar != NULL && lvar->lv_func_idx > 0) | |
2649 { | |
2650 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) | |
2651 + lvar->lv_func_idx; | |
2652 res = generate_CALL(cctx, dfunc->df_ufunc, argcount); | |
2641 goto theend; | 2653 goto theend; |
2642 } | 2654 } |
2643 | 2655 |
2644 // If we can find the function by name generate the right call. | 2656 // If we can find the function by name generate the right call. |
2645 ufunc = find_func(name, FALSE, cctx); | 2657 ufunc = find_func(name, FALSE, cctx); |
4047 // "return val | endif" is possible | 4059 // "return val | endif" is possible |
4048 return skipwhite(p); | 4060 return skipwhite(p); |
4049 } | 4061 } |
4050 | 4062 |
4051 /* | 4063 /* |
4064 * Get a line from the compilation context, compatible with exarg_T getline(). | |
4065 * Return a pointer to the line in allocated memory. | |
4066 * Return NULL for end-of-file or some error. | |
4067 */ | |
4068 static char_u * | |
4069 exarg_getline( | |
4070 int c UNUSED, | |
4071 void *cookie, | |
4072 int indent UNUSED, | |
4073 int do_concat UNUSED) | |
4074 { | |
4075 cctx_T *cctx = (cctx_T *)cookie; | |
4076 | |
4077 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len) | |
4078 { | |
4079 iemsg("Heredoc got to end"); | |
4080 return NULL; | |
4081 } | |
4082 ++cctx->ctx_lnum; | |
4083 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data) | |
4084 [cctx->ctx_lnum]); | |
4085 } | |
4086 | |
4087 /* | |
4088 * Compile a nested :def command. | |
4089 */ | |
4090 static char_u * | |
4091 compile_nested_function(exarg_T *eap, cctx_T *cctx) | |
4092 { | |
4093 char_u *name_start = eap->arg; | |
4094 char_u *name_end = to_name_end(eap->arg, FALSE); | |
4095 char_u *name = get_lambda_name(); | |
4096 lvar_T *lvar; | |
4097 ufunc_T *ufunc; | |
4098 | |
4099 eap->arg = name_end; | |
4100 eap->getline = exarg_getline; | |
4101 eap->cookie = cctx; | |
4102 eap->skip = cctx->ctx_skip == TRUE; | |
4103 eap->forceit = FALSE; | |
4104 ufunc = def_function(eap, name, cctx); | |
4105 | |
4106 if (ufunc == NULL) | |
4107 return NULL; | |
4108 | |
4109 // Define a local variable for the function, but change the index to -1 to | |
4110 // mark it as a function name. | |
4111 lvar = reserve_local(cctx, name_start, name_end - name_start, | |
4112 TRUE, &t_func_unknown); | |
4113 lvar->lv_idx = 0; | |
4114 ++cctx->ctx_locals_count; // doesn't count as a local variable | |
4115 lvar->lv_func_idx = ufunc->uf_dfunc_idx; | |
4116 | |
4117 // TODO: warning for trailing? | |
4118 return (char_u *)""; | |
4119 } | |
4120 | |
4121 /* | |
4052 * Return the length of an assignment operator, or zero if there isn't one. | 4122 * Return the length of an assignment operator, or zero if there isn't one. |
4053 */ | 4123 */ |
4054 int | 4124 int |
4055 assignment_len(char_u *p, int *heredoc) | 4125 assignment_len(char_u *p, int *heredoc) |
4056 { | 4126 { |
4074 static char *reserved[] = { | 4144 static char *reserved[] = { |
4075 "true", | 4145 "true", |
4076 "false", | 4146 "false", |
4077 NULL | 4147 NULL |
4078 }; | 4148 }; |
4079 | |
4080 /* | |
4081 * Get a line for "=<<". | |
4082 * Return a pointer to the line in allocated memory. | |
4083 * Return NULL for end-of-file or some error. | |
4084 */ | |
4085 static char_u * | |
4086 heredoc_getline( | |
4087 int c UNUSED, | |
4088 void *cookie, | |
4089 int indent UNUSED, | |
4090 int do_concat UNUSED) | |
4091 { | |
4092 cctx_T *cctx = (cctx_T *)cookie; | |
4093 | |
4094 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len) | |
4095 { | |
4096 iemsg("Heredoc got to end"); | |
4097 return NULL; | |
4098 } | |
4099 ++cctx->ctx_lnum; | |
4100 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data) | |
4101 [cctx->ctx_lnum]); | |
4102 } | |
4103 | 4149 |
4104 typedef enum { | 4150 typedef enum { |
4105 dest_local, | 4151 dest_local, |
4106 dest_option, | 4152 dest_option, |
4107 dest_env, | 4153 dest_env, |
4392 { | 4438 { |
4393 list_T *l; | 4439 list_T *l; |
4394 listitem_T *li; | 4440 listitem_T *li; |
4395 | 4441 |
4396 // [let] varname =<< [trim] {end} | 4442 // [let] varname =<< [trim] {end} |
4397 eap->getline = heredoc_getline; | 4443 eap->getline = exarg_getline; |
4398 eap->cookie = cctx; | 4444 eap->cookie = cctx; |
4399 l = heredoc_get(eap, op + 3, FALSE); | 4445 l = heredoc_get(eap, op + 3, FALSE); |
4400 | 4446 |
4401 // Push each line and the create the list. | 4447 // Push each line and the create the list. |
4402 FOR_ALL_LIST_ITEMS(l, li) | 4448 FOR_ALL_LIST_ITEMS(l, li) |
6297 } | 6343 } |
6298 | 6344 |
6299 switch (ea.cmdidx) | 6345 switch (ea.cmdidx) |
6300 { | 6346 { |
6301 case CMD_def: | 6347 case CMD_def: |
6348 ea.arg = p; | |
6349 line = compile_nested_function(&ea, &cctx); | |
6350 break; | |
6351 | |
6302 case CMD_function: | 6352 case CMD_function: |
6303 // TODO: Nested function | 6353 emsg(_("E1086: Cannot use :function inside :def")); |
6304 emsg("Nested function not implemented yet"); | |
6305 goto erret; | 6354 goto erret; |
6306 | 6355 |
6307 case CMD_return: | 6356 case CMD_return: |
6308 line = compile_return(p, set_return_type, &cctx); | 6357 line = compile_return(p, set_return_type, &cctx); |
6309 had_return = TRUE; | 6358 had_return = TRUE; |