@@ -563,6 +563,27 @@ pub enum ConstantEvaluatorError {
563
563
RuntimeExpr ,
564
564
#[ error( "Unexpected override-expression" ) ]
565
565
OverrideExpr ,
566
+ #[ error( "Expected boolean expression for condition argument of `select`, got something else" ) ]
567
+ SelectScalarConditionNotABool ,
568
+ #[ error(
569
+ "Expected vectors of the same size for reject and accept args., got {:?} and {:?}" ,
570
+ reject,
571
+ accept
572
+ ) ]
573
+ SelectVecRejectAcceptSizeMismatch {
574
+ reject : crate :: VectorSize ,
575
+ accept : crate :: VectorSize ,
576
+ } ,
577
+ #[ error( "Expected boolean vector for condition arg., got something else" ) ]
578
+ SelectConditionNotAVecBool ,
579
+ #[ error(
580
+ "Expected same number of vector components between condition, accept, and reject args., got something else" ,
581
+ ) ]
582
+ SelectConditionVecSizeMismatch ,
583
+ #[ error(
584
+ "Expected reject and accept args. to be scalars of vectors of the same type, got something else" ,
585
+ ) ]
586
+ SelectAcceptRejectTypeMismatch ,
566
587
}
567
588
568
589
impl < ' a > ConstantEvaluator < ' a > {
@@ -904,9 +925,11 @@ impl<'a> ConstantEvaluator<'a> {
904
925
) ) ,
905
926
}
906
927
}
907
- Expression :: Select { .. } => Err ( ConstantEvaluatorError :: NotImplemented (
908
- "select built-in function" . into ( ) ,
909
- ) ) ,
928
+ Expression :: Select {
929
+ reject,
930
+ accept,
931
+ condition,
932
+ } => self . select ( reject, accept, condition, span) ,
910
933
Expression :: Relational { fun, argument } => {
911
934
let argument = self . check_and_get ( argument) ?;
912
935
self . relational ( fun, argument, span)
@@ -2497,6 +2520,114 @@ impl<'a> ConstantEvaluator<'a> {
2497
2520
2498
2521
Ok ( resolution)
2499
2522
}
2523
+
2524
+ fn select (
2525
+ & mut self ,
2526
+ reject : Handle < Expression > ,
2527
+ accept : Handle < Expression > ,
2528
+ condition : Handle < Expression > ,
2529
+ span : Span ,
2530
+ ) -> Result < Handle < Expression > , ConstantEvaluatorError > {
2531
+ let arg = |this : & mut Self , expr| {
2532
+ let expr = this. eval_zero_value_and_splat ( expr, span) ?;
2533
+ let expr: & Expression = & this. expressions [ expr] ;
2534
+ this. try_eval_and_append ( expr. clone ( ) , span)
2535
+ } ;
2536
+
2537
+ let reject = arg ( self , reject) ?;
2538
+ let accept = arg ( self , accept) ?;
2539
+ let condition = arg ( self , condition) ?;
2540
+
2541
+ let select_single_component =
2542
+ |this : & mut Self , reject_scalar, reject, accept, condition| {
2543
+ let accept = this. cast ( accept, reject_scalar, span) ?;
2544
+ if condition {
2545
+ Ok ( accept)
2546
+ } else {
2547
+ Ok ( reject)
2548
+ }
2549
+ } ;
2550
+
2551
+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
2552
+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( _accept_lit) ) => {
2553
+ let reject_scalar = reject_lit. scalar ( ) ;
2554
+ let & Expression :: Literal ( Literal :: Bool ( condition) ) = & self . expressions [ condition]
2555
+ else {
2556
+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
2557
+ } ;
2558
+ select_single_component ( self , reject_scalar, reject, accept, condition)
2559
+ }
2560
+ (
2561
+ & Expression :: Compose {
2562
+ ty : reject_ty,
2563
+ components : ref reject_components,
2564
+ } ,
2565
+ & Expression :: Compose {
2566
+ ty : accept_ty,
2567
+ components : ref accept_components,
2568
+ } ,
2569
+ ) => {
2570
+ let ty_deets = |ty| {
2571
+ let ( size, scalar) = self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
2572
+ ( size. unwrap ( ) , scalar)
2573
+ } ;
2574
+
2575
+ let expected_vec_size = {
2576
+ let [ ( reject_vec_size, _) , ( accept_vec_size, _) ] =
2577
+ [ reject_ty, accept_ty] . map ( ty_deets) ;
2578
+
2579
+ if reject_vec_size != accept_vec_size {
2580
+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptSizeMismatch {
2581
+ reject : reject_vec_size,
2582
+ accept : accept_vec_size,
2583
+ } ) ;
2584
+ }
2585
+ reject_vec_size
2586
+ } ;
2587
+
2588
+ let & Expression :: Compose {
2589
+ ty : condition_ty,
2590
+ components : ref condition_components,
2591
+ } = & self . expressions [ condition]
2592
+ else {
2593
+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2594
+ } ;
2595
+
2596
+ {
2597
+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
2598
+ if condition_scalar. kind != ScalarKind :: Bool {
2599
+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2600
+ }
2601
+ if condition_vec_size != expected_vec_size {
2602
+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
2603
+ }
2604
+ }
2605
+
2606
+ let evaluated = Expression :: Compose {
2607
+ ty : reject_ty,
2608
+ components : reject_components
2609
+ . clone ( )
2610
+ . into_iter ( )
2611
+ . zip ( accept_components. clone ( ) . into_iter ( ) )
2612
+ . zip ( condition_components. clone ( ) . into_iter ( ) )
2613
+ . map ( |( ( reject, accept) , condition) | {
2614
+ let reject_scalar = match & self . expressions [ reject] {
2615
+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
2616
+ _ => unreachable ! ( ) ,
2617
+ } ;
2618
+ let condition = match & self . expressions [ condition] {
2619
+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
2620
+ _ => unreachable ! ( ) ,
2621
+ } ;
2622
+ select_single_component ( self , reject_scalar, reject, accept, condition)
2623
+ } )
2624
+ . collect :: < Result < _ , _ > > ( ) ?,
2625
+ } ;
2626
+ self . register_evaluated_expr ( evaluated, span)
2627
+ }
2628
+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
2629
+ }
2630
+ }
2500
2631
}
2501
2632
2502
2633
fn first_trailing_bit ( concrete_int : ConcreteInt < 1 > ) -> ConcreteInt < 1 > {
0 commit comments