Skip to content

Commit 2ac48f3

Browse files
committed
refactor: Converted user_defined_type_rules to the visitor pattern
1 parent ba010db commit 2ac48f3

6 files changed

Lines changed: 113 additions & 89 deletions

File tree

rusty_linter/src/core/string_length.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,25 @@ use rusty_common::Positioned;
33
use rusty_parser::{Expression, TypeQualifier};
44
use rusty_variant::{Variant, MAX_INTEGER};
55

6-
pub trait ValidateStringLength<E> {
7-
fn validate_string_length(&self, const_lookup: &impl ConstLookup) -> Result<u16, E>;
6+
pub trait ValidateStringLength<E, C: ConstLookup + ?Sized> {
7+
fn validate_string_length(&self, const_lookup: &C) -> Result<u16, E>;
88
}
99

10-
impl<T, E> ValidateStringLength<Positioned<E>> for Positioned<T>
10+
impl<T, E, C> ValidateStringLength<Positioned<E>, C> for Positioned<T>
1111
where
12-
T: ValidateStringLength<E>,
12+
T: ValidateStringLength<E, C>,
13+
C: ConstLookup + ?Sized,
1314
{
14-
fn validate_string_length(
15-
&self,
16-
const_lookup: &impl ConstLookup,
17-
) -> Result<u16, Positioned<E>> {
15+
fn validate_string_length(&self, const_lookup: &C) -> Result<u16, Positioned<E>> {
1816
let Positioned { element, pos } = self;
1917
element
2018
.validate_string_length(const_lookup)
2119
.map_err(|e| Positioned::new(e, *pos))
2220
}
2321
}
2422

25-
impl ValidateStringLength<LintError> for Expression {
26-
fn validate_string_length(&self, const_lookup: &impl ConstLookup) -> Result<u16, LintError> {
23+
impl<C: ConstLookup + ?Sized> ValidateStringLength<LintError, C> for Expression {
24+
fn validate_string_length(&self, const_lookup: &C) -> Result<u16, LintError> {
2725
match self {
2826
Self::IntegerLiteral(i) => {
2927
if (1..=MAX_INTEGER).contains(i) {

rusty_linter/src/core/visitor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ where
7575
}
7676
}
7777
}
78+
79+
pub trait DelegateVisitor<T> {
80+
fn delegate(&mut self) -> impl Visitor<T>;
81+
}

rusty_linter/src/pre_linter/main.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,16 @@ impl Visitor<Statement> for MainContext {
123123

124124
impl Visitor<UserDefinedType> for MainContext {
125125
fn visit(&mut self, user_defined_type: &UserDefinedType) -> VisitResult {
126-
super::user_defined_type_rules::user_defined_type(
126+
self.delegate().visit(user_defined_type)
127+
}
128+
}
129+
130+
impl DelegateVisitor<UserDefinedType> for MainContext {
131+
fn delegate(&mut self) -> impl Visitor<UserDefinedType> {
132+
super::user_defined_type_visitor::UserDefinedTypeVisitor::new(
127133
&mut self.user_defined_types,
128-
&self.global_constants,
129-
user_defined_type,
130134
self.declaration_pos,
135+
&self.global_constants,
131136
)
132137
}
133138
}

rusty_linter/src/pre_linter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod constant_map;
22
mod main;
33
mod pre_linter_result;
44
mod sub_program_context;
5-
mod user_defined_type_rules;
5+
mod user_defined_type_visitor;
66

77
pub use self::constant_map::*;
88
pub use self::main::*;

rusty_linter/src/pre_linter/user_defined_type_rules.rs

Lines changed: 0 additions & 75 deletions
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use crate::core::LintError;
2+
use crate::core::{ConstLookup, ValidateStringLength, VisitResult, Visitor};
3+
use rusty_common::{AtPos, Position, Positioned};
4+
use rusty_parser::{
5+
BareName, Element, ElementPos, ElementType, Expression, UserDefinedType, UserDefinedTypes,
6+
};
7+
use std::collections::HashMap;
8+
9+
pub struct UserDefinedTypeVisitor<'a> {
10+
user_defined_types: &'a mut UserDefinedTypes,
11+
pos: Position,
12+
const_lookup: &'a dyn ConstLookup,
13+
}
14+
15+
impl<'a> UserDefinedTypeVisitor<'a> {
16+
pub fn new(
17+
user_defined_types: &'a mut UserDefinedTypes,
18+
pos: Position,
19+
const_lookup: &'a impl ConstLookup,
20+
) -> Self {
21+
Self {
22+
user_defined_types,
23+
pos,
24+
const_lookup,
25+
}
26+
}
27+
}
28+
29+
impl<'a> Visitor<UserDefinedType> for UserDefinedTypeVisitor<'a> {
30+
fn visit(&mut self, user_defined_type: &UserDefinedType) -> VisitResult {
31+
let type_name: &BareName = user_defined_type.bare_name();
32+
if self.user_defined_types.contains_key(type_name) {
33+
// duplicate type definition
34+
Err(LintError::DuplicateDefinition.at_pos(self.pos))
35+
} else {
36+
let mut resolved_elements: HashMap<BareName, ElementType> = HashMap::new();
37+
for Positioned {
38+
element:
39+
Element {
40+
name: element_name,
41+
element_type,
42+
..
43+
},
44+
pos,
45+
} in user_defined_type.elements()
46+
{
47+
if resolved_elements.contains_key(element_name) {
48+
// duplicate element name within type
49+
return Err(LintError::DuplicateDefinition.at(pos));
50+
}
51+
let resolved_element_type = match element_type {
52+
ElementType::Integer => ElementType::Integer,
53+
ElementType::Long => ElementType::Long,
54+
ElementType::Single => ElementType::Single,
55+
ElementType::Double => ElementType::Double,
56+
ElementType::FixedLengthString(str_len_expression_pos, _) => {
57+
let l: u16 =
58+
str_len_expression_pos.validate_string_length(self.const_lookup)?;
59+
ElementType::FixedLengthString(
60+
Expression::IntegerLiteral(l as i32).at(str_len_expression_pos),
61+
l,
62+
)
63+
}
64+
ElementType::UserDefined(Positioned {
65+
element: referred_name,
66+
pos,
67+
}) => {
68+
if !self.user_defined_types.contains_key(referred_name) {
69+
return Err(LintError::TypeNotDefined.at(pos));
70+
}
71+
ElementType::UserDefined(referred_name.clone().at(pos))
72+
}
73+
};
74+
resolved_elements.insert(element_name.clone(), resolved_element_type);
75+
}
76+
let mut elements: Vec<ElementPos> = vec![];
77+
for Positioned {
78+
element: Element { name, .. },
79+
pos,
80+
} in user_defined_type.elements()
81+
{
82+
let converted_element_type = resolved_elements.remove(name).unwrap();
83+
elements.push(Element::new(name.clone(), converted_element_type, vec![]).at(pos));
84+
}
85+
self.user_defined_types.insert(
86+
type_name.clone(),
87+
UserDefinedType::new(type_name.clone(), vec![], elements),
88+
);
89+
Ok(())
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)