Skip to content

Commit d68066d

Browse files
committed
Refactor analysis module into smaller modules.
1 parent 02a26ec commit d68066d

11 files changed

Lines changed: 1780 additions & 1784 deletions

File tree

vhdl_parser/src/analysis.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
//
55
// Copyright (c) 2019, Olof Kraigher olof.kraigher@gmail.com
66

7-
mod declarative_region;
8-
mod library;
7+
mod analyze;
8+
mod concurrent;
9+
mod declarative;
10+
mod design_unit;
911
mod lock;
12+
mod region;
13+
mod root;
1014
mod semantic;
15+
mod sequential;
1116

1217
#[cfg(test)]
1318
mod tests;
1419

15-
pub use self::library::DesignRoot;
20+
pub use self::root::DesignRoot;
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
// You can obtain one at http://mozilla.org/MPL/2.0/.
4+
//
5+
// Copyright (c) 2019, Olof Kraigher olof.kraigher@gmail.com
6+
7+
use super::region::Region;
8+
use super::root::DependencyRecorder;
9+
use crate::data::*;
10+
11+
pub struct AnalyzeContext<'a> {
12+
pub symtab: &'a SymbolTable,
13+
pub work_sym: Symbol,
14+
pub work_library_name: Symbol,
15+
pub std_sym: Symbol,
16+
pub standard_sym: Symbol,
17+
pub root: DependencyRecorder<'a>,
18+
}
19+
20+
impl<'a> AnalyzeContext<'a> {
21+
pub fn new(
22+
root: DependencyRecorder<'a>,
23+
work_library_name: Symbol,
24+
symtab: &'a SymbolTable,
25+
) -> AnalyzeContext<'a> {
26+
AnalyzeContext {
27+
work_sym: symtab.insert(&Latin1String::new(b"work")),
28+
work_library_name,
29+
std_sym: symtab.insert(&Latin1String::new(b"std")),
30+
standard_sym: symtab.insert(&Latin1String::new(b"standard")),
31+
symtab,
32+
root,
33+
}
34+
}
35+
}
36+
37+
pub trait Analyze {
38+
fn analyze(
39+
&mut self,
40+
context: &AnalyzeContext,
41+
region: &mut Region<'_>,
42+
diagnostics: &mut dyn DiagnosticHandler,
43+
) -> FatalNullResult;
44+
}
45+
46+
pub enum AnalysisError {
47+
Fatal(CircularDependencyError),
48+
NotFatal(Diagnostic),
49+
}
50+
51+
#[derive(Clone, Debug)]
52+
#[must_use]
53+
pub struct CircularDependencyError {
54+
reference: Option<SrcPos>,
55+
}
56+
57+
impl CircularDependencyError {
58+
pub fn new(reference: Option<&SrcPos>) -> CircularDependencyError {
59+
CircularDependencyError {
60+
reference: reference.cloned(),
61+
}
62+
}
63+
64+
pub fn push_into(self, diagnostics: &mut dyn DiagnosticHandler) {
65+
if let Some(pos) = self.reference {
66+
diagnostics.push(Diagnostic::error(
67+
pos,
68+
format!("Found circular dependency",),
69+
));
70+
}
71+
}
72+
}
73+
74+
pub type AnalysisResult<T> = Result<T, AnalysisError>;
75+
pub type FatalResult<T> = Result<T, CircularDependencyError>;
76+
pub type FatalNullResult = FatalResult<()>;
77+
78+
impl From<CircularDependencyError> for AnalysisError {
79+
fn from(err: CircularDependencyError) -> AnalysisError {
80+
AnalysisError::Fatal(err)
81+
}
82+
}
83+
84+
impl From<Diagnostic> for AnalysisError {
85+
fn from(diagnostic: Diagnostic) -> AnalysisError {
86+
AnalysisError::NotFatal(diagnostic)
87+
}
88+
}
89+
90+
impl AnalysisError {
91+
// Add Non-fatal error to diagnostics or return fatal error
92+
pub fn add_to(self, diagnostics: &mut dyn DiagnosticHandler) -> FatalNullResult {
93+
match self {
94+
AnalysisError::Fatal(err) => Err(err),
95+
AnalysisError::NotFatal(diag) => {
96+
diagnostics.push(diag);
97+
Ok(())
98+
}
99+
}
100+
}
101+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
// You can obtain one at http://mozilla.org/MPL/2.0/.
4+
//
5+
// Copyright (c) 2019, Olof Kraigher olof.kraigher@gmail.com
6+
7+
use super::*;
8+
use crate::ast::*;
9+
use crate::data::*;
10+
use analyze::*;
11+
use region::*;
12+
13+
impl<'a> AnalyzeContext<'a> {
14+
pub fn analyze_concurrent_part(
15+
&self,
16+
parent: &mut Region<'_>,
17+
statements: &mut [LabeledConcurrentStatement],
18+
diagnostics: &mut dyn DiagnosticHandler,
19+
) -> FatalNullResult {
20+
for statement in statements.iter_mut() {
21+
self.analyze_concurrent_statement(parent, statement, diagnostics)?;
22+
}
23+
24+
Ok(())
25+
}
26+
27+
fn analyze_concurrent_statement(
28+
&self,
29+
parent: &mut Region<'_>,
30+
statement: &mut LabeledConcurrentStatement,
31+
diagnostics: &mut dyn DiagnosticHandler,
32+
) -> FatalNullResult {
33+
if let Some(ref label) = statement.label {
34+
parent.add(label.clone(), AnyDeclaration::Constant, diagnostics);
35+
}
36+
37+
match statement.statement {
38+
ConcurrentStatement::Block(ref mut block) => {
39+
let mut region = parent.nested();
40+
self.analyze_declarative_part(&mut region, &mut block.decl, diagnostics)?;
41+
self.analyze_concurrent_part(&mut region, &mut block.statements, diagnostics)?;
42+
}
43+
ConcurrentStatement::Process(ref mut process) => {
44+
let ProcessStatement {
45+
postponed: _,
46+
sensitivity_list,
47+
decl,
48+
statements,
49+
} = process;
50+
if let Some(sensitivity_list) = sensitivity_list {
51+
match sensitivity_list {
52+
SensitivityList::Names(names) => {
53+
for name in names.iter_mut() {
54+
self.resolve_name(parent, &name.pos, &mut name.item, diagnostics)?;
55+
}
56+
}
57+
SensitivityList::All => {}
58+
}
59+
}
60+
let mut region = parent.nested();
61+
self.analyze_declarative_part(&mut region, decl, diagnostics)?;
62+
self.analyze_sequential_part(&mut region, statements, diagnostics)?;
63+
}
64+
ConcurrentStatement::ForGenerate(ref mut gen) => {
65+
let ForGenerateStatement {
66+
index_name,
67+
discrete_range,
68+
body,
69+
} = gen;
70+
self.analyze_discrete_range(parent, discrete_range, diagnostics)?;
71+
let mut region = parent.nested();
72+
region.add(index_name.clone(), AnyDeclaration::Constant, diagnostics);
73+
self.analyze_generate_body(&mut region, body, diagnostics)?;
74+
}
75+
ConcurrentStatement::IfGenerate(ref mut gen) => {
76+
let Conditionals {
77+
conditionals,
78+
else_item,
79+
} = gen;
80+
for conditional in conditionals.iter_mut() {
81+
let Conditional { condition, item } = conditional;
82+
self.analyze_expression(parent, condition, diagnostics)?;
83+
let mut region = parent.nested();
84+
self.analyze_generate_body(&mut region, item, diagnostics)?;
85+
}
86+
if let Some(ref mut else_item) = else_item {
87+
let mut region = parent.nested();
88+
self.analyze_generate_body(&mut region, else_item, diagnostics)?;
89+
}
90+
}
91+
ConcurrentStatement::CaseGenerate(ref mut gen) => {
92+
for alternative in gen.alternatives.iter_mut() {
93+
let mut region = parent.nested();
94+
self.analyze_generate_body(&mut region, &mut alternative.item, diagnostics)?;
95+
}
96+
}
97+
ConcurrentStatement::Instance(ref mut instance) => {
98+
self.analyze_instance(parent, instance, diagnostics)?;
99+
}
100+
ConcurrentStatement::Assignment(ref mut assign) => {
101+
// @TODO more delaymechanism
102+
let ConcurrentSignalAssignment { target, rhs, .. } = assign;
103+
self.analyze_waveform_assignment(parent, target, rhs, diagnostics)?;
104+
}
105+
ConcurrentStatement::ProcedureCall(ref mut pcall) => {
106+
let ConcurrentProcedureCall {
107+
call,
108+
postponed: _postponed,
109+
} = pcall;
110+
self.analyze_function_call(parent, call, diagnostics)?;
111+
}
112+
ConcurrentStatement::Assert(ref mut assert) => {
113+
let ConcurrentAssertStatement {
114+
postponed: _postponed,
115+
statement:
116+
AssertStatement {
117+
condition,
118+
report,
119+
severity,
120+
},
121+
} = assert;
122+
self.analyze_expression(parent, condition, diagnostics)?;
123+
if let Some(expr) = report {
124+
self.analyze_expression(parent, expr, diagnostics)?;
125+
}
126+
if let Some(expr) = severity {
127+
self.analyze_expression(parent, expr, diagnostics)?;
128+
}
129+
}
130+
};
131+
Ok(())
132+
}
133+
134+
fn analyze_generate_body(
135+
&self,
136+
region: &mut Region<'_>,
137+
body: &mut GenerateBody,
138+
diagnostics: &mut dyn DiagnosticHandler,
139+
) -> FatalNullResult {
140+
let GenerateBody {
141+
alternative_label,
142+
decl,
143+
statements,
144+
} = body;
145+
if let Some(label) = alternative_label {
146+
region.add(label.clone(), AnyDeclaration::Constant, diagnostics);
147+
}
148+
if let Some(ref mut decl) = decl {
149+
self.analyze_declarative_part(region, decl, diagnostics)?;
150+
}
151+
self.analyze_concurrent_part(region, statements, diagnostics)?;
152+
153+
Ok(())
154+
}
155+
156+
fn analyze_instance(
157+
&self,
158+
parent: &Region<'_>,
159+
instance: &mut InstantiationStatement,
160+
diagnostics: &mut dyn DiagnosticHandler,
161+
) -> FatalNullResult {
162+
match instance.unit {
163+
// @TODO architecture
164+
InstantiatedUnit::Entity(ref mut entity_name, ..) => {
165+
if let Err(err) = self.resolve_selected_name(parent, entity_name) {
166+
err.add_to(diagnostics)?;
167+
}
168+
}
169+
InstantiatedUnit::Component(ref mut component_name) => {
170+
if let Err(err) = self.resolve_selected_name(parent, component_name) {
171+
err.add_to(diagnostics)?;
172+
}
173+
}
174+
InstantiatedUnit::Configuration(ref mut config_name) => {
175+
if let Err(err) = self.resolve_selected_name(parent, config_name) {
176+
err.add_to(diagnostics)?;
177+
}
178+
}
179+
};
180+
181+
self.analyze_assoc_elems(parent, &mut instance.generic_map, diagnostics)?;
182+
self.analyze_assoc_elems(parent, &mut instance.port_map, diagnostics)?;
183+
184+
Ok(())
185+
}
186+
}

0 commit comments

Comments
 (0)