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 Spec(Spec),
17 Model(Model),
18 Form(Form),
19 Instantiation(Instantiation),
20 Extern(Extern),
21 Converter(Converter),
22}
23
24#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
26pub struct Ident(pub String, pub Pos);
27
28#[derive(Clone, PartialEq, Eq, Debug)]
30pub enum Pragma {
31 }
33
34#[derive(Clone, PartialEq, Eq, Debug)]
36pub struct Type {
37 pub name: Ident,
38 pub is_extern: bool,
39 pub is_nodebug: bool,
40 pub ty: TypeValue,
41 pub pos: Pos,
42}
43
44#[derive(Clone, PartialEq, Eq, Debug)]
48pub enum TypeValue {
49 Primitive(Ident, Pos),
50 Enum(Vec<Variant>, Pos),
51}
52
53#[derive(Clone, PartialEq, Eq, Debug)]
55pub struct Variant {
56 pub name: Ident,
57 pub fields: Vec<Field>,
58 pub pos: Pos,
59}
60
61#[derive(Clone, PartialEq, Eq, Debug)]
63pub struct Field {
64 pub name: Ident,
65 pub ty: Ident,
66 pub pos: Pos,
67}
68
69#[derive(Clone, PartialEq, Eq, Debug)]
71pub struct Decl {
72 pub term: Ident,
73 pub arg_tys: Vec<Ident>,
74 pub ret_ty: Ident,
75 pub pure: bool,
77 pub multi: bool,
81 pub partial: bool,
83 pub rec: bool,
85 pub pos: Pos,
86}
87
88#[derive(Clone, PartialEq, Eq, Debug)]
90pub enum SpecExpr {
91 ConstInt {
93 val: i128,
94 pos: Pos,
95 },
96 ConstBitVec {
98 val: i128,
99 width: i8,
100 pos: Pos,
101 },
102 ConstBool {
104 val: bool,
105 pos: Pos,
106 },
107 ConstUnit {
109 pos: Pos,
110 },
111 Var {
113 var: Ident,
114 pos: Pos,
115 },
116 Op {
118 op: SpecOp,
119 args: Vec<SpecExpr>,
120 pos: Pos,
121 },
122 Pair {
124 l: Box<SpecExpr>,
125 r: Box<SpecExpr>,
126 },
127 Enum {
129 name: Ident,
130 },
131}
132
133#[derive(Clone, PartialEq, Eq, Debug)]
135pub enum SpecOp {
136 Eq,
138 And,
139 Or,
140 Not,
141 Imp,
142
143 Lt,
145 Lte,
146 Gt,
147 Gte,
148
149 BVNot,
151 BVAnd,
152 BVOr,
153 BVXor,
154
155 BVNeg,
157 BVAdd,
158 BVSub,
159 BVMul,
160 BVUdiv,
161 BVUrem,
162 BVSdiv,
163 BVSrem,
164 BVShl,
165 BVLshr,
166 BVAshr,
167
168 BVUle,
170 BVUlt,
171 BVUgt,
172 BVUge,
173 BVSlt,
174 BVSle,
175 BVSgt,
176 BVSge,
177
178 BVSaddo,
180
181 Rotr,
183 Rotl,
184 Extract,
185 ZeroExt,
186 SignExt,
187 Concat,
188
189 Subs,
191 Popcnt,
192 Clz,
193 Cls,
194 Rev,
195
196 ConvTo,
198 Int2BV,
199 BV2Int,
200 WidthOf,
201
202 If,
204 Switch,
205
206 LoadEffect,
207 StoreEffect,
208}
209
210#[derive(Clone, PartialEq, Eq, Debug)]
212pub struct Spec {
213 pub term: Ident,
215 pub args: Vec<Ident>,
217 pub provides: Vec<SpecExpr>,
219 pub requires: Vec<SpecExpr>,
221}
222
223#[derive(Clone, PartialEq, Eq, Debug)]
225pub enum ModelType {
226 Int,
228 Bool,
230 BitVec(Option<usize>),
232 Unit,
234}
235
236#[derive(Clone, PartialEq, Eq, Debug)]
238pub enum ModelValue {
239 TypeValue(ModelType),
241 EnumValues(Vec<(Ident, SpecExpr)>),
243}
244
245#[derive(Clone, PartialEq, Eq, Debug)]
247pub struct Model {
248 pub name: Ident,
250 pub val: ModelValue,
252}
253
254#[derive(Clone, PartialEq, Eq, Debug)]
255pub struct Signature {
256 pub args: Vec<ModelType>,
257 pub ret: ModelType,
258 pub canonical: ModelType,
259 pub pos: Pos,
260}
261
262#[derive(Clone, PartialEq, Eq, Debug)]
263pub struct Form {
264 pub name: Ident,
265 pub signatures: Vec<Signature>,
266 pub pos: Pos,
267}
268
269#[derive(Clone, PartialEq, Eq, Debug)]
270pub struct Instantiation {
271 pub term: Ident,
272 pub form: Option<Ident>,
273 pub signatures: Vec<Signature>,
274 pub pos: Pos,
275}
276
277#[derive(Clone, PartialEq, Eq, Debug)]
278pub struct Rule {
279 pub pattern: Pattern,
280 pub iflets: Vec<IfLet>,
281 pub expr: Expr,
282 pub pos: Pos,
283 pub prio: Option<i64>,
284 pub name: Option<Ident>,
285}
286
287#[derive(Clone, PartialEq, Eq, Debug)]
288pub struct IfLet {
289 pub pattern: Pattern,
290 pub expr: Expr,
291 pub pos: Pos,
292}
293
294#[derive(Clone, PartialEq, Eq, Debug)]
297pub struct Extractor {
298 pub term: Ident,
299 pub args: Vec<Ident>,
300 pub template: Pattern,
301 pub pos: Pos,
302}
303
304#[derive(Clone, PartialEq, Eq, Debug)]
306pub enum Pattern {
307 Var { var: Ident, pos: Pos },
316 BindPattern {
319 var: Ident,
320 subpat: Box<Pattern>,
321 pos: Pos,
322 },
323 ConstBool { val: bool, pos: Pos },
325 ConstInt { val: i128, pos: Pos },
327 ConstPrim { val: Ident, pos: Pos },
329 Term {
331 sym: Ident,
332 args: Vec<Pattern>,
333 pos: Pos,
334 },
335 Wildcard { pos: Pos },
337 And { subpats: Vec<Pattern>, pos: Pos },
339 MacroArg { index: usize, pos: Pos },
341}
342
343impl Pattern {
344 pub fn root_term(&self) -> Option<&Ident> {
345 match self {
346 &Pattern::Term { ref sym, .. } => Some(sym),
347 _ => None,
348 }
349 }
350
351 pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
353 match self {
354 Pattern::Term { sym, args, pos } => {
355 f(*pos, sym);
356 for arg in args {
357 arg.terms(f);
358 }
359 }
360 Pattern::And { subpats, .. } => {
361 for p in subpats {
362 p.terms(f);
363 }
364 }
365 Pattern::BindPattern { subpat, .. } => {
366 subpat.terms(f);
367 }
368 Pattern::Var { .. }
369 | Pattern::ConstBool { .. }
370 | Pattern::ConstInt { .. }
371 | Pattern::ConstPrim { .. }
372 | Pattern::Wildcard { .. }
373 | Pattern::MacroArg { .. } => {}
374 }
375 }
376
377 pub fn make_macro_template(&self, macro_args: &[Ident]) -> Pattern {
378 log!("make_macro_template: {:?} with {:?}", self, macro_args);
379 match self {
380 &Pattern::BindPattern {
381 ref var,
382 ref subpat,
383 pos,
384 ..
385 } if matches!(&**subpat, &Pattern::Wildcard { .. }) => {
386 if let Some(i) = macro_args.iter().position(|arg| arg.0 == var.0) {
387 Pattern::MacroArg { index: i, pos }
388 } else {
389 self.clone()
390 }
391 }
392 &Pattern::BindPattern {
393 ref var,
394 ref subpat,
395 pos,
396 } => Pattern::BindPattern {
397 var: var.clone(),
398 subpat: Box::new(subpat.make_macro_template(macro_args)),
399 pos,
400 },
401 &Pattern::Var { ref var, pos } => {
402 if let Some(i) = macro_args.iter().position(|arg| arg.0 == var.0) {
403 Pattern::MacroArg { index: i, pos }
404 } else {
405 self.clone()
406 }
407 }
408 &Pattern::And { ref subpats, pos } => {
409 let subpats = subpats
410 .iter()
411 .map(|subpat| subpat.make_macro_template(macro_args))
412 .collect::<Vec<_>>();
413 Pattern::And { subpats, pos }
414 }
415 &Pattern::Term {
416 ref sym,
417 ref args,
418 pos,
419 } => {
420 let args = args
421 .iter()
422 .map(|arg| arg.make_macro_template(macro_args))
423 .collect::<Vec<_>>();
424 Pattern::Term {
425 sym: sym.clone(),
426 args,
427 pos,
428 }
429 }
430
431 &Pattern::Wildcard { .. }
432 | &Pattern::ConstBool { .. }
433 | &Pattern::ConstInt { .. }
434 | &Pattern::ConstPrim { .. } => self.clone(),
435 &Pattern::MacroArg { .. } => unreachable!(),
436 }
437 }
438
439 pub fn subst_macro_args(&self, macro_args: &[Pattern]) -> Option<Pattern> {
440 log!("subst_macro_args: {:?} with {:?}", self, macro_args);
441 match self {
442 &Pattern::BindPattern {
443 ref var,
444 ref subpat,
445 pos,
446 } => Some(Pattern::BindPattern {
447 var: var.clone(),
448 subpat: Box::new(subpat.subst_macro_args(macro_args)?),
449 pos,
450 }),
451 &Pattern::And { ref subpats, pos } => {
452 let subpats = subpats
453 .iter()
454 .map(|subpat| subpat.subst_macro_args(macro_args))
455 .collect::<Option<Vec<_>>>()?;
456 Some(Pattern::And { subpats, pos })
457 }
458 &Pattern::Term {
459 ref sym,
460 ref args,
461 pos,
462 } => {
463 let args = args
464 .iter()
465 .map(|arg| arg.subst_macro_args(macro_args))
466 .collect::<Option<Vec<_>>>()?;
467 Some(Pattern::Term {
468 sym: sym.clone(),
469 args,
470 pos,
471 })
472 }
473
474 &Pattern::Var { .. }
475 | &Pattern::Wildcard { .. }
476 | &Pattern::ConstBool { .. }
477 | &Pattern::ConstInt { .. }
478 | &Pattern::ConstPrim { .. } => Some(self.clone()),
479 &Pattern::MacroArg { index, .. } => macro_args.get(index).cloned(),
480 }
481 }
482
483 pub fn pos(&self) -> Pos {
484 match self {
485 &Pattern::ConstBool { pos, .. }
486 | &Pattern::ConstInt { pos, .. }
487 | &Pattern::ConstPrim { pos, .. }
488 | &Pattern::And { pos, .. }
489 | &Pattern::Term { pos, .. }
490 | &Pattern::BindPattern { pos, .. }
491 | &Pattern::Var { pos, .. }
492 | &Pattern::Wildcard { pos, .. }
493 | &Pattern::MacroArg { pos, .. } => pos,
494 }
495 }
496}
497
498#[derive(Clone, PartialEq, Eq, Debug)]
504pub enum Expr {
505 Term {
507 sym: Ident,
508 args: Vec<Expr>,
509 pos: Pos,
510 },
511 Var { name: Ident, pos: Pos },
513 ConstBool { val: bool, pos: Pos },
515 ConstInt { val: i128, pos: Pos },
517 ConstPrim { val: Ident, pos: Pos },
519 Let {
521 defs: Vec<LetDef>,
522 body: Box<Expr>,
523 pos: Pos,
524 },
525}
526
527impl Expr {
528 pub fn pos(&self) -> Pos {
529 match self {
530 &Expr::Term { pos, .. }
531 | &Expr::Var { pos, .. }
532 | &Expr::ConstBool { pos, .. }
533 | &Expr::ConstInt { pos, .. }
534 | &Expr::ConstPrim { pos, .. }
535 | &Expr::Let { pos, .. } => pos,
536 }
537 }
538
539 pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
541 match self {
542 Expr::Term { sym, args, pos } => {
543 f(*pos, sym);
544 for arg in args {
545 arg.terms(f);
546 }
547 }
548 Expr::Let { defs, body, .. } => {
549 for def in defs {
550 def.val.terms(f);
551 }
552 body.terms(f);
553 }
554 Expr::Var { .. }
555 | Expr::ConstBool { .. }
556 | Expr::ConstInt { .. }
557 | Expr::ConstPrim { .. } => {}
558 }
559 }
560}
561
562#[derive(Clone, PartialEq, Eq, Debug)]
564pub struct LetDef {
565 pub var: Ident,
566 pub ty: Ident,
567 pub val: Box<Expr>,
568 pub pos: Pos,
569}
570
571#[derive(Clone, PartialEq, Eq, Debug)]
574pub enum Extern {
575 Extractor {
577 term: Ident,
579 func: Ident,
581 pos: Pos,
583 infallible: bool,
588 },
589 Constructor {
591 term: Ident,
593 func: Ident,
595 pos: Pos,
597 },
598 Const { name: Ident, ty: Ident, pos: Pos },
600}
601
602#[derive(Clone, Debug, PartialEq, Eq)]
607pub struct Converter {
608 pub term: Ident,
610 pub inner_ty: Ident,
614 pub outer_ty: Ident,
618 pub pos: Pos,
620}