Skip to content

Commit 59aa506

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 c652cbc commit 59aa506

File tree

14 files changed

+3159
-2960
lines changed

14 files changed

+3159
-2960
lines changed

crates/analyzer/src/handlers/check_type.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,68 @@ impl VerylGrammarTrait for CheckType<'_> {
210210
));
211211
}
212212
}
213+
GenericBoundKind::Inst(proto) => {
214+
// TODO:
215+
// Re-write the nested if statements below
216+
// when Rust 1.85 will be released and the `if-let` chain will be stabilized.
217+
let proto_match = if arg.is_resolvable() {
218+
if let Ok(symbol) =
219+
symbol_table::resolve((&arg.generic_path(), &namespace))
220+
{
221+
if let SymbolKind::Instance(x) = symbol.found.kind {
222+
if let Ok(x) = symbol_table::resolve((
223+
&x.type_name.mangled_path(),
224+
&namespace,
225+
)) {
226+
if let Some(ref x) = x.found.proto() {
227+
let actual =
228+
symbol_table::resolve((x, &namespace));
229+
let required = symbol_table::resolve((
230+
proto,
231+
&defined_namespace,
232+
));
233+
if let (Ok(actual), Ok(required)) =
234+
(actual, required)
235+
{
236+
actual.found.id == required.found.id
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+
} else {
253+
false
254+
};
255+
256+
if !proto_match {
257+
self.errors.push(AnalyzerError::mismatch_type(
258+
&symbol.found.token.to_string(),
259+
&format!("inst {proto}"),
260+
&symbol.found.kind.to_kind_name(),
261+
self.text,
262+
&arg.range,
263+
));
264+
}
265+
}
213266
GenericBoundKind::Proto(proto) => {
267+
// TODO:
268+
// Re-write the nested if statements below
269+
// when Rust 1.85 will be released and the `if-let` chain will be stabilized.
214270
let proto_match = if arg.is_resolvable() {
215271
if let Ok(symbol) =
216272
symbol_table::resolve((&arg.generic_path(), &namespace))
217273
{
218-
if let Some(ref x) = symbol.found.kind.proto() {
274+
if let Some(ref x) = symbol.found.proto() {
219275
let actual = symbol_table::resolve((x, &namespace));
220276
let required = symbol_table::resolve((
221277
proto,

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)