From 2e54f9a8076f40626a40e33e4fa4c540c8b0be43 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 14 Dec 2019 22:05:15 +0900 Subject: [PATCH] implement SyntaxError attributes --- compiler/src/compile.rs | 19 ++++++++++++++++--- compiler/src/error.rs | 7 +++++++ compiler/src/symboltable.rs | 1 + vm/src/exceptions.rs | 8 ++++++++ vm/src/stdlib/symtable.rs | 8 +++++--- vm/src/vm.rs | 10 ++++++++++ 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index e4bf20844..39f550d0e 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -63,17 +63,21 @@ pub fn compile( match mode { Mode::Exec => { let ast = parser::parse_program(source)?; - compile_program(ast, source_path, optimize) + compile_program(ast, source_path.clone(), optimize) } Mode::Eval => { let statement = parser::parse_statement(source)?; - compile_statement_eval(statement, source_path, optimize) + compile_statement_eval(statement, source_path.clone(), optimize) } Mode::Single => { let ast = parser::parse_program(source)?; - compile_program_single(ast, source_path, optimize) + compile_program_single(ast, source_path.clone(), optimize) } } + .map_err(|mut err| { + err.update_source_path(&source_path); + err + }) } /// A helper function for the shared code of the different compile functions @@ -258,6 +262,7 @@ impl Compiler { statement: None, error: CompileErrorType::ExpectExpr, location: statement.location.clone(), + source_path: None, }); } } @@ -537,6 +542,7 @@ impl Compiler { statement: None, error: CompileErrorType::InvalidBreak, location: statement.location.clone(), + source_path: None, }); } self.emit(Instruction::Break); @@ -547,6 +553,7 @@ impl Compiler { statement: None, error: CompileErrorType::InvalidContinue, location: statement.location.clone(), + source_path: None, }); } self.emit(Instruction::Continue); @@ -557,6 +564,7 @@ impl Compiler { statement: None, error: CompileErrorType::InvalidReturn, location: statement.location.clone(), + source_path: None, }); } match value { @@ -635,6 +643,7 @@ impl Compiler { statement: None, error: CompileErrorType::Delete(expression.name()), location: self.current_source_location.clone(), + source_path: None, }); } } @@ -1339,6 +1348,7 @@ impl Compiler { statement: None, error: CompileErrorType::StarArgs, location: self.current_source_location.clone(), + source_path: None, }); } else { seen_star = true; @@ -1369,6 +1379,7 @@ impl Compiler { statement: None, error: CompileErrorType::Assign(target.name()), location: self.current_source_location.clone(), + source_path: None, }); } } @@ -1654,6 +1665,7 @@ impl Compiler { statement: Option::None, error: CompileErrorType::InvalidYield, location: self.current_source_location.clone(), + source_path: Option::None, }); } self.mark_generator(); @@ -1751,6 +1763,7 @@ impl Compiler { "Invalid starred expression", )), location: self.current_source_location.clone(), + source_path: Option::None, }); } IfExpression { test, body, orelse } => { diff --git a/compiler/src/error.rs b/compiler/src/error.rs index f42693760..ae53a0032 100644 --- a/compiler/src/error.rs +++ b/compiler/src/error.rs @@ -10,12 +10,18 @@ pub struct CompileError { pub statement: Option, pub error: CompileErrorType, pub location: Location, + pub source_path: Option, } impl CompileError { pub fn update_statement_info(&mut self, statement: String) { self.statement = Some(statement); } + + pub fn update_source_path(&mut self, source_path: &str) { + debug_assert!(self.source_path.is_none()); + self.source_path = Some(source_path.to_owned()); + } } impl From for CompileError { @@ -24,6 +30,7 @@ impl From for CompileError { statement: None, error: CompileErrorType::Parse(error.error), location: error.location, + source_path: None, } } } diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index 217265b46..281385466 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -145,6 +145,7 @@ impl From for CompileError { statement: None, error: CompileErrorType::SyntaxError(error.error), location: error.location, + source_path: None, } } } diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 264d4ca06..89ad82972 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -565,6 +565,14 @@ pub fn init(ctx: &PyContext) { "__repr__" => ctx.new_rustfunc(exception_repr), }); + extend_class!(ctx, &excs.syntax_error, { + "msg" => ctx.new_property(make_arg_getter(0)), + "filename" => ctx.new_property(make_arg_getter(1)), + "lineno" => ctx.new_property(make_arg_getter(2)), + "offset" => ctx.new_property(make_arg_getter(3)), + "text" => ctx.new_property(make_arg_getter(4)), + }); + extend_class!(ctx, &excs.import_error, { "__init__" => ctx.new_rustfunc(import_error_init) }); diff --git a/vm/src/stdlib/symtable.rs b/vm/src/stdlib/symtable.rs index 59914dda5..51cee7ab2 100644 --- a/vm/src/stdlib/symtable.rs +++ b/vm/src/stdlib/symtable.rs @@ -25,7 +25,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { /// See docs: https://docs.python.org/3/library/symtable.html?highlight=symtable#symtable.symtable fn symtable_symtable( source: PyStringRef, - _filename: PyStringRef, + filename: PyStringRef, mode: PyStringRef, vm: &VirtualMachine, ) -> PyResult { @@ -33,8 +33,10 @@ fn symtable_symtable( .as_str() .parse::() .map_err(|err| vm.new_value_error(err.to_string()))?; - let symtable = - source_to_symtable(source.as_str(), mode).map_err(|err| vm.new_syntax_error(&err))?; + let symtable = source_to_symtable(source.as_str(), mode).map_err(|mut err| { + err.update_source_path(filename.as_str()); + vm.new_syntax_error(&err) + })?; let py_symbol_table = to_py_symbol_table(symtable); Ok(py_symbol_table.into_ref(vm)) diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 42a66dab4..49b1d0bb5 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -409,7 +409,17 @@ impl VirtualMachine { }; let syntax_error = self.new_exception(syntax_error_type, error.to_string()); let lineno = self.new_int(error.location.row()); + let offset = self.new_int(error.location.column()); self.set_attr(&syntax_error, "lineno", lineno).unwrap(); + self.set_attr(&syntax_error, "offset", offset).unwrap(); + if let Some(v) = error.statement.as_ref() { + self.set_attr(&syntax_error, "text", self.new_str(v.to_owned())) + .unwrap(); + } + if let Some(path) = error.source_path.as_ref() { + self.set_attr(&syntax_error, "filename", self.new_str(path.to_owned())) + .unwrap(); + } syntax_error }