1pub use crate::lexer::Pos;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
21pub struct Span {
22 pub start: usize,
23 pub end: usize,
24}
25
26impl Span {
27 pub const fn new(start: usize, end: usize) -> Self {
28 Self { start, end }
29 }
30
31 pub const fn is_empty(&self) -> bool {
32 self.start >= self.end
33 }
34
35 pub const fn contains(&self, other: &Self) -> bool {
37 self.start <= other.start && other.end <= self.end
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum LitKind {
43 Int,
44 Decimal,
45 Text,
46 Char,
47}
48
49#[derive(Debug, Clone)]
50pub struct FieldAssign {
51 pub name: String,
52 pub value: Option<Expr>,
55 pub pos: Pos,
56 pub span: Span,
57}
58
59#[derive(Debug, Clone)]
60pub struct Alt {
61 pub pat: Pat,
62 pub body: Expr,
63 pub pos: Pos,
64 pub span: Span,
65}
66
67#[derive(Debug, Clone)]
68pub struct Binding {
69 pub pat: Pat,
71 pub params: Vec<Pat>,
73 pub expr: Expr,
74 pub pos: Pos,
75 pub span: Span,
76}
77
78#[derive(Debug, Clone)]
79pub enum Pat {
80 Var {
81 name: String,
82 pos: Pos,
83 span: Span,
84 },
85 Wild {
86 pos: Pos,
87 span: Span,
88 },
89 Con {
90 qualifier: Option<String>,
91 name: String,
92 args: Vec<Self>,
93 pos: Pos,
94 span: Span,
95 },
96 Tuple {
97 items: Vec<Self>,
98 pos: Pos,
99 span: Span,
100 },
101 List {
102 items: Vec<Self>,
103 pos: Pos,
104 span: Span,
105 },
106 Lit {
107 kind: LitKind,
108 text: String,
109 pos: Pos,
110 span: Span,
111 },
112 As {
114 name: String,
115 pat: Box<Self>,
116 pos: Pos,
117 span: Span,
118 },
119 Other {
121 raw: String,
122 pos: Pos,
123 span: Span,
124 },
125}
126
127#[derive(Debug, Clone)]
128pub enum Expr {
129 Var {
131 qualifier: Option<String>,
132 name: String,
133 pos: Pos,
134 span: Span,
135 },
136 Con {
138 qualifier: Option<String>,
139 name: String,
140 pos: Pos,
141 span: Span,
142 },
143 Lit {
144 kind: LitKind,
145 text: String,
146 pos: Pos,
147 span: Span,
148 },
149 App {
151 func: Box<Self>,
152 args: Vec<Self>,
153 pos: Pos,
154 span: Span,
155 },
156 BinOp {
158 op: String,
159 lhs: Box<Self>,
160 rhs: Box<Self>,
161 pos: Pos,
162 span: Span,
163 },
164 Neg {
166 expr: Box<Self>,
167 pos: Pos,
168 span: Span,
169 },
170 Lambda {
171 params: Vec<Pat>,
172 body: Box<Self>,
173 pos: Pos,
174 span: Span,
175 },
176 If {
177 cond: Box<Self>,
178 then_branch: Box<Self>,
179 else_branch: Box<Self>,
180 pos: Pos,
181 span: Span,
182 },
183 Case {
184 scrutinee: Box<Self>,
185 alts: Vec<Alt>,
186 pos: Pos,
187 span: Span,
188 },
189 Do {
190 stmts: Vec<DoStmt>,
191 pos: Pos,
192 span: Span,
193 },
194 LetIn {
195 bindings: Vec<Binding>,
196 body: Box<Self>,
197 pos: Pos,
198 span: Span,
199 },
200 Record {
203 base: Box<Self>,
204 fields: Vec<FieldAssign>,
205 pos: Pos,
206 span: Span,
207 },
208 Tuple {
209 items: Vec<Self>,
210 pos: Pos,
211 span: Span,
212 },
213 List {
214 items: Vec<Self>,
215 pos: Pos,
216 span: Span,
217 },
218 Try {
220 body: Box<Self>,
221 handlers: Vec<Alt>,
222 pos: Pos,
223 span: Span,
224 },
225 Section {
227 op: String,
228 operand: Option<Box<Self>>,
229 left: bool,
230 pos: Pos,
231 span: Span,
232 },
233 Error { raw: String, pos: Pos, span: Span },
236}
237
238#[derive(Debug, Clone)]
239pub enum DoStmt {
240 Bind {
242 pat: Pat,
243 expr: Expr,
244 pos: Pos,
245 span: Span,
246 },
247 Let {
249 bindings: Vec<Binding>,
250 pos: Pos,
251 span: Span,
252 },
253 Expr { expr: Expr, pos: Pos, span: Span },
255}
256
257#[derive(Debug, Clone)]
265pub enum Type {
266 Con {
268 qualifier: Option<String>,
269 name: String,
270 span: Span,
271 },
272 App(Box<Self>, Vec<Self>, Span),
277 List(Box<Self>, Span),
279 Tuple(Vec<Self>, Span),
281 Fun(Box<Self>, Box<Self>, Span),
283 Var(String, Span),
285 Unit(Span),
287 Constrained(Box<Self>, Span),
290}
291
292impl Type {
293 pub const fn span(&self) -> Span {
294 match self {
295 Self::Con { span, .. }
296 | Self::App(_, _, span)
297 | Self::List(_, span)
298 | Self::Tuple(_, span)
299 | Self::Fun(_, _, span)
300 | Self::Var(_, span)
301 | Self::Unit(span)
302 | Self::Constrained(_, span) => *span,
303 }
304 }
305
306 pub(crate) const fn with_span(mut self, span: Span) -> Self {
307 match &mut self {
308 Self::Con { span: s, .. }
309 | Self::App(_, _, s)
310 | Self::List(_, s)
311 | Self::Tuple(_, s)
312 | Self::Fun(_, _, s)
313 | Self::Var(_, s)
314 | Self::Unit(s)
315 | Self::Constrained(_, s) => *s = span,
316 }
317 self
318 }
319}
320
321impl PartialEq for Type {
322 fn eq(&self, other: &Self) -> bool {
323 match (self, other) {
324 (
325 Self::Con {
326 qualifier: aq,
327 name: an,
328 ..
329 },
330 Self::Con {
331 qualifier: bq,
332 name: bn,
333 ..
334 },
335 ) => aq == bq && an == bn,
336 (Self::App(ah, aa, _), Self::App(bh, ba, _)) => ah == bh && aa == ba,
337 (Self::List(a, _), Self::List(b, _))
338 | (Self::Constrained(a, _), Self::Constrained(b, _)) => a == b,
339 (Self::Tuple(a, _), Self::Tuple(b, _)) => a == b,
340 (Self::Fun(al, ar, _), Self::Fun(bl, br, _)) => al == bl && ar == br,
341 (Self::Var(a, _), Self::Var(b, _)) => a == b,
342 (Self::Unit(_), Self::Unit(_)) => true,
343 _ => false,
344 }
345 }
346}
347
348#[derive(Debug, Clone)]
349pub struct FieldDecl {
350 pub name: String,
351 pub ty: Option<Type>,
354 pub pos: Pos,
355 pub span: Span,
356}
357
358#[derive(Debug, Clone, Copy, PartialEq, Eq)]
359pub enum Consuming {
360 Consuming,
361 NonConsuming,
362 PreConsuming,
363 PostConsuming,
364}
365
366#[derive(Debug, Clone)]
367pub struct ChoiceDecl {
368 pub name: String,
369 pub consuming: Consuming,
370 pub return_ty: Option<Type>,
373 pub params: Vec<FieldDecl>,
374 pub controllers: Vec<Expr>,
376 pub observers: Vec<Expr>,
378 pub body: Option<Expr>,
379 pub pos: Pos,
380 pub span: Span,
381}
382
383#[derive(Debug, Clone)]
384pub enum TemplateBodyDecl {
385 Signatory {
386 parties: Vec<Expr>,
387 pos: Pos,
388 span: Span,
389 },
390 Observer {
391 parties: Vec<Expr>,
392 pos: Pos,
393 span: Span,
394 },
395 Ensure {
396 expr: Expr,
397 pos: Pos,
398 span: Span,
399 },
400 Key {
401 expr: Expr,
402 ty: Option<Type>,
404 pos: Pos,
405 span: Span,
406 },
407 Maintainer {
408 expr: Expr,
409 pos: Pos,
410 span: Span,
411 },
412 Choice(ChoiceDecl),
413 InterfaceInstance(InterfaceInstanceDecl),
414 Other {
416 raw: String,
417 pos: Pos,
418 span: Span,
419 },
420}
421
422#[derive(Debug, Clone)]
423pub struct InterfaceInstanceDecl {
424 pub interface_name: String,
426 pub for_template: String,
429 pub methods: Vec<Binding>,
431 pub pos: Pos,
432 pub span: Span,
433}
434
435#[derive(Debug, Clone)]
436pub struct TemplateDecl {
437 pub name: String,
438 pub fields: Vec<FieldDecl>,
439 pub body: Vec<TemplateBodyDecl>,
440 pub pos: Pos,
441 pub span: Span,
442}
443
444#[derive(Debug, Clone)]
445pub struct InterfaceDecl {
446 pub name: String,
447 pub requires: Vec<String>,
449 pub viewtype: Option<String>,
450 pub methods: Vec<FieldDecl>,
452 pub choices: Vec<ChoiceDecl>,
453 pub pos: Pos,
454 pub span: Span,
455}
456
457#[derive(Debug, Clone)]
458pub struct Equation {
459 pub params: Vec<Pat>,
460 pub body: Expr,
461 pub guards: Vec<(Expr, Expr)>,
464 pub where_bindings: Vec<Binding>,
466 pub pos: Pos,
467 pub span: Span,
468}
469
470#[derive(Debug, Clone)]
471pub struct FunctionDecl {
472 pub name: String,
473 pub ty: Option<Type>,
474 pub equations: Vec<Equation>,
475 pub pos: Pos,
476 pub span: Span,
480 pub sig_span: Option<Span>,
482}
483
484#[derive(Debug, Clone)]
485pub struct ImportDecl {
486 pub module_name: String,
487 pub qualified: bool,
488 pub alias: Option<String>,
489 pub pos: Pos,
490 pub span: Span,
491}
492
493#[derive(Debug, Clone)]
494pub enum Decl {
495 Template(TemplateDecl),
496 Interface(InterfaceDecl),
497 Function(FunctionDecl),
498 TypeDef {
500 keyword: String,
501 name: String,
502 pos: Pos,
503 span: Span,
504 },
505 Unknown {
507 raw: String,
508 pos: Pos,
509 span: Span,
510 },
511}
512
513#[derive(Debug, Clone)]
514pub struct Module {
515 pub name: String,
516 pub pos: Pos,
517 pub span: Span,
519 pub header: Span,
523 pub imports: Vec<ImportDecl>,
524 pub decls: Vec<Decl>,
525}
526
527#[derive(Debug, Clone, Copy, PartialEq, Eq)]
533pub enum DiagnosticCategory {
534 SkippedDecl,
536 Malformed,
539 UnsupportedSyntax,
542 RecursionLimit,
545 Lex,
547}
548
549impl DiagnosticCategory {
550 pub const fn as_str(self) -> &'static str {
552 match self {
553 Self::SkippedDecl => "skipped-declaration",
554 Self::Malformed => "malformed",
555 Self::UnsupportedSyntax => "unsupported-syntax",
556 Self::RecursionLimit => "recursion-limit",
557 Self::Lex => "lexical-error",
558 }
559 }
560}
561
562#[derive(Debug, Clone)]
564pub struct ParseDiagnostic {
565 pub message: String,
566 pub pos: Pos,
567 pub span: Span,
571 pub category: DiagnosticCategory,
572}
573
574impl Expr {
575 pub const fn pos(&self) -> Pos {
576 match self {
577 Self::Var { pos, .. }
578 | Self::Con { pos, .. }
579 | Self::Lit { pos, .. }
580 | Self::App { pos, .. }
581 | Self::BinOp { pos, .. }
582 | Self::Neg { pos, .. }
583 | Self::Lambda { pos, .. }
584 | Self::If { pos, .. }
585 | Self::Case { pos, .. }
586 | Self::Do { pos, .. }
587 | Self::LetIn { pos, .. }
588 | Self::Record { pos, .. }
589 | Self::Tuple { pos, .. }
590 | Self::List { pos, .. }
591 | Self::Try { pos, .. }
592 | Self::Section { pos, .. }
593 | Self::Error { pos, .. } => *pos,
594 }
595 }
596
597 pub const fn span(&self) -> Span {
599 match self {
600 Self::Var { span, .. }
601 | Self::Con { span, .. }
602 | Self::Lit { span, .. }
603 | Self::App { span, .. }
604 | Self::BinOp { span, .. }
605 | Self::Neg { span, .. }
606 | Self::Lambda { span, .. }
607 | Self::If { span, .. }
608 | Self::Case { span, .. }
609 | Self::Do { span, .. }
610 | Self::LetIn { span, .. }
611 | Self::Record { span, .. }
612 | Self::Tuple { span, .. }
613 | Self::List { span, .. }
614 | Self::Try { span, .. }
615 | Self::Section { span, .. }
616 | Self::Error { span, .. } => *span,
617 }
618 }
619
620 pub fn render(&self) -> String {
630 match self {
631 Self::Var {
632 qualifier, name, ..
633 }
634 | Self::Con {
635 qualifier, name, ..
636 } => qualifier
637 .as_ref()
638 .map_or_else(|| name.clone(), |q| format!("{q}.{name}")),
639 Self::Lit { kind, text, .. } => match kind {
640 LitKind::Text => format!("{text:?}"),
641 LitKind::Char => format!("'{text}'"),
642 _ => text.clone(),
643 },
644 Self::App { func, args, .. } => {
645 let mut s = func.render_atomic();
646 for a in args {
647 s.push(' ');
648 s.push_str(&a.render_atomic());
649 }
650 s
651 }
652 Self::BinOp { op, lhs, rhs, .. } => {
653 if op == "." {
654 format!("{}.{}", lhs.render_atomic(), rhs.render_atomic())
656 } else {
657 format!("{} {} {}", lhs.render_atomic(), op, rhs.render_atomic())
658 }
659 }
660 Self::Neg { expr, .. } => format!("-{}", expr.render_atomic()),
661 Self::Lambda { params, body, .. } => {
662 let ps: Vec<String> = params.iter().map(|p| p.render()).collect();
663 format!("\\{} -> {}", ps.join(" "), body.render())
664 }
665 Self::If {
666 cond,
667 then_branch,
668 else_branch,
669 ..
670 } => format!(
671 "if {} then {} else {}",
672 cond.render(),
673 then_branch.render(),
674 else_branch.render()
675 ),
676 Self::Case {
677 scrutinee, alts, ..
678 } => {
679 let arms: Vec<String> = alts
680 .iter()
681 .map(|a| format!("{} -> {}", a.pat.render(), a.body.render()))
682 .collect();
683 format!("case {} of {}", scrutinee.render(), arms.join("; "))
684 }
685 Self::Do { stmts, .. } => {
686 let body: Vec<String> = stmts.iter().map(render_do_stmt).collect();
687 format!("do {}", body.join("; "))
688 }
689 Self::LetIn { bindings, body, .. } => {
690 let bs: Vec<String> = bindings.iter().map(render_binding).collect();
691 format!("let {} in {}", bs.join("; "), body.render())
692 }
693 Self::Record { base, fields, .. } => {
694 let fs: Vec<String> = fields
695 .iter()
696 .map(|f| {
697 f.value.as_ref().map_or_else(
698 || f.name.clone(),
699 |v| format!("{} = {}", f.name, v.render()),
700 )
701 })
702 .collect();
703 format!("{} with {}", base.render_atomic(), fs.join("; "))
704 }
705 Self::Tuple { items, .. } => {
706 let xs: Vec<String> = items.iter().map(|e| e.render()).collect();
707 format!("({})", xs.join(", "))
708 }
709 Self::List { items, .. } => {
710 let xs: Vec<String> = items.iter().map(|e| e.render()).collect();
711 format!("[{}]", xs.join(", "))
712 }
713 Self::Try { body, handlers, .. } => {
714 let hs: Vec<String> = handlers
715 .iter()
716 .map(|a| format!("{} -> {}", a.pat.render(), a.body.render()))
717 .collect();
718 format!("try {} catch {}", body.render(), hs.join("; "))
719 }
720 Self::Section {
721 op, operand, left, ..
722 } => match (operand, left) {
723 (Some(e), true) => format!("({} {})", e.render(), op),
724 (Some(e), false) => format!("({} {})", op, e.render()),
725 (None, _) => format!("({op})"),
726 },
727 Self::Error { raw, .. } => raw.clone(),
728 }
729 }
730
731 fn render_atomic(&self) -> String {
734 match self {
735 Self::Var { .. }
736 | Self::Con { .. }
737 | Self::Lit { .. }
738 | Self::Tuple { .. }
739 | Self::List { .. }
740 | Self::Section { .. }
741 | Self::Error { .. } => self.render(),
742 _ => format!("({})", self.render()),
743 }
744 }
745
746 pub fn application_head(&self) -> &Self {
749 match self {
750 Self::App { func, .. } => func.application_head(),
751 _ => self,
752 }
753 }
754
755 pub fn application_args(&self) -> &[Self] {
759 match self {
760 Self::App { args, .. } => args,
761 _ => &[],
762 }
763 }
764}
765
766fn render_do_stmt(s: &DoStmt) -> String {
767 match s {
768 DoStmt::Bind { pat, expr, .. } => format!("{} <- {}", pat.render(), expr.render()),
769 DoStmt::Let { bindings, .. } => {
770 let bs: Vec<String> = bindings.iter().map(render_binding).collect();
771 format!("let {}", bs.join("; "))
772 }
773 DoStmt::Expr { expr, .. } => expr.render(),
774 }
775}
776
777fn render_binding(b: &Binding) -> String {
778 let mut s = b.pat.render();
779 for p in &b.params {
780 s.push(' ');
781 s.push_str(&p.render());
782 }
783 format!("{} = {}", s, b.expr.render())
784}
785
786impl Pat {
787 pub const fn pos(&self) -> Pos {
788 match self {
789 Self::Var { pos, .. }
790 | Self::Wild { pos, .. }
791 | Self::Con { pos, .. }
792 | Self::Tuple { pos, .. }
793 | Self::List { pos, .. }
794 | Self::Lit { pos, .. }
795 | Self::As { pos, .. }
796 | Self::Other { pos, .. } => *pos,
797 }
798 }
799
800 pub const fn span(&self) -> Span {
802 match self {
803 Self::Var { span, .. }
804 | Self::Wild { span, .. }
805 | Self::Con { span, .. }
806 | Self::Tuple { span, .. }
807 | Self::List { span, .. }
808 | Self::Lit { span, .. }
809 | Self::As { span, .. }
810 | Self::Other { span, .. } => *span,
811 }
812 }
813
814 pub fn render(&self) -> String {
818 match self {
819 Self::Var { name, .. } => name.clone(),
820 Self::Wild { .. } => "_".to_string(),
821 Self::Con {
822 qualifier,
823 name,
824 args,
825 ..
826 } => {
827 let head = qualifier
828 .as_ref()
829 .map_or_else(|| name.clone(), |q| format!("{q}.{name}"));
830 if args.is_empty() {
831 head
832 } else {
833 let parts: Vec<String> = args.iter().map(|p| p.render()).collect();
834 format!("({} {})", head, parts.join(" "))
835 }
836 }
837 Self::Tuple { items, .. } => {
838 let xs: Vec<String> = items.iter().map(|p| p.render()).collect();
839 format!("({})", xs.join(", "))
840 }
841 Self::List { items, .. } => {
842 let xs: Vec<String> = items.iter().map(|p| p.render()).collect();
843 format!("[{}]", xs.join(", "))
844 }
845 Self::Lit { kind, text, .. } => match kind {
846 LitKind::Text => format!("{text:?}"),
847 LitKind::Char => format!("'{text}'"),
848 _ => text.clone(),
849 },
850 Self::As { name, pat, .. } => format!("{}@{}", name, pat.render()),
851 Self::Other { raw, .. } => raw.clone(),
852 }
853 }
854}