Resolves function arguments. Will return `Err(func)` is partial application is required.
(
&mut self,
#[allow(clippy::boxed_local)] to_resolve: Box<Func>,
)
| 212 | |
| 213 | /// Resolves function arguments. Will return `Err(func)` is partial application is required. |
| 214 | fn resolve_function_args( |
| 215 | &mut self, |
| 216 | #[allow(clippy::boxed_local)] to_resolve: Box<Func>, |
| 217 | ) -> Result<Result<Box<Func>, Box<Func>>> { |
| 218 | let mut closure = Box::new(Func { |
| 219 | args: vec![Expr::new(Literal::Null); to_resolve.args.len()], |
| 220 | ..*to_resolve |
| 221 | }); |
| 222 | let mut partial_application_position = None; |
| 223 | |
| 224 | let func_name = &closure.name_hint; |
| 225 | |
| 226 | let (relations, other): (Vec<_>, Vec<_>) = zip(&closure.params, to_resolve.args) |
| 227 | .enumerate() |
| 228 | .partition(|(_, (param, _))| { |
| 229 | let is_relation = param |
| 230 | .ty |
| 231 | .as_ref() |
| 232 | .map(|t| t.is_relation()) |
| 233 | .unwrap_or_default(); |
| 234 | |
| 235 | is_relation |
| 236 | }); |
| 237 | |
| 238 | let has_relations = !relations.is_empty(); |
| 239 | |
| 240 | // resolve relational args |
| 241 | if has_relations { |
| 242 | self.root_mod.module.shadow(NS_THIS); |
| 243 | self.root_mod.module.shadow(NS_THAT); |
| 244 | |
| 245 | // First, resolve all relational arguments |
| 246 | let mut resolved_relations = Vec::new(); |
| 247 | for (pos, (index, (param, mut arg))) in relations.into_iter().with_position() { |
| 248 | let is_last = matches!(pos, Position::Last | Position::Only); |
| 249 | |
| 250 | // just fold the argument alone |
| 251 | if partial_application_position.is_none() { |
| 252 | arg = self |
| 253 | .fold_and_type_check(arg, param, func_name)? |
| 254 | .unwrap_or_else(|a| { |
| 255 | partial_application_position = Some(index); |
| 256 | a |
| 257 | }); |
| 258 | } |
| 259 | log::debug!("resolved arg to {}", arg.kind.as_ref()); |
| 260 | |
| 261 | resolved_relations.push((index, arg, is_last)); |
| 262 | } |
| 263 | |
| 264 | // Then, add relation frames into scope |
| 265 | for (index, arg, is_last) in resolved_relations { |
| 266 | if partial_application_position.is_none() { |
| 267 | let frame = arg.lineage.as_ref().ok_or_else(|| { |
| 268 | // Provide helpful error for empty arrays/tuples used directly |
| 269 | // (not from functions like std.from_text which set lineage properly) |
| 270 | match &arg.kind { |
| 271 | ExprKind::Array(v) if v.is_empty() => Error::new(Reason::Expected { |
no test coverage detected