-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor analysis module into smaller modules.
- Loading branch information
Showing
11 changed files
with
1,780 additions
and
1,784 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,12 +4,17 @@ | |
// | ||
// Copyright (c) 2019, Olof Kraigher [email protected] | ||
|
||
mod declarative_region; | ||
mod library; | ||
mod analyze; | ||
mod concurrent; | ||
mod declarative; | ||
mod design_unit; | ||
mod lock; | ||
mod region; | ||
mod root; | ||
mod semantic; | ||
mod sequential; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
||
pub use self::library::DesignRoot; | ||
pub use self::root::DesignRoot; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
// You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) 2019, Olof Kraigher [email protected] | ||
|
||
use super::region::Region; | ||
use super::root::DependencyRecorder; | ||
use crate::data::*; | ||
|
||
pub struct AnalyzeContext<'a> { | ||
pub symtab: &'a SymbolTable, | ||
pub work_sym: Symbol, | ||
pub work_library_name: Symbol, | ||
pub std_sym: Symbol, | ||
pub standard_sym: Symbol, | ||
pub root: DependencyRecorder<'a>, | ||
} | ||
|
||
impl<'a> AnalyzeContext<'a> { | ||
pub fn new( | ||
root: DependencyRecorder<'a>, | ||
work_library_name: Symbol, | ||
symtab: &'a SymbolTable, | ||
) -> AnalyzeContext<'a> { | ||
AnalyzeContext { | ||
work_sym: symtab.insert(&Latin1String::new(b"work")), | ||
work_library_name, | ||
std_sym: symtab.insert(&Latin1String::new(b"std")), | ||
standard_sym: symtab.insert(&Latin1String::new(b"standard")), | ||
symtab, | ||
root, | ||
} | ||
} | ||
} | ||
|
||
pub trait Analyze { | ||
fn analyze( | ||
&mut self, | ||
context: &AnalyzeContext, | ||
region: &mut Region<'_>, | ||
diagnostics: &mut dyn DiagnosticHandler, | ||
) -> FatalNullResult; | ||
} | ||
|
||
pub enum AnalysisError { | ||
Fatal(CircularDependencyError), | ||
NotFatal(Diagnostic), | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
#[must_use] | ||
pub struct CircularDependencyError { | ||
reference: Option<SrcPos>, | ||
} | ||
|
||
impl CircularDependencyError { | ||
pub fn new(reference: Option<&SrcPos>) -> CircularDependencyError { | ||
CircularDependencyError { | ||
reference: reference.cloned(), | ||
} | ||
} | ||
|
||
pub fn push_into(self, diagnostics: &mut dyn DiagnosticHandler) { | ||
if let Some(pos) = self.reference { | ||
diagnostics.push(Diagnostic::error( | ||
pos, | ||
format!("Found circular dependency",), | ||
)); | ||
} | ||
} | ||
} | ||
|
||
pub type AnalysisResult<T> = Result<T, AnalysisError>; | ||
pub type FatalResult<T> = Result<T, CircularDependencyError>; | ||
pub type FatalNullResult = FatalResult<()>; | ||
|
||
impl From<CircularDependencyError> for AnalysisError { | ||
fn from(err: CircularDependencyError) -> AnalysisError { | ||
AnalysisError::Fatal(err) | ||
} | ||
} | ||
|
||
impl From<Diagnostic> for AnalysisError { | ||
fn from(diagnostic: Diagnostic) -> AnalysisError { | ||
AnalysisError::NotFatal(diagnostic) | ||
} | ||
} | ||
|
||
impl AnalysisError { | ||
// Add Non-fatal error to diagnostics or return fatal error | ||
pub fn add_to(self, diagnostics: &mut dyn DiagnosticHandler) -> FatalNullResult { | ||
match self { | ||
AnalysisError::Fatal(err) => Err(err), | ||
AnalysisError::NotFatal(diag) => { | ||
diagnostics.push(diag); | ||
Ok(()) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
// You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) 2019, Olof Kraigher [email protected] | ||
|
||
use super::*; | ||
use crate::ast::*; | ||
use crate::data::*; | ||
use analyze::*; | ||
use region::*; | ||
|
||
impl<'a> AnalyzeContext<'a> { | ||
pub fn analyze_concurrent_part( | ||
&self, | ||
parent: &mut Region<'_>, | ||
statements: &mut [LabeledConcurrentStatement], | ||
diagnostics: &mut dyn DiagnosticHandler, | ||
) -> FatalNullResult { | ||
for statement in statements.iter_mut() { | ||
self.analyze_concurrent_statement(parent, statement, diagnostics)?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn analyze_concurrent_statement( | ||
&self, | ||
parent: &mut Region<'_>, | ||
statement: &mut LabeledConcurrentStatement, | ||
diagnostics: &mut dyn DiagnosticHandler, | ||
) -> FatalNullResult { | ||
if let Some(ref label) = statement.label { | ||
parent.add(label.clone(), AnyDeclaration::Constant, diagnostics); | ||
} | ||
|
||
match statement.statement { | ||
ConcurrentStatement::Block(ref mut block) => { | ||
let mut region = parent.nested(); | ||
self.analyze_declarative_part(&mut region, &mut block.decl, diagnostics)?; | ||
self.analyze_concurrent_part(&mut region, &mut block.statements, diagnostics)?; | ||
} | ||
ConcurrentStatement::Process(ref mut process) => { | ||
let ProcessStatement { | ||
postponed: _, | ||
sensitivity_list, | ||
decl, | ||
statements, | ||
} = process; | ||
if let Some(sensitivity_list) = sensitivity_list { | ||
match sensitivity_list { | ||
SensitivityList::Names(names) => { | ||
for name in names.iter_mut() { | ||
self.resolve_name(parent, &name.pos, &mut name.item, diagnostics)?; | ||
} | ||
} | ||
SensitivityList::All => {} | ||
} | ||
} | ||
let mut region = parent.nested(); | ||
self.analyze_declarative_part(&mut region, decl, diagnostics)?; | ||
self.analyze_sequential_part(&mut region, statements, diagnostics)?; | ||
} | ||
ConcurrentStatement::ForGenerate(ref mut gen) => { | ||
let ForGenerateStatement { | ||
index_name, | ||
discrete_range, | ||
body, | ||
} = gen; | ||
self.analyze_discrete_range(parent, discrete_range, diagnostics)?; | ||
let mut region = parent.nested(); | ||
region.add(index_name.clone(), AnyDeclaration::Constant, diagnostics); | ||
self.analyze_generate_body(&mut region, body, diagnostics)?; | ||
} | ||
ConcurrentStatement::IfGenerate(ref mut gen) => { | ||
let Conditionals { | ||
conditionals, | ||
else_item, | ||
} = gen; | ||
for conditional in conditionals.iter_mut() { | ||
let Conditional { condition, item } = conditional; | ||
self.analyze_expression(parent, condition, diagnostics)?; | ||
let mut region = parent.nested(); | ||
self.analyze_generate_body(&mut region, item, diagnostics)?; | ||
} | ||
if let Some(ref mut else_item) = else_item { | ||
let mut region = parent.nested(); | ||
self.analyze_generate_body(&mut region, else_item, diagnostics)?; | ||
} | ||
} | ||
ConcurrentStatement::CaseGenerate(ref mut gen) => { | ||
for alternative in gen.alternatives.iter_mut() { | ||
let mut region = parent.nested(); | ||
self.analyze_generate_body(&mut region, &mut alternative.item, diagnostics)?; | ||
} | ||
} | ||
ConcurrentStatement::Instance(ref mut instance) => { | ||
self.analyze_instance(parent, instance, diagnostics)?; | ||
} | ||
ConcurrentStatement::Assignment(ref mut assign) => { | ||
// @TODO more delaymechanism | ||
let ConcurrentSignalAssignment { target, rhs, .. } = assign; | ||
self.analyze_waveform_assignment(parent, target, rhs, diagnostics)?; | ||
} | ||
ConcurrentStatement::ProcedureCall(ref mut pcall) => { | ||
let ConcurrentProcedureCall { | ||
call, | ||
postponed: _postponed, | ||
} = pcall; | ||
self.analyze_function_call(parent, call, diagnostics)?; | ||
} | ||
ConcurrentStatement::Assert(ref mut assert) => { | ||
let ConcurrentAssertStatement { | ||
postponed: _postponed, | ||
statement: | ||
AssertStatement { | ||
condition, | ||
report, | ||
severity, | ||
}, | ||
} = assert; | ||
self.analyze_expression(parent, condition, diagnostics)?; | ||
if let Some(expr) = report { | ||
self.analyze_expression(parent, expr, diagnostics)?; | ||
} | ||
if let Some(expr) = severity { | ||
self.analyze_expression(parent, expr, diagnostics)?; | ||
} | ||
} | ||
}; | ||
Ok(()) | ||
} | ||
|
||
fn analyze_generate_body( | ||
&self, | ||
region: &mut Region<'_>, | ||
body: &mut GenerateBody, | ||
diagnostics: &mut dyn DiagnosticHandler, | ||
) -> FatalNullResult { | ||
let GenerateBody { | ||
alternative_label, | ||
decl, | ||
statements, | ||
} = body; | ||
if let Some(label) = alternative_label { | ||
region.add(label.clone(), AnyDeclaration::Constant, diagnostics); | ||
} | ||
if let Some(ref mut decl) = decl { | ||
self.analyze_declarative_part(region, decl, diagnostics)?; | ||
} | ||
self.analyze_concurrent_part(region, statements, diagnostics)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
fn analyze_instance( | ||
&self, | ||
parent: &Region<'_>, | ||
instance: &mut InstantiationStatement, | ||
diagnostics: &mut dyn DiagnosticHandler, | ||
) -> FatalNullResult { | ||
match instance.unit { | ||
// @TODO architecture | ||
InstantiatedUnit::Entity(ref mut entity_name, ..) => { | ||
if let Err(err) = self.resolve_selected_name(parent, entity_name) { | ||
err.add_to(diagnostics)?; | ||
} | ||
} | ||
InstantiatedUnit::Component(ref mut component_name) => { | ||
if let Err(err) = self.resolve_selected_name(parent, component_name) { | ||
err.add_to(diagnostics)?; | ||
} | ||
} | ||
InstantiatedUnit::Configuration(ref mut config_name) => { | ||
if let Err(err) = self.resolve_selected_name(parent, config_name) { | ||
err.add_to(diagnostics)?; | ||
} | ||
} | ||
}; | ||
|
||
self.analyze_assoc_elems(parent, &mut instance.generic_map, diagnostics)?; | ||
self.analyze_assoc_elems(parent, &mut instance.port_map, diagnostics)?; | ||
|
||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.