Skip to content

Commit 33f9eb6

Browse files
enhance generic boundary
* introduce a new generic bound `inst` to specify module/interface instance
1 parent b79f4ea commit 33f9eb6

File tree

14 files changed

+3166
-2983
lines changed

14 files changed

+3166
-2983
lines changed

crates/analyzer/src/handlers/check_type.rs

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::analyzer_error::AnalyzerError;
22
use crate::attribute::AllowItem;
33
use crate::attribute::Attribute as Attr;
44
use crate::attribute_table;
5+
use crate::namespace::Namespace;
56
use crate::namespace_table;
67
use crate::symbol::{GenericBoundKind, Symbol, SymbolKind, TypeKind};
78
use crate::symbol_path::GenericSymbolPath;
@@ -66,6 +67,42 @@ fn is_casting_type(symbol: &Symbol) -> bool {
6667
}
6768
}
6869

70+
fn resolve_inst_generic_arg_type(arg: &GenericSymbolPath, namespace: &Namespace) -> Option<Symbol> {
71+
if !arg.is_resolvable() {
72+
return None;
73+
}
74+
75+
let arg_symbol = symbol_table::resolve((&arg.generic_path(), namespace)).ok()?;
76+
let inst_symbol = if let SymbolKind::Instance(inst) = arg_symbol.found.kind {
77+
symbol_table::resolve((&inst.type_name.mangled_path(), namespace)).ok()?
78+
} else {
79+
return None;
80+
};
81+
82+
if let Some(ref proto) = inst_symbol.found.proto() {
83+
symbol_table::resolve((proto, namespace))
84+
.ok()
85+
.map(|s| s.found)
86+
} else {
87+
Some(inst_symbol.found)
88+
}
89+
}
90+
91+
fn resolve_proto_generic_arg_type(
92+
arg: &GenericSymbolPath,
93+
namespace: &Namespace,
94+
) -> Option<Symbol> {
95+
if !arg.is_resolvable() {
96+
return None;
97+
}
98+
99+
let arg_symbol = symbol_table::resolve((&arg.generic_path(), namespace)).ok()?;
100+
let proto = arg_symbol.found.proto()?;
101+
symbol_table::resolve((&proto, namespace))
102+
.ok()
103+
.map(|s| s.found)
104+
}
105+
69106
impl VerylGrammarTrait for CheckType<'_> {
70107
fn user_defined_type(&mut self, _arg: &UserDefinedType) -> Result<(), ParolError> {
71108
match self.point {
@@ -210,33 +247,37 @@ impl VerylGrammarTrait for CheckType<'_> {
210247
));
211248
}
212249
}
250+
GenericBoundKind::Inst(proto) => {
251+
let actual = resolve_inst_generic_arg_type(arg, &namespace);
252+
let required =
253+
symbol_table::resolve((proto, &defined_namespace));
254+
let proto_match =
255+
if let (Some(actual), Ok(required)) = (actual, required) {
256+
actual.id == required.found.id
257+
} else {
258+
false
259+
};
260+
261+
if !proto_match {
262+
self.errors.push(AnalyzerError::mismatch_type(
263+
&symbol.found.token.to_string(),
264+
&format!("inst {proto}"),
265+
&symbol.found.kind.to_kind_name(),
266+
self.text,
267+
&arg.range,
268+
));
269+
}
270+
}
213271
GenericBoundKind::Proto(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 Some(ref x) = symbol.found.kind.proto() {
219-
let actual = symbol_table::resolve((x, &namespace));
220-
let required = symbol_table::resolve((
221-
proto,
222-
&defined_namespace,
223-
));
224-
if let (Ok(actual), Ok(required)) =
225-
(actual, required)
226-
{
227-
actual.found.id == required.found.id
228-
} else {
229-
false
230-
}
231-
} else {
232-
false
233-
}
272+
let actual = resolve_proto_generic_arg_type(arg, &namespace);
273+
let required =
274+
symbol_table::resolve((proto, &defined_namespace));
275+
let proto_match =
276+
if let (Some(actual), Ok(required)) = (actual, required) {
277+
actual.id == required.found.id
234278
} else {
235279
false
236-
}
237-
} else {
238-
false
239-
};
280+
};
240281

241282
if !proto_match {
242283
self.errors.push(AnalyzerError::mismatch_type(

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: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,17 @@ 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::GenericParameter(x) => match x.bound {
305+
GenericBoundKind::Proto(ref x) => Some(x.clone()),
306+
_ => None,
307+
},
308+
_ => None,
309+
}
310+
}
300311
}
301312

302313
#[derive(Debug, Clone)]
@@ -416,17 +427,6 @@ impl SymbolKind {
416427
}
417428
}
418429

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-
430430
pub fn get_type(&self) -> Option<&Type> {
431431
match self {
432432
SymbolKind::Port(x) => x.r#type.as_ref(),
@@ -1354,6 +1354,7 @@ pub struct ModportFunctionMemberProperty {
13541354
pub enum GenericBoundKind {
13551355
Const,
13561356
Type,
1357+
Inst(SymbolPath),
13571358
Proto(SymbolPath),
13581359
}
13591360

@@ -1362,6 +1363,7 @@ impl fmt::Display for GenericBoundKind {
13621363
let text = match self {
13631364
GenericBoundKind::Const => "const".to_string(),
13641365
GenericBoundKind::Type => "type".to_string(),
1366+
GenericBoundKind::Inst(x) => x.to_string(),
13651367
GenericBoundKind::Proto(x) => x.to_string(),
13661368
};
13671369
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)