Merge pull request #3678 from youknowone/block-expr

Add compile::Mode::BlockExpr
This commit is contained in:
Jeong YunWon
2022-05-27 10:44:29 +09:00
committed by GitHub
5 changed files with 75 additions and 10 deletions

View File

@@ -76,12 +76,12 @@ pub fn compile(
source_path: String,
opts: CompileOpts,
) -> Result<CodeObject, CompileError> {
let mode = match mode {
let parser_mode = match mode {
compile::Mode::Exec => parser::Mode::Module,
compile::Mode::Eval => parser::Mode::Expression,
compile::Mode::Single => parser::Mode::Interactive,
compile::Mode::Single | compile::Mode::BlockExpr => parser::Mode::Interactive,
};
let mut ast = match parser::parse(source, mode) {
let mut ast = match parser::parse(source, parser_mode) {
Ok(x) => x,
Err(e) => return Err(CompileError::from_parse(e, source, source_path)),
};
@@ -90,7 +90,8 @@ pub fn compile(
.fold_mod(ast)
.unwrap_or_else(|e| match e {});
}
compile::compile_top(&ast, source_path, opts).map_err(|e| CompileError::from_compile(e, source))
compile::compile_top(&ast, source_path, mode, opts)
.map_err(|e| CompileError::from_compile(e, source))
}
pub fn compile_symtable(
@@ -107,7 +108,7 @@ pub fn compile_symtable(
};
}
let res = match mode {
compile::Mode::Exec | compile::Mode::Single => {
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
let ast = try_parse!(parser::parse_program(source));
symboltable::make_symbol_table(&ast)
}

View File

@@ -104,11 +104,16 @@ impl CompileContext {
pub fn compile_top(
ast: &ast::Mod,
source_path: String,
mode: Mode,
opts: CompileOpts,
) -> CompileResult<CodeObject> {
match ast {
ast::Mod::Module { body, .. } => compile_program(body, source_path, opts),
ast::Mod::Interactive { body } => compile_program_single(body, source_path, opts),
ast::Mod::Interactive { body } => match mode {
Mode::Single => compile_program_single(body, source_path, opts),
Mode::BlockExpr => compile_block_expression(body, source_path, opts),
_ => unreachable!("only Single and BlockExpr parsed to Interactive"),
},
ast::Mod::Expression { body } => compile_expression(body, source_path, opts),
ast::Mod::FunctionType { .. } => panic!("can't compile a FunctionType"),
}
@@ -164,6 +169,20 @@ pub fn compile_program_single(
)
}
pub fn compile_block_expression(
ast: &[ast::Stmt],
source_path: String,
opts: CompileOpts,
) -> CompileResult<CodeObject> {
compile_impl(
ast,
source_path,
opts,
make_symbol_table,
Compiler::compile_block_expr,
)
}
pub fn compile_expression(
ast: &ast::Expr,
source_path: String,
@@ -370,6 +389,35 @@ impl Compiler {
Ok(())
}
fn compile_block_expr(
&mut self,
body: &[ast::Stmt],
symbol_table: SymbolTable,
) -> CompileResult<()> {
self.symbol_table_stack.push(symbol_table);
self.compile_statements(body)?;
if let Some(last_statement) = body.last() {
match last_statement.node {
ast::StmtKind::Expr { .. } => {
self.current_block().instructions.pop(); // pop Instruction::Pop
}
ast::StmtKind::FunctionDef { .. }
| ast::StmtKind::AsyncFunctionDef { .. }
| ast::StmtKind::ClassDef { .. } => {
let store_inst = self.current_block().instructions.pop().unwrap(); // pop Instruction::Store
self.emit(Instruction::Duplicate);
self.current_block().instructions.push(store_inst);
}
_ => self.emit_constant(ConstantData::None),
}
}
self.emit(Instruction::ReturnValue);
Ok(())
}
// Compile statement in eval mode:
fn compile_eval(
&mut self,

View File

@@ -3,10 +3,13 @@ pub enum Mode {
Exec,
Eval,
Single,
BlockExpr,
}
impl std::str::FromStr for Mode {
type Err = ModeParseError;
// To support `builtins.compile()` `mode` argument
fn from_str(s: &str) -> Result<Self, ModeParseError> {
match s {
"exec" => Ok(Mode::Exec),

View File

@@ -269,13 +269,14 @@ pub(crate) fn compile(
vm: &VirtualMachine,
object: PyObjectRef,
filename: &str,
_mode: compile::Mode,
mode: compile::Mode,
) -> PyResult {
let opts = vm.compile_opts();
let ast = Node::ast_from_object(vm, object)?;
let code = rustpython_compiler_core::compile::compile_top(&ast, filename.to_owned(), opts)
// TODO: use vm.new_syntax_error()
.map_err(|err| vm.new_value_error(err.to_string()))?;
let code =
rustpython_compiler_core::compile::compile_top(&ast, filename.to_owned(), mode, opts)
// TODO: use vm.new_syntax_error()
.map_err(|err| vm.new_value_error(err.to_string()))?;
Ok(vm.ctx.new_code(code).into())
}

View File

@@ -767,6 +767,18 @@ impl VirtualMachine {
self.run_code_obj(code_obj, scope)
}
pub fn run_block_expr(&self, scope: Scope, source: &str) -> PyResult {
let code_obj = self
.compile(
source,
crate::compile::Mode::BlockExpr,
"<embedded>".to_owned(),
)
.map_err(|err| self.new_syntax_error(&err))?;
// trace!("Code object: {:?}", code_obj.borrow());
self.run_code_obj(code_obj, scope)
}
pub fn run_module(&self, module: &str) -> PyResult<()> {
let runpy = self.import("runpy", None, 0)?;
let run_module_as_main = runpy.get_attr("_run_module_as_main", self)?;