···22use inkwell::values::FunctionValue;
33use source_span::Span;
44use std::borrow::Borrow;
55-use trilogy_ir::{Id, ir};
55+use trilogy_ir::{Id, ir, visitor::HasCanEvaluate};
6677impl<'ctx> Codegen<'ctx> {
88 fn write_rule_accessor(
···126126 self.begin_next_function(next_parameter_function);
127127 }
128128 }
129129+ // The rule runs the iterator, resulting in new bindings being set.
129130 let Some(next_iteration) = self.compile_iterator(&overload.body, go_to_next_overload)
130131 else {
131132 break 'outer;
···134135135136 let mut arguments = Vec::with_capacity(arity + 1);
136137 arguments.push(next_iteration);
137137- for param in &overload.parameters {
138138- let Some(param_value) = self.compile_expression(param, "") else {
139139- break 'outer;
140140- };
141141- self.bind_temporary(param_value);
142142- arguments.push(param_value);
138138+ // Then each parameter pattern is evaluated to create the values for the output arguments.
139139+ // If the parameter cannot be evaluated (e.g. `rule always(_)`)
140140+ // * Re-use the input parameter value if available; but
141141+ // * if the input parameter was also not set (e.g. `for always(a)`), then consider this a failed
142142+ // overload and go next.
143143+ for (i, param) in overload.parameters.iter().enumerate() {
144144+ if param.can_evaluate() {
145145+ let Some(param_value) = self.compile_expression(param, "") else {
146146+ break 'outer;
147147+ };
148148+ self.bind_temporary(param_value);
149149+ arguments.push(param_value);
150150+ } else {
151151+ let input_param = self.function_params.borrow()[i];
152152+ let input_param = self.use_temporary(input_param).unwrap();
153153+ let here = self.get_function();
154154+ let fully_unbound = self.context.append_basic_block(here, "fully_unbound");
155155+ let rebind_input = self.context.append_basic_block(here, "rebind_input");
156156+ self.branch_undefined(input_param, fully_unbound, rebind_input);
157157+ self.builder.position_at_end(fully_unbound);
158158+ let next_overload = self.use_temporary(go_to_next_overload).unwrap();
159159+ self.void_call_continuation(next_overload);
160160+161161+ self.builder.position_at_end(rebind_input);
162162+ arguments.push(input_param);
163163+ }
143164 }
144165 let next = self.get_next("");
145166 for arg in arguments.iter_mut() {