use super::host::RelPath;
use super::load::FileId;
use super::types::{GlobalId, StructId, SumId, SymbolId, TypeId};
macro_rules! id {
($(#[$doc:meta])* $name:ident) => {
$(#[$doc])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct $name(pub(crate) u32);
impl $name {
pub(crate) fn new(index: usize) -> Self {
debug_assert!(u32::try_from(index).is_ok(), "fewer than 2^32 items exist");
Self(index as u32)
}
pub(crate) fn index(self) -> usize {
self.0 as usize
}
}
};
}
id!(
UnitId
);
id!(
LocalId
);
#[derive(Debug, Clone)]
pub(crate) struct Unit {
pub(crate) file: FileId,
pub(crate) target: Option<StructId>,
pub(crate) facts: Vec<Fact>,
pub(crate) locals: Vec<LocalDef>,
}
#[derive(Debug, Clone)]
pub(crate) struct LocalDef {
pub(crate) name: String,
pub(crate) ty: TypeId,
pub(crate) reads: Vec<SelfRead>,
pub(crate) top: Option<u32>,
}
#[derive(Debug, Clone, Default)]
pub(crate) enum Fact {
#[default]
None,
Expr(ExprFact),
Attr(AttrFact),
Block(BlockFact),
Include(IncludeFact),
Let(LetFact),
For(ForFact),
Pattern(PatternFact),
}
#[derive(Debug, Clone)]
pub(crate) struct ExprFact {
pub(crate) ty: TypeId,
pub(crate) meaning: Meaning,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum Meaning {
Plain,
Local(LocalId),
Global(GlobalId),
Variant { sum: SumId, variant: usize },
Symbol(SymbolId),
RefLabel(StructId),
Field { index: usize, optional: bool },
SelfField(SelfRead),
Path { root: usize, rel: Option<RelPath> },
Call(CallFact),
Struct(StructId),
Binds(Vec<LocalId>),
MapCompKey {
binds: Vec<LocalId>,
key: Box<Meaning>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CallFact {
pub(crate) callee: Callee,
pub(crate) args: Vec<Option<usize>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Callee {
Global(GlobalId),
Builtin(super::builtins::Builtin),
Constructor(SymbolId),
Variant { sum: SumId, variant: usize },
Value,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct SelfRead {
pub(crate) depth: usize,
pub(crate) structure: StructId,
pub(crate) field: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) enum Priority {
Default,
Plain,
Force,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Step {
Field(usize),
Key(String),
}
#[derive(Debug, Clone)]
pub(crate) struct AttrFact {
pub(crate) steps: Vec<Step>,
pub(crate) ty: TypeId,
pub(crate) priority: Priority,
pub(crate) value: usize,
pub(crate) reads: Vec<SelfRead>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Target {
Struct(StructId),
Map {
key: TypeId,
value: TypeId,
},
Variant {
sum: SumId,
variant: usize,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum BlockRule {
Clause,
Field,
MapField,
Tagged,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum LabelFact {
Static(String),
Dynamic,
}
#[derive(Debug, Clone)]
pub(crate) struct BlockFact {
pub(crate) rule: BlockRule,
pub(crate) field: usize,
pub(crate) label: Option<LabelFact>,
pub(crate) target: Target,
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum IncludeFact {
File(UnitId),
Value,
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum LetFact {
Local(LocalId),
Global(GlobalId),
}
#[derive(Debug, Clone)]
pub(crate) struct ForFact {
pub(crate) binds: Vec<LocalId>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum PatternFact {
Wildcard,
Binder(LocalId),
Literal,
Variant {
sum: SumId,
variant: usize,
fields: Vec<(usize, Option<LocalId>)>,
},
Or,
}