:- 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).
% term comparison.
:- op(700, xfx, ==).
+:- op(700, xfx, \==).
% unify.
X = X.
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).
-:- 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).
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).
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]).");
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]]).");
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))]"],
["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))]"]]);
}