Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 124 additions & 47 deletions crates/hir/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,104 @@ use crate::{
generate::{GenerateBlock, GenerateBlockId, GenerateBlockSourceMap},
},
stmt::{Stmt, StmtId, StmtSrc},
subroutine::{Subroutine, SubroutineId, SubroutineSourceMap},
subroutine::{LocalSubroutineId, Subroutine, SubroutineSourceMap},
typedef::{Typedef, TypedefId, TypedefSrc},
},
region_tree::RegionTree,
symbol::ScopeKind,
};

define_enum_deriving_from! {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum ContainerId {
HirFileId(HirFileId),
ModuleId(ModuleId),
GenerateBlockId(GenerateBlockId),
BlockId(BlockId),
SubroutineId(SubroutineId),
pub enum ScopeId {
File(HirFileId),
Module(ModuleId),
GenerateBlock(GenerateBlockId),
Block(BlockId),
Subroutine(SubroutineScope),
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct SubroutineScope {
pub cont_id: SubroutineParent,
pub value: LocalSubroutineId,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum SubroutineParent {
File(HirFileId),
Module(ModuleId),
GenerateBlock(GenerateBlockId),
}

impl SubroutineScope {
pub fn new(cont_id: SubroutineParent, value: LocalSubroutineId) -> Self {
Self { cont_id, value }
}

pub fn parent_scope(self) -> ScopeId {
self.cont_id.into()
}

pub fn as_in_container(self) -> InContainer<LocalSubroutineId> {
InContainer::new(self.parent_scope(), self.value)
}

pub fn file_id(self, db: &dyn InternDb) -> FileId {
match self.cont_id {
SubroutineParent::File(file_id) => file_id.file_id(),
SubroutineParent::Module(module_id) => module_id.file_id(),
SubroutineParent::GenerateBlock(generate_block_id) => generate_block_id.file_id(db),
}
}
}

impl From<SubroutineParent> for ScopeId {
fn from(cont_id: SubroutineParent) -> Self {
match cont_id {
SubroutineParent::File(file_id) => file_id.into(),
SubroutineParent::Module(module_id) => module_id.into(),
SubroutineParent::GenerateBlock(generate_block_id) => generate_block_id.into(),
}
}
}

impl TryFrom<ScopeId> for SubroutineParent {
type Error = ();

fn try_from(cont_id: ScopeId) -> Result<Self, Self::Error> {
match cont_id {
ScopeId::File(file_id) => Ok(Self::File(file_id)),
ScopeId::Module(module_id) => Ok(Self::Module(module_id)),
ScopeId::GenerateBlock(generate_block_id) => Ok(Self::GenerateBlock(generate_block_id)),
ScopeId::Block(_) | ScopeId::Subroutine(_) => Err(()),
}
}
}

impl From<InContainer<LocalSubroutineId>> for SubroutineScope {
fn from(subroutine: InContainer<LocalSubroutineId>) -> Self {
let parent = SubroutineParent::try_from(subroutine.cont_id)
.expect("subroutines are lowered only in file, module, or generate-block scopes");
Self::new(parent, subroutine.value)
}
}

impl From<InContainer<LocalSubroutineId>> for ScopeId {
fn from(subroutine: InContainer<LocalSubroutineId>) -> Self {
ScopeId::Subroutine(subroutine.into())
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct InContainer<T> {
pub value: T,
pub cont_id: ContainerId,
pub cont_id: ScopeId,
}

impl<T> InContainer<T> {
pub fn new(cont_id: ContainerId, value: T) -> InContainer<T> {
pub fn new(cont_id: ScopeId, value: T) -> InContainer<T> {
InContainer { value, cont_id }
}

Expand All @@ -63,11 +136,11 @@ impl<T> InContainer<T> {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct InSubroutine<T> {
pub value: T,
pub subroutine: SubroutineId,
pub subroutine: InContainer<LocalSubroutineId>,
}

impl<T> InSubroutine<T> {
pub fn new(subroutine: SubroutineId, value: T) -> Self {
pub fn new(subroutine: InContainer<LocalSubroutineId>, value: T) -> Self {
Self { value, subroutine }
}

Expand All @@ -78,7 +151,7 @@ impl<T> InSubroutine<T> {

impl<T> From<InSubroutine<T>> for InContainer<T> {
fn from(item: InSubroutine<T>) -> InContainer<T> {
InContainer::new(ContainerId::SubroutineId(item.subroutine), item.value)
InContainer::new(item.subroutine.into(), item.value)
}
}

Expand Down Expand Up @@ -121,41 +194,47 @@ define_container_id! {
InBlock[block_id: BlockId],
}

impl ContainerId {
impl ScopeId {
pub fn kind(self) -> ScopeKind {
match self {
ScopeId::File(_) => ScopeKind::File,
ScopeId::Module(_) => ScopeKind::Module,
ScopeId::GenerateBlock(_) => ScopeKind::GenerateBlock,
ScopeId::Block(_) => ScopeKind::Block,
ScopeId::Subroutine(_) => ScopeKind::Subroutine,
}
}

pub fn file_id(self, db: &dyn InternDb) -> FileId {
match self {
ContainerId::HirFileId(file_id) => file_id.file_id(),
ContainerId::ModuleId(module_id) => module_id.file_id(),
ContainerId::GenerateBlockId(generate_block_id) => generate_block_id.file_id(db),
ContainerId::BlockId(block_id) => block_id.file_id(db),
ContainerId::SubroutineId(subroutine_id) => {
subroutine_id.lookup(db).src.file_id.file_id()
}
ScopeId::File(file_id) => file_id.file_id(),
ScopeId::Module(module_id) => module_id.file_id(),
ScopeId::GenerateBlock(generate_block_id) => generate_block_id.file_id(db),
ScopeId::Block(block_id) => block_id.file_id(db),
ScopeId::Subroutine(subroutine) => subroutine.file_id(db),
}
}

pub fn to_container(self, db: &dyn HirDb) -> Container {
match self {
ContainerId::HirFileId(file_id) => file_id.to_container(db).into(),
ContainerId::ModuleId(module_id) => module_id.to_container(db).into(),
ContainerId::GenerateBlockId(generate_block_id) => {
generate_block_id.to_container(db).into()
}
ContainerId::BlockId(block_id) => block_id.to_container(db).into(),
ContainerId::SubroutineId(subroutine_id) => db.subroutine(subroutine_id).into(),
ScopeId::File(file_id) => file_id.to_container(db).into(),
ScopeId::Module(module_id) => module_id.to_container(db).into(),
ScopeId::GenerateBlock(generate_block_id) => generate_block_id.to_container(db).into(),
ScopeId::Block(block_id) => block_id.to_container(db).into(),
ScopeId::Subroutine(subroutine) => db.subroutine(subroutine.as_in_container()).into(),
}
}

pub fn to_container_src_map(self, db: &dyn HirDb) -> ContainerSrcMap {
match self {
ContainerId::HirFileId(file_id) => file_id.to_container_src_map(db).into(),
ContainerId::ModuleId(module_id) => module_id.to_container_src_map(db).into(),
ContainerId::GenerateBlockId(generate_block_id) => {
ScopeId::File(file_id) => file_id.to_container_src_map(db).into(),
ScopeId::Module(module_id) => module_id.to_container_src_map(db).into(),
ScopeId::GenerateBlock(generate_block_id) => {
generate_block_id.to_container_src_map(db).into()
}
ContainerId::BlockId(block_id) => block_id.to_container_src_map(db).into(),
ContainerId::SubroutineId(subroutine_id) => {
db.subroutine_with_source_map(subroutine_id).1.into()
ScopeId::Block(block_id) => block_id.to_container_src_map(db).into(),
ScopeId::Subroutine(subroutine) => {
db.subroutine_with_source_map(subroutine.as_in_container()).1.into()
}
}
}
Expand Down Expand Up @@ -282,32 +361,30 @@ impl AsRef<ContainerSrcMap> for ContainerSrcMap {
}

/// Parents of a scope.
pub struct ContainerParent<'db> {
pub struct ScopeParent<'db> {
db: &'db dyn InternDb,
cont_id: Option<ContainerId>,
cont_id: Option<ScopeId>,
}

impl ContainerParent<'_> {
pub fn start_from(db: &dyn InternDb, cont_id: ContainerId) -> ContainerParent<'_> {
ContainerParent { db, cont_id: Some(cont_id) }
impl ScopeParent<'_> {
pub fn start_from(db: &dyn InternDb, cont_id: ScopeId) -> ScopeParent<'_> {
ScopeParent { db, cont_id: Some(cont_id) }
}
}

impl Iterator for ContainerParent<'_> {
type Item = ContainerId;
impl Iterator for ScopeParent<'_> {
type Item = ScopeId;

fn next(&mut self) -> Option<Self::Item> {
let next = self.cont_id;
self.cont_id = match self.cont_id? {
ContainerId::HirFileId(_) => None,
ContainerId::ModuleId(module_id) => Some(module_id.file_id.into()),
ContainerId::GenerateBlockId(generate_block_id) => {
ScopeId::File(_) => None,
ScopeId::Module(module_id) => Some(module_id.file_id.into()),
ScopeId::GenerateBlock(generate_block_id) => {
Some(generate_block_id.lookup(self.db).cont_id)
}
ContainerId::BlockId(block_id) => Some(block_id.lookup(self.db).cont_id),
ContainerId::SubroutineId(subroutine_id) => {
Some(subroutine_id.lookup(self.db).cont_id.into())
}
ScopeId::Block(block_id) => Some(block_id.lookup(self.db).cont_id),
ScopeId::Subroutine(subroutine) => Some(subroutine.parent_scope()),
};
next
}
Expand Down
52 changes: 28 additions & 24 deletions crates/hir/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ use crate::{
file::{self, FileSourceMap, HirFile},
macro_file::{self, ExpansionInfo, MacroCallId, MacroCallLoc, MacroFileId, MacroFileLoc},
module::{
self, Module, ModuleId, ModuleSourceMap,
self, Module, ModuleId, ModuleSourceMap, PackageId,
generate::{
self, GenerateBlock, GenerateBlockId, GenerateBlockLoc, GenerateBlockSourceMap,
},
},
subroutine::{
self, Subroutine, SubroutineId, SubroutineLoc, SubroutinePortId, SubroutineSourceMap,
},
subroutine::{self, LocalSubroutineId, Subroutine, SubroutinePortId, SubroutineSourceMap},
typedef::TypedefId,
},
impl_intern_key, impl_intern_lookup,
scope::{BlockScope, GenerateBlockScope, ModuleScope, SubroutineScope, UnitScope},
semantics::pathres::PathResolution,
symbol::{DefId, DefLoc, NameScope},
type_infer::TyResult,
};

Expand All @@ -45,9 +43,6 @@ pub trait InternDb: SourceRootDb {
#[salsa::interned]
fn intern_block(&self, block: BlockLoc) -> BlockId;

#[salsa::interned]
fn intern_subroutine(&self, subroutine: SubroutineLoc) -> SubroutineId;

#[salsa::interned]
fn intern_generate_block(&self, generate_block: GenerateBlockLoc) -> GenerateBlockId;

Expand All @@ -59,11 +54,13 @@ pub trait InternDb: SourceRootDb {

#[salsa::interned]
fn intern_module_def(&self, module_def: ModuleDef) -> ModuleDefId;

#[salsa::interned]
fn intern_def(&self, def: DefLoc) -> DefId;
}

impl_intern!(BuiltinDataTyId, BuiltinDataTy, intern_ty, lookup_intern_ty);
impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
impl_intern!(SubroutineId, SubroutineLoc, intern_subroutine, lookup_intern_subroutine);
impl_intern!(
GenerateBlockId,
GenerateBlockLoc,
Expand All @@ -73,6 +70,7 @@ impl_intern!(
impl_intern!(MacroCallId, MacroCallLoc, intern_macro_call, lookup_intern_macro_call);
impl_intern!(MacroFileId, MacroFileLoc, intern_macro_file, lookup_intern_macro_file);
impl_intern!(ModuleDefId, ModuleDef, intern_module_def, lookup_intern_module_def);
impl_intern!(DefId, DefLoc, intern_def, lookup_intern_def);

#[salsa::query_group(HirDbStorage)]
pub trait HirDb: InternDb {
Expand Down Expand Up @@ -100,10 +98,10 @@ pub trait HirDb: InternDb {
#[salsa::invoke(subroutine::subroutine_with_source_map_query)]
fn subroutine_with_source_map(
&self,
subroutine: SubroutineId,
subroutine: InContainer<LocalSubroutineId>,
) -> (Arc<Subroutine>, Arc<SubroutineSourceMap>);

fn subroutine(&self, subroutine_id: SubroutineId) -> Arc<Subroutine>;
fn subroutine(&self, subroutine_id: InContainer<LocalSubroutineId>) -> Arc<Subroutine>;

#[salsa::invoke(generate::generate_block_with_source_map_query)]
fn generate_block_with_source_map(
Expand All @@ -113,23 +111,29 @@ pub trait HirDb: InternDb {

fn generate_block(&self, generate_block_id: GenerateBlockId) -> Arc<GenerateBlock>;

#[salsa::invoke(UnitScope::unit_scope_query)]
fn unit_scope(&self) -> Arc<UnitScope>;
#[salsa::invoke(NameScope::unit_scope_query)]
fn unit_scope(&self) -> Arc<NameScope>;

#[salsa::invoke(NameScope::file_scope_query)]
fn file_scope(&self, file_id: HirFileId) -> Arc<NameScope>;

#[salsa::invoke(NameScope::module_scope_query)]
fn module_scope(&self, module_id: ModuleId) -> Arc<NameScope>;

#[salsa::invoke(UnitScope::file_scope_query)]
fn file_scope(&self, file_id: HirFileId) -> Arc<UnitScope>;
#[salsa::invoke(NameScope::generate_block_scope_query)]
fn generate_block_scope(&self, generate_block_id: GenerateBlockId) -> Arc<NameScope>;

#[salsa::invoke(ModuleScope::module_scope_query)]
fn module_scope(&self, module_id: ModuleId) -> Arc<ModuleScope>;
#[salsa::invoke(NameScope::block_scope_query)]
fn block_scope(&self, block_id: BlockId) -> Arc<NameScope>;

#[salsa::invoke(GenerateBlockScope::generate_block_scope_query)]
fn generate_block_scope(&self, generate_block_id: GenerateBlockId) -> Arc<GenerateBlockScope>;
#[salsa::invoke(NameScope::subroutine_scope_query)]
fn subroutine_scope(&self, subroutine_id: InContainer<LocalSubroutineId>) -> Arc<NameScope>;

#[salsa::invoke(BlockScope::block_scope_query)]
fn block_scope(&self, block_id: BlockId) -> Arc<BlockScope>;
#[salsa::invoke(NameScope::package_export_signature_query)]
fn package_export_signature(&self, package_id: PackageId) -> Arc<NameScope>;

#[salsa::invoke(SubroutineScope::subroutine_scope_query)]
fn subroutine_scope(&self, subroutine_id: SubroutineId) -> Arc<SubroutineScope>;
#[salsa::invoke(NameScope::package_export_scope_query)]
fn package_export_scope(&self, package_id: PackageId) -> Arc<NameScope>;

#[salsa::invoke(crate::type_infer::type_of_decl_query)]
fn type_of_decl(&self, decl: InContainer<DeclId>) -> Arc<TyResult>;
Expand Down Expand Up @@ -166,7 +170,7 @@ fn block(db: &dyn HirDb, block_id: BlockId) -> Arc<Block> {
db.block_with_source_map(block_id).0
}

fn subroutine(db: &dyn HirDb, subroutine_id: SubroutineId) -> Arc<Subroutine> {
fn subroutine(db: &dyn HirDb, subroutine_id: InContainer<LocalSubroutineId>) -> Arc<Subroutine> {
db.subroutine_with_source_map(subroutine_id).0
}

Expand Down
Loading
Loading