veryl_analyzer/
namespace.rs1use crate::attribute::Attribute;
2use crate::attribute_table;
3use crate::namespace_table;
4use crate::symbol::Symbol;
5use crate::symbol::SymbolKind;
6use crate::symbol_path::SymbolPath;
7use crate::symbol_table;
8use crate::{HashMap, SVec, svec};
9use std::collections::BTreeSet;
10use std::fmt;
11use veryl_parser::resource_table::{self, StrId};
12use veryl_parser::veryl_token::{Token, VerylToken};
13
14#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
15pub struct DefineContext {
16 pos: BTreeSet<StrId>,
17 neg: BTreeSet<StrId>,
18}
19
20impl DefineContext {
21 pub fn exclusive(&self, value: &DefineContext) -> bool {
22 !self.pos.is_disjoint(&value.neg) || !self.neg.is_disjoint(&value.pos)
23 }
24
25 pub fn is_default(&self) -> bool {
26 self.pos.is_empty()
27 }
28}
29
30impl From<Token> for DefineContext {
31 fn from(token: Token) -> Self {
32 let attrs = attribute_table::get(&token);
33 attrs.as_slice().into()
34 }
35}
36
37impl From<&VerylToken> for DefineContext {
38 fn from(token: &VerylToken) -> Self {
39 let attrs = attribute_table::get(&token.token);
40 attrs.as_slice().into()
41 }
42}
43
44impl From<&[Attribute]> for DefineContext {
45 fn from(value: &[Attribute]) -> Self {
46 let mut ret = DefineContext::default();
47 for x in value {
48 match x {
49 Attribute::Ifdef(x) => {
50 ret.pos.insert(*x);
51 }
52 Attribute::Ifndef(x) => {
53 ret.neg.insert(*x);
54 }
55 Attribute::Elsif(x, y, z) => {
56 ret.pos.insert(*x);
57 for y in y {
58 ret.pos.insert(*y);
59 }
60 for z in z {
61 ret.neg.insert(*z);
62 }
63 }
64 Attribute::Else(x, y) => {
65 for x in x {
66 ret.pos.insert(*x);
67 }
68 for y in y {
69 ret.neg.insert(*y);
70 }
71 }
72 _ => (),
73 }
74 }
75 ret
76 }
77}
78
79impl fmt::Display for DefineContext {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 let mut text = String::new();
82 for x in &self.pos {
83 text.push_str(&format!("+{x}"));
84 }
85 for x in &self.neg {
86 text.push_str(&format!("-{x}"));
87 }
88 text.fmt(f)
89 }
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, Hash)]
93pub struct Namespace {
94 pub paths: SVec<StrId>,
95 pub define_context: DefineContext,
96}
97
98impl Namespace {
99 pub fn new() -> Self {
100 Self {
101 paths: SVec::new(),
102 define_context: DefineContext::default(),
103 }
104 }
105
106 pub fn push(&mut self, path: StrId) {
107 self.paths.push(resource_table::canonical_str_id(path));
108 }
109
110 pub fn pop(&mut self) -> Option<StrId> {
111 self.paths.pop()
112 }
113
114 pub fn depth(&self) -> usize {
115 self.paths.len()
116 }
117
118 pub fn included(&self, x: &Namespace) -> bool {
119 let exclusive = self.define_context.exclusive(&x.define_context);
120 for (i, x) in x.paths.iter().enumerate() {
121 if let Some(path) = self.paths.get(i) {
122 if path != x {
123 return false;
124 }
125 } else {
126 return false;
127 }
128 }
129 !exclusive
130 }
131
132 pub fn matched(&self, x: &Namespace) -> bool {
133 if self.paths.len() != x.paths.len() {
134 false
135 } else {
136 self.included(x)
137 }
138 }
139
140 pub fn replace(&self, table: &HashMap<StrId, StrId>) -> Self {
141 let mut paths = SVec::new();
142 for x in &self.paths {
143 if let Some(x) = table.get(x) {
144 paths.push(*x);
145 } else {
146 paths.push(*x);
147 }
148 }
149 Self {
150 paths,
151 define_context: self.define_context.clone(),
152 }
153 }
154
155 pub fn strip_prefix(&mut self, x: &Namespace) {
156 let mut paths = svec![];
157 for (i, p) in self.paths.iter().enumerate() {
158 if x.paths.get(i) != Some(p) {
159 paths.push(*p);
160 }
161 }
162 self.paths = paths;
163 }
164
165 pub fn strip_anonymous_path(&mut self) {
166 self.paths.retain(|x| x.to_string().find('@').is_none());
167 }
168
169 pub fn get_symbol(&self) -> Option<Symbol> {
170 let mut namespace = self.clone();
171 namespace.strip_anonymous_path();
172
173 if let Some(path) = namespace.pop()
174 && namespace.depth() >= 1
175 {
176 symbol_table::resolve((path, &namespace))
177 .map(|x| (*x.found).clone())
178 .ok()
179 } else {
180 None
181 }
182 }
183
184 pub fn generic_namespace(&self) -> Self {
185 let mut ret = Namespace::new();
186 for i in 0..self.depth() {
187 let path = self.paths[i];
188 if i == 0 || !path.to_string().starts_with("__") {
189 ret.push(path);
190 } else if let Ok(symbol) = symbol_table::resolve((path, &ret))
191 && let SymbolKind::GenericInstance(inst) = &symbol.found.kind
192 {
193 let base = inst.base_symbol();
194 ret.push(base.token.text);
195 }
196 }
197 ret
198 }
199}
200
201impl Default for Namespace {
202 fn default() -> Self {
203 namespace_table::get_default()
204 }
205}
206
207impl fmt::Display for Namespace {
208 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209 let mut text = String::new();
210 if let Some(first) = self.paths.first() {
211 text.push_str(&format!("{first}"));
212 for path in &self.paths[1..] {
213 text.push_str(&format!("::{path}"));
214 }
215 }
216 text.push_str(&self.define_context.to_string());
217 text.fmt(f)
218 }
219}
220
221impl From<&SymbolPath> for Namespace {
222 fn from(value: &SymbolPath) -> Self {
223 let mut paths = SVec::new();
224 for x in value.as_slice() {
225 paths.push(*x);
226 }
227 Namespace {
228 paths,
229 define_context: DefineContext::default(),
230 }
231 }
232}
233
234impl From<&[StrId]> for Namespace {
235 fn from(value: &[StrId]) -> Self {
236 Namespace {
237 paths: value.into(),
238 define_context: DefineContext::default(),
239 }
240 }
241}
242
243impl From<&str> for Namespace {
244 fn from(value: &str) -> Self {
245 let mut paths = SVec::new();
246 for x in value.split("::") {
247 paths.push(x.into());
248 }
249 Namespace {
250 paths,
251 define_context: DefineContext::default(),
252 }
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259
260 #[test]
261 fn define_context() {
262 let mut a = DefineContext::default();
263 a.pos.insert(StrId(0));
264 a.pos.insert(StrId(1));
265 a.neg.insert(StrId(2));
266 let mut b = DefineContext::default();
267 b.pos.insert(StrId(2));
268
269 assert!(a.exclusive(&b));
270
271 let mut a = DefineContext::default();
272 a.pos.insert(StrId(0));
273 a.pos.insert(StrId(1));
274 a.neg.insert(StrId(2));
275 let mut b = DefineContext::default();
276 b.pos.insert(StrId(1));
277
278 assert!(!a.exclusive(&b));
279
280 let mut a = DefineContext::default();
281 a.pos.insert(StrId(0));
282 a.pos.insert(StrId(1));
283 a.neg.insert(StrId(2));
284 let mut b = DefineContext::default();
285 b.neg.insert(StrId(0));
286
287 assert!(a.exclusive(&b));
288
289 let a = DefineContext::default();
290 let b = DefineContext::default();
291
292 assert!(!a.exclusive(&b));
293 }
294}