@@ -4,6 +4,7 @@ use alloc::{
4
4
string:: { String , ToString } ,
5
5
vec:: Vec ,
6
6
} ;
7
+ use arrayvec:: ArrayVec ;
7
8
use core:: num:: NonZeroU32 ;
8
9
9
10
use crate :: common:: wgsl:: { TryToWgsl , TypeContext } ;
@@ -2481,13 +2482,46 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
2481
2482
} else {
2482
2483
match function. name {
2483
2484
"select" => {
2484
- let mut args = ctx. prepare_args ( arguments, 3 , span) ;
2485
+ const NUM_ARGS : usize = 3 ;
2486
+
2487
+ // TODO: dedupe with `math_function_helper`
2485
2488
2486
- let reject = self . expression ( args. next ( ) ?, ctx) ?;
2487
- let accept = self . expression ( args. next ( ) ?, ctx) ?;
2488
- let condition = self . expression ( args. next ( ) ?, ctx) ?;
2489
+ let mut lowered_arguments = ArrayVec :: < _ , NUM_ARGS > :: new ( ) ;
2490
+ let mut args = ctx. prepare_args ( arguments, NUM_ARGS as u32 , span) ;
2491
+
2492
+ for _ in 0 ..lowered_arguments. capacity ( ) {
2493
+ let lowered = self . expression_for_abstract ( args. next ( ) ?, ctx) ?;
2494
+ ctx. grow_types ( lowered) ?;
2495
+ lowered_arguments. push ( lowered) ;
2496
+ }
2489
2497
2490
2498
args. finish ( ) ?;
2499
+ let mut lowered_arguments = lowered_arguments. into_inner ( ) . unwrap ( ) ;
2500
+
2501
+ let fun_overloads = proc:: select:: overloads ( ) ;
2502
+
2503
+ let rule = self . resolve_overloads (
2504
+ span,
2505
+ proc:: select:: WgslSymbol ,
2506
+ fun_overloads,
2507
+ & lowered_arguments,
2508
+ ctx,
2509
+ ) ?;
2510
+
2511
+ self . apply_automatic_conversions_for_call (
2512
+ & rule,
2513
+ & mut lowered_arguments,
2514
+ ctx,
2515
+ ) ?;
2516
+
2517
+ // If this function returns a predeclared type, register it
2518
+ // in `Module::special_types`. The typifier will expect to
2519
+ // be able to find it there.
2520
+ if let proc:: Conclusion :: Predeclared ( predeclared) = rule. conclusion {
2521
+ ctx. module . generate_predeclared_type ( predeclared) ;
2522
+ }
2523
+
2524
+ let [ reject, accept, condition] = lowered_arguments;
2491
2525
2492
2526
ir:: Expression :: Select {
2493
2527
reject,
@@ -2988,6 +3022,70 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
2988
3022
} )
2989
3023
}
2990
3024
3025
+ fn resolve_arr_things < const NUM_ARGS : usize , F , O , R > (
3026
+ & mut self ,
3027
+ span : Span ,
3028
+ fun : F ,
3029
+ resolve_overloads : R ,
3030
+ ast_arguments : [ Handle < ast:: Expression < ' source > > ; NUM_ARGS ] ,
3031
+ ctx : & mut ExpressionContext < ' source , ' _ , ' _ > ,
3032
+ ) -> Result < ' source , [ Handle < ir:: Expression > ; NUM_ARGS ] >
3033
+ where
3034
+ F : TryToWgsl + core:: fmt:: Debug + Copy ,
3035
+ O : proc:: OverloadSet ,
3036
+ R : FnOnce (
3037
+ & [ Handle < ir:: Expression > ; NUM_ARGS ] ,
3038
+ & mut ExpressionContext < ' source , ' _ , ' _ > ,
3039
+ ) -> O ,
3040
+ {
3041
+ self . resolve_const_things (
3042
+ span,
3043
+ fun,
3044
+ |args, ctx| {
3045
+ let args = args. try_into ( ) . unwrap ( ) ;
3046
+ resolve_overloads ( args, ctx)
3047
+ } ,
3048
+ ast_arguments. into ( ) ,
3049
+ ctx,
3050
+ )
3051
+ . map ( |arr| arr. into_inner ( ) . unwrap ( ) )
3052
+ }
3053
+
3054
+ fn resolve_const_things < const NUM_ARGS : usize , F , O , R > (
3055
+ & mut self ,
3056
+ span : Span ,
3057
+ fun : F ,
3058
+ resolve_overloads : R ,
3059
+ ast_arguments : ArrayVec < Handle < ast:: Expression < ' source > > , { NUM_ARGS } > ,
3060
+ ctx : & mut ExpressionContext < ' source , ' _ , ' _ > ,
3061
+ ) -> Result < ' source , ArrayVec < Handle < ir:: Expression > , { NUM_ARGS } > >
3062
+ where
3063
+ F : TryToWgsl + core:: fmt:: Debug + Copy ,
3064
+ O : proc:: OverloadSet ,
3065
+ R : FnOnce ( & [ Handle < ir:: Expression > ] , & mut ExpressionContext < ' source , ' _ , ' _ > ) -> O ,
3066
+ {
3067
+ let mut lowered_arguments = ArrayVec :: < _ , { NUM_ARGS } > :: new ( ) ;
3068
+
3069
+ for & arg in ast_arguments. iter ( ) {
3070
+ let lowered = self . expression_for_abstract ( arg, ctx) ?;
3071
+ ctx. grow_types ( lowered) ?;
3072
+ lowered_arguments. push ( lowered) ;
3073
+ }
3074
+
3075
+ let fun_overloads = resolve_overloads ( & lowered_arguments, ctx) ;
3076
+ let rule = self . resolve_overloads ( span, fun, fun_overloads, & lowered_arguments, ctx) ?;
3077
+ self . apply_automatic_conversions_for_call ( & rule, & mut lowered_arguments, ctx) ?;
3078
+
3079
+ // If this function returns a predeclared type, register it
3080
+ // in `Module::special_types`. The typifier will expect to
3081
+ // be able to find it there.
3082
+ if let proc:: Conclusion :: Predeclared ( predeclared) = rule. conclusion {
3083
+ ctx. module . generate_predeclared_type ( predeclared) ;
3084
+ }
3085
+
3086
+ Ok ( lowered_arguments)
3087
+ }
3088
+
2991
3089
/// Choose the right overload for a function call.
2992
3090
///
2993
3091
/// Return a [`Rule`] representing the most preferred overload in
@@ -3826,6 +3924,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
3826
3924
}
3827
3925
}
3828
3926
3927
+ // TODO: Surely this already exists! Find it.
3928
+ const MAX_BUILTIN_ARGS : usize = 4 ;
3929
+
3829
3930
impl ir:: AtomicFunction {
3830
3931
pub fn map ( word : & str ) -> Option < Self > {
3831
3932
Some ( match word {
0 commit comments