1use parking_lot::RwLock;
2use std::collections::HashSet;
3use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
4use strum_macros::{Display, EnumIter, EnumString, FromRepr};
5
6use crate::context::CompileUnit;
7use crate::declare_arena;
8use crate::ir::HirNode;
9use crate::symbol::Symbol;
10
11declare_arena!(BlockArena {
12 bb: BasicBlock<'a>,
13 blk_root: BlockRoot<'a>,
14 blk_module: BlockModule<'a>,
15 blk_func: BlockFunc<'a>,
16 blk_class: BlockClass<'a>,
17 blk_trait: BlockTrait<'a>,
18 blk_interface: BlockInterface<'a>,
19 blk_impl: BlockImpl<'a>,
20 blk_call: BlockCall<'a>,
21 blk_enum: BlockEnum<'a>,
22 blk_field: BlockField<'a>,
23 blk_const: BlockConst<'a>,
24 blk_parameter: BlockParameter<'a>,
25 blk_return: BlockReturn<'a>,
26 blk_alias: BlockAlias<'a>,
27});
28
29#[derive(
30 Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumString, FromRepr, Display, Default,
31)]
32#[strum(serialize_all = "snake_case")]
33pub enum BlockKind {
34 #[default]
35 Undefined,
36 Root,
37 Module,
38 Func,
39 Method,
40 Closure,
41 Call,
42 Class,
43 Trait,
44 Interface,
45 Enum,
46 Const,
47 Impl,
48 Field,
49 Scope,
50 Parameter,
51 Return,
52 Alias,
53}
54
55#[derive(Debug, Clone)]
56pub enum BasicBlock<'blk> {
57 Undefined,
58 Root(&'blk BlockRoot<'blk>),
59 Module(&'blk BlockModule<'blk>),
60 Func(&'blk BlockFunc<'blk>),
61 Call(&'blk BlockCall<'blk>),
62 Enum(&'blk BlockEnum<'blk>),
63 Class(&'blk BlockClass<'blk>),
64 Trait(&'blk BlockTrait<'blk>),
65 Interface(&'blk BlockInterface<'blk>),
66 Impl(&'blk BlockImpl<'blk>),
67 Const(&'blk BlockConst<'blk>),
68 Field(&'blk BlockField<'blk>),
69 Parameter(&'blk BlockParameter<'blk>),
70 Return(&'blk BlockReturn<'blk>),
71 Alias(&'blk BlockAlias<'blk>),
72 Block,
73}
74
75impl<'blk> BasicBlock<'blk> {
76 pub fn format_block(&self, unit: CompileUnit<'blk>) -> String {
79 match self {
80 BasicBlock::Root(root) => root.format(),
81 BasicBlock::Module(module) => module.format(),
82 BasicBlock::Func(func) => func.format(unit),
83 BasicBlock::Class(class) => class.format(),
84 BasicBlock::Trait(trait_blk) => trait_blk.format(),
85 BasicBlock::Interface(iface) => iface.format(),
86 BasicBlock::Impl(impl_blk) => impl_blk.format(),
87 BasicBlock::Call(call) => call.format(),
88 BasicBlock::Enum(enum_blk) => enum_blk.format(),
89 BasicBlock::Const(const_blk) => const_blk.format(),
90 BasicBlock::Field(field) => field.format(),
91 BasicBlock::Parameter(param) => param.format(),
92 BasicBlock::Return(ret) => ret.format(),
93 BasicBlock::Alias(alias) => alias.format(),
94 BasicBlock::Undefined | BasicBlock::Block => "undefined".to_string(),
95 }
96 }
97
98 pub fn format_deps(&self, unit: CompileUnit<'blk>) -> Vec<String> {
101 match self {
102 BasicBlock::Func(func) => func.format_deps(unit),
103 BasicBlock::Class(class) => class.format_deps(unit),
104 _ => Vec::new(),
105 }
106 }
107
108 pub fn format_suffix(&self) -> Option<String> {
111 None
112 }
113
114 pub fn id(&self) -> BlockId {
115 self.block_id()
116 }
117
118 pub fn base(&self) -> Option<&BlockBase<'blk>> {
120 match self {
121 BasicBlock::Undefined | BasicBlock::Block => None,
122 BasicBlock::Root(block) => Some(&block.base),
123 BasicBlock::Module(block) => Some(&block.base),
124 BasicBlock::Func(block) => Some(&block.base),
125 BasicBlock::Class(block) => Some(&block.base),
126 BasicBlock::Trait(block) => Some(&block.base),
127 BasicBlock::Interface(block) => Some(&block.base),
128 BasicBlock::Impl(block) => Some(&block.base),
129 BasicBlock::Call(block) => Some(&block.base),
130 BasicBlock::Enum(block) => Some(&block.base),
131 BasicBlock::Const(block) => Some(&block.base),
132 BasicBlock::Field(block) => Some(&block.base),
133 BasicBlock::Parameter(block) => Some(&block.base),
134 BasicBlock::Return(block) => Some(&block.base),
135 BasicBlock::Alias(block) => Some(&block.base),
136 }
137 }
138
139 pub fn block_id(&self) -> BlockId {
141 self.base().unwrap().id
142 }
143
144 pub fn kind(&self) -> BlockKind {
146 self.base().map(|base| base.kind).unwrap_or_default()
147 }
148
149 pub fn node(&self) -> &HirNode<'blk> {
151 self.base().map(|base| &base.node).unwrap()
152 }
153
154 pub fn opt_node(&self) -> Option<&HirNode<'blk>> {
155 self.base().map(|base| &base.node)
156 }
157
158 pub fn symbol(&self) -> Option<&'blk Symbol> {
160 self.base().and_then(|base| base.symbol())
161 }
162
163 pub fn children(&self) -> Vec<BlockId> {
165 self.base()
166 .map(|base| base.get_children())
167 .unwrap_or_default()
168 }
169
170 pub fn child_count(&self) -> usize {
171 self.children().len()
172 }
173
174 pub fn is_kind(&self, kind: BlockKind) -> bool {
176 self.kind() == kind
177 }
178
179 pub fn as_root(&self) -> Option<&'blk BlockRoot<'blk>> {
181 match self {
182 BasicBlock::Root(r) => Some(r),
183 _ => None,
184 }
185 }
186
187 pub fn as_module(&self) -> Option<&'blk BlockModule<'blk>> {
189 match self {
190 BasicBlock::Module(m) => Some(m),
191 _ => None,
192 }
193 }
194
195 pub fn as_func(&self) -> Option<&'blk BlockFunc<'blk>> {
197 match self {
198 BasicBlock::Func(f) => Some(f),
199 _ => None,
200 }
201 }
202
203 pub fn as_class(&self) -> Option<&'blk BlockClass<'blk>> {
205 match self {
206 BasicBlock::Class(c) => Some(c),
207 _ => None,
208 }
209 }
210
211 pub fn as_trait(&self) -> Option<&'blk BlockTrait<'blk>> {
213 match self {
214 BasicBlock::Trait(t) => Some(t),
215 _ => None,
216 }
217 }
218
219 pub fn as_interface(&self) -> Option<&'blk BlockInterface<'blk>> {
221 match self {
222 BasicBlock::Interface(i) => Some(i),
223 _ => None,
224 }
225 }
226
227 pub fn as_impl(&self) -> Option<&'blk BlockImpl<'blk>> {
229 match self {
230 BasicBlock::Impl(i) => Some(i),
231 _ => None,
232 }
233 }
234
235 pub fn as_enum(&self) -> Option<&'blk BlockEnum<'blk>> {
237 match self {
238 BasicBlock::Enum(e) => Some(e),
239 _ => None,
240 }
241 }
242
243 pub fn as_field(&self) -> Option<&'blk BlockField<'blk>> {
245 match self {
246 BasicBlock::Field(f) => Some(f),
247 _ => None,
248 }
249 }
250
251 pub fn as_call(&self) -> Option<&'blk BlockCall<'blk>> {
253 match self {
254 BasicBlock::Call(c) => Some(c),
255 _ => None,
256 }
257 }
258}
259
260#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Default, PartialOrd, Ord)]
261pub struct BlockId(pub u32);
262
263static BLOCK_ID_COUNTER: AtomicU32 = AtomicU32::new(1);
265
266pub fn reset_block_id_counter() {
268 BLOCK_ID_COUNTER.store(1, Ordering::Relaxed);
269}
270
271impl std::fmt::Display for BlockId {
272 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273 write!(f, "{}", self.0)
274 }
275}
276
277impl BlockId {
278 pub fn new(id: u32) -> Self {
279 Self(id)
280 }
281
282 pub fn allocate() -> Self {
284 let id = BLOCK_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
285 BlockId(id)
286 }
287
288 pub fn next() -> Self {
290 BlockId(BLOCK_ID_COUNTER.load(Ordering::Relaxed))
291 }
292
293 pub fn as_u32(self) -> u32 {
294 self.0
295 }
296
297 pub const ROOT_PARENT: BlockId = BlockId(u32::MAX);
298
299 pub fn is_root_parent(self) -> bool {
300 self.0 == u32::MAX
301 }
302}
303
304#[derive(
305 Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumString, FromRepr, Display, Default,
306)]
307#[strum(serialize_all = "snake_case")]
308pub enum BlockRelation {
309 #[default]
310 Unknown,
311
312 Contains,
315 ContainedBy,
317
318 HasParameters,
321 HasReturn,
323 Calls,
325 CalledBy,
327
328 HasField,
331 FieldOf,
333 TypeOf,
335 TypeFor,
337 ImplFor,
339 HasImpl,
341 HasMethod,
343 MethodOf,
345 Implements,
347 ImplementedBy,
349
350 Uses,
353 UsedBy,
355
356 Extends,
359 ExtendedBy,
361}
362
363#[derive(Debug)]
364pub struct BlockBase<'blk> {
365 pub id: BlockId,
366 pub node: HirNode<'blk>,
367 pub kind: BlockKind,
368 pub parent: RwLock<Option<BlockId>>,
369 pub children: RwLock<Vec<BlockId>>,
370 pub symbol: Option<&'blk Symbol>,
373 pub type_deps: RwLock<HashSet<BlockId>>,
377}
378
379impl<'blk> BlockBase<'blk> {
380 pub fn new(
381 id: BlockId,
382 node: HirNode<'blk>,
383 kind: BlockKind,
384 parent: Option<BlockId>,
385 children: Vec<BlockId>,
386 ) -> Self {
387 Self {
388 id,
389 node,
390 kind,
391 parent: RwLock::new(parent),
392 children: RwLock::new(children),
393 symbol: None,
394 type_deps: RwLock::new(HashSet::new()),
395 }
396 }
397
398 pub fn with_symbol(
400 id: BlockId,
401 node: HirNode<'blk>,
402 kind: BlockKind,
403 parent: Option<BlockId>,
404 children: Vec<BlockId>,
405 symbol: Option<&'blk Symbol>,
406 ) -> Self {
407 Self {
408 id,
409 node,
410 kind,
411 parent: RwLock::new(parent),
412 children: RwLock::new(children),
413 symbol,
414 type_deps: RwLock::new(HashSet::new()),
415 }
416 }
417
418 pub fn symbol(&self) -> Option<&'blk Symbol> {
420 self.symbol
421 }
422
423 pub fn opt_get_name(&self) -> Option<&str> {
424 self.node
425 .as_scope()
426 .and_then(|scope| *scope.ident.read())
427 .map(|ident| ident.name)
428 }
429
430 pub fn add_child(&self, child_id: BlockId) {
431 let mut children = self.children.write();
432 if !children.contains(&child_id) {
433 children.push(child_id);
434 }
435 }
436
437 pub fn remove_child(&self, child_id: BlockId) {
438 self.children.write().retain(|&id| id != child_id);
439 }
440
441 pub fn get_children(&self) -> Vec<BlockId> {
442 self.children.read().clone()
443 }
444
445 pub fn set_parent(&self, parent_id: BlockId) {
446 *self.parent.write() = Some(parent_id);
447 }
448
449 pub fn get_parent(&self) -> Option<BlockId> {
450 *self.parent.read()
451 }
452
453 pub fn add_type_dep(&self, type_id: BlockId) {
455 self.type_deps.write().insert(type_id);
456 }
457
458 pub fn get_type_deps(&self) -> HashSet<BlockId> {
460 self.type_deps.read().clone()
461 }
462}
463
464#[derive(Debug)]
465pub struct BlockRoot<'blk> {
466 pub base: BlockBase<'blk>,
467 pub file_name: Option<String>,
468 pub crate_name: RwLock<Option<String>>,
470 pub crate_root: RwLock<Option<String>>,
472 pub module_path: RwLock<Option<String>>,
474 pub module_root: RwLock<Option<String>>,
476}
477
478impl<'blk> BlockRoot<'blk> {
479 pub fn new(
480 id: BlockId,
481 node: HirNode<'blk>,
482 parent: Option<BlockId>,
483 children: Vec<BlockId>,
484 file_name: Option<String>,
485 ) -> Self {
486 Self::new_with_symbol(id, node, parent, children, file_name, None)
487 }
488
489 pub fn new_with_symbol(
490 id: BlockId,
491 node: HirNode<'blk>,
492 parent: Option<BlockId>,
493 children: Vec<BlockId>,
494 file_name: Option<String>,
495 symbol: Option<&'blk Symbol>,
496 ) -> Self {
497 let base = BlockBase::with_symbol(id, node, BlockKind::Root, parent, children, symbol);
498 Self {
499 base,
500 file_name,
501 crate_name: RwLock::new(None),
502 crate_root: RwLock::new(None),
503 module_path: RwLock::new(None),
504 module_root: RwLock::new(None),
505 }
506 }
507
508 pub fn set_crate_name(&self, name: String) {
509 *self.crate_name.write() = Some(name);
510 }
511
512 pub fn get_crate_name(&self) -> Option<String> {
513 self.crate_name.read().clone()
514 }
515
516 pub fn set_crate_root(&self, root: String) {
517 *self.crate_root.write() = Some(root);
518 }
519
520 pub fn get_crate_root(&self) -> Option<String> {
521 self.crate_root.read().clone()
522 }
523
524 pub fn set_module_path(&self, path: String) {
525 *self.module_path.write() = Some(path);
526 }
527
528 pub fn get_module_path(&self) -> Option<String> {
529 self.module_path.read().clone()
530 }
531
532 pub fn set_module_root(&self, root: String) {
533 *self.module_root.write() = Some(root);
534 }
535
536 pub fn get_module_root(&self) -> Option<String> {
537 self.module_root.read().clone()
538 }
539
540 pub fn format(&self) -> String {
541 let name = self.base.opt_get_name().unwrap_or("");
542 if let Some(file_name) = &self.file_name {
543 format!(
544 "{}:{} {} ({})",
545 self.base.kind, self.base.id, name, file_name
546 )
547 } else {
548 format!("{}:{} {}", self.base.kind, self.base.id, name)
549 }
550 }
551}
552
553#[derive(Debug)]
555pub struct BlockModule<'blk> {
556 pub base: BlockBase<'blk>,
557 pub name: String,
559 pub is_inline: bool,
561}
562
563impl<'blk> BlockModule<'blk> {
564 pub fn new(
565 id: BlockId,
566 node: HirNode<'blk>,
567 parent: Option<BlockId>,
568 children: Vec<BlockId>,
569 name: String,
570 is_inline: bool,
571 ) -> Self {
572 Self::new_with_symbol(id, node, parent, children, name, is_inline, None)
573 }
574
575 pub fn new_with_symbol(
576 id: BlockId,
577 node: HirNode<'blk>,
578 parent: Option<BlockId>,
579 children: Vec<BlockId>,
580 name: String,
581 is_inline: bool,
582 symbol: Option<&'blk Symbol>,
583 ) -> Self {
584 let base = BlockBase::with_symbol(id, node, BlockKind::Module, parent, children, symbol);
585 Self {
586 base,
587 name,
588 is_inline,
589 }
590 }
591
592 pub fn format(&self) -> String {
593 let inline_marker = if self.is_inline { " (inline)" } else { "" };
594 format!(
595 "{}:{} {}{}",
596 self.base.kind, self.base.id, self.name, inline_marker
597 )
598 }
599}
600
601#[derive(Debug)]
602pub struct BlockFunc<'blk> {
603 pub base: BlockBase<'blk>,
604 pub name: String,
605 pub parameters: RwLock<Vec<BlockId>>,
606 pub returns: RwLock<Option<BlockId>>,
607 pub type_deps: RwLock<HashSet<BlockId>>,
610 pub func_deps: RwLock<HashSet<BlockId>>,
612 pub is_method: AtomicBool,
614}
615
616impl<'blk> BlockFunc<'blk> {
617 pub fn new(
618 id: BlockId,
619 node: HirNode<'blk>,
620 kind: BlockKind,
621 parent: Option<BlockId>,
622 children: Vec<BlockId>,
623 ) -> Self {
624 Self::new_with_symbol(id, node, kind, parent, children, None)
625 }
626
627 pub fn new_with_symbol(
628 id: BlockId,
629 node: HirNode<'blk>,
630 kind: BlockKind,
631 parent: Option<BlockId>,
632 children: Vec<BlockId>,
633 symbol: Option<&'blk Symbol>,
634 ) -> Self {
635 let base = BlockBase::with_symbol(id, node, kind, parent, children, symbol);
636 let name = base.opt_get_name().unwrap_or("").to_string();
637 Self {
638 base,
639 name,
640 parameters: RwLock::new(Vec::new()),
641 returns: RwLock::new(None),
642 type_deps: RwLock::new(HashSet::new()),
643 func_deps: RwLock::new(HashSet::new()),
644 is_method: AtomicBool::new(false),
645 }
646 }
647
648 pub fn set_is_method(&self, is_method: bool) {
649 self.is_method.store(is_method, Ordering::Relaxed);
650 }
651
652 pub fn is_method(&self) -> bool {
653 self.is_method.load(Ordering::Relaxed)
654 }
655
656 pub fn add_parameter(&self, param: BlockId) {
657 self.parameters.write().push(param);
658 }
659
660 pub fn get_parameters(&self) -> Vec<BlockId> {
661 self.parameters.read().clone()
662 }
663
664 pub fn set_returns(&self, ret: BlockId) {
665 *self.returns.write() = Some(ret);
666 }
667
668 pub fn get_returns(&self) -> Option<BlockId> {
669 *self.returns.read()
670 }
671
672 pub fn add_type_dep(&self, type_id: BlockId) {
673 self.type_deps.write().insert(type_id);
674 }
675
676 pub fn get_type_deps(&self) -> HashSet<BlockId> {
677 self.type_deps.read().clone()
678 }
679
680 pub fn add_func_dep(&self, func_id: BlockId) {
681 self.func_deps.write().insert(func_id);
682 }
683
684 pub fn get_func_deps(&self) -> HashSet<BlockId> {
685 self.func_deps.read().clone()
686 }
687
688 pub fn format(&self, _unit: CompileUnit<'blk>) -> String {
689 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
690 }
691
692 pub fn format_deps(&self, unit: CompileUnit<'blk>) -> Vec<String> {
695 let mut deps = Vec::new();
696
697 let type_deps = self.get_type_deps();
699 if !type_deps.is_empty() {
700 let mut sorted: Vec<_> = type_deps.iter().collect();
701 sorted.sort();
702 for dep_id in sorted {
703 let dep_block = unit.bb(*dep_id);
704 let dep_name = dep_block
705 .base()
706 .and_then(|b| b.opt_get_name())
707 .unwrap_or("");
708 deps.push(format!("@tdep:{dep_id} {dep_name}"));
709 }
710 }
711
712 let func_deps = self.get_func_deps();
714 if !func_deps.is_empty() {
715 let mut sorted: Vec<_> = func_deps.iter().collect();
716 sorted.sort();
717 for dep_id in sorted {
718 let dep_block = unit.bb(*dep_id);
719 let dep_name = dep_block
720 .base()
721 .and_then(|b| b.opt_get_name())
722 .unwrap_or("");
723 deps.push(format!("@fdep:{dep_id} {dep_name}"));
724 }
725 }
726
727 deps
728 }
729}
730
731#[derive(Debug)]
732pub struct BlockCall<'blk> {
733 pub base: BlockBase<'blk>,
734 pub callee: RwLock<Option<BlockId>>,
735 pub args: RwLock<Vec<BlockId>>,
736}
737
738impl<'blk> BlockCall<'blk> {
739 pub fn new(
740 id: BlockId,
741 node: HirNode<'blk>,
742 parent: Option<BlockId>,
743 children: Vec<BlockId>,
744 ) -> Self {
745 Self::new_with_symbol(id, node, parent, children, None)
746 }
747
748 pub fn new_with_symbol(
749 id: BlockId,
750 node: HirNode<'blk>,
751 parent: Option<BlockId>,
752 children: Vec<BlockId>,
753 symbol: Option<&'blk Symbol>,
754 ) -> Self {
755 let base = BlockBase::with_symbol(id, node, BlockKind::Call, parent, children, symbol);
756 Self {
757 base,
758 callee: RwLock::new(None),
759 args: RwLock::new(Vec::new()),
760 }
761 }
762
763 pub fn set_callee(&self, callee_id: BlockId) {
764 *self.callee.write() = Some(callee_id);
765 }
766
767 pub fn add_arg(&self, arg_id: BlockId) {
768 self.args.write().push(arg_id);
769 }
770
771 pub fn get_callee(&self) -> Option<BlockId> {
772 *self.callee.read()
773 }
774
775 pub fn get_args(&self) -> Vec<BlockId> {
776 self.args.read().clone()
777 }
778
779 pub fn format(&self) -> String {
780 format!("{}:{}", self.base.kind, self.base.id)
781 }
782}
783
784#[derive(Debug)]
785pub struct BlockClass<'blk> {
786 pub base: BlockBase<'blk>,
787 pub name: String,
788 pub fields: RwLock<Vec<BlockId>>,
789 pub methods: RwLock<Vec<BlockId>>,
790 pub extends: RwLock<Option<(String, Option<BlockId>)>>,
793}
794
795impl<'blk> BlockClass<'blk> {
796 pub fn new(
797 id: BlockId,
798 node: HirNode<'blk>,
799 parent: Option<BlockId>,
800 children: Vec<BlockId>,
801 ) -> Self {
802 Self::new_with_symbol(id, node, parent, children, None)
803 }
804
805 pub fn new_with_symbol(
806 id: BlockId,
807 node: HirNode<'blk>,
808 parent: Option<BlockId>,
809 children: Vec<BlockId>,
810 symbol: Option<&'blk Symbol>,
811 ) -> Self {
812 let base = BlockBase::with_symbol(id, node, BlockKind::Class, parent, children, symbol);
813 let name = base.opt_get_name().unwrap_or("").to_string();
814 Self {
815 base,
816 name,
817 fields: RwLock::new(Vec::new()),
818 methods: RwLock::new(Vec::new()),
819 extends: RwLock::new(None),
820 }
821 }
822
823 pub fn add_field(&self, field_id: BlockId) {
824 self.fields.write().push(field_id);
825 }
826
827 pub fn add_method(&self, method_id: BlockId) {
828 self.methods.write().push(method_id);
829 }
830
831 pub fn get_fields(&self) -> Vec<BlockId> {
832 self.fields.read().clone()
833 }
834
835 pub fn get_methods(&self) -> Vec<BlockId> {
836 self.methods.read().clone()
837 }
838
839 pub fn set_extends(&self, name: String, block_id: Option<BlockId>) {
841 *self.extends.write() = Some((name, block_id));
842 }
843
844 pub fn get_extends(&self) -> Option<(String, Option<BlockId>)> {
846 self.extends.read().clone()
847 }
848
849 pub fn format(&self) -> String {
850 let extends = self.extends.read();
851 if let Some((name, id)) = extends.as_ref() {
852 if let Some(block_id) = id {
853 format!(
854 "{}:{} {} @extends:{} {}",
855 self.base.kind, self.base.id, self.name, block_id, name
856 )
857 } else {
858 format!(
859 "{}:{} {} @extends {}",
860 self.base.kind, self.base.id, self.name, name
861 )
862 }
863 } else {
864 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
865 }
866 }
867
868 pub fn format_deps(&self, unit: CompileUnit<'blk>) -> Vec<String> {
871 let mut deps = Vec::new();
872
873 let type_deps = self.base.get_type_deps();
875 if !type_deps.is_empty() {
876 let mut sorted: Vec<_> = type_deps.iter().collect();
877 sorted.sort();
878 for dep_id in sorted {
879 let dep_block = unit.bb(*dep_id);
880 let dep_name = dep_block
881 .base()
882 .and_then(|b| b.opt_get_name())
883 .unwrap_or("");
884 deps.push(format!("@tdep:{} {}", dep_id, dep_name));
885 }
886 }
887
888 deps
889 }
890}
891
892#[derive(Debug)]
893pub struct BlockTrait<'blk> {
894 pub base: BlockBase<'blk>,
895 pub name: String,
896 pub methods: RwLock<Vec<BlockId>>,
897}
898
899impl<'blk> BlockTrait<'blk> {
900 pub fn new(
901 id: BlockId,
902 node: HirNode<'blk>,
903 parent: Option<BlockId>,
904 children: Vec<BlockId>,
905 ) -> Self {
906 Self::new_with_symbol(id, node, parent, children, None)
907 }
908
909 pub fn new_with_symbol(
910 id: BlockId,
911 node: HirNode<'blk>,
912 parent: Option<BlockId>,
913 children: Vec<BlockId>,
914 symbol: Option<&'blk Symbol>,
915 ) -> Self {
916 let base = BlockBase::with_symbol(id, node, BlockKind::Trait, parent, children, symbol);
917 let name = base.opt_get_name().unwrap_or("").to_string();
918 Self {
919 base,
920 name,
921 methods: RwLock::new(Vec::new()),
922 }
923 }
924
925 pub fn add_method(&self, method_id: BlockId) {
926 self.methods.write().push(method_id);
927 }
928
929 pub fn get_methods(&self) -> Vec<BlockId> {
930 self.methods.read().clone()
931 }
932
933 pub fn format(&self) -> String {
934 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
935 }
936}
937
938#[derive(Debug)]
940pub struct BlockInterface<'blk> {
941 pub base: BlockBase<'blk>,
942 pub name: String,
943 pub methods: RwLock<Vec<BlockId>>,
944 pub fields: RwLock<Vec<BlockId>>,
945 pub extends: RwLock<Vec<(String, Option<BlockId>)>>,
947}
948
949impl<'blk> BlockInterface<'blk> {
950 pub fn new(
951 id: BlockId,
952 node: HirNode<'blk>,
953 parent: Option<BlockId>,
954 children: Vec<BlockId>,
955 ) -> Self {
956 Self::new_with_symbol(id, node, parent, children, None)
957 }
958
959 pub fn new_with_symbol(
960 id: BlockId,
961 node: HirNode<'blk>,
962 parent: Option<BlockId>,
963 children: Vec<BlockId>,
964 symbol: Option<&'blk Symbol>,
965 ) -> Self {
966 let base = BlockBase::with_symbol(id, node, BlockKind::Interface, parent, children, symbol);
967 let name = base.opt_get_name().unwrap_or("").to_string();
968 Self {
969 base,
970 name,
971 methods: RwLock::new(Vec::new()),
972 fields: RwLock::new(Vec::new()),
973 extends: RwLock::new(Vec::new()),
974 }
975 }
976
977 pub fn add_method(&self, method_id: BlockId) {
978 self.methods.write().push(method_id);
979 }
980
981 pub fn get_methods(&self) -> Vec<BlockId> {
982 self.methods.read().clone()
983 }
984
985 pub fn add_field(&self, field_id: BlockId) {
986 self.fields.write().push(field_id);
987 }
988
989 pub fn get_fields(&self) -> Vec<BlockId> {
990 self.fields.read().clone()
991 }
992
993 pub fn add_extends(&self, name: String, block_id: Option<BlockId>) {
995 self.extends.write().push((name, block_id));
996 }
997
998 pub fn get_extends(&self) -> Vec<(String, Option<BlockId>)> {
1000 self.extends.read().clone()
1001 }
1002
1003 pub fn format(&self) -> String {
1004 let extends = self.extends.read();
1005 if extends.is_empty() {
1006 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1007 } else {
1008 let extends_list: Vec<_> = extends
1009 .iter()
1010 .map(|(name, id)| {
1011 if let Some(block_id) = id {
1012 format!("@extends:{} {}", block_id, name)
1013 } else {
1014 format!("@extends {}", name)
1015 }
1016 })
1017 .collect();
1018 format!(
1019 "{}:{} {} {}",
1020 self.base.kind,
1021 self.base.id,
1022 self.name,
1023 extends_list.join(" ")
1024 )
1025 }
1026 }
1027}
1028
1029#[derive(Debug)]
1030pub struct BlockImpl<'blk> {
1031 pub base: BlockBase<'blk>,
1032 pub name: String,
1033 pub target: RwLock<Option<BlockId>>,
1035 pub target_sym: Option<&'blk Symbol>,
1037 pub trait_ref: RwLock<Option<BlockId>>,
1039 pub trait_sym: Option<&'blk Symbol>,
1041 pub methods: RwLock<Vec<BlockId>>,
1042}
1043
1044impl<'blk> BlockImpl<'blk> {
1045 pub fn new(
1046 id: BlockId,
1047 node: HirNode<'blk>,
1048 parent: Option<BlockId>,
1049 children: Vec<BlockId>,
1050 ) -> Self {
1051 Self::new_with_symbol(id, node, parent, children, None)
1052 }
1053
1054 pub fn new_with_symbol(
1055 id: BlockId,
1056 node: HirNode<'blk>,
1057 parent: Option<BlockId>,
1058 children: Vec<BlockId>,
1059 symbol: Option<&'blk Symbol>,
1060 ) -> Self {
1061 let base = BlockBase::with_symbol(id, node, BlockKind::Impl, parent, children, symbol);
1062 let name = base.opt_get_name().unwrap_or("").to_string();
1063 Self {
1064 base,
1065 name,
1066 target: RwLock::new(None),
1067 target_sym: None,
1068 trait_ref: RwLock::new(None),
1069 trait_sym: None,
1070 methods: RwLock::new(Vec::new()),
1071 }
1072 }
1073
1074 pub fn set_target_info(&mut self, block_id: Option<BlockId>, sym: Option<&'blk Symbol>) {
1076 *self.target.write() = block_id;
1077 self.target_sym = sym;
1078 }
1079
1080 pub fn set_trait_info(&mut self, block_id: Option<BlockId>, sym: Option<&'blk Symbol>) {
1082 *self.trait_ref.write() = block_id;
1083 self.trait_sym = sym;
1084 }
1085
1086 pub fn set_target(&self, target_id: BlockId) {
1087 *self.target.write() = Some(target_id);
1088 }
1089
1090 pub fn set_trait_ref(&self, trait_id: BlockId) {
1091 *self.trait_ref.write() = Some(trait_id);
1092 }
1093
1094 pub fn add_method(&self, method_id: BlockId) {
1095 self.methods.write().push(method_id);
1096 }
1097
1098 pub fn get_target(&self) -> Option<BlockId> {
1099 *self.target.read()
1100 }
1101
1102 pub fn get_trait_ref(&self) -> Option<BlockId> {
1103 *self.trait_ref.read()
1104 }
1105
1106 pub fn get_methods(&self) -> Vec<BlockId> {
1107 self.methods.read().clone()
1108 }
1109
1110 pub fn format(&self) -> String {
1111 let mut parts = vec![format!("{}:{} {}", self.base.kind, self.base.id, self.name)];
1112 if let Some(target_id) = self.get_target() {
1113 parts.push(format!("@type:{target_id}"));
1114 }
1115 if let Some(trait_id) = self.get_trait_ref() {
1116 parts.push(format!("@trait:{trait_id}"));
1117 }
1118 parts.join(" ")
1119 }
1120}
1121
1122#[derive(Debug)]
1123pub struct BlockEnum<'blk> {
1124 pub base: BlockBase<'blk>,
1125 pub name: String,
1126 pub variants: RwLock<Vec<BlockId>>,
1127}
1128
1129impl<'blk> BlockEnum<'blk> {
1130 pub fn new(
1131 id: BlockId,
1132 node: HirNode<'blk>,
1133 parent: Option<BlockId>,
1134 children: Vec<BlockId>,
1135 ) -> Self {
1136 Self::new_with_symbol(id, node, parent, children, None)
1137 }
1138
1139 pub fn new_with_symbol(
1140 id: BlockId,
1141 node: HirNode<'blk>,
1142 parent: Option<BlockId>,
1143 children: Vec<BlockId>,
1144 symbol: Option<&'blk Symbol>,
1145 ) -> Self {
1146 let base = BlockBase::with_symbol(id, node, BlockKind::Enum, parent, children, symbol);
1147 let name = base.opt_get_name().unwrap_or("").to_string();
1148 Self {
1149 base,
1150 name,
1151 variants: RwLock::new(Vec::new()),
1152 }
1153 }
1154
1155 pub fn add_variant(&self, variant_id: BlockId) {
1156 self.variants.write().push(variant_id);
1157 }
1158
1159 pub fn get_variants(&self) -> Vec<BlockId> {
1160 self.variants.read().clone()
1161 }
1162
1163 pub fn format(&self) -> String {
1164 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1165 }
1166}
1167
1168#[derive(Debug)]
1169pub struct BlockConst<'blk> {
1170 pub base: BlockBase<'blk>,
1171 pub name: String,
1172 pub type_name: String,
1174 pub type_ref: RwLock<Option<BlockId>>,
1176}
1177
1178impl<'blk> BlockConst<'blk> {
1179 pub fn new(
1180 id: BlockId,
1181 node: HirNode<'blk>,
1182 parent: Option<BlockId>,
1183 children: Vec<BlockId>,
1184 ) -> Self {
1185 Self::new_with_symbol(id, node, parent, children, None)
1186 }
1187
1188 pub fn new_with_symbol(
1189 id: BlockId,
1190 node: HirNode<'blk>,
1191 parent: Option<BlockId>,
1192 children: Vec<BlockId>,
1193 symbol: Option<&'blk Symbol>,
1194 ) -> Self {
1195 let base = BlockBase::with_symbol(id, node, BlockKind::Const, parent, children, symbol);
1196 let name = base.opt_get_name().unwrap_or("").to_string();
1197 Self {
1198 base,
1199 name,
1200 type_name: String::new(),
1201 type_ref: RwLock::new(None),
1202 }
1203 }
1204
1205 pub fn set_type_info(&mut self, type_name: String, type_ref: Option<BlockId>) {
1207 self.type_name = type_name;
1208 *self.type_ref.write() = type_ref;
1209 }
1210
1211 pub fn set_type_ref(&self, type_ref: BlockId) {
1213 *self.type_ref.write() = Some(type_ref);
1214 }
1215
1216 pub fn get_type_ref(&self) -> Option<BlockId> {
1218 *self.type_ref.read()
1219 }
1220
1221 pub fn format(&self) -> String {
1222 if !self.type_name.is_empty() {
1223 if let Some(type_id) = *self.type_ref.read() {
1224 return format!(
1225 "{}:{} {} @type:{} {}",
1226 self.base.kind, self.base.id, self.name, type_id, self.type_name
1227 );
1228 } else {
1229 return format!(
1230 "{}:{} {} @type {}",
1231 self.base.kind, self.base.id, self.name, self.type_name
1232 );
1233 }
1234 }
1235 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1236 }
1237}
1238
1239#[derive(Debug)]
1240pub struct BlockField<'blk> {
1241 pub base: BlockBase<'blk>,
1242 pub name: String,
1243 pub type_name: String,
1245 pub type_ref: RwLock<Option<BlockId>>,
1247}
1248
1249impl<'blk> BlockField<'blk> {
1250 pub fn new(
1251 id: BlockId,
1252 node: HirNode<'blk>,
1253 parent: Option<BlockId>,
1254 children: Vec<BlockId>,
1255 ) -> Self {
1256 Self::new_with_symbol(id, node, parent, children, None)
1257 }
1258
1259 pub fn new_with_symbol(
1260 id: BlockId,
1261 node: HirNode<'blk>,
1262 parent: Option<BlockId>,
1263 children: Vec<BlockId>,
1264 symbol: Option<&'blk Symbol>,
1265 ) -> Self {
1266 let base = BlockBase::with_symbol(id, node, BlockKind::Field, parent, children, symbol);
1267 let name = base
1269 .opt_get_name()
1270 .map(|s| s.to_string())
1271 .or_else(|| {
1272 node.as_scope()
1274 .and_then(|scope| scope.opt_ident())
1275 .map(|ident| ident.name.to_string())
1276 })
1277 .unwrap_or_default();
1278 Self {
1279 base,
1280 name,
1281 type_name: String::new(),
1282 type_ref: RwLock::new(None),
1283 }
1284 }
1285
1286 pub fn set_type_info(&mut self, type_name: String, type_ref: Option<BlockId>) {
1288 self.type_name = type_name;
1289 *self.type_ref.write() = type_ref;
1290 }
1291
1292 pub fn set_type_ref(&self, type_ref: BlockId) {
1294 *self.type_ref.write() = Some(type_ref);
1295 }
1296
1297 pub fn get_type_ref(&self) -> Option<BlockId> {
1299 *self.type_ref.read()
1300 }
1301
1302 pub fn format(&self) -> String {
1303 if !self.type_name.is_empty() {
1304 if let Some(type_id) = *self.type_ref.read() {
1305 return format!(
1306 "{}:{} {} @type:{} {}",
1307 self.base.kind, self.base.id, self.name, type_id, self.type_name
1308 );
1309 } else {
1310 return format!(
1311 "{}:{} {} @type {}",
1312 self.base.kind, self.base.id, self.name, self.type_name
1313 );
1314 }
1315 }
1316 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1317 }
1318}
1319
1320#[derive(Debug)]
1322pub struct BlockParameter<'blk> {
1323 pub base: BlockBase<'blk>,
1324 pub name: String,
1326 pub type_name: String,
1328 pub type_ref: RwLock<Option<BlockId>>,
1330}
1331
1332impl<'blk> BlockParameter<'blk> {
1333 pub fn new(
1335 id: BlockId,
1336 node: HirNode<'blk>,
1337 parent: Option<BlockId>,
1338 children: Vec<BlockId>,
1339 ) -> Self {
1340 Self::new_with_symbol(id, node, parent, children, None)
1341 }
1342
1343 pub fn new_with_symbol(
1344 id: BlockId,
1345 node: HirNode<'blk>,
1346 parent: Option<BlockId>,
1347 children: Vec<BlockId>,
1348 symbol: Option<&'blk Symbol>,
1349 ) -> Self {
1350 let base = BlockBase::with_symbol(id, node, BlockKind::Parameter, parent, children, symbol);
1351 let name = base
1353 .opt_get_name()
1354 .map(|s| s.to_string())
1355 .or_else(|| {
1356 node.as_scope()
1358 .and_then(|scope| scope.opt_ident())
1359 .map(|ident| ident.name.to_string())
1360 })
1361 .unwrap_or_default();
1362 Self {
1363 base,
1364 name,
1365 type_name: String::new(),
1366 type_ref: RwLock::new(None),
1367 }
1368 }
1369
1370 pub fn set_type_info(&mut self, type_name: String, type_ref: Option<BlockId>) {
1372 self.type_name = type_name;
1373 *self.type_ref.write() = type_ref;
1374 }
1375
1376 pub fn set_type_ref(&self, type_ref: BlockId) {
1378 *self.type_ref.write() = Some(type_ref);
1379 }
1380
1381 pub fn get_type_ref(&self) -> Option<BlockId> {
1383 *self.type_ref.read()
1384 }
1385
1386 pub fn format(&self) -> String {
1387 if !self.type_name.is_empty() {
1388 if let Some(type_id) = *self.type_ref.read() {
1389 return format!(
1390 "{}:{} {} @type:{} {}",
1391 self.base.kind, self.base.id, self.name, type_id, self.type_name
1392 );
1393 } else {
1394 return format!(
1395 "{}:{} {} @type {}",
1396 self.base.kind, self.base.id, self.name, self.type_name
1397 );
1398 }
1399 }
1400 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1401 }
1402}
1403
1404#[derive(Debug)]
1406pub struct BlockReturn<'blk> {
1407 pub base: BlockBase<'blk>,
1408 pub type_name: String,
1410 pub type_ref: RwLock<Option<BlockId>>,
1412}
1413
1414impl<'blk> BlockReturn<'blk> {
1415 pub fn new(
1416 id: BlockId,
1417 node: HirNode<'blk>,
1418 parent: Option<BlockId>,
1419 children: Vec<BlockId>,
1420 ) -> Self {
1421 Self::new_with_symbol(id, node, parent, children, None)
1422 }
1423
1424 pub fn new_with_symbol(
1425 id: BlockId,
1426 node: HirNode<'blk>,
1427 parent: Option<BlockId>,
1428 children: Vec<BlockId>,
1429 symbol: Option<&'blk Symbol>,
1430 ) -> Self {
1431 let base = BlockBase::with_symbol(id, node, BlockKind::Return, parent, children, symbol);
1432 Self {
1433 base,
1434 type_name: String::new(),
1435 type_ref: RwLock::new(None),
1436 }
1437 }
1438
1439 pub fn set_type_info(&mut self, type_name: String, type_ref: Option<BlockId>) {
1441 self.type_name = type_name;
1442 *self.type_ref.write() = type_ref;
1443 }
1444
1445 pub fn set_type_ref(&self, type_ref: BlockId) {
1447 *self.type_ref.write() = Some(type_ref);
1448 }
1449
1450 pub fn get_type_ref(&self) -> Option<BlockId> {
1452 *self.type_ref.read()
1453 }
1454
1455 pub fn format(&self) -> String {
1456 if !self.type_name.is_empty() {
1457 if let Some(type_id) = *self.type_ref.read() {
1458 return format!(
1459 "{}:{} @type:{} {}",
1460 self.base.kind, self.base.id, type_id, self.type_name
1461 );
1462 } else {
1463 return format!(
1464 "{}:{} @type {}",
1465 self.base.kind, self.base.id, self.type_name
1466 );
1467 }
1468 }
1469 format!("{}:{}", self.base.kind, self.base.id)
1470 }
1471}
1472
1473#[derive(Debug)]
1474pub struct BlockAlias<'blk> {
1475 pub base: BlockBase<'blk>,
1476 pub name: String,
1477}
1478
1479impl<'blk> BlockAlias<'blk> {
1480 pub fn new(
1481 id: BlockId,
1482 node: HirNode<'blk>,
1483 parent: Option<BlockId>,
1484 children: Vec<BlockId>,
1485 ) -> Self {
1486 Self::new_with_symbol(id, node, parent, children, None)
1487 }
1488
1489 pub fn new_with_symbol(
1490 id: BlockId,
1491 node: HirNode<'blk>,
1492 parent: Option<BlockId>,
1493 children: Vec<BlockId>,
1494 symbol: Option<&'blk Symbol>,
1495 ) -> Self {
1496 let base = BlockBase::with_symbol(id, node, BlockKind::Alias, parent, children, symbol);
1497 let name = base.opt_get_name().unwrap_or("").to_string();
1498 Self { base, name }
1499 }
1500
1501 pub fn format(&self) -> String {
1502 format!("{}:{} {}", self.base.kind, self.base.id, self.name)
1503 }
1504}