1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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<usize>;
pub type Error<'s> = Rich<'s, Token<'s>, Span>;
pub type Input<'s> = SpannedInput<Token<'s>, SimpleSpan, Stream<crate::lexer::Lexer<'s>>>;

pub enum Ast<'s> {
    Module(Vec<Expr<'s>>),
}

#[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)]
pub enum Expr<'s> {
    NoOp,
    Value(Value<'s>),
    Ident(&'s str),
    Let {
        name: &'s str,
        rhs: Box<Expr<'s>>,
    },
    If {
        then: Box<Expr<'s>>,
        or: Box<Expr<'s>>,
    },
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Spanned<T> {
    pub inner: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<T> Spanned<T> {
    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
        Spanned {
            inner: f(self.inner),
            span: self.span,
        }
    }

    pub fn dummy(inner: T) -> Spanned<T> {
        Spanned {
            inner,
            span: SimpleSpan::new(0, 0),
        }
    }

    pub fn copys<U>(&self, with: U) -> Spanned<U> {
        Spanned {
            inner: with,
            span: self.span,
        }
    }
}

impl<T> From<(T, Span)> for Spanned<T> {
    fn from((inner, span): (T, Span)) -> Self {
        Self { inner, span }
    }
}

impl<T: std::fmt::Display> std::fmt::Display for Spanned<T> {
    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, "()"),
        }
    }
}