diff --git a/Cargo.lock b/Cargo.lock index f54307d02..7bb6469d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -898,6 +898,18 @@ dependencies = [ "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustpython_compiler" +version = "0.1.0" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustpython_parser 0.0.1", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustpython_derive" version = "0.1.0" @@ -927,7 +939,6 @@ name = "rustpython_vm" version = "0.1.0" dependencies = [ "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -946,6 +957,7 @@ dependencies = [ "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version_runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustpython_compiler 0.1.0", "rustpython_derive 0.1.0", "rustpython_parser 0.0.1", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 71db1d839..2a4fc23bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Windel Bouwman", "Shing Lyu "] edition = "2018" [workspace] -members = [".", "derive", "vm", "wasm/lib", "parser"] +members = [".", "derive", "vm", "wasm/lib", "parser", "compiler"] [[bench]] name = "bench" diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml new file mode 100644 index 000000000..fc0d19593 --- /dev/null +++ b/compiler/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rustpython_compiler" +version = "0.1.0" +authors = ["coolreader18 <33094578+coolreader18@users.noreply.github.com>"] +edition = "2018" + +[dependencies] +bitflags = "1.1" +rustpython_parser = { path = "../parser" } +serde = { version = "1.0", features = ["derive"] } +num-complex = { version = "0.2", features = ["serde"] } +num-bigint = { version = "0.2", features = ["serde"] } +log = "0.3" diff --git a/vm/src/bytecode.rs b/compiler/src/bytecode.rs similarity index 99% rename from vm/src/bytecode.rs rename to compiler/src/bytecode.rs index 5df445d74..0fc226b5b 100644 --- a/vm/src/bytecode.rs +++ b/compiler/src/bytecode.rs @@ -5,6 +5,7 @@ * Primitive instruction type, which can be encoded and decoded. */ +use bitflags::bitflags; use num_bigint::BigInt; use num_complex::Complex64; use rustpython_parser::ast; diff --git a/vm/src/compile.rs b/compiler/src/compile.rs similarity index 99% rename from vm/src/compile.rs rename to compiler/src/compile.rs index b1964ca55..dec158e9b 100644 --- a/vm/src/compile.rs +++ b/compiler/src/compile.rs @@ -7,11 +7,7 @@ use crate::bytecode::{self, CallType, CodeObject, Instruction, Varargs}; use crate::error::{CompileError, CompileErrorType}; -use crate::obj::objcode; -use crate::obj::objcode::PyCodeRef; -use crate::pyobject::PyValue; use crate::symboltable::{make_symbol_table, statements_to_symbol_table, SymbolRole, SymbolScope}; -use crate::VirtualMachine; use num_complex::Complex64; use rustpython_parser::{ast, parser}; @@ -27,12 +23,7 @@ struct Compiler { } /// Compile a given sourcecode into a bytecode object. -pub fn compile( - vm: &VirtualMachine, - source: &str, - mode: &Mode, - source_path: String, -) -> Result { +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()); @@ -57,7 +48,7 @@ pub fn compile( let code = compiler.pop_code_object(); trace!("Compilation completed: {:?}", code); - Ok(objcode::PyCode::new(code).into_ref(vm)) + Ok(code) } pub enum Mode { diff --git a/vm/src/error.rs b/compiler/src/error.rs similarity index 100% rename from vm/src/error.rs rename to compiler/src/error.rs diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs new file mode 100644 index 000000000..1f0805c65 --- /dev/null +++ b/compiler/src/lib.rs @@ -0,0 +1,7 @@ +#[macro_use] +extern crate log; + +pub mod bytecode; +pub mod compile; +pub mod error; +mod symboltable; diff --git a/vm/src/symboltable.rs b/compiler/src/symboltable.rs similarity index 100% rename from vm/src/symboltable.rs rename to compiler/src/symboltable.rs diff --git a/src/main.rs b/src/main.rs index 84d2af51f..5d4d2b9e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,7 +75,8 @@ fn main() { } fn _run_string(vm: &VirtualMachine, source: &str, source_path: String) -> PyResult { - let code_obj = compile::compile(vm, source, &compile::Mode::Exec, source_path.clone()) + let code_obj = vm + .compile(source, &compile::Mode::Exec, source_path.clone()) .map_err(|err| vm.new_syntax_error(&err))?; // trace!("Code object: {:?}", code_obj.borrow()); let attrs = vm.ctx.new_dict(); @@ -160,7 +161,7 @@ fn test_run_script() { } fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> Result<(), CompileError> { - match compile::compile(vm, source, &compile::Mode::Single, "".to_string()) { + match vm.compile(source, &compile::Mode::Single, "".to_string()) { Ok(code) => { match vm.run_code_obj(code, scope.clone()) { Ok(value) => { diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 2868ab65f..de53223ae 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Shing Lyu "] edition = "2018" [dependencies] -bitflags = "1.0.4" num-complex = { version = "0.2", features = ["serde"] } num-bigint = { version = "0.2.1", features = ["serde"] } num-traits = "0.2" @@ -15,6 +14,7 @@ rand = "0.5" log = "0.3" rustpython_derive = {path = "../derive"} rustpython_parser = {path = "../parser"} +rustpython_compiler = {path = "../compiler"} serde = { version = "1.0.66", features = ["derive"] } serde_json = "1.0.26" byteorder = "1.2.6" diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 0673dd908..9779a5054 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -121,7 +121,7 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult PyResult { let source = objstr::get_value(source); // TODO: fix this newline bug: let source = format!("{}\n", source); - compile::compile(vm, &source, &mode, "".to_string()) + vm.compile(&source, &mode, "".to_string()) .map_err(|err| vm.new_syntax_error(&err))? } else { return Err(vm.new_type_error("code argument must be str or code object".to_string())); @@ -198,7 +198,7 @@ fn builtin_exec(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let source = objstr::get_value(source); // TODO: fix this newline bug: let source = format!("{}\n", source); - compile::compile(vm, &source, &mode, "".to_string()) + vm.compile(&source, &mode, "".to_string()) .map_err(|err| vm.new_syntax_error(&err))? } else if let Ok(code_obj) = PyCodeRef::try_from_object(vm, source.clone()) { code_obj diff --git a/vm/src/eval.rs b/vm/src/eval.rs index a927f8f03..e326e300e 100644 --- a/vm/src/eval.rs +++ b/vm/src/eval.rs @@ -6,7 +6,7 @@ use crate::pyobject::PyResult; use crate::vm::VirtualMachine; pub fn eval(vm: &VirtualMachine, source: &str, scope: Scope, source_path: &str) -> PyResult { - match compile::compile(vm, source, &compile::Mode::Eval, source_path.to_string()) { + match vm.compile(source, &compile::Mode::Eval, source_path.to_string()) { Ok(bytecode) => { debug!("Code object: {:?}", bytecode); vm.run_code_obj(bytecode, scope) diff --git a/vm/src/import.rs b/vm/src/import.rs index 554d5e15e..a24e936dc 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -84,7 +84,8 @@ pub fn import_file( content: String, ) -> PyResult { let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules").unwrap(); - let code_obj = compile::compile(vm, &content, &compile::Mode::Exec, file_path.clone()) + let code_obj = vm + .compile(&content, &compile::Mode::Exec, file_path.clone()) .map_err(|err| vm.new_syntax_error(&err))?; // trace!("Code object: {:?}", code_obj); diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 24f28709e..269a0a3b5 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -12,8 +12,6 @@ clippy::implicit_hasher )] -#[macro_use] -extern crate bitflags; #[macro_use] extern crate lazy_static; extern crate lexical; @@ -37,10 +35,7 @@ pub use rustpython_derive::*; pub mod macros; mod builtins; -pub mod bytecode; -pub mod compile; mod dictdatatype; -pub mod error; pub mod eval; mod exceptions; pub mod format; @@ -52,7 +47,6 @@ pub mod obj; mod pyhash; pub mod pyobject; pub mod stdlib; -mod symboltable; mod sysmodule; mod traceback; pub mod util; @@ -61,3 +55,4 @@ mod vm; // pub use self::pyobject::Executor; pub use self::exceptions::print_exception; pub use self::vm::VirtualMachine; +pub use rustpython_compiler::*; diff --git a/vm/src/stdlib/imp.rs b/vm/src/stdlib/imp.rs index fbf0247a0..fda6f11cd 100644 --- a/vm/src/stdlib/imp.rs +++ b/vm/src/stdlib/imp.rs @@ -58,13 +58,8 @@ fn imp_exec_builtin(_mod: PyModuleRef, _vm: &VirtualMachine) -> i32 { fn imp_get_frozen_object(name: PyStringRef, vm: &VirtualMachine) -> PyResult { let name_str = name.as_str(); if let Some(frozen) = vm.frozen.borrow().get(name_str) { - compile::compile( - vm, - frozen, - &compile::Mode::Exec, - format!("frozen {}", name_str), - ) - .map_err(|err| vm.new_syntax_error(&err)) + vm.compile(frozen, &compile::Mode::Exec, format!("frozen {}", name_str)) + .map_err(|err| vm.new_syntax_error(&err)) } else { Err(vm.new_import_error(format!("No such frozen object named {}", name.as_str()))) } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 91543532f..3f23742a1 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -4,8 +4,6 @@ //! https://github.com/ProgVal/pythonvm-rust/blob/master/src/processor/mod.rs //! -extern crate rustpython_parser; - use std::cell::{Ref, RefCell}; use std::collections::hash_map::HashMap; use std::collections::hash_set::HashSet; @@ -14,13 +12,14 @@ use std::sync::{Mutex, MutexGuard}; use crate::builtins; use crate::bytecode; +use crate::compile; use crate::error::CompileError; use crate::frame::{ExecutionResult, Frame, FrameRef, Scope}; use crate::frozen; use crate::function::PyFuncArgs; use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; -use crate::obj::objcode::PyCodeRef; +use crate::obj::objcode::{PyCode, PyCodeRef}; use crate::obj::objdict::PyDictRef; use crate::obj::objfunction::{PyFunction, PyMethod}; use crate::obj::objgenerator::PyGenerator; @@ -736,6 +735,16 @@ impl VirtualMachine { ) } + pub fn compile( + &self, + source: &str, + mode: &compile::Mode, + source_path: String, + ) -> Result { + compile::compile(source, mode, source_path) + .map(|codeobj| PyCode::new(codeobj).into_ref(self)) + } + pub fn _sub(&self, a: PyObjectRef, b: PyObjectRef) -> PyResult { self.call_or_reflection(a, b, "__sub__", "__rsub__", |vm, a, b| { Err(vm.new_unsupported_operand_error(a, b, "-")) diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index f9040dfcb..9526941ff 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -263,7 +263,7 @@ impl WASMVirtualMachine { ref vm, ref scope, .. }| { source.push('\n'); - let code = compile::compile(vm, &source, &mode, "".to_string()); + let code = vm.compile(&source, &mode, "".to_string()); let code = code.map_err(|err| { let js_err = SyntaxError::new(&format!("Error parsing Python code: {}", err)); if let rustpython_vm::error::CompileErrorType::Parse(ref parse_error) =