Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor type dag #1144

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/analyzer/src/analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
pub mod create_type_dag;

use crate::analyzer::create_type_dag::*;
use crate::analyzer::resource_table::PathId;
use crate::analyzer_error::AnalyzerError;
use crate::attribute_table;
Expand Down Expand Up @@ -74,6 +77,12 @@ impl<'a> AnalyzerPass3<'a> {
}
}

pub fn create_type_dag(&self) -> Vec<AnalyzerError> {
let mut dag_creator = CreateTypeDag::new(self.text);
dag_creator.create_type_dag(&self.symbols);
dag_creator.errors
}

pub fn check_variables(&self) -> Vec<AnalyzerError> {
let mut ret = Vec::new();

Expand Down Expand Up @@ -289,6 +298,7 @@ impl Analyzer {

namespace_table::set_default(&[project_name.into()]);
let pass3 = AnalyzerPass3::new(path.as_ref(), text);
ret.append(&mut pass3.create_type_dag());
ret.append(&mut pass3.check_variables());
ret.append(&mut pass3.check_assignment());
ret.append(&mut pass3.check_unassigned());
Expand Down
132 changes: 132 additions & 0 deletions crates/analyzer/src/analyzer/create_type_dag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::analyzer_error::AnalyzerError;
use crate::symbol::{is_dependency_symbol, Symbol, SymbolId, SymbolKind};
use crate::symbol_table;
use crate::type_dag::{self, Context, DagError};
use veryl_parser::resource_table;

#[derive(Default)]
pub struct CreateTypeDag<'a> {
pub errors: Vec<AnalyzerError>,
text: &'a str,
context: Vec<Context>,
parent: Vec<(u32, SymbolId)>,
}

impl<'a> CreateTypeDag<'a> {
pub fn new(text: &'a str) -> Self {
Self {
text,
..Default::default()
}
}

pub fn create_type_dag(&mut self, symbols: &[Symbol]) {
for symbol in symbols.iter().filter(|x| {
matches!(
x.kind,
SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_)
)
}) {
self.add_type_dag(symbol);
}
}

fn add_type_dag(&mut self, symbol: &Symbol) {
// Avoid stack overflow
if self.parent.iter().filter(|(_, x)| *x == symbol.id).count() >= 2 {
return;
}

let name = symbol.token.to_string();
if let Some(x) = self.insert_node(symbol.id, &name) {
self.add_parent_type_dag(symbol);
if let Some((parent, _)) = self.parent.last().cloned() {
self.insert_owned(parent, x);
self.insert_edge(x, parent, *self.context.last().unwrap());
}

let context = match symbol.kind {
SymbolKind::Module(_) => Context::Module,
SymbolKind::Interface(_) => Context::Interface,
SymbolKind::Modport(_) => Context::Modport,
SymbolKind::Package(_) => Context::Package,
SymbolKind::Enum(_) => Context::Enum,
SymbolKind::Parameter(_) => Context::Const,
SymbolKind::TypeDef(_) => Context::TypeDef,
SymbolKind::Struct(_) => Context::Struct,
SymbolKind::Union(_) => Context::Union,
SymbolKind::Function(_) => Context::Function,
_ => {
println!("token: {} kind: {}", symbol.token, symbol.kind);
unreachable!()
}
};
self.context.push(context);
self.parent.push((x, symbol.id));

for dependency in &symbol.dependencies {
let dependency = symbol_table::get(*dependency).unwrap();
self.add_type_dag(&dependency);
}

self.context.pop();
self.parent.pop();
}
}

fn add_parent_type_dag(&mut self, symbol: &Symbol) {
if let Some(ref parent) = symbol.get_parent() {
if is_dependency_symbol(parent) {
if !self.parent.iter().any(|(_, x)| *x == parent.id) {
self.add_type_dag(parent);
}
} else {
self.add_parent_type_dag(parent);
}
}
}

fn insert_node(&mut self, symbol_id: SymbolId, name: &str) -> Option<u32> {
match type_dag::insert_node(symbol_id, name) {
Ok(x) => Some(x),
Err(error) => {
self.add_analyzer_error(error);
None
}
}
}

fn insert_edge(&mut self, start: u32, end: u32, edge: Context) {
// Reversing this order to make traversal work
if let Err(error) = type_dag::insert_edge(start, end, edge) {
self.add_analyzer_error(error);
}
}

fn insert_owned(&mut self, parent: u32, child: u32) {
// If there is already edge to owned type, remove it.
// Argument order should be the same as insert_edge.
if type_dag::exist_edge(child, parent) {
type_dag::remove_edge(child, parent);
}
}

fn add_analyzer_error(&mut self, error: DagError) {
if let DagError::Cyclic(start, end) = error {
let s = match resource_table::get_str_value(start.token.text) {
Some(s) => s,
_ => "<unknown StrId>".into(),
};
let e = match resource_table::get_str_value(end.token.text) {
Some(s) => s,
_ => "<unknown StrId>".into(),
};
self.errors.push(AnalyzerError::cyclic_type_dependency(
self.text,
&s,
&e,
&end.token.into(),
));
}
}
}
7 changes: 0 additions & 7 deletions crates/analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub mod check_unsafe;
pub mod check_var_ref;
pub mod create_reference;
pub mod create_symbol_table;
pub mod create_type_dag;
use check_attribute::*;
use check_clock_domain::*;
use check_clock_reset::*;
Expand All @@ -44,8 +43,6 @@ use crate::analyzer_error::AnalyzerError;
use veryl_metadata::{Build, Lint};
use veryl_parser::veryl_walker::Handler;

use self::create_type_dag::CreateTypeDag;

pub struct Pass1Handlers<'a> {
check_attribute: CheckAttribute<'a>,
check_direction: CheckDirection<'a>,
Expand Down Expand Up @@ -107,7 +104,6 @@ pub struct Pass2Handlers<'a> {
check_var_ref: CheckVarRef<'a>,
check_clock_reset: CheckClockReset<'a>,
create_reference: CreateReference<'a>,
create_type_dag: CreateTypeDag<'a>,
check_expression: CheckExpression<'a>,
check_clock_domain: CheckClockDomain<'a>,
check_proto: CheckProto<'a>,
Expand All @@ -125,7 +121,6 @@ impl<'a> Pass2Handlers<'a> {
check_var_ref: CheckVarRef::new(text),
check_clock_reset: CheckClockReset::new(text),
create_reference: CreateReference::new(text),
create_type_dag: CreateTypeDag::new(text),
check_expression: CheckExpression::new(text),
check_clock_domain: CheckClockDomain::new(text),
check_proto: CheckProto::new(text),
Expand All @@ -143,7 +138,6 @@ impl<'a> Pass2Handlers<'a> {
&mut self.check_var_ref as &mut dyn Handler,
&mut self.check_clock_reset as &mut dyn Handler,
&mut self.create_reference as &mut dyn Handler,
&mut self.create_type_dag as &mut dyn Handler,
&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,
Expand All @@ -161,7 +155,6 @@ impl<'a> Pass2Handlers<'a> {
ret.append(&mut self.check_var_ref.errors);
ret.append(&mut self.check_clock_reset.errors);
ret.append(&mut self.create_reference.errors);
ret.append(&mut self.create_type_dag.errors);
ret.append(&mut self.check_expression.errors);
ret.append(&mut self.check_clock_domain.errors);
ret.append(&mut self.check_proto.errors);
Expand Down
Loading
Loading