[m-rev.] diff: deconstruct list terms in erlang backend

Peter Wang wangp at students.csse.unimelb.edu.au
Fri Aug 24 17:58:26 AEST 2007


Estimated hours taken: 3
Branches: main

library/erlang_rtti_implementation.m:
	Make the Erlang deconstruct implementation handle list terms,
	i.e. Mercury values with constructors '[]' and '[|]'.

tests/hard_coded/Mmakefile:
tests/hard_coded/existential_list.exp:
tests/hard_coded/existential_list.m:
	Add a test case.


Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.330
diff -u -r1.330 Mmakefile
--- tests/hard_coded/Mmakefile	20 Aug 2007 03:36:18 -0000	1.330
+++ tests/hard_coded/Mmakefile	24 Aug 2007 07:54:53 -0000
@@ -71,6 +71,7 @@
 	error_func \
 	existential_bound_tvar \
 	existential_float \
+	existential_list \
 	existential_reordering \
 	existential_reordering_class \
 	existential_type_switch_opt \
Index: tests/hard_coded/existential_list.exp
===================================================================
RCS file: tests/hard_coded/existential_list.exp
diff -N tests/hard_coded/existential_list.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/existential_list.exp	24 Aug 2007 07:54:53 -0000
@@ -0,0 +1 @@
+[42, "bar"]
Index: tests/hard_coded/existential_list.m
===================================================================
RCS file: tests/hard_coded/existential_list.m
diff -N tests/hard_coded/existential_list.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/existential_list.m	24 Aug 2007 07:54:53 -0000
@@ -0,0 +1,22 @@
+% The Erlang backend treats [] and [|] data constructors specially.  This test
+% checks we can deconstruct existential types that use the special syntax.
+
+:- module existential_list.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- type foo
+    --->    []
+    ;       some [T] [T | foo].
+
+main(!IO) :-
+    T = 'new [|]'(42, 'new [|]'("bar", [])) : foo,
+    io.write(T, !IO),
+    io.nl(!IO).
+
+% vim: ft=mercury ts=8 sw=4 et wm=0 tw=0
Index: library/erlang_rtti_implementation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/erlang_rtti_implementation.m,v
retrieving revision 1.15
diff -u -r1.15 erlang_rtti_implementation.m
--- library/erlang_rtti_implementation.m	17 Aug 2007 02:08:38 -0000	1.15
+++ library/erlang_rtti_implementation.m	24 Aug 2007 07:54:53 -0000
@@ -556,11 +556,28 @@
 :- pred check_functor(T::in, erlang_atom::in, int::out) is semidet.
 :- pragma foreign_proc("Erlang", check_functor(Term::in, Atom::in, Size::out),
         [will_not_call_mercury, promise_pure, thread_safe], "
-    %io:format(""check_functor(~p, ~p)~n"", [Term, Atom]),
-    Functor = element(1, Term),
-    Size = size(Term),
-    %io:format(""check_functor(~p, ~p, ~p)~n"", [Term, Atom, Size]),
-    SUCCESS_INDICATOR = Functor =:= Atom
+    case Atom of
+        % This case must come before the next to handle existential types using
+        % the '[|]' constructor.  In that case the Erlang term will be a tuple
+        % and not a list.
+        _ when is_tuple(Term) ->
+            Functor = element(1, Term),
+            Size = size(Term),
+            SUCCESS_INDICATOR = Functor =:= Atom;
+
+        '[|]' ->
+            case Term of
+                [_ | _] ->
+                    SUCCESS_INDICATOR = true;
+                _ ->
+                    SUCCESS_INDICATOR = false
+            end,
+            Size = 3;
+
+        '[]' ->
+            SUCCESS_INDICATOR = Term =:= [],
+            Size = 1
+    end
 ").
 check_functor(_, _, 0) :-
     semidet_unimplemented("check_functor/3").
@@ -1090,11 +1107,18 @@
 "
     % TypeInfo_for_U to avoid compiler warning
 
-    %io:format(""get_subterm(~p, ~p, ~p, ~p)~n"",
-    %    [TypeInfo, Term, Index, ExtraArgs]),
-
     TypeInfo_for_T = TypeInfo,
-    Arg = element(Index + ExtraArgs, Term)
+    case Term of
+        % If there are any extra arguments then we would not use the list
+        % syntax.
+        [A | _] when Index =:= 1 ->
+            Arg = A;
+        [_ | B] when Index =:= 2 ->
+            Arg = B;
+
+        _ when is_tuple(Term) ->
+            Arg = element(Index + ExtraArgs, Term)
+    end
 ").
 
 :- func unsafe_cast(T) = U.
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list