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;