diff --git a/Cargo.lock b/Cargo.lock index 5320d8ad0..917ffed37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1560,6 +1560,13 @@ dependencies = [ "winreg", ] +[[package]] +name = "rustpython_freeze" +version = "0.1.0-pre-alpha.2" +dependencies = [ + "rustpython-vm", +] + [[package]] name = "rustpython_wasm" version = "0.1.0-pre-alpha.2" diff --git a/Cargo.toml b/Cargo.toml index ee3ec2814..92ba3d970 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/RustPython/RustPython" license = "MIT" [workspace] -members = [".", "derive", "vm", "wasm/lib", "parser", "compiler", "bytecode"] +members = [".", "derive", "vm", "wasm/lib", "parser", "compiler", "bytecode", "examples/freeze"] [[bench]] name = "bench" diff --git a/examples/freeze/Cargo.toml b/examples/freeze/Cargo.toml new file mode 100644 index 000000000..514569895 --- /dev/null +++ b/examples/freeze/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustpython_freeze" +version = "0.1.0-pre-alpha.2" +authors = ["RustPython Team"] +license = "MIT" +description = "A Python-3 (CPython >= 3.5.0) Interpreter written in Rust, compiled to frozen executable" +repository = "https://github.com/RustPython/RustPython/tree/master/freeze" +edition = "2018" + +[[bin]] +name = "rustpython_freeze" +path = "src/main.rs" + + +[dependencies] +rustpython-vm = { path = "../../vm", default-features = false } diff --git a/examples/freeze/freeze.py b/examples/freeze/freeze.py new file mode 100644 index 000000000..c600ebf95 --- /dev/null +++ b/examples/freeze/freeze.py @@ -0,0 +1,4 @@ +import time + +print("Hello world!!!", time.time()) + diff --git a/examples/freeze/src/main.rs b/examples/freeze/src/main.rs new file mode 100644 index 000000000..0bd9f8f5f --- /dev/null +++ b/examples/freeze/src/main.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; + +use rustpython_vm as vm; + +fn main() -> vm::pyobject::PyResult<()> { + let vm = vm::VirtualMachine::new(vm::PySettings::default()); + + let scope = vm.new_scope_with_builtins(); + + let modules: HashMap = + vm::py_compile_bytecode!(file = "freeze.py"); + + let res = vm.run_code_obj( + vm.ctx + .new_code_object(modules.get("frozen").unwrap().code.clone()), + scope, + ); + + if let Err(err) = res { + vm::exceptions::print_exception(&vm, &err) + } + + Ok(()) +} diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 69d1e9449..93ad9607f 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -11,6 +11,8 @@ use num_bigint::Sign; use num_traits::{Signed, ToPrimitive, Zero}; #[cfg(feature = "rustpython-compiler")] use rustpython_compiler::compile; +#[cfg(feature = "rustpython-parser")] +use rustpython_parser::parser; use crate::exceptions::PyBaseExceptionRef; use crate::function::{single_or_tuple_any, Args, KwArgs, OptionalArg, PyFuncArgs}; @@ -32,6 +34,7 @@ use crate::pyobject::{ }; use crate::readline::{Readline, ReadlineResult}; use crate::scope::Scope; +#[cfg(feature = "rustpython-parser")] use crate::stdlib::ast; use crate::vm::VirtualMachine; @@ -125,6 +128,7 @@ struct CompileArgs { optimize: OptionalArg, } +#[cfg(feature = "rustpython-compiler")] fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { // TODO: compile::compile should probably get bytes let source = match &args.source { @@ -138,9 +142,9 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { .flags .map_or(Ok(0), |v| i32::try_from_object(vm, v.into_object()))?; - if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { - #[cfg(feature = "rustpython-compiler")] - { + #[cfg(feature = "rustpython-parser")] + { + if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { let mode = mode_str .parse::() .map_err(|err| vm.new_value_error(err.to_string()))?; @@ -148,17 +152,18 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { vm.compile(&source, mode, args.filename.as_str().to_owned()) .map(|o| o.into_object()) .map_err(|err| vm.new_syntax_error(&err)) + } else { + let mode = mode_str + .parse::() + .map_err(|err| vm.new_value_error(err.to_string()))?; + ast::parse(&vm, &source, mode) } - #[cfg(not(feature = "rustpython-compiler"))] - { - Err(vm.new_value_error("PyCF_ONLY_AST flag is required without compiler support")) - } - } else { - use rustpython_parser::parser; - let mode = mode_str - .parse::() - .map_err(|err| vm.new_value_error(err.to_string()))?; - ast::parse(&vm, &source, mode) + } + #[cfg(not(feature = "rustpython-parser"))] + { + Err(vm.new_value_error( + "PyCF_ONLY_AST flag is not supported without parser support".to_string(), + )) } } @@ -217,6 +222,7 @@ fn builtin_exec( run_code(vm, source, scope, compile::Mode::Exec) } +#[cfg(feature = "rustpython-compiler")] fn run_code( vm: &VirtualMachine, source: Either, @@ -237,6 +243,7 @@ fn run_code( vm.run_code_obj(code_obj, scope) } +#[cfg(feature = "rustpython-compiler")] fn make_scope(vm: &VirtualMachine, scope: ScopeArgs) -> PyResult { let globals = scope.globals; let current_scope = vm.current_scope(); @@ -776,6 +783,7 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) { extend_module!(vm, module, { "eval" => ctx.new_function(builtin_eval), "exec" => ctx.new_function(builtin_exec), + "compile" => ctx.new_function(builtin_compile), }); } @@ -796,7 +804,6 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) { "callable" => ctx.new_function(builtin_callable), "chr" => ctx.new_function(builtin_chr), "classmethod" => ctx.classmethod_type(), - "compile" => ctx.new_function(builtin_compile), "complex" => ctx.complex_type(), "delattr" => ctx.new_function(builtin_delattr), "dict" => ctx.dict_type(),