Skip to main content

veryl_analyzer/ir/
signature.rs

1use crate::conv::Context;
2use crate::generic_inference_table;
3use crate::ir::ValueVariant;
4use crate::namespace::Namespace;
5use crate::symbol::GenericMap;
6use crate::symbol::{GenericBoundKind, SymbolId, SymbolKind, TypeKind};
7use crate::symbol_path::GenericSymbolPath;
8use crate::{namespace_table, symbol_table};
9use std::fmt;
10use veryl_parser::resource_table::StrId;
11
12#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub struct Signature {
14    pub symbol: SymbolId,
15    pub full_path: Vec<StrId>,
16    pub parameters: Vec<(StrId, ValueVariant)>,
17    pub generic_parameters: Vec<(StrId, GenericSymbolPath)>,
18}
19
20impl Signature {
21    pub fn new(symbol: SymbolId) -> Self {
22        Self {
23            symbol,
24            full_path: vec![],
25            parameters: vec![],
26            generic_parameters: vec![],
27        }
28    }
29
30    pub fn add_parameter(&mut self, id: StrId, value: ValueVariant) {
31        self.parameters.push((id, value));
32    }
33
34    pub fn add_generic_parameter(&mut self, id: StrId, value: GenericSymbolPath) {
35        self.generic_parameters.push((id, value));
36    }
37
38    pub fn normalize(&mut self) {
39        self.parameters.sort();
40        self.generic_parameters.sort();
41    }
42
43    pub fn from_path(context: &mut Context, mut path: GenericSymbolPath) -> Option<Self> {
44        let namespace = namespace_table::get(path.paths[0].base.id).unwrap();
45        path.resolve_imported(&namespace, None);
46        path.unalias();
47
48        let symbol = symbol_table::resolve(&path).ok()?;
49
50        generic_inference_table::apply_inferred_args(&mut path, &symbol.found);
51        let mut sig = match &symbol.found.kind {
52            SymbolKind::Module(_)
53            | SymbolKind::Interface(_)
54            | SymbolKind::Modport(_)
55            | SymbolKind::Function(_)
56            | SymbolKind::SystemVerilog => Self::new(symbol.found.id),
57            SymbolKind::ModportFunctionMember(x) => Self::new(x.function),
58            SymbolKind::GenericParameter(_) => {
59                let path = context.resolve_path(path.clone());
60                let symbol = symbol_table::resolve(&path).ok()?;
61                if let SymbolKind::GenericParameter(x) = &symbol.found.kind {
62                    if let GenericBoundKind::Proto(x) = &x.bound {
63                        if let TypeKind::UserDefined(x) = &x.kind {
64                            let symbol = symbol_table::resolve(&x.path).ok()?;
65                            return Some(Signature::new(symbol.found.id));
66                        } else {
67                            return None;
68                        }
69                    } else {
70                        return None;
71                    }
72                }
73                Self::new(symbol.found.id)
74            }
75            SymbolKind::ProtoFunction(_) => {
76                let resolved = context.resolve_path(path.clone());
77                let symbol = symbol_table::resolve(&resolved).ok()?;
78                match &symbol.found.kind {
79                    SymbolKind::Function(_) | SymbolKind::ProtoFunction(_) => {
80                        Self::new(symbol.found.id)
81                    }
82                    _ => return None,
83                }
84            }
85            SymbolKind::ProtoAliasModule(x) => {
86                let symbol = symbol_table::resolve(&x.target).ok()?;
87                return Some(Signature::new(symbol.found.id));
88            }
89            _ => return None,
90        };
91
92        if !context.in_generic {
93            // Apply default value
94            for (i, id) in symbol.full_path.iter().enumerate() {
95                let path_symbol = if (i + 1) == symbol.full_path.len() {
96                    symbol_table::get(sig.symbol).unwrap()
97                } else {
98                    symbol_table::get(*id).unwrap()
99                };
100
101                let params = path_symbol.generic_parameters();
102                let n_args = path.paths[i].arguments.len();
103                for (_, default_value) in params.iter().skip(n_args) {
104                    if let Some(default_value) = &default_value.default_value {
105                        path.paths[i].arguments.push(default_value.clone())
106                    }
107                }
108            }
109
110            if path.is_generic() {
111                let namespace = namespace_table::get(path.paths[0].base.id).unwrap();
112                path.resolve_imported(&namespace, None);
113
114                // Apply generic map
115                let path = context.resolve_path(path);
116
117                let namespace = namespace_table::get(path.paths[0].base.id).unwrap();
118                if let Ok(symbol) = symbol_table::resolve((&path.mangled_path(), &namespace)) {
119                    let current_namespace = context.current_namespace();
120                    for id in &symbol.full_path {
121                        let symbol = symbol_table::get(*id).unwrap();
122                        let SymbolKind::GenericInstance(inst) = &symbol.kind else {
123                            continue;
124                        };
125
126                        let base = symbol_table::get(inst.base).unwrap();
127                        let params = base.generic_parameters();
128                        if inst.arguments.len() == params.len() {
129                            for (i, (name, _)) in params.iter().enumerate() {
130                                let mut arg = inst.arguments[i].clone();
131                                if let Some(current_namespace) = &current_namespace {
132                                    arg.append_namespace_path(current_namespace, &base.namespace);
133                                }
134                                sig.add_generic_parameter(*name, arg);
135                            }
136                        }
137                    }
138
139                    sig.full_path
140                        .append(&mut symbol.found.inner_namespace().paths.to_vec());
141                }
142            }
143        }
144
145        Some(sig)
146    }
147
148    pub fn to_generic_map(&self) -> Vec<GenericMap> {
149        let mut ret = GenericMap::default();
150
151        for (key, val) in &self.generic_parameters {
152            ret.map.insert(*key, val.clone());
153        }
154
155        let symbol = symbol_table::get(self.symbol).unwrap();
156        symbol.eval_generic_consts(&mut ret);
157
158        vec![ret]
159    }
160
161    pub fn namespace(&self) -> Namespace {
162        if self.full_path.is_empty() {
163            let symbol = symbol_table::get(self.symbol).unwrap();
164            symbol.inner_namespace()
165        } else {
166            let mut ret = Namespace::new();
167
168            for path in &self.full_path {
169                ret.push(*path);
170            }
171
172            ret
173        }
174    }
175}
176
177impl fmt::Display for Signature {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        let symbol = symbol_table::get(self.symbol).unwrap();
180        let mut ret = symbol.token.text.to_string();
181
182        for x in &self.generic_parameters {
183            ret.push_str(&format!("::<{}>", x.1));
184        }
185
186        ret.fmt(f)
187    }
188}