@@ -7,6 +7,7 @@ use crate::traversal::pragma::check_pragma_version;
7
7
use crate :: AnalyzerDb ;
8
8
use fe_common:: diagnostics:: Diagnostic ;
9
9
use fe_parser:: ast;
10
+ use fe_parser:: ast:: Expr ;
10
11
use fe_parser:: node:: { Node , Span } ;
11
12
use indexmap:: IndexMap ;
12
13
use std:: rc:: Rc ;
@@ -71,6 +72,19 @@ impl ModuleId {
71
72
db. module_structs ( * self )
72
73
}
73
74
75
+ /// All constants, including duplicates
76
+ pub fn all_constants ( & self , db : & dyn AnalyzerDb ) -> Rc < Vec < ModuleConstantId > > {
77
+ db. module_constants ( * self )
78
+ }
79
+
80
+ /// Get constant by name
81
+ pub fn lookup_constant ( & self , db : & dyn AnalyzerDb , name : & str ) -> Option < ModuleConstantId > {
82
+ self . all_constants ( db)
83
+ . iter ( )
84
+ . cloned ( )
85
+ . find ( |item| item. name ( db) == name)
86
+ }
87
+
74
88
pub fn diagnostics ( & self , db : & dyn AnalyzerDb ) -> Vec < Diagnostic > {
75
89
let mut diagnostics = vec ! [ ] ;
76
90
self . sink_diagnostics ( db, & mut diagnostics) ;
@@ -89,6 +103,10 @@ impl ModuleId {
89
103
ast:: ModuleStmt :: Use ( inner) => {
90
104
sink. push ( & errors:: not_yet_implemented ( "use" , inner. span ) ) ;
91
105
}
106
+ ast:: ModuleStmt :: Constant ( _) => self
107
+ . all_constants ( db)
108
+ . iter ( )
109
+ . for_each ( |id| id. sink_diagnostics ( db, sink) ) ,
92
110
_ => { } // everything else is a type def, handled below.
93
111
}
94
112
}
@@ -103,6 +121,58 @@ impl ModuleId {
103
121
}
104
122
}
105
123
124
+ #[ derive( Debug , PartialEq , Eq , Hash , Clone ) ]
125
+ pub struct ModuleConstant {
126
+ pub ast : Node < ast:: ConstantDecl > ,
127
+ pub module : ModuleId ,
128
+ }
129
+
130
+ #[ derive( Debug , PartialEq , Eq , Hash , Copy , Clone ) ]
131
+ pub struct ModuleConstantId ( pub ( crate ) u32 ) ;
132
+ impl_intern_key ! ( ModuleConstantId ) ;
133
+
134
+ impl ModuleConstantId {
135
+ pub fn data ( & self , db : & dyn AnalyzerDb ) -> Rc < ModuleConstant > {
136
+ db. lookup_intern_module_const ( * self )
137
+ }
138
+ pub fn span ( & self , db : & dyn AnalyzerDb ) -> Span {
139
+ self . data ( db) . ast . span
140
+ }
141
+ pub fn typ ( & self , db : & dyn AnalyzerDb ) -> Result < types:: Type , TypeError > {
142
+ db. module_constant_type ( * self ) . value
143
+ }
144
+
145
+ pub fn is_base_type ( & self , db : & dyn AnalyzerDb ) -> bool {
146
+ matches ! ( self . typ( db) , Ok ( types:: Type :: Base ( _) ) )
147
+ }
148
+
149
+ pub fn name ( & self , db : & dyn AnalyzerDb ) -> String {
150
+ self . data ( db) . ast . kind . name . kind . clone ( )
151
+ }
152
+
153
+ pub fn value ( & self , db : & dyn AnalyzerDb ) -> fe_parser:: ast:: Expr {
154
+ self . data ( db) . ast . kind . value . kind . clone ( )
155
+ }
156
+
157
+ pub fn sink_diagnostics ( & self , db : & dyn AnalyzerDb , sink : & mut impl DiagnosticSink ) {
158
+ db. module_constant_type ( * self )
159
+ . diagnostics
160
+ . iter ( )
161
+ . for_each ( |d| sink. push ( d) ) ;
162
+
163
+ if !matches ! (
164
+ self . value( db) ,
165
+ Expr :: Bool ( _) | Expr :: Num ( _) | Expr :: Str ( _) | Expr :: Unit
166
+ ) {
167
+ sink. push ( & errors:: error (
168
+ "non-literal expressions not yet supported for constants" ,
169
+ self . data ( db) . ast . kind . value . span ,
170
+ "not a literal" ,
171
+ ) )
172
+ }
173
+ }
174
+ }
175
+
106
176
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
107
177
pub enum TypeDefId {
108
178
Alias ( TypeAliasId ) ,
0 commit comments