use std::ops::Deref; use crate::lexer::Token; use beef::lean::Cow; use chumsky::{ input::{SpannedInput, Stream}, prelude::*, }; use match_deref::match_deref; pub type Span = SimpleSpan; pub type Error<'s> = Rich<'s, Token<'s>, Span>; pub type Input<'s> = SpannedInput, SimpleSpan, Stream>>; #[derive(Clone)] pub struct FnDef<'s> { pub name: &'s str, pub args: Vec<(Type<'s>, Type<'s>)>, pub ret: Type<'s>, pub block: Option>>, pub meta: Vec>, } impl std::fmt::Debug for FnDef<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} {:?} -> {:?}", self.name, self.args, self.ret)?; if let Some(b) = &self.block { write!(f, " {b:?}")?; } write!(f, " {:?}", self.meta) } } #[derive(Debug, Clone)] pub enum Stmt<'s> { Fn(FnDef<'s>), } #[derive(Debug, Clone)] pub enum Ast<'s> { Module(Vec>), } #[derive(Clone)] pub enum Value<'s> { Float(f64), Int(u64), String(Cow<'s, str>), Unit, } impl std::fmt::Debug for Value<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Float(x) => write!(f, "{x}f"), Self::Int(x) => write!(f, "{x}i"), Self::String(x) => write!(f, "\"{x}\""), Self::Unit => write!(f, "()"), } } } #[derive(Clone, Debug, Copy)] pub enum Associativity { Left, Right, None, } #[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Fix { Pre, Post, In, } #[derive(Clone, Copy)] pub struct FixMetaData<'s> { pub looser_than: Option>, pub tighter_than: Option>, pub fixness: Fix, pub assoc: Option>, } impl std::fmt::Debug for FixMetaData<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?} {{", self.fixness)?; if let Some(x) = self.assoc { write!(f, " assoc {x:?}")?; } if let Some(x) = self.looser_than { write!(f, " looser {x}")?; } if let Some(x) = self.tighter_than { write!(f, " tighter {x}")?; } write!(f, " }}") } } #[derive(Clone, Copy)] pub enum FixMeta<'s> { Default(Spanned), // function precedence Like(Fix, &'s str, Span), Data(Spanned>), } impl<'s> FixMeta<'s> { pub fn span(&self) -> Span { match self { Self::Default(x) => x.span, Self::Like(_, _, x) => x, Self::Data(x) => x.span, } } pub fn fix(&self) -> Fix { match_deref! { match self { Self::Default(Deref @ x) => *x, Self::Like(x,..) => *x, Self::Data(Deref @ FixMetaData { fixness, .. }) => *fixness, } } } } impl std::fmt::Debug for FixMeta<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Default(x) => write!(f, "{x:?}"), Self::Like(x, y, _) => write!(f, "{x:?} {{ like {y} }}"), Self::Data(x) => write!(f, "{x:?}"), } } } #[derive(Clone)] pub enum Meta<'s> { Fix(FixMeta<'s>), Alias(Vec<&'s str>), } impl std::fmt::Debug for Meta<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Fix(fix) => write!(f, "{fix:?}"), Self::Alias(what) => write!(f, "alias {what:?}"), } } } #[derive(Clone)] pub enum Expr<'s> { Value(Value<'s>), Ident(&'s str), Let { name: &'s str, rhs: Box>, }, If { cond: Box>, when: Box>, or: Box>, }, Semicolon(Box>, Box>), Call(&'s str, Vec>), } impl std::fmt::Debug for Expr<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Value(x) => write!(f, "{x:?}"), Self::Ident(x) => write!(f, "{x}"), Self::Let { name, rhs } => write!(f, "let {name} = {rhs:?}"), Self::If { cond, when, or } => { write!(f, "if {cond:?} {{ {when:?} }} else {{ {or:?} }}") } Self::Semicolon(arg0, arg1) => f.debug_list().entries([arg0, arg1]).finish(), Self::Call(arg, x) => f.debug_tuple("callu").field(arg).field(x).finish(), } } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Spanned { pub inner: T, pub span: Span, } impl Deref for Spanned { type Target = T; fn deref(&self) -> &Self::Target { &self.inner } } impl Spanned { pub fn map(self, f: impl FnOnce(T) -> U) -> Spanned { Spanned { inner: f(self.inner), span: self.span, } } pub fn dummy(inner: T) -> Spanned { Spanned { inner, span: SimpleSpan::new(0, 0), } } pub fn copys(&self, with: U) -> Spanned { Spanned { inner: with, span: self.span, } } } impl From<(T, Span)> for Spanned { fn from((inner, span): (T, Span)) -> Self { Self { inner, span } } } impl std::fmt::Display for Spanned { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.inner) } } #[derive(Clone)] pub enum Type<'s> { Tuple(Box<[Type<'s>]>), Path(&'s str), Unit, } impl std::fmt::Debug for Type<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Tuple(x) => write!( f, "{}", std::iter::once("(".to_string()) .chain(x.iter().map(|x| format!("{x:?}")).intersperse(", ".into()),) .chain([")".to_string()]) .reduce(|acc, x| acc + &x) .unwrap() ), Self::Path(x) => write!(f, "{x}"), Self::Unit => write!(f, "()"), } } }