]> Repositorios git - scryer-prolog.git/commitdiff
replace pairs of usize with location struct
authorSkgland <[email protected]>
Sat, 24 Jan 2026 00:54:29 +0000 (01:54 +0100)
committerBennet Bleßmann <[email protected]>
Sat, 24 Jan 2026 03:08:40 +0000 (04:08 +0100)
src/machine/machine_errors.rs
src/machine/system_calls.rs
src/parser/ast.rs
src/parser/lexer.rs
src/parser/parser.rs
src/read.rs

index 4ed198934f165f818822d293e773c8a3eb63250a..2dccd1c871ef748cdf1ca6a2ae08dba5f0b177a5 100644 (file)
@@ -20,7 +20,7 @@ pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>;
 #[derive(Debug)]
 pub(crate) struct MachineError {
     stub: MachineStub,
-    location: Option<(usize, usize)>, // line_num, col_num
+    location: Option<Location>,
 }
 
 // from 7.12.2 b) of 13211-1:1995
@@ -753,14 +753,15 @@ impl MachineState {
     }
 
     pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
-        if let Some((line_num, _col_num)) = err.location {
+        if let Some(location) = err.location {
+            let line = location.line();
             functor!(
                 atom!("error"),
                 [
                     functor((err.stub)),
                     functor(
                         (atom!(":")),
-                        [functor(src), number(line_num, (&mut self.arena))]
+                        [functor(src), number(line, (&mut self.arena))]
                     )
                 ]
             )
@@ -853,9 +854,9 @@ impl From<ParserError> for CompilationError {
 }
 
 impl CompilationError {
-    pub(crate) fn line_and_col_num(&self) -> Option<(usize, usize)> {
+    pub(crate) fn line_and_col_num(&self) -> Option<Location> {
         match self {
-            CompilationError::ParserError(err) => err.line_and_col_num(),
+            CompilationError::ParserError(err) => err.location(),
             _ => None,
         }
     }
index edd08cb5d9bc8bbacdeb11e8f1c2366e22ae2737..f676315375d27cf597a2f65be7dc9f6b92588325 100644 (file)
@@ -1016,7 +1016,7 @@ impl MachineState {
                             self.unify_fixnum(n, nx);
                         }
                         _ => {
-                            let err = ParserError::ParseBigInt(0, 0);
+                            let err = ParserError::ParseBigInt(parser.lexer.location.clone());
                             let err = self.syntax_error(err);
 
                             return Err(self.error_form(err, stub_gen()));
@@ -1026,9 +1026,7 @@ impl MachineState {
                     return Ok(());
                 }
                 Ok(c) => {
-                    let (line_num, col_num) = (lexer.line_num, lexer.col_num);
-
-                    let err = ParserError::UnexpectedChar(c, line_num, col_num);
+                    let err = ParserError::UnexpectedChar(c, lexer.location);
                     let err = self.syntax_error(err);
 
                     return Err(self.error_form(err, stub_gen()));
@@ -9196,7 +9194,7 @@ impl Machine {
                 stream.add_lines_read(parser.lines_read());
             }
             Ok(true) => {
-                stream.add_lines_read(parser.lexer.line_num);
+                stream.add_lines_read(parser.lexer.location.line());
                 self.machine_st.fail = true;
             }
             Err(err) => {
index ba18d36ede8d732627ea8ba8476216f5d4824a94..0d789c33dae1b3115bf142c83978ef3afce24983 100644 (file)
@@ -426,34 +426,53 @@ pub enum ArithmeticError {
     UninstantiatedVar,
 }
 
+#[derive(Debug, Clone)]
+pub struct Location {
+    pub(super) line: usize,
+    pub(super) column: usize,
+}
+
+impl Location {
+    // beginning of file
+    pub(crate) const BOF: Self = Self { line: 0, column: 0 };
+
+    pub fn line(&self) -> usize {
+        self.line
+    }
+
+    pub fn column(&self) -> usize {
+        self.column
+    }
+}
+
 #[allow(dead_code)]
 #[derive(Debug)]
 pub enum ParserError {
-    BackQuotedString(usize, usize),
+    BackQuotedString(Location),
     IO(IOError),
-    IncompleteReduction(usize, usize),
-    InfiniteFloat(usize, usize),
+    IncompleteReduction(Location),
+    InfiniteFloat(Location),
     InvalidSingleQuotedCharacter(char),
     LexicalError(lexical::Error),
-    MissingQuote(usize, usize),
-    NonPrologChar(usize, usize),
-    ParseBigInt(usize, usize),
-    UnexpectedChar(char, usize, usize),
+    MissingQuote(Location),
+    NonPrologChar(Location),
+    ParseBigInt(Location),
+    UnexpectedChar(char, Location),
     // UnexpectedEOF,
-    Utf8Error(usize, usize),
+    Utf8Error(Option<Location>),
 }
 
 impl ParserError {
-    pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
+    pub fn location(&self) -> Option<Location> {
         match self {
-            &ParserError::BackQuotedString(line_num, col_num)
-            | &ParserError::IncompleteReduction(line_num, col_num)
-            | &ParserError::InfiniteFloat(line_num, col_num)
-            | &ParserError::MissingQuote(line_num, col_num)
-            | &ParserError::NonPrologChar(line_num, col_num)
-            | &ParserError::ParseBigInt(line_num, col_num)
-            | &ParserError::UnexpectedChar(_, line_num, col_num)
-            | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
+            ParserError::BackQuotedString(location)
+            | ParserError::IncompleteReduction(location)
+            | ParserError::InfiniteFloat(location)
+            | ParserError::MissingQuote(location)
+            | ParserError::NonPrologChar(location)
+            | ParserError::ParseBigInt(location)
+            | ParserError::UnexpectedChar(_, location) => Some(location.clone()),
+            ParserError::Utf8Error(location) => location.as_ref().cloned(),
             _ => None,
         }
     }
@@ -513,8 +532,11 @@ impl From<IOError> for ParserError {
 
 impl From<&IOError> for ParserError {
     fn from(error: &IOError) -> ParserError {
-        if error.get_ref().filter(|e| e.is::<BadUtf8Error>()).is_some() {
-            ParserError::Utf8Error(0, 0)
+        if let Some(_utf8_error) = error
+            .get_ref()
+            .and_then(|e| e.downcast_ref::<BadUtf8Error>())
+        {
+            ParserError::Utf8Error(None)
         } else {
             ParserError::IO(error.kind().into())
         }
index bfc3fb8f71a20c57e1e27e1c935e6bed0c9fc2bf..ed39e210247376958452af653339cec21161d9ec 100644 (file)
@@ -91,16 +91,14 @@ macro_rules! try_nt {
 pub(crate) struct Lexer<'a, R> {
     pub(crate) reader: R,
     pub(crate) machine_st: &'a mut MachineState,
-    pub(crate) line_num: usize,
-    pub(crate) col_num: usize,
+    pub(crate) location: Location,
 }
 
 impl<'a, R: fmt::Debug> fmt::Debug for Lexer<'a, R> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("LexerParser")
             .field("reader", &"&'a mut R") // Hacky solution.
-            .field("line_num", &self.line_num)
-            .field("col_num", &self.col_num)
+            .field("location", &self.location)
             .finish()
     }
 }
@@ -110,8 +108,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         Self {
             reader: src,
             machine_st,
-            line_num: 0,
-            col_num: 0,
+            location: Location::BOF,
         }
     }
 
@@ -138,10 +135,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         self.reader.consume(c.len_utf8());
 
         if new_line_char!(c) {
-            self.line_num += 1;
-            self.col_num = 0;
+            self.location.line += 1;
+            self.location.column = 0;
         } else {
-            self.col_num += 1;
+            self.location.column += 1;
         }
     }
 
@@ -200,10 +197,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             match comment_loop() {
                 Err(e) if e.is_unexpected_eof() => {
-                    return Err(ParserError::IncompleteReduction(
-                        self.line_num,
-                        self.col_num,
-                    ));
+                    return Err(ParserError::IncompleteReduction(self.location.clone()));
                 }
                 Err(e) => {
                     return Err(e);
@@ -215,7 +209,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 self.skip_char(c);
                 Ok(true)
             } else {
-                Err(ParserError::NonPrologChar(self.line_num, self.col_num))
+                Err(ParserError::NonPrologChar(self.location.clone()))
             }
         } else {
             self.return_char('/');
@@ -232,7 +226,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !back_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.location.clone()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -257,7 +251,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 Ok(None)
             } else {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.location.clone()))
             }
         } else {
             self.get_back_quoted_char().map(Some)
@@ -279,10 +273,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 self.skip_char(c);
                 Ok(token)
             } else {
-                Err(ParserError::MissingQuote(self.line_num, self.col_num))
+                Err(ParserError::MissingQuote(self.location.clone()))
             }
         } else {
-            Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+            Err(ParserError::UnexpectedChar(c, self.location.clone()))
         }
     }
 
@@ -313,7 +307,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !single_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.location.clone()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -354,7 +348,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
 
             if !double_quote_char!(c2) {
                 self.return_char(c);
-                Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+                Err(ParserError::UnexpectedChar(c, self.location.clone()))
             } else {
                 self.skip_char(c2);
                 Ok(c2)
@@ -378,7 +372,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             't' => '\t',
             'n' => '\n',
             'r' => '\r',
-            c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)),
+            c => return Err(ParserError::UnexpectedChar(c, self.location.clone())),
         };
 
         self.skip_char(c);
@@ -396,10 +390,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         if hexadecimal_digit_char!(c) {
             self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16)
         } else {
-            Err(ParserError::IncompleteReduction(
-                self.line_num,
-                self.col_num,
-            ))
+            Err(ParserError::IncompleteReduction(self.location.clone()))
         }
     }
 
@@ -425,17 +416,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         if backslash_char!(c) {
             self.skip_char(c);
             u32::from_str_radix(&token, radix).map_or_else(
-                |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
+                |_| Err(ParserError::ParseBigInt(self.location.clone())),
                 |n| {
                     char::try_from(n)
-                        .map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num))
+                        .map_err(|_| ParserError::Utf8Error(Some(self.location.clone())))
                 },
             )
         } else {
-            Err(ParserError::IncompleteReduction(
-                self.line_num,
-                self.col_num,
-            ))
+            Err(ParserError::IncompleteReduction(self.location.clone()))
         }
     }
 
@@ -447,7 +435,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             Ok(c)
         } else {
             if !backslash_char!(c) {
-                return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num));
+                return Err(ParserError::UnexpectedChar(c, self.location.clone()));
             }
 
             self.skip_char(c);
@@ -478,7 +466,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             self.skip_char(c);
             Ok(token)
         } else {
-            Err(ParserError::MissingQuote(self.line_num, self.col_num))
+            Err(ParserError::MissingQuote(self.location.clone()))
         }
     }
 
@@ -509,7 +497,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 .map(NumberToken::Integer)
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.location.clone()))
         }
     }
 
@@ -540,7 +528,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 .map(NumberToken::Integer)
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.location.clone()))
         }
     }
 
@@ -571,7 +559,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
                 .map(NumberToken::Integer)
         } else {
             self.return_char(start);
-            Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+            Err(ParserError::ParseBigInt(self.location.clone()))
         }
     }
 
@@ -648,7 +636,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             }
         } else {
             match self.get_back_quoted_string() {
-                Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
+                Ok(_) => return Err(ParserError::BackQuotedString(self.location.clone())),
                 Err(e) => return Err(e),
             }
         }
@@ -686,7 +674,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             if decimal_digit_char!(c) {
                 Ok(c)
             } else {
-                Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+                Err(ParserError::ParseBigInt(self.location.clone()))
             }
         } else {
             Ok(c)
@@ -708,7 +696,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
             .or_else(|_| {
                 Integer::from_str_radix(token, radix)
                     .map(|n| GInteger::Integer(arena_alloc!(n, &mut self.machine_st.arena)))
-                    .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
+                    .map_err(|_| ParserError::ParseBigInt(self.location.clone()))
             })
     }
 
index 61e85c7ecf64f2fb6367f82dcf6dcc91c1d809bf..eda980c9f5b92619902764dda09687f8069bcbd2 100644 (file)
@@ -254,10 +254,7 @@ pub fn read_tokens<R: CharRead>(lexer: &mut Lexer<'_, R>) -> Result<Vec<Token>,
                 }
             }
             Err(e) if e.is_unexpected_eof() && !tokens.is_empty() => {
-                return Err(ParserError::IncompleteReduction(
-                    lexer.line_num,
-                    lexer.col_num,
-                ));
+                return Err(ParserError::IncompleteReduction(lexer.location.clone()));
             }
             Err(e) => {
                 return Err(e);
@@ -702,8 +699,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 Some(term) => term,
                 _ => {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ))
                 }
             };
@@ -719,8 +715,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         if arity > self.terms.len() {
             return Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.location.clone(),
             ));
         }
 
@@ -791,8 +786,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                             Some(term) => term,
                             _ => {
                                 return Err(ParserError::IncompleteReduction(
-                                    self.lexer.line_num,
-                                    self.lexer.col_num,
+                                    self.lexer.location.clone(),
                                 ))
                             }
                         };
@@ -972,10 +966,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 self.negate_number(n, negate_rat_rc, Literal::Rational)
             }
             Token::Literal(Literal::F64(_offset, n)) if n.is_infinite() => {
-                return Err(ParserError::InfiniteFloat(
-                    self.lexer.line_num,
-                    self.lexer.col_num,
-                ));
+                return Err(ParserError::InfiniteFloat(self.lexer.location.clone()));
             }
             Token::Literal(Literal::F64(offset, n)) => {
                 self.negate_number((offset, n), negate_f64, |(offset, n)| {
@@ -998,8 +989,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::Close => {
                 if !self.reduce_term() && !self.reduce_brackets() {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ));
                 }
             }
@@ -1007,8 +997,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::CloseList => {
                 if !self.reduce_list()? {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ));
                 }
             }
@@ -1016,8 +1005,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             Token::CloseCurly => {
                 if !self.reduce_curly()? {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ));
                 }
             }
@@ -1053,8 +1041,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 | Some(TokenType::HeadTailSeparator)
                 | Some(TokenType::Comma) => {
                     return Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ))
                 }
                 _ => {}
@@ -1066,12 +1053,12 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
     #[inline]
     pub fn add_lines_read(&mut self, lines_read: usize) {
-        self.lexer.line_num += lines_read;
+        self.lexer.location.line += lines_read;
     }
 
     #[inline]
     pub fn lines_read(&self) -> usize {
-        self.lexer.line_num
+        self.lexer.location.line
     }
 
     // on success, returns the parsed term and the number of lines read.
@@ -1093,8 +1080,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         if self.terms.len() > 1 || self.stack.len() > 1 {
             return Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.location.clone(),
             ));
         }
 
@@ -1104,14 +1090,12 @@ impl<'a, R: CharRead> Parser<'a, R> {
                     Ok(term)
                 } else {
                     Err(ParserError::IncompleteReduction(
-                        self.lexer.line_num,
-                        self.lexer.col_num,
+                        self.lexer.location.clone(),
                     ))
                 }
             }
             _ => Err(ParserError::IncompleteReduction(
-                self.lexer.line_num,
-                self.lexer.col_num,
+                self.lexer.location.clone(),
             )),
         }
     }
index fe709c7e617132820139b9bae168f3aa122b55af..9f578bf8b28fb89fc5d22a167b1393f4d20291da 100644 (file)
@@ -48,12 +48,13 @@ pub(crate) fn error_after_read_term<R>(
     parser: &Parser<R>,
 ) -> CompilationError {
     if err.is_unexpected_eof() {
-        let line_num = parser.lexer.line_num;
-        let col_num = parser.lexer.col_num;
+        let location = &parser.lexer.location;
 
         // rough overlap with errors 8.14.1.3 k) & l) of the ISO standard here
-        if !(line_num == prior_num_lines_read && col_num == 0) {
-            return CompilationError::from(ParserError::IncompleteReduction(line_num, col_num));
+        if !(location.line() == prior_num_lines_read && location.column() == 0) {
+            return CompilationError::from(ParserError::IncompleteReduction(
+                parser.lexer.location.clone(),
+            ));
         }
     }