veryl_analyzer/ir/
signature.rs1use 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 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 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) = ¤t_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}