1#![expect(missing_docs, reason = "fields mostly self-describing")]
4
5use crate::lexer::Pos;
6use crate::log;
7
8#[derive(Clone, PartialEq, Eq, Debug)]
10pub enum Def {
11 Pragma(Pragma),
12 Type(Type),
13 Rule(Rule),
14 Extractor(Extractor),
15 Decl(Decl),
16 Attr(Attr),
17 Spec(Spec),
18 SpecMacro(SpecMacro),
19 Model(Model),
20 State(State),
21 Form(Form),
22 Instantiation(Instantiation),
23 Extern(Extern),
24 Converter(Converter),
25}
26
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct Ident(pub String, pub Pos);
30
31#[derive(Clone, PartialEq, Eq, Debug)]
33pub enum Pragma {
34 }
36
37#[derive(Clone, PartialEq, Eq, Debug)]
39pub struct Type {
40 pub name: Ident,
41 pub is_extern: bool,
42 pub is_nodebug: bool,
43 pub ty: TypeValue,
44 pub pos: Pos,
45}
46
47#[derive(Clone, PartialEq, Eq, Debug)]
49pub enum TypeValue {
50 Primitive(Ident, Pos),
51 Enum(Vec<Variant>, Pos),
52 Struct(Fields, Pos),
53}
54
55#[derive(Clone, PartialEq, Eq, Debug)]
57pub struct Variant {
58 pub name: Ident,
59 pub fields: Fields,
60 pub pos: Pos,
61}
62
63impl Variant {
64 pub fn full_name(enum_name: &Ident, variant_name: &Ident) -> Ident {
65 Ident(
66 format!("{}.{}", enum_name.0, variant_name.0),
67 variant_name.1,
68 )
69 }
70}
71
72#[derive(Clone, PartialEq, Eq, Debug)]
74pub enum Fields {
75 Unit,
76 Struct(StructFields),
77 Tuple(TupleFields),
78}
79
80#[derive(Clone, PartialEq, Eq, Debug)]
82pub struct StructFields {
83 pub fields: Vec<StructField>,
84 pub pos: Pos,
85}
86
87#[derive(Clone, PartialEq, Eq, Debug)]
89pub struct StructField {
90 pub name: Ident,
91 pub ty: Ident,
92 pub pos: Pos,
93}
94
95#[derive(Clone, PartialEq, Eq, Debug)]
97pub struct TupleFields {
98 pub fields: Vec<TupleField>,
99 pub pos: Pos,
100}
101
102#[derive(Clone, PartialEq, Eq, Debug)]
104pub struct TupleField {
105 pub index: usize,
106 pub ty: Ident,
107 pub pos: Pos,
108}
109
110#[derive(Clone, PartialEq, Eq, Debug)]
112pub struct Decl {
113 pub term: Ident,
114 pub arg_tys: Vec<Ident>,
115 pub ret_ty: Ident,
116 pub pure: bool,
118 pub multi: bool,
122 pub partial: bool,
124 pub rec: bool,
126 pub pos: Pos,
127}
128
129#[derive(Clone, PartialEq, Eq, Debug)]
130pub struct Instantiation {
131 pub term: Ident,
132 pub form: Option<Ident>,
133 pub signatures: Vec<Signature>,
134 pub tags: Vec<Ident>,
137 pub pos: Pos,
138}
139
140#[derive(Clone, PartialEq, Eq, Debug)]
142pub struct Attr {
143 pub target: AttrTarget,
144 pub kinds: Vec<AttrKind>,
145 pub pos: Pos,
146}
147
148#[derive(Clone, PartialEq, Eq, Debug)]
150pub enum AttrTarget {
151 Term(Ident),
152 Rule(Ident),
153}
154
155#[derive(Clone, PartialEq, Eq, Debug)]
157pub enum AttrKind {
158 Chain,
164
165 Priority,
179
180 Tag(Ident),
182}
183
184#[derive(Clone, PartialEq, Eq, Debug)]
186pub enum SpecExpr {
187 ConstInt {
189 val: i128,
190 pos: Pos,
191 },
192 ConstBitVec {
194 val: u128,
195 width: usize,
196 pos: Pos,
197 },
198 ConstBool {
200 val: bool,
201 pos: Pos,
202 },
203 Var {
205 var: Ident,
206 pos: Pos,
207 },
208 As {
211 x: Box<SpecExpr>,
212 ty: ModelType,
213 pos: Pos,
214 },
215 Field {
217 field: Ident,
218 x: Box<SpecExpr>,
219 pos: Pos,
220 },
221 Discriminator {
223 variant: Ident,
224 x: Box<SpecExpr>,
225 pos: Pos,
226 },
227 Op {
229 op: SpecOp,
230 args: Vec<SpecExpr>,
231 pos: Pos,
232 },
233 Match {
235 x: Box<SpecExpr>,
236 arms: Vec<Arm>,
237 pos: Pos,
238 },
239 Let {
241 defs: Vec<(Ident, SpecExpr)>,
242 body: Box<SpecExpr>,
243 pos: Pos,
244 },
245 With {
247 decls: Vec<Ident>,
248 body: Box<SpecExpr>,
249 pos: Pos,
250 },
251 Macro {
253 params: Vec<Ident>,
255 body: Box<SpecExpr>,
257 pos: Pos,
258 },
259 Expand {
261 name: Ident,
262 args: Vec<SpecExpr>,
263 pos: Pos,
264 },
265 Pair {
267 l: Box<SpecExpr>,
268 r: Box<SpecExpr>,
269 pos: Pos,
270 },
271 Enum {
273 name: Ident,
274 variant: Ident,
275 args: Vec<SpecExpr>,
276 pos: Pos,
277 },
278 Struct {
280 fields: Vec<FieldInit>,
281 pos: Pos,
282 },
283}
284
285impl SpecExpr {
286 pub fn pos(&self) -> Pos {
287 match self {
288 &Self::ConstInt { pos, .. }
289 | &Self::ConstBitVec { pos, .. }
290 | &Self::ConstBool { pos, .. }
291 | &Self::Var { pos, .. }
292 | &Self::As { pos, .. }
293 | &Self::Field { pos, .. }
294 | &Self::Discriminator { pos, .. }
295 | &Self::Op { pos, .. }
296 | &Self::Match { pos, .. }
297 | &Self::Let { pos, .. }
298 | &Self::With { pos, .. }
299 | &Self::Macro { pos, .. }
300 | &Self::Expand { pos, .. }
301 | &Self::Pair { pos, .. }
302 | &Self::Enum { pos, .. }
303 | &Self::Struct { pos, .. } => pos,
304 }
305 }
306}
307
308#[derive(Clone, PartialEq, Eq, Debug)]
310pub enum SpecOp {
311 Eq,
313 And,
314 Or,
315 Not,
316 Imp,
317
318 Add,
320 Sub,
321 Mul,
322
323 Lt,
325 Lte,
326 Gt,
327 Gte,
328
329 BVNot,
331 BVAnd,
332 BVOr,
333 BVXor,
334
335 BVNeg,
337 BVAdd,
338 BVSub,
339 BVMul,
340 BVUdiv,
341 BVUrem,
342 BVSdiv,
343 BVSrem,
344 BVShl,
345 BVLshr,
346 BVAshr,
347
348 BVUle,
350 BVUlt,
351 BVUgt,
352 BVUge,
353 BVSlt,
354 BVSle,
355 BVSgt,
356 BVSge,
357
358 BVSaddo,
360
361 Rotr,
363 Rotl,
364 Extract,
365 ZeroExt,
366 SignExt,
367 Concat,
368 Replicate,
369
370 FPEq,
372 FPNe,
373 FPLt,
374 FPGt,
375 FPLe,
376 FPGe,
377 FPPositiveInfinity,
378 FPNegativeInfinity,
379 FPPositiveZero,
380 FPNegativeZero,
381 FPNaN,
382 FPAdd,
383 FPSub,
384 FPMul,
385 FPDiv,
386 FPMin,
387 FPMax,
388 FPNeg,
389 FPCeil,
390 FPFloor,
391 FPSqrt,
392 FPTrunc,
393 FPNearest,
394 FPIsZero,
395 FPIsInfinite,
396 FPIsNaN,
397 FPIsNegative,
398 FPIsPositive,
399
400 Popcnt,
402 Clz,
403 Cls,
404 Rev,
405
406 ConvTo,
408 Int2BV,
409 BV2Nat,
410 ToFP,
411 ToFPUnsigned,
412 ToFPFromFP,
413 FPToUBV,
414 FPToSBV,
415 WidthOf,
416
417 If,
419 Switch,
420}
421
422#[derive(Clone, PartialEq, Eq, Debug)]
424pub struct Arm {
425 pub variant: Ident,
426 pub args: Vec<Ident>,
427 pub body: SpecExpr,
428 pub pos: Pos,
429}
430
431#[derive(Clone, PartialEq, Eq, Debug)]
433pub struct FieldInit {
434 pub name: Ident,
435 pub value: Box<SpecExpr>,
436 pub pos: Pos,
437}
438
439#[derive(Clone, PartialEq, Eq, Debug)]
440pub struct SpecMacro {
441 pub name: Ident,
443 pub params: Vec<Ident>,
445 pub body: SpecExpr,
447 pub pos: Pos,
448}
449
450#[derive(Clone, PartialEq, Eq, Debug)]
452pub struct Modifies {
453 pub state: Ident,
454 pub cond: Option<Ident>,
455}
456
457#[derive(Clone, PartialEq, Eq, Debug)]
459pub struct Spec {
460 pub term: Ident,
462 pub args: Vec<Ident>,
464 pub provides: Vec<SpecExpr>,
466 pub requires: Vec<SpecExpr>,
468 pub matches: Vec<SpecExpr>,
470 pub modifies: Vec<Modifies>,
472 pub pos: Pos,
473}
474
475#[derive(Clone, PartialEq, Eq, Debug)]
477pub enum ModelType {
478 Unspecified,
485 Auto,
487 Int,
489 Bool,
491 Unit,
493 BitVec(Option<usize>),
495 Struct(Vec<ModelField>),
497 Named(Ident),
499}
500
501#[derive(Clone, PartialEq, Eq, Debug)]
502pub struct ModelField {
503 pub name: Ident,
504 pub ty: ModelType,
505}
506
507#[derive(Clone, PartialEq, Eq, Debug)]
509pub enum ModelValue {
510 TypeValue(ModelType),
512 ConstValue(SpecExpr),
514}
515
516#[derive(Clone, PartialEq, Eq, Debug)]
518pub struct Model {
519 pub name: Ident,
521 pub val: ModelValue,
523}
524
525#[derive(Clone, PartialEq, Eq, Debug)]
527pub struct State {
528 pub name: Ident,
530 pub ty: ModelType,
532 pub default: SpecExpr,
534 pub pos: Pos,
535}
536
537#[derive(Clone, PartialEq, Eq, Debug)]
538pub struct Signature {
539 pub args: Vec<ModelType>,
540 pub ret: ModelType,
541 pub pos: Pos,
542}
543
544#[derive(Clone, PartialEq, Eq, Debug)]
545pub struct Form {
546 pub name: Ident,
547 pub signatures: Vec<Signature>,
548 pub pos: Pos,
549}
550
551#[derive(Clone, PartialEq, Eq, Debug)]
552pub struct Rule {
553 pub pattern: Pattern,
554 pub iflets: Vec<IfLet>,
555 pub expr: Expr,
556 pub pos: Pos,
557 pub prio: Option<i64>,
558 pub name: Option<Ident>,
559}
560
561#[derive(Clone, PartialEq, Eq, Debug)]
562pub struct IfLet {
563 pub pattern: Pattern,
564 pub expr: Expr,
565 pub pos: Pos,
566}
567
568#[derive(Clone, PartialEq, Eq, Debug)]
571pub struct Extractor {
572 pub term: Ident,
573 pub args: Vec<Ident>,
574 pub template: Pattern,
575 pub pos: Pos,
576}
577
578#[derive(Clone, PartialEq, Eq, Debug)]
580pub enum Pattern {
581 Var { var: Ident, pos: Pos },
590 BindPattern {
593 var: Ident,
594 subpat: Box<Pattern>,
595 pos: Pos,
596 },
597 ConstBool { val: bool, pos: Pos },
599 ConstInt { val: i128, pos: Pos },
601 ConstPrim { val: Ident, pos: Pos },
603 Term {
605 sym: Ident,
606 args: Vec<Pattern>,
607 pos: Pos,
608 },
609 Wildcard { pos: Pos },
611 And { subpats: Vec<Pattern>, pos: Pos },
613 MacroArg { index: usize, pos: Pos },
615}
616
617impl Pattern {
618 pub fn root_term(&self) -> Option<&Ident> {
619 match self {
620 &Pattern::Term { ref sym, .. } => Some(sym),
621 _ => None,
622 }
623 }
624
625 pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
627 match self {
628 Pattern::Term { sym, args, pos } => {
629 f(*pos, sym);
630 for arg in args {
631 arg.terms(f);
632 }
633 }
634 Pattern::And { subpats, .. } => {
635 for p in subpats {
636 p.terms(f);
637 }
638 }
639 Pattern::BindPattern { subpat, .. } => {
640 subpat.terms(f);
641 }
642 Pattern::Var { .. }
643 | Pattern::ConstBool { .. }
644 | Pattern::ConstInt { .. }
645 | Pattern::ConstPrim { .. }
646 | Pattern::Wildcard { .. }
647 | Pattern::MacroArg { .. } => {}
648 }
649 }
650
651 pub fn make_macro_template(&self, macro_args: &[Ident]) -> Pattern {
652 log!("make_macro_template: {:?} with {:?}", self, macro_args);
653 match self {
654 &Pattern::BindPattern {
655 ref var,
656 ref subpat,
657 pos,
658 ..
659 } if matches!(&**subpat, &Pattern::Wildcard { .. }) => {
660 if let Some(i) = macro_args.iter().position(|arg| arg.0 == var.0) {
661 Pattern::MacroArg { index: i, pos }
662 } else {
663 self.clone()
664 }
665 }
666 &Pattern::BindPattern {
667 ref var,
668 ref subpat,
669 pos,
670 } => Pattern::BindPattern {
671 var: var.clone(),
672 subpat: Box::new(subpat.make_macro_template(macro_args)),
673 pos,
674 },
675 &Pattern::Var { ref var, pos } => {
676 if let Some(i) = macro_args.iter().position(|arg| arg.0 == var.0) {
677 Pattern::MacroArg { index: i, pos }
678 } else {
679 self.clone()
680 }
681 }
682 &Pattern::And { ref subpats, pos } => {
683 let subpats = subpats
684 .iter()
685 .map(|subpat| subpat.make_macro_template(macro_args))
686 .collect::<Vec<_>>();
687 Pattern::And { subpats, pos }
688 }
689 &Pattern::Term {
690 ref sym,
691 ref args,
692 pos,
693 } => {
694 let args = args
695 .iter()
696 .map(|arg| arg.make_macro_template(macro_args))
697 .collect::<Vec<_>>();
698 Pattern::Term {
699 sym: sym.clone(),
700 args,
701 pos,
702 }
703 }
704
705 &Pattern::Wildcard { .. }
706 | &Pattern::ConstBool { .. }
707 | &Pattern::ConstInt { .. }
708 | &Pattern::ConstPrim { .. } => self.clone(),
709 &Pattern::MacroArg { .. } => unreachable!(),
710 }
711 }
712
713 pub fn subst_macro_args(&self, macro_args: &[Pattern]) -> Option<Pattern> {
714 log!("subst_macro_args: {:?} with {:?}", self, macro_args);
715 match self {
716 &Pattern::BindPattern {
717 ref var,
718 ref subpat,
719 pos,
720 } => Some(Pattern::BindPattern {
721 var: var.clone(),
722 subpat: Box::new(subpat.subst_macro_args(macro_args)?),
723 pos,
724 }),
725 &Pattern::And { ref subpats, pos } => {
726 let subpats = subpats
727 .iter()
728 .map(|subpat| subpat.subst_macro_args(macro_args))
729 .collect::<Option<Vec<_>>>()?;
730 Some(Pattern::And { subpats, pos })
731 }
732 &Pattern::Term {
733 ref sym,
734 ref args,
735 pos,
736 } => {
737 let args = args
738 .iter()
739 .map(|arg| arg.subst_macro_args(macro_args))
740 .collect::<Option<Vec<_>>>()?;
741 Some(Pattern::Term {
742 sym: sym.clone(),
743 args,
744 pos,
745 })
746 }
747
748 &Pattern::Var { .. }
749 | &Pattern::Wildcard { .. }
750 | &Pattern::ConstBool { .. }
751 | &Pattern::ConstInt { .. }
752 | &Pattern::ConstPrim { .. } => Some(self.clone()),
753 &Pattern::MacroArg { index, .. } => macro_args.get(index).cloned(),
754 }
755 }
756
757 pub fn pos(&self) -> Pos {
758 match self {
759 &Pattern::ConstBool { pos, .. }
760 | &Pattern::ConstInt { pos, .. }
761 | &Pattern::ConstPrim { pos, .. }
762 | &Pattern::And { pos, .. }
763 | &Pattern::Term { pos, .. }
764 | &Pattern::BindPattern { pos, .. }
765 | &Pattern::Var { pos, .. }
766 | &Pattern::Wildcard { pos, .. }
767 | &Pattern::MacroArg { pos, .. } => pos,
768 }
769 }
770}
771
772#[derive(Clone, PartialEq, Eq, Debug)]
778pub enum Expr {
779 Term {
781 sym: Ident,
782 args: Vec<Expr>,
783 pos: Pos,
784 },
785 Var { name: Ident, pos: Pos },
787 ConstBool { val: bool, pos: Pos },
789 ConstInt { val: i128, pos: Pos },
791 ConstPrim { val: Ident, pos: Pos },
793 Let {
795 defs: Vec<LetDef>,
796 body: Box<Expr>,
797 pos: Pos,
798 },
799}
800
801impl Expr {
802 pub fn pos(&self) -> Pos {
803 match self {
804 &Expr::Term { pos, .. }
805 | &Expr::Var { pos, .. }
806 | &Expr::ConstBool { pos, .. }
807 | &Expr::ConstInt { pos, .. }
808 | &Expr::ConstPrim { pos, .. }
809 | &Expr::Let { pos, .. } => pos,
810 }
811 }
812
813 pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
815 match self {
816 Expr::Term { sym, args, pos } => {
817 f(*pos, sym);
818 for arg in args {
819 arg.terms(f);
820 }
821 }
822 Expr::Let { defs, body, .. } => {
823 for def in defs {
824 def.val.terms(f);
825 }
826 body.terms(f);
827 }
828 Expr::Var { .. }
829 | Expr::ConstBool { .. }
830 | Expr::ConstInt { .. }
831 | Expr::ConstPrim { .. } => {}
832 }
833 }
834}
835
836#[derive(Clone, PartialEq, Eq, Debug)]
838pub struct LetDef {
839 pub var: Ident,
840 pub ty: Ident,
841 pub val: Box<Expr>,
842 pub pos: Pos,
843}
844
845#[derive(Clone, PartialEq, Eq, Debug)]
848pub enum Extern {
849 Extractor {
851 term: Ident,
853 func: Ident,
855 pos: Pos,
857 infallible: bool,
862 },
863 Constructor {
865 term: Ident,
867 func: Ident,
869 pos: Pos,
871 },
872 Const { name: Ident, ty: Ident, pos: Pos },
874}
875
876#[derive(Clone, Debug, PartialEq, Eq)]
881pub struct Converter {
882 pub term: Ident,
884 pub inner_ty: Ident,
888 pub outer_ty: Ident,
892 pub pos: Pos,
894}