comparison src/vim9type.c @ 34987:4eeeba47eb0a v9.1.0349

patch 9.1.0349: Vim9: need static type for typealias Commit: https://github.com/vim/vim/commit/76ba252e6192580d22737708d69dad7c777fb68a Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Apr 18 21:33:27 2024 +0200 patch 9.1.0349: Vim9: need static type for typealias Problem: Vim9: need static type for typealias Solution: Refactor the typval2type() function and add a static type for typealias (Yegappan Lakshmanan) closes: #14582 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 18 Apr 2024 21:45:03 +0200
parents 3f9d9ee5cb7c
children 6dca41acb99c
comparison
equal deleted inserted replaced
34986:db6202f2c210 34987:4eeeba47eb0a
416 return type == NULL || type->tt_type == VAR_ANY 416 return type == NULL || type->tt_type == VAR_ANY
417 || type->tt_type == VAR_UNKNOWN; 417 || type->tt_type == VAR_UNKNOWN;
418 } 418 }
419 419
420 /* 420 /*
421 * Get a type_T for a partial typval in "tv". 421 * Get a type_T for a "special" typval in "tv".
422 */
423 static type_T *
424 special_typval2type(typval_T *tv)
425 {
426 switch (tv->vval.v_number)
427 {
428 case VVAL_NULL:
429 return &t_null;
430
431 case VVAL_NONE:
432 return &t_none;
433
434 case VVAL_TRUE:
435 case VVAL_FALSE:
436 return &t_bool;
437
438 default:
439 return &t_unknown;
440 }
441 }
442
443 /*
444 * Get a type_T for a List typval in "tv".
445 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
446 * "any".
447 * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it
448 * is "any".
449 */
450 static type_T *
451 list_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
452 {
453 list_T *l = tv->vval.v_list;
454 listitem_T *li;
455 type_T *member_type = NULL;
456
457 // An empty list has type list<unknown>, unless the type was specified
458 // and is not list<any>. This matters when assigning to a variable
459 // with a specific list type.
460 if (l == NULL || (l->lv_first == NULL
461 && (l->lv_type == NULL || l->lv_type->tt_member == &t_any)))
462 return &t_list_empty;
463
464 if ((flags & TVTT_DO_MEMBER) == 0)
465 return &t_list_any;
466
467 // If the type is list<any> go through the members, it may end up a
468 // more specific type.
469 if (l->lv_type != NULL && (l->lv_first == NULL
470 || (flags & TVTT_MORE_SPECIFIC) == 0
471 || l->lv_type->tt_member != &t_any))
472 // make a copy, lv_type may be freed if the list is freed
473 return copy_type_deep(l->lv_type, type_gap);
474
475 if (l->lv_first == &range_list_item)
476 return &t_list_number;
477
478 if (l->lv_copyID == copyID)
479 // avoid recursion
480 return &t_list_any;
481
482 l->lv_copyID = copyID;
483
484 // Use the common type of all members.
485 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap,
486 TVTT_DO_MEMBER);
487 for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
488 common_type(typval2type(&li->li_tv, copyID, type_gap, TVTT_DO_MEMBER),
489 member_type, &member_type, type_gap);
490
491 return get_list_type(member_type, type_gap);
492 }
493
494 /*
495 * Get a type_T for a Dict typval in "tv".
496 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
497 * "any".
498 * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it
499 * is "any".
500 */
501 static type_T *
502 dict_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
503 {
504 dict_iterator_T iter;
505 typval_T *value;
506 dict_T *d = tv->vval.v_dict;
507 type_T *member_type = NULL;
508
509 if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL))
510 return &t_dict_empty;
511
512 if ((flags & TVTT_DO_MEMBER) == 0)
513 return &t_dict_any;
514
515 // If the type is dict<any> go through the members, it may end up a
516 // more specific type.
517 if (d->dv_type != NULL && (d->dv_hashtab.ht_used == 0
518 || (flags & TVTT_MORE_SPECIFIC) == 0
519 || d->dv_type->tt_member != &t_any))
520 return d->dv_type;
521
522 if (d->dv_copyID == copyID)
523 // avoid recursion
524 return &t_dict_any;
525
526 d->dv_copyID = copyID;
527
528 // Use the common type of all values.
529 dict_iterate_start(tv, &iter);
530 dict_iterate_next(&iter, &value);
531 member_type = typval2type(value, copyID, type_gap, TVTT_DO_MEMBER);
532
533 while (dict_iterate_next(&iter, &value) != NULL)
534 common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER),
535 member_type, &member_type, type_gap);
536
537 return get_dict_type(member_type, type_gap);
538 }
539
540 /*
541 * Get a type_T for a "partial" typval in "tv".
422 */ 542 */
423 static type_T * 543 static type_T *
424 partial_typval2type(typval_T *tv, ufunc_T *ufunc, garray_T *type_gap) 544 partial_typval2type(typval_T *tv, ufunc_T *ufunc, garray_T *type_gap)
425 { 545 {
426 partial_T *pt = tv->vval.v_partial; 546 partial_T *pt = tv->vval.v_partial;
446 566
447 return type; 567 return type;
448 } 568 }
449 569
450 /* 570 /*
451 * Get a type_T for a typval_T. 571 * Get a type_T for a "class" or an "object" typval in "tv".
452 * "type_gap" is used to temporarily create types in.
453 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
454 * "any".
455 * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it
456 * is "any".
457 */ 572 */
458 static type_T * 573 static type_T *
459 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags) 574 oc_typval2type(typval_T *tv)
460 { 575 {
461 type_T *type; 576 if (tv->v_type == VAR_CLASS)
462 type_T *member_type = NULL; 577 {
463 class_T *class_type = NULL; 578 if (tv->vval.v_class == NULL)
464 int argcount = 0; 579 return &t_class;
465 int min_argcount = 0; 580
466 581 return &tv->vval.v_class->class_type;
467 if (tv->v_type == VAR_NUMBER) 582 }
468 return &t_number; 583
469 if (tv->v_type == VAR_BOOL) 584 if (tv->vval.v_object != NULL)
470 return &t_bool; 585 return &tv->vval.v_object->obj_class->class_object_type;
471 if (tv->v_type == VAR_SPECIAL) 586
472 { 587 return &t_object;
473 if (tv->vval.v_number == VVAL_NULL) 588 }
474 return &t_null; 589
475 if (tv->vval.v_number == VVAL_NONE) 590 /*
476 return &t_none; 591 * Get a type_T for a "function" or a "partial"
477 if (tv->vval.v_number == VVAL_TRUE 592 */
478 || tv->vval.v_number == VVAL_FALSE) 593 static type_T *
479 return &t_bool; 594 fp_typval2type(typval_T *tv, garray_T *type_gap)
480 return &t_unknown; 595 {
481 } 596 char_u *name = NULL;
482 if (tv->v_type == VAR_STRING) 597 ufunc_T *ufunc = NULL;
483 return &t_string; 598 type_T *type;
484 if (tv->v_type == VAR_BLOB) 599 type_T *member_type = NULL;
485 { 600 int argcount = 0;
486 if (tv->vval.v_blob == NULL) 601 int min_argcount = 0;
487 return &t_blob_null; 602
488 return &t_blob; 603 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
489 } 604 {
490 605 if (tv->vval.v_partial->pt_func != NULL)
491 if (tv->v_type == VAR_LIST) 606 ufunc = tv->vval.v_partial->pt_func;
492 {
493 list_T *l = tv->vval.v_list;
494 listitem_T *li;
495
496 // An empty list has type list<unknown>, unless the type was specified
497 // and is not list<any>. This matters when assigning to a variable
498 // with a specific list type.
499 if (l == NULL || (l->lv_first == NULL
500 && (l->lv_type == NULL || l->lv_type->tt_member == &t_any)))
501 return &t_list_empty;
502 if ((flags & TVTT_DO_MEMBER) == 0)
503 return &t_list_any;
504 // If the type is list<any> go through the members, it may end up a
505 // more specific type.
506 if (l->lv_type != NULL && (l->lv_first == NULL
507 || (flags & TVTT_MORE_SPECIFIC) == 0
508 || l->lv_type->tt_member != &t_any))
509 // make a copy, lv_type may be freed if the list is freed
510 return copy_type_deep(l->lv_type, type_gap);
511 if (l->lv_first == &range_list_item)
512 return &t_list_number;
513 if (l->lv_copyID == copyID)
514 // avoid recursion
515 return &t_list_any;
516 l->lv_copyID = copyID;
517
518 // Use the common type of all members.
519 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap,
520 TVTT_DO_MEMBER);
521 for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
522 common_type(typval2type(&li->li_tv, copyID, type_gap,
523 TVTT_DO_MEMBER),
524 member_type, &member_type, type_gap);
525 return get_list_type(member_type, type_gap);
526 }
527
528 if (tv->v_type == VAR_DICT)
529 {
530 dict_iterator_T iter;
531 typval_T *value;
532 dict_T *d = tv->vval.v_dict;
533
534 if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL))
535 return &t_dict_empty;
536 if ((flags & TVTT_DO_MEMBER) == 0)
537 return &t_dict_any;
538 // If the type is dict<any> go through the members, it may end up a
539 // more specific type.
540 if (d->dv_type != NULL && (d->dv_hashtab.ht_used == 0
541 || (flags & TVTT_MORE_SPECIFIC) == 0
542 || d->dv_type->tt_member != &t_any))
543 return d->dv_type;
544 if (d->dv_copyID == copyID)
545 // avoid recursion
546 return &t_dict_any;
547 d->dv_copyID = copyID;
548
549 // Use the common type of all values.
550 dict_iterate_start(tv, &iter);
551 dict_iterate_next(&iter, &value);
552 member_type = typval2type(value, copyID, type_gap, TVTT_DO_MEMBER);
553 while (dict_iterate_next(&iter, &value) != NULL)
554 common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER),
555 member_type, &member_type, type_gap);
556 return get_dict_type(member_type, type_gap);
557 }
558
559 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
560 {
561 char_u *name = NULL;
562 ufunc_T *ufunc = NULL;
563
564 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
565 {
566 if (tv->vval.v_partial->pt_func != NULL)
567 ufunc = tv->vval.v_partial->pt_func;
568 else
569 name = tv->vval.v_partial->pt_name;
570 }
571 else 607 else
572 name = tv->vval.v_string; 608 name = tv->vval.v_partial->pt_name;
573 if (name == NULL && ufunc == NULL) 609 }
574 return &t_func_unknown; 610 else
575 if (name != NULL) 611 name = tv->vval.v_string;
576 { 612
577 int idx = find_internal_func(name); 613 if (name == NULL && ufunc == NULL)
578 614 return &t_func_unknown;
579 if (idx >= 0) 615
580 { 616 if (name != NULL)
581 type_T *decl_type; // unused 617 {
582 618 int idx = find_internal_func(name);
583 internal_func_get_argcount(idx, &argcount, &min_argcount); 619
584 member_type = internal_func_ret_type(idx, 0, NULL, &decl_type, 620 if (idx >= 0)
585 type_gap); 621 {
586 } 622 type_T *decl_type; // unused
587 else 623
588 ufunc = find_func(name, FALSE); 624 internal_func_get_argcount(idx, &argcount, &min_argcount);
589 } 625 member_type = internal_func_ret_type(idx, 0, NULL, &decl_type,
590 if (ufunc != NULL) 626 type_gap);
591 { 627 }
592 // May need to get the argument types from default values by 628 else
593 // compiling the function. 629 ufunc = find_func(name, FALSE);
594 if (ufunc->uf_def_status == UF_TO_BE_COMPILED 630 }
595 && compile_def_function(ufunc, TRUE, CT_NONE, NULL) 631 if (ufunc != NULL)
596 == FAIL) 632 {
597 return NULL; 633 // May need to get the argument types from default values by
598 if (ufunc->uf_func_type == NULL) 634 // compiling the function.
599 set_function_type(ufunc); 635 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
600 if (ufunc->uf_func_type != NULL) 636 && compile_def_function(ufunc, TRUE, CT_NONE, NULL)
601 { 637 == FAIL)
602 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) 638 return NULL;
603 return partial_typval2type(tv, ufunc, type_gap); 639 if (ufunc->uf_func_type == NULL)
604 return ufunc->uf_func_type; 640 set_function_type(ufunc);
605 } 641 if (ufunc->uf_func_type != NULL)
606 } 642 {
607 } 643 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
608 644 return partial_typval2type(tv, ufunc, type_gap);
609 if (tv->v_type == VAR_CLASS) 645 return ufunc->uf_func_type;
610 class_type = tv->vval.v_class; 646 }
611 else if (tv->v_type == VAR_OBJECT && tv->vval.v_object != NULL) 647 }
612 class_type = tv->vval.v_object->obj_class;
613 648
614 type = get_type_ptr(type_gap); 649 type = get_type_ptr(type_gap);
615 if (type == NULL) 650 if (type == NULL)
616 return NULL; 651 return NULL;
617 type->tt_type = tv->v_type; 652 type->tt_type = tv->v_type;
618 type->tt_argcount = argcount; 653 type->tt_argcount = argcount;
619 type->tt_min_argcount = min_argcount; 654 type->tt_min_argcount = min_argcount;
620 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL 655 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
621 && tv->vval.v_partial->pt_argc > 0) 656 && tv->vval.v_partial->pt_argc > 0)
622 { 657 {
623 type->tt_argcount -= tv->vval.v_partial->pt_argc; 658 type->tt_argcount -= tv->vval.v_partial->pt_argc;
624 type->tt_min_argcount -= tv->vval.v_partial->pt_argc; 659 type->tt_min_argcount -= tv->vval.v_partial->pt_argc;
625 } 660 }
626 type->tt_member = member_type; 661 type->tt_member = member_type;
627 type->tt_class = class_type;
628 662
629 return type; 663 return type;
664 }
665
666 /*
667 * Get a type_T for a typval_T.
668 * "type_gap" is used to temporarily create types in.
669 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
670 * "any".
671 * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it
672 * is "any".
673 */
674 static type_T *
675 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
676 {
677 switch (tv->v_type)
678 {
679 case VAR_UNKNOWN:
680 return &t_unknown;
681
682 case VAR_ANY:
683 return &t_any;
684
685 case VAR_VOID:
686 return &t_void;
687
688 case VAR_BOOL:
689 return &t_bool;
690
691 case VAR_SPECIAL:
692 return special_typval2type(tv);
693
694 case VAR_NUMBER:
695 return &t_number;
696
697 case VAR_FLOAT:
698 return &t_float;
699
700 case VAR_STRING:
701 return &t_string;
702
703 case VAR_BLOB:
704 if (tv->vval.v_blob == NULL)
705 return &t_blob_null;
706 return &t_blob;
707
708 case VAR_LIST:
709 return list_typval2type(tv, copyID, type_gap, flags);
710
711 case VAR_DICT:
712 return dict_typval2type(tv, copyID, type_gap, flags);
713
714 case VAR_JOB:
715 return &t_job;
716
717 case VAR_CHANNEL:
718 return &t_channel;
719
720 case VAR_CLASS:
721 case VAR_OBJECT:
722 return oc_typval2type(tv);
723
724 case VAR_TYPEALIAS:
725 return &t_typealias;
726
727 case VAR_FUNC:
728 case VAR_PARTIAL:
729 return fp_typval2type(tv, type_gap);
730
731 case VAR_INSTR:
732 default:
733 break;
734 }
735
736 return NULL;
630 } 737 }
631 738
632 /* 739 /*
633 * Return TRUE if "tv" is not a bool but should be converted to bool. 740 * Return TRUE if "tv" is not a bool but should be converted to bool.
634 */ 741 */