@@ -1959,24 +1959,13 @@ impl Compiler<'_> {
1959
1959
) ;
1960
1960
}
1961
1961
1962
- if self . build_closure ( & code) {
1963
- func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
1964
- }
1965
-
1966
1962
// Pop the special type params symbol table
1967
1963
if type_params. is_some ( ) {
1968
1964
self . pop_symbol_table ( ) ;
1969
1965
}
1970
1966
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) ?;
1980
1969
1981
1970
if let Some ( value) = doc_str {
1982
1971
emit ! ( self , Instruction :: Duplicate ) ;
@@ -1993,44 +1982,88 @@ impl Compiler<'_> {
1993
1982
self . store_name ( name)
1994
1983
}
1995
1984
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 (
2003
- 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
1985
+ /// Implementation of CPython's compiler_make_closure
1986
+ /// Loads closure variables if needed and creates a function object
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 '{}'" ,
2003
+ var
2004
+ ) ) ) ) ;
2005
+ }
2006
+ } ;
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
2015
+ }
2016
+ _ => {
2017
+ return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
2018
+ "compiler_make_closure: invalid scope for '{}'" ,
2019
+ var
2020
+ ) ) ) ) ;
2021
+ }
2022
+ } ;
2023
+
2024
+ let idx = match vars. get_index_of ( var) {
2025
+ Some ( i) => i,
2026
+ None => {
2027
+ return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
2028
+ "compiler_make_closure: cannot find '{}' in parent vars" ,
2029
+ var
2030
+ ) ) ) ) ;
2031
+ }
2032
+ } ;
2033
+
2034
+ let mut idx = idx;
2035
+ if let SymbolScope :: Free = symbol. scope {
2036
+ idx += parent_code. metadata . cellvars . len ( ) ;
2015
2037
}
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 ( ) ;
2038
+
2039
+ emit ! ( self , Instruction :: LoadClosure ( idx. to_u32( ) ) ) ;
2024
2040
}
2025
- emit ! ( self , Instruction :: LoadClosure ( idx. to_u32( ) ) )
2041
+
2042
+ // Build tuple of closure variables
2043
+ emit ! (
2044
+ self ,
2045
+ Instruction :: BuildTuple {
2046
+ size: code. freevars. len( ) . to_u32( ) ,
2047
+ }
2048
+ ) ;
2049
+
2050
+ flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
2026
2051
}
2027
- emit ! (
2028
- self ,
2029
- Instruction :: BuildTuple {
2030
- size: code. freevars. len( ) . to_u32( ) ,
2031
- }
2032
- ) ;
2033
- true
2052
+
2053
+ // Load code object
2054
+ self . emit_load_const ( ConstantData :: Code {
2055
+ code : Box :: new ( code) ,
2056
+ } ) ;
2057
+
2058
+ // Load qualified name
2059
+ self . emit_load_const ( ConstantData :: Str {
2060
+ value : qualname. into ( ) ,
2061
+ } ) ;
2062
+
2063
+ // Make function with proper flags
2064
+ emit ! ( self , Instruction :: MakeFunction ( flags) ) ;
2065
+
2066
+ Ok ( ( ) )
2034
2067
}
2035
2068
2036
2069
// Python/compile.c find_ann
@@ -2230,15 +2263,8 @@ impl Compiler<'_> {
2230
2263
emit ! ( self , Instruction :: LoadNameAny ( dot_type_params) ) ;
2231
2264
func_flags |= bytecode:: MakeFunctionFlags :: TYPE_PARAMS ;
2232
2265
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) ) ;
2266
+ // Create class function with closure
2267
+ self . make_closure ( class_code, name, func_flags) ?;
2242
2268
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2243
2269
2244
2270
// Compile original bases
@@ -2287,34 +2313,19 @@ impl Compiler<'_> {
2287
2313
let type_params_code = self . exit_scope ( ) ;
2288
2314
2289
2315
// 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
- ) ;
2316
+ let type_params_name = format ! ( "<generic parameters of {name}>" ) ;
2317
+ self . make_closure (
2318
+ type_params_code,
2319
+ & type_params_name,
2320
+ bytecode:: MakeFunctionFlags :: empty ( ) ,
2321
+ ) ?;
2303
2322
emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
2304
2323
} else {
2305
2324
// Non-generic class: standard path
2306
2325
emit ! ( self , Instruction :: LoadBuildClass ) ;
2307
2326
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) ) ;
2327
+ // Create class function with closure
2328
+ self . make_closure ( class_code, name, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
2318
2329
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2319
2330
2320
2331
let call = if let Some ( arguments) = arguments {
@@ -4026,7 +4037,7 @@ impl Compiler<'_> {
4026
4037
let prev_ctx = self . ctx ;
4027
4038
4028
4039
let name = "<lambda>" . to_owned ( ) ;
4029
- let mut func_flags = self
4040
+ let func_flags = self
4030
4041
. enter_function ( & name, parameters. as_deref ( ) . unwrap_or ( & Default :: default ( ) ) ) ?;
4031
4042
4032
4043
// Set qualname for lambda
@@ -4046,15 +4057,9 @@ impl Compiler<'_> {
4046
4057
self . compile_expression ( body) ?;
4047
4058
self . emit_return_value ( ) ;
4048
4059
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) ) ;
4060
+
4061
+ // Create lambda function with closure
4062
+ self . make_closure ( code, & name, func_flags) ?;
4058
4063
4059
4064
self . ctx = prev_ctx;
4060
4065
}
@@ -4598,21 +4603,8 @@ impl Compiler<'_> {
4598
4603
4599
4604
self . ctx = prev_ctx;
4600
4605
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) ) ;
4606
+ // Create comprehension function with closure
4607
+ self . make_closure ( code, & name, bytecode:: MakeFunctionFlags :: empty ( ) ) ?;
4616
4608
4617
4609
// Evaluate iterated item:
4618
4610
self . compile_expression ( & generators[ 0 ] . iter ) ?;
0 commit comments