(&mut self, closure: Box<Func>)
| 102 | |
| 103 | #[allow(clippy::boxed_local)] |
| 104 | fn materialize_function(&mut self, closure: Box<Func>) -> Result<Expr> { |
| 105 | log::debug!("stack_push for {}", closure.as_debug_name()); |
| 106 | |
| 107 | let (func_env, body, return_ty) = env_of_closure(*closure); |
| 108 | |
| 109 | self.root_mod.module.stack_push(NS_PARAM, func_env); |
| 110 | |
| 111 | // fold again, to resolve inner variables & functions |
| 112 | let body = self.fold_expr(body)?; |
| 113 | |
| 114 | // remove param decls |
| 115 | log::debug!("stack_pop: {:?}", body.id); |
| 116 | let func_env = self.root_mod.module.stack_pop(NS_PARAM).unwrap(); |
| 117 | |
| 118 | Ok(if let ExprKind::Func(mut inner_closure) = body.kind { |
| 119 | // body couldn't been resolved - construct a closure to be evaluated later |
| 120 | |
| 121 | inner_closure.env = func_env.into_exprs(); |
| 122 | |
| 123 | // Get the missing params (params that don't have args yet) |
| 124 | let missing = inner_closure.params[inner_closure.args.len()..].to_vec(); |
| 125 | |
| 126 | // Create wrapper params and add references to them as args to the inner closure |
| 127 | let mut wrapper_params = Vec::with_capacity(missing.len()); |
| 128 | for (i, param) in missing.iter().enumerate() { |
| 129 | let param_name = format!("_partial_{i}"); |
| 130 | let substitute_arg = Expr::new(Ident::from_path(vec![ |
| 131 | NS_PARAM.to_string(), |
| 132 | param_name.clone(), |
| 133 | ])); |
| 134 | inner_closure.args.push(substitute_arg); |
| 135 | wrapper_params.push(FuncParam { |
| 136 | name: param_name, |
| 137 | ty: param.ty.clone(), |
| 138 | default_value: None, |
| 139 | }); |
| 140 | } |
| 141 | |
| 142 | Expr::new(ExprKind::Func(Box::new(Func { |
| 143 | name_hint: None, |
| 144 | args: vec![], |
| 145 | params: wrapper_params, |
| 146 | body: Box::new(Expr::new(ExprKind::Func(inner_closure))), |
| 147 | |
| 148 | // these don't matter |
| 149 | named_params: Default::default(), |
| 150 | return_ty: Default::default(), |
| 151 | env: Default::default(), |
| 152 | }))) |
| 153 | } else { |
| 154 | // resolved, return result |
| 155 | |
| 156 | // make sure to use the resolved type |
| 157 | let mut body = body; |
| 158 | if let Some(ret_ty) = return_ty.map(|x| *x) { |
| 159 | body.ty = Some(ret_ty.clone()); |
| 160 | } |
| 161 |
no test coverage detected