kind_tree/untyped/
mod.rs

1//! This module describes an unsugared and untyped tree
2//! that is a IR
3
4use std::fmt::{Display, Error, Formatter};
5
6use fxhash::FxHashMap;
7use kind_span::Range;
8use linked_hash_map::LinkedHashMap;
9
10pub use crate::Operator;
11use crate::{
12    symbol::{Ident, QualifiedIdent},
13    Attributes,
14};
15
16/// Just a vector of expressions. It is called spine because
17/// it is usually in a form like (a b c d e) that can be interpret
18/// as ((((a b) c) d) e) that looks like a spine.
19pub type Spine = Vec<Box<Expr>>;
20
21#[derive(Clone, Debug, Hash, PartialEq, Eq)]
22pub enum ExprKind {
23    /// Name of a variable
24    Var {
25        name: Ident,
26    },
27    /// A anonymous function that receives one argument
28    Lambda {
29        param: Ident,
30        body: Box<Expr>,
31        erased: bool,
32    },
33    /// Application of a expression to a spine of expressions
34    App {
35        fun: Box<Expr>,
36        args: Vec<Box<Expr>>,
37    },
38    /// Application of a function
39    Fun {
40        name: QualifiedIdent,
41        args: Spine,
42    },
43    /// Application of a Construtor
44    Ctr {
45        name: QualifiedIdent,
46        args: Spine,
47    },
48    /// Declaration of a local variable
49    Let {
50        name: Ident,
51        val: Box<Expr>,
52        next: Box<Expr>,
53    },
54    /// 60 bit unsigned integer
55    U60 {
56        numb: u64,
57    },
58    /// 60 bit floating point number
59    F60 {
60        numb: u64,
61    },
62    /// Very special constructor :)
63    Str {
64        val: String,
65    },
66    /// Binary operation (e.g. 2 + 3)
67    Binary {
68        op: Operator,
69        left: Box<Expr>,
70        right: Box<Expr>,
71    },
72
73    Err,
74}
75
76#[derive(Clone, Debug, Hash, PartialEq, Eq)]
77pub struct Expr {
78    pub data: ExprKind,
79    pub range: Range,
80}
81
82impl Expr {
83    pub fn var(name: Ident) -> Box<Expr> {
84        Box::new(Expr {
85            range: name.range,
86            data: ExprKind::Var { name },
87        })
88    }
89
90    pub fn str(range: Range, val: String) -> Box<Expr> {
91        Box::new(Expr {
92            range,
93            data: ExprKind::Str { val },
94        })
95    }
96
97    pub fn lambda(range: Range, param: Ident, body: Box<Expr>, erased: bool) -> Box<Expr> {
98        Box::new(Expr {
99            range,
100            data: ExprKind::Lambda {
101                param,
102                body,
103                erased,
104            },
105        })
106    }
107
108    pub fn fun(range: Range, name: QualifiedIdent, args: Vec<Box<Expr>>) -> Box<Expr> {
109        Box::new(Expr {
110            range,
111            data: ExprKind::Fun { name, args },
112        })
113    }
114
115    pub fn app(range: Range, fun: Box<Expr>, args: Vec<Box<Expr>>) -> Box<Expr> {
116        Box::new(Expr {
117            range,
118            data: ExprKind::App { fun, args },
119        })
120    }
121
122    pub fn ctr(range: Range, name: QualifiedIdent, args: Vec<Box<Expr>>) -> Box<Expr> {
123        Box::new(Expr {
124            range,
125            data: ExprKind::Ctr { name, args },
126        })
127    }
128
129    pub fn let_(range: Range, name: Ident, val: Box<Expr>, next: Box<Expr>) -> Box<Expr> {
130        Box::new(Expr {
131            range,
132            data: ExprKind::Let { name, val, next },
133        })
134    }
135
136    pub fn u60(range: Range, numb: u64) -> Box<Expr> {
137        Box::new(Expr {
138            range,
139            data: ExprKind::U60 { numb },
140        })
141    }
142
143    pub fn f60(range: Range, numb: u64) -> Box<Expr> {
144        Box::new(Expr {
145            range,
146            data: ExprKind::F60 { numb },
147        })
148    }
149
150    pub fn binary(range: Range, op: Operator, left: Box<Expr>, right: Box<Expr>) -> Box<Expr> {
151        Box::new(Expr {
152            range,
153            data: ExprKind::Binary { op, left, right },
154        })
155    }
156
157    pub fn err(range: Range) -> Box<Expr> {
158        Box::new(Expr {
159            range,
160            data: ExprKind::Err,
161        })
162    }
163}
164
165/// An argument is a 'binding' of a name to a type
166/// it has some other options like
167/// eras: that express the erasure of this type when
168/// compiled.
169/// hide: that express a implicit argument (that will
170/// be discovered through unification).
171#[derive(Clone, Debug)]
172pub struct Argument {
173    pub hidden: bool,
174    pub erased: bool,
175    pub name: Ident,
176    pub typ: Box<Expr>,
177    pub range: Range,
178}
179
180/// A rule is a equation that in the left-hand-side
181/// contains a list of patterns @pats@ and on the
182/// right hand side a value.
183#[derive(Clone, Debug)]
184pub struct Rule {
185    pub name: QualifiedIdent,
186    pub pats: Vec<Box<Expr>>,
187    pub body: Box<Expr>,
188    pub range: Range,
189}
190
191/// An entry describes a function that is typed
192/// and has rules. The type of the function
193/// consists of the arguments @args@ and the
194/// return type @typ@.
195#[derive(Clone, Debug)]
196pub struct Entry {
197    pub name: QualifiedIdent,
198    pub args: Vec<(String, Range, bool)>,
199    pub rules: Vec<Rule>,
200    pub attrs: Attributes,
201    pub range: Range,
202}
203
204/// A book is a collection of desugared entries.
205#[derive(Clone, Debug, Default)]
206pub struct Book {
207    pub entrs: LinkedHashMap<String, Box<Entry>>,
208    pub names: FxHashMap<String, usize>,
209}
210
211impl Expr {
212    pub fn new_var(name: Ident) -> Expr {
213        Expr {
214            range: name.range,
215            data: ExprKind::Var { name },
216        }
217    }
218}
219
220impl Display for Expr {
221    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
222        use ExprKind::*;
223        match &self.data {
224            Err => write!(f, "ERR"),
225            Str { val } => write!(f, "\"{}\"", val),
226            U60 { numb } => write!(f, "{}", numb),
227            F60 { numb: _ } => todo!(),
228            Var { name } => write!(f, "{}", name),
229            Lambda {
230                param,
231                body,
232                erased: false,
233            } => write!(f, "({} => {})", param, body),
234            Lambda {
235                param,
236                body,
237                erased: true,
238            } => write!(f, "(~{} => {})", param, body),
239            App { fun, args } => write!(
240                f,
241                "({}{})",
242                fun,
243                args.iter().map(|x| format!(" {}", x)).collect::<String>()
244            ),
245            Fun { name, args } | Ctr { name, args } => {
246                if args.is_empty() {
247                    write!(f, "{}", name)
248                } else {
249                    write!(
250                        f,
251                        "({}{})",
252                        name,
253                        args.iter().map(|x| format!(" {}", x)).collect::<String>()
254                    )
255                }
256            }
257            Let { name, val, next } => write!(f, "(let {} = {}; {})", name, val, next),
258            Binary { op, left, right } => write!(f, "({} {} {})", op, left, right),
259        }
260    }
261}
262
263impl Display for Book {
264    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
265        for entr in self.entrs.values() {
266            if !entr.rules.is_empty() {
267                writeln!(f, "{}", entr)?;
268            } else {
269                writeln!(f, "ctr {}", entr.name)?;
270            }
271        }
272        Ok(())
273    }
274}
275
276impl Display for Argument {
277    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
278        let (open, close) = match (self.erased, self.hidden) {
279            (false, false) => ("(", ")"),
280            (false, true) => ("+<", ">"),
281            (true, false) => ("-(", ")"),
282            (true, true) => ("<", ">"),
283        };
284        write!(f, "{}{}: {}{}", open, self.name, self.typ, close)
285    }
286}
287
288impl Display for Entry {
289    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
290        for rule in &self.rules {
291            write!(f, "\n{}", rule)?
292        }
293
294        Ok(())
295    }
296}
297
298impl Display for Rule {
299    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
300        write!(f, "{}", self.name)?;
301        for pat in &self.pats {
302            write!(f, " {}", pat)?;
303        }
304        write!(f, " = {}", self.body)
305    }
306}
307
308impl Argument {
309    pub fn to_irrelevant(&self) -> Argument {
310        Argument {
311            hidden: true,
312            erased: true,
313            name: self.name.clone(),
314            typ: self.typ.clone(),
315            range: self.range,
316        }
317    }
318
319    pub fn from_field(name: &Ident, typ: Box<Expr>, range: Range) -> Argument {
320        Argument {
321            hidden: false,
322            erased: false,
323            name: name.clone(),
324            typ,
325            range,
326        }
327    }
328}