dada_ir_sym/check/
scope_tree.rs1use dada_ir_ast::ast::{AstModule, AstWhereClause};
2use dada_util::FromImpls;
3use salsa::Update;
4use serde::Serialize;
5
6use crate::{
7 check::scope::Scope, ir::classes::SymAggregate, ir::functions::SymFunction,
8 ir::module::SymModule, ir::variables::SymVariable,
9};
10
11#[derive(
13 Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Update, FromImpls, Serialize,
14)]
15pub enum ScopeItem<'db> {
16 AstModule(AstModule<'db>),
18
19 SymModule(SymModule<'db>),
21
22 Class(SymAggregate<'db>),
24
25 SymFunction(SymFunction<'db>),
27}
28
29pub trait ScopeTreeNode<'db>: Sized + Into<ScopeItem<'db>> {
30 fn into_scope(self, db: &'db dyn crate::Db) -> Scope<'db, 'db>;
32
33 fn direct_super_scope(self, db: &'db dyn crate::Db) -> Option<ScopeItem<'db>>;
34
35 fn iter_super_scopes(self, db: &'db dyn crate::Db) -> impl Iterator<Item = ScopeItem<'db>> {
37 let mut cursor: Option<ScopeItem<'db>> = Some(self.into());
38 std::iter::from_fn(move || {
39 let p = cursor?;
40 cursor = p.direct_super_scope(db);
41 Some(p)
42 })
43 }
44
45 fn direct_generic_parameters(self, db: &'db dyn crate::Db) -> &'db Vec<SymVariable<'db>>;
46
47 fn transitive_generic_parameters(self, db: &'db dyn crate::Db) -> Vec<SymVariable<'db>> {
50 let mut generic_parameters = self
51 .iter_super_scopes(db)
52 .flat_map(|s| s.direct_generic_parameters(db).iter().rev())
53 .copied()
54 .collect::<Vec<_>>();
55 generic_parameters.reverse();
56 generic_parameters
57 }
58
59 fn expected_generic_parameters(self, db: &'db dyn crate::Db) -> usize {
62 self.iter_super_scopes(db)
63 .flat_map(|s| s.direct_generic_parameters(db).iter().rev())
64 .copied()
65 .count()
66 }
67
68 fn push_direct_ast_where_clauses(
69 self,
70 db: &'db dyn crate::Db,
71 out: &mut Vec<AstWhereClause<'db>>,
72 );
73
74 fn push_transitive_where_clauses(
75 self,
76 db: &'db dyn crate::Db,
77 out: &mut Vec<AstWhereClause<'db>>,
78 ) {
79 self.iter_super_scopes(db)
80 .for_each(|s| s.push_direct_ast_where_clauses(db, out));
81 }
82}
83
84impl<'db> ScopeTreeNode<'db> for ScopeItem<'db> {
85 fn direct_super_scope(self, db: &'db dyn crate::Db) -> Option<ScopeItem<'db>> {
86 match self {
87 ScopeItem::AstModule(sym) => sym.direct_super_scope(db),
88 ScopeItem::SymModule(sym) => sym.direct_super_scope(db),
89 ScopeItem::Class(sym) => sym.direct_super_scope(db),
90 ScopeItem::SymFunction(sym) => sym.direct_super_scope(db),
91 }
92 }
93
94 fn direct_generic_parameters(self, db: &'db dyn crate::Db) -> &'db Vec<SymVariable<'db>> {
95 match self {
96 ScopeItem::AstModule(sym) => sym.direct_generic_parameters(db),
97 ScopeItem::SymModule(sym) => sym.direct_generic_parameters(db),
98 ScopeItem::Class(sym) => sym.direct_generic_parameters(db),
99 ScopeItem::SymFunction(sym) => sym.direct_generic_parameters(db),
100 }
101 }
102
103 fn into_scope(self, db: &'db dyn crate::Db) -> Scope<'db, 'db> {
104 match self {
105 ScopeItem::AstModule(sym) => sym.into_scope(db),
106 ScopeItem::SymModule(sym) => sym.into_scope(db),
107 ScopeItem::Class(sym) => sym.into_scope(db),
108 ScopeItem::SymFunction(sym) => sym.into_scope(db),
109 }
110 }
111
112 fn push_direct_ast_where_clauses(
113 self,
114 db: &'db dyn crate::Db,
115 out: &mut Vec<AstWhereClause<'db>>,
116 ) {
117 match self {
118 ScopeItem::AstModule(_) => {}
119 ScopeItem::SymModule(_) => {}
120 ScopeItem::Class(sym) => {
121 sym.push_direct_ast_where_clauses(db, out);
122 }
123 ScopeItem::SymFunction(sym) => {
124 sym.push_direct_ast_where_clauses(db, out);
125 }
126 }
127 }
128}