use {
crate::core::{Ident, SymbolPath, SymbolVisibility, Value, Visibility},
laburnum::{
ContentHash,
database::{RecordHandle, partitions::IndexEntry},
record::CollectReferences,
},
std::hash::Hash,
};
use super::symbols::Symbols;
#[derive(Clone)]
pub struct SymbolEntry<V, I, P, S = SymbolVisibility>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
pub path: P,
pub span: laburnum::Span,
pub symbol: RecordHandle<Symbols<V, I, P, S>>,
}
impl<V, I, P, S> Hash for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.path.hash(state);
self.span.hash(state);
self.symbol.hash(state);
}
}
impl<V, I, P, S> PartialEq for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn eq(&self, other: &Self) -> bool {
self.path == other.path
&& self.span == other.span
&& self.symbol == other.symbol
}
}
impl<V, I, P, S> Eq for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
}
impl<V, I, P, S> SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
pub fn new(
path: P,
span: laburnum::Span,
symbol: RecordHandle<Symbols<V, I, P, S>>,
) -> Self {
Self { path, span, symbol }
}
}
impl<V, I, P, S> IndexEntry for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn primary_hash(&self) -> Option<ContentHash> {
Some(self.symbol.content_hash())
}
}
impl<V, I, P, S> laburnum::database::partitions::IndexedEntry
for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn content_hash(&self) -> ContentHash {
self.symbol.content_hash()
}
}
impl<V, I, P, S> bluegum::Bluegum for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn node(&self, b: &mut bluegum::Builder) {
b.name("SymbolEntry")
.field("span", self.span)
.field("symbol", self.symbol.content_hash());
}
}
impl<V, I, P, S> bluegum::BluegumWithState<dyn laburnum::SourceResolver>
for SymbolEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn node_with_state(
&self,
b: &mut bluegum::Builder,
_state: &dyn laburnum::SourceResolver,
) {
b.name("SymbolEntry")
.field("symbol", self.symbol.content_hash());
}
}
impl<Ps, V, I, P, S> CollectReferences<Ps> for SymbolEntry<V, I, P, S>
where
Ps: laburnum::database::storage::Partitions,
Ps::Stores: laburnum::database::partitions::HasPartition<Symbols<V, I, P, S>>,
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn collect_references<R: laburnum::record::References<Ps>>(
&self,
refs: &mut R,
) {
refs.add(self.symbol);
}
}
#[derive(Clone, Hash)]
pub enum ResolutionTarget<V, I, P, S = SymbolVisibility>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
Resolved(RecordHandle<Symbols<V, I, P, S>>),
Inaccessible(RecordHandle<Symbols<V, I, P, S>>),
NotFound,
}
impl<V, I, P, S> ResolutionTarget<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
pub fn handle(&self) -> Option<RecordHandle<Symbols<V, I, P, S>>> {
match self {
| Self::Resolved(h) | Self::Inaccessible(h) => Some(*h),
| Self::NotFound => None,
}
}
pub fn is_resolved(&self) -> bool {
matches!(self, Self::Resolved(_))
}
}
#[derive(Clone, Hash)]
pub struct ResolutionEntry<V, I, P, S = SymbolVisibility>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
pub target_path: P,
pub target: ResolutionTarget<V, I, P, S>,
}
impl<V, I, P, S> ResolutionEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
pub fn new(target_path: P, target: ResolutionTarget<V, I, P, S>) -> Self {
Self {
target_path,
target,
}
}
pub fn resolved(
target_path: P,
target: RecordHandle<Symbols<V, I, P, S>>,
) -> Self {
Self::new(target_path, ResolutionTarget::Resolved(target))
}
pub fn inaccessible(
target_path: P,
target: RecordHandle<Symbols<V, I, P, S>>,
) -> Self {
Self::new(target_path, ResolutionTarget::Inaccessible(target))
}
pub fn not_found(target_path: P) -> Self {
Self::new(target_path, ResolutionTarget::NotFound)
}
}
impl<V, I, P, S> IndexEntry for ResolutionEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn primary_hash(&self) -> Option<ContentHash> {
self.target.handle().map(|h| h.content_hash())
}
}
impl<V, I, P, S> laburnum::database::partitions::IndexedEntry
for ResolutionEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn content_hash(&self) -> ContentHash {
laburnum::record::hash_record(self)
}
}
impl<V, I, P, S> bluegum::Bluegum for ResolutionEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn node(&self, b: &mut bluegum::Builder) {
b.name("ResolutionEntry").field("target_path", "<path>");
match &self.target {
| ResolutionTarget::Resolved(h) => {
b.field("resolved", h.content_hash());
},
| ResolutionTarget::Inaccessible(h) => {
b.field("inaccessible", h.content_hash());
},
| ResolutionTarget::NotFound => {
b.field("kind", format!("{:?}", "NotFound"));
},
}
}
}
impl<V, I, P, S> bluegum::BluegumWithState<dyn laburnum::SourceResolver>
for ResolutionEntry<V, I, P, S>
where
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
}
impl<Ps, V, I, P, S> CollectReferences<Ps> for ResolutionEntry<V, I, P, S>
where
Ps: laburnum::database::storage::Partitions,
Ps::Stores: laburnum::database::partitions::HasPartition<Symbols<V, I, P, S>>,
V: Value<I>,
I: Ident,
P: SymbolPath,
S: Visibility,
{
fn collect_references<R: laburnum::record::References<Ps>>(
&self,
refs: &mut R,
) {
if let Some(handle) = self.target.handle() {
refs.add(handle);
}
}
}