Skip to content

Commit

Permalink
merge create_reference and create_type_dag handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
taichi-ishitani committed Dec 15, 2024
1 parent 69464ff commit 6557d91
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 461 deletions.
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
285 changes: 283 additions & 2 deletions crates/analyzer/src/handlers/create_reference.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use crate::analyzer_error::AnalyzerError;
use crate::namespace::Namespace;
use crate::namespace_table;
use crate::symbol::{Direction, GenericBoundKind, GenericMap, Port, SymbolKind};
use crate::symbol_path::GenericSymbolPath;
use crate::symbol::{
Direction, GenericBoundKind, GenericMap, ParameterKind, Port, Symbol, SymbolKind,
};
use crate::symbol_path::{GenericSymbolPath, SymbolPathNamespace};
use crate::symbol_table::{self, ResolveError, ResolveErrorCause};
use crate::type_dag::{self, Context, DagError};
use std::collections::HashMap;
use veryl_parser::resource_table;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_token::{is_anonymous_text, Token, TokenRange};
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
Expand All @@ -17,6 +22,12 @@ pub struct CreateReference<'a> {
inst_ports: Vec<Port>,
inst_sv_module: bool,
is_anonymous_identifier: bool,
dag_scope_parent: Vec<u32>,
dag_scope_context: Vec<Context>,
dag_type_parent: Vec<u32>,
dag_type_context: Vec<Context>,
dag_owned: HashMap<u32, Vec<u32>>,
dag_file_imports: Vec<u32>,
}

impl<'a> CreateReference<'a> {
Expand Down Expand Up @@ -117,6 +128,15 @@ impl<'a> CreateReference<'a> {
continue;
}

let mut generic_args = Vec::new();
for arg in &path.paths[i].arguments {
let path = SymbolPathNamespace(arg.mangled_path(), namespace.clone());
if let Ok(arg) = symbol_table::resolve(&path) {
generic_args.push(arg.found);
}
}
self.insert_base_path_dag_node(&symbol.found, &generic_args);

let mut path = path.paths[i].clone();

for param in params.iter().skip(n_args) {
Expand Down Expand Up @@ -157,6 +177,143 @@ impl<'a> CreateReference<'a> {
}
}
}

fn insert_declaration_dag_node(&mut self, symbol: &Symbol) -> Option<u32> {
if let Some(child) = self.insert_dag_node(symbol) {
if let Some(parent) = self.dag_scope_parent.last().cloned() {
self.insert_dag_owned(parent, child);
self.insert_dag_edge(child, parent, *self.dag_scope_context.last().unwrap());
}
Some(child)
} else {
None
}
}

fn insert_scope_declaration_dag_node(&mut self, symbol: &Symbol, context: Context) {
if let Some(child) = self.insert_declaration_dag_node(symbol) {
self.dag_scope_parent.push(child);
self.dag_scope_context.push(context);

for import_item in &self.dag_file_imports.clone() {
self.insert_dag_edge(child, *import_item, context);
}
}
}

fn pop_scope_dag(&mut self) {
self.dag_scope_parent.pop();
self.dag_scope_context.pop();
}

fn insert_type_declaration_dag_node(&mut self, symbol: &Symbol, context: Context) {
if let Some(child) = self.insert_declaration_dag_node(symbol) {
self.dag_type_parent.push(child);
self.dag_type_context.push(context);
}
}

fn pop_type_dag(&mut self) {
self.dag_type_parent.pop();
self.dag_type_context.pop();
}

fn insert_base_path_dag_node(&mut self, base: &Symbol, generic_args: &[Symbol]) {
if let Some(base) = self.insert_dag_node(base) {
if let Some(parent) = self.dag_scope_parent.last() {
if !self.is_dag_owned(*parent, base) {
self.insert_dag_edge(*parent, base, *self.dag_scope_context.last().unwrap());
}
}
if let Some(parent) = self.dag_type_parent.last() {
if !self.is_dag_owned(*parent, base) {
self.insert_dag_edge(*parent, base, *self.dag_type_context.last().unwrap());
}
}

for arg in generic_args {
if let Some(arg) = self.insert_dag_node(arg) {
self.insert_dag_edge(base, arg, Context::GenericInstance);
}
}
}
}

fn insert_dag_node(&mut self, symbol: &Symbol) -> Option<u32> {
let is_dag_symbol = match symbol.kind {
SymbolKind::Module(_)
| SymbolKind::Interface(_)
| SymbolKind::Modport(_)
| SymbolKind::Package(_)
| SymbolKind::Enum(_)
| SymbolKind::TypeDef(_)
| SymbolKind::Struct(_)
| SymbolKind::Union(_)
| SymbolKind::Function(_) => true,
SymbolKind::Parameter(ref x) => matches!(x.kind, ParameterKind::Const),
_ => false,
};
if !is_dag_symbol {
return None;
}

let name = symbol.token.to_string();
match type_dag::insert_node(symbol.id, &name) {
Ok(n) => Some(n),
Err(error) => {
self.push_cyclic_type_dependency_error(error);
None
}
}
}

fn insert_dag_edge(&mut self, start: u32, end: u32, edge: Context) {
// Reversing this order to make traversal work
match type_dag::insert_edge(end, start, edge) {
Ok(_) => {}
Err(error) => {
self.push_cyclic_type_dependency_error(error);
}
}
}

fn insert_dag_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);
}
self.dag_owned
.entry(parent)
.and_modify(|x| x.push(child))
.or_insert(vec![child]);
}

fn is_dag_owned(&self, parent: u32, child: u32) -> bool {
if let Some(owned) = self.dag_owned.get(&parent) {
owned.contains(&child)
} else {
false
}
}

fn push_cyclic_type_dependency_error(&mut self, error: DagError) {
let DagError::Cyclic(s, e) = error;
let start = match resource_table::get_str_value(s.token.text) {
Some(s) => s,
None => "<unknown StrId>".into(),
};
let end = match resource_table::get_str_value(e.token.text) {
Some(s) => s,
None => "<unknown StrId>".into(),
};
self.errors.push(AnalyzerError::cyclic_type_dependency(
self.text,
&start,
&end,
&e.token.into(),
));
}
}

impl Handler for CreateReference<'_> {
Expand All @@ -166,6 +323,130 @@ impl Handler for CreateReference<'_> {
}

impl VerylGrammarTrait for CreateReference<'_> {
fn veryl(&mut self, arg: &Veryl) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
for x in &arg.veryl_list {
let items: Vec<DescriptionItem> = x.description_group.as_ref().into();
for item in items {
if let DescriptionItem::ImportDeclaration(x) = item {
if let Ok(symbol) = symbol_table::resolve(x.import_declaration.scoped_identifier.as_ref()) {
if let Some(child) = self.insert_dag_node(&symbol.found) {
self.dag_file_imports.push(child);
}
}
}
}
}
}
HandlerPoint::After => self.dag_file_imports.clear(),
}
Ok(())
}

fn module_declaration(&mut self, arg: &ModuleDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_scope_declaration_dag_node(&symbol.found, Context::Module);
}
HandlerPoint::After => self.pop_scope_dag(),
}
Ok(())
}

fn interface_declaration(&mut self, arg: &InterfaceDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_scope_declaration_dag_node(&symbol.found, Context::Interface);
}
HandlerPoint::After => self.pop_scope_dag(),
}
Ok(())
}

fn modport_declaration(&mut self, arg: &ModportDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_type_declaration_dag_node(&symbol.found, Context::Modport);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn package_declaration(&mut self, arg: &PackageDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_scope_declaration_dag_node(&symbol.found, Context::Package);
}
HandlerPoint::After => self.pop_scope_dag(),
}
Ok(())
}

fn struct_union_declaration(&mut self, arg: &StructUnionDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
let context = match &*arg.struct_union {
StructUnion::Struct(_) => Context::Struct,
StructUnion::Union(_) => Context::Union,
};
self.insert_type_declaration_dag_node(&symbol.found, context);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn enum_declaration(&mut self, arg: &EnumDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_type_declaration_dag_node(&symbol.found, Context::Enum);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn type_def_declaration(&mut self, arg: &TypeDefDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_type_declaration_dag_node(&symbol.found, Context::TypeDef);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn const_declaration(&mut self, arg: &ConstDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_type_declaration_dag_node(&symbol.found, Context::Const);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn function_declaration(&mut self, arg: &FunctionDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let symbol = symbol_table::resolve(arg.identifier.as_ref()).unwrap();
self.insert_type_declaration_dag_node(&symbol.found, Context::Function);
}
HandlerPoint::After => self.pop_type_dag(),
}
Ok(())
}

fn hierarchical_identifier(&mut self, arg: &HierarchicalIdentifier) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
match symbol_table::resolve(arg) {
Expand Down
Loading

0 comments on commit 6557d91

Please sign in to comment.