@@ -9,7 +9,10 @@ use petgraph::prelude::StableGraph;
9
9
use petgraph:: { Directed , Incoming , Outgoing } ;
10
10
11
11
use partiql_value:: Value :: { Boolean , Missing , Null } ;
12
- use partiql_value:: { partiql_bag, Bag , BindingsName , Tuple , Value } ;
12
+ use partiql_value:: {
13
+ partiql_bag, Bag , BinaryAnd , BinaryOr , BindingsName , NullableEq , NullableOrd , Tuple , UnaryPlus ,
14
+ Value ,
15
+ } ;
13
16
14
17
use crate :: env:: basic:: MapBindings ;
15
18
use crate :: env:: Bindings ;
@@ -278,16 +281,40 @@ impl EvalExpr for EvalLitExpr {
278
281
}
279
282
280
283
#[ derive( Debug ) ]
281
- pub struct EvalBinopExpr {
282
- pub op : EvalBinop ,
284
+ pub struct EvalUnaryOpExpr {
285
+ pub op : EvalUnaryOp ,
286
+ pub operand : Box < dyn EvalExpr > ,
287
+ }
288
+
289
+ #[ derive( Debug ) ]
290
+ pub struct EvalBinOpExpr {
291
+ pub op : EvalBinOp ,
283
292
pub lhs : Box < dyn EvalExpr > ,
284
293
pub rhs : Box < dyn EvalExpr > ,
285
294
}
286
295
287
296
// TODO we should replace this enum with some identifier that can be looked up in a symtab/funcregistry
288
297
#[ derive( Debug ) ]
289
- #[ allow( dead_code) ] // TODO remove once out of PoC
290
- pub enum EvalBinop {
298
+ pub enum EvalUnaryOp {
299
+ Pos ,
300
+ Neg ,
301
+ Not ,
302
+ }
303
+
304
+ impl EvalExpr for EvalUnaryOpExpr {
305
+ fn evaluate ( & self , bindings : & Tuple , ctx : & dyn EvalContext ) -> Value {
306
+ let value = self . operand . evaluate ( bindings, ctx) ;
307
+ match self . op {
308
+ EvalUnaryOp :: Pos => value. positive ( ) ,
309
+ EvalUnaryOp :: Neg => -value,
310
+ EvalUnaryOp :: Not => !value,
311
+ }
312
+ }
313
+ }
314
+
315
+ // TODO we should replace this enum with some identifier that can be looked up in a symtab/funcregistry
316
+ #[ derive( Debug ) ]
317
+ pub enum EvalBinOp {
291
318
And ,
292
319
Or ,
293
320
Concat ,
@@ -307,46 +334,53 @@ pub enum EvalBinop {
307
334
Exp ,
308
335
}
309
336
310
- impl EvalExpr for EvalBinopExpr {
337
+ impl EvalExpr for EvalBinOpExpr {
311
338
fn evaluate ( & self , bindings : & Tuple , ctx : & dyn EvalContext ) -> Value {
339
+ #[ inline]
340
+ fn short_circuit ( op : & EvalBinOp , value : & Value ) -> Option < Value > {
341
+ match ( op, value) {
342
+ ( EvalBinOp :: And , Value :: Boolean ( false ) ) => Some ( false . into ( ) ) ,
343
+ ( EvalBinOp :: Or , Value :: Boolean ( true ) ) => Some ( true . into ( ) ) ,
344
+ ( _, Value :: Missing ) => Some ( Value :: Missing ) ,
345
+ _ => None ,
346
+ }
347
+ }
348
+
312
349
let lhs = self . lhs . evaluate ( bindings, ctx) ;
350
+ if let Some ( propagate) = short_circuit ( & self . op , & lhs) {
351
+ return propagate;
352
+ }
353
+
313
354
let rhs = self . rhs . evaluate ( bindings, ctx) ;
314
- // Missing and Null propagation. Missing has precedence over Null
315
- if lhs == Value :: Missing || rhs == Value :: Missing {
316
- Value :: Missing
317
- } else if lhs == Value :: Null || rhs == Value :: Null {
318
- Value :: Null
319
- } else {
320
- match self . op {
321
- EvalBinop :: And => todo ! ( ) ,
322
- EvalBinop :: Or => todo ! ( ) ,
323
- EvalBinop :: Concat => {
324
- // TODO non-naive concat
325
- let lhs = if let Value :: String ( s) = lhs {
326
- * s
327
- } else {
328
- format ! ( "{:?}" , lhs)
329
- } ;
330
- let rhs = if let Value :: String ( s) = rhs {
331
- * s
332
- } else {
333
- format ! ( "{:?}" , lhs)
334
- } ;
335
- Value :: String ( Box :: new ( format ! ( "{}{}" , lhs, rhs) ) )
336
- }
337
- EvalBinop :: Eq => todo ! ( ) ,
338
- EvalBinop :: Neq => todo ! ( ) ,
339
- EvalBinop :: Gt => Boolean ( lhs > rhs) ,
340
- EvalBinop :: Gteq => Boolean ( lhs >= rhs) ,
341
- EvalBinop :: Lt => Boolean ( lhs < rhs) ,
342
- EvalBinop :: Lteq => Boolean ( lhs <= rhs) ,
343
- EvalBinop :: Add => lhs + rhs,
344
- EvalBinop :: Sub => lhs - rhs,
345
- EvalBinop :: Mul => lhs * rhs,
346
- EvalBinop :: Div => lhs / rhs,
347
- EvalBinop :: Mod => lhs % rhs,
348
- EvalBinop :: Exp => todo ! ( "Exponentiation" ) ,
355
+ match self . op {
356
+ EvalBinOp :: And => lhs. and ( rhs) ,
357
+ EvalBinOp :: Or => lhs. or ( rhs) ,
358
+ EvalBinOp :: Concat => {
359
+ // TODO non-naive concat. Also doesn't properly propagate MISSING and NULL
360
+ let lhs = if let Value :: String ( s) = lhs {
361
+ * s
362
+ } else {
363
+ format ! ( "{:?}" , lhs)
364
+ } ;
365
+ let rhs = if let Value :: String ( s) = rhs {
366
+ * s
367
+ } else {
368
+ format ! ( "{:?}" , lhs)
369
+ } ;
370
+ Value :: String ( Box :: new ( format ! ( "{}{}" , lhs, rhs) ) )
349
371
}
372
+ EvalBinOp :: Eq => lhs. eq ( rhs) ,
373
+ EvalBinOp :: Neq => lhs. neq ( rhs) ,
374
+ EvalBinOp :: Gt => lhs. gt ( rhs) ,
375
+ EvalBinOp :: Gteq => lhs. gteq ( rhs) ,
376
+ EvalBinOp :: Lt => lhs. lt ( rhs) ,
377
+ EvalBinOp :: Lteq => lhs. lteq ( rhs) ,
378
+ EvalBinOp :: Add => lhs + rhs,
379
+ EvalBinOp :: Sub => lhs - rhs,
380
+ EvalBinOp :: Mul => lhs * rhs,
381
+ EvalBinOp :: Div => lhs / rhs,
382
+ EvalBinOp :: Mod => lhs % rhs,
383
+ EvalBinOp :: Exp => todo ! ( "Exponentiation" ) ,
350
384
}
351
385
}
352
386
}
0 commit comments