1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
use crate::identifier::Identifier;
use crate::types::Type;
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Expression {
Typed(Type, Box<Expression>),
Bot,
Sample(Type),
StringLiteral(String),
IntegerLiteral(String),
BooleanLiteral(String),
Identifier(Identifier),
TableAccess(Box<Identifier>, Box<Expression>),
Tuple(Vec<Expression>),
List(Vec<Expression>),
FnCall(String, Vec<Expression>),
OracleInvoc(String, Vec<Expression>),
LowLevelOracleInvoc {
name: String,
pkgname: String,
args: Vec<Expression>,
},
None(Type),
Some(Box<Expression>),
Unwrap(Box<Expression>),
Not(Box<Expression>),
Neg(Box<Expression>),
Inv(Box<Expression>),
Add(Box<Expression>, Box<Expression>),
Sub(Box<Expression>, Box<Expression>),
Mul(Box<Expression>, Box<Expression>),
Div(Box<Expression>, Box<Expression>),
Pow(Box<Expression>, Box<Expression>),
Mod(Box<Expression>, Box<Expression>),
Equals(Vec<Expression>),
And(Vec<Expression>),
Or(Vec<Expression>),
Xor(Vec<Expression>),
Sum(Box<Expression>),
Prod(Box<Expression>),
Any(Box<Expression>),
All(Box<Expression>),
Union(Box<Expression>),
Cut(Box<Expression>),
SetDiff(Box<Expression>),
Concat(Vec<Expression>),
}
impl Expression {
pub fn map<F>(&self, f: F) -> Expression
where
F: Fn(Expression) -> Expression + Copy,
{
f(match &self {
Expression::Bot
| Expression::None(_)
| Expression::Sample(_)
| Expression::StringLiteral(_)
| Expression::IntegerLiteral(_)
| Expression::BooleanLiteral(_)
| Expression::Identifier(_) => self.clone(),
Expression::Not(expr) => Expression::Not(Box::new(expr.map(f))),
Expression::Some(expr) => Expression::Some(Box::new(expr.map(f))),
Expression::TableAccess(id, expr) => {
Expression::TableAccess(id.clone(), Box::new(expr.map(f)))
}
Expression::Tuple(exprs) => {
Expression::Tuple(exprs.iter().map(|expr| expr.map(f)).collect())
}
Expression::Equals(exprs) => {
Expression::Equals(exprs.iter().map(|expr| expr.map(f)).collect())
}
Expression::FnCall(name, exprs) => {
Expression::FnCall(name.clone(), exprs.iter().map(|expr| expr.map(f)).collect())
}
Expression::OracleInvoc(name, exprs) => Expression::OracleInvoc(
name.clone(),
exprs.iter().map(|expr| expr.map(f)).collect(),
),
Expression::LowLevelOracleInvoc {
name,
pkgname,
args,
} => Expression::LowLevelOracleInvoc {
name: name.clone(),
pkgname: pkgname.clone(),
args: args.iter().map(|expr| expr.map(f)).collect(),
},
Expression::Typed(t, inner) => {
Expression::Typed(t.clone(), Box::new(f(*inner.clone())))
}
_ => {
panic!("Expression: not implemented: {:#?}", self)
}
})
}
pub fn new_equals(exprs: Vec<&Expression>) -> Expression {
Expression::Equals(exprs.into_iter().cloned().collect())
}
}
#[macro_export]
macro_rules! tuple {
( $($e:expr),* ) => {
{
Expression::Tuple(vec![ $( $e.clone(), )* ])
}
};
}
#[macro_export]
macro_rules! list {
( $($e:expr),* ) => {
{
Expression::List(vec![ $( $e.clone(), )* ])
}
};
}
#[macro_export]
macro_rules! oracleinvoc {
( $name:expr, $($e:expr),* ) => {
{
Expression::OracleInvoc(
$name.to_string(),
vec![ $( $e.clone(), )* ],
)
}
};
}
#[macro_export]
macro_rules! fncall {
( $name:expr, $($e:expr),* ) => {
{
Expression::FnCall(
$name.to_string(),
vec![ $( $e.clone(), )* ],
)
}
};
}