Mercurial > vim
diff src/vim9type.c @ 22284:6b385c2b9ff5 v8.2.1691
patch 8.2.1691: Vim9: list<any> is not accepted where list<number> is expected
Commit: https://github.com/vim/vim/commit/5e654230777ad21363a929dce3cfe0387da031a7
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 16 15:22:00 2020 +0200
patch 8.2.1691: Vim9: list<any> is not accepted where list<number> is expected
Problem: Vim9: list<any> is not accepted where list<number> is expected.
Solution: Add functions to allocate and free a type_T, use it in
ISN_CHECKTYPE. (closes #6959)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 16 Sep 2020 15:30:07 +0200 |
parents | 7899b4e2880c |
children | a5b16c9eee9d |
line wrap: on
line diff
--- a/src/vim9type.c +++ b/src/vim9type.c @@ -22,10 +22,10 @@ /* * Allocate memory for a type_T and add the pointer to type_gap, so that it can - * be freed later. + * be easily freed later. */ type_T * -alloc_type(garray_T *type_gap) +get_type_ptr(garray_T *type_gap) { type_T *type; @@ -48,6 +48,60 @@ clear_type_list(garray_T *gap) ga_clear(gap); } +/* + * Take a type that is using entries in a growarray and turn it into a type + * with allocated entries. + */ + type_T * +alloc_type(type_T *type) +{ + type_T *ret; + + if (type == NULL) + return NULL; + + // A fixed type never contains allocated types, return as-is. + if (type->tt_flags & TTFLAG_STATIC) + return type; + + ret = ALLOC_ONE(type_T); + *ret = *type; + + if (ret->tt_member != NULL) + ret->tt_member = alloc_type(ret->tt_member); + if (type->tt_args != NULL) + { + int i; + + ret->tt_args = ALLOC_MULT(type_T *, type->tt_argcount); + if (ret->tt_args != NULL) + for (i = 0; i < type->tt_argcount; ++i) + ret->tt_args[i] = alloc_type(type->tt_args[i]); + } + + return ret; +} + +/* + * Free a type that was created with alloc_type(). + */ + void +free_type(type_T *type) +{ + int i; + + if (type == NULL || (type->tt_flags & TTFLAG_STATIC)) + return; + if (type->tt_args != NULL) + { + for (i = 0; i < type->tt_argcount; ++i) + free_type(type->tt_args[i]); + vim_free(type->tt_args); + } + free_type(type->tt_member); + vim_free(type); +} + type_T * get_list_type(type_T *member_type, garray_T *type_gap) { @@ -67,7 +121,7 @@ get_list_type(type_T *member_type, garra return &t_list_string; // Not a common type, create a new entry. - type = alloc_type(type_gap); + type = get_type_ptr(type_gap); if (type == NULL) return &t_any; type->tt_type = VAR_LIST; @@ -96,7 +150,7 @@ get_dict_type(type_T *member_type, garra return &t_dict_string; // Not a common type, create a new entry. - type = alloc_type(type_gap); + type = get_type_ptr(type_gap); if (type == NULL) return &t_any; type->tt_type = VAR_DICT; @@ -112,7 +166,7 @@ get_dict_type(type_T *member_type, garra type_T * alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) { - type_T *type = alloc_type(type_gap); + type_T *type = get_type_ptr(type_gap); if (type == NULL) return &t_any; @@ -197,13 +251,14 @@ func_type_add_arg_types( /* * Get a type_T for a typval_T. - * "type_list" is used to temporarily create types in. + * "type_gap" is used to temporarily create types in. */ static type_T * typval2type_int(typval_T *tv, garray_T *type_gap) { type_T *type; - type_T *member_type; + type_T *member_type = &t_any; + int argcount = 0; if (tv->v_type == VAR_NUMBER) return &t_number; @@ -262,8 +317,18 @@ typval2type_int(typval_T *tv, garray_T * else name = tv->vval.v_string; if (name != NULL) - // TODO: how about a builtin function? - ufunc = find_func(name, FALSE, NULL); + { + int idx = find_internal_func(name); + + if (idx >= 0) + { + // TODO: get actual arg count and types + argcount = -1; + member_type = internal_func_ret_type(idx, 0, NULL); + } + else + ufunc = find_func(name, FALSE, NULL); + } if (ufunc != NULL) { // May need to get the argument types from default values by @@ -276,11 +341,12 @@ typval2type_int(typval_T *tv, garray_T * } } - type = alloc_type(type_gap); + type = get_type_ptr(type_gap); if (type == NULL) return NULL; type->tt_type = tv->v_type; - type->tt_member = &t_any; + type->tt_argcount = argcount; + type->tt_member = member_type; return type; } @@ -311,7 +377,7 @@ typval2type(typval_T *tv, garray_T *type && (tv->vval.v_number == 0 || tv->vval.v_number == 1)) || (tv->v_lock & VAR_BOOL_OK))) { - type_T *newtype = alloc_type(type_gap); + type_T *newtype = get_type_ptr(type_gap); // Number 0 and 1 and expression with "&&" or "||" can also be used // for bool. @@ -420,6 +486,7 @@ check_type(type_T *expected, type_T *act ret = check_type(expected->tt_member, actual->tt_member, FALSE, 0); if (ret == OK && expected->tt_argcount != -1 + && actual->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount || actual->tt_argcount > expected->tt_argcount)) ret = FAIL; @@ -940,7 +1007,6 @@ type_name(type_T *type, char **tofree) ga_init2(&ga, 1, 100); if (ga_grow(&ga, 20) == FAIL) return "[unknown]"; - *tofree = ga.ga_data; STRCPY(ga.ga_data, "func("); ga.ga_len += 5; @@ -963,20 +1029,19 @@ type_name(type_T *type, char **tofree) if (ga_grow(&ga, len + 8) == FAIL) { vim_free(arg_free); + ga_clear(&ga); return "[unknown]"; } - *tofree = ga.ga_data; if (varargs && i == type->tt_argcount - 1) - { - STRCPY((char *)ga.ga_data + ga.ga_len, "..."); - ga.ga_len += 3; - } + ga_concat(&ga, (char_u *)"..."); else if (i >= type->tt_min_argcount) *((char *)ga.ga_data + ga.ga_len++) = '?'; - STRCPY((char *)ga.ga_data + ga.ga_len, arg_type); - ga.ga_len += len; + ga_concat(&ga, (char_u *)arg_type); vim_free(arg_free); } + if (type->tt_argcount < 0) + // any number of arguments + ga_concat(&ga, (char_u *)"..."); if (type->tt_member == &t_void) STRCPY((char *)ga.ga_data + ga.ga_len, ")"); @@ -990,18 +1055,18 @@ type_name(type_T *type, char **tofree) if (ga_grow(&ga, len) == FAIL) { vim_free(ret_free); + ga_clear(&ga); return "[unknown]"; } - *tofree = ga.ga_data; STRCPY((char *)ga.ga_data + ga.ga_len, "): "); STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); vim_free(ret_free); } + *tofree = ga.ga_data; return ga.ga_data; } return name; } - #endif // FEAT_EVAL