Skip to main content

veryl_analyzer/
symbol.rs

1use crate::HashMap;
2use crate::attribute::EnumEncodingItem;
3use crate::conv::Context;
4use crate::conv::utils::{TypePosition, eval_generic_expr, eval_size, eval_type};
5use crate::definition_table::DefinitionId;
6use crate::ir::{self, Shape};
7use crate::literal::Literal;
8use crate::literal_table;
9use crate::namespace::Namespace;
10use crate::namespace_table;
11use crate::symbol_path::{GenericSymbolPath, GenericSymbolPathKind, SymbolPath};
12use crate::symbol_table::{self, Import};
13use crate::value::Value;
14use std::cell::RefCell;
15use std::fmt;
16use std::hash::{DefaultHasher, Hash, Hasher};
17use veryl_parser::Stringifier;
18use veryl_parser::resource_table::{self, PathId, StrId};
19use veryl_parser::token_range::TokenRange;
20use veryl_parser::veryl_grammar_trait::{self as syntax_tree, ArrayType};
21use veryl_parser::veryl_token::{Token, VerylToken};
22use veryl_parser::veryl_walker::VerylWalker;
23
24#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub struct SymbolId(pub usize);
26
27thread_local!(static SYMBOL_ID: RefCell<usize> = const { RefCell::new(0) });
28
29pub fn new_symbol_id() -> SymbolId {
30    SYMBOL_ID.with(|f| {
31        let mut ret = f.borrow_mut();
32        *ret += 1;
33        SymbolId(*ret)
34    })
35}
36
37/// A single line of a doc comment with its source line number.
38#[derive(Debug, Clone)]
39pub struct DocCommentLine {
40    pub text: StrId,
41    pub line: u32,
42}
43
44#[derive(Debug, Default, Clone)]
45pub struct DocComment(pub Vec<DocCommentLine>);
46
47impl DocComment {
48    pub fn format(&self, single_line: bool) -> String {
49        let mut ret = String::new();
50        for entry in &self.0 {
51            let t = format!("{}", entry.text);
52            let t = t.trim_start_matches("///");
53            ret.push_str(t);
54            if single_line {
55                break;
56            }
57        }
58        ret
59    }
60
61    pub fn is_empty(&self) -> bool {
62        self.0.is_empty()
63    }
64
65    /// Extract WaveDrom JSON from doc comment fenced code blocks.
66    pub fn extract_wavedrom(&self) -> Option<String> {
67        self.extract_wavedrom_block(false).map(|block| block.json)
68    }
69
70    /// Extract WaveDrom JSON only from ```wavedrom,test blocks.
71    pub fn extract_wavedrom_test(&self) -> Option<String> {
72        self.extract_wavedrom_block(true).map(|block| block.json)
73    }
74
75    /// Extract a WaveDrom block with full source location info.
76    pub fn extract_wavedrom_block(&self, test_only: bool) -> Option<WavedromBlock> {
77        let mut in_wavedrom = false;
78        let mut json_lines = Vec::new();
79        let mut fence_line = 0u32;
80        let mut end_line = 0u32;
81        let mut content_lines: Vec<(String, u32)> = Vec::new();
82
83        for entry in &self.0 {
84            let text = format!("{}", entry.text);
85            let trimmed = text.trim_start_matches("///").trim();
86            if !in_wavedrom {
87                let is_match = if test_only {
88                    if let Some(rest) = trimmed.strip_prefix("```wavedrom")
89                        && let Some(attrs) = rest.trim().strip_prefix(',')
90                    {
91                        attrs.trim() == "test"
92                    } else {
93                        false
94                    }
95                } else {
96                    trimmed.starts_with("```wavedrom")
97                };
98                if is_match {
99                    in_wavedrom = true;
100                    json_lines.clear();
101                    content_lines.clear();
102                    fence_line = entry.line;
103                }
104            } else if trimmed == "```" {
105                end_line = entry.line;
106                let json = json_lines.join("\n");
107                if !json.trim().is_empty() {
108                    return Some(WavedromBlock {
109                        json,
110                        fence_line,
111                        end_line,
112                        content_lines,
113                    });
114                }
115                in_wavedrom = false;
116            } else {
117                json_lines.push(trimmed.to_string());
118                content_lines.push((trimmed.to_string(), entry.line));
119            }
120        }
121
122        None
123    }
124}
125
126/// Extracted WaveDrom block with source location info.
127#[derive(Debug)]
128pub struct WavedromBlock {
129    pub json: String,
130    pub fence_line: u32,
131    pub end_line: u32,
132    pub content_lines: Vec<(String, u32)>,
133}
134
135impl WavedromBlock {
136    /// Find the source line number of a content line that contains the given text.
137    pub fn find_line_containing(&self, needle: &str) -> Option<u32> {
138        self.content_lines
139            .iter()
140            .find(|(text, _)| text.contains(needle))
141            .map(|(_, line)| *line)
142    }
143}
144
145pub type GenericTable = HashMap<StrId, GenericSymbolPath>;
146pub type GenericTables = HashMap<Namespace, GenericTable>;
147
148#[derive(Clone, Debug, Default)]
149pub struct GenericMap {
150    pub id: Option<SymbolId>,
151    pub map: GenericTable,
152}
153
154impl GenericMap {
155    pub fn generic(&self) -> bool {
156        !self.map.is_empty()
157    }
158
159    pub fn name(&self, include_namspace_prefix: bool, hashed_name: bool) -> String {
160        let symbol = symbol_table::get(self.id.unwrap()).unwrap();
161        if let SymbolKind::GenericInstance(x) = symbol.kind {
162            let base = symbol_table::get(x.base).unwrap();
163            if hashed_name {
164                format!(
165                    "{}__{}__{:x}",
166                    self.get_name_prefix(&base, include_namspace_prefix),
167                    base.token,
168                    self.calc_args_hash(&x.arguments),
169                )
170            } else {
171                format!(
172                    "{}{}",
173                    self.get_name_prefix(&base, include_namspace_prefix),
174                    symbol.token
175                )
176            }
177        } else {
178            format!(
179                "{}{}",
180                self.get_name_prefix(&symbol, include_namspace_prefix),
181                symbol.token
182            )
183        }
184    }
185
186    fn get_name_prefix(&self, symbol: &Symbol, include_namspace_prefix: bool) -> String {
187        let emit_namespace_preffix = match &symbol.kind {
188            SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_) => {
189                include_namspace_prefix
190            }
191            SymbolKind::Function(x) => include_namspace_prefix && x.is_global(),
192            _ => false,
193        };
194        if emit_namespace_preffix {
195            format!("{}_", symbol.namespace)
196        } else {
197            "".to_string()
198        }
199    }
200
201    fn calc_args_hash(&self, args: &[GenericSymbolPath]) -> u64 {
202        let string_args: Vec<_> = args.iter().map(|x| x.to_string()).collect();
203        let mut hasher = DefaultHasher::new();
204        string_args.hash(&mut hasher);
205        hasher.finish()
206    }
207}
208
209impl fmt::Display for GenericMap {
210    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211        let mut ret = String::new();
212
213        for (k, v) in &self.map {
214            ret.push_str(&format!("{k}: {v}"));
215        }
216
217        ret.fmt(f)
218    }
219}
220
221#[derive(Debug, Clone)]
222pub struct Symbol {
223    pub token: Token,
224    pub id: SymbolId,
225    pub kind: SymbolKind,
226    pub namespace: Namespace,
227    pub references: Vec<Token>,
228    pub generic_instances: Vec<SymbolId>,
229    pub imported: Vec<Import>,
230    pub allow_unused: bool,
231    pub public: bool,
232    pub doc_comment: DocComment,
233}
234
235impl Symbol {
236    pub fn new(
237        token: &Token,
238        kind: SymbolKind,
239        namespace: &Namespace,
240        public: bool,
241        doc_comment: DocComment,
242    ) -> Self {
243        Self {
244            token: *token,
245            id: new_symbol_id(),
246            kind,
247            namespace: namespace.to_owned(),
248            references: Vec::new(),
249            generic_instances: Vec::new(),
250            imported: Vec::new(),
251            allow_unused: false,
252            public,
253            doc_comment,
254        }
255    }
256
257    pub fn get_parent(&self) -> Option<Symbol> {
258        self.namespace.get_symbol()
259    }
260
261    pub fn get_parent_component(&self) -> Option<Symbol> {
262        let parent = self.get_parent()?;
263        Symbol::trace_component_symbol(&parent)
264    }
265
266    fn trace_component_symbol(symbol: &Symbol) -> Option<Symbol> {
267        match &symbol.kind {
268            SymbolKind::Module(_)
269            | SymbolKind::ProtoModule(_)
270            | SymbolKind::Interface(_)
271            | SymbolKind::ProtoInterface(_)
272            | SymbolKind::Package(_)
273            | SymbolKind::ProtoPackage(_)
274            | SymbolKind::SystemVerilog => Some(symbol.clone()),
275            SymbolKind::AliasModule(x) | SymbolKind::ProtoAliasModule(x) => {
276                let symbol =
277                    symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
278                Symbol::trace_component_symbol(&symbol.found)
279            }
280            SymbolKind::AliasInterface(x) | SymbolKind::ProtoAliasInterface(x) => {
281                let symbol =
282                    symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
283                Symbol::trace_component_symbol(&symbol.found)
284            }
285            SymbolKind::AliasPackage(x) | SymbolKind::ProtoAliasPackage(x) => {
286                let symbol =
287                    symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
288                Symbol::trace_component_symbol(&symbol.found)
289            }
290            SymbolKind::GenericInstance(x) => {
291                let symbol = symbol_table::get(x.base)?;
292                Symbol::trace_component_symbol(&symbol)
293            }
294            SymbolKind::GenericParameter(x) => {
295                if let Ok(ProtoBound::ProtoPackage(x)) =
296                    x.bound.resolve_proto_bound(&symbol.namespace)
297                {
298                    Symbol::trace_component_symbol(&x)
299                } else {
300                    None
301                }
302            }
303            _ => None,
304        }
305    }
306
307    pub fn get_parent_package(&self) -> Option<Symbol> {
308        let parent = self.get_parent_component()?;
309        if parent.is_package(true) {
310            Some(parent)
311        } else {
312            None
313        }
314    }
315
316    pub fn inner_namespace(&self) -> Namespace {
317        let mut ret = self.namespace.clone();
318        ret.push(self.token.text);
319        ret
320    }
321
322    pub fn generic_maps(&self) -> Vec<GenericMap> {
323        let mut ret = Vec::new();
324
325        let generic_instances = if matches!(self.kind, SymbolKind::GenericInstance(_)) {
326            &vec![self.id]
327        } else {
328            &self.generic_instances
329        };
330        for i in generic_instances {
331            let symbol = symbol_table::get(*i).unwrap();
332            let map = if let SymbolKind::GenericInstance(ref x) = symbol.kind {
333                self.generic_map(Some(symbol.id), &x.arguments)
334            } else {
335                self.generic_map(Some(symbol.id), &[])
336            };
337            ret.push(map);
338        }
339
340        // empty map for non-generic
341        if ret.is_empty() && !self.kind.is_generic() {
342            ret.push(GenericMap::default());
343        }
344        ret
345    }
346
347    pub fn generic_map(&self, id: Option<SymbolId>, arguments: &[GenericSymbolPath]) -> GenericMap {
348        let map = if arguments.is_empty() {
349            HashMap::default()
350        } else {
351            self.generic_table(arguments)
352        };
353        GenericMap { id, map }
354    }
355
356    pub fn generic_table(&self, arguments: &[GenericSymbolPath]) -> GenericTable {
357        let params = self.generic_parameters();
358        let n_args = arguments.len();
359        let mut map = GenericMap::default();
360
361        let match_arity = if params.len() > n_args {
362            params[n_args].1.default_value.is_some()
363        } else {
364            params.len() == n_args
365        };
366        if !match_arity {
367            // Too many or too few generic args are given.
368            // Return empty generic table.
369            return map.map;
370        }
371
372        for (i, arg) in arguments.iter().enumerate() {
373            if let Some((p, _)) = params.get(i) {
374                map.map.insert(*p, arg.clone());
375            }
376        }
377
378        for param in params.iter().skip(n_args) {
379            map.map
380                .insert(param.0, param.1.default_value.as_ref().unwrap().clone());
381        }
382
383        self.eval_generic_consts(&mut map);
384
385        map.map
386    }
387
388    pub fn eval_generic_consts(&self, generic_map: &mut GenericMap) {
389        for (name, r#const) in self.generic_consts() {
390            if let Some(path) = Self::expr_to_generic_symbol_path(&r#const.value, generic_map) {
391                generic_map.map.insert(name, path);
392            }
393        }
394    }
395
396    fn expr_to_generic_symbol_path(
397        expr: &syntax_tree::Expression,
398        generic_map: &GenericMap,
399    ) -> Option<GenericSymbolPath> {
400        fn eval_value(
401            context: &mut Context,
402            expr: &syntax_tree::Expression,
403        ) -> Option<(Value, TokenRange)> {
404            let (comptime, _) = eval_generic_expr(context, expr).ok()?;
405            comptime
406                .get_value()
407                .cloned()
408                .ok()
409                .map(|x| (x, comptime.token))
410        }
411
412        if let Some(factor) = expr.unwrap_factor() {
413            match factor {
414                syntax_tree::Factor::Number(x) => return Some(x.number.as_ref().into()),
415                syntax_tree::Factor::BooleanLiteral(x) => {
416                    return Some(x.boolean_literal.as_ref().into());
417                }
418                syntax_tree::Factor::IdentifierFactor(x)
419                    if x.identifier_factor.identifier_factor_opt.is_none() =>
420                {
421                    let mut context = Context::default();
422                    context.push_generic_map(vec![generic_map.clone()]);
423
424                    let path = context
425                        .resolve_path(x.identifier_factor.expression_identifier.as_ref().into());
426                    return Some(path);
427                }
428                syntax_tree::Factor::LParenExpressionRParen(x) => {
429                    return Self::expr_to_generic_symbol_path(&x.expression, generic_map);
430                }
431                syntax_tree::Factor::TypeExpression(x) => {
432                    return Self::expr_to_generic_symbol_path(
433                        &x.type_expression.expression,
434                        generic_map,
435                    );
436                }
437                syntax_tree::Factor::FactorTypeFactor(x) => {
438                    match x.factor_type_factor.factor_type.factor_type_group.as_ref() {
439                        syntax_tree::FactorTypeGroup::FixedType(x) => {
440                            return Some(x.fixed_type.as_ref().into());
441                        }
442                        syntax_tree::FactorTypeGroup::VariableTypeFactorTypeOpt(x) => {
443                            let mut width = Vec::new();
444                            if let Some(x) = &x.factor_type_opt {
445                                let mut context = Context::default();
446                                context.push_generic_map(vec![generic_map.clone()]);
447
448                                for expr in Vec::from(x.width.as_ref()) {
449                                    if let Some((x, _)) = eval_value(&mut context, expr)
450                                        && let Some(x) = x.to_usize()
451                                    {
452                                        width.push(x);
453                                    } else {
454                                        return None;
455                                    }
456                                }
457                            }
458
459                            let path = (x.variable_type.as_ref(), &width).into();
460                            return Some(path);
461                        }
462                    }
463                }
464                _ => {}
465            }
466        };
467
468        let mut context = Context::default();
469        context.push_generic_map(vec![generic_map.clone()]);
470        if let Some((value, token)) = eval_value(&mut context, expr)
471            && !value.is_xz()
472        {
473            let text = format!("{}", value.payload());
474            let text = resource_table::insert_str(&text);
475            let token = Token::generate(text, token.beg.source.get_path().unwrap());
476
477            let literal_value = Literal::Value(value);
478            literal_table::insert(token.id, literal_value);
479
480            let mut path: GenericSymbolPath = (&token).into();
481            path.kind = GenericSymbolPathKind::ValueLiteral;
482            Some(path)
483        } else {
484            None
485        }
486    }
487
488    pub fn generic_parameters(&self) -> Vec<(StrId, GenericParameterProperty)> {
489        fn get_generic_parameter(id: SymbolId) -> (StrId, GenericParameterProperty) {
490            let symbol = symbol_table::get(id).unwrap();
491            if let SymbolKind::GenericParameter(x) = symbol.kind {
492                (symbol.token.text, x)
493            } else {
494                unreachable!()
495            }
496        }
497
498        match &self.kind {
499            SymbolKind::Function(x) => x
500                .generic_parameters
501                .iter()
502                .map(|x| get_generic_parameter(*x))
503                .collect(),
504            SymbolKind::Module(x) => x
505                .generic_parameters
506                .iter()
507                .map(|x| get_generic_parameter(*x))
508                .collect(),
509            SymbolKind::Interface(x) => x
510                .generic_parameters
511                .iter()
512                .map(|x| get_generic_parameter(*x))
513                .collect(),
514            SymbolKind::Package(x) => x
515                .generic_parameters
516                .iter()
517                .map(|x| get_generic_parameter(*x))
518                .collect(),
519            SymbolKind::Struct(x) => x
520                .generic_parameters
521                .iter()
522                .map(|x| get_generic_parameter(*x))
523                .collect(),
524            SymbolKind::Union(x) => x
525                .generic_parameters
526                .iter()
527                .map(|x| get_generic_parameter(*x))
528                .collect(),
529            SymbolKind::GenericInstance(x) => {
530                let symbol = symbol_table::get(x.base).unwrap();
531                symbol.generic_parameters()
532            }
533            _ => Vec::new(),
534        }
535    }
536
537    pub fn has_generic_paramters(&self) -> bool {
538        match &self.kind {
539            SymbolKind::Function(x) => !x.generic_parameters.is_empty(),
540            SymbolKind::Module(x) => !x.generic_parameters.is_empty(),
541            SymbolKind::Interface(x) => !x.generic_parameters.is_empty(),
542            SymbolKind::Package(x) => !x.generic_parameters.is_empty(),
543            SymbolKind::Struct(x) => !x.generic_parameters.is_empty(),
544            SymbolKind::Union(x) => !x.generic_parameters.is_empty(),
545            SymbolKind::GenericInstance(x) => {
546                let symbol = symbol_table::get(x.base).unwrap();
547                symbol.has_generic_paramters()
548            }
549            _ => false,
550        }
551    }
552
553    pub fn generic_consts(&self) -> Vec<(StrId, GenericConstProperty)> {
554        fn get_generic_const(id: SymbolId) -> (StrId, GenericConstProperty) {
555            let symbol = symbol_table::get(id).unwrap();
556            if let SymbolKind::GenericConst(x) = symbol.kind {
557                (symbol.token.text, x)
558            } else {
559                unreachable!()
560            }
561        }
562
563        match &self.kind {
564            SymbolKind::Function(x) => x
565                .generic_consts
566                .iter()
567                .map(|x| get_generic_const(*x))
568                .collect(),
569            SymbolKind::Module(x) => x
570                .generic_consts
571                .iter()
572                .map(|x| get_generic_const(*x))
573                .collect(),
574            SymbolKind::Interface(x) => x
575                .generic_consts
576                .iter()
577                .map(|x| get_generic_const(*x))
578                .collect(),
579            SymbolKind::Package(x) => x
580                .generic_consts
581                .iter()
582                .map(|x| get_generic_const(*x))
583                .collect(),
584            SymbolKind::GenericInstance(x) => {
585                let symbol = symbol_table::get(x.base).unwrap();
586                symbol.generic_consts()
587            }
588            _ => Vec::new(),
589        }
590    }
591
592    pub fn generic_references(&self) -> Vec<GenericSymbolPath> {
593        let references = match &self.kind {
594            SymbolKind::Function(x) => &x.generic_references,
595            SymbolKind::Module(x) => &x.generic_references,
596            SymbolKind::Interface(x) => &x.generic_references,
597            SymbolKind::Package(x) => &x.generic_references,
598            SymbolKind::Struct(x) => &x.generic_references,
599            SymbolKind::Union(x) => &x.generic_references,
600            _ => return Vec::new(),
601        };
602        references
603            .iter()
604            .filter(|r| r.is_generic_reference())
605            .cloned()
606            .collect()
607    }
608
609    pub fn proto(&self) -> Option<Symbol> {
610        match &self.kind {
611            SymbolKind::Module(x) => {
612                if let Some(proto) = &x.proto {
613                    return symbol_table::resolve((&proto.generic_path(), &self.namespace))
614                        .map(|x| (*x.found).clone())
615                        .ok();
616                }
617            }
618            SymbolKind::AliasModule(x) => {
619                let symbol =
620                    symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
621                return symbol.found.proto();
622            }
623            SymbolKind::ProtoAliasModule(x) => {
624                return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
625                    .map(|x| (*x.found).clone())
626                    .ok();
627            }
628            SymbolKind::Interface(x) => {
629                if let Some(proto) = &x.proto {
630                    return symbol_table::resolve((&proto.generic_path(), &self.namespace))
631                        .map(|x| (*x.found).clone())
632                        .ok();
633                } else if x.generic_parameters.is_empty() {
634                    return Some(self.clone());
635                }
636            }
637            SymbolKind::AliasInterface(x) => {
638                let symbol =
639                    symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
640                return symbol.found.proto();
641            }
642            SymbolKind::ProtoAliasInterface(x) => {
643                return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
644                    .map(|x| (*x.found).clone())
645                    .ok();
646            }
647            SymbolKind::Package(x) => {
648                if let Some(proto) = &x.proto {
649                    return symbol_table::resolve((&proto.generic_path(), &self.namespace))
650                        .map(|x| (*x.found).clone())
651                        .ok();
652                }
653            }
654            SymbolKind::AliasPackage(x) => {
655                let symbol =
656                    symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
657                return symbol.found.proto();
658            }
659            SymbolKind::ProtoAliasPackage(x) => {
660                return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
661                    .map(|x| (*x.found).clone())
662                    .ok();
663            }
664            SymbolKind::GenericParameter(x) => {
665                let proto = x.bound.resolve_proto_bound(&self.namespace).ok()?;
666                return proto.get_symbol();
667            }
668            _ => {}
669        }
670
671        None
672    }
673
674    pub fn alias_target(&self, include_proto: bool) -> Option<GenericSymbolPath> {
675        match &self.kind {
676            SymbolKind::AliasModule(x) => Some(x.target.clone()),
677            SymbolKind::ProtoAliasModule(x) if include_proto => Some(x.target.clone()),
678            SymbolKind::AliasInterface(x) => Some(x.target.clone()),
679            SymbolKind::ProtoAliasInterface(x) if include_proto => Some(x.target.clone()),
680            SymbolKind::AliasPackage(x) => Some(x.target.clone()),
681            SymbolKind::ProtoAliasPackage(x) if include_proto => Some(x.target.clone()),
682            _ => None,
683        }
684    }
685
686    pub fn is_module(&self, include_proto: bool) -> bool {
687        match &self.kind {
688            SymbolKind::Module(_) | SymbolKind::AliasModule(_) => return true,
689            SymbolKind::ProtoModule(_) => return include_proto,
690            SymbolKind::GenericInstance(x) => {
691                let symbol = symbol_table::get(x.base).unwrap();
692                return symbol.is_module(false);
693            }
694            SymbolKind::GenericParameter(x) => {
695                if let Ok(ProtoBound::ProtoModule(x)) = x.bound.resolve_proto_bound(&self.namespace)
696                {
697                    return x.is_module(true);
698                }
699            }
700            _ => {}
701        }
702        false
703    }
704
705    pub fn is_proto_module(&self, trace_generic_param: bool) -> bool {
706        match &self.kind {
707            SymbolKind::ProtoModule(_) => return true,
708            SymbolKind::GenericParameter(x) if trace_generic_param => {
709                if let Ok(ProtoBound::ProtoModule(x)) = x.bound.resolve_proto_bound(&self.namespace)
710                {
711                    return x.is_proto_module(trace_generic_param);
712                }
713            }
714            _ => {}
715        }
716        false
717    }
718
719    pub fn is_interface(&self, include_proto: bool) -> bool {
720        match &self.kind {
721            SymbolKind::Interface(_) | SymbolKind::AliasInterface(_) => return true,
722            SymbolKind::ProtoInterface(_) => return include_proto,
723            SymbolKind::GenericInstance(x) => {
724                let symbol = symbol_table::get(x.base).unwrap();
725                return symbol.is_interface(false);
726            }
727            SymbolKind::GenericParameter(x) => {
728                if let Ok(ProtoBound::ProtoInterface(x)) =
729                    x.bound.resolve_proto_bound(&self.namespace)
730                {
731                    return x.is_interface(true);
732                }
733            }
734            _ => {}
735        }
736        false
737    }
738
739    pub fn is_proto_interface(
740        &self,
741        trace_generic_param: bool,
742        include_non_generic_interface: bool,
743    ) -> bool {
744        match &self.kind {
745            SymbolKind::Interface(x) => {
746                return include_non_generic_interface && x.generic_parameters.is_empty();
747            }
748            SymbolKind::ProtoInterface(_) => return true,
749            SymbolKind::GenericParameter(x) if trace_generic_param => {
750                if let Ok(ProtoBound::ProtoInterface(x)) =
751                    x.bound.resolve_proto_bound(&self.namespace)
752                {
753                    return x
754                        .is_proto_interface(trace_generic_param, include_non_generic_interface);
755                }
756            }
757            _ => {}
758        }
759        false
760    }
761
762    pub fn is_package(&self, include_proto: bool) -> bool {
763        match &self.kind {
764            SymbolKind::Package(_) | SymbolKind::AliasPackage(_) => return true,
765            SymbolKind::ProtoPackage(_) => return include_proto,
766            SymbolKind::GenericInstance(x) => {
767                let symbol = symbol_table::get(x.base).unwrap();
768                return symbol.is_package(false);
769            }
770            SymbolKind::GenericParameter(x) => {
771                if let Ok(ProtoBound::ProtoPackage(x)) =
772                    x.bound.resolve_proto_bound(&self.namespace)
773                {
774                    return x.is_package(true);
775                }
776            }
777            _ => {}
778        }
779        false
780    }
781
782    pub fn is_component(&self, include_proto: bool) -> bool {
783        match &self.kind {
784            SymbolKind::Module(_)
785            | SymbolKind::AliasModule(_)
786            | SymbolKind::Interface(_)
787            | SymbolKind::AliasInterface(_)
788            | SymbolKind::Package(_)
789            | SymbolKind::AliasPackage(_) => return true,
790            SymbolKind::ProtoModule(_)
791            | SymbolKind::ProtoInterface(_)
792            | SymbolKind::ProtoPackage(_) => return include_proto,
793            SymbolKind::GenericInstance(x) => {
794                let symbol = symbol_table::get(x.base).unwrap();
795                return symbol.is_component(false);
796            }
797            SymbolKind::GenericParameter(x) => {
798                if let Ok(ProtoBound::ProtoInterface(x)) =
799                    x.bound.resolve_proto_bound(&self.namespace)
800                {
801                    return x.is_component(true);
802                }
803            }
804            _ => {}
805        }
806        false
807    }
808
809    pub fn is_proto_package(&self, trace_generic_param: bool) -> bool {
810        match &self.kind {
811            SymbolKind::ProtoPackage(_) => return true,
812            SymbolKind::GenericParameter(x) if trace_generic_param => {
813                if let Ok(ProtoBound::ProtoPackage(x)) =
814                    x.bound.resolve_proto_bound(&self.namespace)
815                {
816                    return x.is_proto_package(trace_generic_param);
817                }
818            }
819            _ => {}
820        }
821        false
822    }
823
824    pub fn is_importable(&self, include_proto: bool) -> bool {
825        match &self.kind {
826            SymbolKind::ProtoConst(_)
827            | SymbolKind::ProtoTypeDef(_)
828            | SymbolKind::ProtoFunction(_) => {
829                return include_proto;
830            }
831            SymbolKind::Parameter(_)
832            | SymbolKind::TypeDef(_)
833            | SymbolKind::Enum(_)
834            | SymbolKind::Struct(_)
835            | SymbolKind::Union(_)
836            | SymbolKind::Function(_) => {
837                if let Some(parent) = self.get_parent() {
838                    return parent.is_package(include_proto);
839                }
840            }
841            SymbolKind::EnumMember(_) | SymbolKind::EnumMemberMangled => {
842                if let Some(parent) = self.get_parent() {
843                    return parent.is_importable(include_proto);
844                }
845            }
846            _ => {}
847        }
848        false
849    }
850
851    pub fn is_variable_type(&self) -> bool {
852        match &self.kind {
853            SymbolKind::Enum(_)
854            | SymbolKind::Union(_)
855            | SymbolKind::Struct(_)
856            | SymbolKind::TypeDef(_)
857            | SymbolKind::ProtoTypeDef(_)
858            | SymbolKind::SystemVerilog => true,
859            SymbolKind::Parameter(x) => matches!(x.r#type.kind, TypeKind::Type),
860            SymbolKind::ProtoConst(x) => matches!(x.r#type.kind, TypeKind::Type),
861            SymbolKind::GenericParameter(x) => matches!(x.bound, GenericBoundKind::Type),
862            SymbolKind::GenericConst(x) => matches!(x.bound, GenericBoundKind::Type),
863            SymbolKind::GenericInstance(x) => symbol_table::get(x.base)
864                .map(|x| x.is_variable_type())
865                .unwrap_or(false),
866            _ => false,
867        }
868    }
869
870    pub fn is_casting_type(&self) -> bool {
871        let type_kind = match &self.kind {
872            SymbolKind::Parameter(x) => &x.r#type.kind,
873            SymbolKind::ProtoConst(x) => &x.r#type.kind,
874            SymbolKind::GenericParameter(x) => {
875                if let GenericBoundKind::Proto(x) = &x.bound {
876                    &x.kind
877                } else {
878                    return matches!(x.bound, GenericBoundKind::Type);
879                }
880            }
881            SymbolKind::GenericConst(x) => {
882                if let GenericBoundKind::Proto(x) = &x.bound {
883                    &x.kind
884                } else {
885                    return matches!(x.bound, GenericBoundKind::Type);
886                }
887            }
888            _ => return self.is_variable_type(),
889        };
890        matches!(
891            type_kind,
892            TypeKind::Type
893                | TypeKind::U8
894                | TypeKind::U16
895                | TypeKind::U32
896                | TypeKind::U64
897                | TypeKind::I8
898                | TypeKind::I16
899                | TypeKind::I32
900                | TypeKind::I64
901                | TypeKind::P8
902                | TypeKind::P16
903                | TypeKind::P32
904                | TypeKind::P64
905        )
906    }
907
908    pub fn is_struct(&self) -> bool {
909        match &self.kind {
910            SymbolKind::Struct(_) => true,
911            SymbolKind::TypeDef(x) => {
912                let namespace = Some(&self.namespace);
913                if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(namespace) {
914                    symbol.is_struct()
915                } else {
916                    false
917                }
918            }
919            _ => false,
920        }
921    }
922
923    pub fn is_union(&self) -> bool {
924        match &self.kind {
925            SymbolKind::Union(_) => true,
926            SymbolKind::TypeDef(x) => {
927                let namespace = Some(&self.namespace);
928                if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(namespace) {
929                    symbol.is_union()
930                } else {
931                    false
932                }
933            }
934            _ => false,
935        }
936    }
937
938    pub fn is_global_function(&self) -> bool {
939        match &self.kind {
940            SymbolKind::Function(x) => x.is_global(),
941            SymbolKind::GenericInstance(x) => {
942                let symbol = symbol_table::get(x.base).unwrap();
943                symbol.is_global_function()
944            }
945            _ => false,
946        }
947    }
948}
949
950#[derive(Debug, Clone)]
951pub enum SymbolKind {
952    Port(PortProperty),
953    Variable(VariableProperty),
954    Module(ModuleProperty),
955    ProtoModule(ProtoModuleProperty),
956    AliasModule(AliasModuleProperty),
957    ProtoAliasModule(AliasModuleProperty),
958    Interface(InterfaceProperty),
959    ProtoInterface(ProtoInterfaceProperty),
960    AliasInterface(AliasInterfaceProperty),
961    ProtoAliasInterface(AliasInterfaceProperty),
962    Function(FunctionProperty),
963    ProtoFunction(FunctionProperty),
964    Parameter(ParameterProperty),
965    ProtoConst(ProtoConstProperty),
966    Instance(InstanceProperty),
967    Block,
968    Package(PackageProperty),
969    ProtoPackage(ProtoPackageProperty),
970    AliasPackage(AliasPackageProperty),
971    ProtoAliasPackage(AliasPackageProperty),
972    Struct(StructProperty),
973    StructMember(StructMemberProperty),
974    Union(UnionProperty),
975    UnionMember(UnionMemberProperty),
976    TypeDef(TypeDefProperty),
977    ProtoTypeDef(ProtoTypeDefProperty),
978    Enum(EnumProperty),
979    EnumMember(EnumMemberProperty),
980    EnumMemberMangled,
981    Modport(ModportProperty),
982    Genvar,
983    ModportVariableMember(ModportVariableMemberProperty),
984    ModportFunctionMember(ModportFunctionMemberProperty),
985    SystemVerilog,
986    Namespace,
987    SystemFunction(SystemFuncitonProperty),
988    GenericParameter(GenericParameterProperty),
989    GenericConst(GenericConstProperty),
990    GenericInstance(GenericInstanceProperty),
991    ClockDomain,
992    Test(TestProperty),
993    Embed,
994    TbComponent(TbComponentProperty),
995}
996
997impl SymbolKind {
998    pub fn to_kind_name(&self) -> String {
999        match self {
1000            SymbolKind::Port(x) => match x.direction {
1001                Direction::Modport => "modport".to_string(),
1002                Direction::Import => "function import".to_string(),
1003                _ => format!("{} port", x.direction),
1004            },
1005            SymbolKind::Variable(_) => "variable".to_string(),
1006            SymbolKind::Module(_) => "module".to_string(),
1007            SymbolKind::ProtoModule(_) => "proto module".to_string(),
1008            SymbolKind::AliasModule(_) => "alias module".to_string(),
1009            SymbolKind::ProtoAliasModule(_) => "proto alias module".to_string(),
1010            SymbolKind::Interface(_) => "interface".to_string(),
1011            SymbolKind::ProtoInterface(_) => "proto interface".to_string(),
1012            SymbolKind::AliasInterface(_) => "alias interface".to_string(),
1013            SymbolKind::ProtoAliasInterface(_) => "proto alias interface".to_string(),
1014            SymbolKind::Function(_) => "function".to_string(),
1015            SymbolKind::ProtoFunction(_) => "proto function".to_string(),
1016            SymbolKind::Parameter(_) => "parameter".to_string(),
1017            SymbolKind::ProtoConst(_) => "proto const".to_string(),
1018            SymbolKind::Instance(_) => "instance".to_string(),
1019            SymbolKind::Block => "block".to_string(),
1020            SymbolKind::Package(_) => "package".to_string(),
1021            SymbolKind::ProtoPackage(_) => "proto package".to_string(),
1022            SymbolKind::AliasPackage(_) => "alias package".to_string(),
1023            SymbolKind::ProtoAliasPackage(_) => "proto alias package".to_string(),
1024            SymbolKind::Struct(_) => "struct".to_string(),
1025            SymbolKind::StructMember(_) => "struct member".to_string(),
1026            SymbolKind::Union(_) => "union".to_string(),
1027            SymbolKind::UnionMember(_) => "union member".to_string(),
1028            SymbolKind::TypeDef(_) => "typedef".to_string(),
1029            SymbolKind::ProtoTypeDef(_) => "proto typedef".to_string(),
1030            SymbolKind::Enum(_) => "enum".to_string(),
1031            SymbolKind::EnumMember(_) => "enum member".to_string(),
1032            SymbolKind::EnumMemberMangled => "enum member mangled".to_string(),
1033            SymbolKind::Modport(_) => "modport".to_string(),
1034            SymbolKind::Genvar => "genvar".to_string(),
1035            SymbolKind::ModportVariableMember(x) => match x.direction {
1036                Direction::Input | Direction::Output | Direction::Inout => {
1037                    format!("modport {} variable member", x.direction)
1038                }
1039                _ => unreachable!(),
1040            },
1041            SymbolKind::ModportFunctionMember(_) => "modport function member".to_string(),
1042            SymbolKind::SystemVerilog => "systemverilog item".to_string(),
1043            SymbolKind::Namespace => "namespace".to_string(),
1044            SymbolKind::SystemFunction(_) => "system function".to_string(),
1045            SymbolKind::GenericParameter(_) => "generic parameter".to_string(),
1046            SymbolKind::GenericConst(_) => "generic const".to_string(),
1047            SymbolKind::GenericInstance(_) => "generic instance".to_string(),
1048            SymbolKind::ClockDomain => "clock domain".to_string(),
1049            SymbolKind::Test(_) => "test".to_string(),
1050            SymbolKind::Embed => "embed".to_string(),
1051            SymbolKind::TbComponent(x) => format!("testbench {}", x.kind),
1052        }
1053    }
1054
1055    pub fn is_generic(&self) -> bool {
1056        match self {
1057            SymbolKind::Module(x) => !x.generic_parameters.is_empty(),
1058            SymbolKind::Interface(x) => !x.generic_parameters.is_empty(),
1059            SymbolKind::Function(x) => !x.generic_parameters.is_empty(),
1060            SymbolKind::Package(x) => !x.generic_parameters.is_empty(),
1061            SymbolKind::Struct(x) => !x.generic_parameters.is_empty(),
1062            SymbolKind::Union(x) => !x.generic_parameters.is_empty(),
1063            _ => false,
1064        }
1065    }
1066
1067    pub fn is_clock(&self) -> bool {
1068        match self {
1069            SymbolKind::Port(x) => x.r#type.kind.is_clock(),
1070            SymbolKind::Variable(x) => x.r#type.kind.is_clock(),
1071            _ => false,
1072        }
1073    }
1074
1075    pub fn can_be_default_clock(&self) -> bool {
1076        match self {
1077            SymbolKind::Port(x) => x.r#type.can_be_default_clock(),
1078            SymbolKind::Variable(x) => x.r#type.can_be_default_clock(),
1079            _ => false,
1080        }
1081    }
1082
1083    pub fn is_reset(&self) -> bool {
1084        match self {
1085            SymbolKind::Port(x) => x.r#type.kind.is_reset(),
1086            SymbolKind::Variable(x) => x.r#type.kind.is_reset(),
1087            _ => false,
1088        }
1089    }
1090
1091    pub fn can_be_default_reset(&self) -> bool {
1092        match self {
1093            SymbolKind::Port(x) => x.r#type.can_be_default_reset(),
1094            SymbolKind::Variable(x) => x.r#type.can_be_default_reset(),
1095            _ => false,
1096        }
1097    }
1098
1099    pub fn is_function(&self) -> bool {
1100        match self {
1101            SymbolKind::Function(_)
1102            | SymbolKind::ProtoFunction(_)
1103            | SymbolKind::SystemVerilog
1104            | SymbolKind::ModportFunctionMember(..)
1105            | SymbolKind::SystemFunction(_) => true,
1106            SymbolKind::GenericInstance(x) => {
1107                let base = symbol_table::get(x.base).unwrap();
1108                matches!(
1109                    base.kind,
1110                    SymbolKind::Function(_)
1111                        | SymbolKind::SystemVerilog
1112                        | SymbolKind::ModportFunctionMember(..)
1113                        | SymbolKind::SystemFunction(_)
1114                )
1115            }
1116            _ => false,
1117        }
1118    }
1119
1120    pub fn get_type(&self) -> Option<&Type> {
1121        match self {
1122            SymbolKind::Port(x) => Some(&x.r#type),
1123            SymbolKind::Variable(x) => Some(&x.r#type),
1124            SymbolKind::Function(x) => x.ret.as_ref(),
1125            SymbolKind::ProtoFunction(x) => x.ret.as_ref(),
1126            SymbolKind::Parameter(x) => Some(&x.r#type),
1127            SymbolKind::ProtoConst(x) => Some(&x.r#type),
1128            SymbolKind::StructMember(x) => Some(&x.r#type),
1129            SymbolKind::UnionMember(x) => Some(&x.r#type),
1130            SymbolKind::TypeDef(x) => Some(&x.r#type),
1131            _ => None,
1132        }
1133    }
1134
1135    pub fn get_type_mut(&mut self) -> Option<&mut Type> {
1136        match self {
1137            SymbolKind::Port(x) => Some(&mut x.r#type),
1138            SymbolKind::Variable(x) => Some(&mut x.r#type),
1139            SymbolKind::Function(x) => x.ret.as_mut(),
1140            SymbolKind::ProtoFunction(x) => x.ret.as_mut(),
1141            SymbolKind::Parameter(x) => Some(&mut x.r#type),
1142            SymbolKind::ProtoConst(x) => Some(&mut x.r#type),
1143            SymbolKind::StructMember(x) => Some(&mut x.r#type),
1144            SymbolKind::UnionMember(x) => Some(&mut x.r#type),
1145            SymbolKind::TypeDef(x) => Some(&mut x.r#type),
1146            _ => None,
1147        }
1148    }
1149
1150    pub fn get_parameters(&self) -> &[Parameter] {
1151        match self {
1152            SymbolKind::Module(x) => &x.parameters,
1153            SymbolKind::Interface(x) => &x.parameters,
1154            _ => &[],
1155        }
1156    }
1157
1158    pub fn get_generic_parameters(&self) -> &[SymbolId] {
1159        match self {
1160            SymbolKind::Module(x) => &x.generic_parameters,
1161            SymbolKind::Interface(x) => &x.generic_parameters,
1162            SymbolKind::Function(x) => &x.generic_parameters,
1163            SymbolKind::Package(x) => &x.generic_parameters,
1164            SymbolKind::Struct(x) => &x.generic_parameters,
1165            SymbolKind::Union(x) => &x.generic_parameters,
1166            _ => &[],
1167        }
1168    }
1169
1170    pub fn get_definition(&self) -> Option<DefinitionId> {
1171        match self {
1172            SymbolKind::Module(x) => Some(x.definition),
1173            SymbolKind::Interface(x) => Some(x.definition),
1174            SymbolKind::Function(x) => x.definition,
1175            _ => None,
1176        }
1177    }
1178}
1179
1180impl fmt::Display for SymbolKind {
1181    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1182        let text = match self {
1183            SymbolKind::Port(x) => {
1184                format!("port ({} {})", x.direction, x.r#type)
1185            }
1186            SymbolKind::Variable(x) => {
1187                format!("variable ({})", x.r#type)
1188            }
1189            SymbolKind::Module(x) => {
1190                format!(
1191                    "module ({} generic, {} params, {} ports)",
1192                    x.generic_parameters.len(),
1193                    x.parameters.len(),
1194                    x.ports.len()
1195                )
1196            }
1197            SymbolKind::ProtoModule(x) => {
1198                format!(
1199                    "proto module ({} params, {} ports)",
1200                    x.parameters.len(),
1201                    x.ports.len()
1202                )
1203            }
1204            SymbolKind::AliasModule(x) => {
1205                format!("alias module (target {})", x.target)
1206            }
1207            SymbolKind::ProtoAliasModule(x) => {
1208                format!("proto alias module (target {})", x.target)
1209            }
1210            SymbolKind::Interface(x) => {
1211                format!(
1212                    "interface ({} generic, {} params)",
1213                    x.generic_parameters.len(),
1214                    x.parameters.len()
1215                )
1216            }
1217            SymbolKind::ProtoInterface(x) => {
1218                format!("proto interface ({} params)", x.parameters.len())
1219            }
1220            SymbolKind::AliasInterface(x) => {
1221                format!("alias interface (target {})", x.target)
1222            }
1223            SymbolKind::ProtoAliasInterface(x) => {
1224                format!("proto alias interface (target {})", x.target)
1225            }
1226            SymbolKind::Function(x) => {
1227                format!(
1228                    "function ({} generic, {} args)",
1229                    x.generic_parameters.len(),
1230                    x.ports.len()
1231                )
1232            }
1233            SymbolKind::ProtoFunction(x) => {
1234                format!(
1235                    "proto function ({} generic, {} args)",
1236                    x.generic_parameters.len(),
1237                    x.ports.len()
1238                )
1239            }
1240            SymbolKind::Parameter(x) => {
1241                if let Some(value) = &x.value {
1242                    let mut stringifier = Stringifier::new();
1243                    stringifier.expression(value);
1244                    format!(
1245                        "{} ({}) = {}",
1246                        x.kind.to_sv_snippet(),
1247                        x.r#type,
1248                        stringifier.as_str()
1249                    )
1250                } else {
1251                    format!("{} ({})", x.kind.to_sv_snippet(), x.r#type)
1252                }
1253            }
1254            SymbolKind::ProtoConst(x) => {
1255                format!("proto localparam ({})", x.r#type)
1256            }
1257            SymbolKind::Instance(x) => {
1258                let type_name = x.type_name.to_string();
1259                format!("instance ({type_name})")
1260            }
1261            SymbolKind::Block => "block".to_string(),
1262            SymbolKind::Package(x) => {
1263                format!("package ({} generic)", x.generic_parameters.len())
1264            }
1265            SymbolKind::ProtoPackage(_) => "proto package".to_string(),
1266            SymbolKind::AliasPackage(x) => {
1267                format!("alias package (target {})", x.target)
1268            }
1269            SymbolKind::ProtoAliasPackage(x) => {
1270                format!("proto alias package (target {})", x.target)
1271            }
1272            SymbolKind::Struct(_) => "struct".to_string(),
1273            SymbolKind::StructMember(x) => {
1274                format!("struct member ({})", x.r#type)
1275            }
1276            SymbolKind::Union(_) => "union".to_string(),
1277            SymbolKind::UnionMember(x) => {
1278                format!("union member ({})", x.r#type)
1279            }
1280            SymbolKind::TypeDef(x) => {
1281                format!("typedef alias ({})", x.r#type)
1282            }
1283            SymbolKind::ProtoTypeDef(x) => {
1284                if let Some(ref r#type) = x.r#type {
1285                    format!("proto typedef alias ({type})")
1286                } else {
1287                    "proto typedef".to_string()
1288                }
1289            }
1290            SymbolKind::Enum(x) => {
1291                if let Some(ref r#type) = x.r#type {
1292                    format!("enum ({type})")
1293                } else {
1294                    "enum ()".to_string()
1295                }
1296            }
1297            SymbolKind::EnumMember(x) => {
1298                if let EnumMemberValue::ExplicitValue(ref expression, ref _evaluated) = x.value {
1299                    let mut stringifier = Stringifier::new();
1300                    stringifier.expression(expression);
1301                    format!("enum member = {}", stringifier.as_str())
1302                } else {
1303                    "enum member".to_string()
1304                }
1305            }
1306            SymbolKind::EnumMemberMangled => "enum member mangled".to_string(),
1307            SymbolKind::Modport(x) => {
1308                format!("modport ({} ports)", x.members.len())
1309            }
1310            SymbolKind::Genvar => "genvar".to_string(),
1311            SymbolKind::ModportVariableMember(x) => {
1312                format!("modport variable member ({})", x.direction)
1313            }
1314            SymbolKind::ModportFunctionMember(_) => "modport function member".to_string(),
1315            SymbolKind::SystemVerilog => "systemverilog item".to_string(),
1316            SymbolKind::Namespace => "namespace".to_string(),
1317            SymbolKind::SystemFunction(_) => "system function".to_string(),
1318            SymbolKind::GenericParameter(_) => "generic parameter".to_string(),
1319            SymbolKind::GenericConst(_) => "generic const".to_string(),
1320            SymbolKind::GenericInstance(_) => "generic instance".to_string(),
1321            SymbolKind::ClockDomain => "clock domain".to_string(),
1322            SymbolKind::Test(_) => "test".to_string(),
1323            SymbolKind::Embed => "embed".to_string(),
1324            SymbolKind::TbComponent(x) => format!("testbench {} component", x.kind),
1325        };
1326        text.fmt(f)
1327    }
1328}
1329
1330#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1331pub enum Direction {
1332    Input,
1333    Output,
1334    Inout,
1335    Interface,
1336    Modport,
1337    Import,
1338}
1339
1340impl Direction {
1341    pub fn converse(&self) -> Direction {
1342        match self {
1343            Direction::Input => Direction::Output,
1344            Direction::Output => Direction::Input,
1345            _ => *self,
1346        }
1347    }
1348
1349    pub fn is_input(&self) -> bool {
1350        self == &Direction::Input
1351    }
1352
1353    pub fn is_output(&self) -> bool {
1354        self == &Direction::Output
1355    }
1356}
1357
1358impl fmt::Display for Direction {
1359    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1360        let text = match self {
1361            Direction::Input => "input".to_string(),
1362            Direction::Output => "output".to_string(),
1363            Direction::Inout => "inout".to_string(),
1364            Direction::Interface => "interface".to_string(),
1365            Direction::Modport => "modport".to_string(),
1366            Direction::Import => "import".to_string(),
1367        };
1368        text.fmt(f)
1369    }
1370}
1371
1372impl From<&syntax_tree::Direction> for Direction {
1373    fn from(value: &syntax_tree::Direction) -> Self {
1374        match value {
1375            syntax_tree::Direction::Input(_) => Direction::Input,
1376            syntax_tree::Direction::Output(_) => Direction::Output,
1377            syntax_tree::Direction::Inout(_) => Direction::Inout,
1378            syntax_tree::Direction::Modport(_) => Direction::Modport,
1379            syntax_tree::Direction::Import(_) => Direction::Import,
1380        }
1381    }
1382}
1383
1384#[derive(Debug, Clone)]
1385pub struct Type {
1386    pub modifier: Vec<TypeModifier>,
1387    pub kind: TypeKind,
1388    pub width: Vec<syntax_tree::Expression>,
1389    pub array: Vec<syntax_tree::Expression>,
1390    pub array_type: Option<syntax_tree::ArrayType>,
1391    pub is_const: bool,
1392    pub token: TokenRange,
1393}
1394
1395impl Type {
1396    pub fn create_inferred(token: TokenRange) -> Self {
1397        Self {
1398            modifier: vec![],
1399            kind: TypeKind::Inferred,
1400            width: vec![],
1401            array: vec![],
1402            array_type: None,
1403            is_const: false,
1404            token,
1405        }
1406    }
1407
1408    pub fn is_compatible(&self, other: &Type) -> bool {
1409        self.to_string() == other.to_string()
1410    }
1411
1412    pub fn has_modifier(&self, kind: &TypeModifierKind) -> bool {
1413        self.modifier.iter().any(|x| x.kind == *kind)
1414    }
1415
1416    pub fn find_modifier(&self, kind: &TypeModifierKind) -> Option<TypeModifier> {
1417        self.modifier.iter().find(|x| x.kind == *kind).cloned()
1418    }
1419
1420    pub fn is_signed(&self) -> bool {
1421        if self.kind.is_fixed() {
1422            self.kind.is_signed()
1423        } else {
1424            self.has_modifier(&TypeModifierKind::Signed)
1425        }
1426    }
1427
1428    pub fn is_inferred(&self) -> bool {
1429        matches!(self.kind, TypeKind::Inferred)
1430    }
1431
1432    pub fn can_be_default_clock(&self) -> bool {
1433        self.kind.is_clock() && self.width.is_empty() && self.array.is_empty()
1434    }
1435
1436    pub fn can_be_default_reset(&self) -> bool {
1437        self.kind.is_reset() && self.width.is_empty() && self.array.is_empty()
1438    }
1439
1440    pub fn get_user_defined(&self) -> Option<UserDefinedType> {
1441        if let TypeKind::UserDefined(x) = &self.kind {
1442            return Some(x.clone());
1443        }
1444
1445        None
1446    }
1447
1448    pub fn trace_user_defined(
1449        &self,
1450        namespace: Option<&Namespace>,
1451    ) -> Option<(Type, Option<Symbol>)> {
1452        if let TypeKind::UserDefined(x) = &self.kind {
1453            let symbol = if let Some(namespace) = namespace {
1454                symbol_table::resolve((&x.path.generic_path(), namespace)).ok()?
1455            } else {
1456                let namespace = namespace_table::get(x.path.paths[0].base.id).unwrap();
1457                symbol_table::resolve((&x.path.generic_path(), &namespace)).ok()?
1458            };
1459            match &symbol.found.kind {
1460                SymbolKind::TypeDef(x) => {
1461                    return x.r#type.trace_user_defined(Some(&symbol.found.namespace));
1462                }
1463                SymbolKind::ProtoTypeDef(x) => {
1464                    if let Some(r#type) = &x.r#type {
1465                        return r#type.trace_user_defined(Some(&symbol.found.namespace));
1466                    } else {
1467                        return Some((self.clone(), Some((*symbol.found).clone())));
1468                    }
1469                }
1470                SymbolKind::Module(_)
1471                | SymbolKind::ProtoModule(_)
1472                | SymbolKind::Interface(_)
1473                | SymbolKind::ProtoInterface(_)
1474                | SymbolKind::Package(_)
1475                | SymbolKind::ProtoPackage(_)
1476                | SymbolKind::Enum(_)
1477                | SymbolKind::Struct(_)
1478                | SymbolKind::Union(_)
1479                | SymbolKind::Modport(_) => {
1480                    return Some((self.clone(), Some((*symbol.found).clone())));
1481                }
1482                _ => {}
1483            }
1484        }
1485
1486        Some((self.clone(), None))
1487    }
1488
1489    pub fn to_ir_type(&self, context: &mut Context, pos: TypePosition) -> ir::IrResult<ir::Type> {
1490        let mut width = match &self.kind {
1491            TypeKind::U8 => Shape::new(vec![Some(8)]),
1492            TypeKind::U16 => Shape::new(vec![Some(16)]),
1493            TypeKind::U32 => Shape::new(vec![Some(32)]),
1494            TypeKind::U64 => Shape::new(vec![Some(64)]),
1495            TypeKind::P8 => Shape::new(vec![Some(8)]),
1496            TypeKind::P16 => Shape::new(vec![Some(16)]),
1497            TypeKind::P32 => Shape::new(vec![Some(32)]),
1498            TypeKind::P64 => Shape::new(vec![Some(64)]),
1499            TypeKind::I8 => Shape::new(vec![Some(8)]),
1500            TypeKind::I16 => Shape::new(vec![Some(16)]),
1501            TypeKind::I32 => Shape::new(vec![Some(32)]),
1502            TypeKind::I64 => Shape::new(vec![Some(64)]),
1503            TypeKind::F32 => Shape::new(vec![Some(32)]),
1504            TypeKind::F64 => Shape::new(vec![Some(64)]),
1505            TypeKind::Clock
1506            | TypeKind::ClockPosedge
1507            | TypeKind::ClockNegedge
1508            | TypeKind::Reset
1509            | TypeKind::ResetAsyncHigh
1510            | TypeKind::ResetAsyncLow
1511            | TypeKind::ResetSyncHigh
1512            | TypeKind::ResetSyncLow
1513            | TypeKind::Bit
1514            | TypeKind::Logic => {
1515                let mut ret = Shape::default();
1516
1517                if self.width.is_empty() {
1518                    ret.push(Some(1));
1519                } else {
1520                    let allow_inferable = matches!(&self.kind, TypeKind::Bit | TypeKind::Logic)
1521                        && self.width.len() == 1
1522                        && pos == TypePosition::Enum;
1523                    for w in &self.width {
1524                        let (_, value) = eval_size(context, w, allow_inferable)?;
1525                        ret.push(value);
1526                    }
1527                }
1528
1529                ret
1530            }
1531            TypeKind::UserDefined(_) => {
1532                let mut ret = Shape::default();
1533                for w in &self.width {
1534                    let (_, value) = eval_size(context, w, false)?;
1535                    ret.push(value);
1536                }
1537
1538                ret
1539            }
1540            TypeKind::BBool
1541            | TypeKind::LBool
1542            | TypeKind::Type
1543            | TypeKind::String
1544            | TypeKind::AbstractInterface(_) => {
1545                // TODO packed array is forbidden
1546                Shape::default()
1547            }
1548            TypeKind::Any => Shape::default(),
1549            TypeKind::Inferred => Shape::default(),
1550        };
1551
1552        let mut array = Shape::default();
1553
1554        for w in &self.array {
1555            let (_, value) = eval_size(context, w, false)?;
1556            array.push(value);
1557        }
1558
1559        let mut signed = match &self.kind {
1560            TypeKind::I8 | TypeKind::I16 | TypeKind::I32 | TypeKind::I64 => true,
1561            TypeKind::Bit | TypeKind::Logic => self.is_signed(),
1562            _ => {
1563                if let Some(x) = self.find_modifier(&TypeModifierKind::Signed) {
1564                    context.insert_error(crate::AnalyzerError::fixed_type_with_signed_modifier(
1565                        &x.token.token.into(),
1566                    ));
1567                }
1568                false
1569            }
1570        };
1571
1572        let is_positive = matches!(
1573            &self.kind,
1574            TypeKind::P8 | TypeKind::P16 | TypeKind::P32 | TypeKind::P64
1575        );
1576
1577        let kind = match &self.kind {
1578            TypeKind::Clock => ir::TypeKind::Clock,
1579            TypeKind::ClockPosedge => ir::TypeKind::ClockPosedge,
1580            TypeKind::ClockNegedge => ir::TypeKind::ClockNegedge,
1581            TypeKind::Reset => ir::TypeKind::Reset,
1582            TypeKind::ResetAsyncHigh => ir::TypeKind::ResetAsyncHigh,
1583            TypeKind::ResetAsyncLow => ir::TypeKind::ResetAsyncLow,
1584            TypeKind::ResetSyncHigh => ir::TypeKind::ResetSyncHigh,
1585            TypeKind::ResetSyncLow => ir::TypeKind::ResetSyncLow,
1586            TypeKind::Bit
1587            | TypeKind::BBool
1588            | TypeKind::P8
1589            | TypeKind::P16
1590            | TypeKind::P32
1591            | TypeKind::P64
1592            | TypeKind::U8
1593            | TypeKind::U16
1594            | TypeKind::U32
1595            | TypeKind::U64
1596            | TypeKind::I8
1597            | TypeKind::I16
1598            | TypeKind::I32
1599            | TypeKind::I64 => ir::TypeKind::Bit,
1600            TypeKind::F32 => ir::TypeKind::F32,
1601            TypeKind::F64 => ir::TypeKind::F64,
1602            TypeKind::LBool | TypeKind::Logic => ir::TypeKind::Logic,
1603            TypeKind::Type => ir::TypeKind::Type,
1604            TypeKind::String => ir::TypeKind::String,
1605            TypeKind::UserDefined(x) => {
1606                let mut r#type = eval_type(context, &x.path, pos)?;
1607
1608                width.append(r#type.width_mut());
1609                array.append(&mut r#type.array);
1610                signed = r#type.signed;
1611
1612                r#type.kind
1613            }
1614            TypeKind::AbstractInterface(x) => ir::TypeKind::AbstractInterface(*x),
1615            TypeKind::Any => ir::TypeKind::Unknown,
1616            TypeKind::Inferred => ir::TypeKind::Unknown,
1617        };
1618
1619        let width_expr = build_width_expr(&self.width, &width);
1620        let mut r#type = ir::Type::new(kind);
1621        r#type.signed = signed;
1622        r#type.is_positive = is_positive;
1623        r#type.array = array;
1624        if width_expr.len() == width.as_slice().len() {
1625            r#type.set_parametric_width(width, width_expr);
1626        } else {
1627            r#type.set_concrete_width(width);
1628        }
1629        Ok(r#type)
1630    }
1631}
1632
1633fn build_width_expr(sources: &[syntax_tree::Expression], width: &Shape) -> Vec<ir::WidthExpr> {
1634    let shape_slice = width.as_slice();
1635    if sources.len() != shape_slice.len() {
1636        return ir::WidthExpr::from_shape(width);
1637    }
1638    let mut result = Vec::with_capacity(shape_slice.len());
1639    for (src, slot) in sources.iter().zip(shape_slice.iter()) {
1640        if let Some(expr) = try_syntax_expr_to_param_width(src) {
1641            result.push(expr);
1642        } else if let Some(n) = slot {
1643            result.push(ir::WidthExpr::Concrete(*n));
1644        } else {
1645            return ir::WidthExpr::from_shape(width);
1646        }
1647    }
1648    result
1649}
1650
1651fn try_syntax_expr_to_param_width(expr: &syntax_tree::Expression) -> Option<ir::WidthExpr> {
1652    let if_expr = &*expr.if_expression;
1653    if !if_expr.if_expression_list.is_empty() {
1654        return None;
1655    }
1656    let e01 = &*if_expr.expression01;
1657    if !e01.expression01_list.is_empty() {
1658        return None;
1659    }
1660    let e02 = &*e01.expression02;
1661    if !e02.expression02_list.is_empty() || e02.expression02_opt.is_some() {
1662        return None;
1663    }
1664    let factor = &*e02.factor;
1665    let id_factor = match factor {
1666        syntax_tree::Factor::IdentifierFactor(x) => &x.identifier_factor,
1667        _ => return None,
1668    };
1669    if id_factor.identifier_factor_opt.is_some() {
1670        return None;
1671    }
1672    let scoped = &*id_factor.expression_identifier;
1673    if scoped.expression_identifier_opt.is_some()
1674        || !scoped.expression_identifier_list.is_empty()
1675        || !scoped.expression_identifier_list0.is_empty()
1676    {
1677        return None;
1678    }
1679    let symbol = symbol_table::resolve(scoped.scoped_identifier.as_ref()).ok()?;
1680    if !matches!(symbol.found.kind, SymbolKind::Parameter(_)) {
1681        return None;
1682    }
1683    let parent = symbol.found.get_parent()?;
1684    match parent.kind {
1685        SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_) => {
1686            Some(ir::WidthExpr::Param(symbol.found.token.text))
1687        }
1688        _ => None,
1689    }
1690}
1691
1692#[derive(Debug, Clone, PartialEq, Eq)]
1693pub enum TypeKind {
1694    Clock,
1695    ClockPosedge,
1696    ClockNegedge,
1697    Reset,
1698    ResetAsyncHigh,
1699    ResetAsyncLow,
1700    ResetSyncHigh,
1701    ResetSyncLow,
1702    Bit,
1703    Logic,
1704    U8,
1705    U16,
1706    U32,
1707    U64,
1708    I8,
1709    I16,
1710    I32,
1711    I64,
1712    F32,
1713    F64,
1714    Type,
1715    BBool,
1716    LBool,
1717    String,
1718    UserDefined(UserDefinedType),
1719    AbstractInterface(Option<StrId>),
1720    P8,
1721    P16,
1722    P32,
1723    P64,
1724    Any,
1725    Inferred,
1726}
1727
1728impl TypeKind {
1729    pub fn is_clock(&self) -> bool {
1730        matches!(
1731            self,
1732            TypeKind::Clock | TypeKind::ClockPosedge | TypeKind::ClockNegedge
1733        )
1734    }
1735
1736    pub fn is_reset(&self) -> bool {
1737        matches!(
1738            self,
1739            TypeKind::Reset
1740                | TypeKind::ResetAsyncHigh
1741                | TypeKind::ResetAsyncLow
1742                | TypeKind::ResetSyncHigh
1743                | TypeKind::ResetSyncLow
1744        )
1745    }
1746
1747    pub fn is_2state(&self) -> bool {
1748        matches!(
1749            self,
1750            TypeKind::Bit
1751                | TypeKind::BBool
1752                | TypeKind::U8
1753                | TypeKind::U16
1754                | TypeKind::U32
1755                | TypeKind::U64
1756                | TypeKind::I8
1757                | TypeKind::I16
1758                | TypeKind::I32
1759                | TypeKind::I64
1760                | TypeKind::F32
1761                | TypeKind::F64
1762        )
1763    }
1764
1765    pub fn is_4state(&self) -> bool {
1766        self.is_clock() | self.is_reset() | (*self == TypeKind::Logic)
1767    }
1768
1769    pub fn is_fixed(&self) -> bool {
1770        matches!(
1771            self,
1772            TypeKind::U8
1773                | TypeKind::U16
1774                | TypeKind::U32
1775                | TypeKind::U64
1776                | TypeKind::I8
1777                | TypeKind::I16
1778                | TypeKind::I32
1779                | TypeKind::I64
1780                | TypeKind::F32
1781                | TypeKind::F64
1782                | TypeKind::BBool
1783                | TypeKind::LBool
1784                | TypeKind::String
1785        )
1786    }
1787
1788    pub fn is_signed(&self) -> bool {
1789        matches!(
1790            self,
1791            TypeKind::I8
1792                | TypeKind::I16
1793                | TypeKind::I32
1794                | TypeKind::I64
1795                | TypeKind::F32
1796                | TypeKind::F64
1797        )
1798    }
1799
1800    pub fn is_type(&self) -> bool {
1801        matches!(self, TypeKind::Type)
1802    }
1803}
1804
1805#[derive(Debug, Clone, PartialEq, Eq)]
1806pub struct UserDefinedType {
1807    pub path: GenericSymbolPath,
1808    // TODO remove this field because actual UserDefinedType should be resolved with replacing
1809    // generic arguments
1810    pub symbol: Option<SymbolId>,
1811}
1812
1813impl From<&syntax_tree::ScopedIdentifier> for UserDefinedType {
1814    fn from(value: &syntax_tree::ScopedIdentifier) -> Self {
1815        let path: GenericSymbolPath = value.into();
1816        Self { path, symbol: None }
1817    }
1818}
1819
1820#[derive(Debug, Clone, PartialEq, Eq)]
1821pub enum TypeModifierKind {
1822    Tri,
1823    Signed,
1824    Default,
1825}
1826
1827#[derive(Debug, Clone)]
1828pub struct TypeModifier {
1829    pub kind: TypeModifierKind,
1830    pub token: VerylToken,
1831}
1832
1833impl From<&syntax_tree::TypeModifier> for TypeModifier {
1834    fn from(value: &syntax_tree::TypeModifier) -> Self {
1835        let (kind, token) = match value {
1836            syntax_tree::TypeModifier::Tri(x) => (TypeModifierKind::Tri, &x.tri.tri_token),
1837            syntax_tree::TypeModifier::Signed(x) => {
1838                (TypeModifierKind::Signed, &x.signed.signed_token)
1839            }
1840            syntax_tree::TypeModifier::Defaul(x) => {
1841                (TypeModifierKind::Default, &x.defaul.default_token)
1842            }
1843        };
1844        TypeModifier {
1845            kind,
1846            token: token.clone(),
1847        }
1848    }
1849}
1850
1851impl fmt::Display for TypeModifier {
1852    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1853        match self.kind {
1854            TypeModifierKind::Tri => "tri".to_string().fmt(f),
1855            TypeModifierKind::Signed => "signed".to_string().fmt(f),
1856            TypeModifierKind::Default => "default".to_string().fmt(f),
1857        }
1858    }
1859}
1860
1861impl fmt::Display for Type {
1862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1863        let mut text = String::new();
1864        for x in &self.modifier {
1865            text.push_str(&x.to_string());
1866        }
1867        match &self.kind {
1868            TypeKind::Clock => text.push_str("clock"),
1869            TypeKind::ClockPosedge => text.push_str("clock posedge"),
1870            TypeKind::ClockNegedge => text.push_str("clock negedge"),
1871            TypeKind::Reset => text.push_str("reset"),
1872            TypeKind::ResetAsyncHigh => text.push_str("reset async high"),
1873            TypeKind::ResetAsyncLow => text.push_str("reset async low"),
1874            TypeKind::ResetSyncHigh => text.push_str("reset sync high"),
1875            TypeKind::ResetSyncLow => text.push_str("reset sync low"),
1876            TypeKind::Bit => text.push_str("bit"),
1877            TypeKind::Logic => text.push_str("logic"),
1878            TypeKind::P8 => text.push_str("p8"),
1879            TypeKind::P16 => text.push_str("p16"),
1880            TypeKind::P32 => text.push_str("p32"),
1881            TypeKind::P64 => text.push_str("p64"),
1882            TypeKind::U8 => text.push_str("u8"),
1883            TypeKind::U16 => text.push_str("u16"),
1884            TypeKind::U32 => text.push_str("u32"),
1885            TypeKind::U64 => text.push_str("u64"),
1886            TypeKind::I8 => text.push_str("i8"),
1887            TypeKind::I16 => text.push_str("i16"),
1888            TypeKind::I32 => text.push_str("i32"),
1889            TypeKind::I64 => text.push_str("i64"),
1890            TypeKind::F32 => text.push_str("f32"),
1891            TypeKind::F64 => text.push_str("f64"),
1892            TypeKind::Type => text.push_str("type"),
1893            TypeKind::BBool => text.push_str("bbool"),
1894            TypeKind::LBool => text.push_str("lbool"),
1895            TypeKind::String => text.push_str("string"),
1896            TypeKind::UserDefined(x) => {
1897                text.push_str(&x.path.to_string());
1898            }
1899            TypeKind::AbstractInterface(x) => {
1900                if let Some(x) = x {
1901                    text.push_str(&format!("interface::{x}"));
1902                } else {
1903                    text.push_str("interface");
1904                }
1905            }
1906            TypeKind::Any => text.push_str("any"),
1907            TypeKind::Inferred => text.push('_'),
1908        }
1909        if !self.width.is_empty() {
1910            text.push('<');
1911            for (i, x) in self.width.iter().enumerate() {
1912                if i != 0 {
1913                    text.push_str(", ");
1914                }
1915                let mut stringifier = Stringifier::new();
1916                stringifier.expression(x);
1917                text.push_str(stringifier.as_str());
1918            }
1919            text.push('>');
1920        }
1921        if !self.array.is_empty() {
1922            text.push_str(" [");
1923            for (i, x) in self.array.iter().enumerate() {
1924                if i != 0 {
1925                    text.push_str(", ");
1926                }
1927                let mut stringifier = Stringifier::new();
1928                stringifier.expression(x);
1929                text.push_str(stringifier.as_str());
1930            }
1931            text.push(']');
1932        }
1933        text.fmt(f)
1934    }
1935}
1936
1937impl TryFrom<&syntax_tree::Expression> for Type {
1938    type Error = ();
1939
1940    fn try_from(value: &syntax_tree::Expression) -> Result<Self, Self::Error> {
1941        let value = value.if_expression.as_ref();
1942        let value = if value.if_expression_list.is_empty() {
1943            value.expression01.as_ref()
1944        } else {
1945            return Err(());
1946        };
1947        let value = if value.expression01_list.is_empty() {
1948            value.expression02.as_ref()
1949        } else {
1950            return Err(());
1951        };
1952        let value = if !value.expression02_list.is_empty() || value.expression02_opt.is_some() {
1953            return Err(());
1954        } else {
1955            value.factor.as_ref()
1956        };
1957
1958        match value {
1959            syntax_tree::Factor::FactorTypeFactor(x) => {
1960                let factor = &x.factor_type_factor;
1961
1962                let mut modifier = Vec::new();
1963                for x in &factor.factor_type_factor_list {
1964                    modifier.push(TypeModifier::from(&*x.type_modifier));
1965                }
1966                let mut factor_type: Type = factor.factor_type.as_ref().into();
1967                factor_type.modifier = modifier;
1968                Ok(factor_type)
1969            }
1970            syntax_tree::Factor::IdentifierFactor(x) => {
1971                let factor = &x.identifier_factor;
1972
1973                if factor.identifier_factor_opt.is_some() {
1974                    Err(())
1975                } else {
1976                    let x = factor.expression_identifier.as_ref();
1977                    if !x.expression_identifier_list.is_empty() {
1978                        return Err(());
1979                    }
1980                    if !x.expression_identifier_list0.is_empty() {
1981                        return Err(());
1982                    }
1983
1984                    let r#type: UserDefinedType = x.scoped_identifier.as_ref().into();
1985                    let kind = TypeKind::UserDefined(r#type);
1986                    let width: Vec<_> = if let Some(ref x) = x.expression_identifier_opt {
1987                        let width: Vec<_> = x.width.as_ref().into();
1988                        width.iter().map(|x| (*x).clone()).collect()
1989                    } else {
1990                        Vec::new()
1991                    };
1992                    Ok(Type {
1993                        kind,
1994                        modifier: vec![],
1995                        width,
1996                        array: vec![],
1997                        array_type: None,
1998                        is_const: false,
1999                        token: factor.as_ref().into(),
2000                    })
2001                }
2002            }
2003            _ => Err(()),
2004        }
2005    }
2006}
2007
2008impl From<&syntax_tree::FixedType> for Type {
2009    fn from(value: &syntax_tree::FixedType) -> Self {
2010        let kind = match value {
2011            syntax_tree::FixedType::P8(_) => TypeKind::P8,
2012            syntax_tree::FixedType::P16(_) => TypeKind::P16,
2013            syntax_tree::FixedType::P32(_) => TypeKind::P32,
2014            syntax_tree::FixedType::P64(_) => TypeKind::P64,
2015            syntax_tree::FixedType::U8(_) => TypeKind::U8,
2016            syntax_tree::FixedType::U16(_) => TypeKind::U16,
2017            syntax_tree::FixedType::U32(_) => TypeKind::U32,
2018            syntax_tree::FixedType::U64(_) => TypeKind::U64,
2019            syntax_tree::FixedType::I8(_) => TypeKind::I8,
2020            syntax_tree::FixedType::I16(_) => TypeKind::I16,
2021            syntax_tree::FixedType::I32(_) => TypeKind::I32,
2022            syntax_tree::FixedType::I64(_) => TypeKind::I64,
2023            syntax_tree::FixedType::F32(_) => TypeKind::F32,
2024            syntax_tree::FixedType::F64(_) => TypeKind::F64,
2025            syntax_tree::FixedType::BBool(_) => TypeKind::BBool,
2026            syntax_tree::FixedType::LBool(_) => TypeKind::LBool,
2027            syntax_tree::FixedType::Strin(_) => TypeKind::String,
2028        };
2029        Type {
2030            kind,
2031            modifier: vec![],
2032            width: vec![],
2033            array: vec![],
2034            array_type: None,
2035            is_const: false,
2036            token: value.into(),
2037        }
2038    }
2039}
2040
2041impl From<&syntax_tree::FactorType> for Type {
2042    fn from(value: &syntax_tree::FactorType) -> Self {
2043        match value.factor_type_group.as_ref() {
2044            syntax_tree::FactorTypeGroup::VariableTypeFactorTypeOpt(x) => {
2045                let kind = match x.variable_type.as_ref() {
2046                    syntax_tree::VariableType::Clock(_) => TypeKind::Clock,
2047                    syntax_tree::VariableType::ClockPosedge(_) => TypeKind::ClockPosedge,
2048                    syntax_tree::VariableType::ClockNegedge(_) => TypeKind::ClockNegedge,
2049                    syntax_tree::VariableType::Reset(_) => TypeKind::Reset,
2050                    syntax_tree::VariableType::ResetAsyncHigh(_) => TypeKind::ResetAsyncHigh,
2051                    syntax_tree::VariableType::ResetAsyncLow(_) => TypeKind::ResetAsyncLow,
2052                    syntax_tree::VariableType::ResetSyncHigh(_) => TypeKind::ResetSyncHigh,
2053                    syntax_tree::VariableType::ResetSyncLow(_) => TypeKind::ResetSyncLow,
2054                    syntax_tree::VariableType::Logic(_) => TypeKind::Logic,
2055                    syntax_tree::VariableType::Bit(_) => TypeKind::Bit,
2056                };
2057                let width: Vec<_> = if let Some(ref x) = x.factor_type_opt {
2058                    let width: Vec<_> = x.width.as_ref().into();
2059                    width.iter().map(|x| (*x).clone()).collect()
2060                } else {
2061                    Vec::new()
2062                };
2063                Type {
2064                    kind,
2065                    modifier: vec![],
2066                    width,
2067                    array: vec![],
2068                    array_type: None,
2069                    is_const: false,
2070                    token: value.into(),
2071                }
2072            }
2073            syntax_tree::FactorTypeGroup::FixedType(x) => {
2074                let kind = match x.fixed_type.as_ref() {
2075                    syntax_tree::FixedType::P8(_) => TypeKind::P8,
2076                    syntax_tree::FixedType::P16(_) => TypeKind::P16,
2077                    syntax_tree::FixedType::P32(_) => TypeKind::P32,
2078                    syntax_tree::FixedType::P64(_) => TypeKind::P64,
2079                    syntax_tree::FixedType::U8(_) => TypeKind::U8,
2080                    syntax_tree::FixedType::U16(_) => TypeKind::U16,
2081                    syntax_tree::FixedType::U32(_) => TypeKind::U32,
2082                    syntax_tree::FixedType::U64(_) => TypeKind::U64,
2083                    syntax_tree::FixedType::I8(_) => TypeKind::I8,
2084                    syntax_tree::FixedType::I16(_) => TypeKind::I16,
2085                    syntax_tree::FixedType::I32(_) => TypeKind::I32,
2086                    syntax_tree::FixedType::I64(_) => TypeKind::I64,
2087                    syntax_tree::FixedType::F32(_) => TypeKind::F32,
2088                    syntax_tree::FixedType::F64(_) => TypeKind::F64,
2089                    syntax_tree::FixedType::BBool(_) => TypeKind::BBool,
2090                    syntax_tree::FixedType::LBool(_) => TypeKind::LBool,
2091                    syntax_tree::FixedType::Strin(_) => TypeKind::String,
2092                };
2093                Type {
2094                    kind,
2095                    modifier: vec![],
2096                    width: vec![],
2097                    array: vec![],
2098                    array_type: None,
2099                    is_const: false,
2100                    token: value.into(),
2101                }
2102            }
2103        }
2104    }
2105}
2106
2107impl From<&syntax_tree::ScalarType> for Type {
2108    fn from(value: &syntax_tree::ScalarType) -> Self {
2109        let mut modifier = Vec::new();
2110        for x in &value.scalar_type_list {
2111            modifier.push(TypeModifier::from(&*x.type_modifier));
2112        }
2113
2114        let array_type = ArrayType {
2115            scalar_type: Box::new(value.clone()),
2116            array_type_opt: None,
2117        };
2118
2119        match &*value.scalar_type_group {
2120            syntax_tree::ScalarTypeGroup::UserDefinedTypeScalarTypeOpt(x) => {
2121                let r#type: UserDefinedType = x.user_defined_type.scoped_identifier.as_ref().into();
2122                let kind = TypeKind::UserDefined(r#type);
2123                let width: Vec<_> = if let Some(ref x) = x.scalar_type_opt {
2124                    let width: Vec<_> = x.width.as_ref().into();
2125                    width.iter().map(|x| (*x).clone()).collect()
2126                } else {
2127                    Vec::new()
2128                };
2129                Type {
2130                    kind,
2131                    modifier,
2132                    width,
2133                    array: vec![],
2134                    array_type: Some(array_type),
2135                    is_const: false,
2136                    token: value.into(),
2137                }
2138            }
2139            syntax_tree::ScalarTypeGroup::FactorType(x) => {
2140                let factor_type: Type = x.factor_type.as_ref().into();
2141                Type {
2142                    kind: factor_type.kind,
2143                    modifier,
2144                    width: factor_type.width,
2145                    array: vec![],
2146                    array_type: Some(array_type),
2147                    is_const: false,
2148                    token: value.into(),
2149                }
2150            }
2151        }
2152    }
2153}
2154
2155impl From<&syntax_tree::ArrayType> for Type {
2156    fn from(value: &syntax_tree::ArrayType) -> Self {
2157        let scalar_type: Type = value.scalar_type.as_ref().into();
2158        let mut array_type = scalar_type.array_type.unwrap();
2159        let array: Vec<_> = if let Some(ref x) = value.array_type_opt {
2160            array_type.array_type_opt.replace(x.clone());
2161            let x: Vec<_> = x.array.as_ref().into();
2162            x.iter().map(|x| (*x).clone()).collect()
2163        } else {
2164            Vec::new()
2165        };
2166        Type {
2167            kind: scalar_type.kind,
2168            modifier: scalar_type.modifier,
2169            width: scalar_type.width,
2170            array,
2171            array_type: Some(array_type),
2172            is_const: false,
2173            token: value.into(),
2174        }
2175    }
2176}
2177
2178impl From<&syntax_tree::ScopedIdentifier> for Type {
2179    fn from(value: &syntax_tree::ScopedIdentifier) -> Self {
2180        let r#type: UserDefinedType = value.into();
2181        let kind = TypeKind::UserDefined(r#type);
2182        Type {
2183            kind,
2184            modifier: vec![],
2185            width: vec![],
2186            array: vec![],
2187            array_type: None,
2188            is_const: false,
2189            token: value.into(),
2190        }
2191    }
2192}
2193
2194impl From<&syntax_tree::GenericProtoBound> for Type {
2195    fn from(value: &syntax_tree::GenericProtoBound) -> Self {
2196        match value {
2197            syntax_tree::GenericProtoBound::ScopedIdentifier(x) => {
2198                x.scoped_identifier.as_ref().into()
2199            }
2200            syntax_tree::GenericProtoBound::FixedType(x) => x.fixed_type.as_ref().into(),
2201        }
2202    }
2203}
2204
2205#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2206pub enum ClockDomain {
2207    Explicit(SymbolId),
2208    Inferred(SymbolId),
2209    Implicit,
2210    #[default]
2211    None,
2212}
2213
2214impl ClockDomain {
2215    pub fn domain_id(&self) -> Option<SymbolId> {
2216        match self {
2217            ClockDomain::Explicit(id) | ClockDomain::Inferred(id) => Some(*id),
2218            _ => None,
2219        }
2220    }
2221
2222    pub fn compatible(&self, x: &ClockDomain) -> bool {
2223        match (self, x) {
2224            (ClockDomain::None, _) | (_, ClockDomain::None) => true,
2225            (a, b) => match (a.domain_id(), b.domain_id()) {
2226                (Some(a), Some(b)) => a == b,
2227                (None, None) => true,
2228                _ => false,
2229            },
2230        }
2231    }
2232}
2233
2234impl fmt::Display for ClockDomain {
2235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2236        let text = match self {
2237            ClockDomain::Explicit(x) | ClockDomain::Inferred(x) => {
2238                format!("'{}", symbol_table::get(*x).unwrap().token)
2239            }
2240            ClockDomain::Implicit => "'_".to_string(),
2241            ClockDomain::None => "".to_string(),
2242        };
2243        text.fmt(f)
2244    }
2245}
2246
2247#[derive(Debug, Clone)]
2248pub struct VariableProperty {
2249    pub r#type: Type,
2250    pub affiliation: Affiliation,
2251    pub prefix: Option<String>,
2252    pub suffix: Option<String>,
2253    pub clock_domain: ClockDomain,
2254    pub loop_variable: bool,
2255}
2256
2257#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2258pub enum Affiliation {
2259    ProjectNamespace,
2260    Module,
2261    Interface,
2262    Package,
2263    StatementBlock,
2264    Function,
2265    Modport,
2266    ProtoModule,
2267    ProtoInterface,
2268    ProtoPackage,
2269    AlwaysComb,
2270    AlwaysFf,
2271}
2272
2273#[derive(Debug, Clone)]
2274pub struct PortProperty {
2275    pub token: Token,
2276    pub r#type: Type,
2277    pub direction: Direction,
2278    pub prefix: Option<String>,
2279    pub suffix: Option<String>,
2280    pub clock_domain: ClockDomain,
2281    pub default_value: Option<syntax_tree::Expression>,
2282    pub is_proto: bool,
2283}
2284
2285#[derive(Debug, Clone)]
2286pub struct Port {
2287    pub token: VerylToken,
2288    pub symbol: SymbolId,
2289}
2290
2291impl fmt::Display for Port {
2292    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2293        let text = format!("{} [{}]", self.name(), self.property().direction);
2294        text.fmt(f)
2295    }
2296}
2297
2298impl Port {
2299    pub fn property(&self) -> PortProperty {
2300        if let SymbolKind::Port(x) = self.symbol().kind {
2301            x.clone()
2302        } else {
2303            unreachable!()
2304        }
2305    }
2306
2307    pub fn symbol(&self) -> Symbol {
2308        symbol_table::get(self.symbol).unwrap()
2309    }
2310
2311    pub fn name(&self) -> StrId {
2312        self.token.token.text
2313    }
2314}
2315
2316#[derive(Debug, Clone, Eq, PartialEq)]
2317pub enum ParameterKind {
2318    Param,
2319    Const,
2320}
2321
2322impl ParameterKind {
2323    pub fn is_const(&self) -> bool {
2324        matches!(self, ParameterKind::Const)
2325    }
2326
2327    pub fn to_sv_snippet(&self) -> String {
2328        if self.is_const() {
2329            "localparam".to_string()
2330        } else {
2331            "parameter".to_string()
2332        }
2333    }
2334}
2335
2336impl From<&ParameterKind> for ir::VarKind {
2337    fn from(value: &ParameterKind) -> Self {
2338        match value {
2339            ParameterKind::Param => ir::VarKind::Param,
2340            ParameterKind::Const => ir::VarKind::Const,
2341        }
2342    }
2343}
2344
2345#[derive(Debug, Clone)]
2346pub struct ParameterProperty {
2347    pub token: Token,
2348    pub r#type: Type,
2349    pub kind: ParameterKind,
2350    pub value: Option<syntax_tree::Expression>,
2351}
2352
2353#[derive(Debug, Clone)]
2354pub struct ProtoConstProperty {
2355    pub token: Token,
2356    pub r#type: Type,
2357}
2358
2359#[derive(Debug, Clone)]
2360pub struct Parameter {
2361    pub name: StrId,
2362    pub symbol: SymbolId,
2363}
2364
2365impl fmt::Display for Parameter {
2366    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2367        let text = format!("{} [{}]", self.name, self.property().r#type);
2368        text.fmt(f)
2369    }
2370}
2371
2372impl Parameter {
2373    pub fn property(&self) -> ParameterProperty {
2374        if let SymbolKind::Parameter(x) = symbol_table::get(self.symbol).unwrap().kind {
2375            x.clone()
2376        } else {
2377            unreachable!()
2378        }
2379    }
2380}
2381
2382#[derive(Debug, Clone)]
2383pub struct ModuleProperty {
2384    pub range: TokenRange,
2385    pub proto: Option<GenericSymbolPath>,
2386    pub generic_parameters: Vec<SymbolId>,
2387    pub generic_consts: Vec<SymbolId>,
2388    pub generic_references: Vec<GenericSymbolPath>,
2389    pub parameters: Vec<Parameter>,
2390    pub ports: Vec<Port>,
2391    pub default_clock: Option<SymbolId>,
2392    pub default_reset: Option<SymbolId>,
2393    pub definition: DefinitionId,
2394    pub test: Option<TestProperty>,
2395}
2396
2397#[derive(Debug, Clone)]
2398pub struct ProtoModuleProperty {
2399    pub range: TokenRange,
2400    pub parameters: Vec<Parameter>,
2401    pub ports: Vec<Port>,
2402    pub definition: DefinitionId,
2403}
2404
2405#[derive(Debug, Clone)]
2406pub struct AliasModuleProperty {
2407    pub target: GenericSymbolPath,
2408}
2409
2410#[derive(Debug, Clone)]
2411pub struct InterfaceProperty {
2412    pub range: TokenRange,
2413    pub proto: Option<GenericSymbolPath>,
2414    pub generic_parameters: Vec<SymbolId>,
2415    pub generic_consts: Vec<SymbolId>,
2416    pub generic_references: Vec<GenericSymbolPath>,
2417    pub parameters: Vec<Parameter>,
2418    pub members: Vec<SymbolId>,
2419    pub definition: DefinitionId,
2420}
2421
2422#[derive(Debug, Clone)]
2423pub struct ProtoInterfaceProperty {
2424    pub range: TokenRange,
2425    pub parameters: Vec<Parameter>,
2426    pub members: Vec<SymbolId>,
2427}
2428
2429#[derive(Debug, Clone)]
2430pub struct AliasInterfaceProperty {
2431    pub target: GenericSymbolPath,
2432}
2433
2434#[derive(Debug, Clone)]
2435pub struct FunctionProperty {
2436    pub affiliation: Affiliation,
2437    pub range: TokenRange,
2438    pub generic_parameters: Vec<SymbolId>,
2439    pub generic_consts: Vec<SymbolId>,
2440    pub generic_references: Vec<GenericSymbolPath>,
2441    pub ports: Vec<Port>,
2442    pub ret: Option<Type>,
2443    pub reference_paths: Vec<GenericSymbolPath>,
2444    pub constantable: Option<bool>,
2445    pub definition: Option<DefinitionId>,
2446}
2447
2448impl FunctionProperty {
2449    pub fn is_global(&self) -> bool {
2450        self.affiliation == Affiliation::ProjectNamespace
2451    }
2452}
2453
2454#[derive(Debug, Clone)]
2455pub struct SystemFuncitonProperty {
2456    pub ports: Vec<Port>,
2457}
2458
2459#[derive(Debug, Clone)]
2460pub struct ConnectTarget {
2461    pub identifiers: Vec<ConnectTargetIdentifier>,
2462    pub expression: syntax_tree::Expression,
2463}
2464
2465#[derive(Debug, Clone)]
2466pub struct ConnectTargetIdentifier {
2467    pub path: Vec<(StrId, Vec<syntax_tree::Expression>)>,
2468}
2469
2470impl ConnectTargetIdentifier {
2471    pub fn path(&self) -> Vec<StrId> {
2472        self.path.iter().map(|x| x.0).collect()
2473    }
2474
2475    pub fn is_empty(&self) -> bool {
2476        self.path.is_empty()
2477    }
2478
2479    pub fn is_partial(&self) -> bool {
2480        self.path.iter().any(|x| !x.1.is_empty())
2481    }
2482}
2483
2484impl From<&syntax_tree::ExpressionIdentifier> for ConnectTargetIdentifier {
2485    fn from(value: &syntax_tree::ExpressionIdentifier) -> Self {
2486        let path: SymbolPath = value.scoped_identifier.as_ref().into();
2487
2488        let mut ret = vec![];
2489        for (i, x) in path.as_slice().iter().enumerate() {
2490            if i == path.as_slice().len() - 1 {
2491                let select: Vec<_> = value
2492                    .expression_identifier_list
2493                    .iter()
2494                    .map(|x| x.select.expression.as_ref().clone())
2495                    .collect();
2496                ret.push((*x, select));
2497            } else {
2498                ret.push((*x, vec![]));
2499            }
2500        }
2501
2502        for x in &value.expression_identifier_list0 {
2503            let text = x.identifier.identifier_token.token.text;
2504            let select: Vec<_> = x
2505                .expression_identifier_list0_list
2506                .iter()
2507                .map(|x| x.select.expression.as_ref().clone())
2508                .collect();
2509            ret.push((text, select));
2510        }
2511        Self { path: ret }
2512    }
2513}
2514
2515#[derive(Debug, Clone)]
2516pub struct InstanceProperty {
2517    pub array: Vec<syntax_tree::Expression>,
2518    pub type_name: GenericSymbolPath,
2519    pub parameter_connects: HashMap<Token, ConnectTarget>,
2520    pub port_connects: HashMap<Token, ConnectTarget>,
2521    pub clock_domain: ClockDomain,
2522}
2523
2524#[derive(Debug, Clone)]
2525pub struct PackageProperty {
2526    pub range: TokenRange,
2527    pub proto: Option<GenericSymbolPath>,
2528    pub generic_parameters: Vec<SymbolId>,
2529    pub generic_consts: Vec<SymbolId>,
2530    pub generic_references: Vec<GenericSymbolPath>,
2531    pub members: Vec<SymbolId>,
2532}
2533
2534#[derive(Debug, Clone)]
2535pub struct AliasPackageProperty {
2536    pub target: GenericSymbolPath,
2537}
2538
2539#[derive(Debug, Clone)]
2540pub struct ProtoPackageProperty {
2541    pub range: TokenRange,
2542    pub members: Vec<SymbolId>,
2543}
2544
2545#[derive(Debug, Clone)]
2546pub struct StructProperty {
2547    pub members: Vec<SymbolId>,
2548    pub generic_parameters: Vec<SymbolId>,
2549    pub generic_references: Vec<GenericSymbolPath>,
2550}
2551
2552#[derive(Debug, Clone)]
2553pub struct StructMemberProperty {
2554    pub r#type: Type,
2555}
2556
2557#[derive(Debug, Clone)]
2558pub struct UnionProperty {
2559    pub members: Vec<SymbolId>,
2560    pub generic_parameters: Vec<SymbolId>,
2561    pub generic_references: Vec<GenericSymbolPath>,
2562}
2563
2564#[derive(Debug, Clone)]
2565pub struct UnionMemberProperty {
2566    pub r#type: Type,
2567}
2568
2569#[derive(Debug, Clone)]
2570pub struct TypeDefProperty {
2571    pub r#type: Type,
2572}
2573
2574#[derive(Debug, Clone)]
2575pub struct ProtoTypeDefProperty {
2576    pub r#type: Option<Type>,
2577}
2578
2579#[derive(Debug, Clone)]
2580pub struct EnumProperty {
2581    pub r#type: Option<Type>,
2582    pub width: usize,
2583    pub members: Vec<SymbolId>,
2584    pub encoding: EnumEncodingItem,
2585}
2586
2587#[derive(Debug, Clone)]
2588pub enum EnumMemberValue {
2589    ImplicitValue(usize),
2590    ExplicitValue(syntax_tree::Expression, Option<usize>),
2591    UnevaluableValue,
2592}
2593
2594impl EnumMemberValue {
2595    pub fn value(&self) -> Option<usize> {
2596        match self {
2597            EnumMemberValue::ImplicitValue(value) => Some(*value),
2598            EnumMemberValue::ExplicitValue(_expression, evaluated) => *evaluated,
2599            EnumMemberValue::UnevaluableValue => None,
2600        }
2601    }
2602}
2603
2604#[derive(Debug, Clone)]
2605pub struct EnumMemberProperty {
2606    pub value: EnumMemberValue,
2607    pub prefix: String,
2608}
2609
2610#[derive(Debug, Clone)]
2611pub struct ModportProperty {
2612    pub interface: SymbolId,
2613    pub members: Vec<SymbolId>,
2614    pub default: Option<ModportDefault>,
2615}
2616
2617#[derive(Debug, Clone)]
2618pub enum ModportDefault {
2619    Input,
2620    Output,
2621    Same(Vec<Token>),
2622    Converse(Vec<Token>),
2623}
2624
2625#[derive(Debug, Clone)]
2626pub struct ModportVariableMemberProperty {
2627    pub direction: Direction,
2628    pub variable: SymbolId,
2629}
2630
2631#[derive(Debug, Clone)]
2632pub struct ModportFunctionMemberProperty {
2633    pub function: SymbolId,
2634}
2635
2636#[derive(Debug, Clone)]
2637pub enum GenericBoundKind {
2638    Type,
2639    Inst(GenericSymbolPath),
2640    Proto(Box<Type>),
2641}
2642
2643#[derive(Debug, Clone)]
2644pub enum ProtoBound {
2645    ProtoModule(Symbol),
2646    ProtoInterface(Symbol),
2647    ProtoPackage(Symbol),
2648    FactorType(Type),
2649    Enum((Symbol, Type)),
2650    Struct((Symbol, Type)),
2651    Union((Symbol, Type)),
2652}
2653
2654impl ProtoBound {
2655    pub fn get_symbol(&self) -> Option<Symbol> {
2656        match self {
2657            ProtoBound::ProtoModule(x)
2658            | ProtoBound::ProtoInterface(x)
2659            | ProtoBound::ProtoPackage(x)
2660            | ProtoBound::Enum((x, _))
2661            | ProtoBound::Struct((x, _))
2662            | ProtoBound::Union((x, _)) => Some(x.clone()),
2663            _ => None,
2664        }
2665    }
2666
2667    pub fn is_variable_type(&self) -> bool {
2668        matches!(
2669            self,
2670            ProtoBound::FactorType(_)
2671                | ProtoBound::Enum(_)
2672                | ProtoBound::Struct(_)
2673                | ProtoBound::Union(_)
2674        )
2675    }
2676}
2677
2678impl GenericBoundKind {
2679    pub fn is_compatible(&self, other: &GenericBoundKind) -> bool {
2680        self.to_string() == other.to_string()
2681    }
2682
2683    pub fn resolve_inst_bound(&self, namespace: &Namespace) -> Result<Symbol, Option<SymbolId>> {
2684        let GenericBoundKind::Inst(path) = self else {
2685            return Err(None);
2686        };
2687
2688        if let Ok(symbol) = symbol_table::resolve((&path.mangled_path(), namespace)) {
2689            if symbol.found.is_proto_interface(false, true) {
2690                Ok((*symbol.found).clone())
2691            } else {
2692                Err(Some(symbol.found.id))
2693            }
2694        } else {
2695            Err(None)
2696        }
2697    }
2698
2699    pub fn resolve_proto_bound(
2700        &self,
2701        namespace: &Namespace,
2702    ) -> Result<ProtoBound, Option<SymbolId>> {
2703        let GenericBoundKind::Proto(proto) = self else {
2704            return Err(None);
2705        };
2706
2707        let Some((r#type, symbol)) = proto.trace_user_defined(Some(namespace)) else {
2708            return Err(None);
2709        };
2710        if symbol.is_none() {
2711            return Ok(ProtoBound::FactorType(r#type));
2712        }
2713
2714        let symbol = symbol.unwrap();
2715        match &symbol.kind {
2716            SymbolKind::ProtoModule(_) => Ok(ProtoBound::ProtoModule(symbol)),
2717            SymbolKind::ProtoInterface(_) => Ok(ProtoBound::ProtoInterface(symbol)),
2718            SymbolKind::ProtoPackage(_) => Ok(ProtoBound::ProtoPackage(symbol)),
2719            SymbolKind::Enum(_) => Ok(ProtoBound::Enum((symbol, r#type))),
2720            SymbolKind::Struct(_) => Ok(ProtoBound::Struct((symbol, r#type))),
2721            SymbolKind::Union(_) => Ok(ProtoBound::Union((symbol, r#type))),
2722            _ => Err(Some(symbol.id)),
2723        }
2724    }
2725}
2726
2727impl fmt::Display for GenericBoundKind {
2728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2729        let text = match self {
2730            GenericBoundKind::Type => "type".to_string(),
2731            GenericBoundKind::Inst(x) => x.to_string(),
2732            GenericBoundKind::Proto(x) => x.to_string(),
2733        };
2734        text.fmt(f)
2735    }
2736}
2737
2738#[derive(Debug, Clone)]
2739pub struct GenericParameterProperty {
2740    pub bound: GenericBoundKind,
2741    pub default_value: Option<GenericSymbolPath>,
2742}
2743
2744#[derive(Debug, Clone)]
2745pub struct GenericConstProperty {
2746    pub bound: GenericBoundKind,
2747    pub value: syntax_tree::Expression,
2748}
2749
2750#[derive(Debug, Clone)]
2751pub struct GenericInstanceProperty {
2752    pub base: SymbolId,
2753    pub arguments: Vec<GenericSymbolPath>,
2754    pub affiliation_symbol: Option<SymbolId>,
2755}
2756
2757impl GenericInstanceProperty {
2758    pub fn base_symbol(&self) -> Symbol {
2759        symbol_table::get(self.base).unwrap()
2760    }
2761}
2762
2763#[derive(Debug, Clone)]
2764pub enum TestType {
2765    Inline,
2766    CocotbEmbed(Box<syntax_tree::EmbedContent>),
2767    CocotbInclude(StrId),
2768    Native,
2769}
2770
2771#[derive(Debug, Clone)]
2772pub struct TestProperty {
2773    pub r#type: TestType,
2774    pub path: PathId,
2775    pub top: Option<StrId>,
2776    pub ignored: bool,
2777}
2778
2779#[derive(Debug, Clone)]
2780pub enum TbComponentKind {
2781    ClockGen,
2782    ResetGen,
2783}
2784
2785impl std::fmt::Display for TbComponentKind {
2786    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2787        match self {
2788            TbComponentKind::ClockGen => write!(f, "clock_gen"),
2789            TbComponentKind::ResetGen => write!(f, "reset_gen"),
2790        }
2791    }
2792}
2793
2794#[derive(Debug, Clone)]
2795pub struct TbComponentProperty {
2796    pub kind: TbComponentKind,
2797}