[m-dev.] Successful test of Mercury solver types
Ralph Becket
rafe at cs.mu.OZ.AU
Mon Apr 19 17:27:00 AEST 2004
I've got a version of the compiler running that compiles the attached
`church.m' module, an implementation and demonstration of a Church
numerals solver type using the new solver types facility.
Output from the demo:
$ ./church
Before...
A = *
B = succ(succ(succ(*)))
C = succ(succ(succ(succ(succ(zero)))))
After B = C...
A = succ(succ(zero))
B = succ(succ(succ(succ(succ(zero)))))
C = succ(succ(succ(succ(succ(zero)))))
Today, solver types; tomorrow, the world.
TODO: there are a few loose ends to tie up in the compiler and various
documentation jobs left to do.
-- Ralph
-------------- next part --------------
%-----------------------------------------------------------------------------%
% church.m
% Ralph Becket <rafe at cs.mu.oz.au>
% Fri Apr 2 14:31:57 EST 2004
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%
%-----------------------------------------------------------------------------%
:- module church.
:- interface.
:- import_module io.
:- semipure pred main(io :: di, io :: uo) is cc_multi.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module anyvar.
:- import_module bool.
:- import_module int.
:- import_module list.
:- import_module std_util.
:- import_module string.
%-----------------------------------------------------------------------------%
main(!IO) :-
A = church_var,
B = church_plus_n(A, 3),
C = church_plus_n(church_zero, 5),
io.format("Before...\n", [], !IO),
io.format("A = ", [], !IO), semipure print_church(A, !IO), io.nl(!IO),
io.format("B = ", [], !IO), semipure print_church(B, !IO), io.nl(!IO),
io.format("C = ", [], !IO), semipure print_church(C, !IO), io.nl(!IO),
io.format("\nAfter B = C...\n", [], !IO),
( if B = C then
io.format("A = ", [], !IO), semipure print_church(A, !IO), io.nl(!IO),
io.format("B = ", [], !IO), semipure print_church(B, !IO), io.nl(!IO),
io.format("C = ", [], !IO), semipure print_church(C, !IO), io.nl(!IO)
else
io.format("* unification failed!\n", [], !IO)
).
%-----------------------------------------------------------------------------%
:- semipure pred print_church(church::in(any), io::di, io::uo) is cc_multi.
:- pragma promise_semipure(print_church/3).
print_church(A0, !IO) :-
impure deref(A0, A1),
impure 'inst cast church/0'(A1, A),
(
A = zero,
io.write_string("zero", !IO)
;
A = succ(A2),
io.write_string("succ(", !IO),
semipure print_church(A2, !IO),
io.write_string(")", !IO)
;
A = var(_),
io.write_string("*", !IO)
).
%-----------------------------------------------------------------------------%
:- func church_zero = (church::out(any)) is det.
:- pragma promise_pure(church_zero/0).
church_zero = A :-
impure 'inst cast church/0'(A, zero).
:- func church_var = (church::in(any)) is det.
church_var = _.
:- func church_plus_n(church::in(any), int::in) = (church::out(any)) is det.
:- pragma promise_pure(church_plus_n/2).
church_plus_n(A0, N) = A :-
( if N = 0 then
A = A0
else
impure 'inst cast church/0'(A1, succ(A0)),
A = church_plus_n(A1, N - 1)
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- solver type church
---> zero
; succ(church `with_inst` any)
; var(church_var)
where initialisation is init_church,
equality is eq_church.
:- type church_var == anyvar(maybe(church)).
%-----------------------------------------------------------------------------%
:- pred init_church(church::out(any)) is det.
:- pragma promise_pure(init_church/1).
init_church(A) :-
impure anyvar.new(no, RefMaybe),
impure 'inst cast church/0'(A, var(RefMaybe)).
%-----------------------------------------------------------------------------%
:- pred eq_church(church::in(any), church::in(any)) is semidet.
eq_church(A, B) :-
promise_only_solution(eq_church_2(A, B)) = yes.
:- pred eq_church_2(church::in(any), church::in(any), bool::out) is cc_multi.
:- pragma promise_pure(eq_church_2/3).
eq_church_2(A0, B0, Eq) :-
impure deref(A0, A1),
impure deref(B0, B1),
impure 'inst cast church/0'(A1, A),
impure 'inst cast church/0'(B1, B),
( A = zero, B = zero, Eq = yes
; A = zero, B = succ(_), Eq = no
; A = zero, B = var(V), impure set_church_var_1(V, A, Eq)
; A = succ(_), B = zero, Eq = no
; A = succ(A2), B = succ(B2), eq_church_2(A2, B2, Eq)
; A = succ(_), B = var(V), impure set_church_var_1(V, A, Eq)
; A = var(V), B = zero, impure set_church_var_1(V, B, Eq)
; A = var(V), B = succ(_), impure set_church_var_1(V, B, Eq)
; A = var(VA), B = var(VB), impure set_church_var_2(VA, VB, B, Eq)
).
:- impure pred deref(church::in(any), church::out(any)) is cc_multi.
deref(A0, A) :-
impure 'inst cast church/0'(A0, A1),
( A1 = zero, A = A0
; A1 = succ(_), A = A0
; A1 = var(V), impure anyvar.get(V, MaybeA2),
(
MaybeA2 = no,
A = A0
;
MaybeA2 = yes(A2),
impure deref(A2, A)
)
).
:- impure pred set_church_var_1(church_var::in, church::in(any), bool::out)
is det.
set_church_var_1(V, A, yes) :-
impure anyvar.set(V, yes(A)).
:- impure pred set_church_var_2(church_var::in, church_var::in,
church::in(any), bool::out) is det.
set_church_var_2(VA, VB, B, yes) :-
( if VA = VB
then true
else impure anyvar.set(VA, yes(B))
).
%-----------------------------------------------------------------------------%
:- semipure pred is_var(church::in(any)) is semidet.
:- pragma promise_semipure(is_var/1).
is_var(A) :-
promise_only_solution(is_var_2(A)) = yes.
:- pred is_var_2(church::in(any), bool::out) is cc_multi.
:- pragma promise_pure(is_var_2/2).
is_var_2(A0, IsV) :-
impure deref(A0, A1),
impure 'inst cast church/0'(A1, A),
( A = zero, IsV = no
; A = succ(_), IsV = no
; A = var(_), IsV = yes
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
-------------- next part --------------
%-----------------------------------------------------------------------------%
% anyvar.m
% Ralph Becket <rafe at cs.mu.oz.au>
% Mon Apr 19 11:19:23 EST 2004
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%
% Trailed variables for inst any arguments.
%
%-----------------------------------------------------------------------------%
:- module anyvar.
:- interface.
% Equality between anyvars is by identity, rather than structural
% equality. That is, two anyvars may contain equal values, but
% not compare equal. This is unfortunate, but necessary.
%
:- type anyvar(T).
:- impure pred new(T::in(any), anyvar(T)::out) is det.
% This is impure, rather than semipure, because we may obtain a
% non-ground value from a ground anyvar.
%
:- impure pred get(anyvar(T)::in, T::out(any)) is det.
:- impure pred set(anyvar(T)::in, T::in(any)) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- pragma foreign_decl("C", "typedef MR_Word *c_anyvar;").
:- pragma foreign_type("C", anyvar(T), "c_anyvar") where equality is eq.
%-----------------------------------------------------------------------------%
:- pred eq(anyvar(T)::in, anyvar(T)::in) is semidet.
:- pragma promise_pure(eq/2).
:- pragma foreign_proc("C", eq(AnyVarA::in, AnyVarB::in),
[thread_safe, will_not_call_mercury],
"
SUCCESS_INDICATOR = (*AnyVarA == *AnyVarB);
").
%-----------------------------------------------------------------------------%
:- pragma foreign_proc("C", new(X::in(any), AnyVar::out),
[thread_safe, will_not_call_mercury],
"
AnyVar = (c_anyvar) MR_GC_NEW(c_anyvar);
*AnyVar = (MR_Word) X;
").
%-----------------------------------------------------------------------------%
:- pragma foreign_proc("C", get(AnyVar::in, X::out(any)),
[thread_safe, will_not_call_mercury],
"
(MR_Word) X = *AnyVar;
").
%-----------------------------------------------------------------------------%
% XXX Is trailing thread_safe? Or, rather, is threading trail safe :-) ?
%
:- pragma foreign_proc("C", set(AnyVar::in, X::in(any)),
[/*thread_safe, */will_not_call_mercury],
"
MR_trail_current_value(AnyVar);
*AnyVar = (MR_Word) X;
").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
More information about the developers
mailing list