Merge branch 'mthom:master' into patch-5

This commit is contained in:
Dan Rose
2025-07-08 18:03:16 -05:00
committed by GitHub
10 changed files with 204 additions and 255 deletions

View File

@@ -24,7 +24,6 @@ hostname = ["dep:hostname"]
tls = ["dep:native-tls"] tls = ["dep:native-tls"]
http = ["dep:warp", "dep:reqwest"] http = ["dep:warp", "dep:reqwest"]
crypto-full = [] crypto-full = []
"rust-version-1.80" = []
[build-dependencies] [build-dependencies]
indexmap = "2.3.0" indexmap = "2.3.0"

View File

@@ -5088,11 +5088,21 @@ run_propagator(pmod(X,Y,Z), MState) -->
; nonvar(Z), nonvar(X) -> ; nonvar(Z), nonvar(X) ->
( Z > 0 -> ( Z > 0 ->
( X < 0 -> true ( X < 0 -> true
; X >= Z ; X >= Z,
% due to X = Z+Y*_ and Y > Z
( X-Z > 0 ->
X-Z > Z
; true
)
) )
; Z < 0 -> ; Z < 0 ->
( X > 0 -> true ( X > 0 -> true
; X =< Z ; X =< Z,
% due to X = Z+Y*_ and Y < Z
( X-Z < 0 ->
X-Z < Z
; true
)
) )
; Z =:= 0 % Multiple solutions so do nothing special. ; Z =:= 0 % Multiple solutions so do nothing special.
), ),
@@ -5100,7 +5110,23 @@ run_propagator(pmod(X,Y,Z), MState) -->
YU < X, X =< 0 } -> kill(MState), Z =:= X YU < X, X =< 0 } -> kill(MState), Z =:= X
; { fd_get(Y, _, n(YL), _, _), ; { fd_get(Y, _, n(YL), _, _),
YL > X, X >= 0 } -> kill(MState), Z =:= X YL > X, X >= 0 } -> kill(MState), Z =:= X
; ( Z > 0 -> ; ( Z > 0, X < 0 ->
{ fd_get(Y, YD, YPs),
YMin is Z+1,
YMax is Z-X,
domain_remove_smaller_than(YD, YMin, YD1),
domain_remove_greater_than(YD1, YMax, YD2) },
fd_put(Y, YD2, YPs)
% queue_goal((Y #> Z, Y #=< Z-X))
; Z < 0, X > 0 ->
{ fd_get(Y, YD, YPs),
YMax is Z-1,
YMin is Z-X,
domain_remove_greater_than(YD, YMax, YD1),
domain_remove_smaller_than(YD1, YMin, YD2) },
fd_put(Y, YD2, YPs)
% queue_goal((Y #< Z, Y #>= Z-X))
; Z > 0 ->
{ fd_get(Y, YD, YPs), { fd_get(Y, YD, YPs),
YMin is Z + 1, YMin is Z + 1,
domain_remove_smaller_than(YD, YMin, YD1) }, domain_remove_smaller_than(YD, YMin, YD1) },
@@ -5112,7 +5138,16 @@ run_propagator(pmod(X,Y,Z), MState) -->
domain_remove_greater_than(YD, YMax, YD1) }, domain_remove_greater_than(YD, YMax, YD1) },
fd_put(Y, YD1, YPs) fd_put(Y, YD1, YPs)
% queue_goal(Y #< Z) % queue_goal(Y #< Z)
; true ; Z =:= 0,
( X =:= 0 ->
kill(MState) % trivial
; % only 4 solutions {-abs(X),-1,1,abs(X)}
{ YL is -abs(X), YU is abs(X),
fd_get(Y, YD0, YPs),
domain_remove_smaller_than(YD0, YL, YD1),
domain_remove_greater_than(YD1, YU, YD) },
fd_put(Y, YD, YPs)
)
) )
) )
; run_propagator(pmodz(X,Y,Z), MState), ; run_propagator(pmodz(X,Y,Z), MState),

View File

@@ -12,8 +12,8 @@ to learn more about them.
[op(1105, xfy, '|'), [op(1105, xfy, '|'),
phrase/2, phrase/2,
phrase/3, phrase/3,
phrase/4, phrase//2,
phrase/5, phrase//3,
seq//1, seq//1,
seqq//1, seqq//1,
... //0, ... //0,
@@ -29,9 +29,9 @@ to learn more about them.
:- meta_predicate phrase(2, ?, ?). :- meta_predicate phrase(2, ?, ?).
:- meta_predicate phrase(2, ?, ?, ?). :- meta_predicate(phrase(3, ?, ?, ?)).
:- meta_predicate phrase(2, ?, ?, ?, ?). :- meta_predicate(phrase(4, ?, ?, ?, ?)).
:- meta_predicate(','(2, 2, ?, ?)). :- meta_predicate(','(2, 2, ?, ?)).

View File

@@ -26,7 +26,6 @@
:- op(200, xfy, ^). :- op(200, xfy, ^).
:- op(500, yfx, /\). :- op(500, yfx, /\).
:- op(500, yfx, \/). :- op(500, yfx, \/).
:- op(500, yfx, xor).
:- op(400, yfx, div). :- op(400, yfx, div).
:- op(400, yfx, //). :- op(400, yfx, //).
:- op(400, yfx, rdiv). :- op(400, yfx, rdiv).

View File

@@ -118,32 +118,6 @@ fn current_dir() -> PathBuf {
} }
} }
#[cfg(not(feature = "rust-version-1.80"))]
mod libraries {
use indexmap::IndexMap;
use std::sync::OnceLock;
fn libraries() -> &'static IndexMap<&'static str, &'static str> {
static LIBRARIES: OnceLock<IndexMap<&'static str, &'static str>> = OnceLock::new();
LIBRARIES.get_or_init(|| {
let mut m = IndexMap::new();
include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
m
})
}
pub(crate) fn contains(name: &str) -> bool {
libraries().contains_key(name)
}
pub(crate) fn get(name: &str) -> Option<&'static str> {
libraries().get(name).copied()
}
}
#[cfg(feature = "rust-version-1.80")]
mod libraries { mod libraries {
use indexmap::IndexMap; use indexmap::IndexMap;
use std::sync::LazyLock; use std::sync::LazyLock;

View File

@@ -911,27 +911,16 @@ impl MachineState {
use crate::parser::lexer::*; use crate::parser::lexer::*;
let nx = self.store(self.deref(self.registers[2])); let nx = self.store(self.deref(self.registers[2]));
let add_dot = !string.ends_with('.'); let iter = std::io::Cursor::new(string);
let cursor = std::io::Cursor::new(string);
let iter = std::io::Read::chain(cursor, {
let mut dot_buf: [u8; '.'.len_utf8()] = [0u8];
if add_dot {
'.'.encode_utf8(&mut dot_buf);
}
std::io::Cursor::new(dot_buf)
});
let mut lexer = Lexer::new(CharReader::new(iter), self); let mut lexer = Lexer::new(CharReader::new(iter), self);
let mut tokens = vec![]; let mut tokens = vec![];
match lexer.next_token() { match lexer.next_number_token() {
Ok(token @ Token::Literal(Literal::Atom(atom!("-")) | Literal::Char('-'))) => { Ok(token @ Token::Literal(Literal::Atom(atom!("-")) | Literal::Char('-'))) => {
tokens.push(token); tokens.push(token);
if let Ok(token) = lexer.next_token() { if let Ok(token) = lexer.next_number_token() {
tokens.push(token); tokens.push(token);
} }
} }
@@ -979,9 +968,6 @@ impl MachineState {
break; break;
} }
Ok('.') => {
lexer.skip_char('.');
}
Ok(c) => { Ok(c) => {
let (line_num, col_num) = (lexer.line_num, lexer.col_num); let (line_num, col_num) = (lexer.line_num, lexer.col_num);

View File

@@ -432,6 +432,7 @@ pub enum ParserError {
BackQuotedString(usize, usize), BackQuotedString(usize, usize),
IO(IOError), IO(IOError),
IncompleteReduction(usize, usize), IncompleteReduction(usize, usize),
InfiniteFloat(usize, usize),
InvalidSingleQuotedCharacter(char), InvalidSingleQuotedCharacter(char),
LexicalError(lexical::Error), LexicalError(lexical::Error),
MissingQuote(usize, usize), MissingQuote(usize, usize),
@@ -447,6 +448,7 @@ impl ParserError {
match self { match self {
&ParserError::BackQuotedString(line_num, col_num) &ParserError::BackQuotedString(line_num, col_num)
| &ParserError::IncompleteReduction(line_num, col_num) | &ParserError::IncompleteReduction(line_num, col_num)
| &ParserError::InfiniteFloat(line_num, col_num)
| &ParserError::MissingQuote(line_num, col_num) | &ParserError::MissingQuote(line_num, col_num)
| &ParserError::NonPrologChar(line_num, col_num) | &ParserError::NonPrologChar(line_num, col_num)
| &ParserError::ParseBigInt(line_num, col_num) | &ParserError::ParseBigInt(line_num, col_num)
@@ -463,6 +465,9 @@ impl ParserError {
ParserError::InvalidSingleQuotedCharacter(..) => { ParserError::InvalidSingleQuotedCharacter(..) => {
atom!("invalid_single_quoted_character") atom!("invalid_single_quoted_character")
} }
ParserError::InfiniteFloat(..) => {
atom!("infinite_float")
}
ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => { ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => {
atom!("unexpected_end_of_file") atom!("unexpected_end_of_file")
} }

View File

@@ -1,3 +1,5 @@
use crate::arena::F64Ptr;
use crate::arena::TypedArenaPtr;
use crate::atom_table::*; use crate::atom_table::*;
pub use crate::machine::machine_state::*; pub use crate::machine::machine_state::*;
use crate::parser::ast::*; use crate::parser::ast::*;
@@ -49,6 +51,55 @@ impl Token {
} }
} }
#[derive(Debug)]
enum Number {
BigInt(TypedArenaPtr<Integer>),
Fixnum(Fixnum),
Float(F64Ptr),
}
impl Number {
#[inline]
fn to_literal(self) -> Literal {
match self {
Number::BigInt(ibig) => Literal::Integer(ibig),
Number::Fixnum(fixnum) => Literal::Fixnum(fixnum),
Number::Float(f) => Literal::Float(f.as_offset()),
}
}
}
#[derive(Debug)]
enum NumberToken {
Number(Number),
Partial(String),
}
impl NumberToken {
#[inline]
fn to_token(self) -> Option<Token> {
match self {
NumberToken::Number(number) => Some(Token::Literal(number.to_literal())),
NumberToken::Partial(_) => None,
}
}
}
macro_rules! try_nt {
($token:expr, $e: expr) => {{
match $e {
Ok(c) => c,
Err(e) => {
return if e.is_unexpected_eof() {
Ok(NumberToken::Partial($token))
} else {
Err(e)
}
}
}
}};
}
pub struct Lexer<'a, R> { pub struct Lexer<'a, R> {
pub(crate) reader: R, pub(crate) reader: R,
pub(crate) machine_st: &'a mut MachineState, pub(crate) machine_st: &'a mut MachineState,
@@ -443,7 +494,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
fn hexadecimal_constant(&mut self, start: char) -> Result<Token, ParserError> { fn hexadecimal_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -454,31 +505,21 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if hexadecimal_digit_char!(c) { if hexadecimal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 16) self.parse_integer_by_radix(&token, 16)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 16)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
} }
} }
fn octal_constant(&mut self, start: char) -> Result<Token, ParserError> { fn octal_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -489,31 +530,21 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if octal_digit_char!(c) { if octal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 8) self.parse_integer_by_radix(&token, 8)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 8)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
} }
} }
fn binary_constant(&mut self, start: char) -> Result<Token, ParserError> { fn binary_constant(&mut self, start: char) -> Result<NumberToken, ParserError> {
self.skip_char(start); self.skip_char(start);
let mut c = self.lookahead_char()?; let mut c = self.lookahead_char()?;
@@ -524,24 +555,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if binary_digit_char!(c) { if binary_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
token.push(c); token.push(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} else { } else {
break; break;
} }
} }
i64::from_str_radix(&token, 2) self.parse_integer_by_radix(&token, 2)
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))) .map(NumberToken::Number)
.or_else(|_| {
Integer::from_str_radix(&token, 2)
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else { } else {
self.return_char(start); self.return_char(start);
Err(ParserError::ParseBigInt(self.line_num, self.col_num)) Err(ParserError::ParseBigInt(self.line_num, self.col_num))
@@ -634,15 +655,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> { fn vacate_with_float(&mut self, mut token: String) -> Result<Number, ParserError> {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Number::Float(float_alloc!(n, self.machine_st.arena)))
Ok(Token::Literal(Literal::from(float_alloc!(
n,
self.machine_st.arena
))))
} }
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> { fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -663,17 +679,43 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
pub fn number_token(&mut self, leading_c: char) -> Result<Token, ParserError> { fn parse_integer_by_radix(
&mut self,
token: &String,
radix: u32,
) -> Result<Number, ParserError> {
i64::from_str_radix(&token, radix)
.map(|n| {
Fixnum::build_with_checked(n)
.map(Number::Fixnum)
.unwrap_or_else(|_| {
Number::BigInt(arena_alloc!(Integer::from(n), &mut self.machine_st.arena))
})
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| Number::BigInt(arena_alloc!(n, &mut self.machine_st.arena)))
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
}
#[inline]
fn parse_integer(&mut self, token: &String) -> Result<Number, ParserError> {
self.parse_integer_by_radix(token, 10)
}
fn number_token(&mut self, leading_c: char) -> Result<NumberToken, ParserError> {
let mut token = String::with_capacity(16); let mut token = String::with_capacity(16);
self.skip_char(leading_c); self.skip_char(leading_c);
token.push(leading_c); token.push(leading_c);
let mut c = self.skip_underscore_in_number()?; let mut c = try_nt!(token, self.skip_underscore_in_number());
while decimal_digit_char!(c) { while decimal_digit_char!(c) {
token.push(c); token.push(c);
self.skip_char(c); self.skip_char(c);
c = self.skip_underscore_in_number()?; c = try_nt!(token, self.skip_underscore_in_number());
} }
if decimal_point_char!(c) { if decimal_point_char!(c) {
@@ -681,31 +723,17 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if self.reader.peek_char().is_none() { if self.reader.peek_char().is_none() {
self.return_char('.'); self.return_char('.');
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else if decimal_digit_char!(self.lookahead_char()?) { } else if decimal_digit_char!(self.lookahead_char()?) {
token.push('.'); token.push('.');
token.push(self.read_char()?); token.push(self.read_char()?);
let mut c = self.lookahead_char()?; let mut c = try_nt!(token, self.lookahead_char());
while decimal_digit_char!(c) { while decimal_digit_char!(c) {
token.push(c); token.push(c);
self.skip_char(c); self.skip_char(c);
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
} }
if exponent_char!(c) { if exponent_char!(c) {
@@ -713,12 +741,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token.push(c); token.push(c);
let c = match self.lookahead_char() { let c = match self.lookahead_char() {
Err(_) => return self.vacate_with_float(token), Err(_) => return self.vacate_with_float(token).map(NumberToken::Number),
Ok(c) => c, Ok(c) => c,
}; };
if !sign_char!(c) && !decimal_digit_char!(c) { if !sign_char!(c) && !decimal_digit_char!(c) {
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
if sign_char!(c) { if sign_char!(c) {
@@ -728,14 +756,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
let c = match self.lookahead_char() { let c = match self.lookahead_char() {
Err(_) => { Err(_) => {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
Ok(c) => c, Ok(c) => c,
}; };
if !decimal_digit_char!(c) { if !decimal_digit_char!(c) {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
} }
@@ -746,7 +774,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
token.push(c); token.push(c);
loop { loop {
c = self.lookahead_char()?; c = try_nt!(token, self.lookahead_char());
if decimal_digit_char!(c) { if decimal_digit_char!(c) {
self.skip_char(c); self.skip_char(c);
@@ -757,60 +785,29 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Token::Literal(Literal::from(float_alloc!( Ok(NumberToken::Number(Number::Float(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
} else { } else {
return self.vacate_with_float(token); return self.vacate_with_float(token).map(NumberToken::Number);
} }
} else { } else {
let n = parse_float_lossy(&token)?; let n = parse_float_lossy(&token)?;
Ok(Token::Literal(Literal::from(float_alloc!( Ok(NumberToken::Number(Number::Float(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
} }
} else { } else {
self.return_char('.'); self.return_char('.');
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} else if token.starts_with('0') && token.len() == 1 { } else if token.starts_with('0') && token.len() == 1 {
if c == 'x' { if c == 'x' {
self.hexadecimal_constant(c).or_else(|e| { self.hexadecimal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -818,24 +815,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} else if c == 'o' { } else if c == 'o' {
self.octal_constant(c).or_else(|e| { self.octal_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -843,24 +823,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} else if c == 'b' { } else if c == 'b' {
self.binary_constant(c).or_else(|e| { self.binary_constant(c).or_else(|e| {
if let ParserError::ParseBigInt(..) = e { if let ParserError::ParseBigInt(..) = e {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
} else { } else {
Err(e) Err(e)
} }
@@ -877,14 +840,14 @@ impl<'a, R: CharRead> Lexer<'a, R> {
self.skip_char(c); self.skip_char(c);
self.return_char('\''); self.return_char('\'');
return Ok(Token::Literal(Literal::Fixnum(Fixnum::build_with(0)))); return Ok(NumberToken::Number(Number::Fixnum(Fixnum::build_with(0))));
} else { } else {
self.return_char('\\'); self.return_char('\\');
} }
} }
self.get_single_quoted_char() self.get_single_quoted_char()
.map(|c| Token::Literal(Literal::Fixnum(Fixnum::build_with(c as i64)))) .map(|c| NumberToken::Number(Number::Fixnum(Fixnum::build_with(c as i64))))
.or_else(|err| { .or_else(|err| {
match err { match err {
ParserError::UnexpectedChar('\'', ..) => {} ParserError::UnexpectedChar('\'', ..) => {}
@@ -892,57 +855,13 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
self.return_char(c); self.return_char(c);
self.parse_integer(&token).map(NumberToken::Number)
token
.parse::<i64>()
.map(|n| {
Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena))
})
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| {
ParserError::ParseBigInt(self.line_num, self.col_num)
})
})
}) })
} else { } else {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} else { } else {
token self.parse_integer(&token).map(NumberToken::Number)
.parse::<i64>()
.map(|n| Token::Literal(fixnum!(Literal, n, &mut self.machine_st.arena)))
.or_else(|_| {
token
.parse::<Integer>()
.map(|n| {
Token::Literal(Literal::Integer(arena_alloc!(
n,
&mut self.machine_st.arena
)))
})
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} }
} }
@@ -1001,6 +920,29 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
pub fn next_number_token(&mut self) -> Result<Token, ParserError> {
self.scan_for_layout()?;
let c = self.lookahead_char()?;
if !decimal_digit_char!(c) {
return self.name_token(c);
}
match self.number_token(c) {
Ok(NumberToken::Partial(token_string)) => match self.parse_integer(&token_string) {
Ok(n) => Ok(Token::Literal(n.to_literal())),
Err(_) => {
let n = parse_float_lossy(&token_string)?;
Ok(Token::Literal(Literal::Float(
float_alloc!(n, self.machine_st.arena).as_offset(),
)))
}
},
Ok(NumberToken::Number(n)) => return Ok(Token::Literal(n.to_literal())),
Err(e) => return Err(e),
}
}
pub fn next_token(&mut self) -> Result<Token, ParserError> { pub fn next_token(&mut self) -> Result<Token, ParserError> {
let layout_inserted = self.scan_for_layout()?; let layout_inserted = self.scan_for_layout()?;
let cr = self.lookahead_char(); let cr = self.lookahead_char();
@@ -1053,7 +995,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
if decimal_digit_char!(c) { if decimal_digit_char!(c) {
return self.number_token(c); return self.number_token(c).and_then(|nt| match nt.to_token() {
Some(token) => Ok(token),
None => Err(ParserError::unexpected_eof()),
});
} }
if c == ']' { if c == ']' {

View File

@@ -976,11 +976,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
Token::Literal(Literal::Rational(n)) => { Token::Literal(Literal::Rational(n)) => {
self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r)) self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r))
} }
Token::Literal(Literal::Float(n)) => self.negate_number( Token::Literal(Literal::Float(n)) if F64Ptr::from_offset(n).is_infinite() => {
return Err(ParserError::InfiniteFloat(
self.lexer.line_num,
self.lexer.col_num,
));
}
Token::Literal(Literal::Float(n)) => self.negate_number(
**n.as_ptr(), **n.as_ptr(),
|n, _| -n, |n, _| -n,
|n, arena| Literal::from(float_alloc!(n, arena)), |n, arena| Literal::from(float_alloc!(n, arena)),
), ),
Token::Literal(c) => { Token::Literal(c) => {
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c); let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);

View File

@@ -258,14 +258,14 @@ test_and_or_xor(X, Y, AndExpected, OrExpected, XorExpected) :-
Or2 is Y \/ X, Or2 is Y \/ X,
Or == OrExpected, Or == OrExpected,
Or == Or2, Or == Or2,
Xor is X xor Y, Xor is xor(X, Y),
Xor2 is Y xor X, Xor2 is xor(Y, X),
Xor == XorExpected, Xor == XorExpected,
Xor2 == Xor, Xor2 == Xor,
call(is, And3, X /\ Y), call(is, And3, X /\ Y),
call(is, Or3, X \/ Y), call(is, Or3, X \/ Y),
call(is, Xor3, X xor Y), call(is, Xor3, xor(X, Y)),
And3 == And, And3 == And,
Or3 == Or, Or3 == Or,
Xor3 == Xor. Xor3 == Xor.
@@ -613,7 +613,7 @@ test("and_or_xor", (
]), arithmetic_tests:test_and_or_xor(X, Y, AndExpected, OrExpected, XorExpected)), ]), arithmetic_tests:test_and_or_xor(X, Y, AndExpected, OrExpected, XorExpected)),
\+ catch(_ is 1 /\ 2.0, _, false), \+ catch(_ is 1 /\ 2.0, _, false),
\+ catch(_ is 1 \/ 2.0, _, false), \+ catch(_ is 1 \/ 2.0, _, false),
\+ catch(_ is 1 xor 2.0, _, false) \+ catch(_ is xor(1, 2.0), _, false)
)). )).
test("mod_rem", ( test("mod_rem", (