-:- module(atts, [attribute/1, absent_attr/2, get_attr/2, put_attr/2,
- absent_from_list/2, get_from_list/2, add_to_list/2,
- del_attr/3, del_attr_step/2, del_attr_non_head/3]).
+:- module(atts, [attribute/1, '$absent_attr'/2, '$get_attr'/2, '$put_attr'/2,
+ '$absent_from_list'/2, '$get_from_list'/2, '$add_to_list'/2,
+ '$del_attr'/3, '$del_attr_step'/2, '$del_attr_buried'/3]).
:- use_module(library(control)).
:- use_module(library(dcgs)).
:- op(1199, fx, attribute).
-absent_attr(V, Attr) :-
+'$absent_attr'(V, Attr) :-
'$get_attr_list'(V, Ls),
- absent_from_list(Ls, Attr).
+ '$absent_from_list'(Ls, Attr).
-absent_from_list(X, _) :-
+'$absent_from_list'(X, _) :-
var(X), !.
-absent_from_list([L|Ls], Attr) :-
- ( L \= Attr -> absent_from_list(Ls, Attr) ).
+'$absent_from_list'([L|Ls], Attr) :-
+ ( L \= Attr -> '$absent_from_list'(Ls, Attr) ).
-get_attr(V, Attr) :-
- '$get_attr_list'(V, Ls), nonvar(Ls), get_from_list(Ls, Attr).
+'$get_attr'(V, Attr) :-
+ '$get_attr_list'(V, Ls), nonvar(Ls), '$get_from_list'(Ls, Attr).
-get_from_list([L|Ls], Attr) :-
+'$get_from_list'([L|Ls], Attr) :-
nonvar(L),
- ( L \= Attr -> nonvar(Ls), get_from_list(Ls, Attr)
+ ( L \= Attr -> nonvar(Ls), '$get_from_list'(Ls, Attr)
; copy_term(L, L0), L0 = Attr
- ; get_from_list(Ls, Attr)
+ ; '$get_from_list'(Ls, Attr)
).
-put_attr(V, Attr) :-
- '$get_attr_list'(V, Ls), add_to_list(Ls, Attr).
+'$put_attr'(V, Attr) :-
+ '$get_attr_list'(V, Ls), '$add_to_list'(Ls, Attr).
-add_to_list(Ls, Attr) :-
+'$add_to_list'(Ls, Attr) :-
( var(Ls) -> Ls = [Attr | _]
- ; Ls = [_ | Ls0] -> add_to_list(Ls0, Attr)
+ ; Ls = [_ | Ls0] -> '$add_to_list'(Ls0, Attr)
).
-del_attr(Ls0, _, _) :-
+'$del_attr'(Ls0, _, _) :-
var(Ls0), !.
-del_attr(Ls0, V, Attr) :-
+'$del_attr'(Ls0, V, Attr) :-
Ls0 = [Att | Ls1],
nonvar(Att),
- ( Att \= Attr -> del_attr_non_head(Ls0, Ls1, Attr)
- ; '$del_attr_head'(V), del_attr(Ls1, V, Attr)
+ ( Att \= Attr -> '$del_attr_buried'(Ls0, Ls1, Attr)
+ ; '$del_attr_head'(V), '$del_attr'(Ls1, V, Attr)
).
-del_attr_step(Ls1, Attr) :-
- ( nonvar(Ls1) -> Ls1 = [_ | Ls2], del_attr_non_head(Ls1, Ls2, Attr)
+'$del_attr_step'(Ls1, Attr) :-
+ ( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, Attr)
; true ).
%% assumptions: Ls0 is a list, Ls1 is its tail;
%% the head of Ls0 can be ignored.
-del_attr_non_head(Ls0, Ls1, Attr) :-
+'$del_attr_buried'(Ls0, Ls1, Attr) :-
Ls0 = [_, Att | _],
nonvar(Att),
!,
- ( Att \= Attr -> del_attr_step(Ls1, Attr)
- ; '$del_attr'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
- del_attr_step(Ls1, Attr)
+ ( Att \= Attr -> '$del_attr_step'(Ls1, Attr)
+ ; '$del_attr_non_head'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
+ '$del_attr_step'(Ls1, Attr)
).
-del_attr_non_head(_, _, _).
+'$del_attr_buried'(_, _, _).
user:term_expansion(Term0, Terms) :-
nonvar(Term0),
{ functor(Attr, Name, Arity),
numbervars(Attr, 0, Arity),
V = '$VAR'(Arity) },
- [(put_atts(V, +Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
- (put_atts(V, Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
- (put_atts(V, -Attr) :- !, functor(Attr, _, _), '$get_attr_list'(V, Ls), del_attr(Ls, V, Attr))].
+ [(put_atts(V, +Attr) :- !, functor(Attr, _, _), '$put_attr'(V, Attr)),
+ (put_atts(V, Attr) :- !, functor(Attr, _, _), '$put_attr'(V, Attr)),
+ (put_atts(V, -Attr) :- !, functor(Attr, _, _), '$get_attr_list'(V, Ls), '$del_attr'(Ls, V, Attr))].
get_attr(Name, Arity) -->
{ functor(Attr, Name, Arity),
numbervars(Attr, 0, Arity),
V = '$VAR'(Arity) },
- [(get_atts(V, +Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
- (get_atts(V, Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
- (get_atts(V, -Attr) :- !, functor(Attr, _, _), absent_attr(V, Attr))].
+ [(get_atts(V, +Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
+ (get_atts(V, Attr) :- !, functor(Attr, _, _), '$get_attr'(V, Attr)),
+ (get_atts(V, -Attr) :- !, functor(Attr, _, _), '$absent_attr'(V, Attr))].
user:goal_expansion(Term, M:put_atts(Var, Attr)) :-
nonvar(Term),
assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abcdef\", X), X = \"abcdef\".",
[["X = [a, b, c, d, e, f]"]]);
}
+
+#[test]
+fn test_queries_on_attributed_variables()
+{
+ let mut wam = Machine::new();
+
+ submit(&mut wam, "
+:- module(my_mod, []).
+:- use_module(library(atts)).
+
+:- attribute dif/1, frozen/1.");
+
+ assert_prolog_success!(&mut wam, "?- ( put_atts(V, my_mod, dif(1)) ; put_atts(V, my_mod, dif(2)) ),
+ get_atts(V, my_mod, L).",
+ [["L = [dif(1) | _17]", "V = _12"],
+ ["L = [dif(2) | _17]", "V = _12"]]);
+
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, frozen(a)),
+ ( put_atts(V, my_mod, dif(1))
+ ; put_atts(V, my_mod, -frozen(a)), put_atts(V, my_mod, dif(2))
+ ; put_atts(V, my_mod, dif(different)) ),
+ get_atts(V, my_mod, Ls).",
+ [["Ls = [frozen(a), dif(1) | _37]", "V = _12"],
+ ["Ls = [dif(2) | _51]", "V = _12"],
+ ["Ls = [frozen(a), dif(different) | _37]", "V = _12"]]);
+
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a)]),
+ ( put_atts(V, my_mod, -dif(2)) ; put_atts(V, my_mod, -frozen(A)) ),
+ get_atts(V, my_mod, L).",
+ [["A = _70", "L = [dif(1), frozen(a) | _68]", "V = _27"],
+ ["A = _70", "L = [dif(1), dif(2) | _68]", "V = _27"]]);
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]),
+ ( put_atts(V, my_mod, -dif(2)) ; put_atts(V, my_mod, -frozen(A)) ),
+ get_atts(V, my_mod, L).",
+ [["A = _98", "L = [dif(1), frozen(a), frozen(b) | _96]", "V = _31"],
+ ["A = _98", "L = [dif(1), dif(2) | _96]", "V = _31"]]);
+ assert_prolog_failure!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]),
+ get_atts(V, my_mod, -dif(1)).");
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]),
+ get_atts(V, my_mod, -dif(3)).");
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]),
+ get_atts(V, my_mod, dif(X)).",
+ [["X = 1", "V = _31"],
+ ["X = 2", "V = _31"]]);
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]),
+ put_atts(V, my_mod, -dif(A)), get_atts(V, my_mod, Ls).",
+ [["A = _99", "Ls = [frozen(a), frozen(b) | _96]", "V = _31"]]);
+ assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), frozen(a), dif(2), frozen(b)]),
+ put_atts(V, my_mod, -dif(A)), get_atts(V, my_mod, Ls).",
+ [["A = _99", "Ls = [frozen(a), frozen(b) | _96]", "V = _31"]]);
+}