use crate::syntax::ast::common::{
Attribute, BindableVisibility, ImportKind, ModulePath, Visibility,
};
use crate::syntax::ast::value::{
DimExpr, Expr, MapEntryKey, MultiDeclSharedAxes, ParamBinding, TypeExpr, UnitExpr,
};
use crate::syntax::names::{
ConstructorName, DeclName, DimName, FieldName, GenericParamName, IndexName, IndexVariantName,
PlotPropertyName, ScopedName, StructTypeName, UnitName,
};
use crate::syntax::phase::{Phase, Raw};
use crate::syntax::span::{Span, Spanned};
#[derive(Debug, Clone)]
pub enum RawDeclSugar {
Multi(MultiDecl<Raw>),
}
impl RawDeclSugar {
#[must_use]
pub const fn span(&self) -> Span {
match self {
Self::Multi(m) => m.span,
}
}
}
#[derive(Debug, Clone)]
pub struct File<P: Phase = Raw> {
pub declarations: Vec<Declaration<P>>,
}
#[derive(Debug, Clone)]
pub struct Declaration<P: Phase = Raw> {
pub attributes: Vec<Attribute>,
pub kind: DeclKind<P>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum DeclKind<P: Phase = Raw> {
Param(ParamDecl<P>),
Node(NodeDecl<P>),
ConstNode(ConstNodeDecl<P>),
BaseDimension(BaseDimDecl),
Dimension(DimDecl),
Unit(UnitDecl<P>),
Type(TypeDecl<P>),
Index(IndexDecl<P>),
Import(ImportDecl),
Include(IncludeDecl<P>),
Dag(DagDecl<P>),
Assert(AssertDecl<P>),
Plot(PlotDecl<P>),
Figure(FigureDecl<P>),
Layer(LayerDecl<P>),
Sugar(P::DeclSugar),
}
impl<P: Phase> DeclKind<P> {
#[must_use]
pub fn name_and_span(&self) -> Option<(&str, Span)> {
match self {
Self::Param(p) => Some((p.name.value.as_str(), p.name.span)),
Self::Node(n) => Some((n.name.value.as_str(), n.name.span)),
Self::ConstNode(c) => Some((c.name.value.as_str(), c.name.span)),
Self::BaseDimension(d) => Some((d.name.value.as_str(), d.name.span)),
Self::Dimension(d) => Some((d.name.value.as_str(), d.name.span)),
Self::Unit(u) => Some((u.name.value.as_str(), u.name.span)),
Self::Type(t) => Some((t.name.value.as_str(), t.name.span)),
Self::Index(i) => Some((i.name.value.as_str(), i.name.span)),
Self::Dag(d) => Some((d.name.value.as_str(), d.name.span)),
Self::Assert(a) => Some((a.name.value.as_str(), a.name.span)),
Self::Plot(p) => Some((p.name.value.as_str(), p.name.span)),
Self::Figure(f) => Some((f.name.value.as_str(), f.name.span)),
Self::Layer(l) => Some((l.name.value.as_str(), l.name.span)),
Self::Import(_) | Self::Include(_) | Self::Sugar(_) => None,
}
}
}
#[derive(Debug, Clone)]
pub struct AssertDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub body: AssertBody<P>,
}
#[derive(Debug, Clone)]
pub enum AssertBody<P: Phase = Raw> {
Expr(Expr<P>),
Tolerance {
actual: Box<Expr<P>>,
expected: Box<Expr<P>>,
tolerance: Box<Expr<P>>,
is_relative: bool,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MarkType {
Point,
Line,
Bar,
Area,
Rect,
Tick,
}
impl std::fmt::Display for MarkType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Point => write!(f, "point"),
Self::Line => write!(f, "line"),
Self::Bar => write!(f, "bar"),
Self::Area => write!(f, "area"),
Self::Rect => write!(f, "rect"),
Self::Tick => write!(f, "tick"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EncodingChannel {
X,
Y,
Color,
Size,
Shape,
Opacity,
Detail,
Text,
Tooltip,
}
impl std::fmt::Display for EncodingChannel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::X => write!(f, "x"),
Self::Y => write!(f, "y"),
Self::Color => write!(f, "color"),
Self::Size => write!(f, "size"),
Self::Shape => write!(f, "shape"),
Self::Opacity => write!(f, "opacity"),
Self::Detail => write!(f, "detail"),
Self::Text => write!(f, "text"),
Self::Tooltip => write!(f, "tooltip"),
}
}
}
#[derive(Debug, Clone)]
pub struct MarkSpec<P: Phase = Raw> {
pub mark_type: MarkType,
pub mark_type_span: Span,
pub properties: Vec<PlotField<P>>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct Encoding<P: Phase = Raw> {
pub channel: EncodingChannel,
pub channel_span: Span,
pub value: Expr<P>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct PlotField<P: Phase = Raw> {
pub name: Spanned<PlotPropertyName>,
pub value: Expr<P>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct PlotDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub mark: MarkSpec<P>,
pub encodings: Vec<Encoding<P>>,
pub properties: Vec<PlotField<P>>,
}
#[derive(Debug, Clone)]
pub struct FigureDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub plot_names: Vec<Spanned<ScopedName>>,
pub fields: Vec<PlotField<P>>,
}
#[derive(Debug, Clone)]
pub struct LayerDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub plot_names: Vec<Spanned<ScopedName>>,
pub fields: Vec<PlotField<P>>,
}
#[derive(Debug, Clone)]
pub struct ImportDecl {
pub visibility: Visibility,
pub path: ModulePath,
pub kind: ImportKind,
}
#[derive(Debug, Clone)]
pub struct IncludeDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub path: ModulePath,
pub param_bindings: Vec<ParamBinding<P>>,
pub kind: ImportKind,
}
#[derive(Debug, Clone)]
pub struct DagDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub body: Vec<Declaration<P>>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct ParamDecl<P: Phase = Raw> {
pub name: Spanned<DeclName>,
pub type_ann: TypeExpr<P>,
pub value: Option<Expr<P>>,
}
#[derive(Debug, Clone)]
pub struct MultiDecl<P: Phase = Raw> {
pub slots: Vec<MultiDeclSlot<P>>,
pub shared_axes: MultiDeclSharedAxes,
pub slot_axes: Vec<MultiSlotAxis>,
pub slices: Vec<MultiDeclSlice<P>>,
pub span: Span,
pub table_expr_span: Span,
}
#[derive(Debug, Clone)]
pub struct MultiDeclSlot<P: Phase = Raw> {
pub visibility: Visibility,
pub kind: MultiSlotKind,
pub kind_span: Span,
pub name: Spanned<DeclName>,
pub type_ann: TypeExpr<P>,
pub header_span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MultiSlotKind {
Param,
Node,
ConstNode,
}
#[derive(Debug, Clone)]
pub enum MultiSlotAxis {
Underscore,
Axis(Spanned<IndexName>),
}
#[derive(Debug, Clone)]
pub enum MultiSlotColumnSpan {
Single(usize),
Range {
start: usize,
end: usize,
extra_axis: Spanned<IndexName>,
},
}
#[derive(Debug, Clone)]
pub struct MultiDeclSlice<P: Phase = Raw> {
pub prefix_keys: Vec<MapEntryKey>,
pub header_cells: Vec<MultiHeaderCell>,
pub header_span: Span,
pub column_layout: Vec<MultiSlotColumnSpan>,
pub rows: Vec<MultiDataRow<P>>,
}
#[derive(Debug, Clone)]
pub enum MultiHeaderCell {
Underscore {
span: Span,
},
Variant {
axis: Option<Spanned<IndexName>>,
variant: Spanned<IndexVariantName>,
span: Span,
},
}
impl MultiHeaderCell {
#[must_use]
pub const fn span(&self) -> Span {
match self {
Self::Underscore { span } | Self::Variant { span, .. } => *span,
}
}
}
#[derive(Debug, Clone)]
pub struct MultiDataRow<P: Phase = Raw> {
pub label: Spanned<IndexVariantName>,
pub values: Vec<Expr<P>>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct NodeDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub type_ann: TypeExpr<P>,
pub value: Expr<P>,
}
#[derive(Debug, Clone)]
pub struct ConstNodeDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub name: Spanned<DeclName>,
pub type_ann: TypeExpr<P>,
pub value: Expr<P>,
}
#[derive(Debug, Clone)]
pub struct BaseDimDecl {
pub visibility: Visibility,
pub name: Spanned<DimName>,
}
#[derive(Debug, Clone)]
pub struct DimDecl {
pub visibility: BindableVisibility,
pub name: Spanned<DimName>,
pub definition: Option<DimExpr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnitConstness {
Const,
Dynamic,
}
impl UnitConstness {
#[must_use]
pub const fn is_const(self) -> bool {
matches!(self, Self::Const)
}
}
#[derive(Debug, Clone)]
pub struct UnitDecl<P: Phase = Raw> {
pub visibility: Visibility,
pub constness: UnitConstness,
pub name: Spanned<UnitName>,
pub dim_type: DimExpr,
pub definition: Option<UnitDef<P>>,
}
#[derive(Debug, Clone)]
pub struct UnitDef<P: Phase = Raw> {
pub scale_expr: Expr<P>,
pub unit_expr: UnitExpr,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TypeDecl<P: Phase = Raw> {
pub visibility: BindableVisibility,
pub name: Spanned<StructTypeName>,
pub generic_params: Vec<GenericParam<P>>,
pub body: TypeDeclBody<P>,
}
#[derive(Debug, Clone)]
pub enum TypeDeclBody<P: Phase = Raw> {
Required,
Constructors(Vec<UnionMember<P>>),
}
#[derive(Debug, Clone)]
pub struct UnionMember<P: Phase = Raw> {
pub name: Spanned<ConstructorName>,
pub payload: Option<Vec<FieldDecl<P>>>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct FieldDecl<P: Phase = Raw> {
pub name: Spanned<FieldName>,
pub type_ann: TypeExpr<P>,
}
#[derive(Debug, Clone)]
pub enum IndexDeclKind<P: Phase = Raw> {
Named {
variants: Vec<Spanned<IndexVariantName>>,
},
Range {
start: Box<Expr<P>>,
end: Box<Expr<P>>,
step: Box<Expr<P>>,
},
RequiredNamed,
RequiredRange { dimension: DimExpr },
}
impl<P: Phase> IndexDeclKind<P> {
#[must_use]
pub const fn is_required(&self) -> bool {
matches!(self, Self::RequiredNamed | Self::RequiredRange { .. })
}
}
#[derive(Debug, Clone)]
pub struct IndexDecl<P: Phase = Raw> {
pub visibility: BindableVisibility,
pub name: Spanned<IndexName>,
pub kind: IndexDeclKind<P>,
}
#[derive(Debug, Clone)]
pub struct GenericParam<P: Phase = Raw> {
pub name: Spanned<GenericParamName>,
pub constraint: GenericConstraint,
pub default: Option<TypeExpr<P>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GenericConstraint {
Dim,
Index,
Nat,
Type,
}