Skip to content

Commit

Permalink
Merge pull request #1011 from taichi-ishitani/fix_type_check
Browse files Browse the repository at this point in the history
Execute `type check` afeter resolving generics
  • Loading branch information
dalance authored Oct 11, 2024
2 parents d2d04bc + 44b0540 commit 929f042
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 70 deletions.
16 changes: 8 additions & 8 deletions crates/analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use self::{check_assignment::CheckAssignment, create_type_dag::CreateTypeDag};

pub struct Pass1Handlers<'a> {
check_attribute: CheckAttribute<'a>,
check_direction: CheckDirection<'a>,
check_embed_include: CheckEmbedInclude<'a>,
check_identifier: CheckIdentifier<'a>,
check_number: CheckNumber<'a>,
Expand All @@ -57,6 +58,7 @@ impl<'a> Pass1Handlers<'a> {
pub fn new(text: &'a str, build_opt: &'a Build, lint_opt: &'a Lint) -> Self {
Self {
check_attribute: CheckAttribute::new(text),
check_direction: CheckDirection::new(text),
check_embed_include: CheckEmbedInclude::new(text),
check_identifier: CheckIdentifier::new(text, lint_opt),
check_number: CheckNumber::new(text),
Expand All @@ -69,6 +71,7 @@ impl<'a> Pass1Handlers<'a> {
pub fn get_handlers(&mut self) -> Vec<&mut dyn Handler> {
vec![
&mut self.check_attribute as &mut dyn Handler,
&mut self.check_direction as &mut dyn Handler,
&mut self.check_embed_include as &mut dyn Handler,
&mut self.check_identifier as &mut dyn Handler,
&mut self.check_number as &mut dyn Handler,
Expand All @@ -81,6 +84,7 @@ impl<'a> Pass1Handlers<'a> {
pub fn get_errors(&mut self) -> Vec<AnalyzerError> {
let mut ret = Vec::new();
ret.append(&mut self.check_attribute.errors);
ret.append(&mut self.check_direction.errors);
ret.append(&mut self.check_embed_include.errors);
ret.append(&mut self.check_identifier.errors);
ret.append(&mut self.check_number.errors);
Expand All @@ -93,10 +97,8 @@ impl<'a> Pass1Handlers<'a> {

pub struct Pass2Handlers<'a> {
check_enum: CheckEnum<'a>,
check_direction: CheckDirection<'a>,
check_modport: CheckModport<'a>,
check_function: CheckFunction<'a>,
check_type: CheckType<'a>,
check_msb_lsb: CheckMsbLsb<'a>,
check_assignment: CheckAssignment<'a>,
check_clock_reset: CheckClockReset<'a>,
Expand All @@ -105,16 +107,15 @@ pub struct Pass2Handlers<'a> {
check_expression: CheckExpression<'a>,
check_clock_domain: CheckClockDomain<'a>,
check_proto: CheckProto<'a>,
check_type: CheckType<'a>,
}

impl<'a> Pass2Handlers<'a> {
pub fn new(text: &'a str, _build_opt: &'a Build, _lint_opt: &'a Lint) -> Self {
Self {
check_enum: CheckEnum::new(text),
check_direction: CheckDirection::new(text),
check_modport: CheckModport::new(text),
check_function: CheckFunction::new(text),
check_type: CheckType::new(text),
check_msb_lsb: CheckMsbLsb::new(text),
check_assignment: CheckAssignment::new(text),
check_clock_reset: CheckClockReset::new(text),
Expand All @@ -123,16 +124,15 @@ impl<'a> Pass2Handlers<'a> {
check_expression: CheckExpression::new(text),
check_clock_domain: CheckClockDomain::new(text),
check_proto: CheckProto::new(text),
check_type: CheckType::new(text),
}
}

pub fn get_handlers(&mut self) -> Vec<&mut dyn Handler> {
vec![
&mut self.check_enum as &mut dyn Handler,
&mut self.check_direction as &mut dyn Handler,
&mut self.check_modport as &mut dyn Handler,
&mut self.check_function as &mut dyn Handler,
&mut self.check_type as &mut dyn Handler,
&mut self.check_msb_lsb as &mut dyn Handler,
&mut self.check_assignment as &mut dyn Handler,
&mut self.check_clock_reset as &mut dyn Handler,
Expand All @@ -141,16 +141,15 @@ impl<'a> Pass2Handlers<'a> {
&mut self.check_expression as &mut dyn Handler,
&mut self.check_clock_domain as &mut dyn Handler,
&mut self.check_proto as &mut dyn Handler,
&mut self.check_type as &mut dyn Handler,
]
}

pub fn get_errors(&mut self) -> Vec<AnalyzerError> {
let mut ret = Vec::new();
ret.append(&mut self.check_enum.errors);
ret.append(&mut self.check_direction.errors);
ret.append(&mut self.check_modport.errors);
ret.append(&mut self.check_function.errors);
ret.append(&mut self.check_type.errors);
ret.append(&mut self.check_msb_lsb.errors);
ret.append(&mut self.check_assignment.errors);
ret.append(&mut self.check_clock_reset.errors);
Expand All @@ -159,6 +158,7 @@ impl<'a> Pass2Handlers<'a> {
ret.append(&mut self.check_expression.errors);
ret.append(&mut self.check_clock_domain.errors);
ret.append(&mut self.check_proto.errors);
ret.append(&mut self.check_type.errors);
ret
}
}
50 changes: 4 additions & 46 deletions crates/analyzer/src/handlers/check_direction.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::analyzer_error::AnalyzerError;
use crate::symbol::SymbolKind;
use crate::symbol_table;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
use veryl_parser::ParolError;
Expand All @@ -13,7 +11,6 @@ pub struct CheckDirection<'a> {
in_function: bool,
in_module: bool,
in_modport: bool,
is_interface_port: bool,
}

impl<'a> CheckDirection<'a> {
Expand All @@ -31,28 +28,15 @@ impl<'a> Handler for CheckDirection<'a> {
}
}

fn is_interface_type(arg: &ArrayType) -> bool {
if let ScalarTypeGroup::VariableTypeScalarTypeOpt(x) = &*arg.scalar_type.scalar_type_group {
if let VariableType::ScopedIdentifier(x) = x.variable_type.as_ref() {
let symbol = symbol_table::resolve(x.scoped_identifier.as_ref()).unwrap();
return matches!(symbol.found.kind, SymbolKind::Interface(_));
}
}

false
}

impl<'a> VerylGrammarTrait for CheckDirection<'a> {
fn port_declaration_item(&mut self, arg: &PortDeclarationItem) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if let PortDeclarationItemGroup::PortTypeConcrete(x) =
arg.port_declaration_item_group.as_ref()
{
let x = x.port_type_concrete.as_ref();
let r#type = &x.array_type;

self.is_interface_port = is_interface_type(r#type);
if let Direction::Inout(_) = x.direction.as_ref() {
let r#type = &x.array_type;
let is_tri = r#type
.scalar_type
.scalar_type_list
Expand All @@ -74,35 +58,8 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> {
fn direction(&mut self, arg: &Direction) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
match arg {
Direction::Input(x) => {
if self.is_interface_port {
self.errors.push(AnalyzerError::invalid_direction(
"input",
self.text,
&x.input.input_token.token.into(),
));
}
}
Direction::Output(x) => {
if self.is_interface_port {
self.errors.push(AnalyzerError::invalid_direction(
"output",
self.text,
&x.output.output_token.token.into(),
));
}
}
Direction::Inout(x) => {
if self.is_interface_port {
self.errors.push(AnalyzerError::invalid_direction(
"inout",
self.text,
&x.inout.inout_token.token.into(),
));
}
}
Direction::Ref(x) => {
if !self.in_function || self.is_interface_port {
if !self.in_function {
self.errors.push(AnalyzerError::invalid_direction(
"ref",
self.text,
Expand All @@ -120,14 +77,15 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> {
}
}
Direction::Import(x) => {
if !self.in_modport || self.is_interface_port {
if !self.in_modport {
self.errors.push(AnalyzerError::invalid_direction(
"import",
self.text,
&x.import.import_token.token.into(),
));
}
}
_ => (),
}
}
Ok(())
Expand Down
94 changes: 78 additions & 16 deletions crates/analyzer/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,22 +595,6 @@ fn invalid_direction() {

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::InvalidDirection { .. }));

let code = r#"
interface InterfaceG {
var value: logic;
modport mp {
value: input,
}
}
module ModuleG (
port_a: input InterfaceG
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::InvalidDirection { .. }));
}

#[test]
Expand Down Expand Up @@ -1105,6 +1089,84 @@ fn mismatch_type() {

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceN1 {
var a: logic;
modport mp {
a: input,
}
}
module ModuleN1 (
port_n1: input InterfaceN1::mp,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceN2::<W: const> {
var a: logic<W>;
modport mp {
a: input,
}
}
module ModuleN2 (
port_n2: input InterfaceN2::<2>::mp,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceN3 {
var a: logic;
}
module ModuleN3 (
port_n3: input InterfaceN3,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceN4::<W: const> {
var a: logic<W>;
}
module ModuleN4 (
port_n4: input InterfaceN4::<2>,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceO1 {
var a: logic;
}
module ModuleO1 (
port_o1: modport InterfaceO1,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));

let code = r#"
interface InterfaceO2::<W: const> {
var a: logic<W>;
}
module ModuleO2 (
port_o2: modport InterfaceO2::<2>,
){}
"#;

let errors = analyze(code);
assert!(matches!(errors[0], AnalyzerError::MismatchType { .. }));
}

#[test]
Expand Down

0 comments on commit 929f042

Please sign in to comment.