shithub: pprolog

ref: 9b4f17521bb8a7d96c09d540880679298ce6f08e
dir: /stdlib.pl/

View raw version
:- 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
	).

% 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).