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