use crate::collections::HashSet;
use crate::compile::{Item, Location, Visibility};
use crate::parse::Id;
use crate::runtime::ConstValue;
use crate::Hash;
use std::fmt;
use std::path::Path;
use std::sync::Arc;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Meta {
pub item: Item,
pub kind: MetaKind,
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct MetaRef<'a> {
pub item: &'a Item,
pub kind: MetaKind,
pub source: Option<&'a SourceMeta>,
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum MetaKind {
Unknown,
UnitStruct,
TupleStruct,
Struct,
UnitVariant,
TupleVariant,
StructVariant,
Enum,
Function {
type_hash: Hash,
is_test: bool,
is_bench: bool,
},
Closure,
AsyncBlock,
Const,
ConstFn,
Import,
}
impl fmt::Display for Meta {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
MetaKind::Unknown => {
write!(fmt, "unknown {}", self.item)?;
}
MetaKind::UnitStruct => {
write!(fmt, "struct {}", self.item)?;
}
MetaKind::TupleStruct => {
write!(fmt, "struct {}", self.item)?;
}
MetaKind::Struct => {
write!(fmt, "struct {}", self.item)?;
}
MetaKind::UnitVariant => {
write!(fmt, "unit variant {}", self.item)?;
}
MetaKind::TupleVariant => {
write!(fmt, "variant {}", self.item)?;
}
MetaKind::StructVariant => {
write!(fmt, "variant {}", self.item)?;
}
MetaKind::Enum => {
write!(fmt, "enum {}", self.item)?;
}
MetaKind::Function { .. } => {
write!(fmt, "fn {}", self.item)?;
}
MetaKind::Closure => {
write!(fmt, "closure {}", self.item)?;
}
MetaKind::AsyncBlock => {
write!(fmt, "async block {}", self.item)?;
}
MetaKind::Const => {
write!(fmt, "const {}", self.item)?;
}
MetaKind::ConstFn => {
write!(fmt, "const fn {}", self.item)?;
}
MetaKind::Import => {
write!(fmt, "import {}", self.item)?;
}
}
Ok(())
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct SourceMeta {
pub location: Location,
pub path: Option<Box<Path>>,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub(crate) struct CaptureMeta {
pub(crate) ident: Box<str>,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub(crate) struct PrivMeta {
pub(crate) item: Arc<ItemMeta>,
pub(crate) kind: PrivMetaKind,
pub(crate) source: Option<SourceMeta>,
}
impl PrivMeta {
pub(crate) fn info(&self) -> Meta {
Meta {
item: self.item.item.clone(),
kind: self.kind.as_meta_info_kind(),
}
}
pub(crate) fn info_ref(&self) -> MetaRef<'_> {
MetaRef {
item: &self.item.item,
kind: self.kind.as_meta_info_kind(),
source: self.source.as_ref(),
}
}
pub(crate) fn type_hash_of(&self) -> Option<Hash> {
match &self.kind {
PrivMetaKind::Unknown { type_hash, .. } => Some(*type_hash),
PrivMetaKind::Struct { type_hash, .. } => Some(*type_hash),
PrivMetaKind::Enum { type_hash, .. } => Some(*type_hash),
PrivMetaKind::Function { type_hash, .. } => Some(*type_hash),
PrivMetaKind::Closure { type_hash, .. } => Some(*type_hash),
PrivMetaKind::AsyncBlock { type_hash, .. } => Some(*type_hash),
PrivMetaKind::Variant { .. } => None,
PrivMetaKind::Const { .. } => None,
PrivMetaKind::ConstFn { .. } => None,
PrivMetaKind::Import { .. } => None,
}
}
}
#[derive(Debug, Clone)]
pub(crate) enum PrivVariantMeta {
Tuple(PrivTupleMeta),
Struct(PrivStructMeta),
Unit,
}
#[derive(Debug, Clone)]
pub(crate) enum PrivMetaKind {
Unknown { type_hash: Hash },
Struct {
type_hash: Hash,
variant: PrivVariantMeta,
},
Variant {
type_hash: Hash,
enum_item: Item,
enum_hash: Hash,
index: usize,
variant: PrivVariantMeta,
},
Enum {
type_hash: Hash,
},
Function {
type_hash: Hash,
is_test: bool,
is_bench: bool,
},
Closure {
type_hash: Hash,
captures: Arc<[CaptureMeta]>,
do_move: bool,
},
AsyncBlock {
type_hash: Hash,
captures: Arc<[CaptureMeta]>,
do_move: bool,
},
Const {
const_value: ConstValue,
},
ConstFn {
id: Id,
},
Import {
module: Arc<ModMeta>,
location: Location,
target: Item,
},
}
impl PrivMetaKind {
pub(crate) fn as_meta_info_kind(&self) -> MetaKind {
match self {
PrivMetaKind::Unknown { .. } => MetaKind::Unknown,
PrivMetaKind::Struct {
variant: PrivVariantMeta::Unit,
..
} => MetaKind::UnitStruct,
PrivMetaKind::Struct {
variant: PrivVariantMeta::Tuple(..),
..
} => MetaKind::TupleStruct,
PrivMetaKind::Struct {
variant: PrivVariantMeta::Struct(..),
..
} => MetaKind::Struct,
PrivMetaKind::Variant {
variant: PrivVariantMeta::Unit,
..
} => MetaKind::UnitVariant,
PrivMetaKind::Variant {
variant: PrivVariantMeta::Tuple(..),
..
} => MetaKind::TupleVariant,
PrivMetaKind::Variant {
variant: PrivVariantMeta::Struct(..),
..
} => MetaKind::StructVariant,
PrivMetaKind::Enum { .. } => MetaKind::Enum,
PrivMetaKind::Function {
type_hash,
is_bench,
is_test,
..
} => MetaKind::Function {
type_hash: *type_hash,
is_bench: *is_bench,
is_test: *is_test,
},
PrivMetaKind::Closure { .. } => MetaKind::Closure,
PrivMetaKind::AsyncBlock { .. } => MetaKind::AsyncBlock,
PrivMetaKind::Const { .. } => MetaKind::Const,
PrivMetaKind::ConstFn { .. } => MetaKind::ConstFn,
PrivMetaKind::Import { .. } => MetaKind::Import,
}
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub(crate) struct PrivStructMeta {
pub(crate) fields: HashSet<Box<str>>,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub(crate) struct PrivTupleMeta {
pub(crate) args: usize,
pub(crate) hash: Hash,
}
#[derive(Default, Debug, Clone)]
#[non_exhaustive]
pub(crate) struct ItemMeta {
pub(crate) id: Id,
pub(crate) location: Location,
pub(crate) item: Item,
pub(crate) visibility: Visibility,
pub(crate) module: Arc<ModMeta>,
}
impl ItemMeta {
pub(crate) fn is_public(&self) -> bool {
self.visibility.is_public() && self.module.is_public()
}
}
impl From<Item> for ItemMeta {
fn from(item: Item) -> Self {
Self {
id: Default::default(),
location: Default::default(),
item,
visibility: Default::default(),
module: Default::default(),
}
}
}
#[derive(Default, Debug)]
#[non_exhaustive]
pub(crate) struct ModMeta {
pub(crate) location: Location,
pub(crate) item: Item,
pub(crate) visibility: Visibility,
pub(crate) parent: Option<Arc<ModMeta>>,
}
impl ModMeta {
pub(crate) fn is_public(&self) -> bool {
let mut current = Some(self);
while let Some(m) = current.take() {
if !m.visibility.is_public() {
return false;
}
current = m.parent.as_deref();
}
true
}
}