@@ -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,19 @@ 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
+ } => {
933
+ let mut arg = |expr| self . eval_zero_value_and_splat ( expr, span) ;
934
+
935
+ let reject = arg ( reject) ?;
936
+ let accept = arg ( accept) ?;
937
+ let condition = arg ( condition) ?;
938
+
939
+ self . select ( reject, accept, condition, span)
940
+ }
910
941
Expression :: Relational { fun, argument } => {
911
942
let argument = self . check_and_get ( argument) ?;
912
943
self . relational ( fun, argument, span)
@@ -2497,6 +2528,110 @@ impl<'a> ConstantEvaluator<'a> {
2497
2528
2498
2529
Ok ( resolution)
2499
2530
}
2531
+
2532
+ fn select (
2533
+ & mut self ,
2534
+ reject : Handle < Expression > ,
2535
+ accept : Handle < Expression > ,
2536
+ condition : Handle < Expression > ,
2537
+ span : Span ,
2538
+ ) -> Result < Handle < Expression > , ConstantEvaluatorError > {
2539
+ let select_single_component =
2540
+ |this : & mut Self , reject_scalar, reject, accept, condition| {
2541
+ let accept = this. cast ( accept, reject_scalar, span) ?;
2542
+ if condition {
2543
+ Ok ( accept)
2544
+ } else {
2545
+ Ok ( reject)
2546
+ }
2547
+ } ;
2548
+
2549
+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
2550
+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( _accept_lit) ) => {
2551
+ let reject_scalar = reject_lit. scalar ( ) ;
2552
+ let & Expression :: Literal ( Literal :: Bool ( condition) ) = & self . expressions [ condition]
2553
+ else {
2554
+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
2555
+ } ;
2556
+ select_single_component ( self , reject_scalar, reject, accept, condition)
2557
+ }
2558
+ (
2559
+ & Expression :: Compose {
2560
+ ty : reject_ty,
2561
+ components : ref reject_components,
2562
+ } ,
2563
+ & Expression :: Compose {
2564
+ ty : accept_ty,
2565
+ components : ref accept_components,
2566
+ } ,
2567
+ ) => {
2568
+ let ty_deets = |ty| {
2569
+ let ( size, scalar) = self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
2570
+ ( size. unwrap ( ) , scalar)
2571
+ } ;
2572
+
2573
+ let expected_vec_size = {
2574
+ let [ ( reject_vec_size, _) , ( accept_vec_size, _) ] =
2575
+ [ reject_ty, accept_ty] . map ( ty_deets) ;
2576
+
2577
+ if reject_vec_size != accept_vec_size {
2578
+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptSizeMismatch {
2579
+ reject : reject_vec_size,
2580
+ accept : accept_vec_size,
2581
+ } ) ;
2582
+ }
2583
+ reject_vec_size
2584
+ } ;
2585
+
2586
+ let condition_components = match self . expressions [ condition] {
2587
+ Expression :: Literal ( Literal :: Bool ( condition) ) => {
2588
+ vec ! [ condition; ( expected_vec_size as u8 ) . into( ) ]
2589
+ }
2590
+ Expression :: Compose {
2591
+ ty : condition_ty,
2592
+ components : ref condition_components,
2593
+ } => {
2594
+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
2595
+ if condition_scalar. kind != ScalarKind :: Bool {
2596
+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2597
+ }
2598
+ if condition_vec_size != expected_vec_size {
2599
+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
2600
+ }
2601
+ condition_components
2602
+ . iter ( )
2603
+ . copied ( )
2604
+ . map ( |component| match & self . expressions [ component] {
2605
+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
2606
+ _ => unreachable ! ( ) ,
2607
+ } )
2608
+ . collect ( )
2609
+ }
2610
+
2611
+ _ => return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ,
2612
+ } ;
2613
+
2614
+ let evaluated = Expression :: Compose {
2615
+ ty : reject_ty,
2616
+ components : reject_components
2617
+ . clone ( )
2618
+ . into_iter ( )
2619
+ . zip ( accept_components. clone ( ) . into_iter ( ) )
2620
+ . zip ( condition_components. into_iter ( ) )
2621
+ . map ( |( ( reject, accept) , condition) | {
2622
+ let reject_scalar = match & self . expressions [ reject] {
2623
+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
2624
+ _ => unreachable ! ( ) ,
2625
+ } ;
2626
+ select_single_component ( self , reject_scalar, reject, accept, condition)
2627
+ } )
2628
+ . collect :: < Result < _ , _ > > ( ) ?,
2629
+ } ;
2630
+ self . register_evaluated_expr ( evaluated, span)
2631
+ }
2632
+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
2633
+ }
2634
+ }
2500
2635
}
2501
2636
2502
2637
fn first_trailing_bit ( concrete_int : ConcreteInt < 1 > ) -> ConcreteInt < 1 > {
0 commit comments