]> Repositorios git - scryer-prolog.git/commitdiff
add ordsets library, domain.pl attributed variables example
authorMark Thom <[email protected]>
Mon, 11 Mar 2019 04:33:09 +0000 (22:33 -0600)
committerMark Thom <[email protected]>
Mon, 11 Mar 2019 04:33:09 +0000 (22:33 -0600)
src/prolog/examples/domain.pl [new file with mode: 0644]
src/prolog/lib/ordsets.pl [new file with mode: 0644]
src/prolog/machine/compile.rs
src/prolog/machine/mod.rs

diff --git a/src/prolog/examples/domain.pl b/src/prolog/examples/domain.pl
new file mode 100644 (file)
index 0000000..cfada79
--- /dev/null
@@ -0,0 +1,52 @@
+/* From the SICSTUS Prolog documentation at:
+https://sicstus.sics.se/sicstus/docs/3.7.1/html/sicstus_17.html
+*/
+
+:- module(domain, [domain/2]).
+
+:- use_module(library(atts)).
+:- use_module(library(ordsets), [
+        ord_intersection/3,
+        ord_intersect/2,
+        list_to_ord_set/2
+   ]).
+
+:- attribute dom/1.
+
+verify_attributes(Var, Other, Goals) :-
+        get_atts(Var, dom(Da)), !,          % are we involved?
+        (   var(Other) ->                   % must be attributed then
+            (   get_atts(Other, dom(Db)) -> %   has a domain?
+                ord_intersection(Da, Db, Dc),
+                Dc = [El|Els],              % at least one element
+                (   Els = [] ->             % exactly one element
+                    Goals = [Other=El]      % implied binding
+                ;   Goals = [],
+                   put_atts(Other, -dom(_)),
+                    put_atts(Other, dom(Dc))% rescue intersection
+                )
+            ;   Goals = [],
+                put_atts(Other, dom(Da))    % rescue the domain
+            )
+        ;   Goals = [],
+            ord_intersect([Other], Da)      % value in domain?
+        ).
+verify_attributes(_, _, []).                % unification triggered
+                                            % because of attributes
+                                            % in other modules
+
+attribute_goals(Var, domain(Var,Dom)) :-     % interpretation as goal
+        get_atts(Var, dom(Dom)).
+
+domain(X, Dom) :-
+        var(Dom), !,
+        get_atts(X, dom(Dom)).
+domain(X, List) :-
+        list_to_ord_set(List, Set),
+        Set = [El|Els],                     % at least one element
+        (   Els = [] ->                     % exactly one element
+            X = El                          % implied binding
+        ;   put_atts(Fresh, dom(Set)),
+            X = Fresh                       % may call
+                                            % verify_attributes/3
+        ).
diff --git a/src/prolog/lib/ordsets.pl b/src/prolog/lib/ordsets.pl
new file mode 100644 (file)
index 0000000..ff08096
--- /dev/null
@@ -0,0 +1,625 @@
+/*  Author:        Jan Wielemaker
+    E-mail:        [email protected]
+    WWW:           http://www.swi-prolog.org
+    Copyright (c)  2001-2014, University of Amsterdam
+                              VU University Amsterdam
+    All rights reserved.
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in
+       the documentation and/or other materials provided with the
+       distribution.
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.
+*/
+
+:- module(ordsets,
+          [ is_ordset/1,                % @Term
+            list_to_ord_set/2,          % +List, -OrdSet
+            ord_add_element/3,          % +Set, +Element, -NewSet
+            ord_del_element/3,          % +Set, +Element, -NewSet
+            ord_selectchk/3,            % +Item, ?Set1, ?Set2
+            ord_intersect/2,            % +Set1, +Set2 (test non-empty)
+            ord_intersect/3,            % +Set1, +Set2, -Intersection
+            ord_intersection/3,         % +Set1, +Set2, -Intersection
+            ord_intersection/4,         % +Set1, +Set2, -Intersection, -Diff
+            ord_disjoint/2,             % +Set1, +Set2
+            ord_subtract/3,             % +Set, +Delete, -Remaining
+            ord_union/2,                % +SetOfOrdSets, -Set
+            ord_union/3,                % +Set1, +Set2, -Union
+            ord_union/4,                % +Set1, +Set2, -Union, -New
+            ord_subset/2,               % +Sub, +Super (test Sub is in Super)
+                                        % Non-Quintus extensions
+            ord_empty/1,                % ?Set
+            ord_memberchk/2,            % +Element, +Set,
+            ord_symdiff/3,              % +Set1, +Set2, ?Diff
+                                        % SICSTus extensions
+            ord_seteq/2,                % +Set1, +Set2
+            ord_intersection/2          % +PowerSet, -Intersection
+          ]).
+
+:- use_module(library(lists)).
+
+/** <module> Ordered set manipulation
+Ordered sets are lists with unique elements sorted to the standard order
+of terms (see sort/2). Exploiting ordering,   many of the set operations
+can be expressed in order N rather  than N^2 when dealing with unordered
+sets that may contain duplicates. The library(ordsets) is available in a
+number of Prolog implementations. Our  predicates   are  designed  to be
+compatible  with  common  practice   in    the   Prolog  community.  The
+implementation is incomplete and  relies   partly  on  library(oset), an
+older ordered set library distributed  with SWI-Prolog. New applications
+are advised to use library(ordsets).
+Some  of  these  predicates  match    directly   to  corresponding  list
+operations. It is advised to use the  versions from this library to make
+clear you are operating on ordered sets.   An exception is member/2. See
+ord_memberchk/2.
+The ordsets library is based  on  the   standard  order  of  terms. This
+implies it can handle  all  Prolog   terms,  including  variables.  Note
+however, that the ordering is not stable  if   a  term inside the set is
+further instantiated. Also  note  that   variable  ordering  changes  if
+variables in the set are unified with each   other  or a variable in the
+set is unified with a variable that  is `older' than the newest variable
+in the set. In  practice,  this  implies   that  it  is  allowed  to use
+member(X, OrdSet) on an ordered set that holds  variables only if X is a
+fresh variable. In other cases one should   cease  using it as an ordset
+because the order it relies on may have been changed.
+*/
+
+%!  is_ordset(@Term) is semidet.
+%
+%   True if Term is an ordered set.   All predicates in this library
+%   expect ordered sets as input arguments.  Failing to fullfil this
+%   assumption results in undefined   behaviour.  Typically, ordered
+%   sets are created by predicates  from   this  library,  sort/2 or
+%   setof/3.
+
+is_ordset(Term) :-
+    '$skip_max_list'(_, -1, Term, Tail), Tail == [], %% is_list(Term),
+    is_ordset2(Term).
+
+is_ordset2([]).
+is_ordset2([H|T]) :-
+    is_ordset3(T, H).
+
+is_ordset3([], _).
+is_ordset3([H2|T], H) :-
+    H2 @> H,
+    is_ordset3(T, H2).
+
+
+%!  ord_empty(?List) is semidet.
+%
+%   True when List is the  empty   ordered  set. Simply unifies list
+%   with the empty list. Not part of Quintus.
+
+ord_empty([]).
+
+
+%!  ord_seteq(+Set1, +Set2) is semidet.
+%
+%   True if Set1 and Set2  have  the   same  elements.  As  both are
+%   canonical sorted lists, this is the same as ==/2.
+%
+%   @compat sicstus
+
+ord_seteq(Set1, Set2) :-
+    Set1 == Set2.
+
+
+%!  list_to_ord_set(+List, -OrdSet) is det.
+%
+%   Transform a list into an ordered set.  This is the same as
+%   sorting the list.
+
+list_to_ord_set(List, Set) :-
+    sort(List, Set).
+
+
+%!  ord_intersect(+Set1, +Set2) is semidet.
+%
+%   True if both ordered sets have a non-empty intersection.
+
+ord_intersect([H1|T1], L2) :-
+    ord_intersect_(L2, H1, T1).
+
+ord_intersect_([H2|T2], H1, T1) :-
+    compare(Order, H1, H2),
+    ord_intersect__(Order, H1, T1, H2, T2).
+
+ord_intersect__(<, _H1, T1,  H2, T2) :-
+    ord_intersect_(T1, H2, T2).
+ord_intersect__(=, _H1, _T1, _H2, _T2).
+ord_intersect__(>, H1, T1,  _H2, T2) :-
+    ord_intersect_(T2, H1, T1).
+
+
+%!  ord_disjoint(+Set1, +Set2) is semidet.
+%
+%   True if Set1 and Set2  have  no   common  elements.  This is the
+%   negation of ord_intersect/2.
+
+ord_disjoint(Set1, Set2) :-
+    \+ ord_intersect(Set1, Set2).
+
+
+%!  ord_intersect(+Set1, +Set2, -Intersection)
+%
+%   Intersection  holds  the  common  elements  of  Set1  and  Set2.
+%
+%   @deprecated Use ord_intersection/3
+
+ord_intersect(Set1, Set2, Intersection) :-
+    oset_int(Set1, Set2, Intersection).
+
+
+%!  ord_intersection(+PowerSet, -Intersection)
+%
+%   Intersection of a powerset. True when Intersection is an ordered
+%   set holding all elements common to all sets in PowerSet.
+%
+%   @compat sicstus
+
+ord_intersection(PowerSet, Intersection) :-
+    key_by_length(PowerSet, Pairs),
+    keysort(Pairs, [_-S|Sorted]),
+    l_int(Sorted, S, Intersection).
+
+key_by_length([], []).
+key_by_length([H|T0], [L-H|T]) :-
+    length(H, L),
+    key_by_length(T0, T).
+
+l_int([], S, S).
+l_int([_-H|T], S0, S) :-
+    ord_intersection(S0, H, S1),
+    l_int(T, S1, S).
+
+
+%!  ord_intersection(+Set1, +Set2, -Intersection) is det.
+%
+%   Intersection holds the common elements of Set1 and Set2.  Uses
+%   ord_disjoint/2 if Intersection is bound to `[]` on entry.
+
+ord_intersection(Set1, Set2, Intersection) :-
+    (   Intersection == []
+    ->  ord_disjoint(Set1, Set2)
+    ;   oset_int(Set1, Set2, Intersection)
+    ).
+
+
+%!  ord_intersection(+Set1, +Set2, ?Intersection, ?Difference) is det.
+%
+%   Intersection  and  difference   between    two   ordered   sets.
+%   Intersection is the intersection between   Set1  and Set2, while
+%   Difference is defined by ord_subtract(Set2, Set1, Difference).
+%
+%   @see ord_intersection/3 and ord_subtract/3.
+
+ord_intersection([], L, [], L) :- !.
+ord_intersection([_|_], [], [], []) :- !.
+ord_intersection([H1|T1], [H2|T2], Intersection, Difference) :-
+    compare(Diff, H1, H2),
+    ord_intersection2(Diff, H1, T1, H2, T2, Intersection, Difference).
+
+ord_intersection2(=, H1, T1, _H2, T2, [H1|T], Difference) :-
+    ord_intersection(T1, T2, T, Difference).
+ord_intersection2(<, _, T1, H2, T2, Intersection, Difference) :-
+    ord_intersection(T1, [H2|T2], Intersection, Difference).
+ord_intersection2(>, H1, T1, H2, T2, Intersection, [H2|HDiff]) :-
+    ord_intersection([H1|T1], T2, Intersection, HDiff).
+
+
+%!  ord_add_element(+Set1, +Element, ?Set2) is det.
+%
+%   Insert  an  element  into  the  set.    This   is  the  same  as
+%   ord_union(Set1, [Element], Set2).
+
+ord_add_element(Set1, Element, Set2) :-
+    oset_addel(Set1, Element, Set2).
+
+
+%!  ord_del_element(+Set, +Element, -NewSet) is det.
+%
+%   Delete an element from an  ordered  set.   This  is  the same as
+%   ord_subtract(Set, [Element], NewSet).
+
+ord_del_element(Set, Element, NewSet) :-
+    oset_delel(Set, Element, NewSet).
+
+
+%!  ord_selectchk(+Item, ?Set1, ?Set2) is semidet.
+%
+%   Selectchk/3,  specialised  for  ordered  sets.    Is  true  when
+%   select(Item, Set1, Set2) and Set1, Set2   are  both sorted lists
+%   without duplicates. This implementation is only expected to work
+%   for Item ground and either Set1 or Set2 ground. The "chk" suffix
+%   is meant to remind you of   memberchk/2,  which also expects its
+%   first  argument  to  be  ground.    ord_selectchk(X,  S,  T)  =>
+%   ord_memberchk(X, S) & \+ ord_memberchk(X, T).
+%
+%   @author Richard O'Keefe
+
+ord_selectchk(Item, [X|Set1], [X|Set2]) :-
+    X @< Item,
+    !,
+    ord_selectchk(Item, Set1, Set2).
+ord_selectchk(Item, [Item|Set1], Set1) :-
+    (   Set1 == []
+    ->  true
+    ;   Set1 = [Y|_]
+    ->  Item @< Y
+    ).
+
+
+%!  ord_memberchk(+Element, +OrdSet) is semidet.
+%
+%   True if Element is a member of   OrdSet, compared using ==. Note
+%   that _enumerating_ elements of an ordered  set can be done using
+%   member/2.
+%
+%   Some Prolog implementations also provide  ord_member/2, with the
+%   same semantics as ord_memberchk/2.  We   believe  that  having a
+%   semidet ord_member/2 is unacceptably inconsistent with the *_chk
+%   convention.  Portable  code  should    use   ord_memberchk/2  or
+%   member/2.
+%
+%   @author Richard O'Keefe
+
+ord_memberchk(Item, [X1,X2,X3,X4|Xs]) :-
+    !,
+    compare(R4, Item, X4),
+    (   R4 = (>) -> ord_memberchk(Item, Xs)
+    ;   R4 = (<) ->
+        compare(R2, Item, X2),
+        (   R2 = (>) -> Item == X3
+        ;   R2 = (<) -> Item == X1
+        ;/* R2 = (=),   Item == X2 */ true
+        )
+    ;/* R4 = (=) */ true
+    ).
+ord_memberchk(Item, [X1,X2|Xs]) :-
+    !,
+    compare(R2, Item, X2),
+    (   R2 = (>) -> ord_memberchk(Item, Xs)
+    ;   R2 = (<) -> Item == X1
+    ;/* R2 = (=) */ true
+    ).
+ord_memberchk(Item, [X1]) :-
+    Item == X1.
+
+
+%!  ord_subset(+Sub, +Super) is semidet.
+%
+%   Is true if all elements of Sub are in Super
+
+ord_subset([], _).
+ord_subset([H1|T1], [H2|T2]) :-
+    compare(Order, H1, H2),
+    ord_subset_(Order, H1, T1, T2).
+
+ord_subset_(>, H1, T1, [H2|T2]) :-
+    compare(Order, H1, H2),
+    ord_subset_(Order, H1, T1, T2).
+ord_subset_(=, _, T1, T2) :-
+    ord_subset(T1, T2).
+
+
+%!  ord_subtract(+InOSet, +NotInOSet, -Diff) is det.
+%
+%   Diff is the set holding all elements of InOSet that are not in
+%   NotInOSet.
+
+ord_subtract(InOSet, NotInOSet, Diff) :-
+    oset_diff(InOSet, NotInOSet, Diff).
+
+
+%!  ord_union(+SetOfSets, -Union) is det.
+%
+%   True if Union is the  union  of   all  elements  in the superset
+%   SetOfSets. Each member of SetOfSets must  be an ordered set, the
+%   sets need not be ordered in any way.
+%
+%   @author Copied from YAP, probably originally by Richard O'Keefe.
+
+ord_union([], []).
+ord_union([Set|Sets], Union) :-
+    length([Set|Sets], NumberOfSets),
+    ord_union_all(NumberOfSets, [Set|Sets], Union, []).
+
+ord_union_all(N, Sets0, Union, Sets) :-
+    (   N =:= 1
+    ->  Sets0 = [Union|Sets]
+    ;   N =:= 2
+    ->  Sets0 = [Set1,Set2|Sets],
+        ord_union(Set1,Set2,Union)
+    ;   A is N>>1,
+        Z is N-A,
+        ord_union_all(A, Sets0, X, Sets1),
+        ord_union_all(Z, Sets1, Y, Sets),
+        ord_union(X, Y, Union)
+    ).
+
+
+%!  ord_union(+Set1, +Set2, ?Union) is det.
+%
+%   Union is the union of Set1 and Set2
+
+ord_union(Set1, Set2, Union) :-
+    oset_union(Set1, Set2, Union).
+
+
+%!  ord_union(+Set1, +Set2, -Union, -New) is det.
+%
+%   True iff ord_union(Set1, Set2, Union) and
+%   ord_subtract(Set2, Set1, New).
+
+ord_union([], Set2, Set2, Set2).
+ord_union([H|T], Set2, Union, New) :-
+    ord_union_1(Set2, H, T, Union, New).
+
+ord_union_1([], H, T, [H|T], []).
+ord_union_1([H2|T2], H, T, Union, New) :-
+    compare(Order, H, H2),
+    ord_union(Order, H, T, H2, T2, Union, New).
+
+ord_union(<, H, T, H2, T2, [H|Union], New) :-
+    ord_union_2(T, H2, T2, Union, New).
+ord_union(>, H, T, H2, T2, [H2|Union], [H2|New]) :-
+    ord_union_1(T2, H, T, Union, New).
+ord_union(=, H, T, _, T2, [H|Union], New) :-
+    ord_union(T, T2, Union, New).
+
+ord_union_2([], H2, T2, [H2|T2], [H2|T2]).
+ord_union_2([H|T], H2, T2, Union, New) :-
+    compare(Order, H, H2),
+    ord_union(Order, H, T, H2, T2, Union, New).
+
+
+%!  ord_symdiff(+Set1, +Set2, ?Difference) is det.
+%
+%   Is true when Difference is the  symmetric difference of Set1 and
+%   Set2. I.e., Difference contains all elements that are not in the
+%   intersection of Set1 and Set2. The semantics  is the same as the
+%   sequence below (but the actual   implementation  requires only a
+%   single scan).
+%
+%     ==
+%           ord_union(Set1, Set2, Union),
+%           ord_intersection(Set1, Set2, Intersection),
+%           ord_subtract(Union, Intersection, Difference).
+%     ==
+%
+%   For example:
+%
+%     ==
+%     ?- ord_symdiff([1,2], [2,3], X).
+%     X = [1,3].
+%     ==
+
+ord_symdiff([], Set2, Set2).
+ord_symdiff([H1|T1], Set2, Difference) :-
+    ord_symdiff(Set2, H1, T1, Difference).
+
+ord_symdiff([], H1, T1, [H1|T1]).
+ord_symdiff([H2|T2], H1, T1, Difference) :-
+    compare(Order, H1, H2),
+    ord_symdiff(Order, H1, T1, H2, T2, Difference).
+
+ord_symdiff(<, H1, Set1, H2, T2, [H1|Difference]) :-
+    ord_symdiff(Set1, H2, T2, Difference).
+ord_symdiff(=, _, T1, _, T2, Difference) :-
+    ord_symdiff(T1, T2, Difference).
+ord_symdiff(>, H1, T1, H2, Set2, [H2|Difference]) :-
+    ord_symdiff(Set2, H1, T1, Difference).
+
+/* The osets library on which ordsets depends.
+
+ Author:        Jon Jagger
+    E-mail:        [email protected]
+    Copyright (c)  1993-2011, Jon Jagger
+    All rights reserved.
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in
+       the documentation and/or other materials provided with the
+       distribution.
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** <module> Ordered set manipulation
+
+This library defines set operations on sets represented as ordered
+lists.
+
+@author Jon Jagger
+@deprecated Use the de-facto library ordsets.pl
+*/
+
+
+%% oset_is(+OSet)
+%   check that OSet in correct format (standard order)
+
+oset_is(-) :- !, fail.    % var filter
+oset_is([]).
+oset_is([H|T]) :-
+    oset_is(T, H).
+
+oset_is(-, _) :- !, fail.  % var filter
+oset_is([], _H).
+oset_is([H|T], H0) :-
+    H0 @< H,               % use standard order
+    oset_is(T, H).
+
+
+
+%% oset_union(+OSet1, +OSet2, -Union).
+
+oset_union([], Union, Union).
+oset_union([H1|T1], L2, Union) :-
+    union2(L2, H1, T1, Union).
+
+union2([], H1, T1, [H1|T1]).
+union2([H2|T2], H1, T1, Union) :-
+    compare(Order, H1, H2),
+    union3(Order, H1, T1, H2, T2, Union).
+
+union3(<, H1, T1,  H2, T2, [H1|Union]) :-
+    union2(T1, H2, T2, Union).
+union3(=, H1, T1, _H2, T2, [H1|Union]) :-
+    oset_union(T1, T2, Union).
+union3(>, H1, T1,  H2, T2, [H2|Union]) :-
+    union2(T2, H1, T1, Union).
+
+
+%% oset_int(+OSet1, +OSet2, -Int)
+%   ordered set intersection
+
+oset_int([], _Int, []).
+oset_int([H1|T1], L2, Int) :-
+    isect2(L2, H1, T1, Int).
+
+isect2([], _H1, _T1, []).
+isect2([H2|T2], H1, T1, Int) :-
+    compare(Order, H1, H2),
+    isect3(Order, H1, T1, H2, T2, Int).
+
+isect3(<, _H1, T1,  H2, T2, Int) :-
+    isect2(T1, H2, T2, Int).
+isect3(=, H1, T1, _H2, T2, [H1|Int]) :-
+    oset_int(T1, T2, Int).
+isect3(>, H1, T1,  _H2, T2, Int) :-
+    isect2(T2, H1, T1, Int).
+
+
+%% oset_diff(+InOSet, +NotInOSet, -Diff)
+%   ordered set difference
+
+oset_diff([], _Not, []).
+oset_diff([H1|T1], L2, Diff) :-
+    diff21(L2, H1, T1, Diff).
+
+diff21([], H1, T1, [H1|T1]).
+diff21([H2|T2], H1, T1, Diff) :-
+    compare(Order, H1, H2),
+    diff3(Order, H1, T1, H2, T2, Diff).
+
+diff12([], _H2, _T2, []).
+diff12([H1|T1], H2, T2, Diff) :-
+    compare(Order, H1, H2),
+    diff3(Order, H1, T1, H2, T2, Diff).
+
+diff3(<,  H1, T1,  H2, T2, [H1|Diff]) :-
+    diff12(T1, H2, T2, Diff).
+diff3(=, _H1, T1, _H2, T2, Diff) :-
+    oset_diff(T1, T2, Diff).
+diff3(>,  H1, T1, _H2, T2, Diff) :-
+    diff21(T2, H1, T1, Diff).
+
+
+%% oset_dunion(+SetofSets, -DUnion)
+%   distributed union
+
+oset_dunion([], []).
+oset_dunion([H|T], DUnion) :-
+    oset_dunion(T, H, DUnion).
+
+oset_dunion([], DUnion, DUnion).
+oset_dunion([H|T], DUnion0, DUnion) :-
+    oset_union(H, DUnion0, DUnion1),
+    oset_dunion(T, DUnion1, DUnion).
+
+
+%% oset_dint(+SetofSets, -DInt)
+%   distributed intersection
+
+oset_dint([], []).
+oset_dint([H|T], DInt) :-
+    dint(T, H, DInt).
+
+dint([], DInt, DInt).
+dint([H|T], DInt0, DInt) :-
+    oset_int(H, DInt0, DInt1),
+    dint(T, DInt1, DInt).
+
+
+%!  oset_power(+Set, -PSet)
+%
+%   True when PSet is the powerset of Set. That is, Pset is a set of
+%   all subsets of Set, where each subset is a proper ordered set.
+
+oset_power(S, PSet) :-
+    reverse(S, R),
+    pset(R, [[]], PSet0),
+    sort(PSet0, PSet).
+
+
+% The powerset of a set  is  the  powerset   of  a  set  of one smaller,
+% together with the set of one  smaller   where  each subset is extended
+% with the new element.  Note that this produces the elements of the set
+% in reverse order.  Hence the reverse in oset_power/2.
+
+pset([], PSet, PSet).
+pset([H|T], PSet0, PSet) :-
+    happ(PSet0, H, PSet1),
+    pset(T, PSet1, PSet).
+
+happ([], _, []).
+happ([S|Ss], H, [[H|S],S|Rest]) :-
+    happ(Ss, H, Rest).
+
+%% oset_addel(+Set, +El, -Add)
+%   ordered set element addition
+
+oset_addel([], El, [El]).
+oset_addel([H|T], El, Add) :-
+    compare(Order, H, El),
+    addel(Order, H, T, El, Add).
+
+addel(<, H, T,  El, [H|Add]) :-
+    oset_addel(T, El, Add).
+addel(=, H, T, _El, [H|T]).
+addel(>, H, T,  El, [El,H|T]).
+
+%% oset_delel(+Set, +El, -Del)
+%   ordered set element deletion
+
+oset_delel([], _El, []).
+oset_delel([H|T], El, Del) :-
+    compare(Order, H, El),
+    delel(Order, H, T, El, Del).
+
+delel(<,  H, T,  El, [H|Del]) :-
+    oset_delel(T, El, Del).
+delel(=, _H, T, _El, T).
+delel(>,  H, T, _El, [H|T]).
index 9761b6ee1d034962d3f8148e439ad2afd1dbe814..b2bb3914d1aba7be984d298aec2f45ba6c345a20 100644 (file)
@@ -192,8 +192,8 @@ fn add_hooks_to_mockup(code_repo: &mut CodeRepo, hook: CompileTimeHook,
     let preds = code_repo.term_dir.entry(key.clone())
         .or_insert((Predicate::new(), VecDeque::from(vec![])));
 
-    (preds.0).0.extend((expansions.0).0.iter().cloned());
-    preds.1.extend(expansions.1.iter().cloned());
+    (preds.0).0.extend((expansions.0).0.into_iter());
+    preds.1.extend(expansions.1.into_iter());
 }
 
 fn setup_module_expansions(wam: &mut Machine, module_name: ClauseName)
index 3b57e7af520452107f80f914d5bdc43f3f27a113..31ff4d728a46bd2ef340602e1a79c758c9e4f7db 100644 (file)
@@ -154,6 +154,7 @@ static DIF: &str      = include_str!("../lib/dif.pl");
 static FREEZE: &str   = include_str!("../lib/freeze.pl");
 static REIF: &str     = include_str!("../lib/reif.pl");
 static ASSOC: &str    = include_str!("../lib/assoc.pl");
+static ORDSETS: &str  = include_str!("../lib/ordsets.pl");
 
 impl Machine {
     fn compile_special_forms(&mut self) {
@@ -186,6 +187,7 @@ impl Machine {
         compile_user_module(self, FREEZE.as_bytes());
         compile_user_module(self, REIF.as_bytes());
         compile_user_module(self, ASSOC.as_bytes());
+        compile_user_module(self, ORDSETS.as_bytes());
     }
 
     pub fn new() -> Self {