Mercurial > vim
comparison src/vim9type.c @ 21711:d2dee69de7c7 v8.2.1405
patch 8.2.1405: Vim9: vim9compile.c is getting too big
Commit: https://github.com/vim/vim/commit/a7cc9e697b9140da66a09f71cdf839d08e32f5fb
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Aug 9 15:25:14 2020 +0200
patch 8.2.1405: Vim9: vim9compile.c is getting too big
Problem: Vim9: vim9compile.c is getting too big.
Solution: Split off type code to vim9type.c.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 09 Aug 2020 15:30:04 +0200 |
parents | |
children | 571832713efa |
comparison
equal
deleted
inserted
replaced
21710:966d5daed211 | 21711:d2dee69de7c7 |
---|---|
1 /* vi:set ts=8 sts=4 sw=4 noet: | |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 | |
10 /* | |
11 * vim9type.c: handling of types | |
12 */ | |
13 | |
14 #define USING_FLOAT_STUFF | |
15 #include "vim.h" | |
16 | |
17 #if defined(FEAT_EVAL) || defined(PROTO) | |
18 | |
19 #ifdef VMS | |
20 # include <float.h> | |
21 #endif | |
22 | |
23 /* | |
24 * Allocate memory for a type_T and add the pointer to type_gap, so that it can | |
25 * be freed later. | |
26 */ | |
27 static type_T * | |
28 alloc_type(garray_T *type_gap) | |
29 { | |
30 type_T *type; | |
31 | |
32 if (ga_grow(type_gap, 1) == FAIL) | |
33 return NULL; | |
34 type = ALLOC_CLEAR_ONE(type_T); | |
35 if (type != NULL) | |
36 { | |
37 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type; | |
38 ++type_gap->ga_len; | |
39 } | |
40 return type; | |
41 } | |
42 | |
43 void | |
44 clear_type_list(garray_T *gap) | |
45 { | |
46 while (gap->ga_len > 0) | |
47 vim_free(((type_T **)gap->ga_data)[--gap->ga_len]); | |
48 ga_clear(gap); | |
49 } | |
50 | |
51 type_T * | |
52 get_list_type(type_T *member_type, garray_T *type_gap) | |
53 { | |
54 type_T *type; | |
55 | |
56 // recognize commonly used types | |
57 if (member_type->tt_type == VAR_ANY) | |
58 return &t_list_any; | |
59 if (member_type->tt_type == VAR_VOID | |
60 || member_type->tt_type == VAR_UNKNOWN) | |
61 return &t_list_empty; | |
62 if (member_type->tt_type == VAR_BOOL) | |
63 return &t_list_bool; | |
64 if (member_type->tt_type == VAR_NUMBER) | |
65 return &t_list_number; | |
66 if (member_type->tt_type == VAR_STRING) | |
67 return &t_list_string; | |
68 | |
69 // Not a common type, create a new entry. | |
70 type = alloc_type(type_gap); | |
71 if (type == NULL) | |
72 return &t_any; | |
73 type->tt_type = VAR_LIST; | |
74 type->tt_member = member_type; | |
75 type->tt_argcount = 0; | |
76 type->tt_args = NULL; | |
77 return type; | |
78 } | |
79 | |
80 type_T * | |
81 get_dict_type(type_T *member_type, garray_T *type_gap) | |
82 { | |
83 type_T *type; | |
84 | |
85 // recognize commonly used types | |
86 if (member_type->tt_type == VAR_ANY) | |
87 return &t_dict_any; | |
88 if (member_type->tt_type == VAR_VOID | |
89 || member_type->tt_type == VAR_UNKNOWN) | |
90 return &t_dict_empty; | |
91 if (member_type->tt_type == VAR_BOOL) | |
92 return &t_dict_bool; | |
93 if (member_type->tt_type == VAR_NUMBER) | |
94 return &t_dict_number; | |
95 if (member_type->tt_type == VAR_STRING) | |
96 return &t_dict_string; | |
97 | |
98 // Not a common type, create a new entry. | |
99 type = alloc_type(type_gap); | |
100 if (type == NULL) | |
101 return &t_any; | |
102 type->tt_type = VAR_DICT; | |
103 type->tt_member = member_type; | |
104 type->tt_argcount = 0; | |
105 type->tt_args = NULL; | |
106 return type; | |
107 } | |
108 | |
109 /* | |
110 * Allocate a new type for a function. | |
111 */ | |
112 type_T * | |
113 alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) | |
114 { | |
115 type_T *type = alloc_type(type_gap); | |
116 | |
117 if (type == NULL) | |
118 return &t_any; | |
119 type->tt_type = VAR_FUNC; | |
120 type->tt_member = ret_type; | |
121 type->tt_argcount = argcount; | |
122 type->tt_args = NULL; | |
123 return type; | |
124 } | |
125 | |
126 /* | |
127 * Get a function type, based on the return type "ret_type". | |
128 * If "argcount" is -1 or 0 a predefined type can be used. | |
129 * If "argcount" > 0 always create a new type, so that arguments can be added. | |
130 */ | |
131 type_T * | |
132 get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) | |
133 { | |
134 // recognize commonly used types | |
135 if (argcount <= 0) | |
136 { | |
137 if (ret_type == &t_unknown) | |
138 { | |
139 // (argcount == 0) is not possible | |
140 return &t_func_unknown; | |
141 } | |
142 if (ret_type == &t_void) | |
143 { | |
144 if (argcount == 0) | |
145 return &t_func_0_void; | |
146 else | |
147 return &t_func_void; | |
148 } | |
149 if (ret_type == &t_any) | |
150 { | |
151 if (argcount == 0) | |
152 return &t_func_0_any; | |
153 else | |
154 return &t_func_any; | |
155 } | |
156 if (ret_type == &t_number) | |
157 { | |
158 if (argcount == 0) | |
159 return &t_func_0_number; | |
160 else | |
161 return &t_func_number; | |
162 } | |
163 if (ret_type == &t_string) | |
164 { | |
165 if (argcount == 0) | |
166 return &t_func_0_string; | |
167 else | |
168 return &t_func_string; | |
169 } | |
170 } | |
171 | |
172 return alloc_func_type(ret_type, argcount, type_gap); | |
173 } | |
174 | |
175 /* | |
176 * For a function type, reserve space for "argcount" argument types (including | |
177 * vararg). | |
178 */ | |
179 int | |
180 func_type_add_arg_types( | |
181 type_T *functype, | |
182 int argcount, | |
183 garray_T *type_gap) | |
184 { | |
185 // To make it easy to free the space needed for the argument types, add the | |
186 // pointer to type_gap. | |
187 if (ga_grow(type_gap, 1) == FAIL) | |
188 return FAIL; | |
189 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount); | |
190 if (functype->tt_args == NULL) | |
191 return FAIL; | |
192 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = | |
193 (void *)functype->tt_args; | |
194 ++type_gap->ga_len; | |
195 return OK; | |
196 } | |
197 | |
198 /* | |
199 * Get a type_T for a typval_T. | |
200 * "type_list" is used to temporarily create types in. | |
201 */ | |
202 type_T * | |
203 typval2type(typval_T *tv, garray_T *type_gap) | |
204 { | |
205 type_T *actual; | |
206 type_T *member_type; | |
207 | |
208 if (tv->v_type == VAR_NUMBER) | |
209 return &t_number; | |
210 if (tv->v_type == VAR_BOOL) | |
211 return &t_bool; // not used | |
212 if (tv->v_type == VAR_STRING) | |
213 return &t_string; | |
214 | |
215 if (tv->v_type == VAR_LIST) | |
216 { | |
217 if (tv->vval.v_list == NULL || tv->vval.v_list->lv_first == NULL) | |
218 return &t_list_empty; | |
219 | |
220 // Use the type of the first member, it is the most specific. | |
221 member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap); | |
222 return get_list_type(member_type, type_gap); | |
223 } | |
224 | |
225 if (tv->v_type == VAR_DICT) | |
226 { | |
227 dict_iterator_T iter; | |
228 typval_T *value; | |
229 | |
230 if (tv->vval.v_dict == NULL | |
231 || tv->vval.v_dict->dv_hashtab.ht_used == 0) | |
232 return &t_dict_empty; | |
233 | |
234 // Use the type of the first value, it is the most specific. | |
235 dict_iterate_start(tv, &iter); | |
236 dict_iterate_next(&iter, &value); | |
237 member_type = typval2type(value, type_gap); | |
238 return get_dict_type(member_type, type_gap); | |
239 } | |
240 | |
241 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) | |
242 { | |
243 char_u *name = NULL; | |
244 ufunc_T *ufunc = NULL; | |
245 | |
246 if (tv->v_type == VAR_PARTIAL) | |
247 { | |
248 if (tv->vval.v_partial->pt_func != NULL) | |
249 ufunc = tv->vval.v_partial->pt_func; | |
250 else | |
251 name = tv->vval.v_partial->pt_name; | |
252 } | |
253 else | |
254 name = tv->vval.v_string; | |
255 if (name != NULL) | |
256 // TODO: how about a builtin function? | |
257 ufunc = find_func(name, FALSE, NULL); | |
258 if (ufunc != NULL) | |
259 { | |
260 // May need to get the argument types from default values by | |
261 // compiling the function. | |
262 if (ufunc->uf_def_status == UF_TO_BE_COMPILED | |
263 && compile_def_function(ufunc, TRUE, NULL) == FAIL) | |
264 return NULL; | |
265 if (ufunc->uf_func_type != NULL) | |
266 return ufunc->uf_func_type; | |
267 } | |
268 } | |
269 | |
270 actual = alloc_type(type_gap); | |
271 if (actual == NULL) | |
272 return NULL; | |
273 actual->tt_type = tv->v_type; | |
274 actual->tt_member = &t_any; | |
275 | |
276 return actual; | |
277 } | |
278 | |
279 /* | |
280 * Get a type_T for a typval_T, used for v: variables. | |
281 * "type_list" is used to temporarily create types in. | |
282 */ | |
283 type_T * | |
284 typval2type_vimvar(typval_T *tv, garray_T *type_gap) | |
285 { | |
286 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles | |
287 return &t_list_string; | |
288 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item | |
289 return &t_dict_any; | |
290 return typval2type(tv, type_gap); | |
291 } | |
292 | |
293 | |
294 /* | |
295 * Return FAIL if "expected" and "actual" don't match. | |
296 */ | |
297 int | |
298 check_typval_type(type_T *expected, typval_T *actual_tv) | |
299 { | |
300 garray_T type_list; | |
301 type_T *actual_type; | |
302 int res = FAIL; | |
303 | |
304 ga_init2(&type_list, sizeof(type_T *), 10); | |
305 actual_type = typval2type(actual_tv, &type_list); | |
306 if (actual_type != NULL) | |
307 res = check_type(expected, actual_type, TRUE); | |
308 clear_type_list(&type_list); | |
309 return res; | |
310 } | |
311 | |
312 void | |
313 type_mismatch(type_T *expected, type_T *actual) | |
314 { | |
315 char *tofree1, *tofree2; | |
316 | |
317 semsg(_("E1013: type mismatch, expected %s but got %s"), | |
318 type_name(expected, &tofree1), type_name(actual, &tofree2)); | |
319 vim_free(tofree1); | |
320 vim_free(tofree2); | |
321 } | |
322 | |
323 void | |
324 arg_type_mismatch(type_T *expected, type_T *actual, int argidx) | |
325 { | |
326 char *tofree1, *tofree2; | |
327 | |
328 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"), | |
329 argidx, | |
330 type_name(expected, &tofree1), type_name(actual, &tofree2)); | |
331 vim_free(tofree1); | |
332 vim_free(tofree2); | |
333 } | |
334 | |
335 /* | |
336 * Check if the expected and actual types match. | |
337 * Does not allow for assigning "any" to a specific type. | |
338 */ | |
339 int | |
340 check_type(type_T *expected, type_T *actual, int give_msg) | |
341 { | |
342 int ret = OK; | |
343 | |
344 // When expected is "unknown" we accept any actual type. | |
345 // When expected is "any" we accept any actual type except "void". | |
346 if (expected->tt_type != VAR_UNKNOWN | |
347 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID)) | |
348 | |
349 { | |
350 if (expected->tt_type != actual->tt_type) | |
351 { | |
352 if (give_msg) | |
353 type_mismatch(expected, actual); | |
354 return FAIL; | |
355 } | |
356 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) | |
357 { | |
358 // "unknown" is used for an empty list or dict | |
359 if (actual->tt_member != &t_unknown) | |
360 ret = check_type(expected->tt_member, actual->tt_member, FALSE); | |
361 } | |
362 else if (expected->tt_type == VAR_FUNC) | |
363 { | |
364 if (expected->tt_member != &t_unknown) | |
365 ret = check_type(expected->tt_member, actual->tt_member, FALSE); | |
366 if (ret == OK && expected->tt_argcount != -1 | |
367 && (actual->tt_argcount < expected->tt_min_argcount | |
368 || actual->tt_argcount > expected->tt_argcount)) | |
369 ret = FAIL; | |
370 if (expected->tt_args != NULL && actual->tt_args != NULL) | |
371 { | |
372 int i; | |
373 | |
374 for (i = 0; i < expected->tt_argcount; ++i) | |
375 // Allow for using "any" argument type, lambda's have them. | |
376 if (actual->tt_args[i] != &t_any && check_type( | |
377 expected->tt_args[i], actual->tt_args[i], FALSE) | |
378 == FAIL) | |
379 { | |
380 ret = FAIL; | |
381 break; | |
382 } | |
383 } | |
384 } | |
385 if (ret == FAIL && give_msg) | |
386 type_mismatch(expected, actual); | |
387 } | |
388 return ret; | |
389 } | |
390 | |
391 /* | |
392 * Skip over a type definition and return a pointer to just after it. | |
393 * When "optional" is TRUE then a leading "?" is accepted. | |
394 */ | |
395 char_u * | |
396 skip_type(char_u *start, int optional) | |
397 { | |
398 char_u *p = start; | |
399 | |
400 if (optional && *p == '?') | |
401 ++p; | |
402 while (ASCII_ISALNUM(*p) || *p == '_') | |
403 ++p; | |
404 | |
405 // Skip over "<type>"; this is permissive about white space. | |
406 if (*skipwhite(p) == '<') | |
407 { | |
408 p = skipwhite(p); | |
409 p = skip_type(skipwhite(p + 1), FALSE); | |
410 p = skipwhite(p); | |
411 if (*p == '>') | |
412 ++p; | |
413 } | |
414 else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1]))) | |
415 && STRNCMP("func", start, 4) == 0) | |
416 { | |
417 if (*p == '(') | |
418 { | |
419 // handle func(args): type | |
420 ++p; | |
421 while (*p != ')' && *p != NUL) | |
422 { | |
423 char_u *sp = p; | |
424 | |
425 if (STRNCMP(p, "...", 3) == 0) | |
426 p += 3; | |
427 p = skip_type(p, TRUE); | |
428 if (p == sp) | |
429 return p; // syntax error | |
430 if (*p == ',') | |
431 p = skipwhite(p + 1); | |
432 } | |
433 if (*p == ')') | |
434 { | |
435 if (p[1] == ':') | |
436 p = skip_type(skipwhite(p + 2), FALSE); | |
437 else | |
438 ++p; | |
439 } | |
440 } | |
441 else | |
442 { | |
443 // handle func: return_type | |
444 p = skip_type(skipwhite(p + 1), FALSE); | |
445 } | |
446 } | |
447 | |
448 return p; | |
449 } | |
450 | |
451 /* | |
452 * Parse the member type: "<type>" and return "type" with the member set. | |
453 * Use "type_gap" if a new type needs to be added. | |
454 * Returns NULL in case of failure. | |
455 */ | |
456 static type_T * | |
457 parse_type_member(char_u **arg, type_T *type, garray_T *type_gap) | |
458 { | |
459 type_T *member_type; | |
460 int prev_called_emsg = called_emsg; | |
461 | |
462 if (**arg != '<') | |
463 { | |
464 if (*skipwhite(*arg) == '<') | |
465 semsg(_(e_no_white_before), "<"); | |
466 else | |
467 emsg(_("E1008: Missing <type>")); | |
468 return type; | |
469 } | |
470 *arg = skipwhite(*arg + 1); | |
471 | |
472 member_type = parse_type(arg, type_gap); | |
473 | |
474 *arg = skipwhite(*arg); | |
475 if (**arg != '>' && called_emsg == prev_called_emsg) | |
476 { | |
477 emsg(_("E1009: Missing > after type")); | |
478 return type; | |
479 } | |
480 ++*arg; | |
481 | |
482 if (type->tt_type == VAR_LIST) | |
483 return get_list_type(member_type, type_gap); | |
484 return get_dict_type(member_type, type_gap); | |
485 } | |
486 | |
487 /* | |
488 * Parse a type at "arg" and advance over it. | |
489 * Return &t_any for failure. | |
490 */ | |
491 type_T * | |
492 parse_type(char_u **arg, garray_T *type_gap) | |
493 { | |
494 char_u *p = *arg; | |
495 size_t len; | |
496 | |
497 // skip over the first word | |
498 while (ASCII_ISALNUM(*p) || *p == '_') | |
499 ++p; | |
500 len = p - *arg; | |
501 | |
502 switch (**arg) | |
503 { | |
504 case 'a': | |
505 if (len == 3 && STRNCMP(*arg, "any", len) == 0) | |
506 { | |
507 *arg += len; | |
508 return &t_any; | |
509 } | |
510 break; | |
511 case 'b': | |
512 if (len == 4 && STRNCMP(*arg, "bool", len) == 0) | |
513 { | |
514 *arg += len; | |
515 return &t_bool; | |
516 } | |
517 if (len == 4 && STRNCMP(*arg, "blob", len) == 0) | |
518 { | |
519 *arg += len; | |
520 return &t_blob; | |
521 } | |
522 break; | |
523 case 'c': | |
524 if (len == 7 && STRNCMP(*arg, "channel", len) == 0) | |
525 { | |
526 *arg += len; | |
527 return &t_channel; | |
528 } | |
529 break; | |
530 case 'd': | |
531 if (len == 4 && STRNCMP(*arg, "dict", len) == 0) | |
532 { | |
533 *arg += len; | |
534 return parse_type_member(arg, &t_dict_any, type_gap); | |
535 } | |
536 break; | |
537 case 'f': | |
538 if (len == 5 && STRNCMP(*arg, "float", len) == 0) | |
539 { | |
540 #ifdef FEAT_FLOAT | |
541 *arg += len; | |
542 return &t_float; | |
543 #else | |
544 emsg(_("E1076: This Vim is not compiled with float support")); | |
545 return &t_any; | |
546 #endif | |
547 } | |
548 if (len == 4 && STRNCMP(*arg, "func", len) == 0) | |
549 { | |
550 type_T *type; | |
551 type_T *ret_type = &t_unknown; | |
552 int argcount = -1; | |
553 int flags = 0; | |
554 int first_optional = -1; | |
555 type_T *arg_type[MAX_FUNC_ARGS + 1]; | |
556 | |
557 // func({type}, ...{type}): {type} | |
558 *arg += len; | |
559 if (**arg == '(') | |
560 { | |
561 // "func" may or may not return a value, "func()" does | |
562 // not return a value. | |
563 ret_type = &t_void; | |
564 | |
565 p = ++*arg; | |
566 argcount = 0; | |
567 while (*p != NUL && *p != ')') | |
568 { | |
569 if (*p == '?') | |
570 { | |
571 if (first_optional == -1) | |
572 first_optional = argcount; | |
573 ++p; | |
574 } | |
575 else if (STRNCMP(p, "...", 3) == 0) | |
576 { | |
577 flags |= TTFLAG_VARARGS; | |
578 p += 3; | |
579 } | |
580 else if (first_optional != -1) | |
581 { | |
582 emsg(_("E1007: mandatory argument after optional argument")); | |
583 return &t_any; | |
584 } | |
585 | |
586 arg_type[argcount++] = parse_type(&p, type_gap); | |
587 | |
588 // Nothing comes after "...{type}". | |
589 if (flags & TTFLAG_VARARGS) | |
590 break; | |
591 | |
592 if (*p != ',' && *skipwhite(p) == ',') | |
593 { | |
594 semsg(_(e_no_white_before), ","); | |
595 return &t_any; | |
596 } | |
597 if (*p == ',') | |
598 { | |
599 ++p; | |
600 if (!VIM_ISWHITE(*p)) | |
601 { | |
602 semsg(_(e_white_after), ","); | |
603 return &t_any; | |
604 } | |
605 } | |
606 p = skipwhite(p); | |
607 if (argcount == MAX_FUNC_ARGS) | |
608 { | |
609 emsg(_("E740: Too many argument types")); | |
610 return &t_any; | |
611 } | |
612 } | |
613 | |
614 p = skipwhite(p); | |
615 if (*p != ')') | |
616 { | |
617 emsg(_(e_missing_close)); | |
618 return &t_any; | |
619 } | |
620 *arg = p + 1; | |
621 } | |
622 if (**arg == ':') | |
623 { | |
624 // parse return type | |
625 ++*arg; | |
626 if (!VIM_ISWHITE(**arg)) | |
627 semsg(_(e_white_after), ":"); | |
628 *arg = skipwhite(*arg); | |
629 ret_type = parse_type(arg, type_gap); | |
630 } | |
631 if (flags == 0 && first_optional == -1 && argcount <= 0) | |
632 type = get_func_type(ret_type, argcount, type_gap); | |
633 else | |
634 { | |
635 type = alloc_func_type(ret_type, argcount, type_gap); | |
636 type->tt_flags = flags; | |
637 if (argcount > 0) | |
638 { | |
639 type->tt_argcount = argcount; | |
640 type->tt_min_argcount = first_optional == -1 | |
641 ? argcount : first_optional; | |
642 if (func_type_add_arg_types(type, argcount, | |
643 type_gap) == FAIL) | |
644 return &t_any; | |
645 mch_memmove(type->tt_args, arg_type, | |
646 sizeof(type_T *) * argcount); | |
647 } | |
648 } | |
649 return type; | |
650 } | |
651 break; | |
652 case 'j': | |
653 if (len == 3 && STRNCMP(*arg, "job", len) == 0) | |
654 { | |
655 *arg += len; | |
656 return &t_job; | |
657 } | |
658 break; | |
659 case 'l': | |
660 if (len == 4 && STRNCMP(*arg, "list", len) == 0) | |
661 { | |
662 *arg += len; | |
663 return parse_type_member(arg, &t_list_any, type_gap); | |
664 } | |
665 break; | |
666 case 'n': | |
667 if (len == 6 && STRNCMP(*arg, "number", len) == 0) | |
668 { | |
669 *arg += len; | |
670 return &t_number; | |
671 } | |
672 break; | |
673 case 's': | |
674 if (len == 6 && STRNCMP(*arg, "string", len) == 0) | |
675 { | |
676 *arg += len; | |
677 return &t_string; | |
678 } | |
679 break; | |
680 case 'v': | |
681 if (len == 4 && STRNCMP(*arg, "void", len) == 0) | |
682 { | |
683 *arg += len; | |
684 return &t_void; | |
685 } | |
686 break; | |
687 } | |
688 | |
689 semsg(_("E1010: Type not recognized: %s"), *arg); | |
690 return &t_any; | |
691 } | |
692 | |
693 /* | |
694 * Check if "type1" and "type2" are exactly the same. | |
695 */ | |
696 static int | |
697 equal_type(type_T *type1, type_T *type2) | |
698 { | |
699 int i; | |
700 | |
701 if (type1->tt_type != type2->tt_type) | |
702 return FALSE; | |
703 switch (type1->tt_type) | |
704 { | |
705 case VAR_UNKNOWN: | |
706 case VAR_ANY: | |
707 case VAR_VOID: | |
708 case VAR_SPECIAL: | |
709 case VAR_BOOL: | |
710 case VAR_NUMBER: | |
711 case VAR_FLOAT: | |
712 case VAR_STRING: | |
713 case VAR_BLOB: | |
714 case VAR_JOB: | |
715 case VAR_CHANNEL: | |
716 break; // not composite is always OK | |
717 case VAR_LIST: | |
718 case VAR_DICT: | |
719 return equal_type(type1->tt_member, type2->tt_member); | |
720 case VAR_FUNC: | |
721 case VAR_PARTIAL: | |
722 if (!equal_type(type1->tt_member, type2->tt_member) | |
723 || type1->tt_argcount != type2->tt_argcount) | |
724 return FALSE; | |
725 if (type1->tt_argcount < 0 | |
726 || type1->tt_args == NULL || type2->tt_args == NULL) | |
727 return TRUE; | |
728 for (i = 0; i < type1->tt_argcount; ++i) | |
729 if (!equal_type(type1->tt_args[i], type2->tt_args[i])) | |
730 return FALSE; | |
731 return TRUE; | |
732 } | |
733 return TRUE; | |
734 } | |
735 | |
736 /* | |
737 * Find the common type of "type1" and "type2" and put it in "dest". | |
738 * "type2" and "dest" may be the same. | |
739 */ | |
740 void | |
741 common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) | |
742 { | |
743 if (equal_type(type1, type2)) | |
744 { | |
745 *dest = type1; | |
746 return; | |
747 } | |
748 | |
749 if (type1->tt_type == type2->tt_type) | |
750 { | |
751 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT) | |
752 { | |
753 type_T *common; | |
754 | |
755 common_type(type1->tt_member, type2->tt_member, &common, type_gap); | |
756 if (type1->tt_type == VAR_LIST) | |
757 *dest = get_list_type(common, type_gap); | |
758 else | |
759 *dest = get_dict_type(common, type_gap); | |
760 return; | |
761 } | |
762 if (type1->tt_type == VAR_FUNC) | |
763 { | |
764 type_T *common; | |
765 | |
766 common_type(type1->tt_member, type2->tt_member, &common, type_gap); | |
767 if (type1->tt_argcount == type2->tt_argcount | |
768 && type1->tt_argcount >= 0) | |
769 { | |
770 int argcount = type1->tt_argcount; | |
771 int i; | |
772 | |
773 *dest = alloc_func_type(common, argcount, type_gap); | |
774 if (type1->tt_args != NULL && type2->tt_args != NULL) | |
775 { | |
776 if (func_type_add_arg_types(*dest, argcount, | |
777 type_gap) == OK) | |
778 for (i = 0; i < argcount; ++i) | |
779 common_type(type1->tt_args[i], type2->tt_args[i], | |
780 &(*dest)->tt_args[i], type_gap); | |
781 } | |
782 } | |
783 else | |
784 *dest = alloc_func_type(common, -1, type_gap); | |
785 return; | |
786 } | |
787 } | |
788 | |
789 *dest = &t_any; | |
790 } | |
791 | |
792 char * | |
793 vartype_name(vartype_T type) | |
794 { | |
795 switch (type) | |
796 { | |
797 case VAR_UNKNOWN: break; | |
798 case VAR_ANY: return "any"; | |
799 case VAR_VOID: return "void"; | |
800 case VAR_SPECIAL: return "special"; | |
801 case VAR_BOOL: return "bool"; | |
802 case VAR_NUMBER: return "number"; | |
803 case VAR_FLOAT: return "float"; | |
804 case VAR_STRING: return "string"; | |
805 case VAR_BLOB: return "blob"; | |
806 case VAR_JOB: return "job"; | |
807 case VAR_CHANNEL: return "channel"; | |
808 case VAR_LIST: return "list"; | |
809 case VAR_DICT: return "dict"; | |
810 | |
811 case VAR_FUNC: | |
812 case VAR_PARTIAL: return "func"; | |
813 } | |
814 return "unknown"; | |
815 } | |
816 | |
817 /* | |
818 * Return the name of a type. | |
819 * The result may be in allocated memory, in which case "tofree" is set. | |
820 */ | |
821 char * | |
822 type_name(type_T *type, char **tofree) | |
823 { | |
824 char *name = vartype_name(type->tt_type); | |
825 | |
826 *tofree = NULL; | |
827 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) | |
828 { | |
829 char *member_free; | |
830 char *member_name = type_name(type->tt_member, &member_free); | |
831 size_t len; | |
832 | |
833 len = STRLEN(name) + STRLEN(member_name) + 3; | |
834 *tofree = alloc(len); | |
835 if (*tofree != NULL) | |
836 { | |
837 vim_snprintf(*tofree, len, "%s<%s>", name, member_name); | |
838 vim_free(member_free); | |
839 return *tofree; | |
840 } | |
841 } | |
842 if (type->tt_type == VAR_FUNC) | |
843 { | |
844 garray_T ga; | |
845 int i; | |
846 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; | |
847 | |
848 ga_init2(&ga, 1, 100); | |
849 if (ga_grow(&ga, 20) == FAIL) | |
850 return "[unknown]"; | |
851 *tofree = ga.ga_data; | |
852 STRCPY(ga.ga_data, "func("); | |
853 ga.ga_len += 5; | |
854 | |
855 for (i = 0; i < type->tt_argcount; ++i) | |
856 { | |
857 char *arg_free; | |
858 char *arg_type; | |
859 int len; | |
860 | |
861 if (type->tt_args == NULL) | |
862 arg_type = "[unknown]"; | |
863 else | |
864 arg_type = type_name(type->tt_args[i], &arg_free); | |
865 if (i > 0) | |
866 { | |
867 STRCPY((char *)ga.ga_data + ga.ga_len, ", "); | |
868 ga.ga_len += 2; | |
869 } | |
870 len = (int)STRLEN(arg_type); | |
871 if (ga_grow(&ga, len + 8) == FAIL) | |
872 { | |
873 vim_free(arg_free); | |
874 return "[unknown]"; | |
875 } | |
876 *tofree = ga.ga_data; | |
877 if (varargs && i == type->tt_argcount - 1) | |
878 { | |
879 STRCPY((char *)ga.ga_data + ga.ga_len, "..."); | |
880 ga.ga_len += 3; | |
881 } | |
882 else if (i >= type->tt_min_argcount) | |
883 *((char *)ga.ga_data + ga.ga_len++) = '?'; | |
884 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type); | |
885 ga.ga_len += len; | |
886 vim_free(arg_free); | |
887 } | |
888 | |
889 if (type->tt_member == &t_void) | |
890 STRCPY((char *)ga.ga_data + ga.ga_len, ")"); | |
891 else | |
892 { | |
893 char *ret_free; | |
894 char *ret_name = type_name(type->tt_member, &ret_free); | |
895 int len; | |
896 | |
897 len = (int)STRLEN(ret_name) + 4; | |
898 if (ga_grow(&ga, len) == FAIL) | |
899 { | |
900 vim_free(ret_free); | |
901 return "[unknown]"; | |
902 } | |
903 *tofree = ga.ga_data; | |
904 STRCPY((char *)ga.ga_data + ga.ga_len, "): "); | |
905 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); | |
906 vim_free(ret_free); | |
907 } | |
908 return ga.ga_data; | |
909 } | |
910 | |
911 return name; | |
912 } | |
913 | |
914 | |
915 #endif // FEAT_EVAL |