Skip to content

Commit e09e97b

Browse files
authored
Merge pull request RustPython#3674 from youknowone/compile-single
compiler clean up
2 parents 34b5852 + 75b3e0d commit e09e97b

File tree

3 files changed

+60
-57
lines changed

3 files changed

+60
-57
lines changed

compiler/src/compile.rs

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,6 @@ impl CompileContext {
100100
}
101101
}
102102

103-
/// A helper function for the shared code of the different compile functions
104-
fn with_compiler(
105-
source_path: String,
106-
opts: CompileOpts,
107-
f: impl FnOnce(&mut Compiler) -> CompileResult<()>,
108-
) -> CompileResult<CodeObject> {
109-
let mut compiler = Compiler::new(opts, source_path, "<module>".to_owned());
110-
f(&mut compiler)?;
111-
let code = compiler.pop_code_object();
112-
trace!("Compilation completed: {:?}", code);
113-
Ok(code)
114-
}
115-
116103
/// Compile an ast::Mod produced from rustpython_parser::parser::parse()
117104
pub fn compile_top(
118105
ast: &ast::Mod,
@@ -127,16 +114,24 @@ pub fn compile_top(
127114
}
128115
}
129116

130-
macro_rules! compile_impl {
131-
($ast:expr, $source_path:expr, $opts:expr, $st:ident, $compile:ident) => {{
132-
let symbol_table = match $st($ast) {
133-
Ok(x) => x,
134-
Err(e) => return Err(e.into_compile_error($source_path)),
135-
};
136-
with_compiler($source_path, $opts, |compiler| {
137-
compiler.$compile($ast, symbol_table)
138-
})
139-
}};
117+
/// A helper function for the shared code of the different compile functions
118+
fn compile_impl<Ast: ?Sized>(
119+
ast: &Ast,
120+
source_path: String,
121+
opts: CompileOpts,
122+
make_symbol_table: impl FnOnce(&Ast) -> Result<SymbolTable, symboltable::SymbolTableError>,
123+
compile: impl FnOnce(&mut Compiler, &Ast, SymbolTable) -> CompileResult<()>,
124+
) -> CompileResult<CodeObject> {
125+
let symbol_table = match make_symbol_table(ast) {
126+
Ok(x) => x,
127+
Err(e) => return Err(e.into_compile_error(source_path)),
128+
};
129+
130+
let mut compiler = Compiler::new(opts, source_path, "<module>".to_owned());
131+
compile(&mut compiler, ast, symbol_table)?;
132+
let code = compiler.pop_code_object();
133+
trace!("Compilation completed: {:?}", code);
134+
Ok(code)
140135
}
141136

142137
/// Compile a standard Python program to bytecode
@@ -145,7 +140,13 @@ pub fn compile_program(
145140
source_path: String,
146141
opts: CompileOpts,
147142
) -> CompileResult<CodeObject> {
148-
compile_impl!(ast, source_path, opts, make_symbol_table, compile_program)
143+
compile_impl(
144+
ast,
145+
source_path,
146+
opts,
147+
make_symbol_table,
148+
Compiler::compile_program,
149+
)
149150
}
150151

151152
/// Compile a Python program to bytecode for the context of a REPL
@@ -154,12 +155,12 @@ pub fn compile_program_single(
154155
source_path: String,
155156
opts: CompileOpts,
156157
) -> CompileResult<CodeObject> {
157-
compile_impl!(
158+
compile_impl(
158159
ast,
159160
source_path,
160161
opts,
161162
make_symbol_table,
162-
compile_program_single
163+
Compiler::compile_program_single,
163164
)
164165
}
165166

@@ -168,7 +169,13 @@ pub fn compile_expression(
168169
source_path: String,
169170
opts: CompileOpts,
170171
) -> CompileResult<CodeObject> {
171-
compile_impl!(ast, source_path, opts, make_symbol_table_expr, compile_eval)
172+
compile_impl(
173+
ast,
174+
source_path,
175+
opts,
176+
make_symbol_table_expr,
177+
Compiler::compile_eval,
178+
)
172179
}
173180

174181
impl Compiler {
@@ -309,7 +316,7 @@ impl Compiler {
309316
let size_before = self.code_stack.len();
310317
self.symbol_table_stack.push(symbol_table);
311318

312-
let (statements, doc) = get_doc(body);
319+
let (doc, statements) = split_doc(body);
313320
if let Some(value) = doc {
314321
self.emit_constant(ConstantData::Str { value });
315322
let doc = self.name("__doc__");
@@ -337,31 +344,30 @@ impl Compiler {
337344
) -> CompileResult<()> {
338345
self.symbol_table_stack.push(symbol_table);
339346

340-
let mut emitted_return = false;
341-
342-
for (i, statement) in body.iter().enumerate() {
343-
let is_last = i == body.len() - 1;
347+
let (last, body) = if let Some(splited) = body.split_last() {
348+
splited
349+
} else {
350+
return Ok(());
351+
};
344352

353+
for statement in body {
345354
if let ast::StmtKind::Expr { value } = &statement.node {
346355
self.compile_expression(value)?;
347-
348-
if is_last {
349-
self.emit(Instruction::Duplicate);
350-
self.emit(Instruction::PrintExpr);
351-
self.emit(Instruction::ReturnValue);
352-
emitted_return = true;
353-
} else {
354-
self.emit(Instruction::PrintExpr);
355-
}
356+
self.emit(Instruction::PrintExpr);
356357
} else {
357358
self.compile_statement(statement)?;
358359
}
359360
}
360361

361-
if !emitted_return {
362+
if let ast::StmtKind::Expr { value } = &last.node {
363+
self.compile_expression(value)?;
364+
self.emit(Instruction::Duplicate);
365+
self.emit(Instruction::PrintExpr);
366+
} else {
367+
self.compile_statement(last)?;
362368
self.emit_constant(ConstantData::None);
363-
self.emit(Instruction::ReturnValue);
364369
}
370+
self.emit(Instruction::ReturnValue);
365371

366372
Ok(())
367373
}
@@ -1046,7 +1052,7 @@ impl Compiler {
10461052
let qualified_name = self.qualified_path.join(".");
10471053
self.push_qualified_path("<locals>");
10481054

1049-
let (body, doc_str) = get_doc(body);
1055+
let (doc_str, body) = split_doc(body);
10501056

10511057
self.compile_statements(body)?;
10521058

@@ -1165,6 +1171,7 @@ impl Compiler {
11651171
true
11661172
}
11671173

1174+
// Python/compile.c find_ann
11681175
fn find_ann(&self, body: &[ast::Stmt]) -> bool {
11691176
use ast::StmtKind::*;
11701177

@@ -1216,7 +1223,7 @@ impl Compiler {
12161223

12171224
self.push_output(bytecode::CodeFlags::empty(), 0, 0, 0, name.to_owned());
12181225

1219-
let (new_body, doc_str) = get_doc(body);
1226+
let (doc_str, body) = split_doc(body);
12201227

12211228
let dunder_name = self.name("__name__");
12221229
self.emit(Instruction::LoadGlobal(dunder_name));
@@ -1234,7 +1241,7 @@ impl Compiler {
12341241
if self.find_ann(body) {
12351242
self.emit(Instruction::SetupAnnotation);
12361243
}
1237-
self.compile_statements(new_body)?;
1244+
self.compile_statements(body)?;
12381245

12391246
let classcell_idx = self
12401247
.code_stack
@@ -2566,15 +2573,15 @@ impl Compiler {
25662573
}
25672574
}
25682575

2569-
fn get_doc(body: &[ast::Stmt]) -> (&[ast::Stmt], Option<String>) {
2576+
fn split_doc(body: &[ast::Stmt]) -> (Option<String>, &[ast::Stmt]) {
25702577
if let Some((val, body_rest)) = body.split_first() {
25712578
if let ast::StmtKind::Expr { value } = &val.node {
25722579
if let Some(doc) = try_get_constant_string(std::slice::from_ref(value)) {
2573-
return (body_rest, Some(doc));
2580+
return (Some(doc), body_rest);
25742581
}
25752582
}
25762583
}
2577-
(body, None)
2584+
(None, body)
25782585
}
25792586

25802587
fn try_get_constant_string(values: &[ast::Expr]) -> Option<String> {

vm/src/builtins/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl PyFunction {
314314
(true, false) => Ok(PyGenerator::new(frame, self.name()).into_pyobject(vm)),
315315
(false, true) => Ok(PyCoroutine::new(frame, self.name()).into_pyobject(vm)),
316316
(true, true) => Ok(PyAsyncGen::new(frame, self.name()).into_pyobject(vm)),
317-
(false, false) => vm.run_frame_full(frame),
317+
(false, false) => vm.run_frame(frame),
318318
}
319319
}
320320

vm/src/vm/mod.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ impl VirtualMachine {
273273

274274
pub fn run_code_obj(&self, code: PyRef<PyCode>, scope: Scope) -> PyResult {
275275
let frame = Frame::new(code, scope, self.builtins.dict(), &[], self).into_ref(self);
276-
self.run_frame_full(frame)
276+
self.run_frame(frame)
277277
}
278278

279279
#[cold]
@@ -297,8 +297,8 @@ impl VirtualMachine {
297297
}
298298

299299
#[inline(always)]
300-
pub fn run_frame_full(&self, frame: FrameRef) -> PyResult {
301-
match self.run_frame(frame)? {
300+
pub fn run_frame(&self, frame: FrameRef) -> PyResult {
301+
match self.with_frame(frame, |f| f.run(self))? {
302302
ExecutionResult::Return(value) => Ok(value),
303303
_ => panic!("Got unexpected result from function"),
304304
}
@@ -333,10 +333,6 @@ impl VirtualMachine {
333333
})
334334
}
335335

336-
pub fn run_frame(&self, frame: FrameRef) -> PyResult<ExecutionResult> {
337-
self.with_frame(frame, |f| f.run(self))
338-
}
339-
340336
// To be called right before raising the recursion depth.
341337
fn check_recursive_call(&self, _where: &str) -> PyResult<()> {
342338
if self.recursion_depth.get() >= self.recursion_limit.get() {

0 commit comments

Comments
 (0)