Mercurial > vim
comparison src/vim9compile.c @ 22631:59cd5f8b2ab2 v8.2.1864
patch 8.2.1864: Vim9: no error for wrong list type
Commit: https://github.com/vim/vim/commit/334a8b4bde55e1095533f70616ac1e6ec337c62c
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Oct 19 16:07:42 2020 +0200
patch 8.2.1864: Vim9: no error for wrong list type
Problem: Vim9: no error for wrong list type.
Solution: Add flag to indicate a constant. (closes https://github.com/vim/vim/issues/7160)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 19 Oct 2020 16:15:04 +0200 |
parents | 1064b9f05b0a |
children | 6589dae9696c |
comparison
equal
deleted
inserted
replaced
22630:b484b36ca2ef | 22631:59cd5f8b2ab2 |
---|---|
813 | 813 |
814 return OK; | 814 return OK; |
815 } | 815 } |
816 | 816 |
817 /* | 817 /* |
818 * Return TRUE if "actual" could be "expected" and a runtime typecheck is to be | |
819 * used. Return FALSE if the types will never match. | |
820 */ | |
821 static int | |
822 use_typecheck(type_T *actual, type_T *expected) | |
823 { | |
824 if (actual->tt_type == VAR_ANY | |
825 || actual->tt_type == VAR_UNKNOWN | |
826 || (actual->tt_type == VAR_FUNC | |
827 && (expected->tt_type == VAR_FUNC | |
828 || expected->tt_type == VAR_PARTIAL) | |
829 && (actual->tt_member == &t_any || actual->tt_argcount < 0))) | |
830 return TRUE; | |
831 if ((actual->tt_type == VAR_LIST || actual->tt_type == VAR_DICT) | |
832 && actual->tt_type == expected->tt_type) | |
833 // This takes care of a nested list or dict. | |
834 return use_typecheck(actual->tt_member, expected->tt_member); | |
835 return FALSE; | |
836 } | |
837 | |
838 /* | |
818 * Check that | 839 * Check that |
819 * - "actual" matches "expected" type or | 840 * - "actual" matches "expected" type or |
820 * - "actual" is a type that can be "expected" type: add a runtime check; or | 841 * - "actual" is a type that can be "expected" type: add a runtime check; or |
821 * - return FAIL. | 842 * - return FAIL. |
843 * If "actual_is_const" is TRUE then the type won't change at runtime, do not | |
844 * generate a TYPECHECK. | |
822 */ | 845 */ |
823 static int | 846 static int |
824 need_type( | 847 need_type( |
825 type_T *actual, | 848 type_T *actual, |
826 type_T *expected, | 849 type_T *expected, |
827 int offset, | 850 int offset, |
828 cctx_T *cctx, | 851 cctx_T *cctx, |
829 int silent) | 852 int silent, |
853 int actual_is_const) | |
830 { | 854 { |
831 if (expected == &t_bool && actual != &t_bool | 855 if (expected == &t_bool && actual != &t_bool |
832 && (actual->tt_flags & TTFLAG_BOOL_OK)) | 856 && (actual->tt_flags & TTFLAG_BOOL_OK)) |
833 { | 857 { |
834 // Using "0", "1" or the result of an expression with "&&" or "||" as a | 858 // Using "0", "1" or the result of an expression with "&&" or "||" as a |
839 | 863 |
840 if (check_type(expected, actual, FALSE, 0) == OK) | 864 if (check_type(expected, actual, FALSE, 0) == OK) |
841 return OK; | 865 return OK; |
842 | 866 |
843 // If the actual type can be the expected type add a runtime check. | 867 // If the actual type can be the expected type add a runtime check. |
844 // TODO: if it's a constant a runtime check makes no sense. | 868 // If it's a constant a runtime check makes no sense. |
845 if (actual->tt_type == VAR_ANY | 869 if (!actual_is_const && use_typecheck(actual, expected)) |
846 || actual->tt_type == VAR_UNKNOWN | |
847 || (actual->tt_type == VAR_FUNC | |
848 && (expected->tt_type == VAR_FUNC | |
849 || expected->tt_type == VAR_PARTIAL) | |
850 && (actual->tt_member == &t_any || actual->tt_argcount < 0)) | |
851 || (actual->tt_type == VAR_LIST | |
852 && expected->tt_type == VAR_LIST | |
853 && actual->tt_member == &t_any) | |
854 || (actual->tt_type == VAR_DICT | |
855 && expected->tt_type == VAR_DICT | |
856 && actual->tt_member == &t_any)) | |
857 { | 870 { |
858 generate_TYPECHECK(cctx, expected, offset); | 871 generate_TYPECHECK(cctx, expected, offset); |
859 return OK; | 872 return OK; |
860 } | 873 } |
861 | 874 |
1524 // possibly a lambda or "...: any" | 1537 // possibly a lambda or "...: any" |
1525 expected = &t_any; | 1538 expected = &t_any; |
1526 else | 1539 else |
1527 expected = ufunc->uf_va_type->tt_member; | 1540 expected = ufunc->uf_va_type->tt_member; |
1528 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; | 1541 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; |
1529 if (need_type(actual, expected, -argcount + i, cctx, TRUE) == FAIL) | 1542 if (need_type(actual, expected, -argcount + i, cctx, |
1543 TRUE, FALSE) == FAIL) | |
1530 { | 1544 { |
1531 arg_type_mismatch(expected, actual, i + 1); | 1545 arg_type_mismatch(expected, actual, i + 1); |
1532 return FAIL; | 1546 return FAIL; |
1533 } | 1547 } |
1534 } | 1548 } |
2059 // Using 50 should be more than enough of 5 levels of (). | 2073 // Using 50 should be more than enough of 5 levels of (). |
2060 #define PPSIZE 50 | 2074 #define PPSIZE 50 |
2061 typedef struct { | 2075 typedef struct { |
2062 typval_T pp_tv[PPSIZE]; // stack of ppconst constants | 2076 typval_T pp_tv[PPSIZE]; // stack of ppconst constants |
2063 int pp_used; // active entries in pp_tv[] | 2077 int pp_used; // active entries in pp_tv[] |
2078 int pp_is_const; // all generated code was constants, used for a | |
2079 // list or dict with constant members | |
2064 } ppconst_T; | 2080 } ppconst_T; |
2065 | 2081 |
2082 static int compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const); | |
2066 static int compile_expr0(char_u **arg, cctx_T *cctx); | 2083 static int compile_expr0(char_u **arg, cctx_T *cctx); |
2067 static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst); | 2084 static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst); |
2068 | 2085 |
2069 /* | 2086 /* |
2070 * Generate a PUSH instruction for "tv". | 2087 * Generate a PUSH instruction for "tv". |
2627 } | 2644 } |
2628 | 2645 |
2629 /* | 2646 /* |
2630 * parse a list: [expr, expr] | 2647 * parse a list: [expr, expr] |
2631 * "*arg" points to the '['. | 2648 * "*arg" points to the '['. |
2632 */ | 2649 * ppconst->pp_is_const is set if all items are a constant. |
2633 static int | 2650 */ |
2634 compile_list(char_u **arg, cctx_T *cctx) | 2651 static int |
2652 compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) | |
2635 { | 2653 { |
2636 char_u *p = skipwhite(*arg + 1); | 2654 char_u *p = skipwhite(*arg + 1); |
2637 char_u *whitep = *arg + 1; | 2655 char_u *whitep = *arg + 1; |
2638 int count = 0; | 2656 int count = 0; |
2657 int is_const; | |
2658 int is_all_const = TRUE; // reset when non-const encountered | |
2639 | 2659 |
2640 for (;;) | 2660 for (;;) |
2641 { | 2661 { |
2642 if (may_get_next_line(whitep, &p, cctx) == FAIL) | 2662 if (may_get_next_line(whitep, &p, cctx) == FAIL) |
2643 { | 2663 { |
2652 if (*p == ']') | 2672 if (*p == ']') |
2653 { | 2673 { |
2654 ++p; | 2674 ++p; |
2655 break; | 2675 break; |
2656 } | 2676 } |
2657 if (compile_expr0(&p, cctx) == FAIL) | 2677 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL) |
2658 return FAIL; | 2678 return FAIL; |
2679 if (!is_const) | |
2680 is_all_const = FALSE; | |
2659 ++count; | 2681 ++count; |
2660 if (*p == ',') | 2682 if (*p == ',') |
2661 { | 2683 { |
2662 ++p; | 2684 ++p; |
2663 if (*p != ']' && !IS_WHITE_OR_NUL(*p)) | 2685 if (*p != ']' && !IS_WHITE_OR_NUL(*p)) |
2669 whitep = p; | 2691 whitep = p; |
2670 p = skipwhite(p); | 2692 p = skipwhite(p); |
2671 } | 2693 } |
2672 *arg = p; | 2694 *arg = p; |
2673 | 2695 |
2674 generate_NEWLIST(cctx, count); | 2696 ppconst->pp_is_const = is_all_const; |
2675 return OK; | 2697 return generate_NEWLIST(cctx, count); |
2676 } | 2698 } |
2677 | 2699 |
2678 /* | 2700 /* |
2679 * parse a lambda: {arg, arg -> expr} | 2701 * parse a lambda: {arg, arg -> expr} |
2680 * "*arg" points to the '{'. | 2702 * "*arg" points to the '{'. |
2770 } | 2792 } |
2771 | 2793 |
2772 /* | 2794 /* |
2773 * parse a dict: {'key': val} or #{key: val} | 2795 * parse a dict: {'key': val} or #{key: val} |
2774 * "*arg" points to the '{'. | 2796 * "*arg" points to the '{'. |
2775 */ | 2797 * ppconst->pp_is_const is set if all item values are a constant. |
2776 static int | 2798 */ |
2777 compile_dict(char_u **arg, cctx_T *cctx, int literal) | 2799 static int |
2800 compile_dict(char_u **arg, cctx_T *cctx, int literal, ppconst_T *ppconst) | |
2778 { | 2801 { |
2779 garray_T *instr = &cctx->ctx_instr; | 2802 garray_T *instr = &cctx->ctx_instr; |
2780 garray_T *stack = &cctx->ctx_type_stack; | 2803 garray_T *stack = &cctx->ctx_type_stack; |
2781 int count = 0; | 2804 int count = 0; |
2782 dict_T *d = dict_alloc(); | 2805 dict_T *d = dict_alloc(); |
2783 dictitem_T *item; | 2806 dictitem_T *item; |
2784 char_u *whitep = *arg; | 2807 char_u *whitep = *arg; |
2785 char_u *p; | 2808 char_u *p; |
2809 int is_const; | |
2810 int is_all_const = TRUE; // reset when non-const encountered | |
2786 | 2811 |
2787 if (d == NULL) | 2812 if (d == NULL) |
2788 return FAIL; | 2813 return FAIL; |
2789 *arg = skipwhite(*arg + 1); | 2814 *arg = skipwhite(*arg + 1); |
2790 for (;;) | 2815 for (;;) |
2825 key = isn->isn_arg.string; | 2850 key = isn->isn_arg.string; |
2826 else | 2851 else |
2827 { | 2852 { |
2828 type_T *keytype = ((type_T **)stack->ga_data) | 2853 type_T *keytype = ((type_T **)stack->ga_data) |
2829 [stack->ga_len - 1]; | 2854 [stack->ga_len - 1]; |
2830 if (need_type(keytype, &t_string, -1, cctx, FALSE) == FAIL) | 2855 if (need_type(keytype, &t_string, -1, cctx, |
2856 FALSE, FALSE) == FAIL) | |
2831 return FAIL; | 2857 return FAIL; |
2832 } | 2858 } |
2833 } | 2859 } |
2834 | 2860 |
2835 // Check for duplicate keys, if using string keys. | 2861 // Check for duplicate keys, if using string keys. |
2871 { | 2897 { |
2872 *arg = NULL; | 2898 *arg = NULL; |
2873 goto failret; | 2899 goto failret; |
2874 } | 2900 } |
2875 | 2901 |
2876 if (compile_expr0(arg, cctx) == FAIL) | 2902 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL) |
2877 return FAIL; | 2903 return FAIL; |
2904 if (!is_const) | |
2905 is_all_const = FALSE; | |
2878 ++count; | 2906 ++count; |
2879 | 2907 |
2880 whitep = *arg; | 2908 whitep = *arg; |
2881 *arg = skipwhite(*arg); | 2909 *arg = skipwhite(*arg); |
2882 if (may_get_next_line(whitep, arg, cctx) == FAIL) | 2910 if (may_get_next_line(whitep, arg, cctx) == FAIL) |
2906 p = skipwhite(*arg); | 2934 p = skipwhite(*arg); |
2907 if (VIM_ISWHITE(**arg) && vim9_comment_start(p)) | 2935 if (VIM_ISWHITE(**arg) && vim9_comment_start(p)) |
2908 *arg += STRLEN(*arg); | 2936 *arg += STRLEN(*arg); |
2909 | 2937 |
2910 dict_unref(d); | 2938 dict_unref(d); |
2939 ppconst->pp_is_const = is_all_const; | |
2911 return generate_NEWDICT(cctx, count); | 2940 return generate_NEWDICT(cctx, count); |
2912 | 2941 |
2913 failret: | 2942 failret: |
2914 if (*arg == NULL) | 2943 if (*arg == NULL) |
2915 { | 2944 { |
3243 type_T *type; | 3272 type_T *type; |
3244 int argcount = 0; | 3273 int argcount = 0; |
3245 | 3274 |
3246 if (generate_ppconst(cctx, ppconst) == FAIL) | 3275 if (generate_ppconst(cctx, ppconst) == FAIL) |
3247 return FAIL; | 3276 return FAIL; |
3277 ppconst->pp_is_const = FALSE; | |
3248 | 3278 |
3249 // funcref(arg) | 3279 // funcref(arg) |
3250 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 3280 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
3251 | 3281 |
3252 *arg = skipwhite(p + 1); | 3282 *arg = skipwhite(p + 1); |
3259 { | 3289 { |
3260 char_u *pstart = p; | 3290 char_u *pstart = p; |
3261 | 3291 |
3262 if (generate_ppconst(cctx, ppconst) == FAIL) | 3292 if (generate_ppconst(cctx, ppconst) == FAIL) |
3263 return FAIL; | 3293 return FAIL; |
3294 ppconst->pp_is_const = FALSE; | |
3264 | 3295 |
3265 // something->method() | 3296 // something->method() |
3266 // Apply the '!', '-' and '+' first: | 3297 // Apply the '!', '-' and '+' first: |
3267 // -1.0->func() works like (-1.0)->func() | 3298 // -1.0->func() works like (-1.0)->func() |
3268 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL) | 3299 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL) |
3314 // TODO: blob index | 3345 // TODO: blob index |
3315 // TODO: more arguments | 3346 // TODO: more arguments |
3316 // TODO: recognize list or dict at runtime | 3347 // TODO: recognize list or dict at runtime |
3317 if (generate_ppconst(cctx, ppconst) == FAIL) | 3348 if (generate_ppconst(cctx, ppconst) == FAIL) |
3318 return FAIL; | 3349 return FAIL; |
3350 ppconst->pp_is_const = FALSE; | |
3319 | 3351 |
3320 ++p; | 3352 ++p; |
3321 *arg = skipwhite(p); | 3353 *arg = skipwhite(p); |
3322 if (may_get_next_line_error(p, arg, cctx) == FAIL) | 3354 if (may_get_next_line_error(p, arg, cctx) == FAIL) |
3323 return FAIL; | 3355 return FAIL; |
3369 // If the index is a string, the variable must be a Dict. | 3401 // If the index is a string, the variable must be a Dict. |
3370 if (*typep == &t_any && valtype == &t_string) | 3402 if (*typep == &t_any && valtype == &t_string) |
3371 vtype = VAR_DICT; | 3403 vtype = VAR_DICT; |
3372 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB) | 3404 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB) |
3373 { | 3405 { |
3374 if (need_type(valtype, &t_number, -1, cctx, FALSE) == FAIL) | 3406 if (need_type(valtype, &t_number, -1, cctx, |
3407 FALSE, FALSE) == FAIL) | |
3375 return FAIL; | 3408 return FAIL; |
3376 if (is_slice) | 3409 if (is_slice) |
3377 { | 3410 { |
3378 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; | 3411 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; |
3379 if (need_type(valtype, &t_number, -2, cctx, FALSE) == FAIL) | 3412 if (need_type(valtype, &t_number, -2, cctx, |
3413 FALSE, FALSE) == FAIL) | |
3380 return FAIL; | 3414 return FAIL; |
3381 } | 3415 } |
3382 } | 3416 } |
3383 | 3417 |
3384 if (vtype == VAR_DICT) | 3418 if (vtype == VAR_DICT) |
3390 } | 3424 } |
3391 if ((*typep)->tt_type == VAR_DICT) | 3425 if ((*typep)->tt_type == VAR_DICT) |
3392 *typep = (*typep)->tt_member; | 3426 *typep = (*typep)->tt_member; |
3393 else | 3427 else |
3394 { | 3428 { |
3395 if (need_type(*typep, &t_dict_any, -2, cctx, FALSE) == FAIL) | 3429 if (need_type(*typep, &t_dict_any, -2, cctx, |
3430 FALSE, FALSE) == FAIL) | |
3396 return FAIL; | 3431 return FAIL; |
3397 *typep = &t_any; | 3432 *typep = &t_any; |
3398 } | 3433 } |
3399 if (may_generate_2STRING(-1, cctx) == FAIL) | 3434 if (may_generate_2STRING(-1, cctx) == FAIL) |
3400 return FAIL; | 3435 return FAIL; |
3439 return FAIL; | 3474 return FAIL; |
3440 } | 3475 } |
3441 } | 3476 } |
3442 else if (*p == '.' && p[1] != '.') | 3477 else if (*p == '.' && p[1] != '.') |
3443 { | 3478 { |
3479 // dictionary member: dict.name | |
3444 if (generate_ppconst(cctx, ppconst) == FAIL) | 3480 if (generate_ppconst(cctx, ppconst) == FAIL) |
3445 return FAIL; | 3481 return FAIL; |
3482 ppconst->pp_is_const = FALSE; | |
3446 | 3483 |
3447 *arg = p + 1; | 3484 *arg = p + 1; |
3448 if (may_get_next_line(*arg, arg, cctx) == FAIL) | 3485 if (may_get_next_line(*arg, arg, cctx) == FAIL) |
3449 { | 3486 { |
3450 emsg(_(e_missing_name_after_dot)); | 3487 emsg(_(e_missing_name_after_dot)); |
3451 return FAIL; | 3488 return FAIL; |
3452 } | 3489 } |
3453 // dictionary member: dict.name | |
3454 p = *arg; | 3490 p = *arg; |
3455 if (eval_isdictc(*p)) | 3491 if (eval_isdictc(*p)) |
3456 while (eval_isnamec(*p)) | 3492 while (eval_isnamec(*p)) |
3457 MB_PTR_ADV(p); | 3493 MB_PTR_ADV(p); |
3458 if (p == *arg) | 3494 if (p == *arg) |
3478 | 3514 |
3479 /* | 3515 /* |
3480 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr". | 3516 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr". |
3481 * "arg" is advanced until after the expression, skipping white space. | 3517 * "arg" is advanced until after the expression, skipping white space. |
3482 * | 3518 * |
3483 * If the value is a constant "ppconst->pp_ret" will be set. | 3519 * If the value is a constant "ppconst->pp_used" will be non-zero. |
3484 * Before instructions are generated, any values in "ppconst" will generated. | 3520 * Before instructions are generated, any values in "ppconst" will generated. |
3485 * | 3521 * |
3486 * This is the compiling equivalent of eval1(), eval2(), etc. | 3522 * This is the compiling equivalent of eval1(), eval2(), etc. |
3487 */ | 3523 */ |
3488 | 3524 |
3518 { | 3554 { |
3519 char_u *start_leader, *end_leader; | 3555 char_u *start_leader, *end_leader; |
3520 int ret = OK; | 3556 int ret = OK; |
3521 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used]; | 3557 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used]; |
3522 int used_before = ppconst->pp_used; | 3558 int used_before = ppconst->pp_used; |
3559 | |
3560 ppconst->pp_is_const = FALSE; | |
3523 | 3561 |
3524 /* | 3562 /* |
3525 * Skip '!', '-' and '+' characters. They are handled later. | 3563 * Skip '!', '-' and '+' characters. They are handled later. |
3526 */ | 3564 */ |
3527 start_leader = *arg; | 3565 start_leader = *arg; |
3608 break; | 3646 break; |
3609 | 3647 |
3610 /* | 3648 /* |
3611 * List: [expr, expr] | 3649 * List: [expr, expr] |
3612 */ | 3650 */ |
3613 case '[': ret = compile_list(arg, cctx); | 3651 case '[': ret = compile_list(arg, cctx, ppconst); |
3614 break; | 3652 break; |
3615 | 3653 |
3616 /* | 3654 /* |
3617 * Dictionary: #{key: val, key: val} | 3655 * Dictionary: #{key: val, key: val} |
3618 */ | 3656 */ |
3619 case '#': if ((*arg)[1] == '{') | 3657 case '#': if ((*arg)[1] == '{') |
3620 { | 3658 { |
3621 ++*arg; | 3659 ++*arg; |
3622 ret = compile_dict(arg, cctx, TRUE); | 3660 ret = compile_dict(arg, cctx, TRUE, ppconst); |
3623 } | 3661 } |
3624 else | 3662 else |
3625 ret = NOTDONE; | 3663 ret = NOTDONE; |
3626 break; | 3664 break; |
3627 | 3665 |
3636 ret = get_function_args(&start, '-', NULL, | 3674 ret = get_function_args(&start, '-', NULL, |
3637 NULL, NULL, NULL, TRUE, NULL, NULL); | 3675 NULL, NULL, NULL, TRUE, NULL, NULL); |
3638 if (ret != FAIL && *start == '>') | 3676 if (ret != FAIL && *start == '>') |
3639 ret = compile_lambda(arg, cctx); | 3677 ret = compile_lambda(arg, cctx); |
3640 else | 3678 else |
3641 ret = compile_dict(arg, cctx, FALSE); | 3679 ret = compile_dict(arg, cctx, FALSE, ppconst); |
3642 } | 3680 } |
3643 break; | 3681 break; |
3644 | 3682 |
3645 /* | 3683 /* |
3646 * Option value: &name | 3684 * Option value: &name |
3805 | 3843 |
3806 generate_ppconst(cctx, ppconst); | 3844 generate_ppconst(cctx, ppconst); |
3807 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 3845 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
3808 if (check_type(want_type, actual, FALSE, 0) == FAIL) | 3846 if (check_type(want_type, actual, FALSE, 0) == FAIL) |
3809 { | 3847 { |
3810 if (need_type(actual, want_type, -1, cctx, FALSE) == FAIL) | 3848 if (need_type(actual, want_type, -1, cctx, FALSE, FALSE) == FAIL) |
3811 return FAIL; | 3849 return FAIL; |
3812 } | 3850 } |
3813 } | 3851 } |
3814 | 3852 |
3815 return OK; | 3853 return OK; |
4418 return OK; | 4456 return OK; |
4419 } | 4457 } |
4420 | 4458 |
4421 /* | 4459 /* |
4422 * Toplevel expression. | 4460 * Toplevel expression. |
4423 */ | 4461 * Sets "is_const" (if not NULL) to indicate the value is a constant. |
4424 static int | 4462 * Returns OK or FAIL. |
4425 compile_expr0(char_u **arg, cctx_T *cctx) | 4463 */ |
4464 static int | |
4465 compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const) | |
4426 { | 4466 { |
4427 ppconst_T ppconst; | 4467 ppconst_T ppconst; |
4428 | 4468 |
4429 CLEAR_FIELD(ppconst); | 4469 CLEAR_FIELD(ppconst); |
4430 if (compile_expr1(arg, cctx, &ppconst) == FAIL) | 4470 if (compile_expr1(arg, cctx, &ppconst) == FAIL) |
4431 { | 4471 { |
4432 clear_ppconst(&ppconst); | 4472 clear_ppconst(&ppconst); |
4433 return FAIL; | 4473 return FAIL; |
4434 } | 4474 } |
4475 if (is_const != NULL) | |
4476 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const; | |
4435 if (generate_ppconst(cctx, &ppconst) == FAIL) | 4477 if (generate_ppconst(cctx, &ppconst) == FAIL) |
4436 return FAIL; | 4478 return FAIL; |
4437 return OK; | 4479 return OK; |
4480 } | |
4481 | |
4482 /* | |
4483 * Toplevel expression. | |
4484 */ | |
4485 static int | |
4486 compile_expr0(char_u **arg, cctx_T *cctx) | |
4487 { | |
4488 return compile_expr0_ext(arg, cctx, NULL); | |
4438 } | 4489 } |
4439 | 4490 |
4440 /* | 4491 /* |
4441 * compile "return [expr]" | 4492 * compile "return [expr]" |
4442 */ | 4493 */ |
4464 { | 4515 { |
4465 emsg(_(e_returning_value_in_function_without_return_type)); | 4516 emsg(_(e_returning_value_in_function_without_return_type)); |
4466 return NULL; | 4517 return NULL; |
4467 } | 4518 } |
4468 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, | 4519 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, |
4469 cctx, FALSE) == FAIL) | 4520 cctx, FALSE, FALSE) == FAIL) |
4470 return NULL; | 4521 return NULL; |
4471 } | 4522 } |
4472 } | 4523 } |
4473 else | 4524 else |
4474 { | 4525 { |
4832 if (stacktype->tt_type == VAR_VOID) | 4883 if (stacktype->tt_type == VAR_VOID) |
4833 { | 4884 { |
4834 emsg(_(e_cannot_use_void_value)); | 4885 emsg(_(e_cannot_use_void_value)); |
4835 goto theend; | 4886 goto theend; |
4836 } | 4887 } |
4837 if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL) | 4888 if (need_type(stacktype, &t_list_any, -1, cctx, |
4889 FALSE, FALSE) == FAIL) | |
4838 goto theend; | 4890 goto theend; |
4839 // TODO: check the length of a constant list here | 4891 // TODO: check the length of a constant list here |
4840 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, | 4892 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, |
4841 semicolon); | 4893 semicolon); |
4842 } | 4894 } |
5192 } | 5244 } |
5193 } | 5245 } |
5194 else if (oplen > 0) | 5246 else if (oplen > 0) |
5195 { | 5247 { |
5196 type_T *stacktype; | 5248 type_T *stacktype; |
5249 int is_const = FALSE; | |
5197 | 5250 |
5198 // For "var = expr" evaluate the expression. | 5251 // For "var = expr" evaluate the expression. |
5199 if (var_count == 0) | 5252 if (var_count == 0) |
5200 { | 5253 { |
5201 int r; | 5254 int r; |
5217 // variable here, it is not available to this expression. | 5270 // variable here, it is not available to this expression. |
5218 if (new_local) | 5271 if (new_local) |
5219 --cctx->ctx_locals.ga_len; | 5272 --cctx->ctx_locals.ga_len; |
5220 instr_count = instr->ga_len; | 5273 instr_count = instr->ga_len; |
5221 p = skipwhite(op + oplen); | 5274 p = skipwhite(op + oplen); |
5222 r = compile_expr0(&p, cctx); | 5275 r = compile_expr0_ext(&p, cctx, &is_const); |
5223 if (new_local) | 5276 if (new_local) |
5224 ++cctx->ctx_locals.ga_len; | 5277 ++cctx->ctx_locals.ga_len; |
5225 if (r == FAIL) | 5278 if (r == FAIL) |
5226 goto theend; | 5279 goto theend; |
5227 } | 5280 } |
5279 use_type = use_type->tt_member; | 5332 use_type = use_type->tt_member; |
5280 if (use_type == NULL) | 5333 if (use_type == NULL) |
5281 // could be indexing "any" | 5334 // could be indexing "any" |
5282 use_type = &t_any; | 5335 use_type = &t_any; |
5283 } | 5336 } |
5284 if (need_type(stacktype, use_type, -1, cctx, FALSE) | 5337 if (need_type(stacktype, use_type, -1, cctx, |
5285 == FAIL) | 5338 FALSE, is_const) == FAIL) |
5286 goto theend; | 5339 goto theend; |
5287 } | 5340 } |
5288 } | 5341 } |
5289 else if (*p != '=' && need_type(stacktype, member_type, -1, | 5342 else if (*p != '=' && need_type(stacktype, member_type, -1, |
5290 cctx, FALSE) == FAIL) | 5343 cctx, FALSE, FALSE) == FAIL) |
5291 goto theend; | 5344 goto theend; |
5292 } | 5345 } |
5293 else if (cmdidx == CMD_final) | 5346 else if (cmdidx == CMD_final) |
5294 { | 5347 { |
5295 emsg(_(e_final_requires_a_value)); | 5348 emsg(_(e_final_requires_a_value)); |
5372 if ( | 5425 if ( |
5373 #ifdef FEAT_FLOAT | 5426 #ifdef FEAT_FLOAT |
5374 // If variable is float operation with number is OK. | 5427 // If variable is float operation with number is OK. |
5375 !(expected == &t_float && stacktype == &t_number) && | 5428 !(expected == &t_float && stacktype == &t_number) && |
5376 #endif | 5429 #endif |
5377 need_type(stacktype, expected, -1, cctx, FALSE) == FAIL) | 5430 need_type(stacktype, expected, -1, cctx, |
5431 FALSE, FALSE) == FAIL) | |
5378 goto theend; | 5432 goto theend; |
5379 | 5433 |
5380 if (*op == '.') | 5434 if (*op == '.') |
5381 { | 5435 { |
5382 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL) | 5436 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL) |
5766 garray_T *stack = &cctx->ctx_type_stack; | 5820 garray_T *stack = &cctx->ctx_type_stack; |
5767 type_T *type; | 5821 type_T *type; |
5768 | 5822 |
5769 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 5823 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
5770 if (type != &t_bool && type != &t_number && type != &t_any | 5824 if (type != &t_bool && type != &t_number && type != &t_any |
5771 && need_type(type, &t_bool, -1, cctx, FALSE) == FAIL) | 5825 && need_type(type, &t_bool, -1, cctx, FALSE, FALSE) == FAIL) |
5772 return FAIL; | 5826 return FAIL; |
5773 return OK; | 5827 return OK; |
5774 } | 5828 } |
5775 | 5829 |
5776 /* | 5830 /* |
6103 } | 6157 } |
6104 | 6158 |
6105 // Now that we know the type of "var", check that it is a list, now or at | 6159 // Now that we know the type of "var", check that it is a list, now or at |
6106 // runtime. | 6160 // runtime. |
6107 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 6161 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
6108 if (need_type(vartype, &t_list_any, -1, cctx, FALSE) == FAIL) | 6162 if (need_type(vartype, &t_list_any, -1, cctx, FALSE, FALSE) == FAIL) |
6109 { | 6163 { |
6110 drop_scope(cctx); | 6164 drop_scope(cctx); |
6111 return NULL; | 6165 return NULL; |
6112 } | 6166 } |
6113 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY) | 6167 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY) |