@@ -563,6 +563,24 @@ pub enum ConstantEvaluatorError {
563563 RuntimeExpr ,
564564 #[ error( "Unexpected override-expression" ) ]
565565 OverrideExpr ,
566+ #[ error( "Expected scalars of the same type for reject and accept args., got something else" ) ]
567+ SelectScalarRejectAcceptTypeMismatch ,
568+ #[ error( "Expected boolean expression for condition argument of `select`, got something else" ) ]
569+ SelectScalarConditionNotABool ,
570+ #[ error(
571+ "Expected vectors of the same component type for reject and accept args., got something else" ,
572+ ) ]
573+ SelectVecRejectAcceptTypeMismatch ,
574+ #[ error( "Expected boolean vector for condition arg., got something else" ) ]
575+ SelectConditionNotAVecBool ,
576+ #[ error(
577+ "Expected same number of vector components between condition, accept, and reject args., got something else" ,
578+ ) ]
579+ SelectConditionVecSizeMismatch ,
580+ #[ error(
581+ "Expected reject and accept args. to be scalars of vectors of the same type, got something else" ,
582+ ) ]
583+ SelectAcceptRejectTypeMismatch ,
566584}
567585
568586impl < ' a > ConstantEvaluator < ' a > {
@@ -904,9 +922,118 @@ impl<'a> ConstantEvaluator<'a> {
904922 ) ) ,
905923 }
906924 }
907- Expression :: Select { .. } => Err ( ConstantEvaluatorError :: NotImplemented (
908- "select built-in function" . into ( ) ,
909- ) ) ,
925+ Expression :: Select {
926+ reject,
927+ accept,
928+ condition,
929+ } => {
930+ let arg = |this : & mut Self , expr| {
931+ let expr: & Expression = & this. expressions [ expr] ;
932+ this. try_eval_and_append ( expr. clone ( ) , span)
933+ } ;
934+
935+ let reject = arg ( self , reject) ?;
936+ let accept = arg ( self , accept) ?;
937+ let condition = arg ( self , condition) ?;
938+
939+ let select_single_component =
940+ |this : & mut Self , reject_scalar, reject, accept, condition| {
941+ let accept = this. cast ( accept, reject_scalar, span) ?;
942+ if condition {
943+ Ok ( accept)
944+ } else {
945+ Ok ( reject)
946+ }
947+ } ;
948+
949+ // NOTE: Frontends are on the hook for any conversions between arguments, if the
950+ // language supports it. If types don't match, the buck stops here.
951+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
952+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( accept_lit) ) => {
953+ let reject_scalar = reject_lit. scalar ( ) ;
954+ // if reject_scalar != accept_lit.scalar() {
955+ // return Err(
956+ // ConstantEvaluatorError::SelectScalarRejectAcceptTypeMismatch,
957+ // );
958+ // }
959+ let & Expression :: Literal ( Literal :: Bool ( condition) ) =
960+ & self . expressions [ condition]
961+ else {
962+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
963+ } ;
964+ select_single_component ( self , reject_scalar, reject, accept, condition)
965+ }
966+ (
967+ & Expression :: Compose {
968+ ty : reject_ty,
969+ components : ref reject_components,
970+ } ,
971+ & Expression :: Compose {
972+ ty : accept_ty,
973+ components : ref accept_components,
974+ } ,
975+ ) => {
976+ if reject_ty != accept_ty {
977+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptTypeMismatch ) ;
978+ }
979+ let ty = reject_ty;
980+
981+ let ty_deets = |ty| {
982+ let ( size, scalar) =
983+ self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
984+ ( size. unwrap ( ) , scalar)
985+ } ;
986+ let ( expected_vec_size, _scalar) = ty_deets ( ty) ;
987+
988+ let & Expression :: Compose {
989+ ty : condition_ty,
990+ components : ref condition_components,
991+ } = & self . expressions [ condition]
992+ else {
993+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
994+ } ;
995+
996+ {
997+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
998+ if condition_scalar. kind != ScalarKind :: Bool {
999+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
1000+ }
1001+ if condition_vec_size != expected_vec_size {
1002+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
1003+ }
1004+ }
1005+
1006+ let evaluated = Expression :: Compose {
1007+ ty,
1008+ components : reject_components
1009+ . clone ( )
1010+ . into_iter ( )
1011+ . zip ( accept_components. clone ( ) . into_iter ( ) )
1012+ . zip ( condition_components. clone ( ) . into_iter ( ) )
1013+ . map ( |( ( reject, accept) , condition) | {
1014+ let reject_scalar = match & self . expressions [ reject] {
1015+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
1016+ _ => unreachable ! ( ) ,
1017+ } ;
1018+ let condition = match & self . expressions [ condition] {
1019+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
1020+ _ => unreachable ! ( ) ,
1021+ } ;
1022+ select_single_component (
1023+ self ,
1024+ reject_scalar,
1025+ reject,
1026+ accept,
1027+ condition,
1028+ )
1029+ } )
1030+ . collect :: < Result < _ , _ > > ( ) ?,
1031+ } ;
1032+ self . register_evaluated_expr ( evaluated, span)
1033+ }
1034+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
1035+ }
1036+ }
9101037 Expression :: Relational { fun, argument } => {
9111038 let argument = self . check_and_get ( argument) ?;
9121039 self . relational ( fun, argument, span)
0 commit comments