Skip to content

Commit

Permalink
Add post_pass1 stage for import handling
Browse files Browse the repository at this point in the history
  • Loading branch information
dalance committed Sep 11, 2024
1 parent 859f2d9 commit 5b2f389
Show file tree
Hide file tree
Showing 16 changed files with 325 additions and 91 deletions.
4 changes: 4 additions & 0 deletions crates/analyzer/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ impl Analyzer {
ret
}

pub fn analyze_post_pass1() {
symbol_table::apply_import();
}

pub fn analyze_pass2<T: AsRef<Path>>(
&self,
project_name: &str,
Expand Down
165 changes: 165 additions & 0 deletions crates/analyzer/src/handlers/create_import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use crate::analyzer_error::AnalyzerError;
use crate::namespace::Namespace;
use crate::namespace_table;
use crate::symbol::SymbolKind;
use crate::symbol_table::{self, ResolveError, ResolveErrorCause};
use veryl_parser::resource_table::TokenId;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_token::TokenRange;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
use veryl_parser::ParolError;

#[derive(Default)]
pub struct CreateImport<'a> {
pub errors: Vec<AnalyzerError>,
text: &'a str,
point: HandlerPoint,
top_level: bool,
file_scope_imported_items: Vec<TokenId>,
file_scope_imported_packages: Vec<Namespace>,
}

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

fn push_resolve_error(&mut self, err: ResolveError, token: &TokenRange) {
if let Some(last_found) = err.last_found {
let name = last_found.token.to_string();
match err.cause {
ResolveErrorCause::NotFound(not_found) => {
let member = format!("{}", not_found);
self.errors.push(AnalyzerError::unknown_member(
&name, &member, self.text, token,
));
}
ResolveErrorCause::Private => {
self.errors
.push(AnalyzerError::private_member(&name, self.text, token));
}
}
} else if let ResolveErrorCause::NotFound(not_found) = err.cause {
let name = format!("{}", not_found);
self.errors
.push(AnalyzerError::undefined_identifier(&name, self.text, token));
} else {
unreachable!();
}
}
}

impl<'a> Handler for CreateImport<'a> {
fn set_point(&mut self, p: HandlerPoint) {
self.point = p;
}
}

impl<'a> VerylGrammarTrait for CreateImport<'a> {
fn module_declaration(&mut self, arg: &ModuleDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn interface_declaration(&mut self, arg: &InterfaceDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn package_declaration(&mut self, arg: &PackageDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn import_declaration(&mut self, arg: &ImportDeclaration) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
let is_wildcard = arg.import_declaration_opt.is_some();
let id = arg.scoped_identifier.identifier().token.id;
let namespace = namespace_table::get(id).unwrap();
match symbol_table::resolve(arg.scoped_identifier.as_ref()) {
Ok(symbol) => {
let symbol = symbol.found;
match symbol.kind {
SymbolKind::Package(_) if is_wildcard => {
let mut target = symbol.namespace.clone();
target.push(symbol.token.text);

if self.top_level {
self.file_scope_imported_packages.push(target);
} else {
symbol_table::add_imported_package(&target, &namespace);
}
}
SymbolKind::SystemVerilog => (),
_ if is_wildcard => {
self.errors.push(AnalyzerError::invalid_import(
self.text,
&arg.scoped_identifier.as_ref().into(),
));
}
_ => {
if self.top_level {
self.file_scope_imported_items.push(symbol.token.id);
} else {
symbol_table::add_imported_item(symbol.token.id, &namespace);
}
}
}
}
Err(err) => {
self.push_resolve_error(err, &arg.scoped_identifier.as_ref().into());
}
}
}
Ok(())
}
}
86 changes: 2 additions & 84 deletions crates/analyzer/src/handlers/create_reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::namespace_table;
use crate::symbol::{GenericMap, SymbolKind};
use crate::symbol_path::{GenericSymbolPath, SymbolPath};
use crate::symbol_table::{self, ResolveError, ResolveErrorCause};
use veryl_parser::resource_table::TokenId;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_token::TokenRange;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
Expand All @@ -15,16 +14,12 @@ pub struct CreateReference<'a> {
pub errors: Vec<AnalyzerError>,
text: &'a str,
point: HandlerPoint,
top_level: bool,
file_scope_imported_items: Vec<TokenId>,
file_scope_imported_packages: Vec<Namespace>,
}

impl<'a> CreateReference<'a> {
pub fn new(text: &'a str) -> Self {
Self {
text,
top_level: true,
..Default::default()
}
}
Expand Down Expand Up @@ -223,99 +218,22 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> {
Ok(())
}

fn module_declaration(&mut self, arg: &ModuleDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn interface_declaration(&mut self, arg: &InterfaceDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn package_declaration(&mut self, arg: &PackageDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.top_level = false;
let mut namespace = Namespace::default();
namespace.push(arg.identifier.identifier_token.token.text);
for x in &self.file_scope_imported_items {
symbol_table::add_imported_item(*x, &namespace);
}
for x in &self.file_scope_imported_packages {
symbol_table::add_imported_package(x, &namespace);
}
}
HandlerPoint::After => {
self.top_level = true;
}
}
Ok(())
}

fn import_declaration(&mut self, arg: &ImportDeclaration) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
let is_wildcard = arg.import_declaration_opt.is_some();
let id = arg.scoped_identifier.identifier().token.id;
let namespace = namespace_table::get(id).unwrap();
match symbol_table::resolve(arg.scoped_identifier.as_ref()) {
Ok(symbol) => {
let symbol = symbol.found;
match symbol.kind {
SymbolKind::Package(_) if is_wildcard => {
let mut target = symbol.namespace.clone();
target.push(symbol.token.text);

if self.top_level {
self.file_scope_imported_packages.push(target);
} else {
symbol_table::add_imported_package(&target, &namespace);
}
}
SymbolKind::Package(_) if is_wildcard => (),
SymbolKind::SystemVerilog => (),
_ if is_wildcard => {
self.errors.push(AnalyzerError::invalid_import(
self.text,
&arg.scoped_identifier.as_ref().into(),
));
}
_ => {
if self.top_level {
self.file_scope_imported_items.push(symbol.token.id);
} else {
symbol_table::add_imported_item(symbol.token.id, &namespace);
}
}
_ => (),
}
}
Err(err) => {
Expand Down
Loading

0 comments on commit 5b2f389

Please sign in to comment.