]> Repositorios git - scryer-prolog.git/commitdiff
print line numbers to trace the location of parsing errors
authorMark Thom <[email protected]>
Wed, 18 Sep 2019 04:50:32 +0000 (22:50 -0600)
committerMark Thom <[email protected]>
Wed, 18 Sep 2019 04:50:32 +0000 (22:50 -0600)
Cargo.toml
src/prolog/machine/machine_errors.rs
src/prolog/machine/system_calls.rs
src/tests.rs

index 7005232aaf72f42134223d8d7205fbd5fb6cf337..e2d7fb5bbcb55aca484cdc651aa629e0a5561265 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.89"
+version = "0.8.90"
 authors = ["Mark Thom <[email protected]>"]
 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"
index 0945a9e0fa92ec237167d145cac0be200fdd44ae..ae2bb38b94df41a0c7935f2decafd42ef1865bd7 100644 (file)
@@ -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<Iterator<Item=HeapCellValue>> {
@@ -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),
index 06fbffb00adc59b45606a89122e00dd19786e747..81f63c69f2b3048b74859f194ceb1c7bbefd7218 100644 (file)
@@ -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);
                       }
index 6bebd3c5922bc948498647609a0d27e569d73487..bf103f388965ae75eee2276b871ad6662da30a50 100644 (file)
@@ -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 = _"]]);