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 }