Mercurial > vim
comparison src/vim9compile.c @ 20203:5a397db2c1ed v8.2.0657
patch 8.2.0657: Vim9: no check if called variable is a FuncRef
Commit: https://github.com/vim/vim/commit/a0a9f43ab24928a0b01b6d91d084bf50a6dbefc2
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 28 21:29:34 2020 +0200
patch 8.2.0657: Vim9: no check if called variable is a FuncRef
Problem: Vim9: no check if called variable is a FuncRef.
Solution: Add a type check.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 28 Apr 2020 21:30:03 +0200 |
parents | 63cc54100ae4 |
children | 3c247d9cd6f9 |
comparison
equal
deleted
inserted
replaced
20202:c798c7387c39 | 20203:5a397db2c1ed |
---|---|
1325 return OK; | 1325 return OK; |
1326 } | 1326 } |
1327 | 1327 |
1328 /* | 1328 /* |
1329 * Generate an ISN_PCALL instruction. | 1329 * Generate an ISN_PCALL instruction. |
1330 */ | 1330 * "type" is the type of the FuncRef. |
1331 static int | 1331 */ |
1332 generate_PCALL(cctx_T *cctx, int argcount, int at_top) | 1332 static int |
1333 generate_PCALL( | |
1334 cctx_T *cctx, | |
1335 int argcount, | |
1336 char_u *name, | |
1337 type_T *type, | |
1338 int at_top) | |
1333 { | 1339 { |
1334 isn_T *isn; | 1340 isn_T *isn; |
1335 garray_T *stack = &cctx->ctx_type_stack; | 1341 garray_T *stack = &cctx->ctx_type_stack; |
1342 type_T *ret_type; | |
1336 | 1343 |
1337 RETURN_OK_IF_SKIP(cctx); | 1344 RETURN_OK_IF_SKIP(cctx); |
1345 | |
1346 if (type->tt_type == VAR_ANY) | |
1347 ret_type = &t_any; | |
1348 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL) | |
1349 ret_type = type->tt_member; | |
1350 else | |
1351 { | |
1352 semsg(_("E1085: Not a callable type: %s"), name); | |
1353 return FAIL; | |
1354 } | |
1338 | 1355 |
1339 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL) | 1356 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL) |
1340 return FAIL; | 1357 return FAIL; |
1341 isn->isn_arg.pfunc.cpf_top = at_top; | 1358 isn->isn_arg.pfunc.cpf_top = at_top; |
1342 isn->isn_arg.pfunc.cpf_argcount = argcount; | 1359 isn->isn_arg.pfunc.cpf_argcount = argcount; |
1343 | 1360 |
1344 stack->ga_len -= argcount; // drop the arguments | 1361 stack->ga_len -= argcount; // drop the arguments |
1345 | 1362 |
1346 // drop the funcref/partial, get back the return value | 1363 // drop the funcref/partial, get back the return value |
1347 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any; | 1364 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type; |
1348 | 1365 |
1349 // If partial is above the arguments it must be cleared and replaced with | 1366 // If partial is above the arguments it must be cleared and replaced with |
1350 // the return value. | 1367 // the return value. |
1351 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL) | 1368 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL) |
1352 return FAIL; | 1369 return FAIL; |
2463 // Not for g:Func(), we don't know if it is a variable or not. | 2480 // Not for g:Func(), we don't know if it is a variable or not. |
2464 p = namebuf; | 2481 p = namebuf; |
2465 if (STRNCMP(namebuf, "g:", 2) != 0 | 2482 if (STRNCMP(namebuf, "g:", 2) != 0 |
2466 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) | 2483 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) |
2467 { | 2484 { |
2468 res = generate_PCALL(cctx, argcount, FALSE); | 2485 garray_T *stack = &cctx->ctx_type_stack; |
2486 type_T *type; | |
2487 | |
2488 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
2489 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); | |
2469 goto theend; | 2490 goto theend; |
2470 } | 2491 } |
2471 | 2492 |
2472 // A global function may be defined only later. Need to figure out at | 2493 // A global function may be defined only later. Need to figure out at |
2473 // runtime. | 2494 // runtime. Also handles a FuncRef at runtime. |
2474 if (STRNCMP(namebuf, "g:", 2) == 0) | 2495 if (STRNCMP(namebuf, "g:", 2) == 0) |
2475 res = generate_UCALL(cctx, name, argcount); | 2496 res = generate_UCALL(cctx, name, argcount); |
2476 else | 2497 else |
2477 semsg(_(e_unknownfunc), namebuf); | 2498 semsg(_(e_unknownfunc), namebuf); |
2478 | 2499 |
3118 { | 3139 { |
3119 for (;;) | 3140 for (;;) |
3120 { | 3141 { |
3121 if (**arg == '(') | 3142 if (**arg == '(') |
3122 { | 3143 { |
3123 int argcount = 0; | 3144 garray_T *stack = &cctx->ctx_type_stack; |
3145 type_T *type; | |
3146 int argcount = 0; | |
3124 | 3147 |
3125 // funcref(arg) | 3148 // funcref(arg) |
3149 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
3150 | |
3126 *arg = skipwhite(*arg + 1); | 3151 *arg = skipwhite(*arg + 1); |
3127 if (compile_arguments(arg, cctx, &argcount) == FAIL) | 3152 if (compile_arguments(arg, cctx, &argcount) == FAIL) |
3128 return FAIL; | 3153 return FAIL; |
3129 if (generate_PCALL(cctx, argcount, TRUE) == FAIL) | 3154 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL) |
3130 return FAIL; | 3155 return FAIL; |
3131 } | 3156 } |
3132 else if (**arg == '-' && (*arg)[1] == '>') | 3157 else if (**arg == '-' && (*arg)[1] == '>') |
3133 { | 3158 { |
3134 char_u *p; | 3159 char_u *p; |