@@ -4,6 +4,7 @@ use alloc::{
44 string:: { String , ToString } ,
55 vec:: Vec ,
66} ;
7+ use arrayvec:: ArrayVec ;
78use core:: num:: NonZeroU32 ;
89
910use crate :: common:: wgsl:: { TryToWgsl , TypeContext } ;
@@ -2481,13 +2482,46 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
24812482 } else {
24822483 match function. name {
24832484 "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`
24852488
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+ }
24892497
24902498 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;
24912525
24922526 ir:: Expression :: Select {
24932527 reject,
@@ -2988,6 +3022,70 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
29883022 } )
29893023 }
29903024
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+
29913089 /// Choose the right overload for a function call.
29923090 ///
29933091 /// Return a [`Rule`] representing the most preferred overload in
@@ -3826,6 +3924,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
38263924 }
38273925}
38283926
3927+ // TODO: Surely this already exists! Find it.
3928+ const MAX_BUILTIN_ARGS : usize = 4 ;
3929+
38293930impl ir:: AtomicFunction {
38303931 pub fn map ( word : & str ) -> Option < Self > {
38313932 Some ( match word {
0 commit comments