From: Mark Thom Date: Wed, 18 Sep 2019 04:50:32 +0000 (-0600) Subject: print line numbers to trace the location of parsing errors X-Git-Tag: v0.8.110~47 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=40500ca2d6945b015f62e6e1ed0b6f45014d58ad;p=scryer-prolog.git print line numbers to trace the location of parsing errors --- diff --git a/Cargo.toml b/Cargo.toml index 7005232a..e2d7fb5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.89" +version = "0.8.90" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." @@ -15,7 +15,7 @@ dirs = "2.0.2" downcast = "0.10.0" indexmap = "1.0.2" ordered-float = "0.5.0" -prolog_parser = "0.8.27" +prolog_parser = "0.8.28" readline_rs_compat = { version = "0.1.9", optional = true } ref_thread_local = "0.0.0" rug = "1.4.0" diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 0945a9e0..ae2bb38b 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -15,6 +15,7 @@ enum ErrorProvenance { pub(super) struct MachineError { stub: MachineStub, + location: Option<(usize, usize)>, // line_num, col_num from: ErrorProvenance } @@ -26,14 +27,14 @@ impl MachineError { pub(super) fn evaluation_error(eval_error: EvalError) -> Self { let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]); - MachineError { stub, from: ErrorProvenance::Received } + MachineError { stub, location: None, from: ErrorProvenance::Received } } pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self { let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()), HeapCellValue::Addr(culprit)]); - MachineError { stub, from: ErrorProvenance::Received } + MachineError { stub, location: None, from: ErrorProvenance::Received } } pub(super) @@ -49,23 +50,23 @@ impl MachineError { SharedOpDesc::new(400, YFX))); stub.append(&mut functor!(":", 2, [mod_name, name], SharedOpDesc::new(600, XFY))); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location: None, from: ErrorProvenance::Constructed } } pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self - { + { match err { ExistenceError::Procedure(name, arity) => { let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]); stub.append(&mut Self::functor_stub(name, arity)); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location: None, from: ErrorProvenance::Constructed } }, ExistenceError::Module(name) => { let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None))); - let mut stub = functor!("existence_error", 2, [heap_atom!("module"), name]); + let stub = functor!("existence_error", 2, [heap_atom!("module"), name]); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location: None, from: ErrorProvenance::Constructed } } } } @@ -91,7 +92,7 @@ impl MachineError { SessionError::OpIsInfixAndPostFix(op) => Self::permission_error(PermissionError::Create, "operator", - op), + op), _ => unreachable!() } } @@ -106,7 +107,7 @@ impl MachineError { stub.extend(err.into_iter()); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location: None, from: ErrorProvenance::Constructed } } fn arithmetic_error(h: usize, err: ArithmeticError) -> Self { @@ -114,14 +115,14 @@ impl MachineError { ArithmeticError::UninstantiatedVar => Self::instantiation_error(), ArithmeticError::NonEvaluableFunctor(name, arity) => { - let name = HeapCellValue::Addr(Addr::Con(name)); + let name = HeapCellValue::Addr(Addr::Con(name)); let culprit = functor!("/", 2, [name, heap_integer!(Integer::from(arity))], SharedOpDesc::new(400, YFX)); - + let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3+h)).stub; stub.extend(culprit.into_iter()); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location: None, from: ErrorProvenance::Constructed } } } } @@ -130,7 +131,8 @@ impl MachineError { if let ParserError::Arithmetic(err) = err { return Self::arithmetic_error(h, err); } - + + let location = err.line_and_col_num(); let err = vec![heap_atom!(err.as_str())]; let mut stub = if err.len() == 1 { @@ -141,23 +143,23 @@ impl MachineError { stub.extend(err.into_iter()); - MachineError { stub, from: ErrorProvenance::Constructed } + MachineError { stub, location, from: ErrorProvenance::Constructed } } pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self { let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]); - MachineError { stub, from: ErrorProvenance::Received } + MachineError { stub, location: None, from: ErrorProvenance::Received } } pub(super) fn instantiation_error() -> Self { let stub = functor!("instantiation_error"); - MachineError { stub, from: ErrorProvenance::Received } + MachineError { stub, location: None, from: ErrorProvenance::Received } } pub(super) fn representation_error(flag: RepFlag) -> Self { let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]); - MachineError { stub, from: ErrorProvenance::Received } + MachineError { stub, location: None, from: ErrorProvenance::Received } } fn into_iter(self, offset: usize) -> Box> { @@ -382,14 +384,25 @@ impl MachineState { } pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub { + let location = err.location; + let err_len = err.len(); + let h = self.heap.h; let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None), HeapCellValue::Addr(Addr::HeapCell(h + 3)), - HeapCellValue::Addr(Addr::HeapCell(h + 3 + err.len()))]; + HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len))]; stub.extend(err.into_iter(3)); - stub.extend(src.into_iter()); + if let Some((line_num, _)) = location { + let colon_op_desc = Some(SharedOpDesc::new(600, XFY)); + + stub.extend(vec![HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc), + HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)), + heap_integer!(Integer::from(line_num))].into_iter()); + } + + stub.extend(src.into_iter()); stub } @@ -417,7 +430,7 @@ pub enum SessionError { CannotOverwriteBuiltIn(ClauseName), CannotOverwriteImport(ClauseName), InvalidFileName(ClauseName), - ModuleDoesNotContainExport, + ModuleDoesNotContainExport, ModuleNotFound, NamelessEntry, NoModuleDeclaration(ClauseName), diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 06fbffb0..81f63c69 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -339,7 +339,10 @@ impl MachineState { if let Some(c) = string.chars().last() { if layout_char!(c) { - let err = ParserError::UnexpectedChar(c); + let (line_num, col_num) = string.chars().fold((0, 0), |(line_num, col_num), c| + if new_line_char!(c) { (1 + line_num, 0) } else { (line_num, col_num + 1) } + ); + let err = ParserError::UnexpectedChar(c, line_num, col_num); let h = self.heap.h; let err = MachineError::syntax_error(h, err); @@ -370,7 +373,7 @@ impl MachineState { Ok(Term::Constant(_, Constant::CharCode(c))) => self.unify(nx, Addr::Con(Constant::CharCode(c))), _ => { - let err = ParserError::ParseBigInt; + let err = ParserError::ParseBigInt(0, 0); let h = self.heap.h; let err = MachineError::syntax_error(h, err); @@ -873,17 +876,17 @@ impl MachineState { | addr @ Addr::StackCell(..) | addr @ Addr::AttrVar(_) => { let mut iter = indices.code_dir.iter(); - + while let Some(((name, arity), _)) = iter.next() { if is_builtin_predicate(&name) { continue; } - + let spec = get_clause_spec(name.clone(), *arity, composite_op!(&indices.op_dir)); let db_ref = DBRef::NamedPred(name.clone(), *arity, spec); let r = addr.as_var().unwrap(); - + self.bind(r, Addr::DBRef(db_ref)); return return_from_clause!(self.last_call, self); } diff --git a/src/tests.rs b/src/tests.rs index 6bebd3c5..bf103f38 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -2273,10 +2273,6 @@ fn test_queries_on_string_lists() Y = \"defghijkl\".", [["X = [a,b,c,d,e,f,g,h,i,j,k,l]", "Y = [d,e,f,g,h,i,j,k,l]"]]); - assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), - \"defghijkl\" = Y.", - [["X = [a,b,c,d,e,f,g,h,i,j,k,l]", - "Y = [d,e,f,g,h,i,j,k,l]"]]); assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G].", [["X = [a,b,c,d,e,f|_]","Y = [d,e,f|_]","G = _"]]);