1
use std::cell::RefCell;
2
use std::mem::ManuallyDrop;
3

            
4
use merc_aterm::Symb;
5
use merc_aterm::Symbol;
6
use merc_aterm::SymbolRef;
7
use merc_aterm::Term;
8
use merc_aterm::is_int_term;
9

            
10
thread_local! {
11
    /// Thread local storage that stores various default terms representing data symbols.
12
    pub static DATA_SYMBOLS: RefCell<DataSymbols> = RefCell::new(DataSymbols::new());
13
}
14

            
15
/// Defines default symbols and terms for data elements.
16
///
17
/// For now these mirror the mCRL2 definitions since that is convenient.
18
pub struct DataSymbols {
19
    pub sort_id_symbol: ManuallyDrop<Symbol>,
20
    /// OpId(name, sort)
21
    pub data_function_symbol: ManuallyDrop<Symbol>,
22
    pub data_function_symbol_no_index: ManuallyDrop<Symbol>,
23
    pub data_variable: ManuallyDrop<Symbol>,
24
    pub data_where_clause: ManuallyDrop<Symbol>,
25
    pub data_abstraction: ManuallyDrop<Symbol>,
26

            
27
    /// The data application symbol for a given arity.
28
    data_appl: Vec<Symbol>,
29
}
30

            
31
impl DataSymbols {
32
388
    fn new() -> Self {
33
388
        Self {
34
388
            sort_id_symbol: ManuallyDrop::new(Symbol::new("SortId", 1)),
35
388
            data_function_symbol: ManuallyDrop::new(Symbol::new("OpId", 2)),
36
388
            data_function_symbol_no_index: ManuallyDrop::new(Symbol::new("OpIdNoIndex", 2)),
37
388
            data_variable: ManuallyDrop::new(Symbol::new("DataVarId", 2)),
38
388

            
39
388
            data_where_clause: ManuallyDrop::new(Symbol::new("Where", 2)),
40
388
            data_abstraction: ManuallyDrop::new(Symbol::new("Abstraction", 2)),
41
388
            data_appl: Vec::new(),
42
388
        }
43
388
    }
44

            
45
    pub fn is_sort_expression<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
46
        term.get_head_symbol() == **self.sort_id_symbol
47
    }
48

            
49
    pub fn is_bool_sort<'a, 'b>(&self, _term: &'b impl Term<'a, 'b>) -> bool {
50
        true
51
    }
52

            
53
613022334
    pub fn is_data_variable<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
54
613022334
        term.get_head_symbol() == **self.data_variable
55
613022334
    }
56

            
57
611294151
    pub fn is_data_expression<'a, 'b>(&mut self, term: &'b impl Term<'a, 'b>) -> bool {
58
611294151
        self.is_data_variable(term)
59
610186447
            || self.is_data_function_symbol(term)
60
540930916
            || self.is_data_machine_number(term)
61
540930316
            || self.is_data_abstraction(term)
62
540930316
            || self.is_data_where_clause(term)
63
540930316
            || self.is_data_application(term)
64
611294151
    }
65

            
66
948918450
    pub fn is_data_function_symbol<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
67
948918450
        term.get_head_symbol() == **self.data_function_symbol
68
541478647
            || term.get_head_symbol() == **self.data_function_symbol_no_index
69
948918450
    }
70

            
71
541005847
    pub fn is_data_machine_number<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
72
541005847
        is_int_term(term)
73
541005847
    }
74

            
75
540930316
    pub fn is_data_where_clause<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
76
540930316
        term.get_head_symbol() == **self.data_where_clause
77
540930316
    }
78

            
79
540930316
    pub fn is_data_abstraction<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
80
540930316
        term.get_head_symbol() == **self.data_abstraction
81
540930316
    }
82

            
83
    /// Returns true iff the given term is a data application.
84
856261763
    pub fn is_data_application<'a, 'b>(&mut self, term: &'b impl Term<'a, 'b>) -> bool {
85
856261763
        let arity = term.get_head_symbol().arity();
86
856261763
        term.get_head_symbol() == *self.get_data_application_symbol(arity)
87
856261763
    }
88

            
89
    /// Returns the data application symbol for the given arity, creating it if necessary.
90
890504464
    pub fn get_data_application_symbol(&mut self, arity: usize) -> &SymbolRef<'_> {
91
        // It can be that data_applications are created without create_data_application in the mcrl2 ffi.
92
890505925
        while self.data_appl.len() <= arity {
93
1461
            let symbol = Symbol::new("DataAppl", self.data_appl.len());
94
1461

            
95
1461
            self.data_appl.push(symbol);
96
1461
        }
97

            
98
890504464
        &self.data_appl[arity]
99
890504464
    }
100
}
101

            
102
pub fn is_sort_expression<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
103
    DATA_SYMBOLS.with_borrow(|ds| ds.is_sort_expression(term))
104
}
105

            
106
pub fn is_bool_sort<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
107
    DATA_SYMBOLS.with_borrow(|ds| ds.is_bool_sort(term))
108
}
109

            
110
1728183
pub fn is_data_variable<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
111
1728183
    DATA_SYMBOLS.with_borrow(|ds| ds.is_data_variable(term))
112
1728183
}
113

            
114
611294151
pub fn is_data_expression<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
115
611294151
    DATA_SYMBOLS.with_borrow_mut(|ds| ds.is_data_expression(term))
116
611294151
}
117

            
118
338732003
pub fn is_data_function_symbol<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
119
338732003
    DATA_SYMBOLS.with_borrow(|ds| ds.is_data_function_symbol(term))
120
338732003
}
121

            
122
74931
pub fn is_data_machine_number<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
123
74931
    DATA_SYMBOLS.with_borrow(|ds| ds.is_data_machine_number(term))
124
74931
}
125

            
126
pub fn is_data_where_clause<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
127
    DATA_SYMBOLS.with_borrow(|ds| ds.is_data_where_clause(term))
128
}
129

            
130
pub fn is_data_abstraction<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
131
    DATA_SYMBOLS.with_borrow(|ds| ds.is_data_abstraction(term))
132
}
133

            
134
315331447
pub fn is_data_application<'a, 'b>(term: &'b impl Term<'a, 'b>) -> bool {
135
315331447
    DATA_SYMBOLS.with_borrow_mut(|ds| ds.is_data_application(term))
136
315331447
}