diff --git a/compiler/src/bytecode.rs b/compiler/src/bytecode.rs index b5b3c11d3..c87bc0ae0 100644 --- a/compiler/src/bytecode.rs +++ b/compiler/src/bytecode.rs @@ -21,7 +21,7 @@ pub struct CodeObject { pub varargs: Varargs, // *args or * pub kwonlyarg_names: Vec, pub varkeywords: Varargs, // **kwargs or ** - pub source_path: Option, + pub source_path: String, pub first_line_number: usize, pub obj_name: String, // Name of the object that created this code object pub is_generator: bool, @@ -269,7 +269,7 @@ impl CodeObject { varargs: Varargs, kwonlyarg_names: Vec, varkeywords: Varargs, - source_path: Option, + source_path: String, first_line_number: usize, obj_name: String, ) -> CodeObject { diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index 0efa3adfb..8b806b1d1 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -23,11 +23,7 @@ struct Compiler { } /// Compile a given sourcecode into a bytecode object. -pub fn compile( - source: &str, - mode: &Mode, - source_path: Option, -) -> Result { +pub fn compile(source: &str, mode: &Mode, source_path: String) -> Result { match mode { Mode::Exec => { let ast = parser::parse_program(source)?; @@ -46,11 +42,11 @@ pub fn compile( /// A helper function for the shared code of the different compile functions fn with_compiler( - source_path: Option, + source_path: String, f: impl FnOnce(&mut Compiler) -> Result<(), CompileError>, ) -> Result { let mut compiler = Compiler::new(); - compiler.source_path = source_path; + compiler.source_path = Some(source_path); compiler.push_new_code_object("".to_string()); f(&mut compiler)?; let code = compiler.pop_code_object(); @@ -59,10 +55,7 @@ fn with_compiler( } /// Compile a standard Python program to bytecode -pub fn compile_program( - ast: ast::Program, - source_path: Option, -) -> Result { +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) @@ -72,7 +65,7 @@ pub fn compile_program( /// Compile a single Python expression to bytecode pub fn compile_statement_eval( statement: Vec, - source_path: Option, + source_path: String, ) -> Result { with_compiler(source_path, |compiler| { let symbol_table = statements_to_symbol_table(&statement)?; @@ -83,7 +76,7 @@ pub fn compile_statement_eval( /// Compile a Python program to bytecode for the context of a REPL pub fn compile_program_single( ast: ast::Program, - source_path: Option, + source_path: String, ) -> Result { with_compiler(source_path, |compiler| { let symbol_table = make_symbol_table(&ast)?; @@ -126,7 +119,7 @@ impl Compiler { Varargs::None, Vec::new(), Varargs::None, - self.source_path.clone(), + self.source_path.clone().unwrap(), line_number, obj_name, )); @@ -603,7 +596,7 @@ impl Compiler { Varargs::from(&args.vararg), args.kwonlyargs.iter().map(|a| a.arg.clone()).collect(), Varargs::from(&args.kwarg), - self.source_path.clone(), + self.source_path.clone().unwrap(), line_number, name.to_string(), )); @@ -856,7 +849,7 @@ impl Compiler { Varargs::None, vec![], Varargs::None, - self.source_path.clone(), + self.source_path.clone().unwrap(), line_number, name.to_string(), )); @@ -1578,7 +1571,7 @@ impl Compiler { Varargs::None, vec![], Varargs::None, - self.source_path.clone(), + self.source_path.clone().unwrap(), line_number, name.clone(), )); diff --git a/derive/src/compile_bytecode.rs b/derive/src/compile_bytecode.rs index 4c9946f89..35db2eb04 100644 --- a/derive/src/compile_bytecode.rs +++ b/derive/src/compile_bytecode.rs @@ -35,11 +35,7 @@ struct CompilationSource { } impl CompilationSource { - fn compile( - self, - mode: &compile::Mode, - source_path: Option, - ) -> Result { + fn compile(self, mode: &compile::Mode, source_path: String) -> Result { let compile = |source| { compile::compile(source, mode, source_path).map_err(|err| { Diagnostic::spans_error(self.span, format!("Compile error: {}", err)) @@ -139,7 +135,10 @@ impl PyCompileInput { "Must have either file or source in py_compile_bytecode!()", ) })? - .compile(&mode.unwrap_or(compile::Mode::Exec), source_path) + .compile( + &mode.unwrap_or(compile::Mode::Exec), + source_path.unwrap_or_else(|| "frozen".to_string()), + ) } } diff --git a/src/main.rs b/src/main.rs index 895ea6290..5d4d2b9e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,7 @@ fn main() { fn _run_string(vm: &VirtualMachine, source: &str, source_path: String) -> PyResult { let code_obj = vm - .compile(source, &compile::Mode::Exec, Some(source_path.clone())) + .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(); @@ -161,7 +161,7 @@ fn test_run_script() { } fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> Result<(), CompileError> { - match vm.compile(source, &compile::Mode::Single, Some("".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/src/builtins.rs b/vm/src/builtins.rs index 1d82ae121..570b1fbbf 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -122,7 +122,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); - vm.compile(&source, &mode, Some("".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())); @@ -199,7 +199,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); - vm.compile(&source, &mode, Some("".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 706c7271f..e326e300e 100644 --- a/vm/src/eval.rs +++ b/vm/src/eval.rs @@ -1,15 +1,12 @@ +extern crate rustpython_parser; + use crate::compile; use crate::frame::Scope; use crate::pyobject::PyResult; use crate::vm::VirtualMachine; -pub fn eval( - vm: &VirtualMachine, - source: &str, - scope: Scope, - source_path: Option, -) -> PyResult { - match vm.compile(source, &compile::Mode::Eval, source_path) { +pub fn eval(vm: &VirtualMachine, source: &str, scope: Scope, source_path: &str) -> PyResult { + match vm.compile(source, &compile::Mode::Eval, source_path.to_string()) { Ok(bytecode) => { debug!("Code object: {:?}", bytecode); vm.run_code_obj(bytecode, scope) @@ -28,7 +25,7 @@ mod tests { let source = String::from("print('Hello world')\n"); let mut vm = VirtualMachine::new(); let vars = vm.new_scope_with_builtins(); - let _result = eval(&mut vm, &source, vars, Some("".to_string())); + let _result = eval(&mut vm, &source, vars, ""); // TODO: check result? //assert_eq!( diff --git a/vm/src/frame.rs b/vm/src/frame.rs index c671fc5bd..8ea114854 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -271,10 +271,7 @@ impl Frame { } pub fn run(&self, vm: &VirtualMachine) -> Result { - let filename = match self.code.source_path.clone() { - Some(s) => vm.ctx.new_str(s), - None => vm.get_none(), - }; + let filename = &self.code.source_path.to_string(); // This is the name of the object being run: let run_obj_name = &self.code.obj_name.to_string(); @@ -302,7 +299,7 @@ impl Frame { .unwrap(); trace!("Adding to traceback: {:?} {:?}", traceback, lineno); let raise_location = vm.ctx.new_tuple(vec![ - filename.clone(), + vm.ctx.new_str(filename.clone()), vm.ctx.new_int(lineno.get_row()), vm.ctx.new_str(run_obj_name.clone()), ]); diff --git a/vm/src/import.rs b/vm/src/import.rs index 84f89d91c..ad1fd8e6a 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -25,12 +25,13 @@ pub fn init_importlib(vm: &VirtualMachine) -> PyResult { } pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult { - vm.frozen - .borrow() - .get(module_name) - .cloned() - .ok_or_else(|| vm.new_import_error(format!("Cannot import frozen module {}", module_name))) - .and_then(|frozen| import_codeobj(vm, module_name, frozen)) + if let Some(frozen) = vm.frozen.borrow().get(module_name) { + let mut frozen = frozen.clone(); + frozen.source_path = format!("frozen {}", module_name); + import_codeobj(vm, module_name, frozen) + } else { + Err(vm.new_import_error(format!("Cannot import frozen module {}", module_name))) + } } pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult { @@ -68,7 +69,7 @@ pub fn import_module(vm: &VirtualMachine, current_path: PathBuf, module_name: &s import_file( vm, module_name, - Some(file_path.to_str().unwrap().to_string()), + file_path.to_str().unwrap().to_string(), source, ) } @@ -77,7 +78,7 @@ pub fn import_module(vm: &VirtualMachine, current_path: PathBuf, module_name: &s pub fn import_file( vm: &VirtualMachine, module_name: &str, - file_path: Option, + file_path: String, content: String, ) -> PyResult { let code_obj = compile::compile(&content, &compile::Mode::Exec, file_path) @@ -88,8 +89,10 @@ pub fn import_file( pub fn import_codeobj(vm: &VirtualMachine, module_name: &str, code_obj: CodeObject) -> PyResult { let attrs = vm.ctx.new_dict(); attrs.set_item("__name__", vm.new_str(module_name.to_string()), vm)?; - if let Some(source_path) = &code_obj.source_path { - attrs.set_item("__file__", vm.new_str(source_path.to_owned()), vm)?; + let file_path = &code_obj.source_path; + if !file_path.starts_with("frozen") { + // TODO: Should be less hacky, not depend on source_path + attrs.set_item("__file__", vm.new_str(file_path.to_owned()), vm)?; } let module = vm.ctx.new_module(module_name, attrs.clone()); diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 17d3e743d..51a73d614 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -54,7 +54,7 @@ impl PyCodeRef { self.code.arg_names.len() } - fn co_filename(self, _vm: &VirtualMachine) -> Option { + fn co_filename(self, _vm: &VirtualMachine) -> String { self.code.source_path.clone() } diff --git a/vm/src/stdlib/imp.rs b/vm/src/stdlib/imp.rs index 96437187e..184fc5003 100644 --- a/vm/src/stdlib/imp.rs +++ b/vm/src/stdlib/imp.rs @@ -58,8 +58,11 @@ fn imp_get_frozen_object(name: PyStringRef, vm: &VirtualMachine) -> PyResult, + source_path: String, ) -> Result { compile::compile(source, mode, source_path) .map(|codeobj| PyCode::new(codeobj).into_ref(self)) diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index b2b59ecd2..b3d689d3f 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -373,7 +373,7 @@ fn browser_load_module(module: PyStringRef, path: PyStringRef, vm: &VirtualMachi .expect("that the vm is valid when the promise resolves"); let vm = &stored_vm.vm; let resp_text = text.as_string().unwrap(); - let res = import_file(vm, module.as_str(), Some("WEB".to_string()), resp_text); + let res = import_file(vm, module.as_str(), "WEB".to_string(), resp_text); match res { Ok(_) => Ok(JsValue::null()), Err(err) => Err(convert::py_err_to_js_err(vm, &err)), diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index efa7d503b..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 = vm.compile(&source, &mode, Some("".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) =