From b0bdf50a7811e9095721936363fb265318806f4c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 12 May 2018 18:23:57 -0600 Subject: [PATCH] parse negative numbers properly, handle length errors and failures properly. --- src/prolog/lib/builtins.pl | 36 ++++++++++++++++++++++++++++-- src/prolog/lib/lists.pl | 10 ++++----- src/prolog/machine/system_calls.rs | 4 ++-- src/prolog/parser | 2 +- src/tests.rs | 20 ++++++++--------- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index a8fa00a0..006fed1e 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -3,8 +3,8 @@ :- module(builtins, [(=)/2, (+)/2, (*)/2, (-)/2, (/)/2, (/\)/2, (\/)/2, (is)/2, (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2, (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, - (-)/1, (>=)/2, (=<)/2, (->)/2, (;)/2, (==)/2, arg/3, catch/3, - throw/1, true/0, false/0]). + (-)/1, (>=)/2, (=<)/2, (->)/2, (;)/2, (==)/2, (\==)/2, arg/3, + catch/3, throw/1, true/0, false/0, length/2]). % arithmetic operators. :- op(700, xfx, is). @@ -40,6 +40,7 @@ % term comparison. :- op(700, xfx, ==). +:- op(700, xfx, \==). % unify. X = X. @@ -96,3 +97,34 @@ arg(N, Functor, Arg) :- throw(error(type_error(integer, N), arg/3)). arg_(N, N, N, Functor, Arg) :- !, '$get_arg'(N, Functor, Arg). arg_(N, N, Arity, Functor, Arg) :- '$get_arg'(N, Functor, Arg). arg_(N, N0, Arity, Functor, Arg) :- N0 < Arity, N1 is N0 + 1, arg_(N, N1, Arity, Functor, Arg). + +% length. + +length(Xs, N) :- + var(N), !, + '$skip_max_list'(M, -1, Xs, Xs0), + ( Xs0 == [] -> N = M + ; var(Xs0) -> '$length_addendum'(Xs0, N, M)). + % ; throw(error(type_error(list, Xs), length/2))). +length(Xs, N) :- + integer(N), + N >= 0, !, + '$skip_max_list'(M, N, Xs, Xs0), + ( Xs0 == [] -> N = M + ; var(Xs0) -> R is N-M, '$length_rundown'(Xs0, R)). + % ; throw(error(type_error(list, Xs), length/2))). +length(_, N) :- + integer(N), !, + throw(error(domain_error(not_less_than_zero, N), length/2)). +length(_, N) :- + throw(error(type_error(integer, N), length/2)). + +'$length_addendum'([], N, N). +'$length_addendum'([_|Xs], N, M) :- + M1 is M + 1, + '$length_addendum'(Xs, N, M1). + +'$length_rundown'([], 0) :- !. +'$length_rundown'([_|Xs], N) :- + N1 is N-1, + '$length_rundown'(Xs, N1). diff --git a/src/prolog/lib/lists.pl b/src/prolog/lib/lists.pl index bd3ecd5d..11c0f275 100644 --- a/src/prolog/lib/lists.pl +++ b/src/prolog/lib/lists.pl @@ -1,5 +1,7 @@ -:- module(lists, [member/2, select/3, append/3, is_list/1, memberchk/2, reverse/2, maplist/2, - maplist/3, maplist/4, maplist/5, maplist/6, maplist/7, maplist/8, maplist/9]). +:- module(lists, [member/2, select/3, append/3, memberchk/2, + reverse/2, maplist/2, maplist/3, maplist/4, + maplist/5, maplist/6, maplist/7, maplist/8, + maplist/9]). member(X, [X|_]). member(X, [_|Xs]) :- member(X, Xs). @@ -10,10 +12,6 @@ select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys). append([], R, R). append([X|L], R, [X|S]) :- append(L, R, S). -is_list(X) :- var(X), !, false. -is_list([]). -is_list([_|T]) :- is_list(T). - memberchk(X, Xs) :- member(X, Xs), !. reverse(Xs, Ys) :- reverse(Xs, [], Ys). diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index ada82b66..ca4d2468 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -103,10 +103,10 @@ impl MachineState { } pub(super) fn skip_max_list(&mut self) -> Result<(), MachineError> { - let max_steps = self.arith_eval_by_metacall(temp_v!(2))?; + let max_steps = self.store(self.deref(self[temp_v!(2)].clone())); match max_steps { - Number::Integer(ref max_steps) + Addr::Con(Constant::Number(Number::Integer(ref max_steps))) if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) => { let n = self.store(self.deref(self[temp_v!(1)].clone())); diff --git a/src/prolog/parser b/src/prolog/parser index 51e38dd2..7f9094ea 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 51e38dd24252431432ec7deb5ad80e2fc11a5753 +Subproject commit 7f9094eaedf235ffacb7c49f098593f22957fcfc diff --git a/src/tests.rs b/src/tests.rs index 81a2064f..6a8ae689 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -550,7 +550,7 @@ fn test_queries_on_lists() assert_prolog_failure!(&mut wam, "?- p([Z, W, Y])."); assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["Z = _0", "W = [_0]"]]); assert_prolog_success!(&mut wam, "?- p([Z | [Z]]).", [["Z = _0"]]); - assert_prolog_success!(&mut wam, "?- p([Z | [W]]).", [["Z = _2", "W = _2"]]); + assert_prolog_success!(&mut wam, "?- p([Z | [W]]).", [["Z = _0", "W = _0"]]); assert_prolog_failure!(&mut wam, "?- p([Z | []])."); submit(&mut wam, "p([Z])."); @@ -581,7 +581,7 @@ fn test_queries_on_lists() assert_prolog_success!(&mut wam, "?- member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).", [["X = b", "Y = c", "Z = _14"], ["X = b", "Y = b", "Z = _14"], - ["X = _14", "Y = x", "Z = _14"], + ["X = _2", "Y = x", "Z = _2"], ["X = d", "Y = f", "Z = _14"]]); assert_prolog_failure!(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]])."); assert_prolog_failure!(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]])."); @@ -640,12 +640,12 @@ fn test_queries_on_conjuctive_queries() { submit(&mut wam, "q([f(g(x))], Z). q([f(g(y))], Y). q([f(g(z))], a)."); assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", - [["Z = _10", "X = a", "Y = [f(g(x))]"], - ["Z = _10", "X = a", "Y = [f(g(y))]"], + [["Z = _11", "X = a", "Y = [f(g(x))]"], + ["Z = _11", "X = a", "Y = [f(g(y))]"], ["Z = a", "X = a", "Y = [f(g(z))]"]]); assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).", - [["X = a", "Y = [f(g(x))]", "Z = _10"], - ["X = a", "Y = [f(g(y))]", "Z = _10"], + [["X = a", "Y = [f(g(x))]", "Z = _11"], + ["X = a", "Y = [f(g(y))]", "Z = _11"], ["X = a", "Y = [f(g(z))]", "Z = a"]]); assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, X).", [["X = a", "Y = [f(g(x))]"], @@ -670,12 +670,12 @@ fn test_queries_on_conjuctive_queries() { ["Y = [f(g(z))]", "X = [f(g(x))]"], ["Y = [f(g(z))]", "X = [f(g(y))]"]]); assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, X).", - [["Y = [f(g(x))]", "X = s_0_2"], - ["Y = [f(g(y))]", "X = s_0_2"], + [["Y = [f(g(x))]", "X = _10"], + ["Y = [f(g(y))]", "X = _10"], ["Y = [f(g(z))]", "X = a"]]); assert_prolog_success!(&mut wam, "?- q(X, Y), p(Y, X).", - [["Y = s_0_1", "X = [f(g(x))]"], - ["Y = s_0_1", "X = [f(g(y))]"], + [["Y = _9", "X = [f(g(x))]"], + ["Y = _9", "X = [f(g(y))]"], ["Y = a" , "X = [f(g(z))]"]]); } -- 2.54.0