diff --git a/src/bytecode.rs b/src/bytecode.rs index 0fc226b..aede69c 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -1,10 +1,6 @@ //! Implement python as a virtual machine with bytecodes. This module //! implements bytecode structure. -/* - * Primitive instruction type, which can be encoded and decoded. - */ - use bitflags::bitflags; use num_bigint::BigInt; use num_complex::Complex64; diff --git a/src/compile.rs b/src/compile.rs index dec158e..30510c2 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -24,33 +24,66 @@ struct Compiler { /// Compile a given sourcecode into a bytecode object. pub fn compile(source: &str, mode: &Mode, source_path: String) -> Result { - let mut compiler = Compiler::new(); - compiler.source_path = Some(source_path); - compiler.push_new_code_object("".to_string()); - match mode { Mode::Exec => { let ast = parser::parse_program(source)?; - let symbol_table = make_symbol_table(&ast)?; - compiler.compile_program(&ast, symbol_table) + compile_program(ast, source_path) } Mode::Eval => { let statement = parser::parse_statement(source)?; - let symbol_table = statements_to_symbol_table(&statement)?; - compiler.compile_statement_eval(&statement, symbol_table) + compile_statement_eval(statement, source_path) } Mode::Single => { let ast = parser::parse_program(source)?; - let symbol_table = make_symbol_table(&ast)?; - compiler.compile_program_single(&ast, symbol_table) + compile_program_single(ast, source_path) } - }?; + } +} +/// A helper function for the shared code of the different compile functions +fn with_compiler( + source_path: String, + f: impl FnOnce(&mut Compiler) -> Result<(), CompileError>, +) -> Result { + let mut compiler = Compiler::new(); + compiler.source_path = Some(source_path); + compiler.push_new_code_object("".to_string()); + f(&mut compiler)?; let code = compiler.pop_code_object(); trace!("Compilation completed: {:?}", code); Ok(code) } +/// Compile a standard Python program to bytecode +pub fn compile_program(ast: ast::Program, source_path: String) -> Result { + with_compiler(source_path, |compiler| { + let symbol_table = make_symbol_table(&ast)?; + compiler.compile_program(&ast, symbol_table) + }) +} + +/// Compile a single Python expression to bytecode +pub fn compile_statement_eval( + statement: Vec, + source_path: String, +) -> Result { + with_compiler(source_path, |compiler| { + let symbol_table = statements_to_symbol_table(&statement)?; + compiler.compile_statement_eval(&statement, symbol_table) + }) +} + +/// Compile a Python program to bytecode for the context of a REPL +pub fn compile_program_single( + ast: ast::Program, + source_path: String, +) -> Result { + with_compiler(source_path, |compiler| { + let symbol_table = make_symbol_table(&ast)?; + compiler.compile_program_single(&ast, symbol_table) + }) +} + pub enum Mode { Exec, Eval, diff --git a/src/lib.rs b/src/lib.rs index 1f0805c..382647d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +//! Compile a Python AST or source code into bytecode consumable by RustPython or +//! (eventually) CPython. + #[macro_use] extern crate log;