Skip to content

Commit

Permalink
Merge pull request #957 from veryl-lang/split_import
Browse files Browse the repository at this point in the history
Add post_pass1 stage for import handling
  • Loading branch information
dalance authored Sep 11, 2024
2 parents 859f2d9 + 996772b commit 6856bb4
Show file tree
Hide file tree
Showing 15 changed files with 122 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
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
57 changes: 56 additions & 1 deletion crates/analyzer/src/handlers/create_symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -64,6 +65,8 @@ pub struct CreateSymbolTable<'a> {
function_ids: HashMap<StrId, SymbolId>,
exist_clock_without_domain: bool,
in_proto: bool,
file_scope_import_item: Vec<SymbolPathNamespace>,
file_scope_import_wildcard: Vec<SymbolPathNamespace>,
}

#[derive(Clone)]
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
47 changes: 41 additions & 6 deletions crates/analyzer/src/symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<StrId, Vec<SymbolId>>,
symbol_table: HashMap<SymbolId, Symbol>,
project_local_table: HashMap<StrId, HashMap<StrId, StrId>>,
assign_list: Vec<Assign>,
import_list: Vec<Import>,
}

impl SymbolTable {
Expand Down Expand Up @@ -380,22 +388,49 @@ 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());
}
}
}

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());
}
}
}

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)
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions crates/analyzer/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fn analyze(code: &str) -> Vec<AnalyzerError> {

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);
Expand Down
1 change: 1 addition & 0 deletions crates/emitter/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions crates/languageserver/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions crates/mdbook/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
);
Expand Down
1 change: 1 addition & 0 deletions crates/tests/benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
})
Expand Down
3 changes: 3 additions & 0 deletions crates/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6856bb4

Please sign in to comment.