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, _)) => a == b,
338 (Self::Tuple(a, _), Self::Tuple(b, _)) => a == b,
339 (Self::Fun(al, ar, _), Self::Fun(bl, br, _)) => al == bl && ar == br,
340 (Self::Var(a, _), Self::Var(b, _)) => a == b,
341 (Self::Unit(_), Self::Unit(_)) => true,
342 (Self::Constrained(a, _), Self::Constrained(b, _)) => a == b,
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)]
510pub struct DataConstructor {
511 pub name: String,
512 pub fields: Vec<FieldDecl>,
516 pub arg_types: Vec<Type>,
521 pub pos: Pos,
522 pub span: Span,
523}
524
525#[derive(Debug, Clone)]
526pub enum Decl {
527 Template(TemplateDecl),
528 Interface(InterfaceDecl),
529 Function(FunctionDecl),
530 TypeDef {
532 keyword: String,
533 name: String,
534 constructors: Vec<DataConstructor>,
538 synonym: Option<Type>,
541 deriving: Vec<String>,
544 pos: Pos,
545 span: Span,
546 },
547 Unknown {
549 raw: String,
550 pos: Pos,
551 span: Span,
552 },
553}
554
555#[derive(Debug, Clone)]
556pub struct Module {
557 pub name: String,
558 pub pos: Pos,
559 pub span: Span,
561 pub header: Span,
565 pub imports: Vec<ImportDecl>,
566 pub decls: Vec<Decl>,
567}
568
569#[derive(Debug, Clone, Copy, PartialEq, Eq)]
575pub enum DiagnosticCategory {
576 SkippedDecl,
578 Malformed,
581 UnsupportedSyntax,
584 RecursionLimit,
587 Lex,
589}
590
591impl DiagnosticCategory {
592 pub const fn as_str(self) -> &'static str {
594 match self {
595 Self::SkippedDecl => "skipped-declaration",
596 Self::Malformed => "malformed",
597 Self::UnsupportedSyntax => "unsupported-syntax",
598 Self::RecursionLimit => "recursion-limit",
599 Self::Lex => "lexical-error",
600 }
601 }
602}
603
604#[derive(Debug, Clone)]
606pub struct ParseDiagnostic {
607 pub message: String,
608 pub pos: Pos,
609 pub span: Span,
613 pub category: DiagnosticCategory,
614}
615
616impl Expr {
617 pub const fn pos(&self) -> Pos {
618 match self {
619 Self::Var { pos, .. }
620 | Self::Con { pos, .. }
621 | Self::Lit { pos, .. }
622 | Self::App { pos, .. }
623 | Self::BinOp { pos, .. }
624 | Self::Neg { pos, .. }
625 | Self::Lambda { pos, .. }
626 | Self::If { pos, .. }
627 | Self::Case { pos, .. }
628 | Self::Do { pos, .. }
629 | Self::LetIn { pos, .. }
630 | Self::Record { pos, .. }
631 | Self::Tuple { pos, .. }
632 | Self::List { pos, .. }
633 | Self::Try { pos, .. }
634 | Self::Section { pos, .. }
635 | Self::Error { pos, .. } => *pos,
636 }
637 }
638
639 pub const fn span(&self) -> Span {
641 match self {
642 Self::Var { span, .. }
643 | Self::Con { span, .. }
644 | Self::Lit { span, .. }
645 | Self::App { span, .. }
646 | Self::BinOp { span, .. }
647 | Self::Neg { span, .. }
648 | Self::Lambda { span, .. }
649 | Self::If { span, .. }
650 | Self::Case { span, .. }
651 | Self::Do { span, .. }
652 | Self::LetIn { span, .. }
653 | Self::Record { span, .. }
654 | Self::Tuple { span, .. }
655 | Self::List { span, .. }
656 | Self::Try { span, .. }
657 | Self::Section { span, .. }
658 | Self::Error { span, .. } => *span,
659 }
660 }
661
662 pub fn render(&self) -> String {
664 match self {
665 Self::Var {
666 qualifier, name, ..
667 }
668 | Self::Con {
669 qualifier, name, ..
670 } => qualifier
671 .as_ref()
672 .map_or_else(|| name.clone(), |q| format!("{}.{}", q, name)),
673 Self::Lit { kind, text, .. } => match kind {
674 LitKind::Text => format!("{:?}", text),
675 LitKind::Char => format!("'{}'", text),
676 _ => text.clone(),
677 },
678 Self::App { func, args, .. } => {
679 let mut s = func.render_atomic();
680 for a in args {
681 s.push(' ');
682 s.push_str(&a.render_atomic());
683 }
684 s
685 }
686 Self::BinOp { op, lhs, rhs, .. } => {
687 if op == "." {
688 format!("{}.{}", lhs.render_atomic(), rhs.render_atomic())
690 } else {
691 format!("{} {} {}", lhs.render_atomic(), op, rhs.render_atomic())
692 }
693 }
694 Self::Neg { expr, .. } => format!("-{}", expr.render_atomic()),
695 Self::Lambda { params, body, .. } => {
696 let ps: Vec<String> = params.iter().map(|p| p.render()).collect();
697 format!("\\{} -> {}", ps.join(" "), body.render())
698 }
699 Self::If {
700 cond,
701 then_branch,
702 else_branch,
703 ..
704 } => format!(
705 "if {} then {} else {}",
706 cond.render(),
707 then_branch.render(),
708 else_branch.render()
709 ),
710 Self::Case {
711 scrutinee, alts, ..
712 } => {
713 let arms: Vec<String> = alts
714 .iter()
715 .map(|a| format!("{} -> {}", a.pat.render(), a.body.render()))
716 .collect();
717 format!("case {} of {}", scrutinee.render(), arms.join("; "))
718 }
719 Self::Do { stmts, .. } => {
720 let body: Vec<String> = stmts.iter().map(render_do_stmt).collect();
721 format!("do {}", body.join("; "))
722 }
723 Self::LetIn { bindings, body, .. } => {
724 let bs: Vec<String> = bindings.iter().map(render_binding).collect();
725 format!("let {} in {}", bs.join("; "), body.render())
726 }
727 Self::Record { base, fields, .. } => {
728 let fs: Vec<String> = fields
729 .iter()
730 .map(|f| {
731 f.value.as_ref().map_or_else(
732 || f.name.clone(),
733 |v| format!("{} = {}", f.name, v.render()),
734 )
735 })
736 .collect();
737 format!("{} with {}", base.render_atomic(), fs.join("; "))
738 }
739 Self::Tuple { items, .. } => {
740 let xs: Vec<String> = items.iter().map(|e| e.render()).collect();
741 format!("({})", xs.join(", "))
742 }
743 Self::List { items, .. } => {
744 let xs: Vec<String> = items.iter().map(|e| e.render()).collect();
745 format!("[{}]", xs.join(", "))
746 }
747 Self::Try { body, handlers, .. } => {
748 let hs: Vec<String> = handlers
749 .iter()
750 .map(|a| format!("{} -> {}", a.pat.render(), a.body.render()))
751 .collect();
752 format!("try {} catch {}", body.render(), hs.join("; "))
753 }
754 Self::Section {
755 op, operand, left, ..
756 } => match (operand, left) {
757 (Some(e), true) => format!("({} {})", e.render(), op),
758 (Some(e), false) => format!("({} {})", op, e.render()),
759 (None, _) => format!("({})", op),
760 },
761 Self::Error { raw, .. } => raw.clone(),
762 }
763 }
764
765 fn render_atomic(&self) -> String {
768 match self {
769 Self::Var { .. }
770 | Self::Con { .. }
771 | Self::Lit { .. }
772 | Self::Tuple { .. }
773 | Self::List { .. }
774 | Self::Section { .. }
775 | Self::Error { .. } => self.render(),
776 _ => format!("({})", self.render()),
777 }
778 }
779
780 pub fn app_head(&self) -> &Self {
783 match self {
784 Self::App { func, .. } => func.app_head(),
785 _ => self,
786 }
787 }
788
789 pub fn app_args(&self) -> &[Self] {
791 match self {
792 Self::App { args, .. } => args,
793 _ => &[],
794 }
795 }
796
797 pub fn head_is(&self, name: &str) -> bool {
799 matches!(
800 self.app_head(),
801 Self::Var { qualifier: None, name: n, .. } if n == name
802 )
803 }
804}
805
806pub fn render_do_stmt(s: &DoStmt) -> String {
807 match s {
808 DoStmt::Bind { pat, expr, .. } => format!("{} <- {}", pat.render(), expr.render()),
809 DoStmt::Let { bindings, .. } => {
810 let bs: Vec<String> = bindings.iter().map(render_binding).collect();
811 format!("let {}", bs.join("; "))
812 }
813 DoStmt::Expr { expr, .. } => expr.render(),
814 }
815}
816
817pub fn render_binding(b: &Binding) -> String {
818 let mut s = b.pat.render();
819 for p in &b.params {
820 s.push(' ');
821 s.push_str(&p.render());
822 }
823 format!("{} = {}", s, b.expr.render())
824}
825
826impl Pat {
827 pub const fn pos(&self) -> Pos {
828 match self {
829 Self::Var { pos, .. }
830 | Self::Wild { pos, .. }
831 | Self::Con { pos, .. }
832 | Self::Tuple { pos, .. }
833 | Self::List { pos, .. }
834 | Self::Lit { pos, .. }
835 | Self::As { pos, .. }
836 | Self::Other { pos, .. } => *pos,
837 }
838 }
839
840 pub const fn span(&self) -> Span {
842 match self {
843 Self::Var { span, .. }
844 | Self::Wild { span, .. }
845 | Self::Con { span, .. }
846 | Self::Tuple { span, .. }
847 | Self::List { span, .. }
848 | Self::Lit { span, .. }
849 | Self::As { span, .. }
850 | Self::Other { span, .. } => *span,
851 }
852 }
853
854 pub fn render(&self) -> String {
855 match self {
856 Self::Var { name, .. } => name.clone(),
857 Self::Wild { .. } => "_".to_string(),
858 Self::Con {
859 qualifier,
860 name,
861 args,
862 ..
863 } => {
864 let head = qualifier
865 .as_ref()
866 .map_or_else(|| name.clone(), |q| format!("{}.{}", q, name));
867 if args.is_empty() {
868 head
869 } else {
870 let parts: Vec<String> = args.iter().map(|p| p.render()).collect();
871 format!("({} {})", head, parts.join(" "))
872 }
873 }
874 Self::Tuple { items, .. } => {
875 let xs: Vec<String> = items.iter().map(|p| p.render()).collect();
876 format!("({})", xs.join(", "))
877 }
878 Self::List { items, .. } => {
879 let xs: Vec<String> = items.iter().map(|p| p.render()).collect();
880 format!("[{}]", xs.join(", "))
881 }
882 Self::Lit { kind, text, .. } => match kind {
883 LitKind::Text => format!("{:?}", text),
884 LitKind::Char => format!("'{}'", text),
885 _ => text.clone(),
886 },
887 Self::As { name, pat, .. } => format!("{}@{}", name, pat.render()),
888 Self::Other { raw, .. } => raw.clone(),
889 }
890 }
891}