rain_lang/parser/ast/
mod.rs

1/*!
2An abstract syntax tree for `rain` programs
3*/
4
5//TODO: consider using a non collision-resistant hashmap
6use std::fmt::{self, Debug, Display, Formatter};
7
8use crate::value::primitive::binary::{Natural, Integer};
9use crate::value::primitive::logical::{LogicalOp, Bool};
10
11/// A scope in a `rain` program
12#[derive(Clone, Eq, PartialEq)]
13pub struct Scope<'a> {
14    /// The definitions in this scope
15    pub definitions: Vec<Let<'a>>,
16    /// The value in this scope, if any
17    pub value: Option<Box<Expr<'a>>>
18}
19
20impl Debug for Scope<'_> {
21    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
22        <Self as Display>::fmt(self, fmt)
23    }
24}
25
26impl Display for Scope<'_> {
27    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
28        if self.definitions.len() == 0 {
29            return if let Some(value) = &self.value { write!(fmt, "{{ {} }}", value) }
30            else { write!(fmt, "{{}}")}
31        }
32        write!(fmt, "{{\n")?;
33        for definition in self.definitions.iter() {
34            write!(fmt, "{}\n", definition)?;
35        }
36        if let Some(value) = &self.value { write!(fmt, "{}\n", value)? }
37        write!(fmt, "}}")
38    }
39}
40
41/// A phi node
42#[derive(Clone, Eq, PartialEq)]
43pub struct Phi<'a>(pub Scope<'a>);
44
45impl Debug for Phi<'_> {
46    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
47        <Self as Display>::fmt(self, fmt)
48    }
49}
50
51impl Display for Phi<'_> {
52    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { write!(fmt, "#phi {}", self.0) }
53}
54
55
56/// A `rain` path, denoting a value in a namespace
57#[derive(Clone, Eq, PartialEq)]
58pub struct Path<'a> {
59    /// The base of this path, if any (TODO: this)
60    pub base: Option<()>,
61    /// The names in this path
62    pub names: Vec<&'a str>
63}
64
65impl Debug for Path<'_> {
66    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
67        <Self as Display>::fmt(self, fmt)
68    }
69}
70
71impl Display for Path<'_> {
72    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
73        let tail_names = if let Some(base) = self.base {
74            write!(fmt, "{:?}", base)?; // TODO: fixme
75            &self.names[..]
76        } else if self.names.len() > 0 {
77            write!(fmt, "{}", self.names[0])?;
78            &self.names[1..]
79        }
80        else {
81            // Invalid path. For now, do nothing. TODO: think about this
82            return Ok(())
83        };
84        for name in tail_names { write!(fmt, ".{}", name)?; }
85        Ok(())
86    }
87}
88
89impl<'a> Path<'a> {
90    /// Create a new path consisting of just an identifier
91    pub fn ident<T>(ident: T) -> Path<'a> where T: Into<&'a str> {
92        Path { base: None, names: vec![ident.into()] }
93    }
94}
95
96impl<'a> From<Vec<&'a str>> for Path<'a> {
97    fn from(names: Vec<&'a str>) -> Path<'a> { Path { names, base: None } }
98}
99
100/// An AST node for a `rain` expression
101#[derive(Clone, Eq, PartialEq)]
102pub enum Expr<'a> {
103    /// A path
104    Path(Path<'a>),
105    /// A scope
106    Scope(Scope<'a>),
107    /// An S-expression
108    Sexpr(Sexpr<'a>),
109    /// A lambda expression
110    Lambda(Lambda<'a>),
111    /// A pi type
112    Pi(Pi<'a>),
113    /// A phi node
114    Phi(Phi<'a>),
115    /// A gamma node
116    Gamma(Gamma<'a>),
117    /// A boolean constant
118    Bool(bool),
119    /// The boolean type
120    BoolTy(Bool),
121    /// A logical operation
122    LogicalOp(LogicalOp),
123    /// A natural number
124    Natural(Natural),
125    /// An integer
126    Integer(Integer)
127}
128
129impl<'a> Expr<'a> {
130    /// Create a new path consisting of just an identifier
131    pub fn ident<T>(ident: T) -> Expr<'a> where T: Into<&'a str> {
132        Expr::Path(Path::ident(ident))
133    }
134    /// Attempt to build an S-expression from this value, with the other value at the front.
135    /// For example, `5 + 5 = (+ 5 5)` can be written `let sum = 5`, `sum.push(5)`, `sum.push(+)`
136    pub fn push<T>(self, other: T) -> Expr<'a> where T: Into<Box<Expr<'a>>> {
137        match self {
138            Expr::Sexpr(mut s) => { s.push(other); Expr::Sexpr(s) }
139            atom => {
140                Expr::Sexpr(Sexpr { ops: vec![Box::new(atom), other.into()] })
141            },
142        }
143    }
144}
145
146impl Debug for Expr<'_> {
147    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
148        <Self as Display>::fmt(self, fmt)
149    }
150}
151
152impl Display for Expr<'_> {
153    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
154        match self {
155            Expr::Path(p) => std::fmt::Display::fmt(p, fmt),
156            Expr::Scope(s) => std::fmt::Display::fmt(s, fmt),
157            Expr::Sexpr(s) => std::fmt::Display::fmt(s, fmt),
158            Expr::Lambda(l) => std::fmt::Display::fmt(l, fmt),
159            Expr::Pi(p) => std::fmt::Display::fmt(p, fmt),
160            Expr::Phi(p) => std::fmt::Display::fmt(p, fmt),
161            Expr::Gamma(g) => std::fmt::Display::fmt(g, fmt),
162            Expr::Bool(b) => write!(fmt, "#{}", b),
163            Expr::BoolTy(b) => std::fmt::Display::fmt(b, fmt),
164            Expr::LogicalOp(l) => std::fmt::Display::fmt(l, fmt),
165            Expr::Natural(n) => std::fmt::Display::fmt(n, fmt),
166            Expr::Integer(z) => std::fmt::Display::fmt(z, fmt)
167        }
168    }
169}
170
171/// An AST node for an S-expression
172#[derive(Clone, Eq, PartialEq)]
173pub struct Sexpr<'a> {
174    /// The operands of this S-expression. Stored in *reverse* order, i.e. `f(5)` is represented as
175    /// the list `[5, f]`.
176    pub ops: Vec<Box<Expr<'a>>>
177}
178
179impl<'a> From<Vec<Box<Expr<'a>>>> for Sexpr<'a> {
180    fn from(ops: Vec<Box<Expr<'a>>>) -> Sexpr<'a> { Sexpr { ops } }
181}
182
183impl<'a> Sexpr<'a> {
184    /// Push an operand to this S-expression
185    pub fn push<T>(&mut self, op: T) where T: Into<Box<Expr<'a>>> {
186        self.ops.push(op.into())
187    }
188}
189
190impl Debug for Sexpr<'_> {
191    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
192        <Self as Display>::fmt(self, fmt)
193    }
194}
195
196impl Display for Sexpr<'_> {
197    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
198        write!(fmt, "(")?;
199        let mut first: bool = true;
200        for op in self.ops.iter().rev() {
201            write!(fmt, "{}{}", if first {""} else {" "}, op)?;
202            first = false;
203        }
204        write!(fmt, ")")
205    }
206}
207
208/// An AST-node for a lambda expression
209#[derive(Clone, Eq, PartialEq)]
210pub struct Lambda<'a>(pub Parametrized<'a>);
211
212impl Debug for Lambda<'_> {
213    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
214        <Self as Display>::fmt(self, fmt)
215    }
216}
217
218impl Display for Lambda<'_> {
219    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
220        write!(fmt, "#lambda {}", self.0)
221    }
222}
223
224/// An AST-node for a pi expression
225#[derive(Clone, Eq, PartialEq)]
226pub struct Pi<'a>(pub Parametrized<'a>);
227
228impl Debug for Pi<'_> {
229    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
230        <Self as Display>::fmt(self, fmt)
231    }
232}
233
234impl Display for Pi<'_> {
235    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
236        write!(fmt, "#pi {}", self.0)
237    }
238}
239
240/// A a parametrized expression
241#[derive(Clone, Eq, PartialEq)]
242pub struct Parametrized<'a> {
243    /// The arguments of this parametrized expression, along with their types
244    pub args: Vec<(Option<&'a str>, Expr<'a>)>,
245    /// The optional return type of this parametrized expression
246    pub ret_ty: Option<Box<Expr<'a>>>,
247    /// The result of this parametrized expression
248    pub result: Box<Expr<'a>>
249}
250
251impl Debug for Parametrized<'_> {
252    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
253        <Self as Display>::fmt(self, fmt)
254    }
255}
256
257impl Display for Parametrized<'_> {
258    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
259        write!(fmt, "|")?;
260        let mut first: bool = true;
261        for (arg, ty) in self.args.iter() {
262            let sep = if first {""} else {", "};
263            let arg = if let Some(arg) = arg { arg } else { "_" };
264            write!(fmt, "{}{} : {}", sep, arg, ty)?;
265            first = false;
266        }
267        write!(fmt, "| ")?;
268        if let Some(ty) = &self.ret_ty {
269            write!(fmt, "=> {} ", ty)?;
270        }
271        write!(fmt, "{}", self.result)
272    }
273}
274
275/// A simple assignment (i.e. a single variable with an optional type)
276#[derive(Clone, Eq, PartialEq)]
277pub struct SimpleAssignment<'a> {
278    /// The name of the variable being assigned to
279    pub name: &'a str,
280    /// The type constraint on the variable, if any
281    pub ty: Option<Expr<'a>>
282}
283
284impl Debug for SimpleAssignment<'_> {
285    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
286        <Self as Display>::fmt(self, fmt)
287    }
288}
289
290impl Display for SimpleAssignment<'_> {
291    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
292        write!(fmt, "{}", self.name)?;
293        if let Some(ty) = &self.ty { write!(fmt, " : {}", ty) } else { Ok(()) }
294    }
295}
296
297
298/// A pattern for assignment
299#[derive(Clone, Eq, PartialEq)]
300pub enum Pattern<'a> {
301    /// A simple assignment
302    Simple(SimpleAssignment<'a>)
303}
304
305impl Debug for Pattern<'_> {
306    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
307        <Self as Display>::fmt(self, fmt)
308    }
309}
310
311impl Display for Pattern<'_> {
312    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
313        match self {
314            Pattern::Simple(s) => write!(fmt, "{}", s)
315        }
316    }
317}
318
319/// A `let` statement, defining a set of variables
320#[derive(Clone, Eq, PartialEq)]
321pub struct Let<'a> {
322    /// The pattern being assigned to
323    pub pattern: Pattern<'a>,
324    /// The value being assigned
325    pub expr: Expr<'a>
326}
327
328impl Debug for Let<'_> {
329    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
330        <Self as Display>::fmt(self, fmt)
331    }
332}
333
334impl Display for Let<'_> {
335    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
336        write!(fmt, "let {} = {};", self.pattern, self.expr) //TODO: this
337    }
338}
339
340/// A `gamma` node, corresponding to a `match` statement
341#[derive(Clone, Eq, PartialEq)]
342pub struct Gamma<'a> {
343    /// The branches of this `gamma` node
344    pub branches: Vec<(Pattern<'a>, Expr<'a>)>
345}
346
347impl Debug for Gamma<'_> {
348    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
349        <Self as Display>::fmt(self, fmt)
350    }
351}
352
353impl Display for Gamma<'_> {
354    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
355        write!(fmt, "#match {{\n")?;
356        let mut first = true;
357        for (pattern, value) in self.branches.iter() {
358            write!(fmt, "{}{} => {}", if first { "" } else { ",\n" }, pattern, value)?;
359            first = false;
360        }
361        write!(fmt, "{}}}", if first { "" } else { "\n" })
362    }
363}
364
365#[cfg(test)]
366mod tests {
367    use super::*;
368
369    #[test]
370    fn expr_push_works_as_expected() {
371        assert_eq!(
372            Expr::ident("x").push(Expr::ident("f")),
373            Expr::Sexpr(vec![Expr::ident("x").into(), Expr::ident("f").into()].into())
374        );
375        assert_eq!(
376            Expr::ident("x").push(Expr::ident("y")).push(Expr::ident("f")),
377            Expr::Sexpr(vec![
378                Expr::ident("x").into(),
379                Expr::ident("y").into(),
380                Expr::ident("f").into()]
381            .into())
382        )
383    }
384}