Loads closure variables if needed and creates a function object = compiler_make_closure
(
&mut self,
code: CodeObject,
flags: bytecode::MakeFunctionFlags,
)
| 4649 | /// Loads closure variables if needed and creates a function object |
| 4650 | // = compiler_make_closure |
| 4651 | fn make_closure( |
| 4652 | &mut self, |
| 4653 | code: CodeObject, |
| 4654 | flags: bytecode::MakeFunctionFlags, |
| 4655 | ) -> CompileResult<()> { |
| 4656 | // Handle free variables (closure) |
| 4657 | let has_freevars = !code.freevars.is_empty(); |
| 4658 | if has_freevars { |
| 4659 | // Build closure tuple by loading free variables |
| 4660 | |
| 4661 | for var in &code.freevars { |
| 4662 | // Special case: If a class contains a method with a |
| 4663 | // free variable that has the same name as a method, |
| 4664 | // the name will be considered free *and* local in the |
| 4665 | // class. It should be handled by the closure, as |
| 4666 | // well as by the normal name lookup logic. |
| 4667 | |
| 4668 | // Get reference type using our get_ref_type function |
| 4669 | let ref_type = self.get_ref_type(var).map_err(|e| self.error(e))?; |
| 4670 | |
| 4671 | // Get parent code info |
| 4672 | let parent_code = self.code_stack.last().unwrap(); |
| 4673 | let cellvars_len = parent_code.metadata.cellvars.len(); |
| 4674 | |
| 4675 | // Look up the variable index based on reference type |
| 4676 | let idx = match ref_type { |
| 4677 | SymbolScope::Cell => parent_code |
| 4678 | .metadata |
| 4679 | .cellvars |
| 4680 | .get_index_of(var) |
| 4681 | .or_else(|| { |
| 4682 | parent_code |
| 4683 | .metadata |
| 4684 | .freevars |
| 4685 | .get_index_of(var) |
| 4686 | .map(|i| i + cellvars_len) |
| 4687 | }) |
| 4688 | .ok_or_else(|| { |
| 4689 | self.error(CodegenErrorType::SyntaxError(format!( |
| 4690 | "compiler_make_closure: cannot find '{var}' in parent vars", |
| 4691 | ))) |
| 4692 | })?, |
| 4693 | SymbolScope::Free => parent_code |
| 4694 | .metadata |
| 4695 | .freevars |
| 4696 | .get_index_of(var) |
| 4697 | .map(|i| i + cellvars_len) |
| 4698 | .or_else(|| parent_code.metadata.cellvars.get_index_of(var)) |
| 4699 | .ok_or_else(|| { |
| 4700 | self.error(CodegenErrorType::SyntaxError(format!( |
| 4701 | "compiler_make_closure: cannot find '{var}' in parent vars", |
| 4702 | ))) |
| 4703 | })?, |
| 4704 | _ => { |
| 4705 | return Err(self.error(CodegenErrorType::SyntaxError(format!( |
| 4706 | "compiler_make_closure: unexpected ref_type {ref_type:?} for '{var}'", |
| 4707 | )))); |
| 4708 | } |
no test coverage detected