Mercurial > vim
comparison src/vim9compile.c @ 23352:37118deff718 v8.2.2219
patch 8.2.2219: Vim9: method call with expression not supported
Commit: https://github.com/vim/vim/commit/7e3682068bebc53a5d1e9eaaba61bb4fa9c612da
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Dec 25 21:56:57 2020 +0100
patch 8.2.2219: Vim9: method call with expression not supported
Problem: Vim9: method call with expression not supported.
Solution: Implement expr->(expr)().
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 25 Dec 2020 22:00:04 +0100 |
parents | 2060f53b7c17 |
children | eb7d8f39363c |
comparison
equal
deleted
inserted
replaced
23351:ae0e6f75e315 | 23352:37118deff718 |
---|---|
2815 p = namebuf; | 2815 p = namebuf; |
2816 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload | 2816 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload |
2817 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK) | 2817 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK) |
2818 { | 2818 { |
2819 garray_T *stack = &cctx->ctx_type_stack; | 2819 garray_T *stack = &cctx->ctx_type_stack; |
2820 type_T *type; | 2820 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
2821 | 2821 |
2822 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
2823 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); | 2822 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); |
2824 goto theend; | 2823 goto theend; |
2825 } | 2824 } |
2826 | 2825 |
2827 // If we can find a global function by name generate the right call. | 2826 // If we can find a global function by name generate the right call. |
3428 } | 3427 } |
3429 return type; | 3428 return type; |
3430 } | 3429 } |
3431 | 3430 |
3432 /* | 3431 /* |
3432 * Skip over an expression, ignoring most errors. | |
3433 */ | |
3434 static void | |
3435 skip_expr_cctx(char_u **arg, cctx_T *cctx) | |
3436 { | |
3437 evalarg_T evalarg; | |
3438 | |
3439 CLEAR_FIELD(evalarg); | |
3440 evalarg.eval_cctx = cctx; | |
3441 skip_expr(arg, &evalarg); | |
3442 } | |
3443 | |
3444 /* | |
3433 * Compile code to apply '-', '+' and '!'. | 3445 * Compile code to apply '-', '+' and '!'. |
3434 * When "numeric_only" is TRUE do not apply '!'. | 3446 * When "numeric_only" is TRUE do not apply '!'. |
3435 */ | 3447 */ |
3436 static int | 3448 static int |
3437 compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end) | 3449 compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end) |
3486 *end = p; | 3498 *end = p; |
3487 return OK; | 3499 return OK; |
3488 } | 3500 } |
3489 | 3501 |
3490 /* | 3502 /* |
3503 * Compile "(expression)": recursive! | |
3504 * Return FAIL/OK. | |
3505 */ | |
3506 static int | |
3507 compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) | |
3508 { | |
3509 int ret; | |
3510 | |
3511 *arg = skipwhite(*arg + 1); | |
3512 if (ppconst->pp_used <= PPSIZE - 10) | |
3513 { | |
3514 ret = compile_expr1(arg, cctx, ppconst); | |
3515 } | |
3516 else | |
3517 { | |
3518 // Not enough space in ppconst, flush constants. | |
3519 if (generate_ppconst(cctx, ppconst) == FAIL) | |
3520 return FAIL; | |
3521 ret = compile_expr0(arg, cctx); | |
3522 } | |
3523 *arg = skipwhite(*arg); | |
3524 if (**arg == ')') | |
3525 ++*arg; | |
3526 else if (ret == OK) | |
3527 { | |
3528 emsg(_(e_missing_close)); | |
3529 ret = FAIL; | |
3530 } | |
3531 return ret; | |
3532 } | |
3533 | |
3534 /* | |
3491 * Compile whatever comes after "name" or "name()". | 3535 * Compile whatever comes after "name" or "name()". |
3492 * Advances "*arg" only when something was recognized. | 3536 * Advances "*arg" only when something was recognized. |
3493 */ | 3537 */ |
3494 static int | 3538 static int |
3495 compile_subscript( | 3539 compile_subscript( |
3570 if (compile_lambda_call(arg, cctx) == FAIL) | 3614 if (compile_lambda_call(arg, cctx) == FAIL) |
3571 return FAIL; | 3615 return FAIL; |
3572 } | 3616 } |
3573 else if (**arg == '(') | 3617 else if (**arg == '(') |
3574 { | 3618 { |
3575 // Funcref call: list->(Refs[2])() | 3619 int argcount = 1; |
3576 // or lambda: list->((arg) => expr)() | 3620 char_u *expr; |
3577 // TODO: make this work | 3621 garray_T *stack; |
3578 if (compile_lambda_call(arg, cctx) == FAIL) | 3622 type_T *type; |
3623 | |
3624 // Funcref call: list->(Refs[2])(arg) | |
3625 // or lambda: list->((arg) => expr)(arg) | |
3626 // Fist compile the arguments. | |
3627 expr = *arg; | |
3628 *arg = skipwhite(*arg + 1); | |
3629 skip_expr_cctx(arg, cctx); | |
3630 *arg = skipwhite(*arg); | |
3631 if (**arg != ')') | |
3632 { | |
3633 semsg(_(e_missing_paren), *arg); | |
3634 return FAIL; | |
3635 } | |
3636 ++*arg; | |
3637 if (**arg != '(') | |
3638 { | |
3639 semsg(_(e_missing_paren), *arg); | |
3640 return FAIL; | |
3641 } | |
3642 | |
3643 *arg = skipwhite(*arg + 1); | |
3644 if (compile_arguments(arg, cctx, &argcount) == FAIL) | |
3645 return FAIL; | |
3646 | |
3647 // Compile the function expression. | |
3648 if (compile_parenthesis(&expr, cctx, ppconst) == FAIL) | |
3649 return FAIL; | |
3650 | |
3651 stack = &cctx->ctx_type_stack; | |
3652 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
3653 if (generate_PCALL(cctx, argcount, | |
3654 (char_u *)"[expression]", type, FALSE) == FAIL) | |
3579 return FAIL; | 3655 return FAIL; |
3580 } | 3656 } |
3581 else | 3657 else |
3582 { | 3658 { |
3583 // method call: list->method() | 3659 // method call: list->method() |
3996 { | 4072 { |
3997 ret = compile_lambda(arg, cctx); | 4073 ret = compile_lambda(arg, cctx); |
3998 break; | 4074 break; |
3999 } | 4075 } |
4000 } | 4076 } |
4001 | 4077 ret = compile_parenthesis(arg, cctx, ppconst); |
4002 // (expression): recursive! | |
4003 *arg = skipwhite(*arg + 1); | |
4004 if (ppconst->pp_used <= PPSIZE - 10) | |
4005 { | |
4006 ret = compile_expr1(arg, cctx, ppconst); | |
4007 } | |
4008 else | |
4009 { | |
4010 // Not enough space in ppconst, flush constants. | |
4011 if (generate_ppconst(cctx, ppconst) == FAIL) | |
4012 return FAIL; | |
4013 ret = compile_expr0(arg, cctx); | |
4014 } | |
4015 *arg = skipwhite(*arg); | |
4016 if (**arg == ')') | |
4017 ++*arg; | |
4018 else if (ret == OK) | |
4019 { | |
4020 emsg(_(e_missing_close)); | |
4021 ret = FAIL; | |
4022 } | |
4023 } | 4078 } |
4024 break; | 4079 break; |
4025 | 4080 |
4026 default: ret = NOTDONE; | 4081 default: ret = NOTDONE; |
4027 break; | 4082 break; |
4595 * JUMP_AND_KEEP_IF_TRUE end jump if true | 4650 * JUMP_AND_KEEP_IF_TRUE end jump if true |
4596 * EVAL expr1 | 4651 * EVAL expr1 |
4597 * end: | 4652 * end: |
4598 */ | 4653 */ |
4599 static int | 4654 static int |
4600 compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) | 4655 compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) |
4601 { | 4656 { |
4602 char_u *p; | 4657 char_u *p; |
4603 int ppconst_used = ppconst->pp_used; | 4658 int ppconst_used = ppconst->pp_used; |
4604 char_u *next; | 4659 char_u *next; |
4605 | 4660 |
4606 // Ignore all kinds of errors when not producing code. | 4661 // Ignore all kinds of errors when not producing code. |
4607 if (cctx->ctx_skip == SKIP_YES) | 4662 if (cctx->ctx_skip == SKIP_YES) |
4608 { | 4663 { |
4609 evalarg_T evalarg; | 4664 skip_expr_cctx(arg, cctx); |
4610 | |
4611 CLEAR_FIELD(evalarg); | |
4612 evalarg.eval_cctx = cctx; | |
4613 skip_expr(arg, &evalarg); | |
4614 return OK; | 4665 return OK; |
4615 } | 4666 } |
4616 | 4667 |
4617 // Evaluate the first expression. | 4668 // Evaluate the first expression. |
4618 if (compile_expr2(arg, cctx, ppconst) == FAIL) | 4669 if (compile_expr2(arg, cctx, ppconst) == FAIL) |