Mercurial > vim
comparison src/vim9compile.c @ 23368:a7cbdb9294c4 v8.2.2227
patch 8.2.2227: Vim9: recognizing lambda is too complicated
Commit: https://github.com/vim/vim/commit/e462f52db3cab656485a71e4322b6cb18d564a06
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Dec 27 14:43:30 2020 +0100
patch 8.2.2227: Vim9: recognizing lambda is too complicated
Problem: Vim9: recognizing lambda is too complicated.
Solution: Call compile_lambda() and check for NOTDONE.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 27 Dec 2020 14:45:03 +0100 |
parents | 17a0e32eefd4 |
children | 517fca70e084 |
comparison
equal
deleted
inserted
replaced
23367:91b6cc84c6b7 | 23368:a7cbdb9294c4 |
---|---|
2947 } | 2947 } |
2948 | 2948 |
2949 /* | 2949 /* |
2950 * parse a lambda: "{arg, arg -> expr}" or "(arg, arg) => expr" | 2950 * parse a lambda: "{arg, arg -> expr}" or "(arg, arg) => expr" |
2951 * "*arg" points to the '{'. | 2951 * "*arg" points to the '{'. |
2952 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda. | |
2952 */ | 2953 */ |
2953 static int | 2954 static int |
2954 compile_lambda(char_u **arg, cctx_T *cctx) | 2955 compile_lambda(char_u **arg, cctx_T *cctx) |
2955 { | 2956 { |
2957 int r; | |
2956 typval_T rettv; | 2958 typval_T rettv; |
2957 ufunc_T *ufunc; | 2959 ufunc_T *ufunc; |
2958 evalarg_T evalarg; | 2960 evalarg_T evalarg; |
2959 | 2961 |
2960 CLEAR_FIELD(evalarg); | 2962 CLEAR_FIELD(evalarg); |
2961 evalarg.eval_flags = EVAL_EVALUATE; | 2963 evalarg.eval_flags = EVAL_EVALUATE; |
2962 evalarg.eval_cctx = cctx; | 2964 evalarg.eval_cctx = cctx; |
2963 | 2965 |
2964 // Get the funcref in "rettv". | 2966 // Get the funcref in "rettv". |
2965 if (get_lambda_tv(arg, &rettv, TRUE, &evalarg) != OK) | 2967 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg); |
2968 if (r != OK) | |
2966 { | 2969 { |
2967 clear_evalarg(&evalarg, NULL); | 2970 clear_evalarg(&evalarg, NULL); |
2968 return FAIL; | 2971 return r; |
2969 } | 2972 } |
2970 | 2973 |
2971 // "rettv" will now be a partial referencing the function. | 2974 // "rettv" will now be a partial referencing the function. |
2972 ufunc = rettv.vval.v_partial->pt_func; | 2975 ufunc = rettv.vval.v_partial->pt_func; |
2973 ++ufunc->uf_refcount; | 2976 ++ufunc->uf_refcount; |
3999 | 4002 |
4000 /* | 4003 /* |
4001 * Lambda: {arg, arg -> expr} | 4004 * Lambda: {arg, arg -> expr} |
4002 * Dictionary: {'key': val, 'key': val} | 4005 * Dictionary: {'key': val, 'key': val} |
4003 */ | 4006 */ |
4004 case '{': { | 4007 case '{': // Try parsing as a lambda, if NOTDONE is returned it |
4005 char_u *start = skipwhite(*arg + 1); | 4008 // must be a dict. |
4006 char_u *after = start; | 4009 // TODO: if we go with the "(arg) => expr" syntax remove |
4007 garray_T ga_arg; | 4010 // this |
4008 | 4011 ret = compile_lambda(arg, cctx); |
4009 // Find out what comes after the arguments. | 4012 if (ret == NOTDONE) |
4010 ret = get_function_args(&after, '-', NULL, | 4013 ret = compile_dict(arg, cctx, ppconst); |
4011 &ga_arg, TRUE, NULL, NULL, | |
4012 TRUE, NULL, NULL); | |
4013 if (ret != FAIL && after[0] == '>' | |
4014 && ((after > start + 2 | |
4015 && VIM_ISWHITE(after[-2])) | |
4016 || after == start + 1) | |
4017 && IS_WHITE_OR_NUL(after[1])) | |
4018 // TODO: if we go with the "(arg) => expr" syntax | |
4019 // remove this | |
4020 ret = compile_lambda(arg, cctx); | |
4021 else | |
4022 ret = compile_dict(arg, cctx, ppconst); | |
4023 } | |
4024 break; | 4014 break; |
4025 | 4015 |
4026 /* | 4016 /* |
4027 * Option value: &name | 4017 * Option value: &name |
4028 */ | 4018 */ |
4049 /* | 4039 /* |
4050 * nested expression: (expression). | 4040 * nested expression: (expression). |
4051 * lambda: (arg, arg) => expr | 4041 * lambda: (arg, arg) => expr |
4052 * funcref: (arg, arg) => { statement } | 4042 * funcref: (arg, arg) => { statement } |
4053 */ | 4043 */ |
4054 case '(': { | 4044 case '(': // if compile_lambda returns NOTDONE then it must be (expr) |
4055 char_u *start = skipwhite(*arg + 1); | 4045 ret = compile_lambda(arg, cctx); |
4056 char_u *after = start; | 4046 if (ret == NOTDONE) |
4057 garray_T ga_arg; | |
4058 | |
4059 // Find out if "=>" comes after the (). | |
4060 ret = get_function_args(&after, ')', NULL, | |
4061 &ga_arg, TRUE, NULL, NULL, | |
4062 TRUE, NULL, NULL); | |
4063 if (ret == OK && VIM_ISWHITE( | |
4064 *after == ':' ? after[1] : *after)) | |
4065 { | |
4066 if (*after == ':') | |
4067 // Skip over type in "(arg): type". | |
4068 after = skip_type(skipwhite(after + 1), TRUE); | |
4069 | |
4070 after = skipwhite(after); | |
4071 if (after[0] == '=' && after[1] == '>' | |
4072 && IS_WHITE_OR_NUL(after[2])) | |
4073 { | |
4074 ret = compile_lambda(arg, cctx); | |
4075 break; | |
4076 } | |
4077 } | |
4078 ret = compile_parenthesis(arg, cctx, ppconst); | 4047 ret = compile_parenthesis(arg, cctx, ppconst); |
4079 } | |
4080 break; | 4048 break; |
4081 | 4049 |
4082 default: ret = NOTDONE; | 4050 default: ret = NOTDONE; |
4083 break; | 4051 break; |
4084 } | 4052 } |