@@ -1959,24 +1959,13 @@ impl Compiler<'_> {
19591959 ) ;
19601960 }
19611961
1962- if self . build_closure ( & code) {
1963- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
1964- }
1965-
19661962 // Pop the special type params symbol table
19671963 if type_params. is_some ( ) {
19681964 self . pop_symbol_table ( ) ;
19691965 }
19701966
1971- self . emit_load_const ( ConstantData :: Code {
1972- code : Box :: new ( code) ,
1973- } ) ;
1974- self . emit_load_const ( ConstantData :: Str {
1975- value : qualname. into ( ) ,
1976- } ) ;
1977-
1978- // Turn code object into function object:
1979- emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
1967+ // Create function with closure
1968+ self . make_closure ( code, & qualname, func_flags) ?;
19801969
19811970 if let Some ( value) = doc_str {
19821971 emit ! ( self , Instruction :: Duplicate ) ;
@@ -1993,44 +1982,86 @@ impl Compiler<'_> {
19931982 self . store_name ( name)
19941983 }
19951984
1996- fn build_closure ( & mut self , code : & CodeObject ) -> bool {
1997- if code. freevars . is_empty ( ) {
1998- return false ;
1999- }
2000- for var in & * code. freevars {
2001- let table = self . symbol_table_stack . last ( ) . unwrap ( ) ;
2002- let symbol = unwrap_internal (
1985+ /// Loads closure variables if needed and creates a function object
1986+ // = compiler_make_closure
1987+ fn make_closure (
1988+ & mut self ,
1989+ code : CodeObject ,
1990+ qualname : & str ,
1991+ mut flags : bytecode:: MakeFunctionFlags ,
1992+ ) -> CompileResult < ( ) > {
1993+ // Handle free variables (closure)
1994+ if !code. freevars . is_empty ( ) {
1995+ // Build closure tuple by loading free variables
1996+ for var in & code. freevars {
1997+ let table = self . symbol_table_stack . last ( ) . unwrap ( ) ;
1998+ let symbol = match table. lookup ( var) {
1999+ Some ( s) => s,
2000+ None => {
2001+ return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
2002+ "compiler_make_closure: cannot find symbol '{var}'" ,
2003+ ) ) ) ) ;
2004+ }
2005+ } ;
2006+
2007+ let parent_code = self . code_stack . last ( ) . unwrap ( ) ;
2008+ let vars = match symbol. scope {
2009+ SymbolScope :: Free => & parent_code. metadata . freevars ,
2010+ SymbolScope :: Cell => & parent_code. metadata . cellvars ,
2011+ SymbolScope :: TypeParams => & parent_code. metadata . cellvars ,
2012+ _ if symbol. flags . contains ( SymbolFlags :: FREE_CLASS ) => {
2013+ & parent_code. metadata . freevars
2014+ }
2015+ _ => {
2016+ return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
2017+ "compiler_make_closure: invalid scope for '{var}'" ,
2018+ ) ) ) ) ;
2019+ }
2020+ } ;
2021+
2022+ let idx = match vars. get_index_of ( var) {
2023+ Some ( i) => i,
2024+ None => {
2025+ return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
2026+ "compiler_make_closure: cannot find '{var}' in parent vars" ,
2027+ ) ) ) ) ;
2028+ }
2029+ } ;
2030+
2031+ let idx = if let SymbolScope :: Free = symbol. scope {
2032+ idx + parent_code. metadata . cellvars . len ( )
2033+ } else {
2034+ idx
2035+ } ;
2036+
2037+ emit ! ( self , Instruction :: LoadClosure ( idx. to_u32( ) ) ) ;
2038+ }
2039+
2040+ // Build tuple of closure variables
2041+ emit ! (
20032042 self ,
2004- table
2005- . lookup ( var)
2006- . ok_or_else ( || InternalError :: MissingSymbol ( var. to_owned ( ) ) ) ,
2007- ) ;
2008- let parent_code = self . code_stack . last ( ) . unwrap ( ) ;
2009- let vars = match symbol. scope {
2010- SymbolScope :: Free => & parent_code. metadata . freevars ,
2011- SymbolScope :: Cell => & parent_code. metadata . cellvars ,
2012- SymbolScope :: TypeParams => & parent_code. metadata . cellvars ,
2013- _ if symbol. flags . contains ( SymbolFlags :: FREE_CLASS ) => {
2014- & parent_code. metadata . freevars
2043+ Instruction :: BuildTuple {
2044+ size: code. freevars. len( ) . to_u32( ) ,
20152045 }
2016- x => unreachable ! (
2017- "var {} in a {:?} should be free or cell but it's {:?}" ,
2018- var, table. typ, x
2019- ) ,
2020- } ;
2021- let mut idx = vars. get_index_of ( var) . unwrap ( ) ;
2022- if let SymbolScope :: Free = symbol. scope {
2023- idx += parent_code. metadata . cellvars . len ( ) ;
2024- }
2025- emit ! ( self , Instruction :: LoadClosure ( idx. to_u32( ) ) )
2046+ ) ;
2047+
2048+ flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
20262049 }
2027- emit ! (
2028- self ,
2029- Instruction :: BuildTuple {
2030- size: code. freevars. len( ) . to_u32( ) ,
2031- }
2032- ) ;
2033- true
2050+
2051+ // Load code object
2052+ self . emit_load_const ( ConstantData :: Code {
2053+ code : Box :: new ( code) ,
2054+ } ) ;
2055+
2056+ // Load qualified name
2057+ self . emit_load_const ( ConstantData :: Str {
2058+ value : qualname. into ( ) ,
2059+ } ) ;
2060+
2061+ // Make function with proper flags
2062+ emit ! ( self , Instruction :: MakeFunction ( flags) ) ;
2063+
2064+ Ok ( ( ) )
20342065 }
20352066
20362067 // Python/compile.c find_ann
@@ -2230,15 +2261,8 @@ impl Compiler<'_> {
22302261 emit ! ( self , Instruction :: LoadNameAny ( dot_type_params) ) ;
22312262 func_flags |= bytecode:: MakeFunctionFlags :: TYPE_PARAMS ;
22322263
2233- if self . build_closure ( & class_code) {
2234- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
2235- }
2236-
2237- self . emit_load_const ( ConstantData :: Code {
2238- code : Box :: new ( class_code) ,
2239- } ) ;
2240- self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2241- emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
2264+ // Create class function with closure
2265+ self . make_closure ( class_code, name, func_flags) ?;
22422266 self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
22432267
22442268 // Compile original bases
@@ -2287,34 +2311,19 @@ impl Compiler<'_> {
22872311 let type_params_code = self . exit_scope ( ) ;
22882312
22892313 // Execute the type params function
2290- if self . build_closure ( & type_params_code) {
2291- // Should not need closure
2292- }
2293- self . emit_load_const ( ConstantData :: Code {
2294- code : Box :: new ( type_params_code) ,
2295- } ) ;
2296- self . emit_load_const ( ConstantData :: Str {
2297- value : format ! ( "<generic parameters of {name}>" ) . into ( ) ,
2298- } ) ;
2299- emit ! (
2300- self ,
2301- Instruction :: MakeFunction ( bytecode:: MakeFunctionFlags :: empty( ) )
2302- ) ;
2314+ let type_params_name = format ! ( "<generic parameters of {name}>" ) ;
2315+ self . make_closure (
2316+ type_params_code,
2317+ & type_params_name,
2318+ bytecode:: MakeFunctionFlags :: empty ( ) ,
2319+ ) ?;
23032320 emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
23042321 } else {
23052322 // Non-generic class: standard path
23062323 emit ! ( self , Instruction :: LoadBuildClass ) ;
23072324
2308- let mut func_flags = bytecode:: MakeFunctionFlags :: empty ( ) ;
2309- if self . build_closure ( & class_code) {
2310- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
2311- }
2312-
2313- self . emit_load_const ( ConstantData :: Code {
2314- code : Box :: new ( class_code) ,
2315- } ) ;
2316- self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2317- emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
2325+ // Create class function with closure
2326+ self . make_closure ( class_code, name, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
23182327 self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
23192328
23202329 let call = if let Some ( arguments) = arguments {
@@ -4026,7 +4035,7 @@ impl Compiler<'_> {
40264035 let prev_ctx = self . ctx ;
40274036
40284037 let name = "<lambda>" . to_owned ( ) ;
4029- let mut func_flags = self
4038+ let func_flags = self
40304039 . enter_function ( & name, parameters. as_deref ( ) . unwrap_or ( & Default :: default ( ) ) ) ?;
40314040
40324041 // Set qualname for lambda
@@ -4046,15 +4055,9 @@ impl Compiler<'_> {
40464055 self . compile_expression ( body) ?;
40474056 self . emit_return_value ( ) ;
40484057 let code = self . exit_scope ( ) ;
4049- if self . build_closure ( & code) {
4050- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
4051- }
4052- self . emit_load_const ( ConstantData :: Code {
4053- code : Box :: new ( code) ,
4054- } ) ;
4055- self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
4056- // Turn code object into function object:
4057- emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
4058+
4059+ // Create lambda function with closure
4060+ self . make_closure ( code, & name, func_flags) ?;
40584061
40594062 self . ctx = prev_ctx;
40604063 }
@@ -4598,21 +4601,8 @@ impl Compiler<'_> {
45984601
45994602 self . ctx = prev_ctx;
46004603
4601- let mut func_flags = bytecode:: MakeFunctionFlags :: empty ( ) ;
4602- if self . build_closure ( & code) {
4603- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
4604- }
4605-
4606- // List comprehension code:
4607- self . emit_load_const ( ConstantData :: Code {
4608- code : Box :: new ( code) ,
4609- } ) ;
4610-
4611- // List comprehension function name:
4612- self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
4613-
4614- // Turn code object into function object:
4615- emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
4604+ // Create comprehension function with closure
4605+ self . make_closure ( code, name, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
46164606
46174607 // Evaluate iterated item:
46184608 self . compile_expression ( & generators[ 0 ] . iter ) ?;
0 commit comments