patch 8.2.2799: Vim9: type casts don't fully work at the script level
Problem: Vim9: type casts don't fully work at the script level.
Solution: Implement the missing piece.
diff --git a/src/eval.c b/src/eval.c
index 4dbbc40..a9f5ae6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -51,6 +51,7 @@
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,7 +3069,7 @@
/*
* Get the first variable.
*/
- if (eval7(arg, rettv, evalarg, want_string) == FAIL)
+ if (eval7t(arg, rettv, evalarg, want_string) == FAIL)
return FAIL;
/*
@@ -3141,7 +3142,7 @@
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
- if (eval7(arg, &var2, evalarg, FALSE) == FAIL)
+ if (eval7t(arg, &var2, evalarg, FALSE) == FAIL)
return FAIL;
if (evaluate)
@@ -3231,6 +3232,86 @@
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 <type> 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)
{