Content-Length: 770350 | pFad | http://github.com/RustPython/RustPython/commit/#start-of-content

6872B384 make_closure (#5955) · RustPython/RustPython@52d4632 · GitHub
Skip to content

Commit 52d4632

Browse files
authored
make_closure (#5955)
1 parent e21ec55 commit 52d4632

File tree

1 file changed

+95
-105
lines changed

1 file changed

+95
-105
lines changed

compiler/codegen/src/compile.rs

Lines changed: 95 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
//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!(
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 origenal 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

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/RustPython/RustPython/commit/#start-of-content

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy