To: vim_dev@googlegroups.com Subject: Patch 8.2.2799 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2799 Problem: Vim9: type casts don't fully work at the script level. Solution: Implement the missing piece. Files: src/eval.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.2798/src/eval.c 2021-04-18 16:08:49.416235259 +0200 --- src/eval.c 2021-04-21 17:27:36.336574801 +0200 *************** *** 51,56 **** --- 51,57 ---- static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg); static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg); static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string); + static int eval7t(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string); static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string); static int eval7_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp); *************** *** 3068,3074 **** /* * Get the first variable. */ ! if (eval7(arg, rettv, evalarg, want_string) == FAIL) return FAIL; /* --- 3069,3075 ---- /* * Get the first variable. */ ! if (eval7t(arg, rettv, evalarg, want_string) == FAIL) return FAIL; /* *************** *** 3141,3147 **** return FAIL; } *arg = skipwhite_and_linebreak(*arg + 1, evalarg); ! if (eval7(arg, &var2, evalarg, FALSE) == FAIL) return FAIL; if (evaluate) --- 3142,3148 ---- return FAIL; } *arg = skipwhite_and_linebreak(*arg + 1, evalarg); ! if (eval7t(arg, &var2, evalarg, FALSE) == FAIL) return FAIL; if (evaluate) *************** *** 3231,3236 **** --- 3232,3317 ---- return OK; } + /* + * Handle a type cast before a base level expression. + * "arg" must point to the first non-white of the expression. + * "arg" is advanced to just after the recognized expression. + * Return OK or FAIL. + */ + static int + eval7t( + char_u **arg, + typval_T *rettv, + evalarg_T *evalarg, + int want_string) // after "." operator + { + type_T *want_type = NULL; + garray_T type_list; // list of pointers to allocated types + int res; + int evaluate = evalarg == NULL ? 0 + : (evalarg->eval_flags & EVAL_EVALUATE); + + // Recognize in Vim9 script only. + if (in_vim9script() && **arg == '<' && eval_isnamec1((*arg)[1])) + { + ++*arg; + ga_init2(&type_list, sizeof(type_T *), 10); + want_type = parse_type(arg, &type_list, TRUE); + if (want_type == NULL && (evaluate || **arg != '>')) + { + clear_type_list(&type_list); + return FAIL; + } + + if (**arg != '>') + { + if (*skipwhite(*arg) == '>') + semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg); + else + emsg(_(e_missing_gt)); + clear_type_list(&type_list); + return FAIL; + } + ++*arg; + *arg = skipwhite_and_linebreak(*arg, evalarg); + } + + res = eval7(arg, rettv, evalarg, want_string); + + if (want_type != NULL && evaluate) + { + if (res == OK) + { + type_T *actual = typval2type(rettv, get_copyID(), &type_list, TRUE); + + if (!equal_type(want_type, actual)) + { + if (want_type == &t_bool && actual != &t_bool + && (actual->tt_flags & TTFLAG_BOOL_OK)) + { + int n = tv2bool(rettv); + + // can use "0" and "1" for boolean in some places + clear_tv(rettv); + rettv->v_type = VAR_BOOL; + rettv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; + } + else + { + where_T where; + + where.wt_index = 0; + where.wt_variable = TRUE; + res = check_type(want_type, actual, TRUE, where); + } + } + } + clear_type_list(&type_list); + } + + return res; + } + int eval_leader(char_u **arg, int vim9) { *** ../vim-8.2.2798/src/testdir/test_vim9_expr.vim 2021-04-11 20:26:30.486312262 +0200 --- src/testdir/test_vim9_expr.vim 2021-04-21 17:30:22.140131199 +0200 *************** *** 1575,1590 **** " type casts def Test_expr7t() ! var ls: list = ['a', g:string_empty] ! var ln: list = [g:anint, g:thefour] ! var nr = 234 ! assert_equal(234, nr) ! CheckDefAndScriptFailure2(["var x = 123"], 'E1010:', 'E15:', 1) CheckDefFailure(["var x = "], 'E1097:', 3) CheckScriptFailure(['vim9script', "var x = "], 'E15:', 2) ! CheckDefAndScriptFailure2(["var x = 123"], 'E1068:', 'E15:', 1) ! CheckDefAndScriptFailure2(["var x = = ['a', g:string_empty] ! var ln: list = [g:anint, g:thefour] ! var nr = 234 ! assert_equal(234, nr) ! var text = ! ! 'text' ! if false ! text = 'xxx' ! endif ! END ! CheckDefAndScriptSuccess(lines) ! CheckDefAndScriptFailure(["var x = 123"], 'E1010:', 1) CheckDefFailure(["var x = "], 'E1097:', 3) CheckScriptFailure(['vim9script', "var x = "], 'E15:', 2) ! CheckDefAndScriptFailure(["var x = 123"], 'E1068:', 1) ! CheckDefAndScriptFailure(["var x =