1
use std::hash::Hash;
2

            
3
use merc_utilities::TagIndex;
4

            
5
/// A unique type for declarations.
6
pub struct DeclTag;
7

            
8
/// The index type for a label.
9
pub type DeclId = TagIndex<usize, DeclTag>;
10

            
11
/// A complete mCRL2 process specification.
12
#[derive(Debug, Default, Eq, PartialEq, Hash)]
13
pub struct UntypedProcessSpecification {
14
    pub data_specification: UntypedDataSpecification,
15
    pub global_variables: Vec<IdDecl>,
16
    pub action_declarations: Vec<ActDecl>,
17
    pub process_declarations: Vec<ProcDecl>,
18
    pub init: Option<ProcessExpr>,
19
}
20

            
21
/// An mCRL2 data specification.
22
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
23
pub struct UntypedDataSpecification {
24
    pub sort_declarations: Vec<SortDecl>,
25
    pub constructor_declarations: Vec<IdDecl>,
26
    pub map_declarations: Vec<IdDecl>,
27
    pub equation_declarations: Vec<EqnSpec>,
28
}
29

            
30
impl UntypedDataSpecification {
31
    /// Returns true if the data specification is empty.
32
    pub fn is_empty(&self) -> bool {
33
        self.sort_declarations.is_empty()
34
            && self.constructor_declarations.is_empty()
35
            && self.map_declarations.is_empty()
36
            && self.equation_declarations.is_empty()
37
    }
38

            
39
    /// Merges another data specification into the current one.
40
    pub fn merge(&mut self, other_spec: &UntypedDataSpecification) {
41
        self.sort_declarations.extend_from_slice(&other_spec.sort_declarations);
42
        self.constructor_declarations
43
            .extend_from_slice(&other_spec.constructor_declarations);
44
        self.map_declarations.extend_from_slice(&other_spec.map_declarations);
45
        self.equation_declarations
46
            .extend_from_slice(&other_spec.equation_declarations);
47
    }
48
}
49

            
50
/// An mCRL2 parameterised boolean equation system (PBES).
51
#[derive(Debug, Default, Eq, PartialEq, Hash)]
52
pub struct UntypedPbes {
53
    pub data_specification: UntypedDataSpecification,
54
    pub global_variables: Vec<IdDecl>,
55
    pub equations: Vec<PbesEquation>,
56
    pub init: PropVarInst,
57
}
58

            
59
/// An mCRL2 parameterised boolean equation system (PBES).
60
#[derive(Debug, Default, Eq, PartialEq, Hash)]
61
pub struct UntypedPres {
62
    pub data_specification: UntypedDataSpecification,
63
    pub global_variables: Vec<IdDecl>,
64
    pub equations: Vec<PresEquation>,
65
    pub init: PropVarInst,
66
}
67

            
68
#[derive(Debug, Eq, PartialEq, Hash)]
69
pub struct PropVarDecl {
70
    pub identifier: String,
71
    pub parameters: Vec<IdDecl>,
72
    pub span: Span,
73
}
74

            
75
#[derive(Debug, Default, Eq, PartialEq, Hash)]
76
pub struct PropVarInst {
77
    pub identifier: String,
78
    pub arguments: Vec<DataExpr>,
79
}
80

            
81
/// A declaration of an identifier with its sort.
82
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
83
pub struct IdDecl {
84
    /// Identifier being declared
85
    pub identifier: String,
86
    /// Sort expression for this identifier
87
    pub sort: SortExpression,
88
    /// Source location information
89
    pub span: Span,
90
    /// Unique ID assigned to this declaration during name resolution.
91
    pub id: Option<DeclId>,
92
}
93

            
94
impl IdDecl {
95
    /// Creates a new identifier declaration with the given identifier, sort, and span.
96
82170
    pub fn new(identifier: String, sort: SortExpression, span: Span) -> Self {
97
82170
        IdDecl {
98
82170
            identifier,
99
82170
            sort,
100
82170
            span,
101
82170
            id: None,
102
82170
        }
103
82170
    }
104
}
105

            
106
/// Expression representing a sort (type).
107
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
108
pub enum SortExpression {
109
    /// Product of two sorts (A # B)
110
    Product {
111
        lhs: Box<SortExpression>,
112
        rhs: Box<SortExpression>,
113
    },
114
    /// Function sort (A -> B)
115
    Function {
116
        domain: Box<SortExpression>,
117
        range: Box<SortExpression>,
118
    },
119
    Struct {
120
        inner: Vec<ConstructorDecl>,
121
    },
122
    /// Reference to a named sort    
123
    Reference(String),
124
    /// Built-in simple sort
125
    Simple(Sort),
126
    /// Parameterized complex sort
127
    Complex(ComplexSort, Box<SortExpression>),
128
}
129

            
130
/// Constructor declaration
131
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
132
pub struct ConstructorDecl {
133
    pub name: String,
134
    pub args: Vec<(Option<String>, SortExpression)>,
135
    pub projection: Option<String>,
136
}
137

            
138
/// Built-in simple sorts.
139
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
140
pub enum Sort {
141
    Bool,
142
    Pos,
143
    Int,
144
    Nat,
145
    Real,
146
}
147

            
148
/// Complex (parameterized) sorts.
149
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
150
pub enum ComplexSort {
151
    List,
152
    Set,
153
    FSet,
154
    FBag,
155
    Bag,
156
}
157

            
158
/// Sort declaration
159
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
160
pub struct SortDecl {
161
    /// Sort identifier
162
    pub identifier: String,
163
    /// Sort expression (if structured)
164
    pub expr: Option<SortExpression>,
165
    /// Where the sort is defined
166
    pub span: Span,
167
    /// Unique ID assigned to this declaration during name resolution.
168
    pub id: Option<DeclId>,
169
}
170

            
171
impl SortDecl {
172
    /// Creates a new sort declaration with the given identifier, expression, and span.
173
5154
    pub fn new(identifier: String, expr: Option<SortExpression>, span: Span) -> Self {
174
5154
        SortDecl {
175
5154
            identifier,
176
5154
            expr,
177
5154
            span,
178
5154
            id: None,
179
5154
        }
180
5154
    }
181
}
182

            
183
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
184
pub struct EqnSpec {
185
    pub variables: Vec<IdDecl>,
186
    pub equations: Vec<EqnDecl>,
187
}
188

            
189
/// Equation declaration
190
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
191
pub struct EqnDecl {
192
    pub condition: Option<DataExpr>,
193
    pub lhs: DataExpr,
194
    pub rhs: DataExpr,
195
    pub span: Span,
196
}
197

            
198
/// Action declaration
199
#[derive(Debug, Eq, PartialEq, Hash)]
200
pub struct ActDecl {
201
    pub identifier: String,
202
    pub args: Vec<SortExpression>,
203
    pub span: Span,
204
}
205

            
206
/// Process declaration
207
#[derive(Debug, Eq, PartialEq, Hash)]
208
pub struct ProcDecl {
209
    pub identifier: String,
210
    pub params: Vec<IdDecl>,
211
    pub body: ProcessExpr,
212
    pub span: Span,
213
}
214

            
215
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
216
pub enum DataExprUnaryOp {
217
    Negation,
218
    Minus,
219
    Size,
220
}
221

            
222
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
223
pub enum DataExprBinaryOp {
224
    Conj,
225
    Disj,
226
    Implies,
227
    Equal,
228
    NotEqual,
229
    LessThan,
230
    LessEqual,
231
    GreaterThan,
232
    GreaterEqual,
233
    Cons,
234
    Snoc,
235
    In,
236
    Concat,
237
    Add,
238
    Subtract,
239
    Div,
240
    IntDiv,
241
    Mod,
242
    Multiply,
243
    At,
244
}
245

            
246
/// Data expression
247
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
248
pub enum DataExpr {
249
    Id(String),
250
    Number(String), // Is string because the number can be any size.
251
    Bool(bool),
252
    Application {
253
        function: Box<DataExpr>,
254
        arguments: Vec<DataExpr>,
255
    },
256
    EmptyList,
257
    List(Vec<DataExpr>),
258
    EmptySet,
259
    Set(Vec<DataExpr>),
260
    EmptyBag,
261
    Bag(Vec<BagElement>),
262
    SetBagComp {
263
        variable: IdDecl,
264
        predicate: Box<DataExpr>,
265
    },
266
    Lambda {
267
        variables: Vec<IdDecl>,
268
        body: Box<DataExpr>,
269
    },
270
    Quantifier {
271
        op: Quantifier,
272
        variables: Vec<IdDecl>,
273
        body: Box<DataExpr>,
274
    },
275
    Unary {
276
        op: DataExprUnaryOp,
277
        expr: Box<DataExpr>,
278
    },
279
    Binary {
280
        op: DataExprBinaryOp,
281
        lhs: Box<DataExpr>,
282
        rhs: Box<DataExpr>,
283
    },
284
    FunctionUpdate {
285
        expr: Box<DataExpr>,
286
        update: Box<DataExprUpdate>,
287
    },
288
    Whr {
289
        expr: Box<DataExpr>,
290
        assignments: Vec<Assignment>,
291
    },
292
}
293

            
294
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
295
pub struct BagElement {
296
    pub expr: DataExpr,
297
    pub multiplicity: DataExpr,
298
}
299

            
300
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
301
pub struct DataExprUpdate {
302
    pub expr: DataExpr,
303
    pub update: DataExpr,
304
}
305

            
306
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
307
pub struct Assignment {
308
    pub identifier: String,
309
    pub expr: DataExpr,
310
}
311

            
312
#[derive(Debug, Eq, PartialEq, Hash)]
313
pub enum ProcExprBinaryOp {
314
    Sequence,
315
    Choice,
316
    Parallel,
317
    LeftMerge,
318
    CommMerge,
319
}
320

            
321
/// Process expression
322
#[derive(Debug, Eq, PartialEq, Hash)]
323
pub enum ProcessExpr {
324
    Id(String, Vec<Assignment>),
325
    Action(String, Vec<DataExpr>),
326
    Delta,
327
    Tau,
328
    Sum {
329
        variables: Vec<IdDecl>,
330
        operand: Box<ProcessExpr>,
331
    },
332
    Dist {
333
        variables: Vec<IdDecl>,
334
        expr: DataExpr,
335
        operand: Box<ProcessExpr>,
336
    },
337
    Binary {
338
        op: ProcExprBinaryOp,
339
        lhs: Box<ProcessExpr>,
340
        rhs: Box<ProcessExpr>,
341
    },
342
    Hide {
343
        actions: Vec<String>,
344
        operand: Box<ProcessExpr>,
345
    },
346
    Rename {
347
        renames: Vec<Rename>,
348
        operand: Box<ProcessExpr>,
349
    },
350
    Allow {
351
        actions: Vec<MultiActionLabel>,
352
        operand: Box<ProcessExpr>,
353
    },
354
    Block {
355
        actions: Vec<String>,
356
        operand: Box<ProcessExpr>,
357
    },
358
    Comm {
359
        comm: Vec<Comm>,
360
        operand: Box<ProcessExpr>,
361
    },
362
    Condition {
363
        condition: DataExpr,
364
        then: Box<ProcessExpr>,
365
        else_: Option<Box<ProcessExpr>>,
366
    },
367
    At {
368
        expr: Box<ProcessExpr>,
369
        operand: DataExpr,
370
    },
371
}
372

            
373
#[derive(Debug, Eq, PartialEq, Hash)]
374
pub struct UntypedStateFrmSpec {
375
    pub data_specification: UntypedDataSpecification,
376
    pub action_declarations: Vec<ActDecl>,
377
    pub formula: StateFrm,
378
}
379

            
380
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
381
pub enum StateFrmUnaryOp {
382
    Minus,
383
    Negation,
384
}
385

            
386
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
387
pub enum StateFrmOp {
388
    Addition,
389
    Implies,
390
    Disjunction,
391
    Conjunction,
392
}
393

            
394
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
395
pub enum FixedPointOperator {
396
    Least,
397
    Greatest,
398
}
399

            
400
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
401
pub struct StateVarDecl {
402
    pub identifier: String,
403
    pub arguments: Vec<StateVarAssignment>,
404
    pub span: Span,
405
}
406

            
407
impl StateVarDecl {
408
    /// Creates a new state variable declaration.
409
12828
    pub fn new(identifier: String, arguments: Vec<StateVarAssignment>) -> Self {
410
12828
        StateVarDecl {
411
12828
            identifier,
412
12828
            arguments,
413
12828
            span: Span::default(),
414
12828
        }
415
12828
    }
416
}
417

            
418
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
419
pub struct StateVarAssignment {
420
    pub identifier: String,
421
    pub sort: SortExpression,
422
    pub expr: DataExpr,
423
}
424

            
425
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
426
pub enum ModalityOperator {
427
    Diamond,
428
    Box,
429
}
430

            
431
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
432
pub enum StateFrm {
433
    True,
434
    False,
435
    Delay(DataExpr),
436
    Yaled(DataExpr),
437
    Id(String, Vec<DataExpr>),
438
    DataValExprLeftMult(DataExpr, Box<StateFrm>),
439
    DataValExprRightMult(Box<StateFrm>, DataExpr),
440
    DataValExpr(DataExpr),
441
    Modality {
442
        operator: ModalityOperator,
443
        formula: RegFrm,
444
        expr: Box<StateFrm>,
445
    },
446
    Unary {
447
        op: StateFrmUnaryOp,
448
        expr: Box<StateFrm>,
449
    },
450
    Binary {
451
        op: StateFrmOp,
452
        lhs: Box<StateFrm>,
453
        rhs: Box<StateFrm>,
454
    },
455
    Quantifier {
456
        quantifier: Quantifier,
457
        variables: Vec<IdDecl>,
458
        body: Box<StateFrm>,
459
    },
460
    Bound {
461
        bound: Bound,
462
        variables: Vec<IdDecl>,
463
        body: Box<StateFrm>,
464
    },
465
    FixedPoint {
466
        operator: FixedPointOperator,
467
        variable: StateVarDecl,
468
        body: Box<StateFrm>,
469
    },
470
}
471

            
472
/// Represents a multi action label `a | b | c ...`.
473
#[derive(Debug, Eq, PartialEq, Hash)]
474
pub struct MultiActionLabel {
475
    pub actions: Vec<String>,
476
}
477

            
478
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
479
pub struct Action {
480
    pub id: String,
481
    pub args: Vec<DataExpr>,
482
}
483

            
484
impl Action {
485
    /// Creates a new action from an identifier and a list of arguments.
486
6696
    pub fn new(id: String, args: Vec<DataExpr>) -> Self {
487
6696
        Action { id, args }
488
6696
    }
489
}
490

            
491
#[derive(Clone, Debug, Eq)]
492
pub struct MultiAction {
493
    pub actions: Vec<Action>,
494
}
495

            
496
impl MultiAction {
497
    /// Creates a new multi-action from a list of actions.
498
8226
    pub fn new(actions: Vec<Action>) -> Self {
499
8226
        MultiAction { actions }
500
8226
    }
501

            
502
    /// Creates the empty multi-action, which represents the tau action.
503
3690
    pub fn tau() -> Self {
504
3690
        MultiAction { actions: Vec::new() }
505
3690
    }
506
}
507

            
508
impl PartialEq for MultiAction {
509
114876
    fn eq(&self, other: &Self) -> bool {
510
        // Check whether both multi-actions contain the same actions
511
114876
        if self.actions.len() != other.actions.len() {
512
39180
            return false;
513
75696
        }
514

            
515
        // Map every action onto the other, equal length means they must be the same.
516
75696
        for action in self.actions.iter() {
517
56922
            if !other.actions.contains(action) {
518
30684
                return false;
519
26238
            }
520
        }
521

            
522
45012
        true
523
114876
    }
524
}
525

            
526
impl Hash for MultiAction {
527
15597
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
528
15597
        let mut actions = self.actions.clone();
529
        // Sort the action ids to ensure that the hash is independent of the order.
530
15597
        actions.sort();
531
15597
        for action in actions {
532
8557
            action.hash(state);
533
8557
        }
534
15597
    }
535
}
536

            
537
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
538
pub enum Quantifier {
539
    Exists,
540
    Forall,
541
}
542

            
543
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
544
pub enum ActFrmBinaryOp {
545
    Implies,
546
    Union,
547
    Intersect,
548
}
549

            
550
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
551
pub enum ActFrm {
552
    True,
553
    False,
554
    MultAct(MultiAction),
555
    DataExprVal(DataExpr),
556
    Negation(Box<ActFrm>),
557
    Quantifier {
558
        quantifier: Quantifier,
559
        variables: Vec<IdDecl>,
560
        body: Box<ActFrm>,
561
    },
562
    Binary {
563
        op: ActFrmBinaryOp,
564
        lhs: Box<ActFrm>,
565
        rhs: Box<ActFrm>,
566
    },
567
}
568

            
569
#[derive(Debug, Eq, PartialEq, Hash)]
570
pub enum PbesExpr {
571
    DataValExpr(DataExpr),
572
    PropVarInst(PropVarInst),
573
    Quantifier {
574
        quantifier: Quantifier,
575
        variables: Vec<IdDecl>,
576
        body: Box<PbesExpr>,
577
    },
578
    Negation(Box<PbesExpr>),
579
    Binary {
580
        op: PbesExprBinaryOp,
581
        lhs: Box<PbesExpr>,
582
        rhs: Box<PbesExpr>,
583
    },
584
    True,
585
    False,
586
}
587

            
588
#[derive(Debug, Eq, PartialEq, Hash)]
589
pub enum Eq {
590
    EqInf,
591
    EqnInf,
592
}
593

            
594
#[derive(Debug, Eq, PartialEq, Hash)]
595
pub enum Condition {
596
    Condsm,
597
    Condeq,
598
}
599

            
600
// TODO: What should this be called?
601
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
602
pub enum Bound {
603
    Inf,
604
    Sup,
605
    Sum,
606
}
607

            
608
#[derive(Debug, Eq, PartialEq, Hash)]
609
pub enum PresExprBinaryOp {
610
    Implies,
611
    Disjunction,
612
    Conjunction,
613
    Add,
614
}
615

            
616
#[derive(Debug, Eq, PartialEq, Hash)]
617
pub enum PresExpr {
618
    DataValExpr(DataExpr),
619
    PropVarInst(PropVarInst),
620
    RightConstantMultiply {
621
        expr: Box<PresExpr>,
622
        constant: DataExpr,
623
    },
624
    LeftConstantMultiply {
625
        constant: DataExpr,
626
        expr: Box<PresExpr>,
627
    },
628
    Bound {
629
        op: Bound,
630
        variables: Vec<IdDecl>,
631
        expr: Box<PresExpr>,
632
    },
633
    Equal {
634
        eq: Eq,
635
        body: Box<PresExpr>,
636
    },
637
    Condition {
638
        condition: Condition,
639
        lhs: Box<PresExpr>,
640
        then: Box<PresExpr>,
641
        else_: Box<PresExpr>,
642
    },
643
    Negation(Box<PresExpr>),
644
    Binary {
645
        op: PresExprBinaryOp,
646
        lhs: Box<PresExpr>,
647
        rhs: Box<PresExpr>,
648
    },
649
    True,
650
    False,
651
}
652

            
653
#[derive(Debug, Eq, PartialEq, Hash)]
654
pub struct PbesEquation {
655
    pub operator: FixedPointOperator,
656
    pub variable: PropVarDecl,
657
    pub formula: PbesExpr,
658
    pub span: Span,
659
}
660

            
661
#[derive(Debug, Eq, PartialEq, Hash)]
662
pub enum PbesExprBinaryOp {
663
    Implies,
664
    Disjunction,
665
    Conjunction,
666
}
667

            
668
#[derive(Debug, Eq, PartialEq, Hash)]
669
pub struct PresEquation {
670
    pub operator: FixedPointOperator,
671
    pub variable: PropVarDecl,
672
    pub formula: PresExpr,
673
    pub span: Span,
674
}
675

            
676
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
677
pub enum RegFrm {
678
    Action(ActFrm),
679
    Iteration(Box<RegFrm>),
680
    Plus(Box<RegFrm>),
681
    Sequence { lhs: Box<RegFrm>, rhs: Box<RegFrm> },
682
    Choice { lhs: Box<RegFrm>, rhs: Box<RegFrm> },
683
}
684

            
685
#[derive(Debug, Eq, PartialEq, Hash)]
686
pub struct Rename {
687
    pub from: String,
688
    pub to: String,
689
}
690

            
691
#[derive(Debug, Eq, PartialEq, Hash)]
692
pub struct Comm {
693
    pub from: MultiActionLabel,
694
    pub to: String,
695
}
696

            
697
#[derive(Debug, Eq, PartialEq, Hash)]
698
pub struct UntypedActionRenameSpec {
699
    pub data_specification: UntypedDataSpecification,
700
    pub action_declarations: Vec<ActDecl>,
701
    pub rename_declarations: Vec<ActionRenameDecl>,
702
}
703

            
704
#[derive(Debug, Eq, PartialEq, Hash)]
705
pub struct ActionRenameDecl {
706
    pub variables_specification: Vec<IdDecl>,
707
    pub rename_rule: ActionRenameRule,
708
}
709

            
710
#[derive(Debug, Eq, PartialEq, Hash)]
711
pub struct ActionRenameRule {
712
    pub condition: Option<DataExpr>,
713
    pub action: Action,
714
    pub rhs: ActionRHS,
715
}
716

            
717
#[derive(Debug, Eq, PartialEq, Hash)]
718
pub enum ActionRHS {
719
    Tau,
720
    Delta,
721
    Action(Action),
722
}
723

            
724
/// Source location information, spanning from start to end in the source text.
725
#[derive(Clone, Default, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
726
pub struct Span {
727
    pub start: usize,
728
    pub end: usize,
729
}
730

            
731
impl From<pest::Span<'_>> for Span {
732
174764
    fn from(span: pest::Span) -> Self {
733
174764
        Span {
734
174764
            start: span.start(),
735
174764
            end: span.end(),
736
174764
        }
737
174764
    }
738
}