Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
22283:84bd68382a9a | 22284:6b385c2b9ff5 |
---|---|
20 # include <float.h> | 20 # include <float.h> |
21 #endif | 21 #endif |
22 | 22 |
23 /* | 23 /* |
24 * Allocate memory for a type_T and add the pointer to type_gap, so that it can | 24 * Allocate memory for a type_T and add the pointer to type_gap, so that it can |
25 * be freed later. | 25 * be easily freed later. |
26 */ | 26 */ |
27 type_T * | 27 type_T * |
28 alloc_type(garray_T *type_gap) | 28 get_type_ptr(garray_T *type_gap) |
29 { | 29 { |
30 type_T *type; | 30 type_T *type; |
31 | 31 |
32 if (ga_grow(type_gap, 1) == FAIL) | 32 if (ga_grow(type_gap, 1) == FAIL) |
33 return NULL; | 33 return NULL; |
44 clear_type_list(garray_T *gap) | 44 clear_type_list(garray_T *gap) |
45 { | 45 { |
46 while (gap->ga_len > 0) | 46 while (gap->ga_len > 0) |
47 vim_free(((type_T **)gap->ga_data)[--gap->ga_len]); | 47 vim_free(((type_T **)gap->ga_data)[--gap->ga_len]); |
48 ga_clear(gap); | 48 ga_clear(gap); |
49 } | |
50 | |
51 /* | |
52 * Take a type that is using entries in a growarray and turn it into a type | |
53 * with allocated entries. | |
54 */ | |
55 type_T * | |
56 alloc_type(type_T *type) | |
57 { | |
58 type_T *ret; | |
59 | |
60 if (type == NULL) | |
61 return NULL; | |
62 | |
63 // A fixed type never contains allocated types, return as-is. | |
64 if (type->tt_flags & TTFLAG_STATIC) | |
65 return type; | |
66 | |
67 ret = ALLOC_ONE(type_T); | |
68 *ret = *type; | |
69 | |
70 if (ret->tt_member != NULL) | |
71 ret->tt_member = alloc_type(ret->tt_member); | |
72 if (type->tt_args != NULL) | |
73 { | |
74 int i; | |
75 | |
76 ret->tt_args = ALLOC_MULT(type_T *, type->tt_argcount); | |
77 if (ret->tt_args != NULL) | |
78 for (i = 0; i < type->tt_argcount; ++i) | |
79 ret->tt_args[i] = alloc_type(type->tt_args[i]); | |
80 } | |
81 | |
82 return ret; | |
83 } | |
84 | |
85 /* | |
86 * Free a type that was created with alloc_type(). | |
87 */ | |
88 void | |
89 free_type(type_T *type) | |
90 { | |
91 int i; | |
92 | |
93 if (type == NULL || (type->tt_flags & TTFLAG_STATIC)) | |
94 return; | |
95 if (type->tt_args != NULL) | |
96 { | |
97 for (i = 0; i < type->tt_argcount; ++i) | |
98 free_type(type->tt_args[i]); | |
99 vim_free(type->tt_args); | |
100 } | |
101 free_type(type->tt_member); | |
102 vim_free(type); | |
49 } | 103 } |
50 | 104 |
51 type_T * | 105 type_T * |
52 get_list_type(type_T *member_type, garray_T *type_gap) | 106 get_list_type(type_T *member_type, garray_T *type_gap) |
53 { | 107 { |
65 return &t_list_number; | 119 return &t_list_number; |
66 if (member_type->tt_type == VAR_STRING) | 120 if (member_type->tt_type == VAR_STRING) |
67 return &t_list_string; | 121 return &t_list_string; |
68 | 122 |
69 // Not a common type, create a new entry. | 123 // Not a common type, create a new entry. |
70 type = alloc_type(type_gap); | 124 type = get_type_ptr(type_gap); |
71 if (type == NULL) | 125 if (type == NULL) |
72 return &t_any; | 126 return &t_any; |
73 type->tt_type = VAR_LIST; | 127 type->tt_type = VAR_LIST; |
74 type->tt_member = member_type; | 128 type->tt_member = member_type; |
75 type->tt_argcount = 0; | 129 type->tt_argcount = 0; |
94 return &t_dict_number; | 148 return &t_dict_number; |
95 if (member_type->tt_type == VAR_STRING) | 149 if (member_type->tt_type == VAR_STRING) |
96 return &t_dict_string; | 150 return &t_dict_string; |
97 | 151 |
98 // Not a common type, create a new entry. | 152 // Not a common type, create a new entry. |
99 type = alloc_type(type_gap); | 153 type = get_type_ptr(type_gap); |
100 if (type == NULL) | 154 if (type == NULL) |
101 return &t_any; | 155 return &t_any; |
102 type->tt_type = VAR_DICT; | 156 type->tt_type = VAR_DICT; |
103 type->tt_member = member_type; | 157 type->tt_member = member_type; |
104 type->tt_argcount = 0; | 158 type->tt_argcount = 0; |
110 * Allocate a new type for a function. | 164 * Allocate a new type for a function. |
111 */ | 165 */ |
112 type_T * | 166 type_T * |
113 alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) | 167 alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) |
114 { | 168 { |
115 type_T *type = alloc_type(type_gap); | 169 type_T *type = get_type_ptr(type_gap); |
116 | 170 |
117 if (type == NULL) | 171 if (type == NULL) |
118 return &t_any; | 172 return &t_any; |
119 type->tt_type = VAR_FUNC; | 173 type->tt_type = VAR_FUNC; |
120 type->tt_member = ret_type; | 174 type->tt_member = ret_type; |
195 return OK; | 249 return OK; |
196 } | 250 } |
197 | 251 |
198 /* | 252 /* |
199 * Get a type_T for a typval_T. | 253 * Get a type_T for a typval_T. |
200 * "type_list" is used to temporarily create types in. | 254 * "type_gap" is used to temporarily create types in. |
201 */ | 255 */ |
202 static type_T * | 256 static type_T * |
203 typval2type_int(typval_T *tv, garray_T *type_gap) | 257 typval2type_int(typval_T *tv, garray_T *type_gap) |
204 { | 258 { |
205 type_T *type; | 259 type_T *type; |
206 type_T *member_type; | 260 type_T *member_type = &t_any; |
261 int argcount = 0; | |
207 | 262 |
208 if (tv->v_type == VAR_NUMBER) | 263 if (tv->v_type == VAR_NUMBER) |
209 return &t_number; | 264 return &t_number; |
210 if (tv->v_type == VAR_BOOL) | 265 if (tv->v_type == VAR_BOOL) |
211 return &t_bool; | 266 return &t_bool; |
260 name = tv->vval.v_partial->pt_name; | 315 name = tv->vval.v_partial->pt_name; |
261 } | 316 } |
262 else | 317 else |
263 name = tv->vval.v_string; | 318 name = tv->vval.v_string; |
264 if (name != NULL) | 319 if (name != NULL) |
265 // TODO: how about a builtin function? | 320 { |
266 ufunc = find_func(name, FALSE, NULL); | 321 int idx = find_internal_func(name); |
322 | |
323 if (idx >= 0) | |
324 { | |
325 // TODO: get actual arg count and types | |
326 argcount = -1; | |
327 member_type = internal_func_ret_type(idx, 0, NULL); | |
328 } | |
329 else | |
330 ufunc = find_func(name, FALSE, NULL); | |
331 } | |
267 if (ufunc != NULL) | 332 if (ufunc != NULL) |
268 { | 333 { |
269 // May need to get the argument types from default values by | 334 // May need to get the argument types from default values by |
270 // compiling the function. | 335 // compiling the function. |
271 if (ufunc->uf_def_status == UF_TO_BE_COMPILED | 336 if (ufunc->uf_def_status == UF_TO_BE_COMPILED |
274 if (ufunc->uf_func_type != NULL) | 339 if (ufunc->uf_func_type != NULL) |
275 return ufunc->uf_func_type; | 340 return ufunc->uf_func_type; |
276 } | 341 } |
277 } | 342 } |
278 | 343 |
279 type = alloc_type(type_gap); | 344 type = get_type_ptr(type_gap); |
280 if (type == NULL) | 345 if (type == NULL) |
281 return NULL; | 346 return NULL; |
282 type->tt_type = tv->v_type; | 347 type->tt_type = tv->v_type; |
283 type->tt_member = &t_any; | 348 type->tt_argcount = argcount; |
349 type->tt_member = member_type; | |
284 | 350 |
285 return type; | 351 return type; |
286 } | 352 } |
287 | 353 |
288 /* | 354 /* |
309 if (type != NULL && type != &t_bool | 375 if (type != NULL && type != &t_bool |
310 && ((tv->v_type == VAR_NUMBER | 376 && ((tv->v_type == VAR_NUMBER |
311 && (tv->vval.v_number == 0 || tv->vval.v_number == 1)) | 377 && (tv->vval.v_number == 0 || tv->vval.v_number == 1)) |
312 || (tv->v_lock & VAR_BOOL_OK))) | 378 || (tv->v_lock & VAR_BOOL_OK))) |
313 { | 379 { |
314 type_T *newtype = alloc_type(type_gap); | 380 type_T *newtype = get_type_ptr(type_gap); |
315 | 381 |
316 // Number 0 and 1 and expression with "&&" or "||" can also be used | 382 // Number 0 and 1 and expression with "&&" or "||" can also be used |
317 // for bool. | 383 // for bool. |
318 if (newtype != NULL) | 384 if (newtype != NULL) |
319 { | 385 { |
418 { | 484 { |
419 if (expected->tt_member != &t_unknown) | 485 if (expected->tt_member != &t_unknown) |
420 ret = check_type(expected->tt_member, actual->tt_member, | 486 ret = check_type(expected->tt_member, actual->tt_member, |
421 FALSE, 0); | 487 FALSE, 0); |
422 if (ret == OK && expected->tt_argcount != -1 | 488 if (ret == OK && expected->tt_argcount != -1 |
489 && actual->tt_argcount != -1 | |
423 && (actual->tt_argcount < expected->tt_min_argcount | 490 && (actual->tt_argcount < expected->tt_min_argcount |
424 || actual->tt_argcount > expected->tt_argcount)) | 491 || actual->tt_argcount > expected->tt_argcount)) |
425 ret = FAIL; | 492 ret = FAIL; |
426 if (expected->tt_args != NULL && actual->tt_args != NULL) | 493 if (expected->tt_args != NULL && actual->tt_args != NULL) |
427 { | 494 { |
938 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; | 1005 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; |
939 | 1006 |
940 ga_init2(&ga, 1, 100); | 1007 ga_init2(&ga, 1, 100); |
941 if (ga_grow(&ga, 20) == FAIL) | 1008 if (ga_grow(&ga, 20) == FAIL) |
942 return "[unknown]"; | 1009 return "[unknown]"; |
943 *tofree = ga.ga_data; | |
944 STRCPY(ga.ga_data, "func("); | 1010 STRCPY(ga.ga_data, "func("); |
945 ga.ga_len += 5; | 1011 ga.ga_len += 5; |
946 | 1012 |
947 for (i = 0; i < type->tt_argcount; ++i) | 1013 for (i = 0; i < type->tt_argcount; ++i) |
948 { | 1014 { |
961 } | 1027 } |
962 len = (int)STRLEN(arg_type); | 1028 len = (int)STRLEN(arg_type); |
963 if (ga_grow(&ga, len + 8) == FAIL) | 1029 if (ga_grow(&ga, len + 8) == FAIL) |
964 { | 1030 { |
965 vim_free(arg_free); | 1031 vim_free(arg_free); |
1032 ga_clear(&ga); | |
966 return "[unknown]"; | 1033 return "[unknown]"; |
967 } | 1034 } |
968 *tofree = ga.ga_data; | |
969 if (varargs && i == type->tt_argcount - 1) | 1035 if (varargs && i == type->tt_argcount - 1) |
970 { | 1036 ga_concat(&ga, (char_u *)"..."); |
971 STRCPY((char *)ga.ga_data + ga.ga_len, "..."); | |
972 ga.ga_len += 3; | |
973 } | |
974 else if (i >= type->tt_min_argcount) | 1037 else if (i >= type->tt_min_argcount) |
975 *((char *)ga.ga_data + ga.ga_len++) = '?'; | 1038 *((char *)ga.ga_data + ga.ga_len++) = '?'; |
976 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type); | 1039 ga_concat(&ga, (char_u *)arg_type); |
977 ga.ga_len += len; | |
978 vim_free(arg_free); | 1040 vim_free(arg_free); |
979 } | 1041 } |
1042 if (type->tt_argcount < 0) | |
1043 // any number of arguments | |
1044 ga_concat(&ga, (char_u *)"..."); | |
980 | 1045 |
981 if (type->tt_member == &t_void) | 1046 if (type->tt_member == &t_void) |
982 STRCPY((char *)ga.ga_data + ga.ga_len, ")"); | 1047 STRCPY((char *)ga.ga_data + ga.ga_len, ")"); |
983 else | 1048 else |
984 { | 1049 { |
988 | 1053 |
989 len = (int)STRLEN(ret_name) + 4; | 1054 len = (int)STRLEN(ret_name) + 4; |
990 if (ga_grow(&ga, len) == FAIL) | 1055 if (ga_grow(&ga, len) == FAIL) |
991 { | 1056 { |
992 vim_free(ret_free); | 1057 vim_free(ret_free); |
1058 ga_clear(&ga); | |
993 return "[unknown]"; | 1059 return "[unknown]"; |
994 } | 1060 } |
995 *tofree = ga.ga_data; | |
996 STRCPY((char *)ga.ga_data + ga.ga_len, "): "); | 1061 STRCPY((char *)ga.ga_data + ga.ga_len, "): "); |
997 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); | 1062 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); |
998 vim_free(ret_free); | 1063 vim_free(ret_free); |
999 } | 1064 } |
1065 *tofree = ga.ga_data; | |
1000 return ga.ga_data; | 1066 return ga.ga_data; |
1001 } | 1067 } |
1002 | 1068 |
1003 return name; | 1069 return name; |
1004 } | 1070 } |
1005 | 1071 |
1006 | |
1007 #endif // FEAT_EVAL | 1072 #endif // FEAT_EVAL |