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_variable: ManuallyDrop<Symbol>,
23
    pub data_where_clause: ManuallyDrop<Symbol>,
24
    pub data_abstraction: ManuallyDrop<Symbol>,
25

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

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

            
37
340
            data_where_clause: ManuallyDrop::new(Symbol::new("Where", 2)),
38
340
            data_abstraction: ManuallyDrop::new(Symbol::new("Abstraction", 2)),
39
340
            data_appl: Vec::new(),
40
340
        }
41
340
    }
42

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

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

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

            
55
609973615
    pub fn is_data_expression<'a, 'b>(&mut self, term: &'b impl Term<'a, 'b>) -> bool {
56
609973615
        self.is_data_variable(term)
57
608869767
            || self.is_data_function_symbol(term)
58
539963164
            || self.is_data_machine_number(term)
59
539963164
            || self.is_data_abstraction(term)
60
539963164
            || self.is_data_where_clause(term)
61
539963164
            || self.is_data_application(term)
62
609973615
    }
63

            
64
947371058
    pub fn is_data_function_symbol<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
65
947371058
        term.get_head_symbol() == **self.data_function_symbol
66
947371058
    }
67

            
68
540036895
    pub fn is_data_machine_number<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
69
540036895
        is_int_term(term)
70
540036895
    }
71

            
72
539963164
    pub fn is_data_where_clause<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
73
539963164
        term.get_head_symbol() == **self.data_where_clause
74
539963164
    }
75

            
76
539963164
    pub fn is_data_abstraction<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
77
539963164
        term.get_head_symbol() == **self.data_abstraction
78
539963164
    }
79

            
80
    /// Returns true iff the given term is a data application.
81
854660867
    pub fn is_data_application<'a, 'b>(&self, term: &'b impl Term<'a, 'b>) -> bool {
82
854660867
        if let Some(symbol) = self.data_appl.get(term.get_head_symbol().arity()) {
83
854660811
            return term.get_head_symbol() == **symbol;
84
56
        }
85

            
86
56
        false
87
854660867
    }
88

            
89
34280773
    pub fn get_data_application_symbol(&mut self, arity: usize) -> &SymbolRef<'_> {
90
        // It can be that data_applications are created without create_data_application in the mcrl2 ffi.
91
34282106
        while self.data_appl.len() <= arity {
92
1333
            let symbol = Symbol::new("DataAppl", self.data_appl.len());
93
1333

            
94
1333
            self.data_appl.push(symbol);
95
1333
        }
96

            
97
34280773
        &self.data_appl[arity]
98
34280773
    }
99
}
100

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

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

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

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

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

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

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

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

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