1#![allow(dead_code)]
13use super::obj::{LangObj, ObjSet};
14use super::objects::{ObjKey, ScopeKey, TCObjects, TypeKey};
15use std::cell::{Ref, RefCell, RefMut};
16use std::collections::HashSet;
17use std::fmt;
18use std::fmt::Debug;
19use std::fmt::Write;
20use std::mem::size_of as std_size_of;
21use std::rc::Rc;
22
23macro_rules! compare_by_method_name {
24 ($objs:expr) => {{
25 |a, b| {
26 let oa = &$objs.lobjs[*a];
27 let ob = &$objs.lobjs[*b];
28 oa.id($objs).as_ref().cmp(ob.id($objs).as_ref())
29 }
30 }};
31}
32
33macro_rules! compare_by_type_name {
34 ($objs:expr) => {{
35 |a, b| {
36 let sort_name = |t: &Type| match t {
37 Type::Named(n) => {
38 let typ = &$objs.lobjs[n.obj().unwrap()];
39 typ.id($objs)
40 }
41 _ => "".into(),
42 };
43 let ta = sort_name(&$objs.types[*a]);
44 let tb = sort_name(&$objs.types[*b]);
45 ta.as_ref().cmp(tb.as_ref())
46 }
47 }};
48}
49
50#[derive(Debug)]
51pub enum Type {
52 Basic(BasicDetail),
53 Array(ArrayDetail),
54 Slice(SliceDetail),
55 Struct(StructDetail),
56 Pointer(PointerDetail),
57 Tuple(TupleDetail),
58 Signature(SignatureDetail),
59 Interface(InterfaceDetail),
60 Map(MapDetail),
61 Chan(ChanDetail),
62 Named(NamedDetail),
63}
64
65impl Type {
66 pub fn try_as_basic(&self) -> Option<&BasicDetail> {
67 match &self {
68 Type::Basic(b) => Some(b),
69 _ => None,
70 }
71 }
72
73 pub fn try_as_array(&self) -> Option<&ArrayDetail> {
74 match &self {
75 Type::Array(a) => Some(a),
76 _ => None,
77 }
78 }
79
80 pub fn try_as_array_mut(&mut self) -> Option<&mut ArrayDetail> {
81 match self {
82 Type::Array(a) => Some(a),
83 _ => None,
84 }
85 }
86
87 pub fn try_as_slice(&self) -> Option<&SliceDetail> {
88 match &self {
89 Type::Slice(s) => Some(s),
90 _ => None,
91 }
92 }
93
94 pub fn try_as_struct(&self) -> Option<&StructDetail> {
95 match &self {
96 Type::Struct(s) => Some(s),
97 _ => None,
98 }
99 }
100
101 pub fn try_as_pointer(&self) -> Option<&PointerDetail> {
102 match &self {
103 Type::Pointer(p) => Some(p),
104 _ => None,
105 }
106 }
107
108 pub fn try_as_tuple(&self) -> Option<&TupleDetail> {
109 match self {
110 Type::Tuple(t) => Some(t),
111 _ => None,
112 }
113 }
114
115 pub fn try_as_tuple_mut(&mut self) -> Option<&mut TupleDetail> {
116 match self {
117 Type::Tuple(t) => Some(t),
118 _ => None,
119 }
120 }
121
122 pub fn try_as_signature(&self) -> Option<&SignatureDetail> {
123 match self {
124 Type::Signature(s) => Some(s),
125 _ => None,
126 }
127 }
128
129 pub fn try_as_signature_mut(&mut self) -> Option<&mut SignatureDetail> {
130 match self {
131 Type::Signature(s) => Some(s),
132 _ => None,
133 }
134 }
135
136 pub fn try_as_interface(&self) -> Option<&InterfaceDetail> {
137 match &self {
138 Type::Interface(i) => Some(i),
139 _ => None,
140 }
141 }
142
143 pub fn try_as_interface_mut(&mut self) -> Option<&mut InterfaceDetail> {
144 match self {
145 Type::Interface(i) => Some(i),
146 _ => None,
147 }
148 }
149
150 pub fn try_as_map(&self) -> Option<&MapDetail> {
151 match &self {
152 Type::Map(m) => Some(m),
153 _ => None,
154 }
155 }
156
157 pub fn try_as_chan(&self) -> Option<&ChanDetail> {
158 match self {
159 Type::Chan(c) => Some(c),
160 _ => None,
161 }
162 }
163
164 pub fn try_as_chan_mut(&mut self) -> Option<&mut ChanDetail> {
165 match self {
166 Type::Chan(c) => Some(c),
167 _ => None,
168 }
169 }
170
171 pub fn try_as_named(&self) -> Option<&NamedDetail> {
172 match self {
173 Type::Named(n) => Some(n),
174 _ => None,
175 }
176 }
177
178 pub fn try_as_named_mut(&mut self) -> Option<&mut NamedDetail> {
179 match self {
180 Type::Named(n) => Some(n),
181 _ => None,
182 }
183 }
184
185 pub fn underlying(&self) -> Option<TypeKey> {
186 match self {
187 Type::Named(detail) => detail.underlying,
188 _ => None,
189 }
190 }
191
192 pub fn underlying_val<'a>(&'a self, objs: &'a TCObjects) -> &'a Type {
193 if let Some(k) = self.underlying() {
194 &objs.types[k]
195 } else {
196 &self
197 }
198 }
199
200 pub fn is_named(&self) -> bool {
201 match self {
202 Type::Basic(_) | Type::Named(_) => true,
203 _ => false,
204 }
205 }
206 pub fn is_invalid(&self, objs: &TCObjects) -> bool {
207 match self.underlying_val(objs) {
208 Type::Basic(b) => b.info() == BasicInfo::IsInvalid,
209 _ => false,
210 }
211 }
212 pub fn is_boolean(&self, objs: &TCObjects) -> bool {
213 match self.underlying_val(objs) {
214 Type::Basic(b) => b.info() == BasicInfo::IsBoolean,
215 _ => false,
216 }
217 }
218 pub fn is_integer(&self, objs: &TCObjects) -> bool {
219 match self.underlying_val(objs) {
220 Type::Basic(b) => b.info() == BasicInfo::IsInteger,
221 _ => false,
222 }
223 }
224 pub fn is_unsigned(&self, objs: &TCObjects) -> bool {
225 match self.underlying_val(objs) {
226 Type::Basic(b) => b.typ().is_unsigned(),
227 _ => false,
228 }
229 }
230 pub fn is_float(&self, objs: &TCObjects) -> bool {
231 match self.underlying_val(objs) {
232 Type::Basic(b) => b.info() == BasicInfo::IsFloat,
233 _ => false,
234 }
235 }
236 pub fn is_complex(&self, objs: &TCObjects) -> bool {
237 match self.underlying_val(objs) {
238 Type::Basic(b) => b.info() == BasicInfo::IsComplex,
239 _ => false,
240 }
241 }
242 pub fn is_numeric(&self, objs: &TCObjects) -> bool {
243 match self.underlying_val(objs) {
244 Type::Basic(b) => b.info().is_numeric(),
245 _ => false,
246 }
247 }
248 pub fn is_string(&self, objs: &TCObjects) -> bool {
249 match self.underlying_val(objs) {
250 Type::Basic(b) => b.info() == BasicInfo::IsString,
251 _ => false,
252 }
253 }
254 pub fn is_typed(&self, objs: &TCObjects) -> bool {
255 match self.underlying_val(objs) {
256 Type::Basic(b) => !b.typ().is_untyped(),
257 _ => true,
258 }
259 }
260 pub fn is_untyped(&self, objs: &TCObjects) -> bool {
261 match self.underlying_val(objs) {
262 Type::Basic(b) => b.typ().is_untyped(),
263 _ => false,
264 }
265 }
266 pub fn is_ordered(&self, objs: &TCObjects) -> bool {
267 match self.underlying_val(objs) {
268 Type::Basic(b) => b.info().is_ordered(),
269 _ => false,
270 }
271 }
272 pub fn is_const_type(&self, objs: &TCObjects) -> bool {
273 match self.underlying_val(objs) {
274 Type::Basic(b) => b.info().is_const_type(),
275 _ => false,
276 }
277 }
278 pub fn is_interface(&self, objs: &TCObjects) -> bool {
279 match self.underlying_val(objs) {
280 Type::Interface(_) => true,
281 _ => false,
282 }
283 }
284 pub fn has_nil(&self, objs: &TCObjects) -> bool {
286 match self.underlying_val(objs) {
287 Type::Basic(b) => b.typ() == BasicType::UnsafePointer,
288 Type::Slice(_)
289 | Type::Pointer(_)
290 | Type::Signature(_)
291 | Type::Interface(_)
292 | Type::Map(_)
293 | Type::Chan(_) => true,
294 _ => false,
295 }
296 }
297 pub fn comparable(&self, objs: &TCObjects) -> bool {
299 match self.underlying_val(objs) {
300 Type::Basic(b) => b.typ() != BasicType::UntypedNil,
301 Type::Pointer(_) | Type::Interface(_) | Type::Chan(_) => true,
302 Type::Struct(s) => !s
303 .fields()
304 .iter()
305 .any(|f| !comparable(objs.lobjs[*f].typ().unwrap(), objs)),
306 Type::Array(a) => comparable(a.elem(), objs),
307 _ => false,
308 }
309 }
310}
311
312#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
313pub enum BasicType {
314 Invalid,
315 Bool,
317 Int,
318 Int8,
319 Int16,
320 Int32,
321 Int64,
322 Uint,
323 Uint8,
324 Uint16,
325 Uint32,
326 Uint64,
327 Uintptr,
328 Float32,
329 Float64,
330 Complex64,
331 Complex128,
332 Str,
333 UnsafePointer,
334 UntypedBool,
336 UntypedInt,
337 UntypedRune,
338 UntypedFloat,
339 UntypedComplex,
340 UntypedString,
341 UntypedNil,
342 Byte, Rune, }
346
347impl BasicType {
348 pub fn is_unsigned(&self) -> bool {
349 match self {
350 BasicType::Uint
351 | BasicType::Uint8
352 | BasicType::Uint16
353 | BasicType::Uint32
354 | BasicType::Uint64
355 | BasicType::Byte
356 | BasicType::Rune
357 | BasicType::Uintptr => true,
358 _ => false,
359 }
360 }
361
362 pub fn is_untyped(&self) -> bool {
363 match self {
364 BasicType::UntypedBool
365 | BasicType::UntypedInt
366 | BasicType::UntypedRune
367 | BasicType::UntypedFloat
368 | BasicType::UntypedComplex
369 | BasicType::UntypedString
370 | BasicType::UntypedNil => true,
371 _ => false,
372 }
373 }
374
375 pub fn real_type(&self) -> BasicType {
376 match self {
377 BasicType::Byte => BasicType::Uint8,
378 BasicType::Rune => BasicType::Int32,
379 _ => *self,
380 }
381 }
382}
383
384#[derive(Copy, Clone, Debug, PartialEq, Eq)]
385pub enum BasicInfo {
386 IsInvalid,
387 IsBoolean,
388 IsInteger,
389 IsFloat,
390 IsComplex,
391 IsString,
392}
393
394impl BasicInfo {
395 pub fn is_ordered(&self) -> bool {
396 match self {
397 BasicInfo::IsInteger | BasicInfo::IsFloat | BasicInfo::IsString => true,
398 _ => false,
399 }
400 }
401
402 pub fn is_numeric(&self) -> bool {
403 match self {
404 BasicInfo::IsInteger | BasicInfo::IsFloat | BasicInfo::IsComplex => true,
405 _ => false,
406 }
407 }
408
409 pub fn is_const_type(&self) -> bool {
410 match self {
411 BasicInfo::IsBoolean
412 | BasicInfo::IsInteger
413 | BasicInfo::IsFloat
414 | BasicInfo::IsComplex
415 | BasicInfo::IsString => true,
416 _ => false,
417 }
418 }
419}
420
421#[derive(Copy, Clone, Debug)]
423pub struct BasicDetail {
424 typ: BasicType,
425 info: BasicInfo,
426 name: &'static str,
427}
428
429impl BasicDetail {
430 pub fn new(typ: BasicType, info: BasicInfo, name: &'static str) -> BasicDetail {
431 BasicDetail {
432 typ: typ,
433 info: info,
434 name: name,
435 }
436 }
437
438 pub fn typ(&self) -> BasicType {
439 self.typ
440 }
441
442 pub fn info(&self) -> BasicInfo {
443 self.info
444 }
445
446 pub fn name(&self) -> &str {
447 self.name
448 }
449
450 pub fn size_of(&self) -> usize {
451 match self.typ {
452 BasicType::Bool | BasicType::Byte | BasicType::Uint8 | BasicType::Int8 => 1,
453 BasicType::Int16 | BasicType::Uint16 => 2,
454 BasicType::Int32 | BasicType::Uint32 | BasicType::Rune | BasicType::Float32 => 4,
455 BasicType::Int64 | BasicType::Uint64 | BasicType::Float64 | BasicType::Complex64 => 8,
456 BasicType::Int | BasicType::Uint | BasicType::Uintptr | BasicType::UnsafePointer => {
457 std_size_of::<usize>()
458 }
459 BasicType::Complex128 => 16,
460 BasicType::Str => std_size_of::<String>(),
461 _ => unreachable!(),
462 }
463 }
464}
465
466#[derive(Debug)]
468pub struct ArrayDetail {
469 len: Option<u64>,
470 elem: TypeKey,
471}
472
473impl ArrayDetail {
474 pub fn new(elem: TypeKey, len: Option<u64>) -> ArrayDetail {
475 ArrayDetail {
476 len: len,
477 elem: elem,
478 }
479 }
480
481 pub fn len(&self) -> Option<u64> {
482 self.len
483 }
484
485 pub fn set_len(&mut self, len: u64) {
486 self.len = Some(len);
487 }
488
489 pub fn elem(&self) -> TypeKey {
490 self.elem
491 }
492}
493
494#[derive(Debug)]
496pub struct SliceDetail {
497 elem: TypeKey,
498}
499
500impl SliceDetail {
501 pub fn new(elem: TypeKey) -> SliceDetail {
502 SliceDetail { elem: elem }
503 }
504
505 pub fn elem(&self) -> TypeKey {
506 self.elem
507 }
508}
509
510#[derive(Debug)]
512pub struct StructDetail {
513 fields: Vec<ObjKey>, tags: Option<Vec<Option<String>>>, }
516
517impl StructDetail {
518 pub fn new(
519 fields: Vec<ObjKey>,
520 tags: Option<Vec<Option<String>>>,
521 objs: &TCObjects,
522 ) -> StructDetail {
523 if cfg!(debug_assertions) {
525 let set = ObjSet::new();
526 let result = fields.iter().try_fold(set, |s, x| {
527 if !objs.lobjs[*x].entity_type().is_var() {
528 Err(())
529 } else if s.insert(*x, objs).is_some() {
530 Err(())
531 } else {
532 Ok::<ObjSet, ()>(s)
533 }
534 });
535 assert!(result.is_ok());
536 assert!(tags.is_none() || fields.len() >= tags.as_ref().unwrap().len());
537 }
538 StructDetail {
539 fields: fields,
540 tags: tags,
541 }
542 }
543
544 pub fn fields(&self) -> &Vec<ObjKey> {
545 &self.fields
546 }
547
548 pub fn tags(&self) -> &Option<Vec<Option<String>>> {
549 &self.tags
550 }
551
552 pub fn tag(&self, i: usize) -> Option<&String> {
553 self.tags
554 .as_ref()
555 .map(|x| if i < x.len() { x[i].as_ref() } else { None })
556 .flatten()
557 }
558}
559
560#[derive(Debug)]
562pub struct PointerDetail {
563 base: TypeKey, }
565
566impl PointerDetail {
567 pub fn new(base: TypeKey) -> PointerDetail {
568 PointerDetail { base: base }
569 }
570
571 pub fn base(&self) -> TypeKey {
572 self.base
573 }
574}
575
576#[derive(Debug)]
580pub struct TupleDetail {
581 vars: Vec<ObjKey>, }
583
584impl TupleDetail {
585 pub fn new(vars: Vec<ObjKey>) -> TupleDetail {
586 TupleDetail { vars: vars }
587 }
588
589 pub fn vars(&self) -> &Vec<ObjKey> {
590 &self.vars
591 }
592
593 pub fn vars_mut(&mut self) -> &mut Vec<ObjKey> {
594 &mut self.vars
595 }
596}
597
598#[derive(Copy, Clone, Debug)]
601pub struct SignatureDetail {
602 scope: Option<ScopeKey>, recv: Option<ObjKey>, params: TypeKey,
605 results: TypeKey,
606 variadic: bool,
607}
608
609impl SignatureDetail {
610 pub fn new(
611 scope: Option<ScopeKey>,
612 recv: Option<ObjKey>,
613 params: TypeKey,
614 results: TypeKey,
615 variadic: bool,
616 objs: &TCObjects,
617 ) -> SignatureDetail {
618 if false && cfg!(debug_assertions) {
620 if variadic {
621 let typ = &objs.types[params];
622 match typ {
623 Type::Tuple(t) => {
624 assert!(t.vars.len() > 0);
625 let okey = t.vars[t.vars.len() - 1];
626 let tkey = &objs.lobjs[okey].typ().unwrap();
627 assert!(objs.types[*tkey].try_as_slice().is_some());
628 }
629 _ => unreachable!(),
630 }
631 }
632 }
633 SignatureDetail {
634 scope: scope,
635 recv: recv,
636 params: params,
637 results: results,
638 variadic: variadic,
639 }
640 }
641
642 pub fn scope(&self) -> Option<ScopeKey> {
643 self.scope
644 }
645
646 pub fn recv(&self) -> &Option<ObjKey> {
653 &self.recv
654 }
655
656 pub fn set_recv(&mut self, r: Option<ObjKey>) {
657 self.recv = r
658 }
659
660 pub fn params(&self) -> TypeKey {
661 self.params
662 }
663
664 pub fn set_params(&mut self, p: TypeKey) {
665 self.params = p;
666 }
667
668 pub fn results(&self) -> TypeKey {
669 self.results
670 }
671
672 pub fn variadic(&self) -> bool {
673 self.variadic
674 }
675
676 pub fn params_count(&self, objs: &TCObjects) -> usize {
677 let l = objs.types[self.params].try_as_tuple().unwrap().vars().len();
678 if self.variadic {
679 l - 1
680 } else {
681 l
682 }
683 }
684
685 pub fn results_count(&self, objs: &TCObjects) -> usize {
686 objs.types[self.results]
687 .try_as_tuple()
688 .unwrap()
689 .vars()
690 .len()
691 }
692}
693
694#[derive(Debug)]
696pub struct InterfaceDetail {
697 methods: Vec<ObjKey>,
698 embeddeds: Vec<TypeKey>,
699 all_methods: Rc<RefCell<Option<Vec<ObjKey>>>>,
700}
701
702impl InterfaceDetail {
703 pub fn new(
704 mut methods: Vec<ObjKey>,
705 mut embeddeds: Vec<TypeKey>,
706 objs: &mut TCObjects,
707 ) -> InterfaceDetail {
708 let set = ObjSet::new();
709 let result = methods.iter().try_fold(set, |s, x| {
710 let mobj = &objs.lobjs[*x];
711 if !mobj.entity_type().is_func() {
712 Err(())
713 } else if s.insert(*x, &objs).is_some() {
714 Err(())
715 } else {
716 let signature = objs.types[mobj.typ().unwrap()].try_as_signature_mut();
717 if let Some(sig) = signature {
718 if sig.recv.is_none() {
719 let var =
720 LangObj::new_var(mobj.pos(), mobj.pkg(), "".to_owned(), mobj.typ());
721 sig.recv = Some(objs.lobjs.insert(var));
722 }
723 Ok(s)
724 } else {
725 Err(())
726 }
727 }
728 });
729 assert!(result.is_ok());
730 methods.sort_by(compare_by_method_name!(&objs));
731 embeddeds.sort_by(compare_by_type_name!(&objs));
732 InterfaceDetail {
733 methods: methods,
734 embeddeds: embeddeds,
735 all_methods: Rc::new(RefCell::new(None)),
736 }
737 }
738
739 pub fn new_empty() -> InterfaceDetail {
740 InterfaceDetail {
741 methods: Vec::new(),
742 embeddeds: Vec::new(),
743 all_methods: Rc::new(RefCell::new(Some(Vec::new()))),
744 }
745 }
746
747 pub fn methods(&self) -> &Vec<ObjKey> {
748 &self.methods
749 }
750
751 pub fn methods_mut(&mut self) -> &mut Vec<ObjKey> {
752 &mut self.methods
753 }
754
755 pub fn embeddeds(&self) -> &Vec<TypeKey> {
756 &self.embeddeds
757 }
758
759 pub fn embeddeds_mut(&mut self) -> &mut Vec<TypeKey> {
760 &mut self.embeddeds
761 }
762
763 pub fn all_methods(&self) -> Ref<Option<Vec<ObjKey>>> {
764 self.all_methods.borrow()
765 }
766
767 pub fn all_methods_mut(&self) -> RefMut<Option<Vec<ObjKey>>> {
768 self.all_methods.borrow_mut()
769 }
770
771 pub fn all_methods_push(&self, t: ObjKey) {
772 if self.all_methods.borrow_mut().is_none() {
773 *self.all_methods.borrow_mut() = Some(vec![t]);
774 } else {
775 self.all_methods.borrow_mut().as_mut().unwrap().push(t);
776 }
777 }
778
779 pub fn is_empty(&self) -> bool {
780 self.all_methods().as_ref().unwrap().len() == 0
781 }
782
783 pub fn set_empty_complete(&self) {
784 *self.all_methods.borrow_mut() = Some(vec![]);
785 }
786
787 pub fn complete(&self, objs: &TCObjects) {
788 if self.all_methods.borrow().is_some() {
789 return;
790 }
791 let mut all = self.methods.clone();
792 for tkey in self.embeddeds.iter() {
793 let embeded = &objs.types[*tkey].try_as_interface().unwrap();
794 embeded.complete(objs);
795 all.append(&mut embeded.all_methods().as_ref().unwrap().clone());
796 }
797 all.sort_by(compare_by_method_name!(&objs));
798 *self.all_methods.borrow_mut() = Some(all);
799 }
800}
801
802#[derive(Debug)]
803pub struct MapDetail {
804 key: TypeKey,
805 elem: TypeKey,
806}
807
808impl MapDetail {
809 pub fn new(key: TypeKey, elem: TypeKey) -> MapDetail {
810 MapDetail {
811 key: key,
812 elem: elem,
813 }
814 }
815
816 pub fn key(&self) -> TypeKey {
817 self.key
818 }
819
820 pub fn elem(&self) -> TypeKey {
821 self.elem
822 }
823}
824
825#[derive(Copy, Clone, Debug, PartialEq, Eq)]
826pub enum ChanDir {
827 SendRecv,
828 SendOnly,
829 RecvOnly,
830}
831
832#[derive(Debug)]
833pub struct ChanDetail {
834 dir: ChanDir,
835 elem: TypeKey,
836}
837
838impl ChanDetail {
839 pub fn new(dir: ChanDir, elem: TypeKey) -> ChanDetail {
840 ChanDetail {
841 dir: dir,
842 elem: elem,
843 }
844 }
845
846 pub fn dir(&self) -> ChanDir {
847 self.dir
848 }
849
850 pub fn elem(&self) -> TypeKey {
851 self.elem
852 }
853}
854
855#[derive(Debug)]
856pub struct NamedDetail {
857 obj: Option<ObjKey>, underlying: Option<TypeKey>, methods: Vec<ObjKey>, }
861
862impl NamedDetail {
863 pub fn new(
864 obj: Option<ObjKey>,
865 underlying: Option<TypeKey>,
866 methods: Vec<ObjKey>,
867 objs: &TCObjects,
868 ) -> NamedDetail {
869 if cfg!(debug_assertions) && underlying.is_some() {
870 let t = &objs.types[underlying.unwrap()];
871 assert!(t.try_as_named().is_none());
872 }
873 NamedDetail {
875 obj: obj,
876 underlying: underlying,
877 methods: methods,
878 }
879 }
880
881 pub fn obj(&self) -> &Option<ObjKey> {
882 &self.obj
883 }
884
885 pub fn set_obj(&mut self, obj: ObjKey) {
886 self.obj = Some(obj)
887 }
888
889 pub fn methods(&self) -> &Vec<ObjKey> {
890 &self.methods
891 }
892
893 pub fn methods_mut(&mut self) -> &mut Vec<ObjKey> {
894 &mut self.methods
895 }
896
897 pub fn underlying(&self) -> TypeKey {
898 self.underlying.unwrap()
899 }
900
901 pub fn set_underlying(&mut self, t: TypeKey) {
902 self.underlying = Some(t);
903 }
904}
905
906pub fn size_of(t: &TypeKey, objs: &TCObjects) -> usize {
913 let typ = &objs.types[*t].underlying_val(objs);
914 match typ {
915 Type::Basic(detail) => detail.size_of(),
916 _ => std_size_of::<usize>(),
917 }
918}
919
920pub fn underlying_type(t: TypeKey, objs: &TCObjects) -> TypeKey {
922 let typ = &objs.types[t];
923 match typ.underlying() {
924 Some(ut) => ut,
925 None => t,
926 }
927}
928
929pub fn deep_underlying_type(t: TypeKey, objs: &TCObjects) -> TypeKey {
932 let mut typ = &objs.types[t];
933 let mut ret = t;
934 loop {
935 match typ.underlying() {
936 Some(ut) => {
937 typ = &objs.types[ut];
938 ret = ut;
939 continue;
940 }
941 None => return ret,
942 }
943 }
944}
945
946pub fn is_named(t: TypeKey, objs: &TCObjects) -> bool {
947 objs.types[t].is_named()
948}
949
950pub fn is_boolean(t: TypeKey, objs: &TCObjects) -> bool {
951 objs.types[t].is_boolean(objs)
952}
953
954pub fn is_integer(t: TypeKey, objs: &TCObjects) -> bool {
955 objs.types[t].is_integer(objs)
956}
957
958pub fn is_unsigned(t: TypeKey, objs: &TCObjects) -> bool {
959 objs.types[t].is_unsigned(objs)
960}
961
962pub fn is_float(t: TypeKey, objs: &TCObjects) -> bool {
963 objs.types[t].is_float(objs)
964}
965
966pub fn is_complex(t: TypeKey, objs: &TCObjects) -> bool {
967 objs.types[t].is_complex(objs)
968}
969
970pub fn is_numeric(t: TypeKey, objs: &TCObjects) -> bool {
971 objs.types[t].is_numeric(objs)
972}
973
974pub fn is_string(t: TypeKey, objs: &TCObjects) -> bool {
975 objs.types[t].is_string(objs)
976}
977
978pub fn is_typed(t: TypeKey, objs: &TCObjects) -> bool {
979 objs.types[t].is_typed(objs)
980}
981
982pub fn is_untyped(t: TypeKey, objs: &TCObjects) -> bool {
983 objs.types[t].is_untyped(objs)
984}
985
986pub fn is_ordered(t: TypeKey, objs: &TCObjects) -> bool {
987 objs.types[t].is_ordered(objs)
988}
989
990pub fn is_const_type(t: TypeKey, objs: &TCObjects) -> bool {
991 objs.types[t].is_const_type(objs)
992}
993
994pub fn is_interface(t: TypeKey, objs: &TCObjects) -> bool {
995 objs.types[t].is_interface(objs)
996}
997
998pub fn has_nil(t: TypeKey, objs: &TCObjects) -> bool {
1000 objs.types[t].has_nil(objs)
1001}
1002
1003pub fn comparable(t: TypeKey, objs: &TCObjects) -> bool {
1005 objs.types[t].comparable(objs)
1006}
1007
1008pub fn untyped_default_type(t: TypeKey, objs: &TCObjects) -> TypeKey {
1012 objs.types[t].try_as_basic().map_or(t, |bt| match bt.typ() {
1013 BasicType::UntypedBool => objs.universe().types()[&BasicType::Bool],
1014 BasicType::UntypedInt => objs.universe().types()[&BasicType::Int],
1015 BasicType::UntypedRune => *objs.universe().rune(),
1016 BasicType::UntypedFloat => objs.universe().types()[&BasicType::Float64],
1017 BasicType::UntypedComplex => objs.universe().types()[&BasicType::Complex128],
1018 BasicType::UntypedString => objs.universe().types()[&BasicType::Str],
1019 _ => t,
1020 })
1021}
1022
1023pub fn identical(x: TypeKey, y: TypeKey, objs: &TCObjects) -> bool {
1026 identical_impl(x, y, true, &mut HashSet::new(), objs)
1027}
1028
1029pub fn identical_o(x: Option<TypeKey>, y: Option<TypeKey>, objs: &TCObjects) -> bool {
1031 identical_impl_o(x, y, true, &mut HashSet::new(), objs)
1032}
1033
1034pub fn identical_ignore_tags(x: TypeKey, y: TypeKey, objs: &TCObjects) -> bool {
1037 identical_impl(x, y, false, &mut HashSet::new(), objs)
1038}
1039
1040pub fn identical_ignore_tags_o(x: Option<TypeKey>, y: Option<TypeKey>, objs: &TCObjects) -> bool {
1042 identical_impl_o(x, y, false, &mut HashSet::new(), objs)
1043}
1044
1045fn identical_impl_o(
1047 x: Option<TypeKey>,
1048 y: Option<TypeKey>,
1049 cmp_tags: bool,
1050 dup: &mut HashSet<(TypeKey, TypeKey)>,
1051 objs: &TCObjects,
1052) -> bool {
1053 if x == y {
1054 true
1055 } else if x.is_none() || y.is_none() {
1056 false
1057 } else {
1058 identical_impl(x.unwrap(), y.unwrap(), cmp_tags, dup, objs)
1059 }
1060}
1061
1062fn identical_impl(
1065 x: TypeKey,
1066 y: TypeKey,
1067 cmp_tags: bool,
1068 dup: &mut HashSet<(TypeKey, TypeKey)>,
1069 objs: &TCObjects,
1070) -> bool {
1071 if x == y {
1072 return true;
1073 }
1074 let tx = &objs.types[x];
1075 let ty = &objs.types[y];
1076
1077 match (tx, ty) {
1078 (Type::Basic(bx), Type::Basic(by)) => bx.typ().real_type() == by.typ().real_type(),
1079 (Type::Array(ax), Type::Array(ay)) => {
1080 ax.len() == ay.len() && identical_impl(ax.elem(), ay.elem(), cmp_tags, dup, objs)
1081 }
1082 (Type::Slice(sx), Type::Slice(sy)) => {
1083 identical_impl(sx.elem(), sy.elem(), cmp_tags, dup, objs)
1084 }
1085 (Type::Struct(sx), Type::Struct(sy)) => {
1086 if sx.fields().len() == sy.fields().len() {
1087 !sx.fields().iter().enumerate().any(|(i, f)| {
1088 let of = &objs.lobjs[*f];
1089 let og = &objs.lobjs[sy.fields()[i]];
1090 (of.var_embedded() != og.var_embedded())
1091 || (cmp_tags && sx.tag(i) != sy.tag(i))
1092 || (!of.same_id(og.pkg(), og.name(), objs))
1093 || (!identical_impl_o(of.typ(), og.typ(), cmp_tags, dup, objs))
1094 })
1095 } else {
1096 false
1097 }
1098 }
1099 (Type::Pointer(px), Type::Pointer(py)) => {
1100 identical_impl(px.base(), py.base(), cmp_tags, dup, objs)
1101 }
1102 (Type::Tuple(tx), Type::Tuple(ty)) => {
1103 if tx.vars().len() == ty.vars().len() {
1104 !tx.vars().iter().enumerate().any(|(i, v)| {
1105 let ov = &objs.lobjs[*v];
1106 let ow = &objs.lobjs[ty.vars()[i]];
1107 !identical_impl_o(ov.typ(), ow.typ(), cmp_tags, dup, objs)
1108 })
1109 } else {
1110 false
1111 }
1112 }
1113 (Type::Signature(sx), Type::Signature(sy)) => {
1114 sx.variadic() == sy.variadic()
1115 && identical_impl(sx.params(), sy.params(), cmp_tags, dup, objs)
1116 && identical_impl(sx.results(), sy.results(), cmp_tags, dup, objs)
1117 }
1118 (Type::Interface(ix), Type::Interface(iy)) => {
1119 match (ix.all_methods().as_ref(), iy.all_methods().as_ref()) {
1120 (None, None) => true,
1121 (Some(a), Some(b)) => {
1122 if a.len() == b.len() {
1123 let pair = (x, y);
1139 if dup.get(&pair).is_some() {
1140 true
1142 } else {
1143 dup.insert(pair);
1144 !a.iter().enumerate().any(|(i, k)| {
1145 let ox = &objs.lobjs[*k];
1146 let oy = &objs.lobjs[b[i]];
1147 ox.id(objs) != oy.id(objs)
1148 || !identical_impl_o(ox.typ(), oy.typ(), cmp_tags, dup, objs)
1149 })
1150 }
1151 } else {
1152 false
1153 }
1154 }
1155 _ => false,
1156 }
1157 }
1158 (Type::Map(mx), Type::Map(my)) => {
1159 identical_impl(mx.key(), my.key(), cmp_tags, dup, objs)
1160 && identical_impl(mx.elem(), my.elem(), cmp_tags, dup, objs)
1161 }
1162 (Type::Chan(cx), Type::Chan(cy)) => {
1163 cx.dir() == cy.dir() && identical_impl(cx.elem(), cy.elem(), cmp_tags, dup, objs)
1164 }
1165 (Type::Named(nx), Type::Named(ny)) => nx.obj() == ny.obj(),
1166 _ => false,
1167 }
1168}
1169
1170pub fn fmt_type(t: Option<TypeKey>, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
1171 fmt_type_impl(t, f, &mut HashSet::new(), objs)
1172}
1173
1174pub fn fmt_signature(t: TypeKey, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
1175 fmt_signature_impl(t, f, &mut HashSet::new(), objs)
1176}
1177
1178fn fmt_type_impl(
1179 t: Option<TypeKey>,
1180 f: &mut fmt::Formatter<'_>,
1181 visited: &mut HashSet<TypeKey>,
1182 objs: &TCObjects,
1183) -> fmt::Result {
1184 if t.is_none() {
1185 return f.write_str("<nil>");
1186 }
1187 let tkey = t.unwrap();
1188 if visited.get(&tkey).is_some() {
1189 return tkey.fmt(f);
1190 }
1191 visited.insert(tkey);
1192 let typ = &objs.types[tkey];
1193 match typ {
1194 Type::Basic(detail) => {
1195 if detail.typ == BasicType::UnsafePointer {
1196 f.write_str("unsafe.")?;
1197 }
1198 write!(f, "{}", detail.name)?;
1199 }
1200 Type::Array(detail) => {
1201 match detail.len {
1202 Some(i) => write!(f, "[{}]", i)?,
1203 None => f.write_str("[unknown]")?,
1204 };
1205 fmt_type_impl(Some(detail.elem), f, visited, objs)?;
1206 }
1207 Type::Slice(detail) => {
1208 f.write_str("[]")?;
1209 fmt_type_impl(Some(detail.elem), f, visited, objs)?;
1210 }
1211 Type::Struct(detail) => {
1212 f.write_str("struct{")?;
1213 for (i, key) in detail.fields().iter().enumerate() {
1214 if i > 0 {
1215 f.write_str("; ")?;
1216 }
1217 let field = &objs.lobjs[*key];
1218 if !field.var_embedded() {
1219 write!(f, "{} ", field.name())?;
1220 }
1221 fmt_type_impl(field.typ(), f, visited, objs)?;
1222 if let Some(tag) = detail.tag(i) {
1223 write!(f, " {}", tag)?;
1224 }
1225 }
1226 f.write_str("}")?;
1227 }
1228 Type::Pointer(detail) => {
1229 f.write_char('*')?;
1230 fmt_type_impl(Some(detail.base()), f, visited, objs)?;
1231 }
1232 Type::Tuple(_) => {
1233 fmt_tuple(tkey, false, f, visited, objs)?;
1234 }
1235 Type::Signature(_) => {
1236 f.write_str("func")?;
1237 fmt_signature_impl(t.unwrap(), f, visited, objs)?;
1238 }
1239 Type::Interface(detail) => {
1240 f.write_str("interface{")?;
1241 for (i, k) in detail.methods().iter().enumerate() {
1242 if i > 0 {
1243 f.write_str("; ")?;
1244 }
1245 let mobj = &objs.lobjs[*k];
1246 f.write_str(mobj.name())?;
1247 fmt_signature_impl(mobj.typ().unwrap(), f, visited, objs)?;
1248 }
1249 for (i, k) in detail.embeddeds().iter().enumerate() {
1250 if i > 0 || detail.methods().len() > 0 {
1251 f.write_str("; ")?;
1252 }
1253 fmt_type_impl(Some(*k), f, visited, objs)?;
1254 }
1255 if detail.all_methods().is_none() {
1256 f.write_str(" /* incomplete */")?;
1257 }
1258 f.write_char('}')?;
1259 }
1260 Type::Map(detail) => {
1261 f.write_str("map[")?;
1262 fmt_type_impl(Some(detail.key()), f, visited, objs)?;
1263 f.write_char(']')?;
1264 fmt_type_impl(Some(detail.elem()), f, visited, objs)?;
1265 }
1266 Type::Chan(detail) => {
1267 let (s, paren) = match detail.dir() {
1268 ChanDir::SendRecv => ("chan ", {
1269 let elm = &objs.types[detail.elem()];
1271 if let Some(c) = elm.try_as_chan() {
1272 c.dir() == ChanDir::RecvOnly
1273 } else {
1274 false
1275 }
1276 }),
1277 ChanDir::SendOnly => ("chan<- ", false),
1278 ChanDir::RecvOnly => ("<-chan ", false),
1279 };
1280 f.write_str(s)?;
1281 if paren {
1282 f.write_char('(')?;
1283 }
1284 fmt_type_impl(Some(detail.elem()), f, visited, objs)?;
1285 if paren {
1286 f.write_char(')')?;
1287 }
1288 }
1289 Type::Named(detail) => {
1290 if let Some(okey) = detail.obj() {
1291 let o = &objs.lobjs[*okey];
1292 if let Some(pkg) = o.pkg() {
1293 objs.pkgs[pkg].fmt_with_qualifier(f, objs.fmt_qualifier.as_ref())?;
1294 }
1295 f.write_str(o.name())?;
1296 } else {
1297 f.write_str("<Named w/o object>")?;
1298 }
1299 }
1300 }
1301 Ok(())
1302}
1303
1304fn fmt_signature_impl(
1305 t: TypeKey,
1306 f: &mut fmt::Formatter<'_>,
1307 visited: &mut HashSet<TypeKey>,
1308 objs: &TCObjects,
1309) -> fmt::Result {
1310 let sig = &objs.types[t].try_as_signature().unwrap();
1311 fmt_tuple(sig.params(), sig.variadic(), f, visited, &objs)?;
1312 f.write_char(' ')?;
1313 let results = &objs.types[sig.results()].try_as_tuple().unwrap();
1314 if results.vars().len() == 1 {
1315 let obj = &objs.lobjs[results.vars()[0]];
1316 if obj.name().is_empty() {
1317 return fmt_type_impl(obj.typ(), f, visited, objs);
1319 }
1320 }
1321 fmt_tuple(sig.results(), false, f, visited, objs)
1323}
1324
1325fn fmt_tuple(
1326 tkey: TypeKey,
1327 variadic: bool,
1328 f: &mut fmt::Formatter<'_>,
1329 visited: &mut HashSet<TypeKey>,
1330 objs: &TCObjects,
1331) -> fmt::Result {
1332 f.write_char('(')?;
1333 let tuple = &objs.types[tkey].try_as_tuple().unwrap();
1334 for (i, v) in tuple.vars().iter().enumerate() {
1335 if i > 0 {
1336 f.write_str(", ")?;
1337 }
1338 let obj = &objs.lobjs[*v];
1339 if !obj.name().is_empty() {
1340 write!(f, "{} ", obj.name())?;
1341 }
1342 let tkey = obj.typ();
1343 if variadic && i == tuple.vars().len() - 1 {
1344 let utype = underlying_type(tkey.unwrap(), &objs);
1345 let typ = &objs.types[utype];
1346 match typ {
1347 Type::Slice(detail) => {
1348 f.write_str("...")?;
1349 fmt_type_impl(Some(detail.elem()), f, visited, objs)?;
1350 }
1351 Type::Basic(detail) => {
1352 assert!(detail.typ() == BasicType::Str);
1355 fmt_type_impl(tkey, f, visited, objs)?;
1356 f.write_str("...")?;
1357 }
1358 _ => unreachable!(),
1359 }
1360 } else {
1361 fmt_type_impl(tkey, f, visited, objs)?;
1362 }
1363 }
1364 f.write_char(')')?;
1365 Ok(())
1366}