ref: 9d5c9d3fe5d8951fac0902abf125c68a6e720e52
dir: /stdlib.pl/
:- module(system, []).
% Logic and control predicates
\+ Goal :- call(Goal), !, fail.
\+ Goal.
once(Goal) :-
call(Goal),
!.
repeat :- true ; repeat.
% Control structures.
If -> Then :-
If, !, Then.
If -> Then ; _ :-
If, !, Then.
_ -> _ ; Else :-
!, Else.
If ; _ :-
If.
_ ; Else :-
Else.
A , B :- A , B.
% Term unification
A = A.
A \= B :-
\+ A = B.
% Comparison of terms using the standard order
A == B :-
compare(=, A, B).
A \== B :-
\+ A == B.
A @< B :-
compare(<, A, B).
A @=< B :-
A == B.
A @=< B :-
A @< B.
A @> B :-
compare(>, A, B).
A @>= B :-
A == B.
A @>= B :-
A @> B.
% Input output
open(SourceSink, Mode, Stream) :-
open(SourceSink, Mode, Stream, []).
close(StreamOrAlias) :-
close(StreamOrAlias, []).
% Standard exceptions
instantiation_error :-
throw(error(instantiation_error, _)).
type_error(ValidType, Culprit) :-
throw(error(type_error(ValidType, Culprit), _)).
domain_error(ValidDomain, Culprit) :-
throw(error(domain_error(ValidDomain, Culprit), _)).
existence_error(ObjectType, Culprit) :-
throw(error(existence_error(ObjectType, Culprit), _)).
permission_error(Operation, PermissionType, Culprit) :-
throw(error(permission_error(Operation, PermissionType, Culprit), _)).
representation_error(Flag) :-
throw(error(representation_error(Flag), _)).
evaluation_error(Error) :-
throw(error(evaluation_error(Error), _)).
resource_error(Resource) :-
throw(error(resource_error(Resource), _)).
syntax_error(Error) :-
throw(error(syntax_error(Error), _)).
% Input and output
read_term(Term, Options) :-
current_input(S),
read_term(S, Term, Options).
read(Term) :-
current_input(S),
read_term(S, Term, []).
write_term(Term, Options) :-
current_output(S),
write_term(S, Term, Options).
write(Term) :-
current_output(S),
write_term(S, Term, [numbervars(true)]).
writeq(Term) :-
current_output(S),
write_term(S, Term, [quoted(true), numbervars(true)]).
writeq(S, Term) :-
write_term(S, Term, [quoted(true), numbervars(true)]).
write_canonical(Term) :-
current_output(S),
write_term(S, Term, [quoted(true), ignore_ops(true)]).
write_canonical(S, Term) :-
write_term(S, Term, [quoted(true), ignore_ops(true)]).
% Arithmetic comparisons defined in terms of >=. This is not the most effective way,
% but it is fine for now.
E1 =:= E2 :-
E1 >= E2,
E2 >= E1.
E1 =\= E2 :-
\+ E1 =:= E2.
E1 < E2 :-
E2 >= E1,
E1 =\= E2.
E1 =< E2 :-
E2 >= E1.
E1 > E2 :-
E2 < E1.
% Clause retrieval and information and removal
clause(Head, Body) :-
clause(Head, Body, Clauses),
member(clause(Head, Body), Clauses).
current_predicate(PI) :-
current_predicate(PI, Predicates),
member(PI, Predicates).
retract(Clause) :-
copy_term(Clause, ClauseCopy),
retract_one(ClauseCopy),
( Clause = ClauseCopy
; retract(Clause)
).
% Basic list predicates
member(X, [X|_]).
member(X, [_|Tail]) :-
member(X, Tail).
append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :-
append(Xs, Ys, Zs).
length([], 0).
length([_|T], Len) :-
length(T, Len0),
Len is Len0 + 1.
unique([], []).
unique([H|T], [H|Rest]) :-
findall(_, (member(X, T), X == H), []),
!,
unique(T, Rest).
unique([H|T], Rest) :-
unique(T, Rest).
union(A, B, C) :-
append(A, B, C0),
unique(C0, C).
difference(A, B, Diff) :-
append(A, B, AB),
unique_in(AB, AB, Diff).
unique_in([], _, []).
unique_in([H|T], L, [H|Rest]) :-
findall(_, (member(X, L), X == H), [_]),
!,
unique_in(T, L, Rest).
unique_in([H|T], L, Rest) :-
unique_in(T, L, Rest).
include(_, [], []).
include(Goal, [X|Xs], Included) :-
Goal =.. L,
append(L, [X], L1),
G =.. L1,
( call(G)
-> Included = [X|Included0]
; Included = Included0
),
include(Goal, Xs, Included0).
% Additional type tests
callable(T) :- atom(T) ; compound(T).
list([]).
list([_|T]) :- list(T).
partial_list(T) :- var(T).
partial_list([_|T]) :- partial_list(T).
atomic(T) :- atom(T) ; integer(T) ; float(T).
% type assertions (throws an error if false)
is_callable(T) :- callable(T), ! ; type_error(callable, T).
is_nonvar(T) :- nonvar(T), ! ; instantiation_error.
is_list_or_partial_list(T) :- (list(T) ; partial_list(T)), ! ; type_error(list, T).
% All solutions
findall(Template, Goal, Instances) :-
is_nonvar(Goal),
is_callable(Goal),
is_list_or_partial_list(Instances),
system:asserta('find all'([])),
call(Goal),
system:asserta('find all'(solution(Template))),
fail.
findall(Template, Goal, Instances) :-
findall_collect([], Instances).
findall_collect(Acc, Instances) :-
retract('find all'(Item)),
!,
findall_collect(Item, Acc, Instances).
findall_collect([], Instances, Instances).
findall_collect(solution(T), Acc, Instances) :-
findall_collect([T|Acc], Instances).
bagof(Template, Goal, Instances) :-
free_variable_set(Goal, Template, Witness),
iterated_goal(Goal, G),
findall(Witness+Template, G, S),
bagof_loop(Witness, S, Instances).
bagof_loop(Witness, S, Instances) :-
[W+T|_] = S,
bagof_wt_list(S, W+T, WT_list),
bagof_split(WT_list, W_list, T_list),
( bagof_unify_list(Witness, W_list), Instances = T_list
; bagof_next_s(S, WT_list, S_next), bagof_loop(Witness, S_next, Instances)
).
bagof_wt_list([], _, []).
bagof_wt_list([W+T|Tail], W0+T0, Rest) :-
copy_term(W+T, W1+T1),
bagof_wt_list(Tail, W0+T0, Rest0),
( variant(W1, W0)
-> Rest = [W1+T1|Rest0]
; Rest = Rest0
).
copy_terms_list([], []).
copy_terms_list([H|T], [HH|TT]) :-
copy_term(H, HH),
copy_terms_list(T, TT).
bagof_split([], [], []).
bagof_split([WW+TT|RestWT], [WW|RestW], [TT|RestT]) :-
bagof_split(RestWT, RestW, RestT).
bagof_unify_list(W, []).
bagof_unify_list(W, [W|T]) :- bagof_unify_list(W, T).
bagof_next_s([], _, []).
bagof_next_s([H|T], WT_list, Rest) :-
bagof_next_s(T, WT_list, Rest0),
( findall(_, (member(X, WT_list), variant(X, H)), [])
-> Rest = [H|Rest0]
; Rest = Rest0
).
setof(Template, Goal, Instances) :-
bagof(Template, Goal, Instances_list),
sort(Instances_list, Instances).
% misc helpers
variable_set(Term, []) :-
atomic(Term).
variable_set(Term, [Term]) :-
var(Term).
variable_set(Term, Vars) :-
compound(Term),
Term =.. [_|Args],
variable_set(Args, [], Vars0),
unique(Vars0, Vars).
variable_set([], Acc, Acc).
variable_set([Arg|Rest], Acc0, Result) :-
variable_set(Arg, VarSet),
append(Acc0, VarSet, Acc),
variable_set(Rest, Acc, Result).
existential_variable_set(Term, []) :-
(atomic(Term) ; var(Term)),
!.
existential_variable_set(V^G, Vars) :-
!,
existential_variable_set(G, Vars0),
variable_set(V, Vars1),
union(Vars0, Vars1, Vars).
existential_variable_set(_, []).
free_variable_set(T, V, Vars) :-
variable_set(T, TVars),
variable_set(V, VVars),
existential_variable_set(T, TExVars),
union(VVars, TExVars, BV),
difference(TVars, BV, Vars).
iterated_goal(Goal, T) :-
compound(Goal),
_^G = Goal,
!,
iterated_goal(G, T).
iterated_goal(G, G).
variant(T1, T2) :-
var(T1), var(T2), !.
variant(T1, T2) :-
compound(T1),
compound(T2),
!,
T1 =.. [Name|Args1],
T2 =.. [Name|Args2],
variant_list(Args1, Args2).
variant(T1, T2) :-
T1 == T2.
variant_list([], []).
variant_list([H1|T1], [H2|T2]) :-
variant(H1, H2),
variant_list(T1, T2).
% Sorting, which also removes duplicates (should be implemented in C for speed I think).
sort(Ls0, Ls) :-
append(Lefts, [A,B|Rights], Ls0),
A @> B,
!,
append(Lefts, [B,A|Rights], Ls1),
sort(Ls1, Ls).
sort(Ls0, Ls) :-
append(Lefts, [A,B|Rights], Ls0),
A == B,
!,
append(Lefts, [A|Rights], Ls1),
sort(Ls1, Ls).
sort(Ls, Ls).