diff --git a/Cargo.toml b/Cargo.toml index c396c9b6e..abd8bd5f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ triomphe.workspace = true [workspace.dependencies] hir = { path = "./crates/hir/", version = "0.0.0" } ide = { path = "./crates/ide/", version = "0.0.0" } -proc-macro-utils = { path = "./crates/proc-macro-utils/", version = "0.0.0" } preproc = { path = "./crates/preproc/", version = "0.0.0" } project-model = { path = "./crates/project-model/", version = "0.0.0" } syntax = { path = "./crates/syntax/", version = "0.0.0" } diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 1ac4afc78..89087e1b5 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -8,7 +8,6 @@ hashbrown = { version = "0.12.3", features = ["inline-more"], default-features = itertools.workspace = true la-arena.workspace = true preproc.workspace = true -proc-macro-utils.workspace = true rustc-hash.workspace = true salsa.workspace = true smallvec.workspace = true diff --git a/crates/hir/src/container.rs b/crates/hir/src/container.rs index 2ad34069b..ceab9b1a0 100644 --- a/crates/hir/src/container.rs +++ b/crates/hir/src/container.rs @@ -1,7 +1,9 @@ -use proc_macro_utils::impl_container; use smol_str::SmolStr; use triomphe::Arc; -use utils::{define_enum_deriving_from, get::GetRef}; +use utils::{ + define_enum_deriving_from, + get::{Get, GetRef}, +}; use crate::{ base_db::intern::Lookup, @@ -360,26 +362,32 @@ impl ArenaOwnerId { pub fn data(self, db: &dyn HirDb) -> Container { match self { - ArenaOwnerId::File(file_id) => file_id.to_container(db).into(), - ArenaOwnerId::Module(module_id) => module_id.to_container(db).into(), + ArenaOwnerId::File(file_id) => Container::HirFile(file_id.to_container(db)), + ArenaOwnerId::Module(module_id) => Container::Module(module_id.to_container(db)), ArenaOwnerId::GenerateBlock(generate_block_id) => { - generate_block_id.to_container(db).into() + Container::GenerateBlock(generate_block_id.to_container(db)) + } + ArenaOwnerId::Block(block_id) => Container::Block(block_id.to_container(db)), + ArenaOwnerId::Subroutine(subroutine) => { + Container::Subroutine(db.subroutine(subroutine)) } - ArenaOwnerId::Block(block_id) => block_id.to_container(db).into(), - ArenaOwnerId::Subroutine(subroutine) => db.subroutine(subroutine).into(), } } pub fn source_map(self, db: &dyn HirDb) -> ContainerSrcMap { match self { - ArenaOwnerId::File(file_id) => file_id.to_container_src_map(db).into(), - ArenaOwnerId::Module(module_id) => module_id.to_container_src_map(db).into(), + ArenaOwnerId::File(file_id) => ContainerSrcMap::File(file_id.to_container_src_map(db)), + ArenaOwnerId::Module(module_id) => { + ContainerSrcMap::Module(module_id.to_container_src_map(db)) + } ArenaOwnerId::GenerateBlock(generate_block_id) => { - generate_block_id.to_container_src_map(db).into() + ContainerSrcMap::GenerateBlock(generate_block_id.to_container_src_map(db)) + } + ArenaOwnerId::Block(block_id) => { + ContainerSrcMap::Block(block_id.to_container_src_map(db)) } - ArenaOwnerId::Block(block_id) => block_id.to_container_src_map(db).into(), ArenaOwnerId::Subroutine(subroutine) => { - db.subroutine_with_source_map(subroutine).1.into() + ContainerSrcMap::Subroutine(db.subroutine_with_source_map(subroutine).1) } } } @@ -441,28 +449,25 @@ impl GenerateBlockId { } } -impl_container! { - #[derive(Debug, PartialEq, Eq, Clone)] - pub enum { - HirFile | FileSourceMap, - Module | ModuleSourceMap, - GenerateBlock | GenerateBlockSourceMap, - Block | BlockSourceMap, - Subroutine | SubroutineSourceMap, - } => { - Declaration[DeclarationId | DeclarationSrc], - Typedef[TypedefId | TypedefSrc], - StructDef[StructId | StructSrc], - Expr[ExprId | ExprSrc], - EventExpr[EventExprId | EventExprSrc], - Declarator[DeclId | DeclaratorSrc], - Stmt[StmtId | StmtSrc], - BlockInfo[LocalBlockId | BlockSrc], - } +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Container { + HirFile(Arc), + Module(Arc), + GenerateBlock(Arc), + Block(Arc), + Subroutine(Arc), +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum ContainerSrcMap { + File(Arc), + Module(Arc), + GenerateBlock(Arc), + Block(Arc), + Subroutine(Arc), } impl Container { - #[inline] pub fn name(&self) -> Option<&SmolStr> { match self { Container::HirFile(_) => None, @@ -472,32 +477,257 @@ impl Container { Container::Subroutine(subroutine) => subroutine.name.as_ref(), } } -} -impl AsRef for Container { - fn as_ref(&self) -> &Container { - self + pub fn declaration(&self, id: DeclarationId) -> &Declaration { + match self { + Container::HirFile(container) => &container.declarations[id], + Container::Module(container) => &container.declarations[id], + Container::GenerateBlock(container) => &container.declarations[id], + Container::Block(container) => &container.declarations[id], + Container::Subroutine(container) => &container.declarations[id], + } + } + + pub fn typedef(&self, id: TypedefId) -> &Typedef { + match self { + Container::HirFile(container) => &container.typedefs[id], + Container::Module(container) => &container.typedefs[id], + Container::GenerateBlock(container) => &container.typedefs[id], + Container::Block(container) => &container.typedefs[id], + Container::Subroutine(container) => &container.typedefs[id], + } + } + + pub fn struct_def(&self, id: StructId) -> &StructDef { + match self { + Container::HirFile(container) => &container.structs[id], + Container::Module(container) => &container.structs[id], + Container::GenerateBlock(container) => &container.structs[id], + Container::Block(container) => &container.structs[id], + Container::Subroutine(container) => &container.structs[id], + } + } + + pub fn expr(&self, id: ExprId) -> &Expr { + match self { + Container::HirFile(container) => &container.exprs[id], + Container::Module(container) => &container.exprs[id], + Container::GenerateBlock(container) => &container.exprs[id], + Container::Block(container) => &container.exprs[id], + Container::Subroutine(container) => &container.exprs[id], + } + } + + pub fn event_expr(&self, id: EventExprId) -> &EventExpr { + match self { + Container::HirFile(container) => &container.event_exprs[id], + Container::Module(container) => &container.event_exprs[id], + Container::GenerateBlock(container) => &container.event_exprs[id], + Container::Block(container) => &container.event_exprs[id], + Container::Subroutine(container) => &container.event_exprs[id], + } + } + + pub fn declarator(&self, id: DeclId) -> &Declarator { + match self { + Container::HirFile(container) => &container.decls[id], + Container::Module(container) => &container.decls[id], + Container::GenerateBlock(container) => &container.decls[id], + Container::Block(container) => &container.decls[id], + Container::Subroutine(container) => &container.decls[id], + } + } + + pub fn stmt(&self, id: StmtId) -> &Stmt { + match self { + Container::HirFile(container) => &container.stmts[id], + Container::Module(container) => &container.stmts[id], + Container::GenerateBlock(container) => &container.stmts[id], + Container::Block(container) => &container.stmts[id], + Container::Subroutine(container) => &container.stmts[id], + } + } + + pub fn block_info(&self, id: LocalBlockId) -> &BlockInfo { + match self { + Container::HirFile(container) => utils::get::GetRef::get(&container.stmts, id), + Container::Module(container) => utils::get::GetRef::get(&container.stmts, id), + Container::GenerateBlock(container) => utils::get::GetRef::get(&container.stmts, id), + Container::Block(container) => utils::get::GetRef::get(&container.stmts, id), + Container::Subroutine(container) => utils::get::GetRef::get(&container.stmts, id), + } } } impl ContainerSrcMap { - #[inline] - pub fn region_tree(&self) -> Option<&RegionTree> { + pub fn region_tree(&self) -> &RegionTree { match self { - ContainerSrcMap::FileSourceMap(file) => Some(&file.region_tree), - ContainerSrcMap::ModuleSourceMap(module) => Some(&module.region_tree), - ContainerSrcMap::GenerateBlockSourceMap(generate_block) => { - Some(&generate_block.region_tree) - } - ContainerSrcMap::BlockSourceMap(block) => Some(&block.region_tree), - ContainerSrcMap::SubroutineSourceMap(subroutine) => Some(&subroutine.region_tree), + ContainerSrcMap::File(container) => &container.region_tree, + ContainerSrcMap::Module(container) => &container.region_tree, + ContainerSrcMap::GenerateBlock(container) => &container.region_tree, + ContainerSrcMap::Block(container) => &container.region_tree, + ContainerSrcMap::Subroutine(container) => &container.region_tree, + } + } + + pub fn declaration_from_source(&self, src: DeclarationSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.declaration_srcs.get(src), + ContainerSrcMap::Module(container) => container.declaration_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.declaration_srcs.get(src), + ContainerSrcMap::Block(container) => container.declaration_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.declaration_srcs.get(src), } } -} -impl AsRef for ContainerSrcMap { - fn as_ref(&self) -> &ContainerSrcMap { - self + pub fn source_of_declaration(&self, id: DeclarationId) -> Option { + match self { + ContainerSrcMap::File(container) => container.declaration_srcs.get(id), + ContainerSrcMap::Module(container) => container.declaration_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.declaration_srcs.get(id), + ContainerSrcMap::Block(container) => container.declaration_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.declaration_srcs.get(id), + } + } + + pub fn typedef_from_source(&self, src: TypedefSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.typedef_srcs.get(src), + ContainerSrcMap::Module(container) => container.typedef_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.typedef_srcs.get(src), + ContainerSrcMap::Block(container) => container.typedef_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.typedef_srcs.get(src), + } + } + + pub fn source_of_typedef(&self, id: TypedefId) -> Option { + match self { + ContainerSrcMap::File(container) => container.typedef_srcs.get(id), + ContainerSrcMap::Module(container) => container.typedef_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.typedef_srcs.get(id), + ContainerSrcMap::Block(container) => container.typedef_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.typedef_srcs.get(id), + } + } + + pub fn struct_from_source(&self, src: StructSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.struct_srcs.get(src), + ContainerSrcMap::Module(container) => container.struct_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.struct_srcs.get(src), + ContainerSrcMap::Block(container) => container.struct_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.struct_srcs.get(src), + } + } + + pub fn source_of_struct(&self, id: StructId) -> Option { + match self { + ContainerSrcMap::File(container) => container.struct_srcs.get(id), + ContainerSrcMap::Module(container) => container.struct_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.struct_srcs.get(id), + ContainerSrcMap::Block(container) => container.struct_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.struct_srcs.get(id), + } + } + + pub fn expr_from_source(&self, src: ExprSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.expr_srcs.get(src), + ContainerSrcMap::Module(container) => container.expr_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.expr_srcs.get(src), + ContainerSrcMap::Block(container) => container.expr_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.expr_srcs.get(src), + } + } + + pub fn source_of_expr(&self, id: ExprId) -> Option { + match self { + ContainerSrcMap::File(container) => container.expr_srcs.get(id), + ContainerSrcMap::Module(container) => container.expr_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.expr_srcs.get(id), + ContainerSrcMap::Block(container) => container.expr_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.expr_srcs.get(id), + } + } + + pub fn event_expr_from_source(&self, src: EventExprSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.event_expr_srcs.get(src), + ContainerSrcMap::Module(container) => container.event_expr_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.event_expr_srcs.get(src), + ContainerSrcMap::Block(container) => container.event_expr_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.event_expr_srcs.get(src), + } + } + + pub fn source_of_event_expr(&self, id: EventExprId) -> Option { + match self { + ContainerSrcMap::File(container) => container.event_expr_srcs.get(id), + ContainerSrcMap::Module(container) => container.event_expr_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.event_expr_srcs.get(id), + ContainerSrcMap::Block(container) => container.event_expr_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.event_expr_srcs.get(id), + } + } + + pub fn declarator_from_source(&self, src: DeclaratorSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.decl_srcs.get(src), + ContainerSrcMap::Module(container) => container.decl_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.decl_srcs.get(src), + ContainerSrcMap::Block(container) => container.decl_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.decl_srcs.get(src), + } + } + + pub fn source_of_declarator(&self, id: DeclId) -> Option { + match self { + ContainerSrcMap::File(container) => container.decl_srcs.get(id), + ContainerSrcMap::Module(container) => container.decl_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.decl_srcs.get(id), + ContainerSrcMap::Block(container) => container.decl_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.decl_srcs.get(id), + } + } + + pub fn stmt_from_source(&self, src: StmtSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Module(container) => container.stmt_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Block(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.stmt_srcs.get(src), + } + } + + pub fn source_of_stmt(&self, id: StmtId) -> Option { + match self { + ContainerSrcMap::File(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Module(container) => container.stmt_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Block(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.stmt_srcs.get(id), + } + } + + pub fn block_from_source(&self, src: BlockSrc) -> Option { + match self { + ContainerSrcMap::File(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Module(container) => container.stmt_srcs.get(src), + ContainerSrcMap::GenerateBlock(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Block(container) => container.stmt_srcs.get(src), + ContainerSrcMap::Subroutine(container) => container.stmt_srcs.get(src), + } + } + + pub fn source_of_block(&self, id: LocalBlockId) -> Option { + match self { + ContainerSrcMap::File(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Module(container) => container.stmt_srcs.get(id), + ContainerSrcMap::GenerateBlock(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Block(container) => container.stmt_srcs.get(id), + ContainerSrcMap::Subroutine(container) => container.stmt_srcs.get(id), + } } } diff --git a/crates/hir/src/def_id.rs b/crates/hir/src/def_id.rs index 26f28d7cf..8fd985891 100644 --- a/crates/hir/src/def_id.rs +++ b/crates/hir/src/def_id.rs @@ -182,12 +182,12 @@ impl DefOrigin { DefOriginLoc::NonAnsiPort(_) => DefKind::NonAnsiPort, DefOriginLoc::Decl(InContainer { value, cont_id }) => { let container = cont_id.data(db); - let decl = container.get(value); + let decl = container.declarator(value); match decl.parent { DeclaratorParent::PortDeclId(_) => DefKind::Port, DeclaratorParent::StmtId(_) => DefKind::Variable, DeclaratorParent::DeclarationId(declaration_id) => { - match container.get(declaration_id) { + match container.declaration(declaration_id) { Declaration::DataDecl(_) => DefKind::Variable, Declaration::NetDecl(_) => DefKind::Net, Declaration::ParamDecl(_) => DefKind::Param, @@ -228,7 +228,8 @@ impl DefOrigin { DefOriginLoc::Block(block_id) => { let BlockLoc { cont_id, src: InFile { value, file_id: _ } } = block_id.lookup(db); let cont = cont_id.data(db); - value.hir(&cont, &cont_id.source_map(db))?.name.clone() + let source_map = cont_id.source_map(db); + cont.block_info(source_map.block_from_source(value)?).name.clone() } DefOriginLoc::GenerateBlock(generate_block_id) => { db.generate_block(generate_block_id).name.clone() @@ -241,10 +242,10 @@ impl DefOrigin { module_id.to_container(db).get(value).label.clone() } DefOriginLoc::Decl(InContainer { value, cont_id }) => { - cont_id.data(db).get(value).name.clone() + cont_id.data(db).declarator(value).name.clone() } DefOriginLoc::Typedef(InContainer { value, cont_id }) => { - cont_id.data(db).get(value).name.clone() + cont_id.data(db).typedef(value).name.clone() } DefOriginLoc::Instance(InModule { value, module_id }) => { module_id.to_container(db).get(value).name.clone() @@ -276,7 +277,7 @@ impl DefOrigin { } DefOriginLoc::Cross(cross) => cross_of(db, cross).and_then(|(cross, _)| cross.name), DefOriginLoc::Stmt(InContainer { value, cont_id }) => { - cont_id.data(db).get(value).label.clone() + cont_id.data(db).stmt(value).label.clone() } } } @@ -336,11 +337,11 @@ impl DefOrigin { Some(InFile::new(module_id.file_id, range)) } DefOriginLoc::Decl(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.name_range()?; + let range = cont_id.source_map(db).source_of_declarator(value)?.name_range()?; Some(InFile::new(cont_id.file_id(db), range)) } DefOriginLoc::Typedef(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.name_range()?; + let range = cont_id.source_map(db).source_of_typedef(value)?.name_range()?; Some(InFile::new(cont_id.file_id(db), range)) } DefOriginLoc::Instance(InModule { value, module_id }) => { @@ -420,7 +421,7 @@ impl DefOrigin { } } DefOriginLoc::Stmt(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.name_range()?; + let range = cont_id.source_map(db).source_of_stmt(value)?.name_range()?; Some(InFile::new(cont_id.file_id(db), range)) } } @@ -478,11 +479,11 @@ impl DefOrigin { InFile::new(module_id.file_id, range) } DefOriginLoc::Decl(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.range(); + let range = cont_id.source_map(db).source_of_declarator(value)?.range(); InFile::new(cont_id.file_id(db), range) } DefOriginLoc::Typedef(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.range(); + let range = cont_id.source_map(db).source_of_typedef(value)?.range(); InFile::new(cont_id.file_id(db), range) } DefOriginLoc::Instance(InModule { value, module_id }) => { @@ -555,7 +556,7 @@ impl DefOrigin { } } DefOriginLoc::Stmt(InContainer { value, cont_id }) => { - let range = cont_id.source_map(db).get(value)?.range(); + let range = cont_id.source_map(db).source_of_stmt(value)?.range(); InFile::new(cont_id.file_id(db), range) } }) @@ -722,5 +723,8 @@ fn is_port_decl_origin(db: &dyn HirDb, origin: DefOrigin) -> bool { let DefOriginLoc::Decl(decl_id) = origin.loc(db) else { return false; }; - matches!(decl_id.cont_id.data(db).get(decl_id.value).parent, DeclaratorParent::PortDeclId(_)) + matches!( + decl_id.cont_id.data(db).declarator(decl_id.value).parent, + DeclaratorParent::PortDeclId(_) + ) } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 83c92b7e1..4f0a1db73 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -2,7 +2,6 @@ use std::fmt::{self, Debug}; use syntax::TimeUnit; use triomphe::Arc; -use utils::get::GetRef; use crate::{ base_db::intern::Lookup, @@ -117,7 +116,7 @@ impl HirDisplay for Ty { Ty::Chandle => f.write_str("chandle"), Ty::Alias { typedef, target } => { let container = typedef.cont_id.data(f.db); - if let Some(name) = &container.get(typedef.value).name { + if let Some(name) = &container.typedef(typedef.value).name { f.write_str(name) } else { target.hir_fmt(f) @@ -170,7 +169,7 @@ fn hir_fmt_def_backed_type( f.write_str(keyword)?; if let DefOriginLoc::Typedef(typedef) = def.primary_origin(f.db).loc(f.db) { let container = typedef.cont_id.data(f.db); - if let Some(name) = &container.get(typedef.value).name { + if let Some(name) = &container.typedef(typedef.value).name { f.write_str(" ")?; f.write_str(name)?; } @@ -304,7 +303,7 @@ impl HirDisplay for InContainer { DataTy::Enum => f.write_str("enum"), DataTy::Struct(struct_ref) => { let cont = struct_ref.cont_id.data(f.db); - let def = cont.get(struct_ref.value); + let def = cont.struct_def(struct_ref.value); let keyword = match def.kind { StructKind::Struct => "struct", StructKind::Union => "union", @@ -370,7 +369,7 @@ impl HirDisplay for InContainer { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { let InContainer { cont_id, value: expr_id } = self; let container = cont_id.data(f.db); - let expr = container.get(*expr_id); + let expr = container.expr(*expr_id); self.with_value(expr).hir_fmt(f) } } @@ -676,7 +675,7 @@ impl HirDisplay for InContainer { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { let InContainer { cont_id, value: decl_id } = self; let container = cont_id.data(f.db); - let decl = container.get(*decl_id); + let decl = container.declarator(*decl_id); if let Some(name) = &decl.name { f.write_str(name)?; @@ -694,7 +693,7 @@ impl HirDisplay for InContainer { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { let InContainer { cont_id, value: typedef_id } = self; let container = cont_id.data(f.db); - let typedef = container.get(*typedef_id); + let typedef = container.typedef(*typedef_id); f.write_str("typedef ")?; if let Some(ty) = typedef.ty { diff --git a/crates/hir/src/hir_def.rs b/crates/hir/src/hir_def.rs index 26c661050..d7996071d 100644 --- a/crates/hir/src/hir_def.rs +++ b/crates/hir/src/hir_def.rs @@ -6,6 +6,7 @@ pub mod declaration; pub mod expr; pub mod file; pub mod literal; +pub(crate) mod lower; pub mod macro_file; pub mod module; pub mod proc; @@ -14,7 +15,45 @@ pub mod subroutine; pub mod ty; pub mod typedef; -use la_arena::{Arena, Idx, RawIdx}; +pub(crate) macro impl_arena_getters( + $container:ty; + $($id:ty => $field:ident => $output:ty),* $(,)? +) { + $( + impl utils::get::GetRef<$id> for $container { + type Output = $output; + + fn get(&self, id: $id) -> &Self::Output { + utils::get::GetRef::get(&self.$field, id) + } + } + )* +} + +pub(crate) macro impl_source_map_getters( + $container:ty; + $($src:ty => $id:ty => $field:ident),* $(,)? +) { + $( + impl utils::get::Get<$src> for $container { + type Output = Option<$id>; + + fn get(&self, src: $src) -> Self::Output { + utils::get::Get::get(&self.$field, src) + } + } + + impl utils::get::Get<$id> for $container { + type Output = Option<$src>; + + fn get(&self, id: $id) -> Self::Output { + utils::get::Get::get(&self.$field, id) + } + } + )* +} + +use la_arena::{Arena, Idx}; use smol_str::{SmolStr, ToSmolStr}; use syntax::{SyntaxToken, TokenKind, ast}; @@ -63,24 +102,48 @@ pub(crate) fn lower_package_imports( .collect() } -macro alloc_idx_and_src($file_id:expr; $hir:expr => $arena:expr, $ast:expr => $src_map:expr $(,)?) {{ - let idx = $arena.alloc($hir.into()); - // HIR lowering can consume include-expanded AST nodes, but source maps only - // store locations that can be navigated in the parsed root file. - if let Some(ast) = $crate::source_map::SourceAst::new($file_id, $ast) { - let src = $crate::source_map::FromSourceAst::from_source_ast(ast); - $src_map.insert(src, idx); +pub(crate) fn alloc_with_optional_source_entry( + data: &mut Arena, + sources: &mut crate::source_map::SourceMap, + value: Input, + source: Option, +) -> Idx +where + Input: Into, + Src: crate::source_map::IsSrc, +{ + let idx = data.alloc(value.into()); + if let Some(source) = source { + sources.insert(source, idx); } idx -}} +} -trait HirData { - fn nxt_idx(&self) -> Idx; +pub(crate) fn alloc_with_source_entry( + data: &mut Arena, + sources: &mut crate::source_map::SourceMap, + value: Input, + source: Src, +) -> Idx +where + Input: Into, + Src: crate::source_map::IsSrc, +{ + alloc_with_optional_source_entry(data, sources, value, Some(source)) } -impl HirData for Arena { - #[inline] - fn nxt_idx(&self) -> Idx { - Idx::from_raw(RawIdx::from(self.len() as u32)) - } +pub(crate) fn alloc_with_source<'ast, Ast, Input, Hir, Src>( + file_id: crate::file::HirFileId, + data: &mut Arena, + sources: &mut crate::source_map::SourceMap, + value: Input, + ast: Ast, +) -> Idx +where + Ast: syntax::ast::AstNode<'ast>, + Input: Into, + Src: crate::source_map::FromSourceAst<'ast, Ast> + crate::source_map::IsSrc, +{ + let source = crate::source_map::SourceAst::new(file_id, ast).map(Src::from_source_ast); + alloc_with_optional_source_entry(data, sources, value, source) } diff --git a/crates/hir/src/hir_def/block.rs b/crates/hir/src/hir_def/block.rs index 5732468a6..9893310d5 100644 --- a/crates/hir/src/hir_def/block.rs +++ b/crates/hir/src/hir_def/block.rs @@ -1,5 +1,4 @@ use la_arena::Arena; -use proc_macro_utils::define_container; use rustc_hash::FxHashMap; use smallvec::SmallVec; use syntax::{ @@ -17,68 +16,101 @@ use utils::{ use super::{ Ident, aggregate::{StructDef, StructId, StructSrc, lower_struct_def}, - alloc_idx_and_src, - declaration::{ - Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, impl_lower_declaration, - }, + alloc_with_source, + declaration::{Declaration, DeclarationId, DeclarationSrc}, expr::{ - Expr, ExprSrc, LowerExpr, - declarator::{Declarator, DeclaratorSrc, impl_lower_decl}, - impl_lower_expr, - timing_control::{EventExpr, EventExprSrc, impl_lower_event_expr}, + Expr, ExprId, ExprSrc, + declarator::{DeclId, Declarator, DeclaratorSrc}, + timing_control::{EventExpr, EventExprId, EventExprSrc}, }, + lower::{BlockStore, LoweringCtx}, lower_ident_opt, - stmt::{LowerStmt, Stmt, StmtId, StmtKind, StmtSrc, impl_lower_stmt}, + stmt::{Stmt, StmtId, StmtKind, StmtSrc}, typedef::{Typedef, TypedefId, TypedefSrc, lower_typedef_data_ty}, }; use crate::{ base_db::intern::Lookup, container::{ArenaOwnerId, InFile}, - db::{HirDb, InternDb}, - file::HirFileId, - region_tree::{RegionTree, RegionTreeBuilder}, + db::HirDb, + region_tree::RegionTree, source_map::{AstKind, IsNamedSrc, IsSrc, NamedAstId, SourceMap, ToAstNode}, }; -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct Block { - name: Option, - kind: BlockKind, - - declarations: [Declaration], - typedefs: [Typedef], - structs: [StructDef], - exprs: [Expr], - event_exprs: [EventExpr], - decls: [Declarator], - stmts: [Stmt] => { - [StmtId | Stmt], - [LocalBlockId | BlockInfo], - } +#[derive(Default, Debug, PartialEq, Eq)] +pub struct Block { + pub name: Option, + pub kind: BlockKind, + pub declarations: Arena, + pub typedefs: Arena, + pub structs: Arena, + pub exprs: Arena, + pub event_exprs: Arena, + pub decls: Arena, + pub stmts: Arena, +} + +impl Block { + pub fn shrink_to_fit(&mut self) { + self.declarations.shrink_to_fit(); + self.typedefs.shrink_to_fit(); + self.structs.shrink_to_fit(); + self.exprs.shrink_to_fit(); + self.event_exprs.shrink_to_fit(); + self.decls.shrink_to_fit(); + self.stmts.shrink_to_fit(); } } -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct BlockSourceMap { - items: SmallVec<[BlockItem; 2]>, - region_tree: RegionTree, - - declaration_srcs: [Declaration | DeclarationSrc], - typedef_srcs: [Typedef | TypedefSrc], - struct_srcs: [StructDef | StructSrc], - expr_srcs: [Expr | ExprSrc], - event_expr_srcs: [EventExpr | EventExprSrc], - decl_srcs: [Declarator | DeclaratorSrc], - stmt_srcs: [Stmt | StmtSrc] => { - [StmtId | StmtSrc], - [LocalBlockId | BlockSrc], - }, - block_srcs: FxHashMap, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct BlockSourceMap { + pub items: SmallVec<[BlockItem; 2]>, + pub region_tree: RegionTree, + pub declaration_srcs: SourceMap, + pub typedef_srcs: SourceMap, + pub struct_srcs: SourceMap, + pub expr_srcs: SourceMap, + pub event_expr_srcs: SourceMap, + pub decl_srcs: SourceMap, + pub stmt_srcs: SourceMap, + pub block_srcs: FxHashMap, +} + +impl BlockSourceMap { + pub fn shrink_to_fit(&mut self) { + self.declaration_srcs.shrink_to_fit(); + self.typedef_srcs.shrink_to_fit(); + self.struct_srcs.shrink_to_fit(); + self.expr_srcs.shrink_to_fit(); + self.event_expr_srcs.shrink_to_fit(); + self.decl_srcs.shrink_to_fit(); + self.stmt_srcs.shrink_to_fit(); } } +crate::hir_def::impl_arena_getters!( + Block; + DeclarationId => declarations => Declaration, + TypedefId => typedefs => Typedef, + StructId => structs => StructDef, + ExprId => exprs => Expr, + EventExprId => event_exprs => EventExpr, + DeclId => decls => Declarator, + StmtId => stmts => Stmt, + LocalBlockId => stmts => BlockInfo, +); + +crate::hir_def::impl_source_map_getters!( + BlockSourceMap; + DeclarationSrc => DeclarationId => declaration_srcs, + TypedefSrc => TypedefId => typedef_srcs, + StructSrc => StructId => struct_srcs, + ExprSrc => ExprId => expr_srcs, + EventExprSrc => EventExprId => event_expr_srcs, + DeclaratorSrc => DeclId => decl_srcs, + StmtSrc => StmtId => stmt_srcs, + BlockSrc => LocalBlockId => stmt_srcs, +); + impl BlockSourceMap { pub fn item_to_ptr(&self, item: &BlockItem) -> Option { Some(match item { @@ -216,63 +248,51 @@ pub struct BlockLoc { pub src: InFile, } -pub(crate) struct LowerBlockCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) block_id: BlockId, - - pub(crate) block: &'a mut Block, - pub(crate) block_source_map: &'a mut BlockSourceMap, - - pub(crate) region_tree: RegionTreeBuilder, -} - -impl_lower_expr!(LowerBlockCtx<'_>, block, block_source_map); -impl_lower_decl!(LowerBlockCtx<'_>, block, block_source_map); -impl_lower_event_expr!(LowerBlockCtx<'_>, block, block_source_map); -impl_lower_stmt!(LowerBlockCtx<'_>, block_id, block, block_source_map); -impl_lower_declaration!(LowerBlockCtx<'_>, block, block_source_map); +pub(crate) type LowerBlockCtx<'a> = LoweringCtx<'a, BlockStore<'a>>; impl LowerBlockCtx<'_> { fn lower_struct_type(&mut self, struct_ty: ast::StructUnionType) -> StructId { - let container_id = ArenaOwnerId::Block(self.block_id); - let struct_def = - lower_struct_def(struct_ty, container_id, |ty| self.expr_ctx().lower_data_ty(ty)); - - alloc_idx_and_src! { - self.file_id; - struct_def => self.block.structs, - struct_ty => self.block_source_map.struct_srcs, - } + let container_id = ArenaOwnerId::Block(self.block_id()); + let struct_def = lower_struct_def(struct_ty, container_id, |ty| self.lower_data_ty(ty)); + + alloc_with_source( + self.file_id, + &mut self.store.data.structs, + &mut self.store.sources.struct_srcs, + struct_def, + struct_ty, + ) } fn lower_typedef(&mut self, typedef: ast::TypedefDeclaration) -> TypedefId { let name = lower_ident_opt(typedef.name()); - let typedef_id = alloc_idx_and_src! { - self.file_id; - Typedef { name, ty: None } => self.block.typedefs, - typedef => self.block_source_map.typedef_srcs, - }; + let typedef_id = alloc_with_source( + self.file_id, + &mut self.store.data.typedefs, + &mut self.store.sources.typedef_srcs, + Typedef { name, ty: None }, + typedef, + ); let data_ty = typedef.type_(); let lowered_ty = lower_typedef_data_ty( self, data_ty, - ArenaOwnerId::Block(self.block_id), + ArenaOwnerId::Block(self.block_id()), |ctx, struct_ty| ctx.lower_struct_type(struct_ty), - |ctx, ty| ctx.expr_ctx().lower_data_ty(ty), + |ctx, ty| ctx.lower_data_ty(ty), ); - self.block.typedefs[typedef_id].ty = Some(lowered_ty); + self.store.data.typedefs[typedef_id].ty = Some(lowered_ty); typedef_id } pub(crate) fn lower_block(&mut self, block: ast::BlockStatement) { // TODO: label? end_block_name? - self.block.name = block.block_name().and_then(|name| lower_ident_opt(name.name())); - self.block.kind = match block.end().map(|end| end.kind()) { + self.store.data.name = block.block_name().and_then(|name| lower_ident_opt(name.name())); + self.store.data.kind = match block.end().map(|end| end.kind()) { Some(TokenKind::JOIN_KEYWORD) => BlockKind::Parallel(ParBlockKind::Join), Some(TokenKind::JOIN_ANY_KEYWORD) => BlockKind::Parallel(ParBlockKind::JoinAny), Some(TokenKind::JOIN_NONE_KEYWORD) => BlockKind::Parallel(ParBlockKind::JoinNone), @@ -282,27 +302,27 @@ impl LowerBlockCtx<'_> { for node in block.items().children() { let idx = match_ast! { node.syntax(), ast::Statement[it] => { - let stmt_id = self.stmt_ctx().lower_stmt(it); + let stmt_id = self.lower_stmt(it); if let Some(block_stmt) = it.as_block_statement() { let block_src = BlockSrc::from_ast(self.file_id, block_stmt); let local_block_id = LocalBlockId(stmt_id); - self.block_source_map.block_srcs.insert(block_src, local_block_id); + self.store.sources.block_srcs.insert(block_src, local_block_id); } stmt_id.into() }, - ast::DataDeclaration[it] => self.declaration_ctx().lower_data_decl(it).into(), + ast::DataDeclaration[it] => self.lower_data_decl(it).into(), ast::ParameterDeclarationStatement[it] => { - self.declaration_ctx().lower_param_decl_base(it.parameter()).into() + self.lower_param_decl_base(it.parameter()).into() }, ast::TypedefDeclaration[it] => self.lower_typedef(it).into(), _ => continue, }; - self.block_source_map.items.push(idx); + self.store.sources.items.push(idx); self.region_tree.handle_node(node.syntax()); } self.region_tree.stage(block.end(), block.syntax()); - self.block_source_map.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.region_tree.finish(); } } @@ -319,15 +339,14 @@ pub(crate) fn block_with_source_map_query( return (Arc::new(block), Arc::new(block_source_map)); }; - let mut lower_ctx = LowerBlockCtx { + let mut lower_ctx = LoweringCtx::new( db, file_id, - block_id, - block: &mut block, - block_source_map: &mut block_source_map, - region_tree: RegionTreeBuilder::new(), - }; + block_id.into(), + BlockStore { data: &mut block, sources: &mut block_source_map }, + ); lower_ctx.lower_block(ast_block); + lower_ctx.emit_diagnostics(); block.shrink_to_fit(); block_source_map.shrink_to_fit(); diff --git a/crates/hir/src/hir_def/checker.rs b/crates/hir/src/hir_def/checker.rs index 292107752..89d5d3c8a 100644 --- a/crates/hir/src/hir_def/checker.rs +++ b/crates/hir/src/hir_def/checker.rs @@ -10,10 +10,10 @@ use syntax::{ use utils::text_edit::TextRange; use super::{ - alloc_idx_and_src, - declaration::{DeclarationId, LowerDeclaration}, - file::LowerFileCtx, - module::{LowerModuleCtx, port::PortDirection}, + alloc_with_source, + declaration::DeclarationId, + lower::{CheckerStore, LoweringCtx}, + module::port::PortDirection, }; use crate::{ hir_def::{Ident, lower_ident_opt}, @@ -95,47 +95,20 @@ pub fn lower_checker_decl(checker: ast::CheckerDeclaration<'_>) -> CheckerDef { } } -pub(crate) trait LowerChecker { - fn lower_checker_decl(&mut self, checker_decl: ast::CheckerDeclaration<'_>) -> CheckerId; -} - -impl LowerChecker for LowerModuleCtx<'_> { - fn lower_checker_decl(&mut self, checker_decl: ast::CheckerDeclaration<'_>) -> CheckerId { +impl LoweringCtx<'_, Store> { + pub(crate) fn lower_checker_decl( + &mut self, + checker_decl: ast::CheckerDeclaration<'_>, + ) -> CheckerId { let mut checker = lower_checker_decl(checker_decl); lower_checker_declarations(&mut checker, checker_decl, |member| match member { - CheckerDeclarationMember::Data(data_decl) => { - self.declaration_ctx().lower_data_decl(data_decl) - } - CheckerDeclarationMember::Net(net_decl) => { - self.declaration_ctx().lower_net_decl(net_decl) - } + CheckerDeclarationMember::Data(data_decl) => self.lower_data_decl(data_decl), + CheckerDeclarationMember::Net(net_decl) => self.lower_net_decl(net_decl), }); - alloc_idx_and_src! { - self.file_id; - checker => self.module.checkers, - checker_decl => self.module_source_map.checker_srcs, - } - } -} - -impl LowerChecker for LowerFileCtx<'_> { - fn lower_checker_decl(&mut self, checker_decl: ast::CheckerDeclaration<'_>) -> CheckerId { - let mut checker = lower_checker_decl(checker_decl); - lower_checker_declarations(&mut checker, checker_decl, |member| match member { - CheckerDeclarationMember::Data(data_decl) => { - self.declaration_ctx().lower_data_decl(data_decl) - } - CheckerDeclarationMember::Net(net_decl) => { - self.declaration_ctx().lower_net_decl(net_decl) - } - }); - - alloc_idx_and_src! { - self.file_id; - checker => self.file.checkers, - checker_decl => self.file_source_map.checker_srcs, - } + let file_id = self.file_id; + let (checkers, sources) = self.store.checkers(); + alloc_with_source(file_id, checkers, sources, checker, checker_decl) } } diff --git a/crates/hir/src/hir_def/declaration.rs b/crates/hir/src/hir_def/declaration.rs index 573cc02d7..61ac052f7 100644 --- a/crates/hir/src/hir_def/declaration.rs +++ b/crates/hir/src/hir_def/declaration.rs @@ -1,30 +1,22 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use syntax::{TokenKind, ast, ptr::SyntaxNodePtr}; use utils::define_enum_deriving_from; use super::expr::{ - declarator::{DeclsRange, impl_lower_decl}, - impl_lower_expr, - timing_control::impl_lower_event_expr, + data_ty::{BuiltinDataTy, DataTy, IntKind}, + declarator::{DeclsRange, empty_decls_range}, + timing_control::DelayControl, }; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - HirData, alloc_idx_and_src, - expr::{ - Expr, ExprSrc, LowerExpr, - data_ty::{BuiltinDataTy, DataTy, IntKind}, - declarator::{Declarator, DeclaratorSrc, LowerDecl}, - timing_control::{DelayControl, EventExpr, EventExprSrc, LowerEventExpr}, - }, + alloc_with_source, + lower::{LoweringCtx, LoweringStore}, ty::{ DriveStrength, NetKind, Strength, lower_drive_strength, lower_net_kind, lower_strength, }, }, source_map::{ - AstId, AstKind, FromSourceAst, IsSrc, SourceAst, SourceMap, ToAstNode, - exact_ast_node_from_ptr, + AstId, AstKind, FromSourceAst, IsSrc, SourceAst, ToAstNode, exact_ast_node_from_ptr, }, }; @@ -323,50 +315,31 @@ pub struct SpecparamDecl { pub decls: DeclsRange, } -pub(crate) struct LowerDeclarationCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) declarations: &'a mut Arena, - pub(crate) declaration_srcs: &'a mut SourceMap, - - pub(crate) decls: &'a mut Arena, - pub(crate) decl_srcs: &'a mut SourceMap, - - pub(crate) event_exprs: &'a mut Arena, - pub(crate) event_expr_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerDeclaration: LowerDecl + LowerEventExpr { - fn declaration_ctx(&mut self) -> LowerDeclarationCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_declaration($ctx:ty, $data:ident, $src_map:ident) { - impl $crate::hir_def::declaration::LowerDeclaration for $ctx { - fn declaration_ctx(&mut self) -> $crate::hir_def::declaration::LowerDeclarationCtx<'_> { - $crate::hir_def::declaration::LowerDeclarationCtx { - db: self.db, - file_id: self.file_id, - declarations: &mut self.$data.declarations, - declaration_srcs: &mut self.$src_map.declaration_srcs, - decls: &mut self.$data.decls, - decl_srcs: &mut self.$src_map.decl_srcs, - event_exprs: &mut self.$data.event_exprs, - event_expr_srcs: &mut self.$src_map.event_expr_srcs, - exprs: &mut self.$data.exprs, - expr_srcs: &mut self.$src_map.expr_srcs, - } +impl LoweringCtx<'_, Store> { + pub(crate) fn alloc_declaration<'ast, Ast>( + &mut self, + declaration: impl Into, + ast: Ast, + ) -> DeclarationId + where + Ast: syntax::ast::AstNode<'ast>, + DeclarationSrc: FromSourceAst<'ast, Ast>, + { + let file_id = self.file_id; + let (declarations, sources) = self.declarations(); + alloc_with_source(file_id, declarations, sources, declaration, ast) + } + + pub(crate) fn finish_declaration_decls(&mut self, id: DeclarationId, decls: DeclsRange) { + match &mut self.declarations().0[id] { + Declaration::DataDecl(declaration) => declaration.decls = decls, + Declaration::NetDecl(declaration) => declaration.decls = decls, + Declaration::ParamDecl(declaration) => declaration.decls = decls, + Declaration::GenvarDecl(declaration) => declaration.decls = decls, + Declaration::SpecparamDecl(declaration) => declaration.decls = decls, } } -} -impl_lower_expr!(LowerDeclarationCtx<'_>); -impl_lower_decl!(LowerDeclarationCtx<'_>); -impl_lower_event_expr!(LowerDeclarationCtx<'_>); - -impl LowerDeclarationCtx<'_> { pub(crate) fn lower_data_decl(&mut self, data_decl: ast::DataDeclaration) -> DeclarationId { let mut const_kw = false; let mut var_kw = false; @@ -377,32 +350,28 @@ impl LowerDeclarationCtx<'_> { _ => {} }); - let ty = self.expr_ctx().lower_data_ty(data_decl.type_()); - - let parent = self.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_declarators(data_decl.declarators(), parent); + let ty = self.lower_data_ty(data_decl.type_()); - alloc_idx_and_src! { - self.file_id; - DataDecl { ty, const_kw, var_kw, decls } => self.declarations, - data_decl => self.declaration_srcs, - } + let parent = self.alloc_declaration( + DataDecl { ty, const_kw, var_kw, decls: empty_decls_range() }, + data_decl, + ); + let decls = self.lower_declarators(data_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } pub(crate) fn lower_net_decl(&mut self, net_decl: ast::NetDeclaration) -> DeclarationId { let net_kind = lower_net_kind(net_decl.net_type()); - let ty = self.expr_ctx().lower_data_ty(net_decl.type_()); + let ty = self.lower_data_ty(net_decl.type_()); let delay = net_decl.delay().and_then(|delay| { use crate::hir_def::expr::timing_control::TimingControl::*; - match self.event_expr_ctx().lower_timing_control(delay) { + match self.lower_timing_control(delay) { DelayControl(delay) => Some(delay), _ => None, } }); - let parent = self.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_declarators(net_decl.declarators(), parent); - let strength = net_decl.strength().and_then(|strength| { use ast::NetStrength::*; match strength { @@ -416,11 +385,13 @@ impl LowerDeclarationCtx<'_> { } }); - alloc_idx_and_src! { - self.file_id; - NetDecl { ty, net_kind, delay, strength, decls } => self.declarations, - net_decl => self.declaration_srcs, - } + let parent = self.alloc_declaration( + NetDecl { ty, net_kind, delay, strength, decls: empty_decls_range() }, + net_decl, + ); + let decls = self.lower_declarators(net_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } pub(crate) fn lower_port_decl_as_data_decl( @@ -429,19 +400,18 @@ impl LowerDeclarationCtx<'_> { ) -> Option { use ast::PortHeader::*; let ty = match port_decl.header() { - VariablePortHeader(header) => self.expr_ctx().lower_data_ty(header.data_type()), - NetPortHeader(header) => self.expr_ctx().lower_data_ty(header.data_type()), + VariablePortHeader(header) => self.lower_data_ty(header.data_type()), + NetPortHeader(header) => self.lower_data_ty(header.data_type()), InterfacePortHeader(_) => return None, }; - let parent = self.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_declarators(port_decl.declarators(), parent); - - Some(alloc_idx_and_src! { - self.file_id; - DataDecl { ty, const_kw: false, var_kw: false, decls } => self.declarations, - port_decl => self.declaration_srcs, - }) + let parent = self.alloc_declaration( + DataDecl { ty, const_kw: false, var_kw: false, decls: empty_decls_range() }, + port_decl, + ); + let decls = self.lower_declarators(port_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + Some(parent) } pub(crate) fn lower_param_decl_base( @@ -481,17 +451,12 @@ impl LowerDeclarationCtx<'_> { inherited_kind, force_local, ); - let start = self.decls.nxt_idx(); + let decls = empty_decls_range(); let ty = DataTy::Builtin( self.db.intern_ty(crate::hir_def::expr::data_ty::BuiltinDataTy::default()), ); - let decls = DeclsRange::new(start..self.decls.nxt_idx()); - alloc_idx_and_src! { - self.file_id; - ParamDecl { ty, kind, is_port, decls } => self.declarations, - type_param_decl => self.declaration_srcs, - } + self.alloc_declaration(ParamDecl { ty, kind, is_port, decls }, type_param_decl) } fn lower_param_decl( @@ -506,16 +471,15 @@ impl LowerDeclarationCtx<'_> { inherited_kind, force_local, ); - let ty = self.expr_ctx().lower_data_ty(param_decl.type_()); + let ty = self.lower_data_ty(param_decl.type_()); - let parent = self.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_declarators(param_decl.declarators(), parent); - - alloc_idx_and_src! { - self.file_id; - ParamDecl { ty, kind, is_port, decls } => self.declarations, - param_decl => self.declaration_srcs, - } + let parent = self.alloc_declaration( + ParamDecl { ty, kind, is_port, decls: empty_decls_range() }, + param_decl, + ); + let decls = self.lower_declarators(param_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } pub(crate) fn lower_genvar_decl( @@ -525,30 +489,23 @@ impl LowerDeclarationCtx<'_> { let ty = DataTy::Builtin( self.db.intern_ty(BuiltinDataTy::Int { kind: IntKind::Integer, signing: true }), ); - let parent = self.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_identifier_names(genvar_decl.identifiers(), parent); - - alloc_idx_and_src! { - self.file_id; - GenvarDecl { ty, decls } => self.declarations, - genvar_decl => self.declaration_srcs, - } + let parent = + self.alloc_declaration(GenvarDecl { ty, decls: empty_decls_range() }, genvar_decl); + let decls = self.lower_identifier_names(genvar_decl.identifiers(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } pub(crate) fn lower_specparam_decl( &mut self, specparam_decl: ast::SpecparamDeclaration, ) -> DeclarationId { - let ty = self.expr_ctx().lower_implicit_data_ty(specparam_decl.type_()); - let parent = self.declarations.nxt_idx().into(); - let decls = - self.decl_ctx().lower_specparam_declarators(specparam_decl.declarators(), parent); - - alloc_idx_and_src! { - self.file_id; - SpecparamDecl { ty, decls } => self.declarations, - specparam_decl => self.declaration_srcs, - } + let ty = self.lower_implicit_data_ty(specparam_decl.type_()); + let parent = self + .alloc_declaration(SpecparamDecl { ty, decls: empty_decls_range() }, specparam_decl); + let decls = self.lower_specparam_declarators(specparam_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } } diff --git a/crates/hir/src/hir_def/expr.rs b/crates/hir/src/hir_def/expr.rs index 252920fcb..fb7588c8f 100644 --- a/crates/hir/src/hir_def/expr.rs +++ b/crates/hir/src/hir_def/expr.rs @@ -1,19 +1,21 @@ use data_ty::DataTy; use itertools::Itertools; -use la_arena::{Arena, Idx}; +use la_arena::Idx; use syntax::{ SyntaxKind, TokenKind, ast::{self, AstNode}, + has_text_range::HasTextRange, }; use super::literal::{Literal, lower_literal}; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - Ident, alloc_idx_and_src, literal::lower_integer_vector, lower_ident, lower_ident_opt, + Ident, alloc_with_source, alloc_with_source_entry, + literal::lower_integer_vector, + lower::{LoweringCtx, LoweringStore}, + lower_ident, lower_ident_opt, }, - source_map::{AstId, AstKind, SourceMap}, + source_map::{AstId, AstKind}, }; pub mod data_ty; @@ -283,44 +285,19 @@ pub enum Selector { Descending(ExprId, ExprId), } -pub(crate) trait LowerExpr { - fn expr_ctx(&mut self) -> LowerExprCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_expr { - ($ctx:ty $(,$data:ident, $src_map:ident)?) => { - impl $crate::hir_def::expr::LowerExpr for $ctx { - fn expr_ctx(&mut self) -> $crate::hir_def::expr::LowerExprCtx<'_> { - $crate::hir_def::expr::LowerExprCtx { - db: self.db, - file_id: self.file_id, - exprs: &mut self.$($data.)?exprs, - expr_srcs: &mut self.$($src_map.)?expr_srcs, - } - } - } - }, -} - -pub(crate) struct LowerExprCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -impl LowerExprCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_expr_opt(&mut self, expr: Option) -> ExprId { - if let Some(expr) = expr { self.lower_expr(expr) } else { self.alloc_missing() } + if let Some(expr) = expr { self.lower_expr(expr) } else { self.alloc_missing_expr() } } pub(crate) fn lower_expr(&mut self, expr: ast::Expression) -> ExprId { let hir_expr = self.lower_expr_inner(expr).unwrap_or(Expr::Invalid); - alloc_idx_and_src! { - self.file_id; - hir_expr => self.exprs, - expr => self.expr_srcs, + if let Expr::Unsupported(kind) = &hir_expr { + self.report_unsupported(*kind, expr.syntax().text_range(), "unsupported expression"); } + let file_id = self.file_id; + let (expressions, sources) = self.expressions(); + alloc_with_source(file_id, expressions, sources, hir_expr, expr) } fn lower_expr_inner(&mut self, expr: ast::Expression) -> Option { @@ -396,7 +373,7 @@ impl LowerExprCtx<'_> { fn lower_name(&mut self, name: ast::Name) -> Option { fn lower_ident_select( - ctx: &mut LowerExprCtx, + ctx: &mut LoweringCtx<'_, impl LoweringStore>, ident_select: ast::IdentifierSelectName, ) -> Option { let mut expr = @@ -418,8 +395,8 @@ impl LowerExprCtx<'_> { loop { match selectors.next() { select @ Some(_) => { - let receiver = ctx.exprs.alloc(expr); - ctx.expr_srcs.insert(src, receiver); + let (expressions, sources) = ctx.expressions(); + let receiver = alloc_with_source_entry(expressions, sources, expr, src); expr = Expr::ElementSelect { receiver, select }; } None => return Some(expr), @@ -439,7 +416,7 @@ impl LowerExprCtx<'_> { ast::Name::ScopedName(scoped) => { let receiver = ast::Expression::cast(scoped.left().syntax()) .map(|left| self.lower_expr(left)) - .unwrap_or_else(|| self.alloc_missing()); + .unwrap_or_else(|| self.alloc_missing_expr()); match scoped.right() { IdentifierName(ident) => { @@ -585,7 +562,7 @@ impl LowerExprCtx<'_> { let expr = ast::Expression::cast(expr.right().syntax()) .map(|right| self.lower_expr(right)) - .unwrap_or_else(|| self.alloc_missing()); + .unwrap_or_else(|| self.alloc_missing_expr()); Some(Expr::Cast { ty, expr }) } @@ -598,7 +575,7 @@ impl LowerExprCtx<'_> { let expr = ast::Expression::cast(expr.inner().syntax()) .map(|inner| self.lower_expr(inner)) - .unwrap_or_else(|| self.alloc_missing()); + .unwrap_or_else(|| self.alloc_missing_expr()); Some(Expr::SignedCast { signed, expr }) } @@ -623,7 +600,7 @@ impl LowerExprCtx<'_> { let name = lower_ident_opt(arg.name()); let expr = match arg.expr() { Some(expr) => self.lower_property_expr(expr), - None => self.alloc_missing(), + None => self.alloc_missing_expr(), }; Arg::Named { name, expr } } @@ -657,14 +634,14 @@ impl LowerExprCtx<'_> { } } - fn alloc_missing(&mut self) -> ExprId { - self.exprs.alloc(Expr::Missing) + fn alloc_missing_expr(&mut self) -> ExprId { + self.expressions().0.alloc(Expr::Missing) } } -impl LowerExprCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_property_expr(&mut self, expr: ast::PropertyExpr) -> ExprId { - self.lower_property_expr_inner(expr).unwrap_or_else(|| self.alloc_missing()) + self.lower_property_expr_inner(expr).unwrap_or_else(|| self.alloc_missing_expr()) } pub(crate) fn lower_property_expr_inner(&mut self, expr: ast::PropertyExpr) -> Option { diff --git a/crates/hir/src/hir_def/expr/data_ty.rs b/crates/hir/src/hir_def/expr/data_ty.rs index 9afec48fa..6f77b8ce0 100644 --- a/crates/hir/src/hir_def/expr/data_ty.rs +++ b/crates/hir/src/hir_def/expr/data_ty.rs @@ -5,10 +5,14 @@ use syntax::{ ast::{self, AstNode}, }; -use super::{Expr, ExprId, LowerExprCtx, Selector}; +use super::{Expr, ExprId, Selector}; use crate::{ container::InContainer, - hir_def::{aggregate::StructId, lower_ident}, + hir_def::{ + aggregate::StructId, + lower::{LoweringCtx, LoweringStore}, + lower_ident, + }, }; // slang exposes enum types directly as `DataType::EnumType`, while struct and @@ -91,7 +95,7 @@ pub enum NamedDataTy { Field(ExprId), } -impl LowerExprCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_data_ty(&mut self, ty: ast::DataType) -> DataTy { use ast::DataType::*; match ty { @@ -123,7 +127,7 @@ impl LowerExprCtx<'_> { fn lower_named_ty(&mut self, ty: ast::NamedType) -> NamedDataTy { let expr_id = ast::Expression::cast(ty.name().syntax()) .map(|expr| self.lower_expr(expr)) - .unwrap_or_else(|| self.alloc_missing()); + .unwrap_or_else(|| self.alloc_missing_expr()); use ast::Name::*; match ty.name() { @@ -199,7 +203,7 @@ impl LowerExprCtx<'_> { if let Some(key) = Self::associative_dimension_key_token(expr) { let expr_id = lower_ident(Some(key)) .map(Expr::Ident) - .map(|expr| self.exprs.alloc(expr)) + .map(|expr| self.expressions().0.alloc(expr)) .unwrap_or_else(|| self.lower_expr(expr)); return Some(Dimension::Assoc(expr_id)); } diff --git a/crates/hir/src/hir_def/expr/declarator.rs b/crates/hir/src/hir_def/expr/declarator.rs index df60d9af4..f1a40bf03 100644 --- a/crates/hir/src/hir_def/expr/declarator.rs +++ b/crates/hir/src/hir_def/expr/declarator.rs @@ -1,18 +1,20 @@ -use la_arena::{Arena, Idx, IdxRange}; +use la_arena::{Idx, IdxRange, RawIdx}; use smallvec::SmallVec; use syntax::{TokenKind, ast}; use utils::define_enum_deriving_from; -use super::{Expr, ExprId, ExprSrc, LowerExpr, data_ty::Dimension, impl_lower_expr}; +use super::{ExprId, data_ty::Dimension}; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - HirData, Ident, alloc_idx_and_src, declaration::DeclarationId, lower_ident_opt, - module::port::PortDeclId, stmt::StmtId, + Ident, alloc_with_source, + declaration::DeclarationId, + lower::{LoweringCtx, LoweringStore}, + lower_ident_opt, + module::port::PortDeclId, + stmt::StmtId, }, source_map::{ - AstKind, FromSourceAst, IsNamedSrc, IsSrc, NamedAstId, SourceAst, SourceMap, ToAstNode, + AstKind, FromSourceAst, IsNamedSrc, IsSrc, NamedAstId, SourceAst, ToAstNode, wrapped_ast_node_from_ptr, }, }; @@ -36,6 +38,11 @@ define_enum_deriving_from! { } pub type DeclId = Idx; + +pub(crate) fn empty_decls_range() -> DeclsRange { + let start = Idx::from_raw(RawIdx::from(0)); + DeclsRange::new(start..start) +} pub type DeclsRange = IdxRange; #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] @@ -143,51 +150,13 @@ impl<'a> FromSourceAst<'a, ast::SpecparamDeclarator<'a>> for DeclaratorSrc { } } -pub(crate) struct LowerDeclCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) decls: &'a mut Arena, - pub(crate) decl_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerDecl: LowerExpr { - fn decl_ctx(&mut self) -> LowerDeclCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_decl { - ($ctx:ty $(,$data:ident, $src_map:ident)?) => { - impl $crate::hir_def::expr::declarator::LowerDecl for $ctx { - fn decl_ctx(&mut self) -> $crate::hir_def::expr::declarator::LowerDeclCtx<'_> { - $crate::hir_def::expr::declarator::LowerDeclCtx { - db: self.db, - file_id: self.file_id, - decls: &mut self.$($data.)?decls, - decl_srcs: &mut self.$($src_map.)?decl_srcs, - exprs: &mut self.$($data.)?exprs, - expr_srcs: &mut self.$($src_map.)?expr_srcs, - } - } - } - }, -} - -impl_lower_expr!(LowerDeclCtx<'_>); - -impl LowerDeclCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_declarators<'a>( &mut self, declarators: ast::SeparatedList<'a, ast::Declarator<'a>>, parent: DeclaratorParent, ) -> DeclsRange { - let start = self.decls.nxt_idx(); - declarators.children().for_each(|decl| { - self.lower_declarator(decl, parent); - }); - let end = self.decls.nxt_idx(); - DeclsRange::new(start..end) + decls_range(declarators.children().map(|decl| self.lower_declarator(decl, parent))) } pub(crate) fn lower_declarator( @@ -196,24 +165,14 @@ impl LowerDeclCtx<'_> { parent: DeclaratorParent, ) -> DeclId { let name = lower_ident_opt(declarator.name()); - let dimensions = declarator - .dimensions() - .children() - .map(|dim| self.expr_ctx().lower_dimension(dim)) - .collect(); - let initializer = - declarator.initializer().map(|init| self.expr_ctx().lower_expr(init.expr())); - alloc_idx_and_src! { - self.file_id; - Declarator { - name, - dimensions, - initializer, - secondary_initializer: None, - parent - } => self.decls, - declarator => self.decl_srcs, - } + let dimensions = + declarator.dimensions().children().map(|dim| self.lower_dimension(dim)).collect(); + let initializer = declarator.initializer().map(|init| self.lower_expr(init.expr())); + let data = + Declarator { name, dimensions, initializer, secondary_initializer: None, parent }; + let file_id = self.file_id; + let (declarators, sources) = self.declarators(); + alloc_with_source(file_id, declarators, sources, data, declarator) } pub(crate) fn lower_identifier_names<'a>( @@ -221,12 +180,7 @@ impl LowerDeclCtx<'_> { identifiers: ast::SeparatedList<'a, ast::IdentifierName<'a>>, parent: DeclaratorParent, ) -> DeclsRange { - let start = self.decls.nxt_idx(); - identifiers.children().for_each(|ident| { - self.lower_identifier_name(ident, parent); - }); - let end = self.decls.nxt_idx(); - DeclsRange::new(start..end) + decls_range(identifiers.children().map(|ident| self.lower_identifier_name(ident, parent))) } fn lower_identifier_name( @@ -235,17 +189,16 @@ impl LowerDeclCtx<'_> { parent: DeclaratorParent, ) -> DeclId { let name = lower_ident_opt(ident.identifier()); - alloc_idx_and_src! { - self.file_id; - Declarator { - name, - dimensions: SmallVec::new(), - initializer: None, - secondary_initializer: None, - parent - } => self.decls, - ident => self.decl_srcs, - } + let data = Declarator { + name, + dimensions: SmallVec::new(), + initializer: None, + secondary_initializer: None, + parent, + }; + let file_id = self.file_id; + let (declarators, sources) = self.declarators(); + alloc_with_source(file_id, declarators, sources, data, ident) } pub(crate) fn lower_specparam_declarators<'a>( @@ -253,12 +206,9 @@ impl LowerDeclCtx<'_> { declarators: ast::SeparatedList<'a, ast::SpecparamDeclarator<'a>>, parent: DeclaratorParent, ) -> DeclsRange { - let start = self.decls.nxt_idx(); - declarators.children().for_each(|decl| { - self.lower_specparam_declarator(decl, parent); - }); - let end = self.decls.nxt_idx(); - DeclsRange::new(start..end) + decls_range( + declarators.children().map(|decl| self.lower_specparam_declarator(decl, parent)), + ) } fn lower_specparam_declarator( @@ -267,19 +217,25 @@ impl LowerDeclCtx<'_> { parent: DeclaratorParent, ) -> DeclId { let name = lower_ident_opt(declarator.name()); - let initializer = Some(self.expr_ctx().lower_expr(declarator.value_1())); - let secondary_initializer = - declarator.value_2().map(|expr| self.expr_ctx().lower_expr(expr)); - alloc_idx_and_src! { - self.file_id; - Declarator { - name, - dimensions: SmallVec::new(), - initializer, - secondary_initializer, - parent - } => self.decls, - declarator => self.decl_srcs, - } - } + let initializer = Some(self.lower_expr(declarator.value_1())); + let secondary_initializer = declarator.value_2().map(|expr| self.lower_expr(expr)); + let data = Declarator { + name, + dimensions: SmallVec::new(), + initializer, + secondary_initializer, + parent, + }; + let file_id = self.file_id; + let (declarators, sources) = self.declarators(); + alloc_with_source(file_id, declarators, sources, data, declarator) + } +} + +fn decls_range(mut ids: impl Iterator) -> DeclsRange { + let Some(first) = ids.next() else { + return empty_decls_range(); + }; + let last = ids.last().unwrap_or(first); + DeclsRange::new_inclusive(first..=last) } diff --git a/crates/hir/src/hir_def/expr/timing_control.rs b/crates/hir/src/hir_def/expr/timing_control.rs index 83a7b7a94..096781c56 100644 --- a/crates/hir/src/hir_def/expr/timing_control.rs +++ b/crates/hir/src/hir_def/expr/timing_control.rs @@ -1,13 +1,14 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use smallvec::SmallVec; use syntax::{TokenKind, ast}; -use super::{Expr, ExprId, ExprSrc, LowerExpr, impl_lower_expr}; +use super::ExprId; use crate::{ - db::InternDb, - file::HirFileId, - hir_def::alloc_idx_and_src, - source_map::{AstId, AstKind, SourceMap}, + hir_def::{ + alloc_with_source, + lower::{LoweringCtx, LoweringStore}, + }, + source_map::{AstId, AstKind}, }; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -61,47 +62,12 @@ pub enum Sensitivity { Edge, } -pub(crate) struct LowerEventExprCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) event_exprs: &'a mut Arena, - pub(crate) event_expr_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerEventExpr: LowerExpr { - fn event_expr_ctx(&mut self) -> LowerEventExprCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_event_expr { - ($ctx:ty $(,$data:ident, $src_map:ident)?) => { - impl $crate::hir_def::expr::timing_control::LowerEventExpr for $ctx { - fn event_expr_ctx(&mut self) -> $crate::hir_def::expr::timing_control::LowerEventExprCtx<'_> { - $crate::hir_def::expr::timing_control::LowerEventExprCtx { - db: self.db, - file_id: self.file_id, - event_exprs: &mut self.$($data.)?event_exprs, - event_expr_srcs: &mut self.$($src_map.)?event_expr_srcs, - exprs: &mut self.$($data.)?exprs, - expr_srcs: &mut self.$($src_map.)?expr_srcs, - } - } - } - } -} - -impl_lower_expr!(LowerEventExprCtx<'_>); - -impl LowerEventExprCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_event_expr(&mut self, event_expr: ast::EventExpression) -> EventExprId { let hir_event_expr = self.lower_event_expr_inner(event_expr); - alloc_idx_and_src! { - self.file_id; - hir_event_expr => self.event_exprs, - event_expr => self.event_expr_srcs, - } + let file_id = self.file_id; + let (event_expressions, sources) = self.event_expressions(); + alloc_with_source(file_id, event_expressions, sources, hir_event_expr, event_expr) } fn lower_event_expr_inner(&mut self, event_expr: ast::EventExpression) -> EventExpr { @@ -132,13 +98,13 @@ impl LowerEventExprCtx<'_> { TokenKind::EDGE_KEYWORD => Some(Sensitivity::Edge), _ => None, }); - let expr = self.expr_ctx().lower_expr(event_expr.expr()); - let iff = event_expr.iff_clause().map(|iff| self.expr_ctx().lower_expr(iff.expr())); + let expr = self.lower_expr(event_expr.expr()); + let iff = event_expr.iff_clause().map(|iff| self.lower_expr(iff.expr())); EventExpr::Atom { sensitivity, expr, iff } } } -impl LowerEventExprCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_timing_control(&mut self, control: ast::TimingControl) -> TimingControl { match control { ast::TimingControl::OneStepDelay(_) => { @@ -166,7 +132,7 @@ impl LowerEventExprCtx<'_> { } fn lower_delay(&mut self, delay: ast::Delay) -> DelayControl { - let val = self.expr_ctx().lower_expr(delay.delay_value()); + let val = self.lower_expr(delay.delay_value()); match delay { ast::Delay::CycleDelay(_) | ast::Delay::DelayControl(_) => DelayControl::Value(val), @@ -175,14 +141,14 @@ impl LowerEventExprCtx<'_> { fn lower_delay3(&mut self, delay: ast::Delay3) -> DelayControl { let mut delays = SmallVec::new(); - delays.push(self.expr_ctx().lower_expr(delay.delay_1())); + delays.push(self.lower_expr(delay.delay_1())); if let Some(delay_2) = delay.delay_2() { - delays.push(self.expr_ctx().lower_expr(delay_2)); + delays.push(self.lower_expr(delay_2)); } if let Some(delay_3) = delay.delay_3() { - delays.push(self.expr_ctx().lower_expr(delay_3)); + delays.push(self.lower_expr(delay_3)); } DelayControl::Delay3(delays) @@ -196,14 +162,14 @@ impl LowerEventExprCtx<'_> { } fn lower_event_control(&mut self, event_control: ast::EventControl) -> EventControl { - EventControl::Event(self.expr_ctx().lower_expr(event_control.event_name())) + EventControl::Event(self.lower_expr(event_control.event_name())) } fn lower_repeated_event_control( &mut self, event_control: ast::RepeatedEventControl, ) -> TimingControl { - let expr = self.expr_ctx().lower_expr(event_control.expr()); + let expr = self.lower_expr(event_control.expr()); let event_control = event_control.event_control().and_then(|control| { match self.lower_timing_control(control) { TimingControl::EventControl(event_control) => Some(event_control), diff --git a/crates/hir/src/hir_def/file.rs b/crates/hir/src/hir_def/file.rs index 967eb4040..f6a6b6d80 100644 --- a/crates/hir/src/hir_def/file.rs +++ b/crates/hir/src/hir_def/file.rs @@ -1,9 +1,8 @@ use config::{ConfigDecl, ConfigDeclId, ConfigDeclSrc}; -use la_arena::Arena; +use la_arena::{Arena, Idx}; use library::{ LibraryDecl, LibraryDeclId, LibraryDeclSrc, LibraryInclude, LibraryIncludeId, LibraryIncludeSrc, }; -use proc_macro_utils::define_container; use smallvec::SmallVec; use syntax::{ ast::{self, AstNode}, @@ -16,38 +15,35 @@ use utils::{define_enum_deriving_from, get::Get}; use super::{ PackageImport, aggregate::{StructDef, StructId, StructSrc, lower_struct_def}, - alloc_idx_and_src, + alloc_with_source, block::{BlockInfo, BlockSrc, LocalBlockId}, - checker::{CheckerDef, CheckerId, CheckerSrc, LowerChecker}, + checker::{CheckerDef, CheckerId, CheckerSrc}, covergroup::{ - CovergroupDef, CovergroupId, CovergroupSrc, CoverpointDef, CoverpointSrc, CrossDef, - CrossSrc, lower_covergroup_decl, lower_coverpoint, lower_cross, - }, - declaration::{ - Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, impl_lower_declaration, + CovergroupDef, CovergroupId, CovergroupSrc, CoverpointDef, CoverpointId, CoverpointSrc, + CrossDef, CrossId, CrossSrc, lower_covergroup_decl, lower_coverpoint, lower_cross, }, + declaration::{Declaration, DeclarationId, DeclarationSrc}, expr::{ - Expr, ExprSrc, LowerExpr, - declarator::{Declarator, DeclaratorSrc, impl_lower_decl}, - impl_lower_expr, - timing_control::{EventExpr, EventExprSrc, impl_lower_event_expr}, + Expr, ExprId, ExprSrc, + declarator::{DeclId, Declarator, DeclaratorSrc}, + timing_control::{EventExpr, EventExprId, EventExprSrc}, }, + lower::{FileStore, LoweringCtx, SubroutineStore}, lower_package_imports, module::{LocalModuleId, ModuleInfo, ModuleKind, ModuleSrc}, - proc::{LowerProc, LowerProcCtx, Proc, ProcId, ProcSrc}, - stmt::{Stmt, StmtId, StmtSrc, impl_lower_stmt}, + proc::{Proc, ProcId, ProcSrc}, + stmt::{Stmt, StmtId, StmtSrc}, subroutine::{ - LocalSubroutineId, LowerSubroutineBodyCtx, Subroutine, SubroutineSrc, lower_subroutine, - lower_subroutine_body, + LocalSubroutineId, Subroutine, SubroutineSrc, lower_subroutine, lower_subroutine_body, }, typedef::{Typedef, TypedefId, TypedefSrc, lower_typedef_data_ty}, }; use crate::{ container::{ArenaOwnerId, SubroutineParent, SubroutineScope}, - db::{HirDb, InternDb}, + db::HirDb, file::HirFileId, hir_def::lower_ident_opt, - region_tree::{RegionTree, RegionTreeBuilder}, + region_tree::RegionTree, source_map::SourceMap, }; @@ -55,67 +51,147 @@ pub mod config; pub mod library; pub mod udp; -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct HirFile { - modules: [ModuleInfo], - procs: [Proc], - - typedefs: [Typedef], - structs: [StructDef], - config_decls: [ConfigDecl], - udp_decls: [UdpDecl], - library_decls: [LibraryDecl], - library_includes: [LibraryInclude], - checkers: [CheckerDef], - covergroups: [CovergroupDef], - coverpoints: [CoverpointDef], - crosses: [CrossDef], - subroutines: [Subroutine], - package_imports: [PackageImport], - - declarations: [Declaration], - exprs: [Expr], - event_exprs: [EventExpr], - decls: [Declarator], - stmts: [Stmt] => { - [StmtId | Stmt], - [LocalBlockId | BlockInfo], - }, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct HirFile { + pub modules: Arena, + pub procs: Arena, + pub typedefs: Arena, + pub structs: Arena, + pub config_decls: Arena, + pub udp_decls: Arena, + pub library_decls: Arena, + pub library_includes: Arena, + pub checkers: Arena, + pub covergroups: Arena, + pub coverpoints: Arena, + pub crosses: Arena, + pub subroutines: Arena, + pub package_imports: Arena, + pub declarations: Arena, + pub exprs: Arena, + pub event_exprs: Arena, + pub decls: Arena, + pub stmts: Arena, +} + +impl HirFile { + pub fn shrink_to_fit(&mut self) { + self.modules.shrink_to_fit(); + self.procs.shrink_to_fit(); + self.typedefs.shrink_to_fit(); + self.structs.shrink_to_fit(); + self.config_decls.shrink_to_fit(); + self.udp_decls.shrink_to_fit(); + self.library_decls.shrink_to_fit(); + self.library_includes.shrink_to_fit(); + self.checkers.shrink_to_fit(); + self.covergroups.shrink_to_fit(); + self.coverpoints.shrink_to_fit(); + self.crosses.shrink_to_fit(); + self.subroutines.shrink_to_fit(); + self.package_imports.shrink_to_fit(); + self.declarations.shrink_to_fit(); + self.exprs.shrink_to_fit(); + self.event_exprs.shrink_to_fit(); + self.decls.shrink_to_fit(); + self.stmts.shrink_to_fit(); } } -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct FileSourceMap { - items: SmallVec<[FileItem; 3]>, - region_tree: RegionTree, - - module_srcs: [ModuleInfo | ModuleSrc], - proc_srcs: [Proc | ProcSrc], - - declaration_srcs: [Declaration | DeclarationSrc], - typedef_srcs: [Typedef | TypedefSrc], - struct_srcs: [StructDef | StructSrc], - config_decl_srcs: [ConfigDecl | ConfigDeclSrc], - udp_decl_srcs: [UdpDecl | UdpDeclSrc], - library_decl_srcs: [LibraryDecl | LibraryDeclSrc], - library_include_srcs: [LibraryInclude | LibraryIncludeSrc], - checker_srcs: [CheckerDef | CheckerSrc], - covergroup_srcs: [CovergroupDef | CovergroupSrc], - coverpoint_srcs: [CoverpointDef | CoverpointSrc], - cross_srcs: [CrossDef | CrossSrc], - subroutine_srcs: [Subroutine | SubroutineSrc], - expr_srcs: [Expr | ExprSrc], - event_expr_srcs: [EventExpr | EventExprSrc], - decl_srcs: [Declarator | DeclaratorSrc], - stmt_srcs: [Stmt | StmtSrc] => { - [StmtId | StmtSrc], - [LocalBlockId | BlockSrc], - } +#[derive(Default, Debug, PartialEq, Eq)] +pub struct FileSourceMap { + pub items: SmallVec<[FileItem; 3]>, + pub region_tree: RegionTree, + pub module_srcs: SourceMap, + pub proc_srcs: SourceMap, + pub declaration_srcs: SourceMap, + pub typedef_srcs: SourceMap, + pub struct_srcs: SourceMap, + pub config_decl_srcs: SourceMap, + pub udp_decl_srcs: SourceMap, + pub library_decl_srcs: SourceMap, + pub library_include_srcs: SourceMap, + pub checker_srcs: SourceMap, + pub covergroup_srcs: SourceMap, + pub coverpoint_srcs: SourceMap, + pub cross_srcs: SourceMap, + pub subroutine_srcs: SourceMap, + pub expr_srcs: SourceMap, + pub event_expr_srcs: SourceMap, + pub decl_srcs: SourceMap, + pub stmt_srcs: SourceMap, +} + +impl FileSourceMap { + pub fn shrink_to_fit(&mut self) { + self.module_srcs.shrink_to_fit(); + self.proc_srcs.shrink_to_fit(); + self.declaration_srcs.shrink_to_fit(); + self.typedef_srcs.shrink_to_fit(); + self.struct_srcs.shrink_to_fit(); + self.config_decl_srcs.shrink_to_fit(); + self.udp_decl_srcs.shrink_to_fit(); + self.library_decl_srcs.shrink_to_fit(); + self.library_include_srcs.shrink_to_fit(); + self.checker_srcs.shrink_to_fit(); + self.covergroup_srcs.shrink_to_fit(); + self.coverpoint_srcs.shrink_to_fit(); + self.cross_srcs.shrink_to_fit(); + self.subroutine_srcs.shrink_to_fit(); + self.expr_srcs.shrink_to_fit(); + self.event_expr_srcs.shrink_to_fit(); + self.decl_srcs.shrink_to_fit(); + self.stmt_srcs.shrink_to_fit(); } } +crate::hir_def::impl_arena_getters!( + HirFile; + LocalModuleId => modules => ModuleInfo, + ProcId => procs => Proc, + TypedefId => typedefs => Typedef, + StructId => structs => StructDef, + ConfigDeclId => config_decls => ConfigDecl, + UdpDeclId => udp_decls => UdpDecl, + LibraryDeclId => library_decls => LibraryDecl, + LibraryIncludeId => library_includes => LibraryInclude, + CheckerId => checkers => CheckerDef, + CovergroupId => covergroups => CovergroupDef, + CoverpointId => coverpoints => CoverpointDef, + CrossId => crosses => CrossDef, + LocalSubroutineId => subroutines => Subroutine, + Idx => package_imports => PackageImport, + DeclarationId => declarations => Declaration, + ExprId => exprs => Expr, + EventExprId => event_exprs => EventExpr, + DeclId => decls => Declarator, + StmtId => stmts => Stmt, + LocalBlockId => stmts => BlockInfo, +); + +crate::hir_def::impl_source_map_getters!( + FileSourceMap; + ModuleSrc => LocalModuleId => module_srcs, + ProcSrc => ProcId => proc_srcs, + DeclarationSrc => DeclarationId => declaration_srcs, + TypedefSrc => TypedefId => typedef_srcs, + StructSrc => StructId => struct_srcs, + ConfigDeclSrc => ConfigDeclId => config_decl_srcs, + UdpDeclSrc => UdpDeclId => udp_decl_srcs, + LibraryDeclSrc => LibraryDeclId => library_decl_srcs, + LibraryIncludeSrc => LibraryIncludeId => library_include_srcs, + CheckerSrc => CheckerId => checker_srcs, + CovergroupSrc => CovergroupId => covergroup_srcs, + CoverpointSrc => CoverpointId => coverpoint_srcs, + CrossSrc => CrossId => cross_srcs, + SubroutineSrc => LocalSubroutineId => subroutine_srcs, + ExprSrc => ExprId => expr_srcs, + EventExprSrc => EventExprId => event_expr_srcs, + DeclaratorSrc => DeclId => decl_srcs, + StmtSrc => StmtId => stmt_srcs, + BlockSrc => LocalBlockId => stmt_srcs, +); + define_enum_deriving_from! { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum FileItem { @@ -153,66 +229,31 @@ impl FileSourceMap { } } -pub(crate) struct LowerFileCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - - pub(crate) file: &'a mut HirFile, - pub(crate) file_source_map: &'a mut FileSourceMap, - - pub(crate) region_tree: RegionTreeBuilder, -} - -impl_lower_expr!(LowerFileCtx<'_>, file, file_source_map); -impl_lower_decl!(LowerFileCtx<'_>, file, file_source_map); -impl_lower_event_expr!(LowerFileCtx<'_>, file, file_source_map); -impl_lower_stmt!(LowerFileCtx<'_>, file_id, file, file_source_map); -impl_lower_declaration!(LowerFileCtx<'_>, file, file_source_map); - -impl LowerProc for LowerFileCtx<'_> { - fn proc_ctx(&mut self) -> LowerProcCtx<'_> { - LowerProcCtx { - db: self.db, - file_id: self.file_id, - cont_id: self.file_id.into(), - procs: &mut self.file.procs, - proc_srcs: &mut self.file_source_map.proc_srcs, - - stmts: &mut self.file.stmts, - stmt_srcs: &mut self.file_source_map.stmt_srcs, - - exprs: &mut self.file.exprs, - expr_srcs: &mut self.file_source_map.expr_srcs, - - event_exprs: &mut self.file.event_exprs, - event_expr_srcs: &mut self.file_source_map.event_expr_srcs, - - decls: &mut self.file.decls, - decl_srcs: &mut self.file_source_map.decl_srcs, - } - } -} +pub(crate) type LowerFileCtx<'a> = LoweringCtx<'a, FileStore<'a>>; impl LowerFileCtx<'_> { fn lower_struct_type(&mut self, struct_ty: ast::StructUnionType) -> StructId { let container_id = ArenaOwnerId::File(self.file_id); - let struct_def = - lower_struct_def(struct_ty, container_id, |ty| self.expr_ctx().lower_data_ty(ty)); - - alloc_idx_and_src! { - self.file_id; - struct_def => self.file.structs, - struct_ty => self.file_source_map.struct_srcs, - } + let struct_def = lower_struct_def(struct_ty, container_id, |ty| self.lower_data_ty(ty)); + + alloc_with_source( + self.file_id, + &mut self.store.data.structs, + &mut self.store.sources.struct_srcs, + struct_def, + struct_ty, + ) } fn lower_typedef(&mut self, typedef: ast::TypedefDeclaration) -> TypedefId { let name = lower_ident_opt(typedef.name()); - let typedef_id = alloc_idx_and_src! { - self.file_id; - Typedef { name, ty: None } => self.file.typedefs, - typedef => self.file_source_map.typedef_srcs, - }; + let typedef_id = alloc_with_source( + self.file_id, + &mut self.store.data.typedefs, + &mut self.store.sources.typedef_srcs, + Typedef { name, ty: None }, + typedef, + ); let data_ty = typedef.type_(); let lowered_ty = lower_typedef_data_ty( @@ -220,10 +261,10 @@ impl LowerFileCtx<'_> { data_ty, ArenaOwnerId::File(self.file_id), |ctx, struct_ty| ctx.lower_struct_type(struct_ty), - |ctx, ty| ctx.expr_ctx().lower_data_ty(ty), + |ctx, ty| ctx.lower_data_ty(ty), ); - self.file.typedefs[typedef_id].ty = Some(lowered_ty); + self.store.data.typedefs[typedef_id].ty = Some(lowered_ty); typedef_id } @@ -232,34 +273,36 @@ impl LowerFileCtx<'_> { &mut self, func: ast::FunctionDeclaration, ) -> Option { - let subroutine = lower_subroutine(&func, |ty| self.expr_ctx().lower_data_ty(ty))?; - - let local_subroutine_id = alloc_idx_and_src! { - self.file_id; - subroutine => self.file.subroutines, - func => self.file_source_map.subroutine_srcs, - }; + let subroutine = lower_subroutine(&func, |ty| self.lower_data_ty(ty))?; + + let local_subroutine_id = alloc_with_source( + self.file_id, + &mut self.store.data.subroutines, + &mut self.store.sources.subroutine_srcs, + subroutine, + func, + ); let subroutine_id = SubroutineScope::new(SubroutineParent::File(self.file_id), local_subroutine_id); if func.end().is_some() { - let subroutine = &mut self.file.subroutines[local_subroutine_id]; + let subroutine = &mut self.store.data.subroutines[local_subroutine_id]; let mut subroutine_source_map = std::mem::take(&mut subroutine.source_map); - let mut ctx = LowerSubroutineBodyCtx { - db: self.db, - file_id: self.file_id, - subroutine_id, - subroutine, - subroutine_source_map: &mut subroutine_source_map, - region_tree: RegionTreeBuilder::new(), - }; + let mut ctx = LoweringCtx::new( + self.db, + self.file_id, + subroutine_id.into(), + SubroutineStore { data: subroutine, sources: &mut subroutine_source_map }, + ); lower_subroutine_body(&mut ctx, func); + ctx.emit_diagnostics(); + drop(ctx); subroutine.source_map = subroutine_source_map; subroutine.source_map.shrink_to_fit(); } - self.file.subroutines[local_subroutine_id].shrink_to_fit(); + self.store.data.subroutines[local_subroutine_id].shrink_to_fit(); Some(local_subroutine_id) } @@ -267,42 +310,50 @@ impl LowerFileCtx<'_> { fn lower_config_decl(&mut self, config_decl: ast::ConfigDeclaration) -> ConfigDeclId { let name = lower_ident_opt(config_decl.name()); - alloc_idx_and_src! { - self.file_id; - ConfigDecl { name } => self.file.config_decls, - config_decl => self.file_source_map.config_decl_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.config_decls, + &mut self.store.sources.config_decl_srcs, + ConfigDecl { name }, + config_decl, + ) } fn lower_udp_decl(&mut self, udp_decl: ast::UdpDeclaration) -> UdpDeclId { let name = lower_ident_opt(udp_decl.name()); - alloc_idx_and_src! { - self.file_id; - UdpDecl { name } => self.file.udp_decls, - udp_decl => self.file_source_map.udp_decl_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.udp_decls, + &mut self.store.sources.udp_decl_srcs, + UdpDecl { name }, + udp_decl, + ) } fn lower_library_decl(&mut self, library_decl: ast::LibraryDeclaration) -> LibraryDeclId { let name = lower_ident_opt(library_decl.name()); - alloc_idx_and_src! { - self.file_id; - LibraryDecl { name } => self.file.library_decls, - library_decl => self.file_source_map.library_decl_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.library_decls, + &mut self.store.sources.library_decl_srcs, + LibraryDecl { name }, + library_decl, + ) } fn lower_library_include( &mut self, library_include: ast::LibraryIncludeStatement, ) -> LibraryIncludeId { - alloc_idx_and_src! { - self.file_id; - LibraryInclude => self.file.library_includes, - library_include => self.file_source_map.library_include_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.library_includes, + &mut self.store.sources.library_include_srcs, + LibraryInclude, + library_include, + ) } fn lower_covergroup_decl( @@ -315,31 +366,37 @@ impl LowerFileCtx<'_> { match member { ast::Member::Coverpoint(coverpoint_ast) => { let coverpoint = lower_coverpoint(coverpoint_ast); - let coverpoint_id = alloc_idx_and_src! { - self.file_id; - coverpoint => self.file.coverpoints, - coverpoint_ast => self.file_source_map.coverpoint_srcs, - }; + let coverpoint_id = alloc_with_source( + self.file_id, + &mut self.store.data.coverpoints, + &mut self.store.sources.coverpoint_srcs, + coverpoint, + coverpoint_ast, + ); covergroup.coverpoints.push(coverpoint_id); } ast::Member::CoverCross(cross_ast) => { let cross = lower_cross(cross_ast); - let cross_id = alloc_idx_and_src! { - self.file_id; - cross => self.file.crosses, - cross_ast => self.file_source_map.cross_srcs, - }; + let cross_id = alloc_with_source( + self.file_id, + &mut self.store.data.crosses, + &mut self.store.sources.cross_srcs, + cross, + cross_ast, + ); covergroup.crosses.push(cross_id); } _ => {} } } - alloc_idx_and_src! { - self.file_id; - covergroup => self.file.covergroups, - covergroup_decl => self.file_source_map.covergroup_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.covergroups, + &mut self.store.sources.covergroup_srcs, + covergroup, + covergroup_decl, + ) } pub(crate) fn lower_file(&mut self, root: ast::CompilationUnit) { @@ -350,18 +407,18 @@ impl LowerFileCtx<'_> { let name = lower_ident_opt(decl.header().name()); let kind = ModuleKind::from_ast(decl); - alloc_idx_and_src! { - self.file_id; - ModuleInfo { name, kind } => self.file.modules, - decl => self.file_source_map.module_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.modules, + &mut self.store.sources.module_srcs, + ModuleInfo { name, kind }, + decl, + ) .into() } - ProceduralBlock(proc) => self.proc_ctx().lower_proc(proc).into(), - DataDeclaration(data_decl) => { - self.declaration_ctx().lower_data_decl(data_decl).into() - } - NetDeclaration(net_decl) => self.declaration_ctx().lower_net_decl(net_decl).into(), + ProceduralBlock(proc) => self.lower_proc(proc).into(), + DataDeclaration(data_decl) => self.lower_data_decl(data_decl).into(), + NetDeclaration(net_decl) => self.lower_net_decl(net_decl).into(), EmptyMember(_x) => continue, TypedefDeclaration(typedef_decl) => self.lower_typedef(typedef_decl).into(), FunctionDeclaration(fn_decl) => match self.lower_subroutine_decl(fn_decl) { @@ -370,7 +427,7 @@ impl LowerFileCtx<'_> { }, PackageImportDeclaration(import_decl) => { for import in lower_package_imports(import_decl) { - self.file.package_imports.alloc(import); + self.store.data.package_imports.alloc(import); } continue; } @@ -382,12 +439,12 @@ impl LowerFileCtx<'_> { } _ => continue, }; - self.file_source_map.items.push(idx); + self.store.sources.items.push(idx); self.region_tree.handle_node(member.syntax()); } self.region_tree.stage(root.end_of_file(), root.syntax()); - self.file_source_map.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.region_tree.finish(); } pub(crate) fn lower_library_map(&mut self, root: ast::LibraryMap) { @@ -401,12 +458,12 @@ impl LowerFileCtx<'_> { EmptyMember(_) => continue, _ => continue, }; - self.file_source_map.items.push(idx); + self.store.sources.items.push(idx); self.region_tree.handle_node(member.syntax()); } self.region_tree.stage(root.end_of_file(), root.syntax()); - self.file_source_map.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.region_tree.finish(); } } @@ -418,13 +475,12 @@ pub(crate) fn hir_file_with_source_map_query( let mut source_map = FileSourceMap::default(); let tree = db.parse(file_id); - let mut lower_ctx = LowerFileCtx { + let mut lower_ctx = LoweringCtx::new( db, file_id, - file: &mut hir_file, - file_source_map: &mut source_map, - region_tree: RegionTreeBuilder::new(), - }; + file_id.into(), + FileStore { data: &mut hir_file, sources: &mut source_map }, + ); match tree.root() { Some(root) if ast::CompilationUnit::can_cast(root.kind()) => { if let Some(root) = ast::CompilationUnit::cast(root) { @@ -439,6 +495,9 @@ pub(crate) fn hir_file_with_source_map_query( _ => {} } + lower_ctx.emit_diagnostics(); + drop(lower_ctx); + hir_file.shrink_to_fit(); source_map.shrink_to_fit(); diff --git a/crates/hir/src/hir_def/lower.rs b/crates/hir/src/hir_def/lower.rs new file mode 100644 index 000000000..fc98011a9 --- /dev/null +++ b/crates/hir/src/hir_def/lower.rs @@ -0,0 +1,493 @@ +use la_arena::Arena; +use syntax::SyntaxKind; +use utils::text_edit::TextRange; + +use super::{ + block::{Block, BlockId, BlockSourceMap}, + checker::{CheckerDef, CheckerSrc}, + declaration::{Declaration, DeclarationSrc}, + expr::{ + Expr, ExprSrc, + declarator::{Declarator, DeclaratorSrc}, + timing_control::{EventExpr, EventExprSrc}, + }, + file::{FileSourceMap, HirFile}, + module::{ + Module, ModuleId, ModuleSourceMap, + continuous_assgin::{ContAssign, ContAssignSrc}, + defparam::{DefParam, DefParamSrc}, + generate::{GenerateBlock, GenerateBlockId, GenerateBlockSourceMap}, + instantiation::{ + Instance, InstanceSrc, Instantiation, InstantiationSrc, ParamAssign, ParamAssignSrc, + PortConn, PortConnSrc, + }, + }, + proc::{Proc, ProcSrc}, + stmt::{Stmt, StmtSrc}, + subroutine::{Subroutine, SubroutineSourceMap}, + ty::NetKind, +}; +use crate::{ + container::ArenaOwnerId, db::InternDb, file::HirFileId, region_tree::RegionTreeBuilder, + source_map::SourceMap, +}; + +/// Mutable data/source pair for a file lowering pass. +pub(crate) struct FileStore<'a> { + pub(crate) data: &'a mut HirFile, + pub(crate) sources: &'a mut FileSourceMap, +} + +/// Mutable data/source pair for a module lowering pass. +pub(crate) struct ModuleStore<'a> { + pub(crate) data: &'a mut Module, + pub(crate) sources: &'a mut ModuleSourceMap, +} + +/// Mutable data/source pair for a generate-block lowering pass. +pub(crate) struct GenerateBlockStore<'a> { + pub(crate) data: &'a mut GenerateBlock, + pub(crate) sources: &'a mut GenerateBlockSourceMap, +} + +/// Mutable data/source pair for a procedural-block lowering pass. +pub(crate) struct BlockStore<'a> { + pub(crate) data: &'a mut Block, + pub(crate) sources: &'a mut BlockSourceMap, +} + +/// Mutable data/source pair for a subroutine-body lowering pass. +pub(crate) struct SubroutineStore<'a> { + pub(crate) data: &'a mut Subroutine, + pub(crate) sources: &'a mut SubroutineSourceMap, +} + +/// Store interface shared by expression, declarator, statement, and declaration +/// lowering. +pub(crate) trait LoweringStore { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap); + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap); + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap); + fn statements(&mut self) -> (&mut Arena, &mut SourceMap); + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap); +} + +impl LoweringStore for FileStore<'_> { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.exprs, &mut self.sources.expr_srcs) + } + + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.event_exprs, &mut self.sources.event_expr_srcs) + } + + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.decls, &mut self.sources.decl_srcs) + } + + fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.stmts, &mut self.sources.stmt_srcs) + } + + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.declarations, &mut self.sources.declaration_srcs) + } +} + +impl LoweringStore for ModuleStore<'_> { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.exprs, &mut self.sources.expr_srcs) + } + + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.event_exprs, &mut self.sources.event_expr_srcs) + } + + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.decls, &mut self.sources.decl_srcs) + } + + fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.stmts, &mut self.sources.stmt_srcs) + } + + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.declarations, &mut self.sources.declaration_srcs) + } +} + +impl LoweringStore for GenerateBlockStore<'_> { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.exprs, &mut self.sources.expr_srcs) + } + + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.event_exprs, &mut self.sources.event_expr_srcs) + } + + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.decls, &mut self.sources.decl_srcs) + } + + fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.stmts, &mut self.sources.stmt_srcs) + } + + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.declarations, &mut self.sources.declaration_srcs) + } +} + +impl LoweringStore for BlockStore<'_> { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.exprs, &mut self.sources.expr_srcs) + } + + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.event_exprs, &mut self.sources.event_expr_srcs) + } + + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.decls, &mut self.sources.decl_srcs) + } + + fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.stmts, &mut self.sources.stmt_srcs) + } + + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.declarations, &mut self.sources.declaration_srcs) + } +} + +impl LoweringStore for SubroutineStore<'_> { + fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.exprs, &mut self.sources.expr_srcs) + } + + fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.event_exprs, &mut self.sources.event_expr_srcs) + } + + fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.decls, &mut self.sources.decl_srcs) + } + + fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.stmts, &mut self.sources.stmt_srcs) + } + + fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.declarations, &mut self.sources.declaration_srcs) + } +} + +pub(crate) trait CheckerStore: LoweringStore { + fn checkers(&mut self) -> (&mut Arena, &mut SourceMap); +} + +impl CheckerStore for FileStore<'_> { + fn checkers(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.checkers, &mut self.sources.checker_srcs) + } +} + +impl CheckerStore for ModuleStore<'_> { + fn checkers(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.checkers, &mut self.sources.checker_srcs) + } +} + +pub(crate) trait ProcStore: LoweringStore { + fn procs(&mut self) -> (&mut Arena, &mut SourceMap); +} + +impl ProcStore for FileStore<'_> { + fn procs(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.procs, &mut self.sources.proc_srcs) + } +} + +impl ProcStore for ModuleStore<'_> { + fn procs(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.procs, &mut self.sources.proc_srcs) + } +} + +impl ProcStore for GenerateBlockStore<'_> { + fn procs(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.procs, &mut self.sources.proc_srcs) + } +} + +pub(crate) trait ModuleItemStore: LoweringStore { + fn continuous_assigns( + &mut self, + ) -> (&mut Arena, &mut SourceMap); + fn defparams(&mut self) -> (&mut Arena, &mut SourceMap); + fn instantiations( + &mut self, + ) -> (&mut Arena, &mut SourceMap); + fn parameter_assignments( + &mut self, + ) -> (&mut Arena, &mut SourceMap); + fn instances(&mut self) -> (&mut Arena, &mut SourceMap); + fn port_connections(&mut self) + -> (&mut Arena, &mut SourceMap); +} + +impl ModuleItemStore for ModuleStore<'_> { + fn continuous_assigns( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.cont_assigns, &mut self.sources.assign_srcs) + } + + fn defparams(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.defparams, &mut self.sources.defparam_srcs) + } + + fn instantiations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.instantiations, &mut self.sources.instantiation_srcs) + } + + fn parameter_assignments( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.inst_param_assigns, &mut self.sources.inst_param_assign_srcs) + } + + fn instances(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.instances, &mut self.sources.instance_srcs) + } + + fn port_connections( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.inst_port_conns, &mut self.sources.inst_port_conn_srcs) + } +} + +impl ModuleItemStore for GenerateBlockStore<'_> { + fn continuous_assigns( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.cont_assigns, &mut self.sources.assign_srcs) + } + + fn defparams(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.defparams, &mut self.sources.defparam_srcs) + } + + fn instantiations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.instantiations, &mut self.sources.instantiation_srcs) + } + + fn parameter_assignments( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.inst_param_assigns, &mut self.sources.inst_param_assign_srcs) + } + + fn instances(&mut self) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.instances, &mut self.sources.instance_srcs) + } + + fn port_connections( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + (&mut self.data.inst_port_conns, &mut self.sources.inst_port_conn_srcs) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct LoweringDiagnostic { + pub(crate) kind: SyntaxKind, + pub(crate) range: Option, + pub(crate) message: &'static str, +} + +/// Complete mutable state for one HIR lowering pass. +pub(crate) struct LoweringCtx<'a, Store> { + pub(crate) db: &'a dyn InternDb, + pub(crate) file_id: HirFileId, + pub(crate) owner: ArenaOwnerId, + pub(crate) store: Store, + pub(crate) diagnostics: Vec, + pub(crate) region_tree: RegionTreeBuilder, + pub(crate) default_net_type: NetKind, +} + +impl<'a, Store> LoweringCtx<'a, Store> { + pub(crate) fn new( + db: &'a dyn InternDb, + file_id: HirFileId, + owner: ArenaOwnerId, + store: Store, + ) -> Self { + Self { + db, + file_id, + owner, + store, + diagnostics: Vec::new(), + region_tree: RegionTreeBuilder::new(), + default_net_type: NetKind::Wire, + } + } + + pub(crate) fn module_id(&self) -> ModuleId { + let ArenaOwnerId::Module(module_id) = self.owner else { + unreachable!("module-only lowering called for {:?}", self.owner); + }; + module_id + } + + pub(crate) fn generate_block_id(&self) -> GenerateBlockId { + let ArenaOwnerId::GenerateBlock(generate_block_id) = self.owner else { + unreachable!("generate-block-only lowering called for {:?}", self.owner); + }; + generate_block_id + } + + pub(crate) fn block_id(&self) -> BlockId { + let ArenaOwnerId::Block(block_id) = self.owner else { + unreachable!("block-only lowering called for {:?}", self.owner); + }; + block_id + } + + pub(crate) fn report_unsupported( + &mut self, + kind: SyntaxKind, + range: Option, + message: &'static str, + ) { + self.diagnostics.push(LoweringDiagnostic { kind, range, message }); + } + + pub(crate) fn emit_diagnostics(&mut self) { + for diagnostic in self.diagnostics.drain(..) { + tracing::warn!( + file = ?self.file_id, + owner = ?self.owner, + kind = ?diagnostic.kind, + range = ?diagnostic.range, + message = diagnostic.message, + "HIR lowering diagnostic" + ); + } + } +} + +impl LoweringCtx<'_, Store> { + pub(crate) fn expressions(&mut self) -> (&mut Arena, &mut SourceMap) { + self.store.expressions() + } + + pub(crate) fn event_expressions( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.event_expressions() + } + + pub(crate) fn declarators( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.declarators() + } + + pub(crate) fn statements(&mut self) -> (&mut Arena, &mut SourceMap) { + self.store.statements() + } + + pub(crate) fn declarations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.declarations() + } +} + +impl LoweringCtx<'_, Store> { + pub(crate) fn procs(&mut self) -> (&mut Arena, &mut SourceMap) { + self.store.procs() + } +} + +impl LoweringCtx<'_, Store> { + pub(crate) fn continuous_assigns( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.continuous_assigns() + } + + pub(crate) fn defparams( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.defparams() + } + + pub(crate) fn instantiations( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.instantiations() + } + + pub(crate) fn parameter_assignments( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.parameter_assignments() + } + + pub(crate) fn instances( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.instances() + } + + pub(crate) fn port_connections( + &mut self, + ) -> (&mut Arena, &mut SourceMap) { + self.store.port_connections() + } +} diff --git a/crates/hir/src/hir_def/module.rs b/crates/hir/src/hir_def/module.rs index bdb4b84f9..a9357470f 100644 --- a/crates/hir/src/hir_def/module.rs +++ b/crates/hir/src/hir_def/module.rs @@ -1,23 +1,19 @@ use clocking::{ ClockingBlockDef, ClockingBlockId, ClockingBlockSrc, DefaultClockingRef, DefaultClockingRefSrc, - LowerClocking, }; -use continuous_assgin::{ - ContAssign, ContAssignId, ContAssignSrc, LowerContAssign, impl_lower_cont_assign, -}; -use defparam::{DefParam, DefParamId, DefParamSrc, LowerDefParam, impl_lower_defparam}; +use continuous_assgin::{ContAssign, ContAssignId, ContAssignSrc}; +use defparam::{DefParam, DefParamId, DefParamSrc}; use generate::{GenerateRegion, GenerateRegionId, GenerateRegionSrc}; use instantiation::{ - Instance, InstanceSrc, Instantiation, InstantiationId, InstantiationSrc, LowerInstantiation, - ParamAssign, ParamAssignSrc, PortConn, PortConnSrc, impl_lower_instantiation, + Instance, InstanceId, InstanceSrc, Instantiation, InstantiationId, InstantiationSrc, + ParamAssign, ParamAssignId, ParamAssignSrc, PortConn, PortConnId, PortConnSrc, }; -use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use modport::{LowerModport, ModportDef, ModportId, ModportSrc}; +use la_arena::{Arena, Idx, IdxRange}; +use modport::{ModportDef, ModportId, ModportSrc}; use port::{ NonAnsiPort, NonAnsiPortId, NonAnsiPortSrc, PortDecl, PortDeclId, PortDeclSrc, PortRef, PortRefId, PortRefSrc, PortSrcs, Ports, }; -use proc_macro_utils::define_container; use specify::{ SpecifyBlock, SpecifyBlockId, SpecifyBlockSrc, SpecifyItem, SpecifyItemId, SpecifyItemSrc, }; @@ -33,40 +29,35 @@ use utils::{ }; use super::{ - HirData, Ident, PackageImport, + Ident, PackageImport, aggregate::{StructDef, StructId, StructSrc, lower_struct_def}, - alloc_idx_and_src, + alloc_with_source, block::{BlockInfo, BlockSrc, LocalBlockId}, - checker::{CheckerDef, CheckerId, CheckerSrc, LowerChecker}, + checker::{CheckerDef, CheckerId, CheckerSrc}, covergroup::{ - CovergroupDef, CovergroupId, CovergroupSrc, CoverpointDef, CoverpointSrc, CrossDef, - CrossSrc, lower_covergroup_decl, lower_coverpoint, lower_cross, - }, - declaration::{ - Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, ParamDeclKind, - impl_lower_declaration, + CovergroupDef, CovergroupId, CovergroupSrc, CoverpointDef, CoverpointId, CoverpointSrc, + CrossDef, CrossId, CrossSrc, lower_covergroup_decl, lower_coverpoint, lower_cross, }, + declaration::{Declaration, DeclarationId, DeclarationSrc, ParamDeclKind}, expr::{ - Expr, ExprSrc, LowerExpr, - declarator::{DeclId, Declarator, DeclaratorSrc, impl_lower_decl}, - impl_lower_expr, - timing_control::{EventExpr, EventExprSrc, impl_lower_event_expr}, + Expr, ExprId, ExprSrc, + declarator::{DeclId, Declarator, DeclaratorSrc}, + timing_control::{EventExpr, EventExprId, EventExprSrc}, }, + lower::{LoweringCtx, ModuleStore, SubroutineStore}, lower_ident_opt, lower_package_imports, - proc::{LowerProc, LowerProcCtx, Proc, ProcId, ProcSrc}, - stmt::{Stmt, StmtId, StmtSrc, impl_lower_stmt}, + proc::{Proc, ProcId, ProcSrc}, + stmt::{Stmt, StmtId, StmtSrc}, subroutine::{ - LocalSubroutineId, LowerSubroutineBodyCtx, Subroutine, SubroutineSrc, lower_subroutine, - lower_subroutine_body, + LocalSubroutineId, Subroutine, SubroutineSrc, lower_subroutine, lower_subroutine_body, }, - ty::NetKind, typedef::{Typedef, TypedefId, TypedefSrc, lower_typedef_data_ty}, }; use crate::{ container::{ArenaOwnerId, InFile, SubroutineParent, SubroutineScope}, - db::{HirDb, InternDb}, + db::HirDb, file::HirFileId, - region_tree::{RegionTree, RegionTreeBuilder}, + region_tree::RegionTree, source_map::{ FromSourceAst, IsNamedSrc, IsSrc, SourceAst, SourceMap, ToAstNode, ast_node_from_ptr, root_token_in, @@ -82,99 +73,197 @@ pub mod modport; pub mod port; pub mod specify; -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct Module { - name: Option, - - param_ports: Option>, - ports: Ports => { - [NonAnsiPortId | NonAnsiPort], - [PortRefId | PortRef], - [PortDeclId | PortDecl], - }, - - cont_assigns: [ContAssign], - defparams: [DefParam], - generate_regions: [GenerateRegion], - specify_blocks: [SpecifyBlock], - specify_items: [SpecifyItem], - declarations: [Declaration], - typedefs: [Typedef], - structs: [StructDef], - subroutines: [Subroutine], - modports: [ModportDef], - default_clocking: Option, - clocking_blocks: [ClockingBlockDef], - checkers: [CheckerDef], - covergroups: [CovergroupDef], - coverpoints: [CoverpointDef], - crosses: [CrossDef], - package_imports: [PackageImport], - - instantiations: [Instantiation], - inst_param_assigns: [ParamAssign], - instances: [Instance], - inst_port_conns: [PortConn], - - procs: [Proc], - - exprs: [Expr], - event_exprs: [EventExpr], - decls: [Declarator], - stmts: [Stmt] => { - [StmtId | Stmt], - [LocalBlockId | BlockInfo], - }, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct Module { + pub name: Option, + pub param_ports: Option>, + pub ports: Ports, + pub cont_assigns: Arena, + pub defparams: Arena, + pub generate_regions: Arena, + pub specify_blocks: Arena, + pub specify_items: Arena, + pub declarations: Arena, + pub typedefs: Arena, + pub structs: Arena, + pub subroutines: Arena, + pub modports: Arena, + pub default_clocking: Option, + pub clocking_blocks: Arena, + pub checkers: Arena, + pub covergroups: Arena, + pub coverpoints: Arena, + pub crosses: Arena, + pub package_imports: Arena, + pub instantiations: Arena, + pub inst_param_assigns: Arena, + pub instances: Arena, + pub inst_port_conns: Arena, + pub procs: Arena, + pub exprs: Arena, + pub event_exprs: Arena, + pub decls: Arena, + pub stmts: Arena, +} + +impl Module { + pub fn shrink_to_fit(&mut self) { + self.ports.shrink_to_fit(); + self.cont_assigns.shrink_to_fit(); + self.defparams.shrink_to_fit(); + self.generate_regions.shrink_to_fit(); + self.specify_blocks.shrink_to_fit(); + self.specify_items.shrink_to_fit(); + self.declarations.shrink_to_fit(); + self.typedefs.shrink_to_fit(); + self.structs.shrink_to_fit(); + self.subroutines.shrink_to_fit(); + self.modports.shrink_to_fit(); + self.clocking_blocks.shrink_to_fit(); + self.checkers.shrink_to_fit(); + self.covergroups.shrink_to_fit(); + self.coverpoints.shrink_to_fit(); + self.crosses.shrink_to_fit(); + self.package_imports.shrink_to_fit(); + self.instantiations.shrink_to_fit(); + self.inst_param_assigns.shrink_to_fit(); + self.instances.shrink_to_fit(); + self.inst_port_conns.shrink_to_fit(); + self.procs.shrink_to_fit(); + self.exprs.shrink_to_fit(); + self.event_exprs.shrink_to_fit(); + self.decls.shrink_to_fit(); + self.stmts.shrink_to_fit(); } } -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct ModuleSourceMap { - items: Vec, - region_tree: RegionTree, - - port_srcs: PortSrcs => { - [NonAnsiPortId | NonAnsiPortSrc], - [PortRefId | PortRefSrc], - [PortDeclId | PortDeclSrc], - }, - - assign_srcs: [ContAssign | ContAssignSrc], - defparam_srcs: [DefParam | DefParamSrc], - generate_region_srcs: [GenerateRegion | GenerateRegionSrc], - specify_block_srcs: [SpecifyBlock | SpecifyBlockSrc], - specify_item_srcs: [SpecifyItem | SpecifyItemSrc], - declaration_srcs: [Declaration | DeclarationSrc], - typedef_srcs: [Typedef | TypedefSrc], - struct_srcs: [StructDef | StructSrc], - subroutine_srcs: [Subroutine | SubroutineSrc], - modport_srcs: [ModportDef | ModportSrc], - default_clocking_src: Option, - clocking_block_srcs: [ClockingBlockDef | ClockingBlockSrc], - checker_srcs: [CheckerDef | CheckerSrc], - covergroup_srcs: [CovergroupDef | CovergroupSrc], - coverpoint_srcs: [CoverpointDef | CoverpointSrc], - cross_srcs: [CrossDef | CrossSrc], - - instantiation_srcs: [Instantiation | InstantiationSrc], - inst_param_assign_srcs: [ParamAssign | ParamAssignSrc], - instance_srcs: [Instance | InstanceSrc], - inst_port_conn_srcs: [PortConn | PortConnSrc], - - proc_srcs: [Proc | ProcSrc], - - expr_srcs: [Expr | ExprSrc], - event_expr_srcs: [EventExpr | EventExprSrc], - decl_srcs: [Declarator | DeclaratorSrc], - stmt_srcs: [Stmt | StmtSrc] => { - [StmtId | StmtSrc], - [LocalBlockId | BlockSrc], - }, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct ModuleSourceMap { + pub items: Vec, + pub region_tree: RegionTree, + pub port_srcs: PortSrcs, + pub assign_srcs: SourceMap, + pub defparam_srcs: SourceMap, + pub generate_region_srcs: SourceMap, + pub specify_block_srcs: SourceMap, + pub specify_item_srcs: SourceMap, + pub declaration_srcs: SourceMap, + pub typedef_srcs: SourceMap, + pub struct_srcs: SourceMap, + pub subroutine_srcs: SourceMap, + pub modport_srcs: SourceMap, + pub default_clocking_src: Option, + pub clocking_block_srcs: SourceMap, + pub checker_srcs: SourceMap, + pub covergroup_srcs: SourceMap, + pub coverpoint_srcs: SourceMap, + pub cross_srcs: SourceMap, + pub instantiation_srcs: SourceMap, + pub inst_param_assign_srcs: SourceMap, + pub instance_srcs: SourceMap, + pub inst_port_conn_srcs: SourceMap, + pub proc_srcs: SourceMap, + pub expr_srcs: SourceMap, + pub event_expr_srcs: SourceMap, + pub decl_srcs: SourceMap, + pub stmt_srcs: SourceMap, +} + +impl ModuleSourceMap { + pub fn shrink_to_fit(&mut self) { + self.port_srcs.shrink_to_fit(); + self.assign_srcs.shrink_to_fit(); + self.defparam_srcs.shrink_to_fit(); + self.generate_region_srcs.shrink_to_fit(); + self.specify_block_srcs.shrink_to_fit(); + self.specify_item_srcs.shrink_to_fit(); + self.declaration_srcs.shrink_to_fit(); + self.typedef_srcs.shrink_to_fit(); + self.struct_srcs.shrink_to_fit(); + self.subroutine_srcs.shrink_to_fit(); + self.modport_srcs.shrink_to_fit(); + self.clocking_block_srcs.shrink_to_fit(); + self.checker_srcs.shrink_to_fit(); + self.covergroup_srcs.shrink_to_fit(); + self.coverpoint_srcs.shrink_to_fit(); + self.cross_srcs.shrink_to_fit(); + self.instantiation_srcs.shrink_to_fit(); + self.inst_param_assign_srcs.shrink_to_fit(); + self.instance_srcs.shrink_to_fit(); + self.inst_port_conn_srcs.shrink_to_fit(); + self.proc_srcs.shrink_to_fit(); + self.expr_srcs.shrink_to_fit(); + self.event_expr_srcs.shrink_to_fit(); + self.decl_srcs.shrink_to_fit(); + self.stmt_srcs.shrink_to_fit(); } } +crate::hir_def::impl_arena_getters!( + Module; + NonAnsiPortId => ports => NonAnsiPort, + PortRefId => ports => PortRef, + PortDeclId => ports => PortDecl, + ContAssignId => cont_assigns => ContAssign, + DefParamId => defparams => DefParam, + GenerateRegionId => generate_regions => GenerateRegion, + SpecifyBlockId => specify_blocks => SpecifyBlock, + SpecifyItemId => specify_items => SpecifyItem, + DeclarationId => declarations => Declaration, + TypedefId => typedefs => Typedef, + StructId => structs => StructDef, + LocalSubroutineId => subroutines => Subroutine, + ModportId => modports => ModportDef, + ClockingBlockId => clocking_blocks => ClockingBlockDef, + CheckerId => checkers => CheckerDef, + CovergroupId => covergroups => CovergroupDef, + CoverpointId => coverpoints => CoverpointDef, + CrossId => crosses => CrossDef, + Idx => package_imports => PackageImport, + InstantiationId => instantiations => Instantiation, + ParamAssignId => inst_param_assigns => ParamAssign, + InstanceId => instances => Instance, + PortConnId => inst_port_conns => PortConn, + ProcId => procs => Proc, + ExprId => exprs => Expr, + EventExprId => event_exprs => EventExpr, + DeclId => decls => Declarator, + StmtId => stmts => Stmt, + LocalBlockId => stmts => BlockInfo, +); + +crate::hir_def::impl_source_map_getters!( + ModuleSourceMap; + NonAnsiPortSrc => NonAnsiPortId => port_srcs, + PortRefSrc => PortRefId => port_srcs, + PortDeclSrc => PortDeclId => port_srcs, + ContAssignSrc => ContAssignId => assign_srcs, + DefParamSrc => DefParamId => defparam_srcs, + GenerateRegionSrc => GenerateRegionId => generate_region_srcs, + SpecifyBlockSrc => SpecifyBlockId => specify_block_srcs, + SpecifyItemSrc => SpecifyItemId => specify_item_srcs, + DeclarationSrc => DeclarationId => declaration_srcs, + TypedefSrc => TypedefId => typedef_srcs, + StructSrc => StructId => struct_srcs, + SubroutineSrc => LocalSubroutineId => subroutine_srcs, + ModportSrc => ModportId => modport_srcs, + ClockingBlockSrc => ClockingBlockId => clocking_block_srcs, + CheckerSrc => CheckerId => checker_srcs, + CovergroupSrc => CovergroupId => covergroup_srcs, + CoverpointSrc => CoverpointId => coverpoint_srcs, + CrossSrc => CrossId => cross_srcs, + InstantiationSrc => InstantiationId => instantiation_srcs, + ParamAssignSrc => ParamAssignId => inst_param_assign_srcs, + InstanceSrc => InstanceId => instance_srcs, + PortConnSrc => PortConnId => inst_port_conn_srcs, + ProcSrc => ProcId => proc_srcs, + ExprSrc => ExprId => expr_srcs, + EventExprSrc => EventExprId => event_expr_srcs, + DeclaratorSrc => DeclId => decl_srcs, + StmtSrc => StmtId => stmt_srcs, + BlockSrc => LocalBlockId => stmt_srcs, +); + #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct ModuleSrc { pub file_id: HirFileId, @@ -368,83 +457,43 @@ pub type LocalModuleId = Idx; pub type ModuleId = InFile; pub type PackageId = ModuleId; -pub(crate) struct LowerModuleCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) module_id: ModuleId, - pub(crate) default_net_type: NetKind, - - pub(crate) module: &'a mut Module, - pub(crate) module_source_map: &'a mut ModuleSourceMap, - pub(crate) region_tree: RegionTreeBuilder, -} - -impl_lower_expr!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_decl!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_event_expr!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_stmt!(LowerModuleCtx<'_>, module_id, module, module_source_map); -impl_lower_declaration!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_cont_assign!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_defparam!(LowerModuleCtx<'_>, module, module_source_map); -impl_lower_instantiation!(LowerModuleCtx<'_>, module, module_source_map); - -impl LowerProc for LowerModuleCtx<'_> { - fn proc_ctx(&mut self) -> LowerProcCtx<'_> { - LowerProcCtx { - db: self.db, - file_id: self.file_id, - cont_id: self.module_id.into(), - - procs: &mut self.module.procs, - proc_srcs: &mut self.module_source_map.proc_srcs, - - stmts: &mut self.module.stmts, - stmt_srcs: &mut self.module_source_map.stmt_srcs, - - exprs: &mut self.module.exprs, - expr_srcs: &mut self.module_source_map.expr_srcs, - - event_exprs: &mut self.module.event_exprs, - event_expr_srcs: &mut self.module_source_map.event_expr_srcs, - - decls: &mut self.module.decls, - decl_srcs: &mut self.module_source_map.decl_srcs, - } - } -} +pub(crate) type LowerModuleCtx<'a> = LoweringCtx<'a, ModuleStore<'a>>; impl LowerModuleCtx<'_> { fn lower_struct_type(&mut self, struct_ty: ast::StructUnionType) -> StructId { - let container_id = ArenaOwnerId::Module(self.module_id); - let struct_def = - lower_struct_def(struct_ty, container_id, |ty| self.expr_ctx().lower_data_ty(ty)); - - alloc_idx_and_src! { - self.file_id; - struct_def => self.module.structs, - struct_ty => self.module_source_map.struct_srcs, - } + let container_id = ArenaOwnerId::Module(self.module_id()); + let struct_def = lower_struct_def(struct_ty, container_id, |ty| self.lower_data_ty(ty)); + + alloc_with_source( + self.file_id, + &mut self.store.data.structs, + &mut self.store.sources.struct_srcs, + struct_def, + struct_ty, + ) } fn lower_typedef(&mut self, typedef: ast::TypedefDeclaration) -> TypedefId { let name = lower_ident_opt(typedef.name()); - let typedef_id = alloc_idx_and_src! { - self.file_id; - Typedef { name, ty: None } => self.module.typedefs, - typedef => self.module_source_map.typedef_srcs, - }; + let typedef_id = alloc_with_source( + self.file_id, + &mut self.store.data.typedefs, + &mut self.store.sources.typedef_srcs, + Typedef { name, ty: None }, + typedef, + ); let data_ty = typedef.type_(); let lowered_ty = lower_typedef_data_ty( self, data_ty, - ArenaOwnerId::Module(self.module_id), + ArenaOwnerId::Module(self.module_id()), |ctx, struct_ty| ctx.lower_struct_type(struct_ty), - |ctx, ty| ctx.expr_ctx().lower_data_ty(ty), + |ctx, ty| ctx.lower_data_ty(ty), ); - self.module.typedefs[typedef_id].ty = Some(lowered_ty); + self.store.data.typedefs[typedef_id].ty = Some(lowered_ty); typedef_id } @@ -453,34 +502,36 @@ impl LowerModuleCtx<'_> { &mut self, func: ast::FunctionDeclaration, ) -> Option { - let subroutine = lower_subroutine(&func, |ty| self.expr_ctx().lower_data_ty(ty))?; - - let subroutine_id = alloc_idx_and_src! { - self.file_id; - subroutine => self.module.subroutines, - func => self.module_source_map.subroutine_srcs, - }; + let subroutine = lower_subroutine(&func, |ty| self.lower_data_ty(ty))?; + + let subroutine_id = alloc_with_source( + self.file_id, + &mut self.store.data.subroutines, + &mut self.store.sources.subroutine_srcs, + subroutine, + func, + ); let subroutine_def_id = - SubroutineScope::new(SubroutineParent::Module(self.module_id), subroutine_id); + SubroutineScope::new(SubroutineParent::Module(self.module_id()), subroutine_id); if func.end().is_some() { - let subroutine = &mut self.module.subroutines[subroutine_id]; + let subroutine = &mut self.store.data.subroutines[subroutine_id]; let mut subroutine_source_map = std::mem::take(&mut subroutine.source_map); - let mut ctx = LowerSubroutineBodyCtx { - db: self.db, - file_id: self.file_id, - subroutine_id: subroutine_def_id, - subroutine, - subroutine_source_map: &mut subroutine_source_map, - region_tree: RegionTreeBuilder::new(), - }; + let mut ctx = LoweringCtx::new( + self.db, + self.file_id, + subroutine_def_id.into(), + SubroutineStore { data: subroutine, sources: &mut subroutine_source_map }, + ); lower_subroutine_body(&mut ctx, func); + ctx.emit_diagnostics(); + drop(ctx); subroutine.source_map = subroutine_source_map; subroutine.source_map.shrink_to_fit(); } - self.module.subroutines[subroutine_id].shrink_to_fit(); + self.store.data.subroutines[subroutine_id].shrink_to_fit(); Some(subroutine_id) } @@ -495,31 +546,37 @@ impl LowerModuleCtx<'_> { match member { ast::Member::Coverpoint(coverpoint_ast) => { let coverpoint = lower_coverpoint(coverpoint_ast); - let coverpoint_id = alloc_idx_and_src! { - self.file_id; - coverpoint => self.module.coverpoints, - coverpoint_ast => self.module_source_map.coverpoint_srcs, - }; + let coverpoint_id = alloc_with_source( + self.file_id, + &mut self.store.data.coverpoints, + &mut self.store.sources.coverpoint_srcs, + coverpoint, + coverpoint_ast, + ); covergroup.coverpoints.push(coverpoint_id); } ast::Member::CoverCross(cross_ast) => { let cross = lower_cross(cross_ast); - let cross_id = alloc_idx_and_src! { - self.file_id; - cross => self.module.crosses, - cross_ast => self.module_source_map.cross_srcs, - }; + let cross_id = alloc_with_source( + self.file_id, + &mut self.store.data.crosses, + &mut self.store.sources.cross_srcs, + cross, + cross_ast, + ); covergroup.crosses.push(cross_id); } _ => {} } } - alloc_idx_and_src! { - self.file_id; - covergroup => self.module.covergroups, - covergroup_decl => self.module_source_map.covergroup_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.covergroups, + &mut self.store.sources.covergroup_srcs, + covergroup, + covergroup_decl, + ) } pub(crate) fn lower_module_decl(&mut self, decl: ast::ModuleDeclaration) { @@ -528,22 +585,22 @@ impl LowerModuleCtx<'_> { if let Some(param_ports) = header.parameters() { let mut inherited_kind = ParamDeclKind::Parameter; for decls in param_ports.declarations().children() { - let decl_id = self.declaration_ctx().lower_param_decl_base_with_context( + let decl_id = self.lower_param_decl_base_with_context( decls, Some(inherited_kind), false, true, ); - if let Declaration::ParamDecl(param_decl) = self.module.get(decl_id) { + if let Declaration::ParamDecl(param_decl) = self.store.data.get(decl_id) { inherited_kind = param_decl.kind; } self.region_tree.handle_node(decls.syntax()); } - let beg = Idx::from_raw(RawIdx::from(0)); - let end = self.module.decls.nxt_idx(); - if beg != end { - self.module.param_ports = Some(IdxRange::new(beg..end)); + let mut decls = self.store.data.decls.iter().map(|(id, _)| id); + if let Some(first) = decls.next() { + let last = decls.next_back().unwrap_or(first); + self.store.data.param_ports = Some(IdxRange::new_inclusive(first..=last)); } self.region_tree.stage(param_ports.close_paren(), param_ports.syntax()); @@ -560,18 +617,13 @@ impl LowerModuleCtx<'_> { use ast::Member::*; let idx = match member { // Assignments - ContinuousAssign(assign) => { - self.cont_assign_ctx().lower_continuous_assign(assign).into() - } + ContinuousAssign(assign) => self.lower_continuous_assign(assign).into(), // Declarations - DataDeclaration(data_decl) => { - self.declaration_ctx().lower_data_decl(data_decl).into() - } - NetDeclaration(net_decl) => self.declaration_ctx().lower_net_decl(net_decl).into(), + DataDeclaration(data_decl) => self.lower_data_decl(data_decl).into(), + NetDeclaration(net_decl) => self.lower_net_decl(net_decl).into(), LocalVariableDeclaration(_) => continue, ParameterDeclarationStatement(param_decl) => self - .declaration_ctx() .lower_param_decl_base_with_context( param_decl.parameter(), None, @@ -580,9 +632,7 @@ impl LowerModuleCtx<'_> { ) .into(), TypedefDeclaration(typedef_decl) => self.lower_typedef(typedef_decl).into(), - GenvarDeclaration(genvar_decl) => { - self.declaration_ctx().lower_genvar_decl(genvar_decl).into() - } + GenvarDeclaration(genvar_decl) => self.lower_genvar_decl(genvar_decl).into(), NetTypeDeclaration(_) | ForwardTypedefDeclaration(_) | UserDefinedNetDeclaration(_) => { @@ -591,13 +641,13 @@ impl LowerModuleCtx<'_> { // Instantiations HierarchyInstantiation(instantiation) => { - self.instantiation_ctx().lower_instantiation(instantiation).into() + self.lower_instantiation(instantiation).into() } PrimitiveInstantiation(instantiation) => { - self.instantiation_ctx().lower_primitive_instantiation(instantiation).into() + self.lower_primitive_instantiation(instantiation).into() } CheckerInstantiation(instantiation) => { - self.instantiation_ctx().lower_checker_instantiation(instantiation).into() + self.lower_checker_instantiation(instantiation).into() } // Subroutines @@ -607,7 +657,7 @@ impl LowerModuleCtx<'_> { }, // Procedural blocks - ProceduralBlock(proc) => self.proc_ctx().lower_proc(proc).into(), + ProceduralBlock(proc) => self.lower_proc(proc).into(), // Ports PortDeclaration(port) => self.lower_port_decl(port).into(), @@ -616,7 +666,7 @@ impl LowerModuleCtx<'_> { // Imports PackageImportDeclaration(import_decl) => { for import in lower_package_imports(import_decl) { - self.module.package_imports.alloc(import); + self.store.data.package_imports.alloc(import); } continue; } @@ -665,7 +715,7 @@ impl LowerModuleCtx<'_> { PulseStyleDeclaration(pulse) => self.lower_pulse_style_item(pulse).into(), DefaultSkewItem(_) => continue, SpecparamDeclaration(specparam_decl) => { - self.declaration_ctx().lower_specparam_decl(specparam_decl).into() + self.lower_specparam_decl(specparam_decl).into() } // DPI and external @@ -679,7 +729,7 @@ impl LowerModuleCtx<'_> { UdpDeclaration(_) => continue, // Defparam - DefParam(defparam) => self.defparam_ctx().lower_defparam(defparam).into(), + DefParam(defparam) => self.lower_defparam(defparam).into(), // Net alias NetAlias(_) => continue, @@ -687,7 +737,7 @@ impl LowerModuleCtx<'_> { // Modport ModportDeclaration(modport) => { for modport_id in self.lower_modport_declaration(modport) { - self.module_source_map.items.push(modport_id.into()); + self.store.sources.items.push(modport_id.into()); } self.region_tree.handle_node(member.syntax()); continue; @@ -735,11 +785,11 @@ impl LowerModuleCtx<'_> { // Empty member - skip EmptyMember(_) => continue, }; - self.module_source_map.items.push(idx); + self.store.sources.items.push(idx); self.region_tree.handle_node(member.syntax()); } self.region_tree.stage(decl.endmodule(), decl.syntax()); - self.module_source_map.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.region_tree.finish(); } } @@ -759,16 +809,14 @@ pub(crate) fn module_with_source_map_query( return (Arc::new(module), Arc::new(module_source_map)); }; - let mut lower_ctx = LowerModuleCtx { + let mut lower_ctx = LoweringCtx::new( db, - default_net_type: NetKind::Wire, file_id, - module_id, - module: &mut module, - module_source_map: &mut module_source_map, - region_tree: RegionTreeBuilder::new(), - }; + module_id.into(), + ModuleStore { data: &mut module, sources: &mut module_source_map }, + ); lower_ctx.lower_module_decl(ast_module); + lower_ctx.emit_diagnostics(); module.shrink_to_fit(); module_source_map.shrink_to_fit(); diff --git a/crates/hir/src/hir_def/module/clocking.rs b/crates/hir/src/hir_def/module/clocking.rs index 0572c5573..5169febf1 100644 --- a/crates/hir/src/hir_def/module/clocking.rs +++ b/crates/hir/src/hir_def/module/clocking.rs @@ -11,11 +11,7 @@ use utils::text_edit::TextRange; use super::{LowerModuleCtx, port::PortDirection}; use crate::{ - hir_def::{ - Ident, alloc_idx_and_src, - expr::timing_control::{EventExprId, LowerEventExpr}, - lower_ident_opt, - }, + hir_def::{Ident, alloc_with_source, expr::timing_control::EventExprId, lower_ident_opt}, source_map::{FromSourceAst, IsNamedSrc, IsSrc, SourceAst, root_token_in}, }; @@ -133,16 +129,8 @@ impl<'a> FromSourceAst<'a, ast::ClockingDeclaration<'a>> for ClockingBlockSrc { } } -pub(crate) trait LowerClocking { - fn lower_clocking_declaration( - &mut self, - clocking: ast::ClockingDeclaration<'_>, - ) -> ClockingBlockId; - fn lower_default_clocking_reference(&mut self, reference: ast::DefaultClockingReference<'_>); -} - -impl LowerClocking for LowerModuleCtx<'_> { - fn lower_clocking_declaration( +impl LowerModuleCtx<'_> { + pub(crate) fn lower_clocking_declaration( &mut self, clocking: ast::ClockingDeclaration<'_>, ) -> ClockingBlockId { @@ -152,20 +140,29 @@ impl LowerClocking for LowerModuleCtx<'_> { Some(TokenKind::GLOBAL_KEYWORD) => ClockingBlockKind::Global, _ => ClockingBlockKind::Regular, }; - let event = self.event_expr_ctx().lower_event_expr(clocking.event()); + let event = self.lower_event_expr(clocking.event()); let signals = lower_clocking_signals(clocking); - alloc_idx_and_src! { - self.file_id; - ClockingBlockDef { name, kind, event, signals } => self.module.clocking_blocks, - clocking => self.module_source_map.clocking_block_srcs, - } + let file_id = self.file_id; + let (clocking_blocks, sources) = + (&mut self.store.data.clocking_blocks, &mut self.store.sources.clocking_block_srcs); + alloc_with_source( + file_id, + clocking_blocks, + sources, + ClockingBlockDef { name, kind, event, signals }, + clocking, + ) } - fn lower_default_clocking_reference(&mut self, reference: ast::DefaultClockingReference<'_>) { - self.module.default_clocking = - Some(DefaultClockingRef { name: lower_ident_opt(reference.name()) }); - self.module_source_map.default_clocking_src = + pub(crate) fn lower_default_clocking_reference( + &mut self, + reference: ast::DefaultClockingReference<'_>, + ) { + let source = SourceAst::new(self.file_id, reference).map(DefaultClockingRefSrc::from_source_ast); + self.store.data.default_clocking = + Some(DefaultClockingRef { name: lower_ident_opt(reference.name()) }); + self.store.sources.default_clocking_src = source; } } diff --git a/crates/hir/src/hir_def/module/continuous_assgin.rs b/crates/hir/src/hir_def/module/continuous_assgin.rs index d1a159995..d45b9b2bd 100644 --- a/crates/hir/src/hir_def/module/continuous_assgin.rs +++ b/crates/hir/src/hir_def/module/continuous_assgin.rs @@ -1,22 +1,18 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use smallvec::SmallVec; use syntax::ast; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - alloc_idx_and_src, + alloc_with_source, expr::{ - Assign, Expr, ExprSrc, LowerExpr, impl_lower_expr, - timing_control::{ - DelayControl, EventExpr, EventExprSrc, LowerEventExpr, TimingControl, - impl_lower_event_expr, - }, + Assign, + timing_control::{DelayControl, TimingControl}, }, + lower::{LoweringCtx, ModuleItemStore}, ty::{DriveStrength, lower_drive_strength}, }, - source_map::{AstId, AstKind, SourceMap}, + source_map::{AstId, AstKind}, }; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -37,70 +33,25 @@ impl AstKind for ContinuousAssignAst { pub type ContAssignSrc = AstId; -pub(crate) struct LowerContAssignCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - - pub(crate) cont_assigns: &'a mut Arena, - pub(crate) assign_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, - - pub(crate) event_exprs: &'a mut Arena, - pub(crate) event_expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerContAssign: LowerExpr + LowerEventExpr { - fn cont_assign_ctx(&mut self) -> LowerContAssignCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_cont_assign($ctx:ty, $data:ident, $src_map:ident) { - impl $crate::hir_def::module::continuous_assgin::LowerContAssign for $ctx { - fn cont_assign_ctx( - &mut self, - ) -> $crate::hir_def::module::continuous_assgin::LowerContAssignCtx<'_> { - $crate::hir_def::module::continuous_assgin::LowerContAssignCtx { - db: self.db, - file_id: self.file_id, - cont_assigns: &mut self.$data.cont_assigns, - assign_srcs: &mut self.$src_map.assign_srcs, - exprs: &mut self.$data.exprs, - expr_srcs: &mut self.$src_map.expr_srcs, - event_exprs: &mut self.$data.event_exprs, - event_expr_srcs: &mut self.$src_map.event_expr_srcs, - } - } - } -} - -impl_lower_expr!(LowerContAssignCtx<'_>); -impl_lower_event_expr!(LowerContAssignCtx<'_>); - -impl LowerContAssignCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_continuous_assign( &mut self, assign: ast::ContinuousAssign, ) -> ContAssignId { let strength = assign.strength().map(lower_drive_strength); let delay = assign.delay().and_then(|control| { - let control = self.event_expr_ctx().lower_timing_control(control); + let control = self.lower_timing_control(control); match control { TimingControl::DelayControl(control) => Some(control), _ => None, } }); - let assigns = assign - .assignments() - .children() - .flat_map(|assign| self.expr_ctx().lower_assign(assign)) - .collect(); + let assigns = + assign.assignments().children().flat_map(|assign| self.lower_assign(assign)).collect(); let continuous_assign = ContAssign { strength, delay, assigns }; - alloc_idx_and_src! { - self.file_id; - continuous_assign => self.cont_assigns, - assign => self.assign_srcs, - } + let file_id = self.file_id; + let (continuous_assigns, sources) = self.continuous_assigns(); + alloc_with_source(file_id, continuous_assigns, sources, continuous_assign, assign) } } diff --git a/crates/hir/src/hir_def/module/defparam.rs b/crates/hir/src/hir_def/module/defparam.rs index 7bc261d3b..4d8eb099c 100644 --- a/crates/hir/src/hir_def/module/defparam.rs +++ b/crates/hir/src/hir_def/module/defparam.rs @@ -1,15 +1,14 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use smallvec::SmallVec; use syntax::ast::{self, AstNode}; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - alloc_idx_and_src, - expr::{Expr, ExprId, ExprSrc, LowerExpr, impl_lower_expr}, + alloc_with_source, + expr::ExprId, + lower::{LoweringCtx, ModuleItemStore}, }, - source_map::{AstId, AstKind, SourceMap}, + source_map::{AstId, AstKind}, }; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -34,56 +33,20 @@ impl AstKind for DefParamAst { pub type DefParamSrc = AstId; -pub(crate) struct LowerDefParamCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - - pub(crate) defparams: &'a mut Arena, - pub(crate) defparam_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerDefParam: LowerExpr { - fn defparam_ctx(&mut self) -> LowerDefParamCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_defparam($ctx:ty, $data:ident, $src_map:ident) { - impl $crate::hir_def::module::defparam::LowerDefParam for $ctx { - fn defparam_ctx(&mut self) -> $crate::hir_def::module::defparam::LowerDefParamCtx<'_> { - $crate::hir_def::module::defparam::LowerDefParamCtx { - db: self.db, - file_id: self.file_id, - defparams: &mut self.$data.defparams, - defparam_srcs: &mut self.$src_map.defparam_srcs, - exprs: &mut self.$data.exprs, - expr_srcs: &mut self.$src_map.expr_srcs, - } - } - } -} - -impl_lower_expr!(LowerDefParamCtx<'_>); - -impl LowerDefParamCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_defparam(&mut self, defparam: ast::DefParam) -> DefParamId { let assignments = defparam .assignments() .children() .map(|assignment| { - let target = self - .expr_ctx() - .lower_expr_opt(ast::Expression::cast(assignment.name().syntax())); - let value = self.expr_ctx().lower_expr(assignment.setter().expr()); + let target = self.lower_expr_opt(ast::Expression::cast(assignment.name().syntax())); + let value = self.lower_expr(assignment.setter().expr()); DefParamAssignment { target, value } }) .collect(); - alloc_idx_and_src! { - self.file_id; - DefParam { assignments } => self.defparams, - defparam => self.defparam_srcs, - } + let file_id = self.file_id; + let (defparams, sources) = self.defparams(); + alloc_with_source(file_id, defparams, sources, DefParam { assignments }, defparam) } } diff --git a/crates/hir/src/hir_def/module/generate.rs b/crates/hir/src/hir_def/module/generate.rs index 2d8e960db..15eca87ba 100644 --- a/crates/hir/src/hir_def/module/generate.rs +++ b/crates/hir/src/hir_def/module/generate.rs @@ -1,5 +1,4 @@ use la_arena::{Arena, Idx}; -use proc_macro_utils::define_container; use smallvec::SmallVec; use syntax::{ SyntaxToken, TokenKind, @@ -12,44 +11,37 @@ use utils::define_enum_deriving_from; use super::{ LowerModuleCtx, - continuous_assgin::{ - ContAssign, ContAssignId, ContAssignSrc, LowerContAssign, impl_lower_cont_assign, - }, - defparam::{DefParam, DefParamId, DefParamSrc, LowerDefParam, impl_lower_defparam}, + continuous_assgin::{ContAssign, ContAssignId, ContAssignSrc}, + defparam::{DefParam, DefParamId, DefParamSrc}, instantiation::{ - Instance, InstanceSrc, Instantiation, InstantiationId, InstantiationSrc, - LowerInstantiation, ParamAssign, ParamAssignSrc, PortConn, PortConnSrc, - impl_lower_instantiation, + Instance, InstanceId, InstanceSrc, Instantiation, InstantiationId, InstantiationSrc, + ParamAssign, ParamAssignId, ParamAssignSrc, PortConn, PortConnId, PortConnSrc, }, }; use crate::{ base_db::intern::Lookup, container::{ArenaOwnerId, InFile, SubroutineParent, SubroutineScope}, - db::{HirDb, InternDb}, - file::HirFileId, + db::HirDb, hir_def::{ Ident, aggregate::{StructDef, StructId, StructSrc, lower_struct_def}, - alloc_idx_and_src, - declaration::{ - Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, impl_lower_declaration, - }, + alloc_with_optional_source_entry, alloc_with_source, + declaration::{Declaration, DeclarationId, DeclarationSrc}, expr::{ - Expr, ExprId, ExprSrc, LowerExpr, - declarator::{Declarator, DeclaratorSrc, impl_lower_decl}, - impl_lower_expr, - timing_control::{EventExpr, EventExprSrc, impl_lower_event_expr}, + Expr, ExprId, ExprSrc, + declarator::{DeclId, Declarator, DeclaratorSrc}, + timing_control::{EventExpr, EventExprId, EventExprSrc}, }, + lower::{GenerateBlockStore, LoweringCtx, SubroutineStore}, lower_ident_opt, - proc::{LowerProc, LowerProcCtx, Proc, ProcId, ProcSrc}, - stmt::{Stmt, StmtId, StmtSrc, impl_lower_stmt}, + proc::{Proc, ProcId, ProcSrc}, + stmt::{Stmt, StmtId, StmtSrc}, subroutine::{ - LocalSubroutineId, LowerSubroutineBodyCtx, Subroutine, SubroutineSrc, lower_subroutine, - lower_subroutine_body, + LocalSubroutineId, Subroutine, SubroutineSrc, lower_subroutine, lower_subroutine_body, }, typedef::{Typedef, TypedefId, TypedefSrc, lower_typedef_data_ty}, }, - region_tree::{RegionTree, RegionTreeBuilder}, + region_tree::RegionTree, source_map::{ FromSourceAst, IsNamedSrc, IsSrc, SourceAst, SourceMap, ToAstNode, root_token_in, }, @@ -287,69 +279,130 @@ fn generate_block_name(block: ast::GenerateBlock<'_>) -> Option> .or_else(|| block.begin_name().and_then(|name| name.name())) } -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct GenerateBlock { - name: Option, - kind: GenerateBlockKind, - - items: Vec, - region_tree: RegionTree, - - cont_assigns: [ContAssign], - defparams: [DefParam], - declarations: [Declaration], - typedefs: [Typedef], - structs: [StructDef], - subroutines: [Subroutine], - - instantiations: [Instantiation], - inst_param_assigns: [ParamAssign], - instances: [Instance], - inst_port_conns: [PortConn], - - procs: [Proc], - - exprs: [Expr], - event_exprs: [EventExpr], - decls: [Declarator], - stmts: [Stmt] => { - [StmtId | Stmt], - [crate::hir_def::block::LocalBlockId | crate::hir_def::block::BlockInfo], - }, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct GenerateBlock { + pub name: Option, + pub kind: GenerateBlockKind, + pub items: Vec, + pub region_tree: RegionTree, + pub cont_assigns: Arena, + pub defparams: Arena, + pub declarations: Arena, + pub typedefs: Arena, + pub structs: Arena, + pub subroutines: Arena, + pub instantiations: Arena, + pub inst_param_assigns: Arena, + pub instances: Arena, + pub inst_port_conns: Arena, + pub procs: Arena, + pub exprs: Arena, + pub event_exprs: Arena, + pub decls: Arena, + pub stmts: Arena, +} + +impl GenerateBlock { + pub fn shrink_to_fit(&mut self) { + self.cont_assigns.shrink_to_fit(); + self.defparams.shrink_to_fit(); + self.declarations.shrink_to_fit(); + self.typedefs.shrink_to_fit(); + self.structs.shrink_to_fit(); + self.subroutines.shrink_to_fit(); + self.instantiations.shrink_to_fit(); + self.inst_param_assigns.shrink_to_fit(); + self.instances.shrink_to_fit(); + self.inst_port_conns.shrink_to_fit(); + self.procs.shrink_to_fit(); + self.exprs.shrink_to_fit(); + self.event_exprs.shrink_to_fit(); + self.decls.shrink_to_fit(); + self.stmts.shrink_to_fit(); } } -define_container! { - #[derive(Default, Debug, PartialEq, Eq)] - pub struct GenerateBlockSourceMap { - items: Vec, - region_tree: RegionTree, - - assign_srcs: [ContAssign | ContAssignSrc], - defparam_srcs: [DefParam | DefParamSrc], - declaration_srcs: [Declaration | DeclarationSrc], - typedef_srcs: [Typedef | TypedefSrc], - struct_srcs: [StructDef | StructSrc], - subroutine_srcs: [Subroutine | SubroutineSrc], - - instantiation_srcs: [Instantiation | InstantiationSrc], - inst_param_assign_srcs: [ParamAssign | ParamAssignSrc], - instance_srcs: [Instance | InstanceSrc], - inst_port_conn_srcs: [PortConn | PortConnSrc], - - proc_srcs: [Proc | ProcSrc], - - expr_srcs: [Expr | ExprSrc], - event_expr_srcs: [EventExpr | EventExprSrc], - decl_srcs: [Declarator | DeclaratorSrc], - stmt_srcs: [Stmt | StmtSrc] => { - [StmtId | StmtSrc], - [crate::hir_def::block::LocalBlockId | crate::hir_def::block::BlockSrc], - }, +#[derive(Default, Debug, PartialEq, Eq)] +pub struct GenerateBlockSourceMap { + pub items: Vec, + pub region_tree: RegionTree, + pub assign_srcs: SourceMap, + pub defparam_srcs: SourceMap, + pub declaration_srcs: SourceMap, + pub typedef_srcs: SourceMap, + pub struct_srcs: SourceMap, + pub subroutine_srcs: SourceMap, + pub instantiation_srcs: SourceMap, + pub inst_param_assign_srcs: SourceMap, + pub instance_srcs: SourceMap, + pub inst_port_conn_srcs: SourceMap, + pub proc_srcs: SourceMap, + pub expr_srcs: SourceMap, + pub event_expr_srcs: SourceMap, + pub decl_srcs: SourceMap, + pub stmt_srcs: SourceMap, +} + +impl GenerateBlockSourceMap { + pub fn shrink_to_fit(&mut self) { + self.assign_srcs.shrink_to_fit(); + self.defparam_srcs.shrink_to_fit(); + self.declaration_srcs.shrink_to_fit(); + self.typedef_srcs.shrink_to_fit(); + self.struct_srcs.shrink_to_fit(); + self.subroutine_srcs.shrink_to_fit(); + self.instantiation_srcs.shrink_to_fit(); + self.inst_param_assign_srcs.shrink_to_fit(); + self.instance_srcs.shrink_to_fit(); + self.inst_port_conn_srcs.shrink_to_fit(); + self.proc_srcs.shrink_to_fit(); + self.expr_srcs.shrink_to_fit(); + self.event_expr_srcs.shrink_to_fit(); + self.decl_srcs.shrink_to_fit(); + self.stmt_srcs.shrink_to_fit(); } } +crate::hir_def::impl_arena_getters!( + GenerateBlock; + ContAssignId => cont_assigns => ContAssign, + DefParamId => defparams => DefParam, + DeclarationId => declarations => Declaration, + TypedefId => typedefs => Typedef, + StructId => structs => StructDef, + LocalSubroutineId => subroutines => Subroutine, + InstantiationId => instantiations => Instantiation, + ParamAssignId => inst_param_assigns => ParamAssign, + InstanceId => instances => Instance, + PortConnId => inst_port_conns => PortConn, + ProcId => procs => Proc, + ExprId => exprs => Expr, + EventExprId => event_exprs => EventExpr, + DeclId => decls => Declarator, + StmtId => stmts => Stmt, + crate::hir_def::block::LocalBlockId => stmts => crate::hir_def::block::BlockInfo, +); + +crate::hir_def::impl_source_map_getters!( + GenerateBlockSourceMap; + ContAssignSrc => ContAssignId => assign_srcs, + DefParamSrc => DefParamId => defparam_srcs, + DeclarationSrc => DeclarationId => declaration_srcs, + TypedefSrc => TypedefId => typedef_srcs, + StructSrc => StructId => struct_srcs, + SubroutineSrc => LocalSubroutineId => subroutine_srcs, + InstantiationSrc => InstantiationId => instantiation_srcs, + ParamAssignSrc => ParamAssignId => inst_param_assign_srcs, + InstanceSrc => InstanceId => instance_srcs, + PortConnSrc => PortConnId => inst_port_conn_srcs, + ProcSrc => ProcId => proc_srcs, + ExprSrc => ExprId => expr_srcs, + EventExprSrc => EventExprId => event_expr_srcs, + DeclaratorSrc => DeclId => decl_srcs, + StmtSrc => StmtId => stmt_srcs, + crate::hir_def::block::BlockSrc => crate::hir_def::block::LocalBlockId => stmt_srcs, +); + define_enum_deriving_from! { #[derive(Debug, PartialEq, Eq, Clone)] pub enum GenerateItem { @@ -401,88 +454,43 @@ pub struct GenerateBlockLoc { pub src: InFile, } -pub(crate) struct LowerGenerateBlockCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) generate_block_id: GenerateBlockId, - - pub(crate) generate_block: &'a mut GenerateBlock, - pub(crate) generate_block_source_map: &'a mut GenerateBlockSourceMap, - - pub(crate) region_tree: RegionTreeBuilder, -} - -impl_lower_expr!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_decl!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_event_expr!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_stmt!( - LowerGenerateBlockCtx<'_>, - generate_block_id, - generate_block, - generate_block_source_map -); -impl_lower_declaration!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_cont_assign!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_defparam!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); -impl_lower_instantiation!(LowerGenerateBlockCtx<'_>, generate_block, generate_block_source_map); - -impl LowerProc for LowerGenerateBlockCtx<'_> { - fn proc_ctx(&mut self) -> LowerProcCtx<'_> { - LowerProcCtx { - db: self.db, - file_id: self.file_id, - cont_id: self.generate_block_id.into(), - - procs: &mut self.generate_block.procs, - proc_srcs: &mut self.generate_block_source_map.proc_srcs, - - stmts: &mut self.generate_block.stmts, - stmt_srcs: &mut self.generate_block_source_map.stmt_srcs, - - exprs: &mut self.generate_block.exprs, - expr_srcs: &mut self.generate_block_source_map.expr_srcs, - - event_exprs: &mut self.generate_block.event_exprs, - event_expr_srcs: &mut self.generate_block_source_map.event_expr_srcs, - - decls: &mut self.generate_block.decls, - decl_srcs: &mut self.generate_block_source_map.decl_srcs, - } - } -} +pub(crate) type LowerGenerateBlockCtx<'a> = LoweringCtx<'a, GenerateBlockStore<'a>>; impl LowerGenerateBlockCtx<'_> { fn lower_struct_type(&mut self, struct_ty: ast::StructUnionType) -> StructId { - let container_id = ArenaOwnerId::GenerateBlock(self.generate_block_id); - let struct_def = - lower_struct_def(struct_ty, container_id, |ty| self.expr_ctx().lower_data_ty(ty)); - - alloc_idx_and_src! { - self.file_id; - struct_def => self.generate_block.structs, - struct_ty => self.generate_block_source_map.struct_srcs, - } + let container_id = ArenaOwnerId::GenerateBlock(self.generate_block_id()); + let struct_def = lower_struct_def(struct_ty, container_id, |ty| self.lower_data_ty(ty)); + + alloc_with_source( + self.file_id, + &mut self.store.data.structs, + &mut self.store.sources.struct_srcs, + struct_def, + struct_ty, + ) } fn lower_typedef(&mut self, typedef: ast::TypedefDeclaration) -> TypedefId { let name = lower_ident_opt(typedef.name()); - let typedef_id = alloc_idx_and_src! { - self.file_id; - Typedef { name, ty: None } => self.generate_block.typedefs, - typedef => self.generate_block_source_map.typedef_srcs, - }; + let typedef_id = alloc_with_source( + self.file_id, + &mut self.store.data.typedefs, + &mut self.store.sources.typedef_srcs, + Typedef { name, ty: None }, + typedef, + ); let data_ty = typedef.type_(); let lowered_ty = lower_typedef_data_ty( self, data_ty, - ArenaOwnerId::GenerateBlock(self.generate_block_id), + ArenaOwnerId::GenerateBlock(self.generate_block_id()), |ctx, struct_ty| ctx.lower_struct_type(struct_ty), - |ctx, ty| ctx.expr_ctx().lower_data_ty(ty), + |ctx, ty| ctx.lower_data_ty(ty), ); - self.generate_block.typedefs[typedef_id].ty = Some(lowered_ty); + self.store.data.typedefs[typedef_id].ty = Some(lowered_ty); typedef_id } @@ -491,43 +499,45 @@ impl LowerGenerateBlockCtx<'_> { &mut self, func: ast::FunctionDeclaration, ) -> Option { - let subroutine = lower_subroutine(&func, |ty| self.expr_ctx().lower_data_ty(ty))?; - - let subroutine_id = alloc_idx_and_src! { - self.file_id; - subroutine => self.generate_block.subroutines, - func => self.generate_block_source_map.subroutine_srcs, - }; + let subroutine = lower_subroutine(&func, |ty| self.lower_data_ty(ty))?; + + let subroutine_id = alloc_with_source( + self.file_id, + &mut self.store.data.subroutines, + &mut self.store.sources.subroutine_srcs, + subroutine, + func, + ); let subroutine_def_id = SubroutineScope::new( - SubroutineParent::GenerateBlock(self.generate_block_id), + SubroutineParent::GenerateBlock(self.generate_block_id()), subroutine_id, ); if func.end().is_some() { - let subroutine = &mut self.generate_block.subroutines[subroutine_id]; + let subroutine = &mut self.store.data.subroutines[subroutine_id]; let mut subroutine_source_map = std::mem::take(&mut subroutine.source_map); - let mut ctx = LowerSubroutineBodyCtx { - db: self.db, - file_id: self.file_id, - subroutine_id: subroutine_def_id, - subroutine, - subroutine_source_map: &mut subroutine_source_map, - region_tree: RegionTreeBuilder::new(), - }; + let mut ctx = LoweringCtx::new( + self.db, + self.file_id, + subroutine_def_id.into(), + SubroutineStore { data: subroutine, sources: &mut subroutine_source_map }, + ); lower_subroutine_body(&mut ctx, func); + ctx.emit_diagnostics(); + drop(ctx); subroutine.source_map = subroutine_source_map; subroutine.source_map.shrink_to_fit(); } - self.generate_block.subroutines[subroutine_id].shrink_to_fit(); + self.store.data.subroutines[subroutine_id].shrink_to_fit(); Some(subroutine_id) } fn intern_generate_block(&self, src: GenerateBlockSrc) -> GenerateBlockId { self.db.intern_generate_block(GenerateBlockLoc { - cont_id: self.generate_block_id.into(), + cont_id: self.generate_block_id().into(), src: InFile::new(self.file_id, src), }) } @@ -555,7 +565,7 @@ impl LowerGenerateBlockCtx<'_> { &mut self, if_generate: ast::IfGenerate, ) -> SmallVec<[GenerateBlockItem; 4]> { - self.expr_ctx().lower_expr(if_generate.condition()); + self.lower_expr(if_generate.condition()); let mut items = self.generate_block_item_from_branch(if_generate.block()); if let Some(else_clause) = if_generate.else_clause() @@ -570,7 +580,7 @@ impl LowerGenerateBlockCtx<'_> { &mut self, case_generate: ast::CaseGenerate, ) -> SmallVec<[GenerateBlockItem; 4]> { - self.expr_ctx().lower_expr(case_generate.condition()); + self.lower_expr(case_generate.condition()); let mut items = SmallVec::new(); for item in case_generate.items().children() { @@ -578,7 +588,7 @@ impl LowerGenerateBlockCtx<'_> { match item { StandardCaseItem(item) => { for expr in item.expressions().children() { - self.expr_ctx().lower_expr(expr); + self.lower_expr(expr); } if let Some(member) = ast::Member::cast(item.clause().syntax()) { items.extend(self.generate_block_item_from_branch(member)); @@ -591,7 +601,7 @@ impl LowerGenerateBlockCtx<'_> { } PatternCaseItem(item) => { if let Some(expr) = item.expr() { - self.expr_ctx().lower_expr(expr); + self.lower_expr(expr); } } } @@ -602,45 +612,39 @@ impl LowerGenerateBlockCtx<'_> { fn lower_generate_member(&mut self, member: ast::Member) -> Option { use ast::Member::*; let item = match member { - ContinuousAssign(assign) => { - self.cont_assign_ctx().lower_continuous_assign(assign).into() - } - DataDeclaration(data_decl) => self.declaration_ctx().lower_data_decl(data_decl).into(), - NetDeclaration(net_decl) => self.declaration_ctx().lower_net_decl(net_decl).into(), + ContinuousAssign(assign) => self.lower_continuous_assign(assign).into(), + DataDeclaration(data_decl) => self.lower_data_decl(data_decl).into(), + NetDeclaration(net_decl) => self.lower_net_decl(net_decl).into(), ParameterDeclarationStatement(param_decl) => { - self.declaration_ctx().lower_param_decl_base(param_decl.parameter()).into() + self.lower_param_decl_base(param_decl.parameter()).into() } TypedefDeclaration(typedef_decl) => self.lower_typedef(typedef_decl).into(), - GenvarDeclaration(genvar_decl) => { - self.declaration_ctx().lower_genvar_decl(genvar_decl).into() - } - HierarchyInstantiation(instantiation) => { - self.instantiation_ctx().lower_instantiation(instantiation).into() - } + GenvarDeclaration(genvar_decl) => self.lower_genvar_decl(genvar_decl).into(), + HierarchyInstantiation(instantiation) => self.lower_instantiation(instantiation).into(), PrimitiveInstantiation(instantiation) => { - self.instantiation_ctx().lower_primitive_instantiation(instantiation).into() + self.lower_primitive_instantiation(instantiation).into() } FunctionDeclaration(fn_decl) => self.lower_subroutine_decl(fn_decl)?.into(), - ProceduralBlock(proc) => self.proc_ctx().lower_proc(proc).into(), + ProceduralBlock(proc) => self.lower_proc(proc).into(), GenerateBlock(block) => { self.intern_generate_block(GenerateBlockSrc::from_generate_block(block)).into() } LoopGenerate(loop_generate) => self.intern_generate_block(loop_generate.into()).into(), IfGenerate(if_generate) => { for item in self.lower_if_generate_items(if_generate) { - self.generate_block.items.push(item.clone()); - self.generate_block_source_map.items.push(item); + self.store.data.items.push(item.clone()); + self.store.sources.items.push(item); } return None; } CaseGenerate(case_generate) => { for item in self.lower_case_generate_items(case_generate) { - self.generate_block.items.push(item.clone()); - self.generate_block_source_map.items.push(item); + self.store.data.items.push(item.clone()); + self.store.sources.items.push(item); } return None; } - DefParam(defparam) => self.defparam_ctx().lower_defparam(defparam).into(), + DefParam(defparam) => self.lower_defparam(defparam).into(), EmptyMember(_) => return None, _ => return None, }; @@ -649,35 +653,35 @@ impl LowerGenerateBlockCtx<'_> { } fn lower_generate_block(&mut self, block: ast::GenerateBlock) { - self.generate_block.name = + self.store.data.name = generate_block_name(block).and_then(|name| lower_ident_opt(Some(name))); - self.generate_block.kind = GenerateBlockKind::Block; + self.store.data.kind = GenerateBlockKind::Block; for member in block.members().children() { let Some(item) = self.lower_generate_member(member) else { continue; }; - self.generate_block.items.push(item.clone()); - self.generate_block_source_map.items.push(item); + self.store.data.items.push(item.clone()); + self.store.sources.items.push(item); self.region_tree.handle_node(member.syntax()); } self.region_tree.stage(block.end(), block.syntax()); - self.generate_block.region_tree = self.region_tree.finish(); - self.generate_block_source_map.region_tree = self.generate_block.region_tree.clone(); + self.store.data.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.store.data.region_tree.clone(); } fn lower_loop_generate(&mut self, loop_generate: ast::LoopGenerate) { - self.generate_block.name = loop_generate + self.store.data.name = loop_generate .block() .as_generate_block() .and_then(generate_block_name) .and_then(|name| lower_ident_opt(Some(name))); - let initial = self.expr_ctx().lower_expr(loop_generate.initial_expr()); - let stop = self.expr_ctx().lower_expr(loop_generate.stop_expr()); - let iteration = self.expr_ctx().lower_expr(loop_generate.iteration_expr()); - self.generate_block.kind = GenerateBlockKind::Loop { + let initial = self.lower_expr(loop_generate.initial_expr()); + let stop = self.lower_expr(loop_generate.stop_expr()); + let iteration = self.lower_expr(loop_generate.iteration_expr()); + self.store.data.kind = GenerateBlockKind::Loop { genvar: lower_ident_opt(loop_generate.identifier()), initial, stop, @@ -689,32 +693,32 @@ impl LowerGenerateBlockCtx<'_> { let Some(item) = self.lower_generate_member(member) else { continue; }; - self.generate_block.items.push(item.clone()); - self.generate_block_source_map.items.push(item); + self.store.data.items.push(item.clone()); + self.store.sources.items.push(item); self.region_tree.handle_node(member.syntax()); } self.region_tree.stage(block.end(), block.syntax()); } - self.generate_block.region_tree = self.region_tree.finish(); - self.generate_block_source_map.region_tree = self.generate_block.region_tree.clone(); + self.store.data.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.store.data.region_tree.clone(); } fn lower_single_member(&mut self, member: ast::Member) { if let Some(item) = self.lower_generate_member(member) { - self.generate_block.items.push(item.clone()); - self.generate_block_source_map.items.push(item); + self.store.data.items.push(item.clone()); + self.store.sources.items.push(item); } - self.generate_block.region_tree = self.region_tree.finish(); - self.generate_block_source_map.region_tree = self.generate_block.region_tree.clone(); + self.store.data.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.store.data.region_tree.clone(); } } impl LowerModuleCtx<'_> { pub(crate) fn intern_generate_block(&self, src: GenerateBlockSrc) -> GenerateBlockId { self.db.intern_generate_block(GenerateBlockLoc { - cont_id: self.module_id.into(), + cont_id: self.module_id().into(), src: InFile::new(self.file_id, src), }) } @@ -739,7 +743,7 @@ impl LowerModuleCtx<'_> { &mut self, if_generate: ast::IfGenerate, ) -> SmallVec<[GenerateItem; 4]> { - self.expr_ctx().lower_expr(if_generate.condition()); + self.lower_expr(if_generate.condition()); let mut items = self.generate_item_from_branch(if_generate.block()); if let Some(else_clause) = if_generate.else_clause() @@ -754,7 +758,7 @@ impl LowerModuleCtx<'_> { &mut self, case_generate: ast::CaseGenerate, ) -> SmallVec<[GenerateItem; 4]> { - self.expr_ctx().lower_expr(case_generate.condition()); + self.lower_expr(case_generate.condition()); let mut items = SmallVec::new(); for item in case_generate.items().children() { @@ -762,7 +766,7 @@ impl LowerModuleCtx<'_> { match item { StandardCaseItem(item) => { for expr in item.expressions().children() { - self.expr_ctx().lower_expr(expr); + self.lower_expr(expr); } if let Some(member) = ast::Member::cast(item.clause().syntax()) { items.extend(self.generate_item_from_branch(member)); @@ -775,7 +779,7 @@ impl LowerModuleCtx<'_> { } PatternCaseItem(item) => { if let Some(expr) = item.expr() { - self.expr_ctx().lower_expr(expr); + self.lower_expr(expr); } } } @@ -791,33 +795,29 @@ impl LowerModuleCtx<'_> { use ast::Member::*; match item { ContinuousAssign(assign) => { - items.push(self.cont_assign_ctx().lower_continuous_assign(assign).into()); + items.push(self.lower_continuous_assign(assign).into()); } DataDeclaration(data_decl) => { - items.push(self.declaration_ctx().lower_data_decl(data_decl).into()); + items.push(self.lower_data_decl(data_decl).into()); } NetDeclaration(net_decl) => { - items.push(self.declaration_ctx().lower_net_decl(net_decl).into()); + items.push(self.lower_net_decl(net_decl).into()); } EmptyMember(_) => {} GenvarDeclaration(genvar_decl) => { - items.push(self.declaration_ctx().lower_genvar_decl(genvar_decl).into()); + items.push(self.lower_genvar_decl(genvar_decl).into()); } ParameterDeclarationStatement(param_decl) => { - items.push( - self.declaration_ctx().lower_param_decl_base(param_decl.parameter()).into(), - ); + items.push(self.lower_param_decl_base(param_decl.parameter()).into()); } TypedefDeclaration(typedef_decl) => { items.push(self.lower_typedef(typedef_decl).into()); } HierarchyInstantiation(instantiation) => { - items.push(self.instantiation_ctx().lower_instantiation(instantiation).into()); + items.push(self.lower_instantiation(instantiation).into()); } PrimitiveInstantiation(instantiation) => { - items.push( - self.instantiation_ctx().lower_primitive_instantiation(instantiation).into(), - ); + items.push(self.lower_primitive_instantiation(instantiation).into()); } FunctionDeclaration(fn_decl) => { if let Some(sub_id) = self.lower_subroutine_decl(fn_decl) { @@ -825,7 +825,7 @@ impl LowerModuleCtx<'_> { } } ProceduralBlock(proc) => { - items.push(self.proc_ctx().lower_proc(proc).into()); + items.push(self.lower_proc(proc).into()); } GenerateBlock(block) => { items.push( @@ -842,7 +842,7 @@ impl LowerModuleCtx<'_> { items.extend(self.lower_case_generate_items(case_generate)); } DefParam(defparam) => { - items.push(self.defparam_ctx().lower_defparam(defparam).into()); + items.push(self.lower_defparam(defparam).into()); } _ => {} } @@ -858,11 +858,13 @@ impl LowerModuleCtx<'_> { self.lower_generate_region_member(item, &mut items); } - alloc_idx_and_src! { - self.file_id; - GenerateRegion { items } => self.module.generate_regions, - region => self.module_source_map.generate_region_srcs, - } + alloc_with_source( + self.file_id, + &mut self.store.data.generate_regions, + &mut self.store.sources.generate_region_srcs, + GenerateRegion { items }, + region, + ) } pub(crate) fn lower_direct_generate_region(&mut self, item: ast::Member) -> GenerateRegionId { @@ -870,11 +872,12 @@ impl LowerModuleCtx<'_> { let mut items = SmallVec::new(); self.lower_generate_region_member(item, &mut items); - let idx = self.module.generate_regions.alloc(GenerateRegion { items }); - if let Some(src) = src { - self.module_source_map.generate_region_srcs.insert(src, idx); - } - idx + alloc_with_optional_source_entry( + &mut self.store.data.generate_regions, + &mut self.store.sources.generate_region_srcs, + GenerateRegion { items }, + src, + ) } } @@ -888,14 +891,12 @@ pub(crate) fn generate_block_with_source_map_query( let mut generate_block = GenerateBlock::default(); let mut generate_block_source_map = GenerateBlockSourceMap::default(); - let mut lower_ctx = LowerGenerateBlockCtx { + let mut lower_ctx = LoweringCtx::new( db, file_id, - generate_block_id, - generate_block: &mut generate_block, - generate_block_source_map: &mut generate_block_source_map, - region_tree: RegionTreeBuilder::new(), - }; + generate_block_id.into(), + GenerateBlockStore { data: &mut generate_block, sources: &mut generate_block_source_map }, + ); match src { GenerateBlockSrc::GenerateBlock { .. } => { @@ -915,6 +916,9 @@ pub(crate) fn generate_block_with_source_map_query( } } + lower_ctx.emit_diagnostics(); + drop(lower_ctx); + generate_block.shrink_to_fit(); generate_block_source_map.shrink_to_fit(); (Arc::new(generate_block), Arc::new(generate_block_source_map)) diff --git a/crates/hir/src/hir_def/module/instantiation.rs b/crates/hir/src/hir_def/module/instantiation.rs index 4d93cc067..695b02c91 100644 --- a/crates/hir/src/hir_def/module/instantiation.rs +++ b/crates/hir/src/hir_def/module/instantiation.rs @@ -1,22 +1,21 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use smallvec::SmallVec; use syntax::{SyntaxToken, ast}; use crate::{ - db::InternDb, - file::HirFileId, hir_def::{ - HirData, Ident, alloc_idx_and_src, - expr::{Expr, ExprId, ExprSrc, LowerExpr, data_ty::Dimension, impl_lower_expr}, + Ident, alloc_with_source, + expr::{ExprId, data_ty::Dimension}, + lower::{LoweringCtx, ModuleItemStore}, lower_ident_opt, }, source_map::{ - AstId, AstKind, FromSourceAst, IsSrc, NamedAstId, SourceAst, SourceMap, ToAstNode, + AstId, AstKind, FromSourceAst, IsSrc, NamedAstId, SourceAst, ToAstNode, exact_ast_node_from_ptr, }, }; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Default, Debug, PartialEq, Eq, Clone)] pub struct Instantiation { pub module_name: Option, pub param_assigns: SmallVec<[ParamAssignId; 1]>, @@ -169,116 +168,58 @@ impl AstKind for PortConnectionAst { pub type PortConnSrc = NamedAstId; -pub(crate) struct LowerInstantiationCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - - pub(crate) instantiations: &'a mut Arena, - pub(crate) instantiation_srcs: &'a mut SourceMap, - - pub(crate) inst_param_assigns: &'a mut Arena, - pub(crate) inst_param_assign_srcs: &'a mut SourceMap, - - pub(crate) instances: &'a mut Arena, - pub(crate) instance_srcs: &'a mut SourceMap, - - pub(crate) inst_port_conns: &'a mut Arena, - pub(crate) inst_port_conn_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, -} - -pub(crate) trait LowerInstantiation: LowerExpr { - fn instantiation_ctx(&mut self) -> LowerInstantiationCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_instantiation($ctx:ty, $data:ident, $src_map:ident) { - impl $crate::hir_def::module::instantiation::LowerInstantiation for $ctx { - fn instantiation_ctx( - &mut self, - ) -> $crate::hir_def::module::instantiation::LowerInstantiationCtx<'_> { - $crate::hir_def::module::instantiation::LowerInstantiationCtx { - db: self.db, - file_id: self.file_id, - instantiations: &mut self.$data.instantiations, - instantiation_srcs: &mut self.$src_map.instantiation_srcs, - inst_param_assigns: &mut self.$data.inst_param_assigns, - inst_param_assign_srcs: &mut self.$src_map.inst_param_assign_srcs, - instances: &mut self.$data.instances, - instance_srcs: &mut self.$src_map.instance_srcs, - inst_port_conns: &mut self.$data.inst_port_conns, - inst_port_conn_srcs: &mut self.$src_map.inst_port_conn_srcs, - exprs: &mut self.$data.exprs, - expr_srcs: &mut self.$src_map.expr_srcs, - } - } +impl LoweringCtx<'_, Store> { + fn reserve_instantiation<'ast, Ast>(&mut self, ast: Ast) -> InstantiationId + where + Ast: syntax::ast::AstNode<'ast>, + InstantiationSrc: FromSourceAst<'ast, Ast>, + { + let file_id = self.file_id; + let (instantiations, sources) = self.instantiations(); + alloc_with_source(file_id, instantiations, sources, Instantiation::default(), ast) } -} -impl_lower_expr!(LowerInstantiationCtx<'_>); + fn finish_instantiation(&mut self, id: InstantiationId, instantiation: Instantiation) { + self.instantiations().0[id] = instantiation; + } -impl LowerInstantiationCtx<'_> { pub(crate) fn lower_instantiation( &mut self, instance: ast::HierarchyInstantiation, ) -> InstantiationId { + let parent = self.reserve_instantiation(instance); let module_name = lower_ident_opt(instance.type_()); let param_assigns = self.lower_param_assign(instance.parameters()); - - let next_instantiation_id = self.instantiations.nxt_idx(); - let instances = instance - .instances() - .children() - .map(|inst| self.lower_instance(inst, next_instantiation_id)) - .collect(); - alloc_idx_and_src! { - self.file_id; - Instantiation { module_name, param_assigns, instances } => self.instantiations, - instance => self.instantiation_srcs, - } + let instances = + instance.instances().children().map(|inst| self.lower_instance(inst, parent)).collect(); + self.finish_instantiation(parent, Instantiation { module_name, param_assigns, instances }); + parent } pub(crate) fn lower_primitive_instantiation( &mut self, inst: ast::PrimitiveInstantiation, ) -> InstantiationId { + let parent = self.reserve_instantiation(inst); let module_name = lower_ident_opt(inst.type_()); let param_assigns = SmallVec::new(); - - let next_instantiation_id = self.instantiations.nxt_idx(); - let instances = inst - .instances() - .children() - .map(|hier| self.lower_instance(hier, next_instantiation_id)) - .collect(); - - alloc_idx_and_src! { - self.file_id; - Instantiation { module_name, param_assigns, instances } => self.instantiations, - inst => self.instantiation_srcs, - } + let instances = + inst.instances().children().map(|hier| self.lower_instance(hier, parent)).collect(); + self.finish_instantiation(parent, Instantiation { module_name, param_assigns, instances }); + parent } pub(crate) fn lower_checker_instantiation( &mut self, inst: ast::CheckerInstantiation, ) -> InstantiationId { + let parent = self.reserve_instantiation(inst); let module_name = lower_name(inst.type_()); let param_assigns = self.lower_param_assign(inst.parameters()); - - let next_instantiation_id = self.instantiations.nxt_idx(); - let instances = inst - .instances() - .children() - .map(|hier| self.lower_instance(hier, next_instantiation_id)) - .collect(); - - alloc_idx_and_src! { - self.file_id; - Instantiation { module_name, param_assigns, instances } => self.instantiations, - inst => self.instantiation_srcs, - } + let instances = + inst.instances().children().map(|hier| self.lower_instance(hier, parent)).collect(); + self.finish_instantiation(parent, Instantiation { module_name, param_assigns, instances }); + parent } fn lower_param_assign( @@ -295,20 +236,18 @@ impl LowerInstantiationCtx<'_> { use ast::ParamAssignment::*; let hir_assign = match assign { OrderedParamAssignment(assign) => { - ParamAssign::Ordered(self.expr_ctx().lower_expr(assign.expr())) + ParamAssign::Ordered(self.lower_expr(assign.expr())) } NamedParamAssignment(assign) => { let name = lower_ident_opt(assign.name()); - let expr = assign.expr().map(|expr| self.expr_ctx().lower_expr(expr)); + let expr = assign.expr().map(|expr| self.lower_expr(expr)); ParamAssign::Named(name, expr) } }; - alloc_idx_and_src! { - self.file_id; - hir_assign => self.inst_param_assigns, - assign => self.inst_param_assign_srcs, - } + let file_id = self.file_id; + let (assignments, sources) = self.parameter_assignments(); + alloc_with_source(file_id, assignments, sources, hir_assign, assign) }) .collect() } @@ -326,22 +265,19 @@ impl LowerInstantiationCtx<'_> { let hir_conn = match conn { EmptyPortConnection(_) => PortConn::Empty, OrderedPortConnection(conn) => { - let expr = self.expr_ctx().lower_property_expr(conn.expr()); + let expr = self.lower_property_expr(conn.expr()); PortConn::Ordered(expr) } NamedPortConnection(conn) => { let name = lower_ident_opt(conn.name()); - let expr = - conn.expr().map(|expr| self.expr_ctx().lower_property_expr(expr)); + let expr = conn.expr().map(|expr| self.lower_property_expr(expr)); PortConn::Named(name, expr) } WildcardPortConnection(_) => PortConn::Wildcard, }; - alloc_idx_and_src! { - self.file_id; - hir_conn => self.inst_port_conns, - conn => self.inst_port_conn_srcs, - } + let file_id = self.file_id; + let (connections, sources) = self.port_connections(); + alloc_with_source(file_id, connections, sources, hir_conn, conn) }) .collect(); @@ -349,20 +285,16 @@ impl LowerInstantiationCtx<'_> { .decl() .map(|decl| { let name = lower_ident_opt(decl.name()); - let dimensions = decl - .dimensions() - .children() - .map(|dim| self.expr_ctx().lower_dimension(dim)) - .collect(); + let dimensions = + decl.dimensions().children().map(|dim| self.lower_dimension(dim)).collect(); (name, dimensions) }) .unwrap_or_default(); - alloc_idx_and_src! { - self.file_id; - Instance { name, dimensions, connections, parent } => self.instances, - instance => self.instance_srcs, - } + let data = Instance { name, dimensions, connections, parent }; + let file_id = self.file_id; + let (instances, sources) = self.instances(); + alloc_with_source(file_id, instances, sources, data, instance) } } diff --git a/crates/hir/src/hir_def/module/modport.rs b/crates/hir/src/hir_def/module/modport.rs index 68a8002cd..3fc03f188 100644 --- a/crates/hir/src/hir_def/module/modport.rs +++ b/crates/hir/src/hir_def/module/modport.rs @@ -10,7 +10,7 @@ use utils::text_edit::TextRange; use super::{LowerModuleCtx, port::PortDirection}; use crate::{ - hir_def::{Ident, alloc_idx_and_src, lower_ident_opt}, + hir_def::{Ident, alloc_with_source, lower_ident_opt}, source_map::{FromSourceAst, IsNamedSrc, IsSrc, SourceAst, root_token_in}, }; @@ -69,15 +69,8 @@ impl<'a> FromSourceAst<'a, ast::ModportItem<'a>> for ModportSrc { } } -pub(crate) trait LowerModport { - fn lower_modport_declaration( - &mut self, - modport: ast::ModportDeclaration<'_>, - ) -> SmallVec<[ModportId; 1]>; -} - -impl LowerModport for LowerModuleCtx<'_> { - fn lower_modport_declaration( +impl LowerModuleCtx<'_> { + pub(crate) fn lower_modport_declaration( &mut self, modport: ast::ModportDeclaration<'_>, ) -> SmallVec<[ModportId; 1]> { @@ -85,11 +78,11 @@ impl LowerModport for LowerModuleCtx<'_> { for item in modport.items().children() { let name = lower_ident_opt(item.name()); let ports = lower_modport_ports(item); - let modport_id = alloc_idx_and_src! { - self.file_id; - ModportDef { name, ports } => self.module.modports, - item => self.module_source_map.modport_srcs, - }; + let file_id = self.file_id; + let (modports, sources) = + (&mut self.store.data.modports, &mut self.store.sources.modport_srcs); + let modport_id = + alloc_with_source(file_id, modports, sources, ModportDef { name, ports }, item); lowered.push(modport_id); } lowered diff --git a/crates/hir/src/hir_def/module/port.rs b/crates/hir/src/hir_def/module/port.rs index d0421882a..1814b43d1 100644 --- a/crates/hir/src/hir_def/module/port.rs +++ b/crates/hir/src/hir_def/module/port.rs @@ -9,11 +9,11 @@ use utils::get::{Get, GetRef}; use crate::{ hir_def::{ - HirData, Ident, alloc_idx_and_src, + Ident, alloc_with_optional_source_entry, alloc_with_source, expr::{ - LowerExpr, Selector, + Selector, data_ty::{BuiltinDataTy, DataTy}, - declarator::{DeclsRange, LowerDecl}, + declarator::{DeclsRange, empty_decls_range}, }, lower_ident_opt, module::LowerModuleCtx, @@ -454,8 +454,8 @@ impl PortSrcs { impl LowerModuleCtx<'_> { pub(crate) fn lower_ansi_ports(&mut self, port_list: ast::AnsiPortList) { - let mut ports = Arena::default(); - let mut decls = SourceMap::default(); + let mut ports: Arena = Arena::default(); + let mut decls: SourceMap = SourceMap::default(); let mut header = None; for port in port_list.ports().children() { @@ -463,41 +463,36 @@ impl LowerModuleCtx<'_> { match port { ImplicitAnsiPort(port) => { header = Some(self.lower_port_header(port.header(), header)); - - let parent = ports.nxt_idx().into(); - let decl_id = self.decl_ctx().lower_declarator(port.declarator(), parent); - let end = self.module.decls.nxt_idx(); - let current_header = header.unwrap_or_else(|| self.default_port_header()); header = Some(current_header); - alloc_idx_and_src! { - self.file_id; - PortDecl { - header: current_header, - decls: IdxRange::new(decl_id..end), - name: None, - } => ports, - port => decls, - }; + let parent = alloc_with_source( + self.file_id, + &mut ports, + &mut decls, + PortDecl { header: current_header, decls: empty_decls_range(), name: None }, + port, + ); + let decl_id = self.lower_declarator(port.declarator(), parent.into()); + ports[parent].decls = IdxRange::new_inclusive(decl_id..=decl_id); } ExplicitAnsiPort(port) => { header = Some(self.lower_explicit_ansi_header(port.direction(), header)); if let Some(expr) = port.expr() { - self.expr_ctx().lower_expr(expr); + self.lower_expr(expr); } let current_header = header.unwrap_or_else(|| self.default_port_header()); header = Some(current_header); - let idx = ports.alloc(PortDecl { - header: current_header, - decls: IdxRange::new( - self.module.decls.nxt_idx()..self.module.decls.nxt_idx(), - ), - name: lower_ident_opt(port.name()), - }); - decls.insert( - PortDeclSrc::ExplicitAnsiPort(AstId::from_ast(self.file_id, port)), - idx, + alloc_with_source( + self.file_id, + &mut ports, + &mut decls, + PortDecl { + header: current_header, + decls: empty_decls_range(), + name: lower_ident_opt(port.name()), + }, + port, ); } _ => continue, @@ -507,8 +502,8 @@ impl LowerModuleCtx<'_> { self.region_tree.stage(port_list.close_paren(), port_list.syntax()); - self.module.ports = Ports::Ansi(ports); - self.module_source_map.port_srcs = PortSrcs::Ansi { + self.store.data.ports = Ports::Ansi(ports); + self.store.sources.port_srcs = PortSrcs::Ansi { decls, port_list_src: Some(PortListSrc::AnsiPortList(AstId::from_ast( self.file_id, @@ -519,8 +514,8 @@ impl LowerModuleCtx<'_> { pub(crate) fn lower_wildcard_ports(&mut self, port_list: ast::WildcardPortList) { self.region_tree.stage(port_list.close_paren(), port_list.syntax()); - self.module.ports = Ports::Ansi(Arena::default()); - self.module_source_map.port_srcs = PortSrcs::Ansi { + self.store.data.ports = Ports::Ansi(Arena::default()); + self.store.sources.port_srcs = PortSrcs::Ansi { decls: SourceMap::default(), port_list_src: Some(PortListSrc::WildcardPortList(AstId::from_ast( self.file_id, @@ -538,29 +533,32 @@ impl LowerModuleCtx<'_> { for port in port_list.ports().children() { use ast::{NonAnsiPort::*, PortExpression::*}; - let start = refs.nxt_idx(); let mut lower_port_exprs = |exprs: Option| { let mut lower_port_ref = |port_ref: ast::PortReference| { let ident = lower_ident_opt(port_ref.name()); let select = port_ref .select() .and_then(|sel| sel.selector()) - .map(|sel| self.expr_ctx().lower_selector(sel)); - alloc_idx_and_src! { - self.file_id; - PortRef { ident, select } => refs, - port_ref => ref_srcs, - }; + .map(|sel| self.lower_selector(sel)); + alloc_with_source( + self.file_id, + &mut refs, + &mut ref_srcs, + PortRef { ident, select }, + port_ref, + ) }; match exprs? { PortConcatenation(concat) => { - concat.references().children().for_each(lower_port_ref); - Some(IdxRange::new(start..refs.nxt_idx())) + let mut ids = concat.references().children().map(&mut lower_port_ref); + let first = ids.next()?; + let last = ids.last().unwrap_or(first); + Some(IdxRange::new_inclusive(first..=last)) } PortReference(port_ref) => { - lower_port_ref(port_ref); - Some(IdxRange::new(start..refs.nxt_idx())) + let id = lower_port_ref(port_ref); + Some(IdxRange::new_inclusive(id..=id)) } } }; @@ -595,22 +593,25 @@ impl LowerModuleCtx<'_> { }; self.region_tree.handle_node(port.syntax()); - let port_id = alloc_idx_and_src! { - self.file_id; - hir_port => ports, - port => port_srcs, - }; - if src_name.is_some() - && let Some(src) = port_srcs.get(port_id) - { - port_srcs.insert(NonAnsiPortSrc::new(src.file_id, src.node, src_name), port_id); + let source = SourceAst::new(self.file_id, port).map(NonAnsiPortSrc::from_source_ast); + let port_id = + alloc_with_optional_source_entry(&mut ports, &mut port_srcs, hir_port, source); + + // Implicit ports are named by their inner PortReference. Keep the + // natural AST key for source-to-HIR lookup, then add the named key + // as the preferred HIR-to-source entry used by navigation. + if let (Some(source), Some(name)) = (source, src_name) { + let named_source = NonAnsiPortSrc::new(source.file_id, source.node, Some(name)); + if named_source != source { + port_srcs.insert(named_source, port_id); + } } } self.region_tree.stage(port_list.close_paren(), port_list.syntax()); - self.module.ports = Ports::NonAnsi { ports, refs, decls: Arena::default() }; - self.module_source_map.port_srcs = PortSrcs::NonAnsi { + self.store.data.ports = Ports::NonAnsi { ports, refs, decls: Arena::default() }; + self.store.sources.port_srcs = PortSrcs::NonAnsi { ports: port_srcs, refs: ref_srcs, decls: SourceMap::default(), @@ -624,25 +625,26 @@ impl LowerModuleCtx<'_> { pub(crate) fn lower_port_decl(&mut self, decl: ast::PortDeclaration) -> PortDeclId { let header = self.lower_port_header(decl.header(), None); - let parent = match &self.module.ports { - Ports::NonAnsi { decls, .. } | Ports::Ansi(decls) => decls.nxt_idx().into(), + let file_id = self.file_id; + let parent = match (&mut self.store.data.ports, &mut self.store.sources.port_srcs) { + (Ports::NonAnsi { decls: port_decls, .. }, PortSrcs::NonAnsi { decls: srcs, .. }) + | (Ports::Ansi(port_decls), PortSrcs::Ansi { decls: srcs, .. }) => alloc_with_source( + file_id, + port_decls, + srcs, + PortDecl { header, decls: empty_decls_range(), name: None }, + decl, + ), + _ => unreachable!("port data and source stores use different variants"), }; - let decls = self.decl_ctx().lower_declarators(decl.declarators(), parent); - - match (&mut self.module.ports, &mut self.module_source_map.port_srcs) { - (Ports::NonAnsi { decls: port_decls, .. }, PortSrcs::NonAnsi { decls: srcs, .. }) - | (Ports::Ansi(port_decls), PortSrcs::Ansi { decls: srcs, .. }) => { - alloc_idx_and_src! { - self.file_id; - PortDecl { header, decls, name: None } => port_decls, - decl => srcs, - } - } - (Ports::NonAnsi { decls: port_decls, .. }, _) | (Ports::Ansi(port_decls), _) => { - port_decls.alloc(PortDecl { header, decls, name: None }) + let decls = self.lower_declarators(decl.declarators(), parent.into()); + match &mut self.store.data.ports { + Ports::NonAnsi { decls: port_decls, .. } | Ports::Ansi(port_decls) => { + port_decls[parent].decls = decls; } } + parent } // Port header may inherit properties from the previous port header, so we @@ -675,7 +677,7 @@ impl LowerModuleCtx<'_> { let dir = Self::lower_dir(ast_dir).unwrap_or_else(|| prev_header.dir()); let ty = if !ty_omitted { - self.expr_ctx().lower_data_ty(ast_ty) + self.lower_data_ty(ast_ty) } else if all_omitted { prev_header.ty() } else { diff --git a/crates/hir/src/hir_def/module/specify.rs b/crates/hir/src/hir_def/module/specify.rs index 7413698cd..888d12345 100644 --- a/crates/hir/src/hir_def/module/specify.rs +++ b/crates/hir/src/hir_def/module/specify.rs @@ -6,10 +6,7 @@ use utils::define_enum_deriving_from; use super::LowerModuleCtx; use crate::{ hir_def::{ - Ident, alloc_idx_and_src, - declaration::{DeclarationId, LowerDeclaration}, - expr::{ExprId, LowerExpr}, - lower_ident_opt, + Ident, alloc_with_source, declaration::DeclarationId, expr::ExprId, lower_ident_opt, }, source_map::{ AstId, AstKind, FromSourceAst, IsNamedSrc, IsSrc, SourceAst, ToAstNode, @@ -218,7 +215,7 @@ impl LowerModuleCtx<'_> { match item { EmptyMember(_) => None, SpecparamDeclaration(specparam_decl) => { - Some(self.declaration_ctx().lower_specparam_decl(specparam_decl).into()) + Some(self.lower_specparam_decl(specparam_decl).into()) } PathDeclaration(path) => Some(self.lower_specify_path_item(path).into()), ConditionalPathDeclaration(path) => { @@ -236,35 +233,44 @@ impl LowerModuleCtx<'_> { }) .collect(); - alloc_idx_and_src! { - self.file_id; - SpecifyBlock { items } => self.module.specify_blocks, - block => self.module_source_map.specify_block_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_blocks, + &mut self.store.sources.specify_block_srcs, + SpecifyBlock { items }, + block, + ) } pub(crate) fn lower_specify_path_item(&mut self, path: ast::PathDeclaration) -> SpecifyItemId { let item = SpecifyItem::Path(self.lower_specify_path(path)); - alloc_idx_and_src! { - self.file_id; - item => self.module.specify_items, - path => self.module_source_map.specify_item_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_items, + &mut self.store.sources.specify_item_srcs, + item, + path, + ) } pub(crate) fn lower_conditional_specify_path_item( &mut self, path: ast::ConditionalPathDeclaration, ) -> SpecifyItemId { - let predicate = self.expr_ctx().lower_expr(path.predicate()); + let predicate = self.lower_expr(path.predicate()); let path_data = self.lower_specify_path(path.path()); let item = SpecifyItem::ConditionalPath { predicate, path: path_data }; - alloc_idx_and_src! { - self.file_id; - item => self.module.specify_items, - path => self.module_source_map.specify_item_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_items, + &mut self.store.sources.specify_item_srcs, + item, + path, + ) } pub(crate) fn lower_ifnone_specify_path_item( @@ -273,11 +279,14 @@ impl LowerModuleCtx<'_> { ) -> SpecifyItemId { let item = SpecifyItem::IfNonePath(self.lower_specify_path(path.path())); - alloc_idx_and_src! { - self.file_id; - item => self.module.specify_items, - path => self.module_source_map.specify_item_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_items, + &mut self.store.sources.specify_item_srcs, + item, + path, + ) } pub(crate) fn lower_pulse_style_item( @@ -287,11 +296,14 @@ impl LowerModuleCtx<'_> { let controls = pulse.inputs().children().map(|name| self.lower_name_expr(name)).collect(); let item = SpecifyItem::PulseStyle { controls }; - alloc_idx_and_src! { - self.file_id; - item => self.module.specify_items, - pulse => self.module_source_map.specify_item_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_items, + &mut self.store.sources.specify_item_srcs, + item, + pulse, + ) } pub(crate) fn lower_system_timing_check_item( @@ -302,11 +314,14 @@ impl LowerModuleCtx<'_> { let args = timing.args().children().map(|arg| self.lower_timing_check_arg(arg)).collect(); let item = SpecifyItem::TimingCheck { name, args }; - alloc_idx_and_src! { - self.file_id; - item => self.module.specify_items, - timing => self.module_source_map.specify_item_srcs, - } + let file_id = self.file_id; + alloc_with_source( + file_id, + &mut self.store.data.specify_items, + &mut self.store.sources.specify_item_srcs, + item, + timing, + ) } fn lower_specify_path(&mut self, path: ast::PathDeclaration) -> SpecifyPath { @@ -321,11 +336,10 @@ impl LowerModuleCtx<'_> { ast::PathSuffix::EdgeSensitivePathSuffix(suffix) => { let outputs = suffix.outputs().children().map(|name| self.lower_name_expr(name)).collect(); - (outputs, Some(self.expr_ctx().lower_expr(suffix.expr()))) + (outputs, Some(self.lower_expr(suffix.expr()))) } }; - let delays = - path.delays().children().map(|expr| self.expr_ctx().lower_expr(expr)).collect(); + let delays = path.delays().children().map(|expr| self.lower_expr(expr)).collect(); SpecifyPath { inputs, outputs, edge_expr, delays } } @@ -335,19 +349,17 @@ impl LowerModuleCtx<'_> { match arg { EmptyTimingCheckArg(_) => TimingCheckArg::Empty, TimingCheckEventArg(arg) => { - let terminal = self.expr_ctx().lower_expr(arg.terminal()); - let condition = arg.condition().map(|cond| self.expr_ctx().lower_expr(cond.expr())); + let terminal = self.lower_expr(arg.terminal()); + let condition = arg.condition().map(|cond| self.lower_expr(cond.expr())); TimingCheckArg::Event { terminal, condition } } - ExpressionTimingCheckArg(arg) => { - TimingCheckArg::Expr(self.expr_ctx().lower_expr(arg.expr())) - } + ExpressionTimingCheckArg(arg) => TimingCheckArg::Expr(self.lower_expr(arg.expr())), } } fn lower_name_expr(&mut self, name: ast::Name) -> ExprId { ast::Expression::cast(name.syntax()) - .map(|expr| self.expr_ctx().lower_expr(expr)) - .unwrap_or_else(|| self.expr_ctx().lower_expr_opt(None)) + .map(|expr| self.lower_expr(expr)) + .unwrap_or_else(|| self.lower_expr_opt(None)) } } diff --git a/crates/hir/src/hir_def/proc.rs b/crates/hir/src/hir_def/proc.rs index fff37136b..35a1b327c 100644 --- a/crates/hir/src/hir_def/proc.rs +++ b/crates/hir/src/hir_def/proc.rs @@ -1,25 +1,12 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use syntax::ast; use super::{ - expr::{declarator::impl_lower_decl, impl_lower_expr, timing_control::impl_lower_event_expr}, - stmt::impl_lower_stmt, -}; -use crate::{ - container::ArenaOwnerId, - db::InternDb, - file::HirFileId, - hir_def::{ - alloc_idx_and_src, - expr::{ - Expr, ExprSrc, - declarator::{Declarator, DeclaratorSrc}, - timing_control::{EventExpr, EventExprSrc}, - }, - stmt::{LowerStmt, Stmt, StmtId, StmtSrc}, - }, - source_map::{AstId, AstKind, SourceMap}, + alloc_with_source, + lower::{LoweringCtx, ProcStore}, + stmt::StmtId, }; +use crate::source_map::{AstId, AstKind}; #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum AlwaysKeyword { @@ -55,37 +42,7 @@ impl AstKind for ProceduralBlockAst { pub type ProcSrc = AstId; -pub(crate) trait LowerProc: LowerStmt { - fn proc_ctx(&mut self) -> LowerProcCtx<'_>; -} - -pub(crate) struct LowerProcCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) cont_id: ArenaOwnerId, - - pub(crate) procs: &'a mut Arena, - pub(crate) proc_srcs: &'a mut SourceMap, - - pub(crate) stmts: &'a mut Arena, - pub(crate) stmt_srcs: &'a mut SourceMap, - - pub(crate) event_exprs: &'a mut Arena, - pub(crate) event_expr_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, - - pub(crate) decls: &'a mut Arena, - pub(crate) decl_srcs: &'a mut SourceMap, -} - -impl_lower_expr!(LowerProcCtx<'_>); -impl_lower_decl!(LowerProcCtx<'_>); -impl_lower_event_expr!(LowerProcCtx<'_>); -impl_lower_stmt!(LowerProcCtx<'_>, cont_id); - -impl LowerProcCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_proc(&mut self, proc: ast::ProceduralBlock) -> ProcId { use ast::ProceduralBlock::*; let proc_ty = match proc { @@ -97,12 +54,10 @@ impl LowerProcCtx<'_> { FinalBlock(_) => ProcType::Final, }; - let stmt = self.stmt_ctx().lower_stmt(proc.statement()); + let stmt = self.lower_stmt(proc.statement()); - alloc_idx_and_src! { - self.file_id; - Proc { proc_ty, stmt } => self.procs, - proc => self.proc_srcs, - } + let file_id = self.file_id; + let (procs, sources) = self.procs(); + alloc_with_source(file_id, procs, sources, Proc { proc_ty, stmt }, proc) } } diff --git a/crates/hir/src/hir_def/stmt.rs b/crates/hir/src/hir_def/stmt.rs index 1b9216ea4..4ebfaa81d 100644 --- a/crates/hir/src/hir_def/stmt.rs +++ b/crates/hir/src/hir_def/stmt.rs @@ -1,4 +1,4 @@ -use la_arena::{Arena, Idx}; +use la_arena::Idx; use smallvec::SmallVec; use syntax::{ SyntaxKind, SyntaxToken, TokenKind, @@ -6,25 +6,16 @@ use syntax::{ }; use super::{ - HirData, Ident, + Ident, block::{BlockInfo, BlockLoc, BlockSrc}, - expr::{ - Expr, ExprId, ExprSrc, LowerExpr, - data_ty::DataTy, - declarator::{DeclId, Declarator, DeclaratorSrc, LowerDecl, impl_lower_decl}, - impl_lower_expr, - timing_control::{ - EventExpr, EventExprSrc, LowerEventExpr, TimingControl, impl_lower_event_expr, - }, - }, + expr::{ExprId, data_ty::DataTy, declarator::DeclId, timing_control::TimingControl}, + lower::{LoweringCtx, LoweringStore}, lower_ident_opt, }; use crate::{ - container::{ArenaOwnerId, InFile}, - db::InternDb, - file::HirFileId, - hir_def::{alloc_idx_and_src, lower_named_label_opt}, - source_map::{AstKind, NamedAstId, SourceMap}, + container::InFile, + hir_def::{alloc_with_source, lower_named_label_opt}, + source_map::{AstKind, NamedAstId}, }; #[derive(Debug, PartialEq, Eq, Clone)] @@ -154,73 +145,30 @@ pub enum CaseItem { Default(StmtId), } -pub(crate) trait LowerStmt: LowerExpr + LowerEventExpr + LowerDecl { - fn stmt_ctx(&mut self) -> LowerStmtCtx<'_>; -} - -pub(in crate::hir_def) macro impl_lower_stmt { - ($ctx:ty, $cont_id:ident $(,$data:ident, $src_map:ident)?) => { - impl $crate::hir_def::stmt::LowerStmt for $ctx { - fn stmt_ctx(&mut self) -> $crate::hir_def::stmt::LowerStmtCtx<'_> { - $crate::hir_def::stmt::LowerStmtCtx { - db: self.db, - file_id: self.file_id, - cont_id: self.$cont_id.into(), - stmts: &mut self.$($data.)?stmts, - stmt_srcs: &mut self.$($src_map.)?stmt_srcs, - event_exprs: &mut self.$($data.)?event_exprs, - event_expr_srcs: &mut self.$($src_map.)?event_expr_srcs, - exprs: &mut self.$($data.)?exprs, - expr_srcs: &mut self.$($src_map.)?expr_srcs, - decls: &mut self.$($data.)?decls, - decl_srcs: &mut self.$($src_map.)?decl_srcs, - } - } - } - } -} - -pub(crate) struct LowerStmtCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) cont_id: ArenaOwnerId, - - pub(crate) stmts: &'a mut Arena, - pub(crate) stmt_srcs: &'a mut SourceMap, - - pub(crate) event_exprs: &'a mut Arena, - pub(crate) event_expr_srcs: &'a mut SourceMap, - - pub(crate) exprs: &'a mut Arena, - pub(crate) expr_srcs: &'a mut SourceMap, - - pub(crate) decls: &'a mut Arena, - pub(crate) decl_srcs: &'a mut SourceMap, -} - -impl_lower_expr!(LowerStmtCtx<'_>); -impl_lower_decl!(LowerStmtCtx<'_>); -impl_lower_event_expr!(LowerStmtCtx<'_>); - -impl LowerStmtCtx<'_> { +impl LoweringCtx<'_, Store> { pub(crate) fn lower_stmt_opt(&mut self, stmt: Option) -> StmtId { if let Some(stmt) = stmt { self.lower_stmt(stmt) } else { self.alloc_missing() } } pub(crate) fn lower_stmt(&mut self, stmt: ast::Statement) -> StmtId { - let hir_stmt = self.lower_stmt_inner(stmt); - alloc_idx_and_src! { - self.file_id; - hir_stmt => self.stmts, - stmt => self.stmt_srcs, - } - } - - fn lower_stmt_inner(&mut self, stmt: ast::Statement) -> Stmt { let label = lower_named_label_opt(stmt.label()); + let file_id = self.file_id; + let (statements, sources) = self.statements(); + let stmt_id = alloc_with_source( + file_id, + statements, + sources, + Stmt { label, kind: StmtKind::Empty }, + stmt, + ); + let kind = self.lower_stmt_kind(stmt, stmt_id); + self.statements().0[stmt_id].kind = kind; + stmt_id + } + fn lower_stmt_kind(&mut self, stmt: ast::Statement, stmt_id: StmtId) -> StmtKind { use ast::Statement::*; - let kind = match stmt { + match stmt { ExpressionStatement(stmt) => self.lower_expr_stmt(stmt), TimingControlStatement(stmt) => self.lower_timing_ctrl_stmt(stmt), ProceduralAssignStatement(stmt) => self.lower_assign_stmt(stmt), @@ -238,25 +186,23 @@ impl LowerStmtCtx<'_> { ForeverStatement(stmt) => self.lower_forever_stmt(stmt), LoopStatement(stmt) => self.lower_loop_stmt(stmt), JumpStatement(stmt) => self.lower_jump_stmt(stmt), - ForLoopStatement(stmt) => self.lower_for_loop_stmt(stmt), + ForLoopStatement(stmt) => self.lower_for_loop_stmt(stmt, stmt_id), BlockStatement(stmt) => self.lower_block_stmt(stmt), EmptyStatement(_) => StmtKind::Empty, unsupported => StmtKind::Unsupported(unsupported.syntax().kind()), - }; - - Stmt { label, kind } + } } fn lower_expr_stmt(&mut self, stmt: ast::ExpressionStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); StmtKind::Expr(expr) } fn lower_assign_stmt(&mut self, stmt: ast::ProceduralAssignStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); use ast::ProceduralAssignStatement::*; let kind = match stmt { @@ -268,7 +214,7 @@ impl LowerStmtCtx<'_> { } fn lower_deassign_stmt(&mut self, stmt: ast::ProceduralDeassignStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.variable()); + let expr = self.lower_expr(stmt.variable()); use ast::ProceduralDeassignStatement::*; let kind = match stmt { @@ -281,9 +227,9 @@ impl LowerStmtCtx<'_> { fn lower_event_trigger_stmt(&mut self, stmt: ast::EventTriggerStatement) -> StmtKind { let event = ast::Expression::cast(stmt.name().syntax()) - .map(|expr| self.expr_ctx().lower_expr(expr)) - .unwrap_or_else(|| self.expr_ctx().lower_expr_opt(None)); - let timing = stmt.timing().map(|timing| self.event_expr_ctx().lower_timing_control(timing)); + .map(|expr| self.lower_expr(expr)) + .unwrap_or_else(|| self.lower_expr_opt(None)); + let timing = stmt.timing().map(|timing| self.lower_timing_control(timing)); let kind = match stmt { ast::EventTriggerStatement::BlockingEventTriggerStatement(_) => { @@ -303,27 +249,27 @@ impl LowerStmtCtx<'_> { } fn lower_do_while_stmt(&mut self, stmt: ast::DoWhileStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); let stmt = self.lower_stmt(stmt.statement()); StmtKind::DoWhile(stmt, expr) } - fn lower_for_loop_stmt(&mut self, stmt: ast::ForLoopStatement) -> StmtKind { + fn lower_for_loop_stmt(&mut self, stmt: ast::ForLoopStatement, stmt_id: StmtId) -> StmtKind { let mut initializers = stmt.initializers().children().peekable(); let inits = match initializers.peek().map(|init| init.syntax().kind()) { Some(SyntaxKind::FOR_VARIABLE_DECLARATION) => { let mut ty = None; let mut inits = SmallVec::new(); - let next_stmt_id = self.stmts.nxt_idx().into(); + let parent = stmt_id.into(); for init in initializers { let Some(init) = ast::ForVariableDeclaration::cast(init.syntax()) else { continue; }; if let Some(ast_ty) = init.type_() { - ty = Some(self.expr_ctx().lower_data_ty(ast_ty)); + ty = Some(self.lower_data_ty(ast_ty)); } - let decl = self.decl_ctx().lower_declarator(init.declarator(), next_stmt_id); + let decl = self.lower_declarator(init.declarator(), parent); inits.push((ty, decl)); } ForInit::Init(inits) @@ -331,8 +277,7 @@ impl LowerStmtCtx<'_> { Some(SyntaxKind::ASSIGNMENT_EXPRESSION) => { let inits = initializers .filter_map(|init| { - ast::Expression::cast(init.syntax()) - .map(|expr| self.expr_ctx().lower_expr(expr)) + ast::Expression::cast(init.syntax()).map(|expr| self.lower_expr(expr)) }) .collect(); ForInit::Assign(inits) @@ -341,20 +286,20 @@ impl LowerStmtCtx<'_> { _ => ForInit::Missing, }; - let stop = self.expr_ctx().lower_expr_opt(stmt.stop_expr()); - let steps = stmt.steps().children().map(|step| self.expr_ctx().lower_expr(step)).collect(); + let stop = self.lower_expr_opt(stmt.stop_expr()); + let steps = stmt.steps().children().map(|step| self.lower_expr(step)).collect(); let stmt = self.lower_stmt(stmt.statement()); StmtKind::For { inits, stop, steps, stmt } } fn lower_return_stmt(&mut self, stmt: ast::ReturnStatement) -> StmtKind { - let expr = stmt.return_value().map(|expr| self.expr_ctx().lower_expr(expr)); + let expr = stmt.return_value().map(|expr| self.lower_expr(expr)); StmtKind::Jump(JumpKind::Return(expr)) } fn lower_loop_stmt(&mut self, stmt: ast::LoopStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); let body = self.lower_stmt(stmt.statement()); match stmt.repeat_or_while().map(|tok| tok.kind()) { Some(TokenKind::REPEAT_KEYWORD) => StmtKind::Repeat(expr, body), @@ -364,15 +309,15 @@ impl LowerStmtCtx<'_> { } fn lower_wait_stmt(&mut self, stmt: ast::WaitStatement) -> StmtKind { - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); let stmt = self.lower_stmt(stmt.statement()); StmtKind::Wait(WaitKind::Wait(expr), stmt) } fn lower_disable_stmt(&mut self, stmt: ast::DisableStatement) -> StmtKind { let name = ast::Expression::cast(stmt.name().syntax()) - .map(|name| self.expr_ctx().lower_expr(name)) - .unwrap_or_else(|| self.expr_ctx().lower_expr_opt(None)); + .map(|name| self.lower_expr(name)) + .unwrap_or_else(|| self.lower_expr_opt(None)); StmtKind::Disable(DisableKind::Disable(name)) } @@ -393,7 +338,7 @@ impl LowerStmtCtx<'_> { .predicate() .conditions() .children() - .map(|cond| self.expr_ctx().lower_expr(cond.expr())) + .map(|cond| self.lower_expr(cond.expr())) .collect(); let then_stmt = self.lower_stmt(stmt.statement()); let else_stmt = stmt @@ -404,7 +349,7 @@ impl LowerStmtCtx<'_> { } fn lower_timing_ctrl_stmt(&mut self, stmt: ast::TimingControlStatement) -> StmtKind { - let timing_control = self.event_expr_ctx().lower_timing_control(stmt.timing_control()); + let timing_control = self.lower_timing_control(stmt.timing_control()); let stmt = self.lower_stmt(stmt.statement()); StmtKind::TimingCtrl(timing_control, stmt) } @@ -419,7 +364,7 @@ impl LowerStmtCtx<'_> { _ => None, }); - let expr = self.expr_ctx().lower_expr(stmt.expr()); + let expr = self.lower_expr(stmt.expr()); let items = stmt .items() @@ -436,7 +381,7 @@ impl LowerStmtCtx<'_> { let exprs = item .expressions() .children() - .map(|expr| self.expr_ctx().lower_expr(expr)) + .map(|expr| self.lower_expr(expr)) .collect(); let clause = self.lower_stmt_opt(ast::Statement::cast(item.clause().syntax())); @@ -445,7 +390,7 @@ impl LowerStmtCtx<'_> { PatternCaseItem(item) => { let mut exprs = SmallVec::new(); if let Some(expr) = item.expr() { - exprs.push(self.expr_ctx().lower_expr(expr)); + exprs.push(self.lower_expr(expr)); } let clause = self.lower_stmt(item.statement()); CaseItem::Case { exprs, clause } @@ -459,7 +404,7 @@ impl LowerStmtCtx<'_> { fn lower_block_stmt(&mut self, stmt: ast::BlockStatement) -> StmtKind { let loc = BlockLoc { - cont_id: self.cont_id, + cont_id: self.owner, src: InFile::new(self.file_id, BlockSrc::from_ast(self.file_id, stmt)), }; let block_id = self.db.intern_block(loc); @@ -468,7 +413,7 @@ impl LowerStmtCtx<'_> { } fn alloc_missing(&mut self) -> StmtId { - self.stmts.alloc(Stmt { label: None, kind: StmtKind::Missing }) + self.statements().0.alloc(Stmt { label: None, kind: StmtKind::Missing }) } } diff --git a/crates/hir/src/hir_def/subroutine.rs b/crates/hir/src/hir_def/subroutine.rs index 137650160..a8407a0a7 100644 --- a/crates/hir/src/hir_def/subroutine.rs +++ b/crates/hir/src/hir_def/subroutine.rs @@ -1,5 +1,4 @@ use la_arena::{Arena, Idx}; -use proc_macro_utils::define_container; use rustc_hash::FxHashMap; use smallvec::SmallVec; use syntax::{ @@ -12,53 +11,52 @@ use triomphe::Arc; use super::{ Ident, aggregate::{StructDef, StructId, StructSrc, lower_struct_def}, - alloc_idx_and_src, + alloc_with_source, block::{BlockInfo, BlockItem, BlockSrc, LocalBlockId}, - declaration::{ - Declaration, DeclarationId, DeclarationSrc, LowerDeclaration, impl_lower_declaration, - }, + declaration::{DataDecl, Declaration, DeclarationId, DeclarationSrc}, expr::{ - Expr, ExprSrc, LowerExpr, + Expr, ExprId, ExprSrc, data_ty::DataTy, - declarator::{Declarator, DeclaratorSrc, impl_lower_decl}, - impl_lower_expr, - timing_control::{EventExpr, EventExprSrc}, + declarator::{DeclId, Declarator, DeclaratorSrc, empty_decls_range}, + timing_control::{EventExpr, EventExprId, EventExprSrc}, }, + lower::{LoweringCtx, SubroutineStore}, lower_ident_opt, - stmt::{LowerStmt, Stmt, StmtId, StmtSrc, impl_lower_stmt}, + stmt::{Stmt, StmtId, StmtSrc}, typedef::{Typedef, TypedefId, TypedefSrc, lower_typedef_data_ty}, }; use crate::{ container::{ArenaOwnerId, SubroutineParent, SubroutineScope}, - db::{HirDb, InternDb}, - file::HirFileId, - hir_def::{ - HirData, - declaration::DataDecl, - expr::{declarator::LowerDecl, timing_control::impl_lower_event_expr}, - }, - region_tree::{RegionTree, RegionTreeBuilder}, + db::HirDb, + region_tree::RegionTree, source_map::{AstKind, NamedAstId, SourceMap}, }; -define_container! { - #[derive(Debug, PartialEq, Eq, Clone)] - pub struct Subroutine { - name: Option, - kind: SubroutineKind, - ports: SmallVec<[SubroutinePort; 4]>, - has_body: bool, - declarations: [Declaration], - typedefs: [Typedef], - structs: [StructDef], - exprs: [Expr], - event_exprs: [EventExpr], - decls: [Declarator], - stmts: [Stmt] => { - [StmtId | Stmt], - [LocalBlockId | BlockInfo], - }, - source_map: SubroutineSourceMap +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Subroutine { + pub name: Option, + pub kind: SubroutineKind, + pub ports: SmallVec<[SubroutinePort; 4]>, + pub has_body: bool, + pub declarations: Arena, + pub typedefs: Arena, + pub structs: Arena, + pub exprs: Arena, + pub event_exprs: Arena, + pub decls: Arena, + pub stmts: Arena, + pub source_map: SubroutineSourceMap, +} + +impl Subroutine { + pub fn shrink_to_fit(&mut self) { + self.declarations.shrink_to_fit(); + self.typedefs.shrink_to_fit(); + self.structs.shrink_to_fit(); + self.exprs.shrink_to_fit(); + self.event_exprs.shrink_to_fit(); + self.decls.shrink_to_fit(); + self.stmts.shrink_to_fit(); } } @@ -81,26 +79,56 @@ impl Default for Subroutine { } } -define_container! { - #[derive(Default, Debug, PartialEq, Eq, Clone)] - pub struct SubroutineSourceMap { - items: SmallVec<[BlockItem; 2]>, - region_tree: RegionTree, - - declaration_srcs: [Declaration | DeclarationSrc], - typedef_srcs: [Typedef | TypedefSrc], - struct_srcs: [StructDef | StructSrc], - expr_srcs: [Expr | ExprSrc], - event_expr_srcs: [EventExpr | EventExprSrc], - decl_srcs: [Declarator | DeclaratorSrc], - stmt_srcs: [Stmt | StmtSrc] => { - [StmtId | StmtSrc], - [LocalBlockId | BlockSrc], - }, - block_srcs: FxHashMap, +#[derive(Default, Debug, PartialEq, Eq, Clone)] +pub struct SubroutineSourceMap { + pub items: SmallVec<[BlockItem; 2]>, + pub region_tree: RegionTree, + pub declaration_srcs: SourceMap, + pub typedef_srcs: SourceMap, + pub struct_srcs: SourceMap, + pub expr_srcs: SourceMap, + pub event_expr_srcs: SourceMap, + pub decl_srcs: SourceMap, + pub stmt_srcs: SourceMap, + pub block_srcs: FxHashMap, +} + +impl SubroutineSourceMap { + pub fn shrink_to_fit(&mut self) { + self.declaration_srcs.shrink_to_fit(); + self.typedef_srcs.shrink_to_fit(); + self.struct_srcs.shrink_to_fit(); + self.expr_srcs.shrink_to_fit(); + self.event_expr_srcs.shrink_to_fit(); + self.decl_srcs.shrink_to_fit(); + self.stmt_srcs.shrink_to_fit(); } } +crate::hir_def::impl_arena_getters!( + Subroutine; + DeclarationId => declarations => Declaration, + TypedefId => typedefs => Typedef, + StructId => structs => StructDef, + ExprId => exprs => Expr, + EventExprId => event_exprs => EventExpr, + DeclId => decls => Declarator, + StmtId => stmts => Stmt, + LocalBlockId => stmts => BlockInfo, +); + +crate::hir_def::impl_source_map_getters!( + SubroutineSourceMap; + DeclarationSrc => DeclarationId => declaration_srcs, + TypedefSrc => TypedefId => typedef_srcs, + StructSrc => StructId => struct_srcs, + ExprSrc => ExprId => expr_srcs, + EventExprSrc => EventExprId => event_expr_srcs, + DeclaratorSrc => DeclId => decl_srcs, + StmtSrc => StmtId => stmt_srcs, + BlockSrc => LocalBlockId => stmt_srcs, +); + #[derive(Debug, PartialEq, Eq, Clone)] pub enum SubroutineKind { Task, @@ -203,46 +231,36 @@ fn map_direction(kind: Option) -> SubroutinePortDir { } } -pub struct LowerSubroutineBodyCtx<'a> { - pub(crate) db: &'a dyn InternDb, - pub(crate) file_id: HirFileId, - pub(crate) subroutine_id: SubroutineScope, - pub(crate) subroutine: &'a mut Subroutine, - pub(crate) subroutine_source_map: &'a mut SubroutineSourceMap, - pub(crate) region_tree: RegionTreeBuilder, -} - -impl_lower_expr!(LowerSubroutineBodyCtx<'_>, subroutine, subroutine_source_map); -impl_lower_decl!(LowerSubroutineBodyCtx<'_>, subroutine, subroutine_source_map); -impl_lower_event_expr!(LowerSubroutineBodyCtx<'_>, subroutine, subroutine_source_map); -impl_lower_stmt!(LowerSubroutineBodyCtx<'_>, subroutine_id, subroutine, subroutine_source_map); -impl_lower_declaration!(LowerSubroutineBodyCtx<'_>, subroutine, subroutine_source_map); +pub(crate) type LowerSubroutineBodyCtx<'a> = LoweringCtx<'a, SubroutineStore<'a>>; impl LowerSubroutineBodyCtx<'_> { fn container_id(&self) -> ArenaOwnerId { - self.subroutine_id.into() + self.owner } fn lower_struct_type(&mut self, struct_ty: ast::StructUnionType) -> StructId { let container_id = self.container_id(); - let struct_def = - lower_struct_def(struct_ty, container_id, |ty| self.expr_ctx().lower_data_ty(ty)); - - alloc_idx_and_src! { - self.file_id; - struct_def => self.subroutine.structs, - struct_ty => self.subroutine_source_map.struct_srcs, - } + let struct_def = lower_struct_def(struct_ty, container_id, |ty| self.lower_data_ty(ty)); + + alloc_with_source( + self.file_id, + &mut self.store.data.structs, + &mut self.store.sources.struct_srcs, + struct_def, + struct_ty, + ) } fn lower_typedef(&mut self, typedef: ast::TypedefDeclaration) -> TypedefId { let name = lower_ident_opt(typedef.name()); - let typedef_id = alloc_idx_and_src! { - self.file_id; - Typedef { name, ty: None } => self.subroutine.typedefs, - typedef => self.subroutine_source_map.typedef_srcs, - }; + let typedef_id = alloc_with_source( + self.file_id, + &mut self.store.data.typedefs, + &mut self.store.sources.typedef_srcs, + Typedef { name, ty: None }, + typedef, + ); let data_ty = typedef.type_(); let lowered_ty = lower_typedef_data_ty( @@ -250,10 +268,10 @@ impl LowerSubroutineBodyCtx<'_> { data_ty, self.container_id(), |ctx, struct_ty| ctx.lower_struct_type(struct_ty), - |ctx, ty| ctx.expr_ctx().lower_data_ty(ty), + |ctx, ty| ctx.lower_data_ty(ty), ); - self.subroutine.typedefs[typedef_id].ty = Some(lowered_ty); + self.store.data.typedefs[typedef_id].ty = Some(lowered_ty); typedef_id } @@ -264,20 +282,19 @@ impl LowerSubroutineBodyCtx<'_> { ) -> DeclarationId { let const_kw = false; let var_kw = local_decl.var().is_some(); - let ty = self.expr_ctx().lower_data_ty(local_decl.type_()); - - let parent = self.subroutine.declarations.nxt_idx().into(); - let decls = self.decl_ctx().lower_declarators(local_decl.declarators(), parent); + let ty = self.lower_data_ty(local_decl.type_()); - alloc_idx_and_src! { - self.file_id; - DataDecl { ty, const_kw, var_kw, decls } => self.subroutine.declarations, - local_decl => self.subroutine_source_map.declaration_srcs, - } + let parent = self.alloc_declaration( + DataDecl { ty, const_kw, var_kw, decls: empty_decls_range() }, + local_decl, + ); + let decls = self.lower_declarators(local_decl.declarators(), parent.into()); + self.finish_declaration_decls(parent, decls); + parent } pub(crate) fn lower_items(&mut self, func: ast::FunctionDeclaration) { - self.subroutine.has_body = true; + self.store.data.has_body = true; for item in func.items().children() { self.region_tree.handle_node(item.syntax()); @@ -285,47 +302,50 @@ impl LowerSubroutineBodyCtx<'_> { let syntax = item.syntax(); match_ast! { syntax, ast::Statement[it] => { - let stmt_id = self.stmt_ctx().lower_stmt(it); + let stmt_id = self.lower_stmt(it); if let Some(block_stmt) = it.as_block_statement() { let block_src = BlockSrc::from_ast(self.file_id, block_stmt); let local_block_id = LocalBlockId(stmt_id); - self.subroutine_source_map.block_srcs.insert(block_src, local_block_id); + self.store.sources.block_srcs.insert(block_src, local_block_id); } - self.subroutine_source_map.items.push(BlockItem::StmtId(stmt_id)); + self.store.sources.items.push(BlockItem::StmtId(stmt_id)); }, ast::DataDeclaration[it] => { - let decl_id = self.declaration_ctx().lower_data_decl(it); - self.subroutine_source_map.items.push(BlockItem::DeclarationId(decl_id)); + let decl_id = self.lower_data_decl(it); + self.store.sources.items.push(BlockItem::DeclarationId(decl_id)); }, ast::PortDeclaration[it] => { if let Some(decl_id) = - self.declaration_ctx().lower_port_decl_as_data_decl(it) + self.lower_port_decl_as_data_decl(it) { - self.subroutine_source_map.items.push(BlockItem::DeclarationId(decl_id)); + self.store.sources.items.push(BlockItem::DeclarationId(decl_id)); } }, ast::LocalVariableDeclaration[it] => { let decl_id = self.lower_local_variable_decl(it); - self.subroutine_source_map.items.push(BlockItem::DeclarationId(decl_id)); + self.store.sources.items.push(BlockItem::DeclarationId(decl_id)); }, ast::ParameterDeclarationStatement[it] => { - let decl_id = self.declaration_ctx().lower_param_decl_base(it.parameter()); - self.subroutine_source_map.items.push(BlockItem::DeclarationId(decl_id)); + let decl_id = self.lower_param_decl_base(it.parameter()); + self.store.sources.items.push(BlockItem::DeclarationId(decl_id)); }, ast::TypedefDeclaration[it] => { let typedef_id = self.lower_typedef(it); - self.subroutine_source_map.items.push(BlockItem::TypedefId(typedef_id)); + self.store.sources.items.push(BlockItem::TypedefId(typedef_id)); }, _ => {}, } } self.region_tree.stage(func.end(), func.syntax()); - self.subroutine_source_map.region_tree = self.region_tree.finish(); + self.store.sources.region_tree = self.region_tree.finish(); } } -pub fn lower_subroutine_body(ctx: &mut LowerSubroutineBodyCtx<'_>, func: ast::FunctionDeclaration) { +pub(crate) fn lower_subroutine_body( + ctx: &mut LowerSubroutineBodyCtx<'_>, + func: ast::FunctionDeclaration, +) { ctx.lower_items(func); } diff --git a/crates/hir/src/scope.rs b/crates/hir/src/scope.rs index b89e1294d..3801d133b 100644 --- a/crates/hir/src/scope.rs +++ b/crates/hir/src/scope.rs @@ -327,9 +327,9 @@ impl NameScope { let owner_id = ArenaOwnerId::from(checker_id.cont_id); let container = owner_id.data(db); for declaration_id in &checker.declarations { - let declaration = container.get(*declaration_id); + let declaration = container.declaration(*declaration_id); for decl_id in declaration.decls() { - let decl = container.get(decl_id); + let decl = container.declarator(decl_id); scope.insert_value_opt(&decl.name, def_id(db, InContainer::new(owner_id, decl_id))); } } @@ -657,6 +657,7 @@ mod tests { use rustc_hash::FxHashSet; use smol_str::SmolStr; + use syntax::ast::{self, AstNode}; use triomphe::Arc; use utils::{ get::{Get, GetRef}, @@ -680,8 +681,12 @@ mod tests { def_id::DefId, display::HirDisplay, file::HirFileId, - hir_def::Ident, + hir_def::{ + Ident, + module::port::{NonAnsiPortSrc, PortSrcs, Ports}, + }, semantics::pathres::resolve_name, + source_map::IsNamedSrc, symbol::{DefKind, DefOriginLoc, NameContext, Resolution, ScopeKind}, }; @@ -932,6 +937,76 @@ endmodule } } + #[test] + fn explicit_non_ansi_port_source_preserves_name_range() { + let db = db_with_root_text( + r#" +module m(.out(foo)); + output foo; +endmodule +"#, + ); + let module_id = db + .unit_scope() + .module_ids(&db, &ident("m")) + .unique() + .expect("module should resolve uniquely"); + let (module, source_map) = db.module_with_source_map(module_id); + let Ports::NonAnsi { ports, .. } = &module.ports else { + panic!("module should have non-ANSI ports"); + }; + let (port_id, _) = ports.iter().next().expect("port should lower"); + let source = source_map.get(port_id).expect("port should retain its source"); + + assert!(source.name_range().is_some(), "explicit port name range should be preserved"); + } + + #[test] + fn implicit_non_ansi_port_source_supports_natural_reverse_lookup() { + let db = db_with_root_text( + r#" +module m(foo); + output foo; +endmodule +"#, + ); + let module_id = db + .unit_scope() + .module_ids(&db, &ident("m")) + .unique() + .expect("module should resolve uniquely"); + let (module, source_map) = db.module_with_source_map(module_id); + let Ports::NonAnsi { ports, .. } = &module.ports else { + panic!("module should have non-ANSI ports"); + }; + let (port_id, _) = ports.iter().next().expect("port should lower"); + + let tree = db.parse(TOP.into()); + let root = tree.root().expect("source should parse"); + let unit = ast::CompilationUnit::cast(root).expect("root should be a compilation unit"); + let ast::Member::ModuleDeclaration(module_ast) = + unit.members().children().next().expect("module should parse") + else { + panic!("first member should be a module"); + }; + let ast::PortList::NonAnsiPortList(port_list) = + module_ast.header().ports().expect("module should have a port list") + else { + panic!("module should have a non-ANSI port list"); + }; + let port_ast = port_list.ports().children().next().expect("port should parse"); + let natural_source = NonAnsiPortSrc::from_ast(TOP.into(), port_ast); + let PortSrcs::NonAnsi { ports: port_sources, .. } = &source_map.port_srcs else { + panic!("source map should contain non-ANSI ports"); + }; + + assert_eq!( + port_sources.src_to_hir(natural_source), + Some(port_id), + "natural AST source key should resolve to the port" + ); + } + #[test] fn non_ansi_port_def_id_is_stable_when_origins_change() { let mut db = db_with_root_text( @@ -1113,31 +1188,25 @@ endmodule .expect("empty statement should lower"); assert!(source_map.get(empty_id).is_some()); - let mut stmts = Default::default(); - let mut stmt_srcs = Default::default(); - let mut event_exprs = Default::default(); - let mut event_expr_srcs = Default::default(); - let mut exprs = Default::default(); - let mut expr_srcs = Default::default(); - let mut decls = Default::default(); - let mut decl_srcs = Default::default(); - let missing_id = crate::hir_def::stmt::LowerStmtCtx { - db: &db, - file_id: TOP.into(), - cont_id: HirFileId::File(TOP).into(), - stmts: &mut stmts, - stmt_srcs: &mut stmt_srcs, - event_exprs: &mut event_exprs, - event_expr_srcs: &mut event_expr_srcs, - exprs: &mut exprs, - expr_srcs: &mut expr_srcs, - decls: &mut decls, - decl_srcs: &mut decl_srcs, - } - .lower_stmt_opt(None); + let mut missing_file = crate::hir_def::file::HirFile::default(); + let mut missing_file_source_map = crate::hir_def::file::FileSourceMap::default(); + let mut ctx = crate::hir_def::lower::LoweringCtx::new( + &db, + TOP.into(), + crate::container::ArenaOwnerId::File(HirFileId::File(TOP)), + crate::hir_def::lower::FileStore { + data: &mut missing_file, + sources: &mut missing_file_source_map, + }, + ); + let missing_id = ctx.lower_stmt_opt(None); + drop(ctx); - assert!(matches!(stmts[missing_id].kind, crate::hir_def::stmt::StmtKind::Missing)); - assert!(stmt_srcs.get(missing_id).is_none()); + assert!(matches!( + missing_file.stmts[missing_id].kind, + crate::hir_def::stmt::StmtKind::Missing + )); + assert!(missing_file_source_map.stmt_srcs.get(missing_id).is_none()); } #[test] diff --git a/crates/hir/src/semantics/resolver.rs b/crates/hir/src/semantics/resolver.rs index 304d01bfe..63d794dc8 100644 --- a/crates/hir/src/semantics/resolver.rs +++ b/crates/hir/src/semantics/resolver.rs @@ -82,7 +82,7 @@ impl SemanticsImpl<'_> { let src_map = container_id.source_map(db); let expr_src = ExprSrc::from_ast(file_id, expr); - let expr_id = src_map.get(expr_src)?; + let expr_id = src_map.expr_from_source(expr_src)?; Some(InContainer::new(container_id, expr_id)) } } diff --git a/crates/hir/src/source_map.rs b/crates/hir/src/source_map.rs index c4b74db07..c0680f464 100644 --- a/crates/hir/src/source_map.rs +++ b/crates/hir/src/source_map.rs @@ -149,7 +149,7 @@ where /// Conversion from a root-buffer AST node into a source-map key. /// -/// `alloc_idx_and_src!` depends on this trait instead of plain `From` +/// `alloc_with_source` depends on this trait instead of plain `From` /// so adding a new source-map entry point requires an explicit implementation /// that is checked by `cargo check`. Keep ordinary `From` impls for /// lookup paths that already operate on AST nodes under the cursor in the root diff --git a/crates/hir/src/type_infer.rs b/crates/hir/src/type_infer.rs index 01edc172f..d32d3dbe0 100644 --- a/crates/hir/src/type_infer.rs +++ b/crates/hir/src/type_infer.rs @@ -999,14 +999,14 @@ mod tests { let DefOriginLoc::Decl(decl) = def.primary_origin(db).loc(db) else { panic!("expected {name} owner to be a declaration"); }; - assert_eq!(decl.cont_id.data(db).get(decl.value).name.as_deref(), Some(name)); + assert_eq!(decl.cont_id.data(db).declarator(decl.value).name.as_deref(), Some(name)); } fn assert_owner_is_typedef(db: &TestDb, def: DefId, name: &str) { let DefOriginLoc::Typedef(typedef) = def.primary_origin(db).loc(db) else { panic!("expected {name} owner to be a typedef"); }; - assert_eq!(typedef.cont_id.data(db).get(typedef.value).name.as_deref(), Some(name)); + assert_eq!(typedef.cont_id.data(db).typedef(typedef.value).name.as_deref(), Some(name)); } #[test] diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index da3e9d64c..2575a9677 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -9,7 +9,6 @@ use syntax::{ token::TokenKindExt, }; use utils::{ - get::GetRef, line_index::{TextRange, TextSize, covering_range}, uniq_vec::UniqVec, }; @@ -135,7 +134,7 @@ fn handle_literal( let expr = ast::Expression::cast(parent)?; let InContainer { value: expr_id, cont_id } = sema.resolve_expr(file_id, expr)?; let container = cont_id.data(sema.db); - let Expr::Literal(literal) = container.get(expr_id) else { + let Expr::Literal(literal) = container.expr(expr_id) else { return None; }; diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 20623948a..fc6ada169 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -174,14 +174,14 @@ impl ToNav for InContainer { let InContainer { value: decl_id, cont_id } = *self; let file_id = cont_id.file_id(db); - let src = cont_id.source_map(db).get(decl_id)?; + let src = cont_id.source_map(db).source_of_declarator(decl_id)?; let cont = cont_id.data(db); - let decl = cont.get(decl_id); + let decl = cont.declarator(decl_id); let kind = match decl.parent { DeclaratorParent::PortDeclId(_) => SymbolKind::PortDecl, - DeclaratorParent::DeclarationId(idx) => match cont.get(idx) { + DeclaratorParent::DeclarationId(idx) => match cont.declaration(idx) { Declaration::DataDecl(_) => SymbolKind::DataDecl, Declaration::NetDecl(_) => SymbolKind::NetDecl, Declaration::ParamDecl(_) => SymbolKind::ParamDecl, @@ -205,10 +205,10 @@ impl ToNav for InContainer { let InContainer { value: typedef_id, cont_id } = *self; let file_id = cont_id.file_id(db); - let src = cont_id.source_map(db).get(typedef_id)?; + let src = cont_id.source_map(db).source_of_typedef(typedef_id)?; let cont = cont_id.data(db); - let typedef = cont.get(typedef_id); + let typedef = cont.typedef(typedef_id); let cont_name = cont.name().cloned(); let (file_id, focus_range, full_range) = @@ -246,10 +246,10 @@ impl ToNav for InContainer { let InContainer { value: stmt_id, cont_id } = *self; let file_id = cont_id.file_id(db); - let src = cont_id.source_map(db).get(stmt_id)?; + let src = cont_id.source_map(db).source_of_stmt(stmt_id)?; let cont = cont_id.data(db); - let name = cont.get(stmt_id).label.clone(); + let name = cont.stmt(stmt_id).label.clone(); let cont_name = cont.name().cloned(); let (file_id, focus_range, full_range) = diff --git a/crates/ide/src/render.rs b/crates/ide/src/render.rs index a9fe4408e..97490e4ae 100644 --- a/crates/ide/src/render.rs +++ b/crates/ide/src/render.rs @@ -326,11 +326,11 @@ fn render_definition_title(db: &RootDb, origin: &DefOrigin) -> Option { fn render_decl_title_kind(db: &RootDb, decl_id: InContainer) -> Option<&'static str> { let container = decl_id.cont_id.data(db); - let decl = container.get(decl_id.value); + let decl = container.declarator(decl_id.value); Some(match decl.parent { DeclaratorParent::PortDeclId(_) => "Port", - DeclaratorParent::DeclarationId(parent) => match container.get(parent) { + DeclaratorParent::DeclarationId(parent) => match container.declaration(parent) { Declaration::ParamDecl(param_decl) => match param_decl.kind.keyword() { "parameter" => "Parameter", "localparam" => "Localparam", @@ -572,7 +572,7 @@ fn render_clocking_block_signature( fn render_decl_signature(db: &RootDb, decl_id: InContainer) -> Option { let container = decl_id.cont_id.data(db); - let decl = container.get(decl_id.value); + let decl = container.declarator(decl_id.value); decl.name.as_ref()?; match decl.parent { @@ -589,7 +589,7 @@ fn render_decl_signature(db: &RootDb, decl_id: InContainer) -> Option { - let declaration = container.get(parent); + let declaration = container.declaration(parent); let prefix = render_declaration_prefix(db, decl_id.cont_id, declaration)?; let decl = InContainer::new(decl_id.cont_id, decl_id.value).display_signature(db).ok()?; @@ -652,7 +652,7 @@ fn render_declaration_prefix( fn render_initializer(db: &RootDb, decl_id: InContainer) -> Option { let container = decl_id.cont_id.data(db); - let decl = container.get(decl_id.value); + let decl = container.declarator(decl_id.value); let init = decl .initializer .map(|expr| InContainer::new(decl_id.cont_id, expr).display_source(db).ok())??; @@ -748,9 +748,8 @@ fn render_scope_fact(sema: &Semantics, origin: &DefOrigin) -> Option, - vis: Visibility, - container_name: Ident, - fields: Punctuated, -} - -impl Parse for HirContainer { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let attrs = input.call(Attribute::parse_outer)?; - let vis = input.parse()?; - - input.parse::()?; - let container_name = input.parse()?; - - let content; - braced!(content in input); - let fields = content.parse_terminated(|input| input.parse::(), Token![,])?; - - Ok(Self { attrs, vis, container_name, fields }) - } -} - -struct HirField { - name: Ident, - ty: HirFieldType, - access: Option>, -} - -impl Parse for HirField { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let name = input.parse()?; - input.parse::()?; - - let ty = input.parse()?; - - let access = if input.peek(Token![=>]) { - input.parse::]>()?; - - let content; - braced!(content in input); - - let access = content.parse_terminated( - |input| { - let content; - bracketed!(content in input); - - let id = content.parse::()?; - content.parse::()?; - let src = content.parse::()?; - Ok((id, src)) - }, - Token![,], - )?; - Some(access) - } else { - None - }; - - Ok(Self { name, ty, access }) - } -} - -// its just a proc-macro, so it's fine to allow this for clarity -#[allow(clippy::large_enum_variant)] -enum HirFieldType { - Type(Type), - Arena(Type), - SourceMap { hir: Type, src: Type }, -} - -impl Parse for HirFieldType { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let ty = if input.peek(Bracket) { - let content; - bracketed!(content in input); - let ty = content.parse()?; - - if content.peek(Token![|]) { - content.parse::()?; - let src = content.parse()?; - HirFieldType::SourceMap { hir: ty, src } - } else { - HirFieldType::Arena(ty) - } - } else { - let ty = input.parse()?; - HirFieldType::Type(ty) - }; - - Ok(ty) - } -} - -#[proc_macro] -pub fn define_container(input: TokenStream) -> TokenStream { - let HirContainer { attrs, vis, container_name, fields, .. } = - &parse_macro_input!(input as HirContainer); - - let is_arena = fields.iter().any(|HirField { ty, .. }| matches!(ty, HirFieldType::Arena(_))); - - // Generate the fields for the data struct - let container_fields = fields.iter().map(|HirField { name, ty, .. }| match ty { - HirFieldType::Type(ty) => { - quote! { #vis #name: #ty } - } - HirFieldType::Arena(ty) => quote! { #vis #name: Arena<#ty> }, - HirFieldType::SourceMap { hir, src } => { - quote! { #vis #name: SourceMap<#src, #hir> } - } - }); - - let field_names = fields.iter().flat_map(|HirField { name, ty, access }| match (ty, access) { - (HirFieldType::Type(_), None) => Either::Left(iter::empty()), - _ => Either::Right(iter::once(name.clone())), - }); - - let impl_get = fields.iter().flat_map(|HirField { name, ty, access }| { - match (ty, access) { - (HirFieldType::Type(_), _) | (_, Some(_)) => Either::Left(iter::empty()), - (HirFieldType::SourceMap { hir, src }, None) => { - Either::Right(Either::Left(iter::once(quote! { - impl utils::get::Get<#src> for #container_name { - type Output = Option>; - - fn get(&self, src: #src) -> Self::Output { - self.#name.get(src) - } - } - - impl utils::get::Get> for #container_name { - type Output = Option<#src>; - - fn get(&self, idx: la_arena::Idx<#hir>) -> Self::Output { - self.#name.get(idx) - } - } - }))) - } - (HirFieldType::Arena(ty), None) => Either::Right(Either::Right(iter::once(quote! { - impl utils::get::GetRef> for #container_name { - type Output = #ty; - - fn get(&self, idx: la_arena::Idx<#ty>) -> &Self::Output { - self.#name.get(idx) - } - } - }))), - } - .chain(access.iter().flatten().map(move |(id, src)| { - if is_arena { - quote! { - impl utils::get::GetRef<#id> for #container_name { - type Output = #src; - - fn get(&self, idx: #id) -> &Self::Output { - self.#name.get(idx) - } - } - } - } else { - quote! { - impl utils::get::Get<#src> for #container_name { - type Output = Option<#id>; - - fn get(&self, src: #src) -> Self::Output { - self.#name.get(src) - } - } - - impl utils::get::Get<#id> for #container_name { - type Output = Option<#src>; - - fn get(&self, idx: #id) -> Self::Output { - self.#name.get(idx) - } - } - } - } - })) - }); - - let def = quote! { - #(#attrs)* - #vis struct #container_name { - #(#container_fields,)* - } - - impl #container_name { - pub fn shrink_to_fit(&mut self) { - #(self.#field_names.shrink_to_fit();)* - } - } - - #(#impl_get)* - }; - - TokenStream::from(def) -} - -struct HirContainerImpl { - attrs: Vec, - vis: Visibility, - containers: Punctuated<(Type, Type), Token![,]>, - access: Punctuated, -} - -struct HirFieldAccess { - data_ty: Type, - data_id_ty: Type, - src_ty: Type, -} - -impl Parse for HirFieldAccess { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let data_ty = input.parse()?; - - let buffer; - bracketed!(buffer in input); - let data_id_ty = buffer.parse()?; - buffer.parse::()?; - let src_ty = buffer.parse()?; - if !buffer.is_empty() { - return Err(buffer.error("unexpected token")); - } - Ok(Self { data_ty, data_id_ty, src_ty }) - } -} - -impl Parse for HirContainerImpl { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let attrs = input.call(Attribute::parse_outer)?; - let vis = input.parse()?; - input.parse::()?; - let buffer; - braced!(buffer in input); - let containers = buffer.parse_terminated( - |buf| { - let container = buf.parse()?; - buf.parse::()?; - let src_map = buf.parse()?; - Ok((container, src_map)) - }, - Token![,], - )?; - input.parse::]>()?; - let buffer; - braced!(buffer in input); - let access = buffer.parse_terminated(HirFieldAccess::parse, Token![,])?; - Ok(Self { attrs, vis, containers, access }) - } -} - -#[proc_macro] -pub fn impl_container(input: TokenStream) -> TokenStream { - let HirContainerImpl { attrs, vis, containers, access } = - parse_macro_input!(input as HirContainerImpl); - - let container_def = containers.iter().map(|(name, _)| quote! { #name(Arc<#name>), }); - let container_srcmap_def = containers.iter().map(|(_, name)| quote! { #name(Arc<#name>), }); - - let impls = access.iter().flat_map(|HirFieldAccess { data_ty, data_id_ty, src_ty }| { - let data_arms = containers.iter().map(|(name, _)| { - quote! { Self::#name(it) => it.get(idx), } - }); - - let src_arms = containers.iter().map(|(_, name)| { - quote! { Self::#name(it) => it.get(src), } - }); - - let src_arms_2 = containers.iter().map(|(_, name)| { - quote! { Self::#name(it) => it.get(idx), } - }); - - quote! { - impl utils::get::GetRef<#data_id_ty> for Container { - type Output = #data_ty; - - fn get(&self, idx: #data_id_ty) -> &Self::Output { - match self { - #(#data_arms)* - } - } - } - - impl utils::get::Get<#src_ty> for ContainerSrcMap { - type Output = Option<#data_id_ty>; - - fn get(&self, src: #src_ty) -> Self::Output { - match self { - #(#src_arms)* - } - } - } - - impl utils::get::Get<#data_id_ty> for ContainerSrcMap { - type Output = Option<#src_ty>; - - fn get(&self, idx: #data_id_ty) -> Self::Output { - match self { - #(#src_arms_2)* - } - } - } - } - }); - - let output = quote! { - utils::define_enum_deriving_from! { - #(#attrs)* - #vis enum Container { - #(#container_def)* - } - } - - utils::define_enum_deriving_from! { - #(#attrs)* - #vis enum ContainerSrcMap { - #(#container_srcmap_def)* - } - } - - #(#impls)* - }; - TokenStream::from(output) -}