@@ -119,7 +119,7 @@ pub enum ExprRef<'a> {
119
119
}
120
120
121
121
/// An expression (either [`BoolExpr`] or [`NumExpr`])
122
- #[ derive( Clone , Debug , derive_more:: From ) ]
122
+ #[ derive( Clone , Debug , derive_more:: From , derive_more :: TryInto ) ]
123
123
pub enum Expr {
124
124
/// A reference to a [`BoolExpr`]
125
125
Bool ( BoolExpr ) ,
@@ -146,220 +146,284 @@ impl ExprBuilder {
146
146
}
147
147
148
148
/// Declare a constant boolean expression
149
- pub fn bool_const ( & self , value : bool ) -> Box < BoolExpr > {
150
- Box :: new ( BoolLit ( value) . into ( ) )
149
+ pub fn bool_const ( & self , value : bool ) -> BoolExpr {
150
+ BoolLit ( value) . into ( )
151
151
}
152
152
153
153
/// Declare a constant integer expression
154
- pub fn int_const ( & self , value : i64 ) -> Box < NumExpr > {
155
- Box :: new ( IntLit ( value) . into ( ) )
154
+ pub fn int_const ( & self , value : i64 ) -> NumExpr {
155
+ IntLit ( value) . into ( )
156
156
}
157
157
158
158
/// Declare a constant unsigned integer expression
159
- pub fn uint_const ( & self , value : u64 ) -> Box < NumExpr > {
160
- Box :: new ( UIntLit ( value) . into ( ) )
159
+ pub fn uint_const ( & self , value : u64 ) -> NumExpr {
160
+ UIntLit ( value) . into ( )
161
161
}
162
162
163
163
/// Declare a constant floating point expression
164
- pub fn float_const ( & self , value : f64 ) -> Box < NumExpr > {
165
- Box :: new ( FloatLit ( value) . into ( ) )
164
+ pub fn float_const ( & self , value : f64 ) -> NumExpr {
165
+ FloatLit ( value) . into ( )
166
166
}
167
167
168
168
/// Declare a boolean variable
169
- pub fn bool_var ( & mut self , name : String ) -> ArgusResult < Box < BoolExpr > > {
169
+ pub fn bool_var ( & mut self , name : String ) -> ArgusResult < BoolExpr > {
170
170
if self . declarations . insert ( name. clone ( ) ) {
171
- Ok ( Box :: new ( ( BoolVar { name } ) . into ( ) ) )
171
+ Ok ( ( BoolVar { name } ) . into ( ) )
172
172
} else {
173
173
Err ( Error :: IdentifierRedeclaration )
174
174
}
175
175
}
176
176
177
177
/// Declare a integer variable
178
- pub fn int_var ( & mut self , name : String ) -> ArgusResult < Box < NumExpr > > {
178
+ pub fn int_var ( & mut self , name : String ) -> ArgusResult < NumExpr > {
179
179
if self . declarations . insert ( name. clone ( ) ) {
180
- Ok ( Box :: new ( ( IntVar { name } ) . into ( ) ) )
180
+ Ok ( ( IntVar { name } ) . into ( ) )
181
181
} else {
182
182
Err ( Error :: IdentifierRedeclaration )
183
183
}
184
184
}
185
185
186
186
/// Declare a unsigned integer variable
187
- pub fn uint_var ( & mut self , name : String ) -> ArgusResult < Box < NumExpr > > {
187
+ pub fn uint_var ( & mut self , name : String ) -> ArgusResult < NumExpr > {
188
188
if self . declarations . insert ( name. clone ( ) ) {
189
- Ok ( Box :: new ( ( UIntVar { name } ) . into ( ) ) )
189
+ Ok ( ( UIntVar { name } ) . into ( ) )
190
190
} else {
191
191
Err ( Error :: IdentifierRedeclaration )
192
192
}
193
193
}
194
194
195
195
/// Declare a floating point variable
196
- pub fn float_var ( & mut self , name : String ) -> ArgusResult < Box < NumExpr > > {
196
+ pub fn float_var ( & mut self , name : String ) -> ArgusResult < NumExpr > {
197
197
if self . declarations . insert ( name. clone ( ) ) {
198
- Ok ( Box :: new ( ( FloatVar { name } ) . into ( ) ) )
198
+ Ok ( ( FloatVar { name } ) . into ( ) )
199
199
} else {
200
200
Err ( Error :: IdentifierRedeclaration )
201
201
}
202
202
}
203
203
204
204
/// Create a [`NumExpr::Neg`] expression
205
- pub fn make_neg ( & self , arg : Box < NumExpr > ) -> Box < NumExpr > {
206
- Box :: new ( ( Neg { arg } ) . into ( ) )
205
+ pub fn make_neg ( & self , arg : Box < NumExpr > ) -> NumExpr {
206
+ ( Neg { arg } ) . into ( )
207
207
}
208
208
209
209
/// Create a [`NumExpr::Add`] expression
210
- pub fn make_add < I > ( & self , args : I ) -> ArgusResult < Box < NumExpr > >
210
+ pub fn make_add < I > ( & self , args : I ) -> ArgusResult < NumExpr >
211
211
where
212
212
I : IntoIterator < Item = NumExpr > ,
213
213
{
214
- let args: Vec < _ > = args. into_iter ( ) . collect ( ) ;
215
- if args. len ( ) < 2 {
214
+ let mut new_args = Vec :: < NumExpr > :: new ( ) ;
215
+ for arg in args. into_iter ( ) {
216
+ // Flatten the args if there is an Add
217
+ if let NumExpr :: Add ( Add { args } ) = arg {
218
+ new_args. extend ( args. into_iter ( ) ) ;
219
+ } else {
220
+ new_args. push ( arg) ;
221
+ }
222
+ }
223
+ if new_args. len ( ) < 2 {
216
224
Err ( Error :: IncompleteArgs )
217
225
} else {
218
- Ok ( Box :: new ( ( Add { args } ) . into ( ) ) )
226
+ Ok ( ( Add { args : new_args } ) . into ( ) )
219
227
}
220
228
}
221
229
222
230
/// Create a [`NumExpr::Mul`] expression
223
- pub fn make_mul < I > ( & self , args : I ) -> ArgusResult < Box < NumExpr > >
231
+ pub fn make_mul < I > ( & self , args : I ) -> ArgusResult < NumExpr >
224
232
where
225
233
I : IntoIterator < Item = NumExpr > ,
226
234
{
227
- let args: Vec < _ > = args. into_iter ( ) . collect ( ) ;
228
- if args. len ( ) < 2 {
235
+ let mut new_args = Vec :: < NumExpr > :: new ( ) ;
236
+ for arg in args. into_iter ( ) {
237
+ // Flatten the args if there is a Mul
238
+ if let NumExpr :: Mul ( Mul { args } ) = arg {
239
+ new_args. extend ( args. into_iter ( ) ) ;
240
+ } else {
241
+ new_args. push ( arg) ;
242
+ }
243
+ }
244
+ if new_args. len ( ) < 2 {
229
245
Err ( Error :: IncompleteArgs )
230
246
} else {
231
- Ok ( Box :: new ( ( Mul { args } ) . into ( ) ) )
247
+ Ok ( ( Mul { args : new_args } ) . into ( ) )
232
248
}
233
249
}
234
250
251
+ /// Create a [`NumExpr::Sub`] expression
252
+ pub fn make_sub ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> NumExpr {
253
+ ( Sub { lhs, rhs } ) . into ( )
254
+ }
255
+
235
256
/// Create a [`NumExpr::Div`] expression
236
- pub fn make_div ( & self , dividend : Box < NumExpr > , divisor : Box < NumExpr > ) -> Box < NumExpr > {
237
- Box :: new ( ( Div { dividend, divisor } ) . into ( ) )
257
+ pub fn make_div ( & self , dividend : Box < NumExpr > , divisor : Box < NumExpr > ) -> NumExpr {
258
+ ( Div { dividend, divisor } ) . into ( )
238
259
}
239
260
240
261
/// Create a [`BoolExpr::Cmp`] expression
241
- pub fn make_cmp ( & self , op : Ordering , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
242
- Box :: new ( ( Cmp { op, lhs, rhs } ) . into ( ) )
262
+ pub fn make_cmp ( & self , op : Ordering , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
263
+ ( Cmp { op, lhs, rhs } ) . into ( )
243
264
}
244
265
245
266
/// Create a "less than" ([`BoolExpr::Cmp`]) expression
246
- pub fn make_lt ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
267
+ pub fn make_lt ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
247
268
self . make_cmp ( Ordering :: Less { strict : true } , lhs, rhs)
248
269
}
249
270
250
271
/// Create a "less than or equal" ([`BoolExpr::Cmp`]) expression
251
- pub fn make_le ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
272
+ pub fn make_le ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
252
273
self . make_cmp ( Ordering :: Less { strict : false } , lhs, rhs)
253
274
}
254
275
255
276
/// Create a "greater than" ([`BoolExpr::Cmp`]) expression
256
- pub fn make_gt ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
277
+ pub fn make_gt ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
257
278
self . make_cmp ( Ordering :: Greater { strict : true } , lhs, rhs)
258
279
}
259
280
260
281
/// Create a "greater than or equal" ([`BoolExpr::Cmp`]) expression
261
- pub fn make_ge ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
282
+ pub fn make_ge ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
262
283
self . make_cmp ( Ordering :: Greater { strict : false } , lhs, rhs)
263
284
}
264
285
265
286
/// Create a "equals" ([`BoolExpr::Cmp`]) expression
266
- pub fn make_eq ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
287
+ pub fn make_eq ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
267
288
self . make_cmp ( Ordering :: Eq , lhs, rhs)
268
289
}
269
290
270
291
/// Create a "not equals" ([`BoolExpr::Cmp`]) expression
271
- pub fn make_neq ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> Box < BoolExpr > {
292
+ pub fn make_neq ( & self , lhs : Box < NumExpr > , rhs : Box < NumExpr > ) -> BoolExpr {
272
293
self . make_cmp ( Ordering :: NotEq , lhs, rhs)
273
294
}
274
295
275
296
/// Create a [`BoolExpr::Not`] expression.
276
- pub fn make_not ( & self , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
277
- Box :: new ( ( Not { arg } ) . into ( ) )
297
+ pub fn make_not ( & self , arg : Box < BoolExpr > ) -> BoolExpr {
298
+ ( Not { arg } ) . into ( )
278
299
}
279
300
280
301
/// Create a [`BoolExpr::Or`] expression.
281
- pub fn make_or < I > ( & self , args : I ) -> ArgusResult < Box < BoolExpr > >
302
+ pub fn make_or < I > ( & self , args : I ) -> ArgusResult < BoolExpr >
282
303
where
283
304
I : IntoIterator < Item = BoolExpr > ,
284
305
{
285
- let args: Vec < _ > = args. into_iter ( ) . collect ( ) ;
286
- if args. len ( ) < 2 {
306
+ let mut new_args = Vec :: < BoolExpr > :: new ( ) ;
307
+ for arg in args. into_iter ( ) {
308
+ // Flatten the args if there is an Or
309
+ if let BoolExpr :: Or ( Or { args } ) = arg {
310
+ new_args. extend ( args. into_iter ( ) ) ;
311
+ } else {
312
+ new_args. push ( arg) ;
313
+ }
314
+ }
315
+ if new_args. len ( ) < 2 {
287
316
Err ( Error :: IncompleteArgs )
288
317
} else {
289
- Ok ( Box :: new ( ( Or { args } ) . into ( ) ) )
318
+ Ok ( ( Or { args : new_args } ) . into ( ) )
290
319
}
291
320
}
292
321
293
322
/// Create a [`BoolExpr::And`] expression.
294
- pub fn make_and < I > ( & self , args : I ) -> ArgusResult < Box < BoolExpr > >
323
+ pub fn make_and < I > ( & self , args : I ) -> ArgusResult < BoolExpr >
295
324
where
296
325
I : IntoIterator < Item = BoolExpr > ,
297
326
{
298
- let args: Vec < _ > = args. into_iter ( ) . collect ( ) ;
299
- if args. len ( ) < 2 {
327
+ let mut new_args = Vec :: < BoolExpr > :: new ( ) ;
328
+ for arg in args. into_iter ( ) {
329
+ // Flatten the args if there is an And
330
+ if let BoolExpr :: And ( And { args } ) = arg {
331
+ new_args. extend ( args. into_iter ( ) ) ;
332
+ } else {
333
+ new_args. push ( arg) ;
334
+ }
335
+ }
336
+ if new_args. len ( ) < 2 {
300
337
Err ( Error :: IncompleteArgs )
301
338
} else {
302
- Ok ( Box :: new ( ( And { args } ) . into ( ) ) )
339
+ Ok ( ( And { args : new_args } ) . into ( ) )
303
340
}
304
341
}
305
342
343
+ /// Create an expression equivalent to `lhs -> rhs`.
344
+ ///
345
+ /// This essentially breaks down the expression as `~lhs | rhs`.
346
+ #[ allow( clippy:: boxed_local) ]
347
+ pub fn make_implies ( & self , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> ArgusResult < BoolExpr > {
348
+ let np = self . make_not ( lhs) ;
349
+ self . make_or ( [ np, * rhs] )
350
+ }
351
+
352
+ /// Create an expression equivalent to `lhs <-> rhs`.
353
+ ///
354
+ /// This essentially breaks down the expression as `(lhs & rhs) | (~lhs & ~rhs)`.
355
+ pub fn make_equiv ( & self , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> ArgusResult < BoolExpr > {
356
+ let np = self . make_not ( lhs. clone ( ) ) ;
357
+ let nq = self . make_not ( rhs. clone ( ) ) ;
358
+
359
+ let npnq = self . make_and ( [ np, nq] ) ?;
360
+ let pq = self . make_and ( [ * lhs, * rhs] ) ?;
361
+
362
+ self . make_or ( [ pq, npnq] )
363
+ }
364
+
365
+ /// Create an expression equivalent to `lhs ^ rhs`.
366
+ ///
367
+ /// This essentially breaks down the expression as `~(lhs <-> rhs)`.
368
+ pub fn make_xor ( & self , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> ArgusResult < BoolExpr > {
369
+ Ok ( self . make_not ( Box :: new ( self . make_equiv ( lhs, rhs) ?) ) )
370
+ }
371
+
306
372
/// Create a [`BoolExpr::Next`] expression.
307
- pub fn make_next ( & self , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
308
- Box :: new ( ( Next { arg } ) . into ( ) )
373
+ pub fn make_next ( & self , arg : Box < BoolExpr > ) -> BoolExpr {
374
+ ( Next { arg } ) . into ( )
309
375
}
310
376
311
377
/// Create a [`BoolExpr::Oracle`] expression.
312
- pub fn make_oracle ( & self , steps : usize , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
313
- Box :: new ( ( Oracle { steps, arg } ) . into ( ) )
378
+ pub fn make_oracle ( & self , steps : usize , arg : Box < BoolExpr > ) -> BoolExpr {
379
+ if steps == 1 {
380
+ self . make_next ( arg)
381
+ } else {
382
+ ( Oracle { steps, arg } ) . into ( )
383
+ }
314
384
}
315
385
316
386
/// Create a [`BoolExpr::Always`] expression.
317
- pub fn make_always ( & self , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
318
- Box :: new (
319
- ( Always {
320
- arg,
321
- interval : ( ..) . into ( ) ,
322
- } )
323
- . into ( ) ,
324
- )
387
+ pub fn make_always ( & self , arg : Box < BoolExpr > ) -> BoolExpr {
388
+ ( Always {
389
+ arg,
390
+ interval : ( ..) . into ( ) ,
391
+ } )
392
+ . into ( )
325
393
}
326
394
327
395
/// Create a [`BoolExpr::Always`] expression with an interval.
328
- pub fn make_timed_always ( & self , interval : Interval , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
329
- Box :: new ( ( Always { arg, interval } ) . into ( ) )
396
+ pub fn make_timed_always ( & self , interval : Interval , arg : Box < BoolExpr > ) -> BoolExpr {
397
+ ( Always { arg, interval } ) . into ( )
330
398
}
331
399
332
400
/// Create a [`BoolExpr::Eventually`] expression.
333
- pub fn make_eventually ( & self , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
334
- Box :: new (
335
- ( Eventually {
336
- arg,
337
- interval : ( ..) . into ( ) ,
338
- } )
339
- . into ( ) ,
340
- )
401
+ pub fn make_eventually ( & self , arg : Box < BoolExpr > ) -> BoolExpr {
402
+ ( Eventually {
403
+ arg,
404
+ interval : ( ..) . into ( ) ,
405
+ } )
406
+ . into ( )
341
407
}
342
408
343
409
/// Create a [`BoolExpr::Eventually`] expression with an interval.
344
- pub fn make_timed_eventually ( & self , interval : Interval , arg : Box < BoolExpr > ) -> Box < BoolExpr > {
345
- Box :: new ( ( Eventually { arg, interval } ) . into ( ) )
410
+ pub fn make_timed_eventually ( & self , interval : Interval , arg : Box < BoolExpr > ) -> BoolExpr {
411
+ ( Eventually { arg, interval } ) . into ( )
346
412
}
347
413
348
414
/// Create a [`BoolExpr::Until`] expression.
349
- pub fn make_until ( & self , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> Box < BoolExpr > {
350
- Box :: new (
351
- ( Until {
352
- lhs,
353
- rhs,
354
- interval : ( ..) . into ( ) ,
355
- } )
356
- . into ( ) ,
357
- )
415
+ pub fn make_until ( & self , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> BoolExpr {
416
+ ( Until {
417
+ lhs,
418
+ rhs,
419
+ interval : ( ..) . into ( ) ,
420
+ } )
421
+ . into ( )
358
422
}
359
423
360
424
/// Create a [`BoolExpr::Until`] expression with an interval.
361
- pub fn make_timed_until ( & self , interval : Interval , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> Box < BoolExpr > {
362
- Box :: new ( ( Until { lhs, rhs, interval } ) . into ( ) )
425
+ pub fn make_timed_until ( & self , interval : Interval , lhs : Box < BoolExpr > , rhs : Box < BoolExpr > ) -> BoolExpr {
426
+ BoolExpr :: from ( Until { lhs, rhs, interval } )
363
427
}
364
428
}
365
429
0 commit comments