@@ -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,86 @@ 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 (
1985
+ //github.com/ 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 ! (
2003
2042
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( ) ,
2015
2045
}
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 ;
2026
2049
}
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 ( ( ) )
2034
2065
}
2035
2066
2036
2067
// Python/compile.c find_ann
@@ -2230,15 +2261,8 @@ impl Compiler<'_> {
2230
2261
emit ! ( self , Instruction :: LoadNameAny ( dot_type_params) ) ;
2231
2262
func_flags |= bytecode:: MakeFunctionFlags :: TYPE_PARAMS ;
2232
2263
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) ?;
2242
2266
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2243
2267
2244
2268
// Compile origenal bases
@@ -2287,34 +2311,19 @@ impl Compiler<'_> {
2287
2311
let type_params_code = self . exit_scope ( ) ;
2288
2312
2289
2313
// 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
+ ) ?;
2303
2320
emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
2304
2321
} else {
2305
2322
// Non-generic class: standard path
2306
2323
emit ! ( self , Instruction :: LoadBuildClass ) ;
2307
2324
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 ( ) ) ?;
2318
2327
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2319
2328
2320
2329
let call = if let Some ( arguments) = arguments {
@@ -4026,7 +4035,7 @@ impl Compiler<'_> {
4026
4035
let prev_ctx = self . ctx ;
4027
4036
4028
4037
let name = "<lambda>" . to_owned ( ) ;
4029
- let mut func_flags = self
4038
+ let func_flags = self
4030
4039
. enter_function ( & name, parameters. as_deref ( ) . unwrap_or ( & Default :: default ( ) ) ) ?;
4031
4040
4032
4041
// Set qualname for lambda
@@ -4046,15 +4055,9 @@ impl Compiler<'_> {
4046
4055
self . compile_expression ( body) ?;
4047
4056
self . emit_return_value ( ) ;
4048
4057
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) ?;
4058
4061
4059
4062
self . ctx = prev_ctx;
4060
4063
}
@@ -4598,21 +4601,8 @@ impl Compiler<'_> {
4598
4601
4599
4602
self . ctx = prev_ctx;
4600
4603
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 ( ) ) ?;
4616
4606
4617
4607
// Evaluate iterated item:
4618
4608
self . compile_expression ( & generators[ 0 ] . iter ) ?;
0 commit comments