[m-rev.] diff: Implement string.to_rev_char_list in Mercury.
Peter Wang
novalazy at gmail.com
Thu May 2 13:16:35 AEST 2019
library/string.m:
Replace string.to_rev_char_list foreign proc with an efficient
Mercury implementation.
Add a note about a similar change for string.to_char_list.
diff --git a/library/string.m b/library/string.m
index 8b21ec1b1..8f23b0d64 100644
--- a/library/string.m
+++ b/library/string.m
@@ -1565,6 +1565,10 @@ to_char_list(Str::uo, CharList::in) :-
CharList = unicode:characters_to_list(Str)
").
+ % It would be worth checking if this Mercury implementation (or another
+ % one) is as fast the foreign_proc implementations, the next time any
+ % changes are required.
+ %
do_to_char_list(Str, CharList) :-
foldr(list.cons, Str, [], CharList).
@@ -1582,29 +1586,19 @@ to_rev_char_list(Str::uo, CharList::in) :-
:- pred do_to_rev_char_list(string::in, list(char)::out) is det.
-:- pragma foreign_proc("C",
- do_to_rev_char_list(Str::in, CharList::out),
- [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
- does_not_affect_liveness, no_sharing],
-"{
- MR_Integer pos;
- int c;
+do_to_rev_char_list(Str, RevCharList) :-
+ do_to_rev_char_list_loop(Str, 0, [], RevCharList).
- CharList = MR_list_empty_msg(MR_ALLOC_ID);
- pos = 0;
- for (;;) {
- c = MR_utf8_get_next(Str, &pos);
- if (c <= 0) {
- break;
- }
- CharList = MR_char_list_cons_msg((MR_UnsignedChar) c, CharList,
- MR_ALLOC_ID);
- }
-}").
+:- pred do_to_rev_char_list_loop(string::in, int::in,
+ list(char)::in, list(char)::out) is det.
-do_to_rev_char_list(Str, RevCharList) :-
- do_to_char_list(Str, CharList),
- list.reverse(CharList, RevCharList).
+do_to_rev_char_list_loop(Str, Index0, !RevCharList) :-
+ ( if string.unsafe_index_next(Str, Index0, Index1, C) then
+ !:RevCharList = [C | !.RevCharList],
+ do_to_rev_char_list_loop(Str, Index1, !RevCharList)
+ else
+ true
+ ).
%---------------------%
--
2.21.0
More information about the reviews
mailing list