From 996772b8b20708180ebebbd7f82aa583a60a6840 Mon Sep 17 00:00:00 2001 From: dalance Date: Tue, 10 Sep 2024 16:59:12 +0900 Subject: [PATCH] Add post_pass1 stage for import handling --- crates/analyzer/src/analyzer.rs | 4 + .../analyzer/src/handlers/create_reference.rs | 86 +------------------ .../src/handlers/create_symbol_table.rs | 57 +++++++++++- crates/analyzer/src/symbol_table.rs | 47 ++++++++-- crates/analyzer/src/tests.rs | 1 + crates/emitter/src/tests.rs | 1 + crates/languageserver/src/server.rs | 2 + crates/mdbook/src/main.rs | 1 + crates/tests/benches/benchmark.rs | 1 + crates/tests/src/lib.rs | 3 + crates/veryl/src/cmd_build.rs | 2 + crates/veryl/src/cmd_check.rs | 2 + crates/veryl/src/cmd_doc.rs | 2 + crates/veryl/src/cmd_dump.rs | 2 + crates/veryl/src/cmd_publish.rs | 2 + 15 files changed, 122 insertions(+), 91 deletions(-) diff --git a/crates/analyzer/src/analyzer.rs b/crates/analyzer/src/analyzer.rs index 1d76b64e..c2a81e60 100644 --- a/crates/analyzer/src/analyzer.rs +++ b/crates/analyzer/src/analyzer.rs @@ -215,6 +215,10 @@ impl Analyzer { ret } + pub fn analyze_post_pass1() { + symbol_table::apply_import(); + } + pub fn analyze_pass2>( &self, project_name: &str, diff --git a/crates/analyzer/src/handlers/create_reference.rs b/crates/analyzer/src/handlers/create_reference.rs index ebc4d896..32c9dc6f 100644 --- a/crates/analyzer/src/handlers/create_reference.rs +++ b/crates/analyzer/src/handlers/create_reference.rs @@ -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}; @@ -15,16 +14,12 @@ pub struct CreateReference<'a> { pub errors: Vec, text: &'a str, point: HandlerPoint, - top_level: bool, - file_scope_imported_items: Vec, - file_scope_imported_packages: Vec, } impl<'a> CreateReference<'a> { pub fn new(text: &'a str) -> Self { Self { text, - top_level: true, ..Default::default() } } @@ -223,85 +218,14 @@ 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( @@ -309,13 +233,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { &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) => { diff --git a/crates/analyzer/src/handlers/create_symbol_table.rs b/crates/analyzer/src/handlers/create_symbol_table.rs index 832a79d8..270b92d4 100644 --- a/crates/analyzer/src/handlers/create_symbol_table.rs +++ b/crates/analyzer/src/handlers/create_symbol_table.rs @@ -19,8 +19,9 @@ use crate::symbol::{ SymbolKind, TestProperty, TestType, TypeDefProperty, TypeKind, UnionMemberProperty, UnionProperty, VariableAffiniation, VariableProperty, }; -use crate::symbol_path::{GenericSymbolPath, SymbolPath}; +use crate::symbol_path::{GenericSymbolPath, SymbolPath, SymbolPathNamespace}; use crate::symbol_table; +use crate::symbol_table::Import as SymImport; use std::collections::{HashMap, HashSet}; use veryl_metadata::ClockType; use veryl_metadata::{Build, ResetType}; @@ -64,6 +65,8 @@ pub struct CreateSymbolTable<'a> { function_ids: HashMap, exist_clock_without_domain: bool, in_proto: bool, + file_scope_import_item: Vec, + file_scope_import_wildcard: Vec, } #[derive(Clone)] @@ -344,6 +347,26 @@ impl<'a> CreateSymbolTable<'a> { } } } + + fn apply_file_scope_import(&self) { + for x in &self.file_scope_import_item { + let import = SymImport { + path: x.clone(), + namespace: self.namespace.clone(), + wildcard: false, + }; + symbol_table::add_import(import); + } + + for x in &self.file_scope_import_wildcard { + let import = SymImport { + path: x.clone(), + namespace: self.namespace.clone(), + wildcard: true, + }; + symbol_table::add_import(import); + } + } } impl<'a> Handler for CreateSymbolTable<'a> { @@ -1088,6 +1111,32 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { Ok(()) } + fn import_declaration(&mut self, arg: &ImportDeclaration) -> Result<(), ParolError> { + if let HandlerPoint::Before = self.point { + let path: SymbolPath = arg.scoped_identifier.as_ref().into(); + let path: SymbolPathNamespace = (&path, &self.namespace).into(); + let namespace = path.1.clone(); + let wildcard = arg.import_declaration_opt.is_some(); + + let import = SymImport { + path: path.clone(), + namespace, + wildcard, + }; + + if self.affiniation.is_empty() { + if wildcard { + self.file_scope_import_wildcard.push(path); + } else { + self.file_scope_import_item.push(path); + } + } else { + symbol_table::add_import(import); + } + } + Ok(()) + } + fn module_declaration(&mut self, arg: &ModuleDeclaration) -> Result<(), ParolError> { let name = arg.identifier.identifier_token.token.text; match self.point { @@ -1100,6 +1149,8 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { self.module_namspace_depth = self.namespace.depth(); self.function_ids.clear(); self.exist_clock_without_domain = false; + + self.apply_file_scope_import(); } HandlerPoint::After => { self.namespace.pop(); @@ -1227,6 +1278,8 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { self.affiniation.push(VariableAffiniation::Intarface); self.function_ids.clear(); self.modport_member_ids.clear(); + + self.apply_file_scope_import(); } HandlerPoint::After => { self.namespace.pop(); @@ -1277,6 +1330,8 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { self.generic_parameters.push(Vec::new()); self.affiniation.push(VariableAffiniation::Package); self.function_ids.clear(); + + self.apply_file_scope_import(); } HandlerPoint::After => { self.namespace.pop(); diff --git a/crates/analyzer/src/symbol_table.rs b/crates/analyzer/src/symbol_table.rs index 987a39d9..c056c1a6 100644 --- a/crates/analyzer/src/symbol_table.rs +++ b/crates/analyzer/src/symbol_table.rs @@ -36,12 +36,20 @@ impl ResolveError { } } +#[derive(Clone, Debug)] +pub struct Import { + pub path: SymbolPathNamespace, + pub namespace: Namespace, + pub wildcard: bool, +} + #[derive(Clone, Default, Debug)] pub struct SymbolTable { name_table: HashMap>, symbol_table: HashMap, project_local_table: HashMap>, assign_list: Vec, + import_list: Vec, } impl SymbolTable { @@ -380,7 +388,7 @@ impl SymbolTable { } } - pub fn add_imported_item(&mut self, target: TokenId, namespace: &Namespace) { + fn add_imported_item(&mut self, target: TokenId, namespace: &Namespace) { for (_, symbol) in self.symbol_table.iter_mut() { if symbol.token.id == target { symbol.imported.push(namespace.to_owned()); @@ -388,7 +396,7 @@ impl SymbolTable { } } - pub fn add_imported_package(&mut self, target: &Namespace, namespace: &Namespace) { + fn add_imported_package(&mut self, target: &Namespace, namespace: &Namespace) { for (_, symbol) in self.symbol_table.iter_mut() { if symbol.namespace.matched(target) { symbol.imported.push(namespace.to_owned()); @@ -396,6 +404,33 @@ impl SymbolTable { } } + pub fn add_import(&mut self, import: Import) { + self.import_list.push(import); + } + + pub fn apply_import(&mut self) { + let import_list: Vec<_> = self.import_list.drain(0..).collect(); + for import in import_list { + if let Ok(symbol) = self.resolve(&import.path.0, &import.path.1) { + let symbol = symbol.found; + match symbol.kind { + SymbolKind::Package(_) if import.wildcard => { + let mut target = symbol.namespace.clone(); + target.push(symbol.token.text); + + self.add_imported_package(&target, &import.namespace); + } + SymbolKind::SystemVerilog => (), + // Error will be reported at create_reference + _ if import.wildcard => (), + _ => { + self.add_imported_item(symbol.token.id, &import.namespace); + } + } + } + } + } + pub fn add_project_local(&mut self, prj: StrId, from: StrId, to: StrId) { self.project_local_table .entry(prj) @@ -1011,12 +1046,12 @@ pub fn add_generic_instance(target: SymbolId, instance: SymbolId) { SYMBOL_TABLE.with(|f| f.borrow_mut().add_generic_instance(target, instance)) } -pub fn add_imported_item(target: TokenId, namespace: &Namespace) { - SYMBOL_TABLE.with(|f| f.borrow_mut().add_imported_item(target, namespace)) +pub fn add_import(import: Import) { + SYMBOL_TABLE.with(|f| f.borrow_mut().add_import(import)) } -pub fn add_imported_package(target: &Namespace, namespace: &Namespace) { - SYMBOL_TABLE.with(|f| f.borrow_mut().add_imported_package(target, namespace)) +pub fn apply_import() { + SYMBOL_TABLE.with(|f| f.borrow_mut().apply_import()) } pub fn add_project_local(prj: StrId, from: StrId, to: StrId) { diff --git a/crates/analyzer/src/tests.rs b/crates/analyzer/src/tests.rs index 188752d8..02b8bb02 100644 --- a/crates/analyzer/src/tests.rs +++ b/crates/analyzer/src/tests.rs @@ -13,6 +13,7 @@ fn analyze(code: &str) -> Vec { let mut errors = vec![]; errors.append(&mut analyzer.analyze_pass1(&"prj", &code, &"", &parser.veryl)); + Analyzer::analyze_post_pass1(); errors.append(&mut analyzer.analyze_pass2(&"prj", &code, &"", &parser.veryl)); errors.append(&mut analyzer.analyze_pass3(&"prj", &code, &"", &parser.veryl)); dbg!(&errors); diff --git a/crates/emitter/src/tests.rs b/crates/emitter/src/tests.rs index fb4f3e86..9d64aacc 100644 --- a/crates/emitter/src/tests.rs +++ b/crates/emitter/src/tests.rs @@ -10,6 +10,7 @@ fn emit(metadata: &Metadata, code: &str) -> String { let analyzer = Analyzer::new(metadata); analyzer.analyze_pass1(&"prj", &code, &"", &parser.veryl); + Analyzer::analyze_post_pass1(); analyzer.analyze_pass2(&"prj", &code, &"", &parser.veryl); let mut emitter = Emitter::new( diff --git a/crates/languageserver/src/server.rs b/crates/languageserver/src/server.rs index b2317592..ce05730a 100644 --- a/crates/languageserver/src/server.rs +++ b/crates/languageserver/src/server.rs @@ -177,6 +177,7 @@ impl Server { ); } if task.paths.is_empty() { + Analyzer::analyze_post_pass1(); self.progress_done("background analyze done"); if self.background_tasks.is_empty() { self.background_done = true; @@ -647,6 +648,7 @@ impl Server { } let analyzer = Analyzer::new(&metadata); let mut errors = analyzer.analyze_pass1(prj, text, &path, &x.veryl); + Analyzer::analyze_post_pass1(); errors.append(&mut analyzer.analyze_pass2(prj, text, &path, &x.veryl)); errors.append(&mut analyzer.analyze_pass3(prj, text, &path, &x.veryl)); let ret: Vec<_> = errors diff --git a/crates/mdbook/src/main.rs b/crates/mdbook/src/main.rs index 4165ee1f..8e8dc584 100644 --- a/crates/mdbook/src/main.rs +++ b/crates/mdbook/src/main.rs @@ -164,6 +164,7 @@ impl Preprocessor for Veryl { errors.append( &mut analyzer.analyze_pass1(prj, &x, "", &ret.veryl), ); + Analyzer::analyze_post_pass1(); errors.append( &mut analyzer.analyze_pass2(prj, &x, "", &ret.veryl), ); diff --git a/crates/tests/benches/benchmark.rs b/crates/tests/benches/benchmark.rs index 5a01bfb0..00e6355d 100644 --- a/crates/tests/benches/benchmark.rs +++ b/crates/tests/benches/benchmark.rs @@ -34,6 +34,7 @@ fn criterion_benchmark(c: &mut Criterion) { let prj = &metadata.project.name; let analyzer = Analyzer::new(black_box(&metadata)); analyzer.analyze_pass1(prj, black_box(&text), &"", &parser.veryl); + Analyzer::analyze_post_pass1(); analyzer.analyze_pass2(prj, black_box(&text), &"", &parser.veryl); //analyzer.analyze_pass3(prj, black_box(&text), &"", &parser.veryl); }) diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index 47b4682d..48649ae6 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -53,6 +53,8 @@ mod analyzer { dbg!(&errors); assert!(errors.is_empty()); + Analyzer::analyze_post_pass1(); + let errors = analyzer.analyze_pass2(&prj, &input, &file, &ret.veryl); dbg!(&errors); assert!(errors.is_empty()); @@ -135,6 +137,7 @@ mod emitter { let prj = &metadata.project.name; let analyzer = Analyzer::new(&metadata); let _ = analyzer.analyze_pass1(&prj, &input, &src_path, &ret.veryl); + Analyzer::analyze_post_pass1(); let _ = analyzer.analyze_pass2(&prj, &input, &src_path, &ret.veryl); let mut emitter = Emitter::new(&metadata, &src_path, &dst_path, &map_path); emitter.emit(&prj, &ret.veryl); diff --git a/crates/veryl/src/cmd_build.rs b/crates/veryl/src/cmd_build.rs index 6ea01a31..232ede06 100644 --- a/crates/veryl/src/cmd_build.rs +++ b/crates/veryl/src/cmd_build.rs @@ -46,6 +46,8 @@ impl CmdBuild { contexts.push((path, input, parser, analyzer)); } + Analyzer::analyze_post_pass1(); + for (path, input, parser, analyzer) in &contexts { let mut errors = analyzer.analyze_pass2(&path.prj, input, &path.src, &parser.veryl); check_error = check_error.append(&mut errors).check_err()?; diff --git a/crates/veryl/src/cmd_check.rs b/crates/veryl/src/cmd_check.rs index b69da1f6..ae66bacf 100644 --- a/crates/veryl/src/cmd_check.rs +++ b/crates/veryl/src/cmd_check.rs @@ -71,6 +71,8 @@ impl CmdCheck { contexts.push((path, input, parser, analyzer)); } + Analyzer::analyze_post_pass1(); + for (path, input, parser, analyzer) in &contexts { let mut errors = analyzer.analyze_pass2(&path.prj, input, &path.src, &parser.veryl); check_error = check_error.append(&mut errors).check_err()?; diff --git a/crates/veryl/src/cmd_doc.rs b/crates/veryl/src/cmd_doc.rs index b32c886c..583141c9 100644 --- a/crates/veryl/src/cmd_doc.rs +++ b/crates/veryl/src/cmd_doc.rs @@ -37,6 +37,8 @@ impl CmdDoc { contexts.push((path, input, parser, analyzer)); } + Analyzer::analyze_post_pass1(); + for (path, input, parser, analyzer) in &contexts { analyzer.analyze_pass2(&path.prj, input, &path.src, &parser.veryl); } diff --git a/crates/veryl/src/cmd_dump.rs b/crates/veryl/src/cmd_dump.rs index f3c4bc3d..41479dfb 100644 --- a/crates/veryl/src/cmd_dump.rs +++ b/crates/veryl/src/cmd_dump.rs @@ -33,6 +33,8 @@ impl CmdDump { contexts.push((path, input, parser, analyzer)); } + Analyzer::analyze_post_pass1(); + for (path, input, parser, analyzer) in &contexts { analyzer.analyze_pass2(&path.prj, input, &path.src, &parser.veryl); } diff --git a/crates/veryl/src/cmd_publish.rs b/crates/veryl/src/cmd_publish.rs index 12a64782..494209b2 100644 --- a/crates/veryl/src/cmd_publish.rs +++ b/crates/veryl/src/cmd_publish.rs @@ -47,6 +47,8 @@ impl CmdPublish { contexts.push((path, input, parser, analyzer)); } + Analyzer::analyze_post_pass1(); + for (path, input, parser, analyzer) in &contexts { let mut errors = analyzer.analyze_pass2(&path.prj, input, &path.src, &parser.veryl); check_error = check_error.append(&mut errors).check_err()?;