Skip to content

Commit b4486e6

Browse files
authored
Merge pull request RustPython#3678 from youknowone/block-expr
Add compile::Mode::BlockExpr
2 parents 0b01e04 + beff32a commit b4486e6

File tree

5 files changed

+75
-10
lines changed

5 files changed

+75
-10
lines changed

compiler/porcelain/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ pub fn compile(
7676
source_path: String,
7777
opts: CompileOpts,
7878
) -> Result<CodeObject, CompileError> {
79-
let mode = match mode {
79+
let parser_mode = match mode {
8080
compile::Mode::Exec => parser::Mode::Module,
8181
compile::Mode::Eval => parser::Mode::Expression,
82-
compile::Mode::Single => parser::Mode::Interactive,
82+
compile::Mode::Single | compile::Mode::BlockExpr => parser::Mode::Interactive,
8383
};
84-
let mut ast = match parser::parse(source, mode) {
84+
let mut ast = match parser::parse(source, parser_mode) {
8585
Ok(x) => x,
8686
Err(e) => return Err(CompileError::from_parse(e, source, source_path)),
8787
};
@@ -90,7 +90,8 @@ pub fn compile(
9090
.fold_mod(ast)
9191
.unwrap_or_else(|e| match e {});
9292
}
93-
compile::compile_top(&ast, source_path, opts).map_err(|e| CompileError::from_compile(e, source))
93+
compile::compile_top(&ast, source_path, mode, opts)
94+
.map_err(|e| CompileError::from_compile(e, source))
9495
}
9596

9697
pub fn compile_symtable(
@@ -107,7 +108,7 @@ pub fn compile_symtable(
107108
};
108109
}
109110
let res = match mode {
110-
compile::Mode::Exec | compile::Mode::Single => {
111+
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
111112
let ast = try_parse!(parser::parse_program(source));
112113
symboltable::make_symbol_table(&ast)
113114
}

compiler/src/compile.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,16 @@ impl CompileContext {
104104
pub fn compile_top(
105105
ast: &ast::Mod,
106106
source_path: String,
107+
mode: Mode,
107108
opts: CompileOpts,
108109
) -> CompileResult<CodeObject> {
109110
match ast {
110111
ast::Mod::Module { body, .. } => compile_program(body, source_path, opts),
111-
ast::Mod::Interactive { body } => compile_program_single(body, source_path, opts),
112+
ast::Mod::Interactive { body } => match mode {
113+
Mode::Single => compile_program_single(body, source_path, opts),
114+
Mode::BlockExpr => compile_block_expression(body, source_path, opts),
115+
_ => unreachable!("only Single and BlockExpr parsed to Interactive"),
116+
},
112117
ast::Mod::Expression { body } => compile_expression(body, source_path, opts),
113118
ast::Mod::FunctionType { .. } => panic!("can't compile a FunctionType"),
114119
}
@@ -164,6 +169,20 @@ pub fn compile_program_single(
164169
)
165170
}
166171

172+
pub fn compile_block_expression(
173+
ast: &[ast::Stmt],
174+
source_path: String,
175+
opts: CompileOpts,
176+
) -> CompileResult<CodeObject> {
177+
compile_impl(
178+
ast,
179+
source_path,
180+
opts,
181+
make_symbol_table,
182+
Compiler::compile_block_expr,
183+
)
184+
}
185+
167186
pub fn compile_expression(
168187
ast: &ast::Expr,
169188
source_path: String,
@@ -370,6 +389,35 @@ impl Compiler {
370389
Ok(())
371390
}
372391

392+
fn compile_block_expr(
393+
&mut self,
394+
body: &[ast::Stmt],
395+
symbol_table: SymbolTable,
396+
) -> CompileResult<()> {
397+
self.symbol_table_stack.push(symbol_table);
398+
399+
self.compile_statements(body)?;
400+
401+
if let Some(last_statement) = body.last() {
402+
match last_statement.node {
403+
ast::StmtKind::Expr { .. } => {
404+
self.current_block().instructions.pop(); // pop Instruction::Pop
405+
}
406+
ast::StmtKind::FunctionDef { .. }
407+
| ast::StmtKind::AsyncFunctionDef { .. }
408+
| ast::StmtKind::ClassDef { .. } => {
409+
let store_inst = self.current_block().instructions.pop().unwrap(); // pop Instruction::Store
410+
self.emit(Instruction::Duplicate);
411+
self.current_block().instructions.push(store_inst);
412+
}
413+
_ => self.emit_constant(ConstantData::None),
414+
}
415+
}
416+
self.emit(Instruction::ReturnValue);
417+
418+
Ok(())
419+
}
420+
373421
// Compile statement in eval mode:
374422
fn compile_eval(
375423
&mut self,

compiler/src/mode.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ pub enum Mode {
33
Exec,
44
Eval,
55
Single,
6+
BlockExpr,
67
}
78

89
impl std::str::FromStr for Mode {
910
type Err = ModeParseError;
11+
12+
// To support `builtins.compile()` `mode` argument
1013
fn from_str(s: &str) -> Result<Self, ModeParseError> {
1114
match s {
1215
"exec" => Ok(Mode::Exec),

vm/src/stdlib/ast.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,14 @@ pub(crate) fn compile(
269269
vm: &VirtualMachine,
270270
object: PyObjectRef,
271271
filename: &str,
272-
_mode: compile::Mode,
272+
mode: compile::Mode,
273273
) -> PyResult {
274274
let opts = vm.compile_opts();
275275
let ast = Node::ast_from_object(vm, object)?;
276-
let code = rustpython_compiler_core::compile::compile_top(&ast, filename.to_owned(), opts)
277-
// TODO: use vm.new_syntax_error()
278-
.map_err(|err| vm.new_value_error(err.to_string()))?;
276+
let code =
277+
rustpython_compiler_core::compile::compile_top(&ast, filename.to_owned(), mode, opts)
278+
// TODO: use vm.new_syntax_error()
279+
.map_err(|err| vm.new_value_error(err.to_string()))?;
279280
Ok(vm.ctx.new_code(code).into())
280281
}
281282

vm/src/vm/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,18 @@ impl VirtualMachine {
767767
self.run_code_obj(code_obj, scope)
768768
}
769769

770+
pub fn run_block_expr(&self, scope: Scope, source: &str) -> PyResult {
771+
let code_obj = self
772+
.compile(
773+
source,
774+
crate::compile::Mode::BlockExpr,
775+
"<embedded>".to_owned(),
776+
)
777+
.map_err(|err| self.new_syntax_error(&err))?;
778+
// trace!("Code object: {:?}", code_obj.borrow());
779+
self.run_code_obj(code_obj, scope)
780+
}
781+
770782
pub fn run_module(&self, module: &str) -> PyResult<()> {
771783
let runpy = self.import("runpy", None, 0)?;
772784
let run_module_as_main = runpy.get_attr("_run_module_as_main", self)?;

0 commit comments

Comments
 (0)