mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.1408: Vim9: type casting not supported
Problem: Vim9: type casting not supported. Solution: Introduce type casting.
This commit is contained in:
@@ -640,6 +640,35 @@ And classes and interfaces can be used as types: >
|
|||||||
{not implemented yet}
|
{not implemented yet}
|
||||||
|
|
||||||
|
|
||||||
|
Variable types and type casting *variable-types*
|
||||||
|
|
||||||
|
Variables declared in Vim9 script or in a `:def` function have a type, either
|
||||||
|
specified explicitly or inferred from the initialization.
|
||||||
|
|
||||||
|
Global, buffer, window and tab page variables do not have a specific type, the
|
||||||
|
value can be changed at any time, possibly changing the type. Therefore, in
|
||||||
|
compiled code the "any" type is assumed.
|
||||||
|
|
||||||
|
This can be a problem when the "any" type is undesired and the actual type is
|
||||||
|
expected to always be the same. For example, when declaring a list: >
|
||||||
|
let l: list<number> = [1, g:two]
|
||||||
|
This will give an error, because "g:two" has type "any". To avoid this, use a
|
||||||
|
type cast: >
|
||||||
|
let l: list<number> = [1, <number>g:two]
|
||||||
|
< *type-casting*
|
||||||
|
The compiled code will then check that "g:two" is a number at runtime and give
|
||||||
|
an error if it isn't. This is called type casting.
|
||||||
|
|
||||||
|
The syntax of a type cast is: "<" {type} ">". There cannot be white space
|
||||||
|
after the "<" or before the ">" (to avoid them being confused with
|
||||||
|
smaller-than and bigger-than operators).
|
||||||
|
|
||||||
|
The semantics is that, if needed, a runtime type check is performed. The
|
||||||
|
value is not actually changed. If you need to change the type, e.g. to change
|
||||||
|
it to a string, use the |string()| function. Or use |str2nr()| to convert a
|
||||||
|
string to a number.
|
||||||
|
|
||||||
|
|
||||||
Type inference *type-inference*
|
Type inference *type-inference*
|
||||||
|
|
||||||
In general: Whenever the type is clear it can be omitted. For example, when
|
In general: Whenever the type is clear it can be omitted. For example, when
|
||||||
|
@@ -817,6 +817,24 @@ enddef
|
|||||||
|
|
||||||
let g:number = 42
|
let g:number = 42
|
||||||
|
|
||||||
|
def TypeCast()
|
||||||
|
let l: list<number> = [23, <number>g:number]
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_disassemble_typecast()
|
||||||
|
let instr = execute('disassemble TypeCast')
|
||||||
|
assert_match('TypeCast.*' ..
|
||||||
|
'let l: list<number> = \[23, <number>g:number\].*' ..
|
||||||
|
'\d PUSHNR 23\_s*' ..
|
||||||
|
'\d LOADG g:number\_s*' ..
|
||||||
|
'\d CHECKTYPE number stack\[-1\]\_s*' ..
|
||||||
|
'\d NEWLIST size 2\_s*' ..
|
||||||
|
'\d STORE $0\_s*' ..
|
||||||
|
'\d PUSHNR 0\_s*' ..
|
||||||
|
'\d RETURN\_s*',
|
||||||
|
instr)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Computing()
|
def Computing()
|
||||||
let nr = 3
|
let nr = 3
|
||||||
let nrres = nr + 7
|
let nrres = nr + 7
|
||||||
|
@@ -1247,6 +1247,12 @@ let g:dict_one = #{one: 1}
|
|||||||
|
|
||||||
let $TESTVAR = 'testvar'
|
let $TESTVAR = 'testvar'
|
||||||
|
|
||||||
|
" type casts
|
||||||
|
def Test_expr7t()
|
||||||
|
let ls: list<string> = ['a', <string>g:string_empty]
|
||||||
|
let ln: list<number> = [<number>g:anint, <number>g:alsoint]
|
||||||
|
enddef
|
||||||
|
|
||||||
" test low level expression
|
" test low level expression
|
||||||
def Test_expr7_number()
|
def Test_expr7_number()
|
||||||
# number constant
|
# number constant
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1408,
|
||||||
/**/
|
/**/
|
||||||
1407,
|
1407,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -3401,6 +3401,56 @@ error_white_both(char_u *op, int len)
|
|||||||
semsg(_(e_white_both), buf);
|
semsg(_(e_white_both), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <type>expr7: runtime type check / conversion
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||||
|
{
|
||||||
|
type_T *want_type = NULL;
|
||||||
|
|
||||||
|
// Recognize <type>
|
||||||
|
if (**arg == '<' && eval_isnamec1((*arg)[1]))
|
||||||
|
{
|
||||||
|
int called_emsg_before = called_emsg;
|
||||||
|
|
||||||
|
++*arg;
|
||||||
|
want_type = parse_type(arg, cctx->ctx_type_list);
|
||||||
|
if (called_emsg != called_emsg_before)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
if (**arg != '>')
|
||||||
|
{
|
||||||
|
if (*skipwhite(*arg) == '>')
|
||||||
|
semsg(_(e_no_white_before), ">");
|
||||||
|
else
|
||||||
|
emsg(_("E1104: Missing >"));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
++*arg;
|
||||||
|
if (may_get_next_line_error(*arg - 1, arg, cctx) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
if (want_type != NULL)
|
||||||
|
{
|
||||||
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
|
type_T *actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
|
|
||||||
|
if (check_type(want_type, actual, FALSE) == FAIL)
|
||||||
|
{
|
||||||
|
generate_ppconst(cctx, ppconst);
|
||||||
|
if (need_type(actual, want_type, -1, cctx, FALSE) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* * number multiplication
|
* * number multiplication
|
||||||
* / number division
|
* / number division
|
||||||
@@ -3414,7 +3464,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
|||||||
int ppconst_used = ppconst->pp_used;
|
int ppconst_used = ppconst->pp_used;
|
||||||
|
|
||||||
// get the first expression
|
// get the first expression
|
||||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
if (compile_expr7t(arg, cctx, ppconst) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3441,7 +3491,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
// get the second expression
|
// get the second expression
|
||||||
if (compile_expr7(arg, cctx, ppconst) == FAIL)
|
if (compile_expr7t(arg, cctx, ppconst) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if (ppconst->pp_used == ppconst_used + 2
|
if (ppconst->pp_used == ppconst_used + 2
|
||||||
|
Reference in New Issue
Block a user