print line numbers to trace the location of parsing errors
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.89"
|
version = "0.8.90"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
description = "A modern Prolog implementation written mostly in Rust."
|
description = "A modern Prolog implementation written mostly in Rust."
|
||||||
@@ -15,7 +15,7 @@ dirs = "2.0.2"
|
|||||||
downcast = "0.10.0"
|
downcast = "0.10.0"
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = "0.8.27"
|
prolog_parser = "0.8.28"
|
||||||
readline_rs_compat = { version = "0.1.9", optional = true }
|
readline_rs_compat = { version = "0.1.9", optional = true }
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = "1.4.0"
|
rug = "1.4.0"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ enum ErrorProvenance {
|
|||||||
|
|
||||||
pub(super) struct MachineError {
|
pub(super) struct MachineError {
|
||||||
stub: MachineStub,
|
stub: MachineStub,
|
||||||
|
location: Option<(usize, usize)>, // line_num, col_num
|
||||||
from: ErrorProvenance
|
from: ErrorProvenance
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,14 +27,14 @@ impl MachineError {
|
|||||||
|
|
||||||
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
||||||
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
|
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 {
|
pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
|
||||||
let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()),
|
let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()),
|
||||||
HeapCellValue::Addr(culprit)]);
|
HeapCellValue::Addr(culprit)]);
|
||||||
|
|
||||||
MachineError { stub, from: ErrorProvenance::Received }
|
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
@@ -49,23 +50,23 @@ impl MachineError {
|
|||||||
SharedOpDesc::new(400, YFX)));
|
SharedOpDesc::new(400, YFX)));
|
||||||
stub.append(&mut functor!(":", 2, [mod_name, name], SharedOpDesc::new(600, XFY)));
|
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
|
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self
|
||||||
{
|
{
|
||||||
match err {
|
match err {
|
||||||
ExistenceError::Procedure(name, arity) => {
|
ExistenceError::Procedure(name, arity) => {
|
||||||
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
|
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
|
||||||
stub.append(&mut Self::functor_stub(name, arity));
|
stub.append(&mut Self::functor_stub(name, arity));
|
||||||
|
|
||||||
MachineError { stub, from: ErrorProvenance::Constructed }
|
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||||
},
|
},
|
||||||
ExistenceError::Module(name) => {
|
ExistenceError::Module(name) => {
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
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) =>
|
SessionError::OpIsInfixAndPostFix(op) =>
|
||||||
Self::permission_error(PermissionError::Create,
|
Self::permission_error(PermissionError::Create,
|
||||||
"operator",
|
"operator",
|
||||||
op),
|
op),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ impl MachineError {
|
|||||||
|
|
||||||
stub.extend(err.into_iter());
|
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 {
|
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||||
@@ -114,14 +115,14 @@ impl MachineError {
|
|||||||
ArithmeticError::UninstantiatedVar =>
|
ArithmeticError::UninstantiatedVar =>
|
||||||
Self::instantiation_error(),
|
Self::instantiation_error(),
|
||||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
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))],
|
let culprit = functor!("/", 2, [name, heap_integer!(Integer::from(arity))],
|
||||||
SharedOpDesc::new(400, YFX));
|
SharedOpDesc::new(400, YFX));
|
||||||
|
|
||||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3+h)).stub;
|
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3+h)).stub;
|
||||||
stub.extend(culprit.into_iter());
|
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 {
|
if let ParserError::Arithmetic(err) = err {
|
||||||
return Self::arithmetic_error(h, err);
|
return Self::arithmetic_error(h, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let location = err.line_and_col_num();
|
||||||
let err = vec![heap_atom!(err.as_str())];
|
let err = vec![heap_atom!(err.as_str())];
|
||||||
|
|
||||||
let mut stub = if err.len() == 1 {
|
let mut stub = if err.len() == 1 {
|
||||||
@@ -141,23 +143,23 @@ impl MachineError {
|
|||||||
|
|
||||||
stub.extend(err.into_iter());
|
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 {
|
pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self {
|
||||||
let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()),
|
let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()),
|
||||||
HeapCellValue::Addr(culprit)]);
|
HeapCellValue::Addr(culprit)]);
|
||||||
MachineError { stub, from: ErrorProvenance::Received }
|
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn instantiation_error() -> Self {
|
pub(super) fn instantiation_error() -> Self {
|
||||||
let stub = functor!("instantiation_error");
|
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 {
|
pub(super) fn representation_error(flag: RepFlag) -> Self {
|
||||||
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
|
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>> {
|
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 {
|
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 h = self.heap.h;
|
||||||
let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None),
|
let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None),
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
|
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(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
|
stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +430,7 @@ pub enum SessionError {
|
|||||||
CannotOverwriteBuiltIn(ClauseName),
|
CannotOverwriteBuiltIn(ClauseName),
|
||||||
CannotOverwriteImport(ClauseName),
|
CannotOverwriteImport(ClauseName),
|
||||||
InvalidFileName(ClauseName),
|
InvalidFileName(ClauseName),
|
||||||
ModuleDoesNotContainExport,
|
ModuleDoesNotContainExport,
|
||||||
ModuleNotFound,
|
ModuleNotFound,
|
||||||
NamelessEntry,
|
NamelessEntry,
|
||||||
NoModuleDeclaration(ClauseName),
|
NoModuleDeclaration(ClauseName),
|
||||||
|
|||||||
@@ -339,7 +339,10 @@ impl MachineState {
|
|||||||
|
|
||||||
if let Some(c) = string.chars().last() {
|
if let Some(c) = string.chars().last() {
|
||||||
if layout_char!(c) {
|
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 h = self.heap.h;
|
||||||
let err = MachineError::syntax_error(h, err);
|
let err = MachineError::syntax_error(h, err);
|
||||||
@@ -370,7 +373,7 @@ impl MachineState {
|
|||||||
Ok(Term::Constant(_, Constant::CharCode(c))) =>
|
Ok(Term::Constant(_, Constant::CharCode(c))) =>
|
||||||
self.unify(nx, Addr::Con(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 h = self.heap.h;
|
||||||
let err = MachineError::syntax_error(h, err);
|
let err = MachineError::syntax_error(h, err);
|
||||||
@@ -873,17 +876,17 @@ impl MachineState {
|
|||||||
| addr @ Addr::StackCell(..)
|
| addr @ Addr::StackCell(..)
|
||||||
| addr @ Addr::AttrVar(_) => {
|
| addr @ Addr::AttrVar(_) => {
|
||||||
let mut iter = indices.code_dir.iter();
|
let mut iter = indices.code_dir.iter();
|
||||||
|
|
||||||
while let Some(((name, arity), _)) = iter.next() {
|
while let Some(((name, arity), _)) = iter.next() {
|
||||||
if is_builtin_predicate(&name) {
|
if is_builtin_predicate(&name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let spec = get_clause_spec(name.clone(), *arity,
|
let spec = get_clause_spec(name.clone(), *arity,
|
||||||
composite_op!(&indices.op_dir));
|
composite_op!(&indices.op_dir));
|
||||||
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
|
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
|
||||||
let r = addr.as_var().unwrap();
|
let r = addr.as_var().unwrap();
|
||||||
|
|
||||||
self.bind(r, Addr::DBRef(db_ref));
|
self.bind(r, Addr::DBRef(db_ref));
|
||||||
return return_from_clause!(self.last_call, self);
|
return return_from_clause!(self.last_call, self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2273,10 +2273,6 @@ fn test_queries_on_string_lists()
|
|||||||
Y = \"defghijkl\".",
|
Y = \"defghijkl\".",
|
||||||
[["X = [a,b,c,d,e,f,g,h,i,j,k,l]",
|
[["X = [a,b,c,d,e,f,g,h,i,j,k,l]",
|
||||||
"Y = [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].",
|
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 = _"]]);
|
[["X = [a,b,c,d,e,f|_]","Y = [d,e,f|_]","G = _"]]);
|
||||||
|
|||||||
Reference in New Issue
Block a user