Patch 8.2.0508
Problem: Vim9: func and partial types not done yet
Solution: Fill in details about func declaration, drop a separate partial
declaration.
Files: runtime/doc/vim9.txt, src/vim9compile.c, src/globals.h,
src/structs.h, src/evalfunc.c, src/testdir/test_vim9_expr.vim,
src/testdir/test_vim9_script.vim,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.0507/runtime/doc/vim9.txt 2020-02-29 22:06:25.647709244 +0100
--- runtime/doc/vim9.txt 2020-04-03 20:52:01.541368955 +0200
***************
*** 213,219 ****
blob non-empty
list non-empty (different from JavaScript)
dictionary non-empty (different from JavaScript)
! funcref when not NULL
partial when not NULL
special v:true
job when not NULL
--- 213,219 ----
blob non-empty
list non-empty (different from JavaScript)
dictionary non-empty (different from JavaScript)
! func when not NULL
partial when not NULL
special v:true
job when not NULL
***************
*** 249,256 ****
the function follows in the next lines, until the
matching `:enddef`.
! When {return-type} is omitted the function is not
! expected to return anything.
{arguments} is a sequence of zero or more argument
declarations. There are three forms:
--- 249,256 ----
the function follows in the next lines, until the
matching `:enddef`.
! When {return-type} is omitted or is "void" the
! function is not expected to return anything.
{arguments} is a sequence of zero or more argument
declarations. There are three forms:
***************
*** 296,322 ****
float
string
blob
! list<type>
! dict<type>
! (a: type, b: type): type
job
channel
Not supported yet:
! tuple<a: type, b: type, ...>
! These types can be used in declarations, but no variable will have this type:
! type|type
void
any
! There is no array type, use list<type> instead. For a list constant an
efficient implementation is used that avoids allocating lot of small pieces of
memory.
! A function defined with `:def` must declare the return type. If there is no
! type then the function doesn't return anything. "void" is used in type
! declarations.
Custom types can be defined with `:type`: >
:type MyList list<string>
--- 296,335 ----
float
string
blob
! list<{type}>
! dict<{type}>
job
channel
+ func
+ func({type}, ...)
+ func({type}, ...): {type}
Not supported yet:
! tuple<a: {type}, b: {type}, ...>
! These types can be used in declarations, but no value will have this type:
! {type}|{type}
void
any
! There is no array type, use list<{type}> instead. For a list constant an
efficient implementation is used that avoids allocating lot of small pieces of
memory.
! A partial and function can be declared in more or less specific ways:
! func any kind of function reference, no type
! checking
! func: {type} any number and type of arguments with specific
! return type
! func({type} ...) function with argument types, does not return
! a value
! func({type} ...): {type} function with argument types and return type
!
! If the return type is "void" the function does not return a value.
!
! The reference can also be a |Partial|, in which case it stores extra arguments
! and/or a dictionary, which are not visible to the caller. Since they are
! called in the same way the declaration is the same.
Custom types can be defined with `:type`: >
:type MyList list<string>
*** ../vim-8.2.0507/src/vim9compile.c 2020-04-02 22:57:32.331945116 +0200
--- src/vim9compile.c 2020-04-03 21:29:53.848485949 +0200
***************
*** 224,230 ****
}
static type_T *
! get_list_type(type_T *member_type, garray_T *type_list)
{
type_T *type;
--- 224,230 ----
}
static type_T *
! get_list_type(type_T *member_type, garray_T *type_gap)
{
type_T *type;
***************
*** 241,257 ****
return &t_list_string;
// Not a common type, create a new entry.
! if (ga_grow(type_list, 1) == FAIL)
return &t_any;
! type = ((type_T *)type_list->ga_data) + type_list->ga_len;
! ++type_list->ga_len;
type->tt_type = VAR_LIST;
type->tt_member = member_type;
return type;
}
static type_T *
! get_dict_type(type_T *member_type, garray_T *type_list)
{
type_T *type;
--- 241,259 ----
return &t_list_string;
// Not a common type, create a new entry.
! if (ga_grow(type_gap, 1) == FAIL)
return &t_any;
! type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
! ++type_gap->ga_len;
type->tt_type = VAR_LIST;
type->tt_member = member_type;
+ type->tt_argcount = 0;
+ type->tt_args = NULL;
return type;
}
static type_T *
! get_dict_type(type_T *member_type, garray_T *type_gap)
{
type_T *type;
***************
*** 268,279 ****
return &t_dict_string;
// Not a common type, create a new entry.
! if (ga_grow(type_list, 1) == FAIL)
return &t_any;
! type = ((type_T *)type_list->ga_data) + type_list->ga_len;
! ++type_list->ga_len;
type->tt_type = VAR_DICT;
type->tt_member = member_type;
return type;
}
--- 270,337 ----
return &t_dict_string;
// Not a common type, create a new entry.
! if (ga_grow(type_gap, 1) == FAIL)
return &t_any;
! type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
! ++type_gap->ga_len;
type->tt_type = VAR_DICT;
type->tt_member = member_type;
+ type->tt_argcount = 0;
+ type->tt_args = NULL;
+ return type;
+ }
+
+ /*
+ * Get a function type, based on the return type "ret_type".
+ * If "argcount" is -1 or 0 a predefined type can be used.
+ * If "argcount" > 0 always create a new type, so that arguments can be added.
+ */
+ static type_T *
+ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
+ {
+ type_T *type;
+
+ // recognize commonly used types
+ if (argcount <= 0)
+ {
+ if (ret_type == &t_void)
+ {
+ if (argcount == 0)
+ return &t_func_0_void;
+ else
+ return &t_func_void;
+ }
+ if (ret_type == &t_any)
+ {
+ if (argcount == 0)
+ return &t_func_0_any;
+ else
+ return &t_func_any;
+ }
+ if (ret_type == &t_number)
+ {
+ if (argcount == 0)
+ return &t_func_0_number;
+ else
+ return &t_func_number;
+ }
+ if (ret_type == &t_string)
+ {
+ if (argcount == 0)
+ return &t_func_0_string;
+ else
+ return &t_func_string;
+ }
+ }
+
+ // Not a common type or has arguments, create a new entry.
+ if (ga_grow(type_gap, 1) == FAIL)
+ return &t_any;
+ type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
+ ++type_gap->ga_len;
+ type->tt_type = VAR_FUNC;
+ type->tt_member = ret_type;
+ type->tt_args = NULL;
return type;
}
***************
*** 774,781 ****
isn_T *isn;
RETURN_OK_IF_SKIP(cctx);
! if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL,
! &t_partial_any)) == NULL)
return FAIL;
isn->isn_arg.partial = part;
--- 832,838 ----
isn_T *isn;
RETURN_OK_IF_SKIP(cctx);
! if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL, &t_func_any)) == NULL)
return FAIL;
isn->isn_arg.partial = part;
***************
*** 942,948 ****
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
- garray_T *type_list = cctx->ctx_type_list;
type_T *type;
type_T *member;
--- 999,1004 ----
***************
*** 960,966 ****
member = ((type_T **)stack->ga_data)[stack->ga_len];
else
member = &t_void;
! type = get_list_type(member, type_list);
// add the list type to the type stack
if (ga_grow(stack, 1) == FAIL)
--- 1016,1022 ----
member = ((type_T **)stack->ga_data)[stack->ga_len];
else
member = &t_void;
! type = get_list_type(member, cctx->ctx_type_list);
// add the list type to the type stack
if (ga_grow(stack, 1) == FAIL)
***************
*** 979,985 ****
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
- garray_T *type_list = cctx->ctx_type_list;
type_T *type;
type_T *member;
--- 1035,1040 ----
***************
*** 997,1003 ****
member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
else
member = &t_void;
! type = get_dict_type(member, type_list);
// add the dict type to the type stack
if (ga_grow(stack, 1) == FAIL)
--- 1052,1058 ----
member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
else
member = &t_void;
! type = get_dict_type(member, cctx->ctx_type_list);
// add the dict type to the type stack
if (ga_grow(stack, 1) == FAIL)
***************
*** 1024,1030 ****
if (ga_grow(stack, 1) == FAIL)
return FAIL;
! ((type_T **)stack->ga_data)[stack->ga_len] = &t_partial_any;
// TODO: argument and return types
++stack->ga_len;
--- 1079,1085 ----
if (ga_grow(stack, 1) == FAIL)
return FAIL;
! ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
// TODO: argument and return types
++stack->ga_len;
***************
*** 1298,1303 ****
--- 1353,1360 ----
static char e_white_both[] =
N_("E1004: white space required before and after '%s'");
+ static char e_white_after[] = N_("E1069: white space required after '%s'");
+ static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
/*
* Reserve space for a local variable.
***************
*** 1385,1395 ****
/*
* Parse the member type: "<type>" and return "type" with the member set.
! * Use "type_list" if a new type needs to be added.
* Returns NULL in case of failure.
*/
static type_T *
! parse_type_member(char_u **arg, type_T *type, garray_T *type_list)
{
type_T *member_type;
int prev_called_emsg = called_emsg;
--- 1442,1452 ----
/*
* Parse the member type: "<type>" and return "type" with the member set.
! * Use "type_gap" if a new type needs to be added.
* Returns NULL in case of failure.
*/
static type_T *
! parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
{
type_T *member_type;
int prev_called_emsg = called_emsg;
***************
*** 1397,1410 ****
if (**arg != '<')
{
if (*skipwhite(*arg) == '<')
! emsg(_("E1007: No white space allowed before <"));
else
emsg(_("E1008: Missing <type>"));
return type;
}
*arg = skipwhite(*arg + 1);
! member_type = parse_type(arg, type_list);
*arg = skipwhite(*arg);
if (**arg != '>' && called_emsg == prev_called_emsg)
--- 1454,1467 ----
if (**arg != '<')
{
if (*skipwhite(*arg) == '<')
! semsg(_(e_no_white_before), "<");
else
emsg(_("E1008: Missing <type>"));
return type;
}
*arg = skipwhite(*arg + 1);
! member_type = parse_type(arg, type_gap);
*arg = skipwhite(*arg);
if (**arg != '>' && called_emsg == prev_called_emsg)
***************
*** 1415,1422 ****
++*arg;
if (type->tt_type == VAR_LIST)
! return get_list_type(member_type, type_list);
! return get_dict_type(member_type, type_list);
}
/*
--- 1472,1479 ----
++*arg;
if (type->tt_type == VAR_LIST)
! return get_list_type(member_type, type_gap);
! return get_dict_type(member_type, type_gap);
}
/*
***************
*** 1424,1430 ****
* Return &t_any for failure.
*/
type_T *
! parse_type(char_u **arg, garray_T *type_list)
{
char_u *p = *arg;
size_t len;
--- 1481,1487 ----
* Return &t_any for failure.
*/
type_T *
! parse_type(char_u **arg, garray_T *type_gap)
{
char_u *p = *arg;
size_t len;
***************
*** 1466,1472 ****
if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
{
*arg += len;
! return parse_type_member(arg, &t_dict_any, type_list);
}
break;
case 'f':
--- 1523,1529 ----
if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
{
*arg += len;
! return parse_type_member(arg, &t_dict_any, type_gap);
}
break;
case 'f':
***************
*** 1482,1490 ****
}
if (len == 4 && STRNCMP(*arg, "func", len) == 0)
{
*arg += len;
! // TODO: arguments and return type
! return &t_func_any;
}
break;
case 'j':
--- 1539,1623 ----
}
if (len == 4 && STRNCMP(*arg, "func", len) == 0)
{
+ type_T *type;
+ type_T *ret_type = &t_void;
+ int argcount = -1;
+ int flags = 0;
+ type_T *arg_type[MAX_FUNC_ARGS + 1];
+
+ // func({type}, ...): {type}
*arg += len;
! if (**arg == '(')
! {
! p = ++*arg;
! argcount = 0;
! while (*p != NUL && *p != ')')
! {
! if (STRNCMP(p, "...", 3) == 0)
! {
! flags |= TTFLAG_VARARGS;
! break;
! }
! arg_type[argcount++] = parse_type(&p, type_gap);
!
! if (*p != ',' && *skipwhite(p) == ',')
! {
! semsg(_(e_no_white_before), ",");
! return &t_any;
! }
! if (*p == ',')
! {
! ++p;
! if (!VIM_ISWHITE(*p))
! semsg(_(e_white_after), ",");
! }
! p = skipwhite(p);
! if (argcount == MAX_FUNC_ARGS)
! {
! emsg(_("E740: Too many argument types"));
! return &t_any;
! }
! }
!
! p = skipwhite(p);
! if (*p != ')')
! {
! emsg(_(e_missing_close));
! return &t_any;
! }
! *arg = p + 1;
! }
! if (**arg == ':')
! {
! // parse return type
! ++*arg;
! if (!VIM_ISWHITE(*p))
! semsg(_(e_white_after), ":");
! *arg = skipwhite(*arg);
! ret_type = parse_type(arg, type_gap);
! }
! type = get_func_type(ret_type, flags == 0 ? argcount : 99,
! type_gap);
! if (flags != 0)
! type->tt_flags = flags;
! if (argcount > 0)
! {
! int type_ptr_cnt = (sizeof(type_T *) * argcount
! + sizeof(type_T) - 1) / sizeof(type_T);
!
! type->tt_argcount = argcount;
! // Get space from "type_gap" to avoid having to keep track
! // of the pointer and freeing it.
! ga_grow(type_gap, type_ptr_cnt);
! if (ga_grow(type_gap, type_ptr_cnt) == FAIL)
! return &t_any;
! type->tt_args =
! ((type_T **)type_gap->ga_data) + type_gap->ga_len;
! type_gap->ga_len += type_ptr_cnt;
! mch_memmove(type->tt_args, arg_type,
! sizeof(type_T *) * argcount);
! }
! return type;
}
break;
case 'j':
***************
*** 1498,1504 ****
if (len == 4 && STRNCMP(*arg, "list", len) == 0)
{
*arg += len;
! return parse_type_member(arg, &t_list_any, type_list);
}
break;
case 'n':
--- 1631,1637 ----
if (len == 4 && STRNCMP(*arg, "list", len) == 0)
{
*arg += len;
! return parse_type_member(arg, &t_list_any, type_gap);
}
break;
case 'n':
***************
*** 1508,1521 ****
return &t_number;
}
break;
- case 'p':
- if (len == 7 && STRNCMP(*arg, "partial", len) == 0)
- {
- *arg += len;
- // TODO: arguments and return type
- return &t_partial_any;
- }
- break;
case 's':
if (len == 6 && STRNCMP(*arg, "string", len) == 0)
{
--- 1641,1646 ----
***************
*** 1574,1580 ****
* "type2" and "dest" may be the same.
*/
static void
! common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_list)
{
if (equal_type(type1, type2))
{
--- 1699,1705 ----
* "type2" and "dest" may be the same.
*/
static void
! common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
{
if (equal_type(type1, type2))
{
***************
*** 1588,1598 ****
{
type_T *common;
! common_type(type1->tt_member, type2->tt_member, &common, type_list);
if (type1->tt_type == VAR_LIST)
! *dest = get_list_type(common, type_list);
else
! *dest = get_dict_type(common, type_list);
return;
}
// TODO: VAR_FUNC and VAR_PARTIAL
--- 1713,1723 ----
{
type_T *common;
! common_type(type1->tt_member, type2->tt_member, &common, type_gap);
if (type1->tt_type == VAR_LIST)
! *dest = get_list_type(common, type_gap);
else
! *dest = get_dict_type(common, type_gap);
return;
}
// TODO: VAR_FUNC and VAR_PARTIAL
***************
*** 1962,1975 ****
if (*p != ',' && *skipwhite(p) == ',')
{
! emsg(_("E1068: No white space allowed before ,"));
p = skipwhite(p);
}
if (*p == ',')
{
++p;
if (!VIM_ISWHITE(*p))
! emsg(_("E1069: white space required after ,"));
}
p = skipwhite(p);
}
--- 2087,2100 ----
if (*p != ',' && *skipwhite(p) == ',')
{
! semsg(_(e_no_white_before), ",");
p = skipwhite(p);
}
if (*p == ',')
{
++p;
if (!VIM_ISWHITE(*p))
! semsg(_(e_white_after), ",");
}
p = skipwhite(p);
}
*** ../vim-8.2.0507/src/globals.h 2020-04-02 18:50:42.419773128 +0200
--- src/globals.h 2020-04-03 21:31:30.596059891 +0200
***************
*** 379,414 ****
// Commonly used types.
! EXTERN type_T t_any INIT4(VAR_UNKNOWN, 0, NULL, NULL);
! EXTERN type_T t_void INIT4(VAR_VOID, 0, NULL, NULL);
! EXTERN type_T t_bool INIT4(VAR_BOOL, 0, NULL, NULL);
! EXTERN type_T t_special INIT4(VAR_SPECIAL, 0, NULL, NULL);
! EXTERN type_T t_number INIT4(VAR_NUMBER, 0, NULL, NULL);
! EXTERN type_T t_float INIT4(VAR_FLOAT, 0, NULL, NULL);
! EXTERN type_T t_string INIT4(VAR_STRING, 0, NULL, NULL);
! EXTERN type_T t_blob INIT4(VAR_BLOB, 0, NULL, NULL);
! EXTERN type_T t_job INIT4(VAR_JOB, 0, NULL, NULL);
! EXTERN type_T t_channel INIT4(VAR_CHANNEL, 0, NULL, NULL);
!
! EXTERN type_T t_func_void INIT4(VAR_FUNC, -1, &t_void, NULL);
! EXTERN type_T t_func_any INIT4(VAR_FUNC, -1, &t_any, NULL);
!
! EXTERN type_T t_partial_void INIT4(VAR_PARTIAL, -1, &t_void, NULL);
! EXTERN type_T t_partial_any INIT4(VAR_PARTIAL, -1, &t_any, NULL);
!
! EXTERN type_T t_list_any INIT4(VAR_LIST, 0, &t_any, NULL);
! EXTERN type_T t_dict_any INIT4(VAR_DICT, 0, &t_any, NULL);
! EXTERN type_T t_list_empty INIT4(VAR_LIST, 0, &t_void, NULL);
! EXTERN type_T t_dict_empty INIT4(VAR_DICT, 0, &t_void, NULL);
!
! EXTERN type_T t_list_bool INIT4(VAR_LIST, 0, &t_bool, NULL);
! EXTERN type_T t_list_number INIT4(VAR_LIST, 0, &t_number, NULL);
! EXTERN type_T t_list_string INIT4(VAR_LIST, 0, &t_string, NULL);
! EXTERN type_T t_list_dict_any INIT4(VAR_LIST, 0, &t_dict_any, NULL);
!
! EXTERN type_T t_dict_bool INIT4(VAR_DICT, 0, &t_bool, NULL);
! EXTERN type_T t_dict_number INIT4(VAR_DICT, 0, &t_number, NULL);
! EXTERN type_T t_dict_string INIT4(VAR_DICT, 0, &t_string, NULL);
#endif
--- 379,417 ----
// Commonly used types.
! EXTERN type_T t_any INIT5(VAR_UNKNOWN, 0, 0, NULL, NULL);
! EXTERN type_T t_void INIT5(VAR_VOID, 0, 0, NULL, NULL);
! EXTERN type_T t_bool INIT5(VAR_BOOL, 0, 0, NULL, NULL);
! EXTERN type_T t_special INIT5(VAR_SPECIAL, 0, 0, NULL, NULL);
! EXTERN type_T t_number INIT5(VAR_NUMBER, 0, 0, NULL, NULL);
! EXTERN type_T t_float INIT5(VAR_FLOAT, 0, 0, NULL, NULL);
! EXTERN type_T t_string INIT5(VAR_STRING, 0, 0, NULL, NULL);
! EXTERN type_T t_blob INIT5(VAR_BLOB, 0, 0, NULL, NULL);
! EXTERN type_T t_job INIT5(VAR_JOB, 0, 0, NULL, NULL);
! EXTERN type_T t_channel INIT5(VAR_CHANNEL, 0, 0, NULL, NULL);
!
! EXTERN type_T t_func_void INIT5(VAR_FUNC, -1, 0, &t_void, NULL);
! EXTERN type_T t_func_any INIT5(VAR_FUNC, -1, 0, &t_any, NULL);
! EXTERN type_T t_func_number INIT5(VAR_FUNC, -1, 0, &t_number, NULL);
! EXTERN type_T t_func_string INIT5(VAR_FUNC, -1, 0, &t_string, NULL);
! EXTERN type_T t_func_0_void INIT5(VAR_FUNC, 0, 0, &t_void, NULL);
! EXTERN type_T t_func_0_any INIT5(VAR_FUNC, 0, 0, &t_any, NULL);
! EXTERN type_T t_func_0_number INIT5(VAR_FUNC, 0, 0, &t_number, NULL);
! EXTERN type_T t_func_0_string INIT5(VAR_FUNC, 0, 0, &t_string, NULL);
!
! EXTERN type_T t_list_any INIT5(VAR_LIST, 0, 0, &t_any, NULL);
! EXTERN type_T t_dict_any INIT5(VAR_DICT, 0, 0, &t_any, NULL);
! EXTERN type_T t_list_empty INIT5(VAR_LIST, 0, 0, &t_void, NULL);
! EXTERN type_T t_dict_empty INIT5(VAR_DICT, 0, 0, &t_void, NULL);
!
! EXTERN type_T t_list_bool INIT5(VAR_LIST, 0, 0, &t_bool, NULL);
! EXTERN type_T t_list_number INIT5(VAR_LIST, 0, 0, &t_number, NULL);
! EXTERN type_T t_list_string INIT5(VAR_LIST, 0, 0, &t_string, NULL);
! EXTERN type_T t_list_dict_any INIT5(VAR_LIST, 0, 0, &t_dict_any, NULL);
!
! EXTERN type_T t_dict_bool INIT5(VAR_DICT, 0, 0, &t_bool, NULL);
! EXTERN type_T t_dict_number INIT5(VAR_DICT, 0, 0, &t_number, NULL);
! EXTERN type_T t_dict_string INIT5(VAR_DICT, 0, 0, &t_string, NULL);
#endif
*** ../vim-8.2.0507/src/structs.h 2020-03-26 20:33:20.995063766 +0100
--- src/structs.h 2020-04-03 21:20:22.703051055 +0200
***************
*** 1342,1351 ****
struct type_S {
vartype_T tt_type;
short tt_argcount; // for func, partial, -1 for unknown
type_T *tt_member; // for list, dict, func return type
! type_T *tt_args; // func arguments
};
/*
* Structure to hold an internal variable without a name.
*/
--- 1342,1355 ----
struct type_S {
vartype_T tt_type;
short tt_argcount; // for func, partial, -1 for unknown
+ short tt_flags; // TTFLAG_ values
type_T *tt_member; // for list, dict, func return type
! type_T **tt_args; // func arguments, allocated
};
+ #define TTFLAG_VARARGS 1 // func args ends with "..."
+ #define TTFLAG_OPTARG 2 // func arg type with "?"
+
/*
* Structure to hold an internal variable without a name.
*/
*** ../vim-8.2.0507/src/evalfunc.c 2020-04-02 18:50:42.419773128 +0200
--- src/evalfunc.c 2020-04-03 21:14:25.256444458 +0200
***************
*** 336,346 ****
return &t_func_any;
}
static type_T *
- ret_partial_any(int argcount UNUSED, type_T **argtypes UNUSED)
- {
- return &t_partial_any;
- }
- static type_T *
ret_channel(int argcount UNUSED, type_T **argtypes UNUSED)
{
return &t_channel;
--- 336,341 ----
***************
*** 564,570 ****
{"foldtext", 0, 0, 0, ret_string, f_foldtext},
{"foldtextresult", 1, 1, FEARG_1, ret_string, f_foldtextresult},
{"foreground", 0, 0, 0, ret_void, f_foreground},
! {"funcref", 1, 3, FEARG_1, ret_partial_any, f_funcref},
{"function", 1, 3, FEARG_1, ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, ret_void, f_garbagecollect},
{"get", 2, 3, FEARG_1, ret_any, f_get},
--- 559,565 ----
{"foldtext", 0, 0, 0, ret_string, f_foldtext},
{"foldtextresult", 1, 1, FEARG_1, ret_string, f_foldtextresult},
{"foreground", 0, 0, 0, ret_void, f_foreground},
! {"funcref", 1, 3, FEARG_1, ret_func_any, f_funcref},
{"function", 1, 3, FEARG_1, ret_f_function, f_function},
{"garbagecollect", 0, 1, 0, ret_void, f_garbagecollect},
{"get", 2, 3, FEARG_1, ret_any, f_get},
***************
*** 961,967 ****
{"test_null_function", 0, 0, 0, ret_func_any, f_test_null_function},
{"test_null_job", 0, 0, 0, ret_job, JOB_FUNC(f_test_null_job)},
{"test_null_list", 0, 0, 0, ret_list_any, f_test_null_list},
! {"test_null_partial", 0, 0, 0, ret_partial_any, f_test_null_partial},
{"test_null_string", 0, 0, 0, ret_string, f_test_null_string},
{"test_option_not_set", 1, 1, FEARG_1,ret_void, f_test_option_not_set},
{"test_override", 2, 2, FEARG_2, ret_void, f_test_override},
--- 956,962 ----
{"test_null_function", 0, 0, 0, ret_func_any, f_test_null_function},
{"test_null_job", 0, 0, 0, ret_job, JOB_FUNC(f_test_null_job)},
{"test_null_list", 0, 0, 0, ret_list_any, f_test_null_list},
! {"test_null_partial", 0, 0, 0, ret_func_any, f_test_null_partial},
{"test_null_string", 0, 0, 0, ret_string, f_test_null_string},
{"test_option_not_set", 1, 1, FEARG_1,ret_void, f_test_option_not_set},
{"test_override", 2, 2, FEARG_2, ret_void, f_test_override},
***************
*** 2902,2908 ****
{
if (argcount == 1 && argtypes[0]->tt_type == VAR_STRING)
return &t_func_any;
! return &t_partial_void;
}
/*
--- 2897,2903 ----
{
if (argcount == 1 && argtypes[0]->tt_type == VAR_STRING)
return &t_func_any;
! return &t_func_void;
}
/*
*** ../vim-8.2.0507/src/testdir/test_vim9_expr.vim 2020-04-01 21:17:17.268409971 +0200
--- src/testdir/test_vim9_expr.vim 2020-04-03 21:41:49.053439350 +0200
***************
*** 461,467 ****
call CheckDefFailureMult(['let j: job', 'let chan: channel', 'let r = j == chan'], 'Cannot compare job with channel')
call CheckDefFailureMult(['let j: job', 'let x: list<any>', 'let r = j == x'], 'Cannot compare job with list')
call CheckDefFailureMult(['let j: job', 'let x: func', 'let r = j == x'], 'Cannot compare job with func')
! call CheckDefFailureMult(['let j: job', 'let x: partial', 'let r = j == x'], 'Cannot compare job with partial')
endfunc
" test addition, subtraction, concatenation
--- 461,467 ----
call CheckDefFailureMult(['let j: job', 'let chan: channel', 'let r = j == chan'], 'Cannot compare job with channel')
call CheckDefFailureMult(['let j: job', 'let x: list<any>', 'let r = j == x'], 'Cannot compare job with list')
call CheckDefFailureMult(['let j: job', 'let x: func', 'let r = j == x'], 'Cannot compare job with func')
! call CheckDefFailureMult(['let j: job', 'let x: func', 'let r = j == x'], 'Cannot compare job with func')
endfunc
" test addition, subtraction, concatenation
*** ../vim-8.2.0507/src/testdir/test_vim9_script.vim 2020-04-02 22:33:17.868287352 +0200
--- src/testdir/test_vim9_script.vim 2020-04-03 21:43:59.008901654 +0200
***************
*** 68,75 ****
endif
let funky1: func
let funky2: func = function('len')
! let party1: partial
! let party2: partial = funcref('Test_syntax')
" type becomes list<any>
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
--- 68,74 ----
endif
let funky1: func
let funky2: func = function('len')
! let party2: func = funcref('Test_syntax')
" type becomes list<any>
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
***************
*** 157,165 ****
let thefunc: func
assert_equal(test_null_function(), thefunc)
- let thepartial: partial
- assert_equal(test_null_partial(), thepartial)
-
let thelist: list<any>
assert_equal([], thelist)
--- 156,161 ----
***************
*** 213,219 ****
call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
! call CheckDefFailure(['let var: dict <number>'], 'E1007:')
call CheckDefFailure(['let var: dict<number'], 'E1009:')
endfunc
--- 209,215 ----
call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
! call CheckDefFailure(['let var: dict <number>'], 'E1068:')
call CheckDefFailure(['let var: dict<number'], 'E1009:')
endfunc
*** ../vim-8.2.0507/src/testdir/test_vim9_disassemble.vim 2020-04-02 21:13:21.396362396 +0200
--- src/testdir/test_vim9_disassemble.vim 2020-04-03 21:49:34.439523652 +0200
***************
*** 362,369 ****
def WithFunc()
let funky1: func
let funky2: func = function("len")
! let party1: partial
! let party2: partial = funcref("UserFunc")
enddef
def Test_disassemble_function()
--- 362,368 ----
def WithFunc()
let funky1: func
let funky2: func = function("len")
! let party2: func = funcref("UserFunc")
enddef
def Test_disassemble_function()
***************
*** 376,390 ****
\ .. '2 PUSHS "len".*'
\ .. '3 BCALL function(argc 1).*'
\ .. '4 STORE $1.*'
! \ .. 'let party1: partial.*'
! \ .. '5 PUSHPARTIAL "\[none]".*'
! \ .. '6 STORE $2.*'
! \ .. 'let party2: partial = funcref("UserFunc").*'
! \ .. '7 PUSHS "UserFunc".*'
! \ .. '8 BCALL funcref(argc 1).*'
! \ .. '9 STORE $3.*'
! \ .. '10 PUSHNR 0.*'
! \ .. '11 RETURN.*'
\, instr)
enddef
--- 375,386 ----
\ .. '2 PUSHS "len".*'
\ .. '3 BCALL function(argc 1).*'
\ .. '4 STORE $1.*'
! \ .. 'let party2: func = funcref("UserFunc").*'
! \ .. '\d PUSHS "UserFunc".*'
! \ .. '\d BCALL funcref(argc 1).*'
! \ .. '\d STORE $2.*'
! \ .. '\d PUSHNR 0.*'
! \ .. '\d RETURN.*'
\, instr)
enddef
***************
*** 753,762 ****
\ ['#{a:1} is #{x:2}', 'COMPAREDICT is'],
\ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'],
\
! \ ['{->33} == {->44}', 'COMPAREPARTIAL =='],
! \ ['{->33} != {->44}', 'COMPAREPARTIAL !='],
! \ ['{->33} is {->44}', 'COMPAREPARTIAL is'],
! \ ['{->33} isnot {->44}', 'COMPAREPARTIAL isnot'],
\
\ ['77 == g:xx', 'COMPAREANY =='],
\ ['77 != g:xx', 'COMPAREANY !='],
--- 749,758 ----
\ ['#{a:1} is #{x:2}', 'COMPAREDICT is'],
\ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'],
\
! \ ['{->33} == {->44}', 'COMPAREFUNC =='],
! \ ['{->33} != {->44}', 'COMPAREFUNC !='],
! \ ['{->33} is {->44}', 'COMPAREFUNC is'],
! \ ['{->33} isnot {->44}', 'COMPAREFUNC isnot'],
\
\ ['77 == g:xx', 'COMPAREANY =='],
\ ['77 != g:xx', 'COMPAREANY !='],
*** ../vim-8.2.0507/src/version.c 2020-04-03 18:43:31.886980756 +0200
--- src/version.c 2020-04-03 21:49:54.083443302 +0200
***************
*** 740,741 ****
--- 740,743 ----
{ /* Add new patch number below this line */
+ /**/
+ 508,
/**/
--
ARTHUR: No, hang on! Just answer the five questions ...
GALAHAD: Three questions ...
ARTHUR: Three questions ... And we shall watch ... and pray.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language --
http://www.Zimbu.org ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///