Mercurial > vim
comparison src/vim9compile.c @ 19942:b471038ec3ea v8.2.0527
patch 8.2.0527: Vim9: function types insufficiently tested
Commit: https://github.com/vim/vim/commit/ec5929d0fe7e90f953fa5b019486c0c4e5826d92
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 7 20:53:39 2020 +0200
patch 8.2.0527: Vim9: function types insufficiently tested
Problem: Vim9: function types insufficiently tested.
Solution: Add more tests. Fix white space check. Add "test_vim9" target.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 07 Apr 2020 21:00:04 +0200 |
parents | 3ff714d765ba |
children | 3055cd26e139 |
comparison
equal
deleted
inserted
replaced
19941:e0542f0c06d7 | 19942:b471038ec3ea |
---|---|
312 type_T *type; | 312 type_T *type; |
313 | 313 |
314 // recognize commonly used types | 314 // recognize commonly used types |
315 if (argcount <= 0) | 315 if (argcount <= 0) |
316 { | 316 { |
317 if (ret_type == &t_unknown) | |
318 { | |
319 // (argcount == 0) is not possible | |
320 return &t_func_unknown; | |
321 } | |
317 if (ret_type == &t_void) | 322 if (ret_type == &t_void) |
318 { | 323 { |
319 if (argcount == 0) | 324 if (argcount == 0) |
320 return &t_func_0_void; | 325 return &t_func_0_void; |
321 else | 326 else |
348 type = alloc_type(type_gap); | 353 type = alloc_type(type_gap); |
349 if (type == NULL) | 354 if (type == NULL) |
350 return &t_any; | 355 return &t_any; |
351 type->tt_type = VAR_FUNC; | 356 type->tt_type = VAR_FUNC; |
352 type->tt_member = ret_type; | 357 type->tt_member = ret_type; |
358 type->tt_argcount = argcount; | |
353 type->tt_args = NULL; | 359 type->tt_args = NULL; |
354 return type; | 360 return type; |
355 } | 361 } |
356 | 362 |
357 /* | 363 /* |
1587 #endif | 1593 #endif |
1588 } | 1594 } |
1589 if (len == 4 && STRNCMP(*arg, "func", len) == 0) | 1595 if (len == 4 && STRNCMP(*arg, "func", len) == 0) |
1590 { | 1596 { |
1591 type_T *type; | 1597 type_T *type; |
1592 type_T *ret_type = &t_any; | 1598 type_T *ret_type = &t_unknown; |
1593 int argcount = -1; | 1599 int argcount = -1; |
1594 int flags = 0; | 1600 int flags = 0; |
1595 int first_optional = -1; | 1601 int first_optional = -1; |
1596 type_T *arg_type[MAX_FUNC_ARGS + 1]; | 1602 type_T *arg_type[MAX_FUNC_ARGS + 1]; |
1597 | 1603 |
1655 } | 1661 } |
1656 if (**arg == ':') | 1662 if (**arg == ':') |
1657 { | 1663 { |
1658 // parse return type | 1664 // parse return type |
1659 ++*arg; | 1665 ++*arg; |
1660 if (!VIM_ISWHITE(*p)) | 1666 if (!VIM_ISWHITE(**arg)) |
1661 semsg(_(e_white_after), ":"); | 1667 semsg(_(e_white_after), ":"); |
1662 *arg = skipwhite(*arg); | 1668 *arg = skipwhite(*arg); |
1663 ret_type = parse_type(arg, type_gap); | 1669 ret_type = parse_type(arg, type_gap); |
1664 } | 1670 } |
1665 type = get_func_type(ret_type, | 1671 type = get_func_type(ret_type, |
2403 static int | 2409 static int |
2404 check_type(type_T *expected, type_T *actual, int give_msg) | 2410 check_type(type_T *expected, type_T *actual, int give_msg) |
2405 { | 2411 { |
2406 int ret = OK; | 2412 int ret = OK; |
2407 | 2413 |
2408 if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY) | 2414 // When expected is "unknown" we accept any actual type. |
2415 // When expected is "any" we accept any actual type except "void". | |
2416 if (expected->tt_type != VAR_UNKNOWN | |
2417 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID)) | |
2409 { | 2418 { |
2410 if (expected->tt_type != actual->tt_type) | 2419 if (expected->tt_type != actual->tt_type) |
2411 { | 2420 { |
2412 if (give_msg) | 2421 if (give_msg) |
2413 type_mismatch(expected, actual); | 2422 type_mismatch(expected, actual); |
2419 if (actual->tt_member != &t_unknown) | 2428 if (actual->tt_member != &t_unknown) |
2420 ret = check_type(expected->tt_member, actual->tt_member, FALSE); | 2429 ret = check_type(expected->tt_member, actual->tt_member, FALSE); |
2421 } | 2430 } |
2422 else if (expected->tt_type == VAR_FUNC) | 2431 else if (expected->tt_type == VAR_FUNC) |
2423 { | 2432 { |
2424 if (expected->tt_member != &t_any | 2433 if (expected->tt_member != &t_unknown) |
2425 && expected->tt_member != &t_unknown) | |
2426 ret = check_type(expected->tt_member, actual->tt_member, FALSE); | 2434 ret = check_type(expected->tt_member, actual->tt_member, FALSE); |
2427 if (ret == OK && expected->tt_argcount != -1 | 2435 if (ret == OK && expected->tt_argcount != -1 |
2428 && (actual->tt_argcount < expected->tt_min_argcount | 2436 && (actual->tt_argcount < expected->tt_min_argcount |
2429 || actual->tt_argcount > expected->tt_argcount)) | 2437 || actual->tt_argcount > expected->tt_argcount)) |
2430 ret = FAIL; | 2438 ret = FAIL; |
4042 if (new_local) | 4050 if (new_local) |
4043 ++cctx->ctx_locals.ga_len; | 4051 ++cctx->ctx_locals.ga_len; |
4044 if (r == FAIL) | 4052 if (r == FAIL) |
4045 goto theend; | 4053 goto theend; |
4046 | 4054 |
4047 stack = &cctx->ctx_type_stack; | 4055 if (cctx->ctx_skip != TRUE) |
4048 stacktype = stack->ga_len == 0 ? &t_void | 4056 { |
4057 stack = &cctx->ctx_type_stack; | |
4058 stacktype = stack->ga_len == 0 ? &t_void | |
4049 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 4059 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
4050 if (idx >= 0 && (is_decl || !has_type)) | 4060 if (idx >= 0 && (is_decl || !has_type)) |
4051 { | |
4052 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
4053 if (new_local && !has_type) | |
4054 { | 4061 { |
4055 if (stacktype->tt_type == VAR_VOID) | 4062 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; |
4063 if (new_local && !has_type) | |
4056 { | 4064 { |
4057 emsg(_("E1031: Cannot use void value")); | 4065 if (stacktype->tt_type == VAR_VOID) |
4066 { | |
4067 emsg(_("E1031: Cannot use void value")); | |
4068 goto theend; | |
4069 } | |
4070 else | |
4071 { | |
4072 // An empty list or dict has a &t_void member, for a | |
4073 // variable that implies &t_any. | |
4074 if (stacktype == &t_list_empty) | |
4075 lvar->lv_type = &t_list_any; | |
4076 else if (stacktype == &t_dict_empty) | |
4077 lvar->lv_type = &t_dict_any; | |
4078 else | |
4079 lvar->lv_type = stacktype; | |
4080 } | |
4081 } | |
4082 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) | |
4058 goto theend; | 4083 goto theend; |
4059 } | |
4060 else | |
4061 { | |
4062 // An empty list or dict has a &t_void member, for a | |
4063 // variable that implies &t_any. | |
4064 if (stacktype == &t_list_empty) | |
4065 lvar->lv_type = &t_list_any; | |
4066 else if (stacktype == &t_dict_empty) | |
4067 lvar->lv_type = &t_dict_any; | |
4068 else | |
4069 lvar->lv_type = stacktype; | |
4070 } | |
4071 } | 4084 } |
4072 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) | 4085 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) |
4073 goto theend; | 4086 goto theend; |
4074 } | 4087 } |
4075 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) | |
4076 goto theend; | |
4077 } | 4088 } |
4078 else if (cmdidx == CMD_const) | 4089 else if (cmdidx == CMD_const) |
4079 { | 4090 { |
4080 emsg(_("E1021: const requires a value")); | 4091 emsg(_("E1021: const requires a value")); |
4081 goto theend; | 4092 goto theend; |