1use std::fmt::{Display, Error, Formatter};
5
6use fxhash::FxHashMap;
7use kind_span::Range;
8use linked_hash_map::LinkedHashMap;
9
10pub use crate::Operator;
11
12use crate::{
13 symbol::{Ident, QualifiedIdent},
14 telescope::Telescope,
15 Attributes,
16};
17
18pub type Spine = Vec<Box<Expr>>;
22
23#[derive(Clone, Debug, Hash, PartialEq, Eq)]
24pub struct AppBinding {
25 pub data: Box<Expr>,
26 pub erased: bool,
27}
28
29#[derive(Clone, Debug, Hash, PartialEq, Eq)]
30pub enum ExprKind {
31 Var { name: Ident },
33 All {
35 param: Ident,
36 typ: Box<Expr>,
37 body: Box<Expr>,
38 erased: bool,
39 },
40 Lambda {
42 param: Ident,
43 body: Box<Expr>,
44 erased: bool,
45 },
46 App {
48 fun: Box<Expr>,
49 args: Vec<AppBinding>,
50 },
51 Fun { name: QualifiedIdent, args: Spine },
53 Ctr { name: QualifiedIdent, args: Spine },
55 Let {
57 name: Ident,
58 val: Box<Expr>,
59 next: Box<Expr>,
60 },
61 Ann { expr: Box<Expr>, typ: Box<Expr> },
63 Sub {
65 name: Ident,
66 indx: usize,
67 redx: usize,
68 expr: Box<Expr>,
69 },
70 Typ,
72 NumTypeU60,
74 NumTypeF60,
76 NumU60 { numb: u64 },
78 NumF60 { numb: u64 },
80 Str { val: String },
82 Binary {
84 op: Operator,
85 left: Box<Expr>,
86 right: Box<Expr>,
87 },
88 Hole { num: u64 },
90 Hlp(Ident),
92 Err,
96}
97
98#[derive(Clone, Debug, Hash, PartialEq, Eq)]
99pub struct Expr {
100 pub data: ExprKind,
101 pub range: Range,
102}
103
104impl Expr {
105 pub fn var(name: Ident) -> Box<Expr> {
106 Box::new(Expr {
107 range: name.range,
108 data: ExprKind::Var { name },
109 })
110 }
111
112 pub fn all(
113 range: Range,
114 param: Ident,
115 typ: Box<Expr>,
116 body: Box<Expr>,
117 erased: bool,
118 ) -> Box<Expr> {
119 Box::new(Expr {
120 range,
121 data: ExprKind::All {
122 param,
123 typ,
124 body,
125 erased,
126 },
127 })
128 }
129
130 pub fn sub(range: Range, name: Ident, indx: usize, redx: usize, expr: Box<Expr>) -> Box<Expr> {
131 Box::new(Expr {
132 range,
133 data: ExprKind::Sub {
134 name,
135 indx,
136 redx,
137 expr,
138 },
139 })
140 }
141
142 pub fn lambda(range: Range, param: Ident, body: Box<Expr>, erased: bool) -> Box<Expr> {
143 Box::new(Expr {
144 range,
145 data: ExprKind::Lambda {
146 param,
147 body,
148 erased,
149 },
150 })
151 }
152
153 pub fn identity_lambda(ident: Ident) -> Box<Expr> {
154 Box::new(Expr {
155 range: ident.range,
156 data: ExprKind::Lambda {
157 param: ident.clone(),
158 body: Self::var(ident),
159 erased: false,
160 },
161 })
162 }
163
164 pub fn unfold_lambda(irrelev: &[bool], idents: &[Ident], body: Box<Expr>) -> Box<Expr> {
165 idents
166 .iter()
167 .rev()
168 .zip(irrelev)
169 .fold(body, |body, (ident, irrelev)| {
170 Expr::lambda(ident.range, ident.clone(), body, *irrelev)
171 })
172 }
173
174 pub fn unfold_all(
175 irrelev: &[bool],
176 idents: &[(Ident, Box<Expr>)],
177 body: Box<Expr>,
178 ) -> Box<Expr> {
179 idents
180 .iter()
181 .rev()
182 .zip(irrelev)
183 .fold(body, |body, ((ident, typ), irrelev)| {
184 Expr::all(ident.range, ident.clone(), typ.clone(), body, *irrelev)
185 })
186 }
187
188 pub fn app(range: Range, fun: Box<Expr>, args: Vec<AppBinding>) -> Box<Expr> {
189 Box::new(Expr {
190 range,
191 data: ExprKind::App { fun, args },
192 })
193 }
194
195 pub fn fun(range: Range, name: QualifiedIdent, args: Vec<Box<Expr>>) -> Box<Expr> {
196 Box::new(Expr {
197 range,
198 data: ExprKind::Fun { name, args },
199 })
200 }
201
202 pub fn ctr(range: Range, name: QualifiedIdent, args: Vec<Box<Expr>>) -> Box<Expr> {
203 Box::new(Expr {
204 range,
205 data: ExprKind::Ctr { name, args },
206 })
207 }
208
209 pub fn let_(range: Range, name: Ident, val: Box<Expr>, next: Box<Expr>) -> Box<Expr> {
210 Box::new(Expr {
211 range,
212 data: ExprKind::Let { name, val, next },
213 })
214 }
215
216 pub fn ann(range: Range, expr: Box<Expr>, typ: Box<Expr>) -> Box<Expr> {
217 Box::new(Expr {
218 range,
219 data: ExprKind::Ann { expr, typ },
220 })
221 }
222
223 pub fn typ(range: Range) -> Box<Expr> {
224 Box::new(Expr {
225 range,
226 data: ExprKind::Typ,
227 })
228 }
229
230 pub fn type_u60(range: Range) -> Box<Expr> {
231 Box::new(Expr {
232 range,
233 data: ExprKind::NumTypeU60,
234 })
235 }
236
237 pub fn type_f60(range: Range) -> Box<Expr> {
238 Box::new(Expr {
239 range,
240 data: ExprKind::NumTypeF60,
241 })
242 }
243
244 pub fn num_u60(range: Range, numb: u64) -> Box<Expr> {
245 Box::new(Expr {
246 range,
247 data: ExprKind::NumU60 { numb },
248 })
249 }
250
251 pub fn num_u120(range: Range, numb: u128) -> Box<Expr> {
252 let name = QualifiedIdent::new_static("Data.U120.new", None, range);
253 let lo = Expr::num_u60(range, (numb & 0xFFFFFFFFFFFFFFF) as u64);
254 let hi = Expr::num_u60(range, (numb >> 60) as u64);
255 Box::new(Expr {
256 range,
257 data: ExprKind::Ctr {
258 name,
259 args: vec![hi, lo],
260 },
261 })
262 }
263
264 pub fn num_f60(range: Range, numb: u64) -> Box<Expr> {
265 Box::new(Expr {
266 range,
267 data: ExprKind::NumF60 { numb },
268 })
269 }
270
271 pub fn binary(range: Range, op: Operator, left: Box<Expr>, right: Box<Expr>) -> Box<Expr> {
272 Box::new(Expr {
273 range,
274 data: ExprKind::Binary { op, left, right },
275 })
276 }
277
278 pub fn hole(range: Range, num: u64) -> Box<Expr> {
279 Box::new(Expr {
280 range,
281 data: ExprKind::Hole { num },
282 })
283 }
284
285 pub fn str(range: Range, val: String) -> Box<Expr> {
286 Box::new(Expr {
287 range,
288 data: ExprKind::Str { val },
289 })
290 }
291
292 pub fn hlp(range: Range, hlp: Ident) -> Box<Expr> {
293 Box::new(Expr {
294 range,
295 data: ExprKind::Hlp(hlp),
296 })
297 }
298
299 pub fn err(range: Range) -> Box<Expr> {
300 Box::new(Expr {
301 data: ExprKind::Err,
302 range,
303 })
304 }
305}
306
307#[derive(Clone, Debug)]
314pub struct Argument {
315 pub hidden: bool,
316 pub erased: bool,
317 pub name: Ident,
318 pub typ: Box<Expr>,
319 pub range: Range,
320}
321
322#[derive(Clone, Debug)]
326pub struct Rule {
327 pub name: QualifiedIdent,
328 pub pats: Vec<Box<Expr>>,
329 pub body: Box<Expr>,
330 pub range: Range,
331}
332
333#[derive(Clone, Debug)]
338pub struct Entry {
339 pub name: QualifiedIdent,
340 pub args: Vec<Argument>,
341 pub typ: Box<Expr>,
342 pub rules: Vec<Rule>,
343 pub attrs: Attributes,
344 pub range: Range,
345}
346
347#[derive(Clone, Debug)]
349pub struct Family {
350 pub name: QualifiedIdent,
351 pub parameters: Telescope<Argument>,
352 pub constructors: Vec<QualifiedIdent>,
353}
354
355#[derive(Clone, Debug, Default)]
357pub struct Book {
358 pub entrs: LinkedHashMap<String, Box<Entry>>,
359 pub names: FxHashMap<String, usize>,
360 pub families: FxHashMap<String, Family>,
361 pub holes: u64,
362}
363
364impl Expr {
365 pub fn new_var(name: Ident) -> Expr {
366 Expr {
367 range: name.range,
368 data: ExprKind::Var { name },
369 }
370 }
371
372 pub fn traverse_pi_types(&self) -> String {
373 match &self.data {
374 ExprKind::All {
375 param,
376 typ,
377 body,
378 erased,
379 } => {
380 let tilde = if *erased { "~" } else { "" };
381 if param.to_string().starts_with('_') {
382 format!("{}{} -> {}", tilde, typ, body.traverse_pi_types())
383 } else {
384 let body = body.traverse_pi_types();
385 format!("{}({} : {}) -> {}", tilde, param, typ, body)
386 }
387 }
388 _ => format!("{}", self),
389 }
390 }
391}
392
393impl Display for AppBinding {
394 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
395 if self.erased {
396 write!(f, "~({})", self.data)
397 } else {
398 write!(f, "{}", self.data)
399 }
400 }
401}
402
403pub fn try_desugar_to_nat(name: &QualifiedIdent, spine: &[Box<Expr>], acc: u128) -> Option<u128> {
404 match (name.to_str(), spine) {
405 ("Data.Nat.zero", []) => Some(acc),
406 ("Data.Nat.succ", [spine]) => match &spine.data {
407 ExprKind::Ctr { name, args } => try_desugar_to_nat(name, args, acc + 1),
408 _ => None,
409 },
410 _ => None,
411 }
412}
413
414impl Display for Expr {
415 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
416 use ExprKind::*;
417 match &self.data {
418 Typ => write!(f, "Type"),
419 NumTypeU60 => write!(f, "Data.U60"),
420 NumTypeF60 => write!(f, "Data.F60"),
421 Str { val } => write!(f, "\"{}\"", val),
422 NumU60 { numb } => write!(f, "{}", numb),
423 NumF60 { numb: _ } => todo!(),
424 All { .. } => write!(f, "({})", self.traverse_pi_types()),
425 Var { name } => write!(f, "{}", name),
426 Lambda {
427 param,
428 body,
429 erased: false,
430 } => write!(f, "({} => {})", param, body),
431 Lambda {
432 param,
433 body,
434 erased: true,
435 } => write!(f, "(~{} => {})", param, body),
436 Sub {
437 name, redx, expr, ..
438 } => write!(f, "(## {}/{} {})", name, redx, expr),
439 App { fun, args } => write!(
440 f,
441 "({}{})",
442 fun,
443 args.iter().map(|x| format!(" {}", x)).collect::<String>()
444 ),
445 Fun { name, args } | Ctr { name, args } => {
446 if let Some(res) = try_desugar_to_nat(name, args, 0) {
447 write!(f, "{res}n")
448 } else if args.is_empty() {
449 write!(f, "{}", name)
450 } else {
451 write!(
452 f,
453 "({}{})",
454 name,
455 args.iter().map(|x| format!(" {}", x)).collect::<String>()
456 )
457 }
458 }
459 Let { name, val, next } => write!(f, "(let {} = {}; {})", name, val, next),
460 Ann { expr, typ } => write!(f, "({} :: {})", expr, typ),
461 Binary { op, left, right } => write!(f, "({} {} {})", op, left, right),
462 Hole { .. } => write!(f, "_"),
463 Hlp(name) => write!(f, "?{}", name),
464 Err => write!(f, "ERR"),
465 }
466 }
467}
468
469impl Display for Book {
470 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
471 for entr in self.entrs.values() {
472 writeln!(f, "{}\n", entr)?;
473 }
474 Ok(())
475 }
476}
477
478impl Display for Argument {
479 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
480 let (open, close) = match (self.erased, self.hidden) {
481 (false, false) => ("(", ")"),
482 (false, true) => ("+<", ">"),
483 (true, false) => ("-(", ")"),
484 (true, true) => ("<", ">"),
485 };
486 write!(f, "{}{}: {}{}", open, self.name, self.typ, close)
487 }
488}
489
490impl Display for Entry {
491 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
492 write!(f, "{}", self.name.clone())?;
493
494 for arg in &self.args {
495 write!(f, " {}", arg)?;
496 }
497
498 write!(f, " : {}", &self.typ)?;
499
500 for rule in &self.rules {
501 write!(f, "\n{}", rule)?
502 }
503
504 Ok(())
505 }
506}
507
508impl Display for Rule {
509 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
510 write!(f, "{}", self.name)?;
511 for pat in &self.pats {
512 write!(f, " {}", pat)?;
513 }
514 write!(f, " = {}", self.body)
515 }
516}
517
518impl Argument {
519 pub fn to_irrelevant(&self) -> Argument {
520 Argument {
521 hidden: true,
522 erased: true,
523 name: self.name.clone(),
524 typ: self.typ.clone(),
525 range: self.range,
526 }
527 }
528
529 pub fn from_field(name: &Ident, typ: Box<Expr>, range: Range) -> Argument {
530 Argument {
531 hidden: false,
532 erased: false,
533 name: name.clone(),
534 typ,
535 range,
536 }
537 }
538}