Skip to content

Commit

Permalink
Add unknown member check #84
Browse files Browse the repository at this point in the history
  • Loading branch information
dalance committed Jan 17, 2023
1 parent 24173ce commit 6b8807b
Show file tree
Hide file tree
Showing 10 changed files with 508 additions and 317 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased](https://github.com/dalance/veryl/compare/v0.2.0...Unreleased) - ReleaseDate

* [Added] uknown member check [#84](https://github.com/dalance/veryl/issues/84)

## [v0.2.0](https://github.com/dalance/veryl/compare/v0.1.14...v0.2.0) - 2023-01-16

* [Changed] modport separator from `.` to `::` [#65](https://github.com/dalance/veryl/issues/65)
Expand Down
22 changes: 21 additions & 1 deletion crates/analyzer/src/analyzer_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub enum AnalyzerError {
},

#[diagnostic(code(AnalyzerError::UnknownPort), help("remove \"{port}\" port"))]
#[error("module \"{name}\" doesn't has \"{port}\", but it is connected")]
#[error("module \"{name}\" doesn't have port \"{port}\", but it is connected")]
UnknownPort {
name: String,
port: String,
Expand All @@ -123,6 +123,17 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::UnknownMember), help(""))]
#[error("\"{name}\" doesn't have member \"{member}\"")]
UnknownMember {
name: String,
member: String,
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::DuplicatedIdentifier), help(""))]
#[error("{identifier} is duplicated")]
DuplicatedIdentifier {
Expand Down Expand Up @@ -277,6 +288,15 @@ impl AnalyzerError {
}
}

pub fn unknown_member(name: &str, member: &str, source: &str, token: &VerylToken) -> Self {
AnalyzerError::UnknownMember {
name: name.to_string(),
member: member.to_string(),
input: AnalyzerError::named_source(source, token),
error_location: token.token.into(),
}
}

pub fn duplicated_identifier(identifier: &str, source: &str, token: &VerylToken) -> Self {
AnalyzerError::DuplicatedIdentifier {
identifier: identifier.to_string(),
Expand Down
61 changes: 31 additions & 30 deletions crates/analyzer/src/handlers/check_function_arity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,42 @@ impl<'a> VerylGrammarTrait for CheckFunctionArity<'a> {
return Ok(());
}

let symbol = symbol_table::resolve(x.expression_identifier.as_ref());
let arity = if let Some(symbol) = symbol {
if let SymbolKind::Function(x) = symbol.kind {
Some(x.ports.len())
if let Ok(symbol) = symbol_table::resolve(x.expression_identifier.as_ref()) {
let arity = if let Some(symbol) = symbol.found {
if let SymbolKind::Function(x) = symbol.kind {
Some(x.ports.len())
} else {
None
}
} else {
None
}
} else {
None
};
};

let mut args = 0;
if let Some(ref x) = x.factor_opt {
if let Some(ref x) = x.factor_opt0 {
args += 1;
args += x.function_call_arg.function_call_arg_list.len();
let mut args = 0;
if let Some(ref x) = x.factor_opt {
if let Some(ref x) = x.factor_opt0 {
args += 1;
args += x.function_call_arg.function_call_arg_list.len();
}
}
}

if let Some(arity) = arity {
if arity != args {
let name = format!(
"{}",
SymbolPath::from(x.expression_identifier.as_ref())
.as_slice()
.last()
.unwrap()
);
self.errors.push(AnalyzerError::mismatch_arity(
&name,
arity,
args,
self.text,
&x.expression_identifier.identifier.identifier_token,
));
if let Some(arity) = arity {
if arity != args {
let name = format!(
"{}",
SymbolPath::from(x.expression_identifier.as_ref())
.as_slice()
.last()
.unwrap()
);
self.errors.push(AnalyzerError::mismatch_arity(
&name,
arity,
args,
self.text,
&x.expression_identifier.identifier.identifier_token,
));
}
}
}
}
Expand Down
69 changes: 35 additions & 34 deletions crates/analyzer/src/handlers/check_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,43 +43,44 @@ impl<'a> VerylGrammarTrait for CheckInstance<'a> {
}
}

let symbol = symbol_table::resolve(arg.identifier0.as_ref());
let name = arg.identifier0.identifier_token.text();
if let Some(symbol) = symbol {
match symbol.kind {
SymbolKind::Module(ref x) => {
for port in &x.ports {
if !connected_ports.contains(&port.name) {
let port = resource_table::get_str_value(port.name).unwrap();
self.errors.push(AnalyzerError::missing_port(
&name,
&port,
self.text,
&arg.identifier.identifier_token,
));
if let Ok(symbol) = symbol_table::resolve(arg.identifier0.as_ref()) {
let name = arg.identifier0.identifier_token.text();
if let Some(symbol) = symbol.found {
match symbol.kind {
SymbolKind::Module(ref x) => {
for port in &x.ports {
if !connected_ports.contains(&port.name) {
let port = resource_table::get_str_value(port.name).unwrap();
self.errors.push(AnalyzerError::missing_port(
&name,
&port,
self.text,
&arg.identifier.identifier_token,
));
}
}
}
for port in &connected_ports {
if !x.ports.iter().any(|x| &x.name == port) {
let port = resource_table::get_str_value(*port).unwrap();
self.errors.push(AnalyzerError::unknown_port(
&name,
&port,
self.text,
&arg.identifier.identifier_token,
));
for port in &connected_ports {
if !x.ports.iter().any(|x| &x.name == port) {
let port = resource_table::get_str_value(*port).unwrap();
self.errors.push(AnalyzerError::unknown_port(
&name,
&port,
self.text,
&arg.identifier.identifier_token,
));
}
}
}
}
SymbolKind::Interface(_) => (),
_ => {
self.errors.push(AnalyzerError::mismatch_type(
&name,
"module or interface",
&symbol.kind.to_kind_name(),
self.text,
&arg.identifier.identifier_token,
));
SymbolKind::Interface(_) => (),
_ => {
self.errors.push(AnalyzerError::mismatch_type(
&name,
"module or interface",
&symbol.kind.to_kind_name(),
self.text,
&arg.identifier.identifier_token,
));
}
}
}
}
Expand Down
128 changes: 94 additions & 34 deletions crates/analyzer/src/handlers/create_reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,33 @@ impl<'a> Handler for CreateReference<'a> {
impl<'a> VerylGrammarTrait for CreateReference<'a> {
fn hierarchical_identifier(&mut self, arg: &HierarchicalIdentifier) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
let symbol = symbol_table::resolve(arg);
if let Some(symbol) = symbol {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
} else {
let is_single_identifier = SymbolPath::from(arg).as_slice().len() == 1;
if is_single_identifier {
let name = arg.identifier.identifier_token.text();
self.errors.push(AnalyzerError::undefined_identifier(
match symbol_table::resolve(arg) {
Ok(symbol) => {
if symbol.found.is_some() {
for symbol in symbol.full_path {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
}
} else {
let is_single_identifier = SymbolPath::from(arg).as_slice().len() == 1;
if is_single_identifier {
let name = arg.identifier.identifier_token.text();
self.errors.push(AnalyzerError::undefined_identifier(
&name,
self.text,
&arg.identifier.identifier_token,
));
}
}
}
Err(err) => {
let name = format!("{}", err.last_found.token.text);
let member = format!("{}", err.not_found);
self.errors.push(AnalyzerError::unknown_member(
&name,
&member,
self.text,
&arg.identifier.identifier_token,
));
Expand All @@ -57,18 +72,33 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> {
return Ok(());
}

let symbol = symbol_table::resolve(arg);
if let Some(symbol) = symbol {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
} else {
let is_single_identifier = SymbolPath::from(arg).as_slice().len() == 1;
if is_single_identifier {
let name = arg.identifier.identifier_token.text();
self.errors.push(AnalyzerError::undefined_identifier(
match symbol_table::resolve(arg) {
Ok(symbol) => {
if symbol.found.is_some() {
for symbol in symbol.full_path {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
}
} else {
let is_single_identifier = SymbolPath::from(arg).as_slice().len() == 1;
if is_single_identifier {
let name = arg.identifier.identifier_token.text();
self.errors.push(AnalyzerError::undefined_identifier(
&name,
self.text,
&arg.identifier.identifier_token,
));
}
}
}
Err(err) => {
let name = format!("{}", err.last_found.token.text);
let member = format!("{}", err.not_found);
self.errors.push(AnalyzerError::unknown_member(
&name,
&member,
self.text,
&arg.identifier.identifier_token,
));
Expand All @@ -80,25 +110,55 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> {

fn modport_item(&mut self, arg: &ModportItem) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
let symbol = symbol_table::resolve(arg.identifier.as_ref());
if let Some(symbol) = symbol {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
match symbol_table::resolve(arg.identifier.as_ref()) {
Ok(symbol) => {
if symbol.found.is_some() {
for symbol in symbol.full_path {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier.identifier_token.token,
);
}
}
}
Err(err) => {
let name = format!("{}", err.last_found.token.text);
let member = format!("{}", err.not_found);
self.errors.push(AnalyzerError::unknown_member(
&name,
&member,
self.text,
&arg.identifier.identifier_token,
));
}
}
}
Ok(())
}

fn inst_declaration(&mut self, arg: &InstDeclaration) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
let symbol = symbol_table::resolve(arg.identifier0.as_ref());
if let Some(symbol) = symbol {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier0.identifier_token.token,
);
match symbol_table::resolve(arg.identifier0.as_ref()) {
Ok(symbol) => {
if symbol.found.is_some() {
for symbol in symbol.full_path {
symbol_table::add_reference(
symbol.token.id,
&arg.identifier0.identifier_token.token,
);
}
}
}
Err(err) => {
let name = format!("{}", err.last_found.token.text);
let member = format!("{}", err.not_found);
self.errors.push(AnalyzerError::unknown_member(
&name,
&member,
self.text,
&arg.identifier0.identifier_token,
));
}
}
}
Ok(())
Expand Down
8 changes: 8 additions & 0 deletions crates/analyzer/src/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ impl Namespace {
}
true
}

pub fn matched(&self, x: &Namespace) -> bool {
if self.paths.len() != x.paths.len() {
false
} else {
self.included(x)
}
}
}

impl fmt::Display for Namespace {
Expand Down
6 changes: 3 additions & 3 deletions crates/analyzer/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ impl From<&syntax_tree::Direction> for Direction {

#[derive(Debug, Clone)]
pub struct Type {
modifier: Option<TypeModifier>,
kind: TypeKind,
width: Vec<syntax_tree::Expression>,
pub modifier: Option<TypeModifier>,
pub kind: TypeKind,
pub width: Vec<syntax_tree::Expression>,
}

#[derive(Debug, Clone)]
Expand Down
Loading

0 comments on commit 6b8807b

Please sign in to comment.