Mercurial > vim
comparison src/vim9compile.c @ 23072:4b398a229b0b v8.2.2082
patch 8.2.2082: Vim9: can still use the depricated #{} dict syntax
Commit: https://github.com/vim/vim/commit/e0de171ecd2ff7acd56deda2cf81f0d13a69c803
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Dec 2 17:36:54 2020 +0100
patch 8.2.2082: Vim9: can still use the depricated #{} dict syntax
Problem: Vim9: can still use the depricated #{} dict syntax.
Solution: Remove support for #{} in Vim9 script. (closes https://github.com/vim/vim/issues/7406, closes https://github.com/vim/vim/issues/7405)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 02 Dec 2020 17:45:05 +0100 |
parents | 6a70803f4cbe |
children | 2120e4b40e12 |
comparison
equal
deleted
inserted
replaced
23071:20dac5998fa6 | 23072:4b398a229b0b |
---|---|
2125 } | 2125 } |
2126 ga_clear(&cctx->ctx_imports); | 2126 ga_clear(&cctx->ctx_imports); |
2127 } | 2127 } |
2128 | 2128 |
2129 /* | 2129 /* |
2130 * Return TRUE if "p" points at a "#" but not at "#{". | 2130 * Return TRUE if "p" points at a "#". Does not check for white space. |
2131 */ | 2131 */ |
2132 int | 2132 int |
2133 vim9_comment_start(char_u *p) | 2133 vim9_comment_start(char_u *p) |
2134 { | 2134 { |
2135 return p[0] == '#' && p[1] != '{'; | 2135 return p[0] == '#'; |
2136 } | 2136 } |
2137 | 2137 |
2138 /* | 2138 /* |
2139 * Return a pointer to the next line that isn't empty or only contains a | 2139 * Return a pointer to the next line that isn't empty or only contains a |
2140 * comment. Skips over white space. | 2140 * comment. Skips over white space. |
2838 | 2838 |
2839 // Can be "[1, 2, 3]->Func()". | 2839 // Can be "[1, 2, 3]->Func()". |
2840 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL) | 2840 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL) |
2841 p = arg; | 2841 p = arg; |
2842 } | 2842 } |
2843 else if (p == arg && *arg == '#' && arg[1] == '{') | |
2844 { | |
2845 // Can be "#{a: 1}->Func()". | |
2846 ++p; | |
2847 if (eval_dict(&p, &rettv, NULL, TRUE) == FAIL) | |
2848 p = arg; | |
2849 } | |
2850 | |
2851 return p; | 2843 return p; |
2852 } | 2844 } |
2853 | 2845 |
2854 /* | 2846 /* |
2855 * parse a list: [expr, expr] | 2847 * parse a list: [expr, expr] |
2997 func_ptr_unref(ufunc); | 2989 func_ptr_unref(ufunc); |
2998 return ret; | 2990 return ret; |
2999 } | 2991 } |
3000 | 2992 |
3001 /* | 2993 /* |
3002 * parse a dict: {'key': val} or #{key: val} | 2994 * parse a dict: {key: val, [key]: val} |
3003 * "*arg" points to the '{'. | 2995 * "*arg" points to the '{'. |
3004 * ppconst->pp_is_const is set if all item values are a constant. | 2996 * ppconst->pp_is_const is set if all item values are a constant. |
3005 */ | 2997 */ |
3006 static int | 2998 static int |
3007 compile_dict(char_u **arg, cctx_T *cctx, int literal, ppconst_T *ppconst) | 2999 compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) |
3008 { | 3000 { |
3009 garray_T *instr = &cctx->ctx_instr; | 3001 garray_T *instr = &cctx->ctx_instr; |
3010 garray_T *stack = &cctx->ctx_type_stack; | 3002 garray_T *stack = &cctx->ctx_type_stack; |
3011 int count = 0; | 3003 int count = 0; |
3012 dict_T *d = dict_alloc(); | 3004 dict_T *d = dict_alloc(); |
3020 return FAIL; | 3012 return FAIL; |
3021 *arg = skipwhite(*arg + 1); | 3013 *arg = skipwhite(*arg + 1); |
3022 for (;;) | 3014 for (;;) |
3023 { | 3015 { |
3024 char_u *key = NULL; | 3016 char_u *key = NULL; |
3025 char_u *end; | |
3026 | 3017 |
3027 if (may_get_next_line(whitep, arg, cctx) == FAIL) | 3018 if (may_get_next_line(whitep, arg, cctx) == FAIL) |
3028 { | 3019 { |
3029 *arg = NULL; | 3020 *arg = NULL; |
3030 goto failret; | 3021 goto failret; |
3031 } | 3022 } |
3032 | 3023 |
3033 if (**arg == '}') | 3024 if (**arg == '}') |
3034 break; | 3025 break; |
3035 | 3026 |
3036 // Eventually {name: value} will use "name" as a literal key and | 3027 // {name: value} uses "name" as a literal key and |
3037 // {[expr]: value} for an evaluated key. | 3028 // {[expr]: value} uses an evaluated key. |
3038 // Temporarily: if "name" is indeed a valid key, or "[expr]" is | 3029 if (**arg != '[') |
3039 // used, use the new method, like JavaScript. Otherwise fall back | 3030 { |
3040 // to the old method. | 3031 char_u *end = skip_literal_key(*arg); |
3041 end = to_name_end(*arg, FALSE); | 3032 |
3042 if (literal || *end == ':') | |
3043 { | |
3044 if (end == *arg) | 3033 if (end == *arg) |
3045 { | 3034 { |
3046 semsg(_(e_invalid_key_str), *arg); | 3035 semsg(_(e_invalid_key_str), *arg); |
3047 return FAIL; | 3036 return FAIL; |
3048 } | 3037 } |
3052 *arg = end; | 3041 *arg = end; |
3053 } | 3042 } |
3054 else | 3043 else |
3055 { | 3044 { |
3056 isn_T *isn; | 3045 isn_T *isn; |
3057 int has_bracket = **arg == '['; | 3046 |
3058 | 3047 *arg = skipwhite(*arg + 1); |
3059 if (has_bracket) | |
3060 *arg = skipwhite(*arg + 1); | |
3061 if (compile_expr0(arg, cctx) == FAIL) | 3048 if (compile_expr0(arg, cctx) == FAIL) |
3062 return FAIL; | 3049 return FAIL; |
3063 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; | 3050 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; |
3064 if (isn->isn_type == ISN_PUSHS) | 3051 if (isn->isn_type == ISN_PUSHS) |
3065 key = isn->isn_arg.string; | 3052 key = isn->isn_arg.string; |
3069 [stack->ga_len - 1]; | 3056 [stack->ga_len - 1]; |
3070 if (need_type(keytype, &t_string, -1, cctx, | 3057 if (need_type(keytype, &t_string, -1, cctx, |
3071 FALSE, FALSE) == FAIL) | 3058 FALSE, FALSE) == FAIL) |
3072 return FAIL; | 3059 return FAIL; |
3073 } | 3060 } |
3074 if (has_bracket) | 3061 *arg = skipwhite(*arg); |
3075 { | 3062 if (**arg != ']') |
3076 *arg = skipwhite(*arg); | 3063 { |
3077 if (**arg != ']') | 3064 emsg(_(e_missing_matching_bracket_after_dict_key)); |
3078 { | 3065 return FAIL; |
3079 emsg(_(e_missing_matching_bracket_after_dict_key)); | 3066 } |
3080 return FAIL; | 3067 ++*arg; |
3081 } | |
3082 ++*arg; | |
3083 } | |
3084 } | 3068 } |
3085 | 3069 |
3086 // Check for duplicate keys, if using string keys. | 3070 // Check for duplicate keys, if using string keys. |
3087 if (key != NULL) | 3071 if (key != NULL) |
3088 { | 3072 { |
3764 * identifier variable value | 3748 * identifier variable value |
3765 * function() function call | 3749 * function() function call |
3766 * $VAR environment variable | 3750 * $VAR environment variable |
3767 * (expression) nested expression | 3751 * (expression) nested expression |
3768 * [expr, expr] List | 3752 * [expr, expr] List |
3769 * {key: val, key: val} Dictionary | 3753 * {key: val, [key]: val} Dictionary |
3770 * #{key: val, key: val} Dictionary with literal keys | |
3771 * | 3754 * |
3772 * Also handle: | 3755 * Also handle: |
3773 * ! in front logical NOT | 3756 * ! in front logical NOT |
3774 * - in front unary minus | 3757 * - in front unary minus |
3775 * + in front unary plus (ignored) | 3758 * + in front unary plus (ignored) |
3882 */ | 3865 */ |
3883 case '[': ret = compile_list(arg, cctx, ppconst); | 3866 case '[': ret = compile_list(arg, cctx, ppconst); |
3884 break; | 3867 break; |
3885 | 3868 |
3886 /* | 3869 /* |
3887 * Dictionary: #{key: val, key: val} | |
3888 */ | |
3889 case '#': if ((*arg)[1] == '{') | |
3890 { | |
3891 ++*arg; | |
3892 ret = compile_dict(arg, cctx, TRUE, ppconst); | |
3893 } | |
3894 else | |
3895 ret = NOTDONE; | |
3896 break; | |
3897 | |
3898 /* | |
3899 * Lambda: {arg, arg -> expr} | 3870 * Lambda: {arg, arg -> expr} |
3900 * Dictionary: {'key': val, 'key': val} | 3871 * Dictionary: {'key': val, 'key': val} |
3901 */ | 3872 */ |
3902 case '{': { | 3873 case '{': { |
3903 char_u *start = skipwhite(*arg + 1); | 3874 char_u *start = skipwhite(*arg + 1); |
3908 &ga_arg, TRUE, NULL, NULL, | 3879 &ga_arg, TRUE, NULL, NULL, |
3909 TRUE, NULL, NULL); | 3880 TRUE, NULL, NULL); |
3910 if (ret != FAIL && *start == '>') | 3881 if (ret != FAIL && *start == '>') |
3911 ret = compile_lambda(arg, cctx); | 3882 ret = compile_lambda(arg, cctx); |
3912 else | 3883 else |
3913 ret = compile_dict(arg, cctx, FALSE, ppconst); | 3884 ret = compile_dict(arg, cctx, ppconst); |
3914 } | 3885 } |
3915 break; | 3886 break; |
3916 | 3887 |
3917 /* | 3888 /* |
3918 * Option value: &name | 3889 * Option value: &name |
4198 error_white_both(op, oplen); | 4169 error_white_both(op, oplen); |
4199 return FAIL; | 4170 return FAIL; |
4200 } | 4171 } |
4201 | 4172 |
4202 *arg = skipwhite(op + oplen); | 4173 *arg = skipwhite(op + oplen); |
4203 if (may_get_next_line(op + oplen, arg, cctx) == FAIL) | 4174 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL) |
4204 return FAIL; | 4175 return FAIL; |
4205 | 4176 |
4206 // get the second expression | 4177 // get the second expression |
4207 if (compile_expr6(arg, cctx, ppconst) == FAIL) | 4178 if (compile_expr6(arg, cctx, ppconst) == FAIL) |
4208 return FAIL; | 4179 return FAIL; |
7482 | 7453 |
7483 // Some things can be recognized by the first character. | 7454 // Some things can be recognized by the first character. |
7484 switch (*ea.cmd) | 7455 switch (*ea.cmd) |
7485 { | 7456 { |
7486 case '#': | 7457 case '#': |
7487 // "#" starts a comment, but "#{" does not. | 7458 // "#" starts a comment |
7488 if (ea.cmd[1] != '{') | 7459 line = (char_u *)""; |
7489 { | 7460 continue; |
7490 line = (char_u *)""; | |
7491 continue; | |
7492 } | |
7493 break; | |
7494 | 7461 |
7495 case '}': | 7462 case '}': |
7496 { | 7463 { |
7497 // "}" ends a block scope | 7464 // "}" ends a block scope |
7498 scopetype_T stype = cctx.ctx_scope == NULL | 7465 scopetype_T stype = cctx.ctx_scope == NULL |