Skip to content

Commit e7c90ff

Browse files
enhance generic boundary
* allow to use interface as generic bound * introduce a new generic bound `inst` to specify module/interface instance
1 parent 7a7430d commit e7c90ff

File tree

17 files changed

+3212
-2968
lines changed

17 files changed

+3212
-2968
lines changed

crates/analyzer/src/handlers/check_type.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,62 @@ impl VerylGrammarTrait for CheckType<'_> {
210210
));
211211
}
212212
}
213+
GenericBoundKind::Inst(proto) => {
214+
let proto_match = if arg.is_resolvable() {
215+
if let Ok(symbol) =
216+
symbol_table::resolve((&arg.generic_path(), &namespace))
217+
{
218+
if let SymbolKind::Instance(x) = symbol.found.kind {
219+
if let Ok(x) = symbol_table::resolve((
220+
&x.type_name.mangled_path(),
221+
&namespace,
222+
)) {
223+
if let Some(ref x) = x.found.proto() {
224+
let actual =
225+
symbol_table::resolve((x, &namespace));
226+
let required = symbol_table::resolve((
227+
proto,
228+
&defined_namespace,
229+
));
230+
if let (Ok(actual), Ok(required)) =
231+
(actual, required)
232+
{
233+
actual.found.id == required.found.id
234+
} else {
235+
false
236+
}
237+
} else {
238+
false
239+
}
240+
} else {
241+
false
242+
}
243+
} else {
244+
false
245+
}
246+
} else {
247+
false
248+
}
249+
} else {
250+
false
251+
};
252+
253+
if !proto_match {
254+
self.errors.push(AnalyzerError::mismatch_type(
255+
&symbol.found.token.to_string(),
256+
&format!("inst {proto}"),
257+
&symbol.found.kind.to_kind_name(),
258+
self.text,
259+
&arg.range,
260+
));
261+
}
262+
}
213263
GenericBoundKind::Proto(proto) => {
214264
let proto_match = if arg.is_resolvable() {
215265
if let Ok(symbol) =
216266
symbol_table::resolve((&arg.generic_path(), &namespace))
217267
{
218-
if let Some(ref x) = symbol.found.kind.proto() {
268+
if let Some(ref x) = symbol.found.proto() {
219269
let actual = symbol_table::resolve((x, &namespace));
220270
let required = symbol_table::resolve((
221271
proto,
@@ -327,13 +377,18 @@ impl VerylGrammarTrait for CheckType<'_> {
327377
if let GenericBoundKind::Proto(ref x) = x.bound {
328378
if let Ok(symbol) = symbol_table::resolve((x, &symbol.found.namespace))
329379
{
330-
if let SymbolKind::ProtoModule(x) = symbol.found.kind {
331-
params.append(&mut x.parameters.clone());
332-
ports.append(&mut x.ports.clone());
333-
check_port_connection = true;
334-
None
335-
} else {
336-
Some("module or interface")
380+
match &symbol.found.kind {
381+
SymbolKind::ProtoModule(x) => {
382+
params.append(&mut x.parameters.clone());
383+
ports.append(&mut x.ports.clone());
384+
check_port_connection = true;
385+
None
386+
}
387+
SymbolKind::Interface(x) => {
388+
params.append(&mut x.parameters.clone());
389+
None
390+
}
391+
_ => Some("module or interface"),
337392
}
338393
} else {
339394
None

crates/analyzer/src/handlers/create_symbol_table.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,9 @@ impl VerylGrammarTrait for CreateSymbolTable<'_> {
977977
let bound = match arg.generic_bound.as_ref() {
978978
GenericBound::Const(_) => GenericBoundKind::Const,
979979
GenericBound::Type(_) => GenericBoundKind::Type,
980+
GenericBound::InstScopedIdentifier(x) => {
981+
GenericBoundKind::Inst(x.scoped_identifier.as_ref().into())
982+
}
980983
GenericBound::ScopedIdentifier(x) => {
981984
GenericBoundKind::Proto(x.scoped_identifier.as_ref().into())
982985
}

crates/analyzer/src/symbol.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,18 @@ impl Symbol {
297297
_ => Vec::new(),
298298
}
299299
}
300+
301+
pub fn proto(&self) -> Option<SymbolPath> {
302+
match &self.kind {
303+
SymbolKind::Module(x) => x.proto.clone(),
304+
SymbolKind::Interface(_) => Some((&self.token).into()),
305+
SymbolKind::GenericParameter(x) => match x.bound {
306+
GenericBoundKind::Proto(ref x) => Some(x.clone()),
307+
_ => None,
308+
},
309+
_ => None,
310+
}
311+
}
300312
}
301313

302314
#[derive(Debug, Clone)]
@@ -416,17 +428,6 @@ impl SymbolKind {
416428
}
417429
}
418430

419-
pub fn proto(&self) -> Option<SymbolPath> {
420-
match self {
421-
SymbolKind::Module(x) => x.proto.clone(),
422-
SymbolKind::GenericParameter(x) => match x.bound {
423-
GenericBoundKind::Proto(ref x) => Some(x.clone()),
424-
_ => None,
425-
},
426-
_ => None,
427-
}
428-
}
429-
430431
pub fn get_type(&self) -> Option<&Type> {
431432
match self {
432433
SymbolKind::Port(x) => x.r#type.as_ref(),
@@ -1354,6 +1355,7 @@ pub struct ModportFunctionMemberProperty {
13541355
pub enum GenericBoundKind {
13551356
Const,
13561357
Type,
1358+
Inst(SymbolPath),
13571359
Proto(SymbolPath),
13581360
}
13591361

@@ -1362,6 +1364,7 @@ impl fmt::Display for GenericBoundKind {
13621364
let text = match self {
13631365
GenericBoundKind::Const => "const".to_string(),
13641366
GenericBoundKind::Type => "type".to_string(),
1367+
GenericBoundKind::Inst(x) => x.to_string(),
13651368
GenericBoundKind::Proto(x) => x.to_string(),
13661369
};
13671370
text.fmt(f)

crates/analyzer/src/symbol_table.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::evaluator::Evaluated;
22
use crate::namespace::Namespace;
3-
use crate::symbol::{DocComment, Symbol, SymbolId, SymbolKind, TypeKind};
3+
use crate::symbol::{DocComment, GenericBoundKind, Symbol, SymbolId, SymbolKind, TypeKind};
44
use crate::symbol_path::{SymbolPath, SymbolPathNamespace};
55
use crate::var_ref::{Assign, VarRef, VarRefAffiliation};
66
use std::cell::RefCell;
@@ -268,9 +268,15 @@ impl SymbolTable {
268268
.generic_namespace_map
269269
.insert(symbol.token.text, found.token.text);
270270
}
271-
SymbolKind::GenericParameter(_) => {
272-
context.namespace = found.inner_namespace();
273-
context.inner = true;
271+
SymbolKind::GenericParameter(ref x) => {
272+
if let GenericBoundKind::Inst(proto) = &x.bound {
273+
let symbol = self.resolve(proto, &found.namespace)?;
274+
context.namespace = symbol.found.inner_namespace();
275+
context.inner = true;
276+
} else {
277+
context.namespace = found.inner_namespace();
278+
context.inner = true;
279+
}
274280
}
275281
// don't trace inner item
276282
SymbolKind::Function(_)

0 commit comments

Comments
 (0)