Skip to content

Commit 314175c

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

File tree

14 files changed

+3167
-2983
lines changed

14 files changed

+3167
-2983
lines changed

crates/analyzer/src/handlers/check_type.rs

Lines changed: 66 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;
@@ -210,33 +211,37 @@ impl VerylGrammarTrait for CheckType<'_> {
210211
));
211212
}
212213
}
214+
GenericBoundKind::Inst(proto) => {
215+
let actual = resolve_inst_generic_arg_type(&arg, &namespace);
216+
let required =
217+
symbol_table::resolve((proto, &defined_namespace));
218+
let proto_match =
219+
if let (Some(actual), Ok(required)) = (actual, required) {
220+
actual.id == required.found.id
221+
} else {
222+
false
223+
};
224+
225+
if !proto_match {
226+
self.errors.push(AnalyzerError::mismatch_type(
227+
&symbol.found.token.to_string(),
228+
&format!("inst {proto}"),
229+
&symbol.found.kind.to_kind_name(),
230+
self.text,
231+
&arg.range,
232+
));
233+
}
234+
}
213235
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-
}
236+
let actual = resolve_proto_generic_arg_type(&arg, &namespace);
237+
let required =
238+
symbol_table::resolve((proto, &defined_namespace));
239+
let proto_match =
240+
if let (Some(actual), Ok(required)) = (actual, required) {
241+
actual.id == required.found.id
234242
} else {
235243
false
236-
}
237-
} else {
238-
false
239-
};
244+
};
240245

241246
if !proto_match {
242247
self.errors.push(AnalyzerError::mismatch_type(
@@ -407,3 +412,40 @@ impl VerylGrammarTrait for CheckType<'_> {
407412
Ok(())
408413
}
409414
}
415+
416+
fn resolve_inst_generic_arg_type(arg: &GenericSymbolPath, namespace: &Namespace) -> Option<Symbol> {
417+
if !arg.is_resolvable() {
418+
return None;
419+
}
420+
421+
let arg_symbol = symbol_table::resolve((&arg.generic_path(), namespace)).ok()?;
422+
let inst_symbol = if let SymbolKind::Instance(inst) = arg_symbol.found.kind {
423+
symbol_table::resolve((&inst.type_name.mangled_path(), namespace)).ok()?
424+
} else {
425+
return None;
426+
};
427+
428+
if let Some(ref proto) = inst_symbol.found.proto() {
429+
symbol_table::resolve((proto, namespace))
430+
.ok()
431+
.map(|s| s.found)
432+
} else {
433+
Some(inst_symbol.found)
434+
}
435+
436+
}
437+
438+
fn resolve_proto_generic_arg_type(
439+
arg: &GenericSymbolPath,
440+
namespace: &Namespace,
441+
) -> Option<Symbol> {
442+
if !arg.is_resolvable() {
443+
return None;
444+
}
445+
446+
let arg_symbol = symbol_table::resolve((&arg.generic_path(), namespace)).ok()?;
447+
let proto = arg_symbol.found.proto()?;
448+
symbol_table::resolve((&proto, namespace))
449+
.ok()
450+
.map(|s| s.found)
451+
}

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)