[m-rev.] for review: fix an XXX: escape characters returned by deconstruct.functor/4
Julien Fischer
jfischer at opturion.com
Sat Jun 9 00:05:19 AEST 2018
For review by anyone.
--------------------------------
Fix an XXX: escape characters returned by deconstruct.functor/4.
runtime/mercury_ml_expand_body.h:
Fix an XXX: escape characters in functors.
library/rtti_implementation.m:
Do the same for the C# and Java backends.
tests/hard_coded/deconstruct_arg.{m,exp}:
Extend this test to cover the above.
tests/declarative_debugger/io_stream_test.exp2:
Update this expected output: one of the I/O actions contains
a newline character and previously the lack of a character escape
meant that it was split across two lines.
Julien.
diff --git a/library/rtti_implementation.m b/library/rtti_implementation.m
index 0564a27..9ea5046 100644
--- a/library/rtti_implementation.m
+++ b/library/rtti_implementation.m
@@ -2814,7 +2814,11 @@ deconstruct_2(Term, TypeInfo, TypeCtorInfo, TypeCtorRep, NonCanon,
;
TypeCtorRep = tcr_char,
det_dynamic_cast(Term, Char),
- Functor = string.from_char_list(['\'', Char, '\'']),
+ ( if escape_char_functor(Char, EscapedChar) then
+ Functor = EscapedChar
+ else
+ Functor = string.from_char_list(['\'', Char, '\''])
+ ),
Ordinal = -1,
Arity = 0,
Arguments = []
@@ -3010,6 +3014,18 @@ univ_named_arg(Term, NonCanon, Name, Argument) :-
MaybeArgument),
MaybeArgument = yes(Argument).
+:- pred escape_char_functor(character::in, string::out) is semidet.
+
+escape_char_functor('\\', "'\\\\'").
+escape_char_functor('\'', "'\\'").
+escape_char_functor('\a', "'\\a'").
+escape_char_functor('\b', "'\\b'").
+escape_char_functor('\r', "'\\r'").
+escape_char_functor('\f', "'\\f'").
+escape_char_functor('\t', "'\\t'").
+escape_char_functor('\n', "'\\n'").
+escape_char_functor('\v', "'\\v'").
+
:- pred univ_named_arg_2(T, type_info, type_ctor_info, type_ctor_rep,
noncanon_handling, string, maybe(univ)).
:- mode univ_named_arg_2(in, in, in, in, in(do_not_allow), in, out) is det.
diff --git a/runtime/mercury_ml_expand_body.h b/runtime/mercury_ml_expand_body.h
index 7a1dee2..70510fc 100644
--- a/runtime/mercury_ml_expand_body.h
+++ b/runtime/mercury_ml_expand_body.h
@@ -875,14 +875,28 @@ EXPAND_FUNCTION_NAME(MR_TypeInfo type_info, MR_Word *data_word_ptr,
case MR_TYPECTOR_REP_CHAR:
#ifdef EXPAND_FUNCTOR_FIELD
{
- // XXX Should escape characters correctly.
char buf[8];
MR_Word data_word;
- char *str;
+ const char *str_ptr;
+ char *str;
data_word = *data_word_ptr;
- sprintf(buf, "\'%c\'", (char) data_word);
- MR_make_aligned_string_copy_saved_hp(str, buf, NULL);
+ // XXX what should we do with other non-printable characters.
+ switch (data_word) {
+ case '\\': str_ptr = "'\\\\'"; break;
+ case '\'': str_ptr = "'\\''"; break;
+ case '\a': str_ptr = "'\\a'"; break;
+ case '\b': str_ptr = "'\\b'"; break;
+ case '\r': str_ptr = "'\\r'"; break;
+ case '\f': str_ptr = "'\\f'"; break;
+ case '\t': str_ptr = "'\\t'"; break;
+ case '\n': str_ptr = "'\\n'"; break;
+ case '\v': str_ptr = "'\\v'"; break;
+ default:
+ sprintf(buf, "\'%c\'", (char) data_word);
+ str_ptr = buf;
+ }
+ MR_make_aligned_string_copy_saved_hp(str, str_ptr, NULL);
expand_info->EXPAND_FUNCTOR_FIELD = str;
}
#endif // EXPAND_FUNCTOR_FIELD
diff --git a/tests/declarative_debugger/io_stream_test.exp2 b/tests/declarative_debugger/io_stream_test.exp2
index a5163ca..f07949b 100644
--- a/tests/declarative_debugger/io_stream_test.exp2
+++ b/tests/declarative_debugger/io_stream_test.exp2
@@ -26,8 +26,7 @@ test(stream(0, input, text, file("tabled_read_decl.data")), 1123, _, _)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '1', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '2', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '3', <<foreign(system_error, 0xXXXX)>>)
-read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '
-', <<foreign(system_error, 0xXXXX)>>)
+read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '\n', <<foreign(system_error, 0xXXXX)>>)
Valid? print 1-2
stream(0, input, text, file("tabled_read_decl.data"))
1123
@@ -40,8 +39,7 @@ test_2(stream(0, input, text, file("tabled_read_decl.data")), 1, 1123, _, _)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '1', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '2', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '3', <<foreign(system_error, 0xXXXX)>>)
-read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '
-', <<foreign(system_error, 0xXXXX)>>)
+read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '\n', <<foreign(system_error, 0xXXXX)>>)
Valid? yes
Found incorrect contour:
test_2(stream(0, input, text, file("tabled_read_decl.data")), 1, 1123, _, _)
@@ -49,15 +47,13 @@ test_2(stream(0, input, text, file("tabled_read_decl.data")), 1, 1123, _, _)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '1', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '2', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '3', <<foreign(system_error, 0xXXXX)>>)
-read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '
-', <<foreign(system_error, 0xXXXX)>>)
+read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '\n', <<foreign(system_error, 0xXXXX)>>)
test(stream(0, input, text, file("tabled_read_decl.data")), 1123, _, _)
4 tabled IO actions:
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '1', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '2', <<foreign(system_error, 0xXXXX)>>)
read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '3', <<foreign(system_error, 0xXXXX)>>)
-read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '
-', <<foreign(system_error, 0xXXXX)>>)
+read_char_code_2(<<foreign(stream, 0xXXXX)>>, ok, '\n', <<foreign(system_error, 0xXXXX)>>)
Is this a bug? yes
E3: C2 EXIT pred io_stream_test.test/4-0 (det)
mdb> c -n -S
diff --git a/tests/hard_coded/deconstruct_arg.exp b/tests/hard_coded/deconstruct_arg.exp
index 9a5af4e..bb7f081 100644
--- a/tests/hard_coded/deconstruct_arg.exp
+++ b/tests/hard_coded/deconstruct_arg.exp
@@ -124,6 +124,136 @@ deconstruct deconstruct: functor 'a' arity 0
deconstruct limited deconstruct 3 of a
functor 'a' arity 0 []
+deconstruct functor: '\a'/0
+deconstruct argument 0 of doesn't exist
+deconstruct argument 1 of doesn't exist
+deconstruct argument 2 of doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\a' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\a' arity 0 []
+
+deconstruct functor: '\b'/0
+deconstruct argument 0 of doesn't exist
+deconstruct argument 1 of doesn't exist
+deconstruct argument 2 of doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\b' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\b' arity 0 []
+
+deconstruct functor: '\r'/0
+deconstruct argument 0 of doesn't exist
+deconstruct argument 1 of doesn't exist
+deconstruct argument 2 of doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\r' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\r' arity 0 []
+
+deconstruct functor: '\f'/0
+deconstruct argument 0 of
doesn't exist
+deconstruct argument 1 of
doesn't exist
+deconstruct argument 2 of
doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\f' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\f' arity 0 []
+
+deconstruct functor: '\t'/0
+deconstruct argument 0 of doesn't exist
+deconstruct argument 1 of doesn't exist
+deconstruct argument 2 of doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\t' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\t' arity 0 []
+
+deconstruct functor: '\n'/0
+deconstruct argument 0 of
+ doesn't exist
+deconstruct argument 1 of
+ doesn't exist
+deconstruct argument 2 of
+ doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\n' arity 0
+[]
+deconstruct limited deconstruct 3 of
+
+functor '\n' arity 0 []
+
+deconstruct functor: '\v'/0
+deconstruct argument 0 of
doesn't exist
+deconstruct argument 1 of
doesn't exist
+deconstruct argument 2 of
doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\v' arity 0
+[]
+deconstruct limited deconstruct 3 of
+functor '\v' arity 0 []
+
+deconstruct functor: '\\'/0
+deconstruct argument 0 of \ doesn't exist
+deconstruct argument 1 of \ doesn't exist
+deconstruct argument 2 of \ doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\\' arity 0
+[]
+deconstruct limited deconstruct 3 of \
+functor '\\' arity 0 []
+
+deconstruct functor: '\''/0
+deconstruct argument 0 of ' doesn't exist
+deconstruct argument 1 of ' doesn't exist
+deconstruct argument 2 of ' doesn't exist
+deconstruct argument 'moo' doesn't exist
+deconstruct argument 'mooo!' doesn't exist
+deconstruct argument 'packed1' doesn't exist
+deconstruct argument 'packed2' doesn't exist
+deconstruct argument 'packed3' doesn't exist
+deconstruct deconstruct: functor '\'' arity 0
+[]
+deconstruct limited deconstruct 3 of '
+functor '\'' arity 0 []
+
deconstruct functor: 0.12345678901234566/0
deconstruct argument 0 of 0.12345678901234566 doesn't exist
deconstruct argument 1 of 0.12345678901234566 doesn't exist
@@ -348,7 +478,7 @@ deconstruct deconstruct: functor newline arity 0
deconstruct limited deconstruct 3 of '<<predicate>>'
functor newline arity 0 []
-deconstruct functor: lambda_deconstruct_arg_m_155/1
+deconstruct functor: lambda_deconstruct_arg_m_164/1
deconstruct argument 0 of '<<predicate>>' is [1, 2]
deconstruct argument 1 of '<<predicate>>' doesn't exist
deconstruct argument 2 of '<<predicate>>' doesn't exist
@@ -357,10 +487,10 @@ deconstruct argument 'mooo!' doesn't exist
deconstruct argument 'packed1' doesn't exist
deconstruct argument 'packed2' doesn't exist
deconstruct argument 'packed3' doesn't exist
-deconstruct deconstruct: functor lambda_deconstruct_arg_m_155 arity 1
+deconstruct deconstruct: functor lambda_deconstruct_arg_m_164 arity 1
[[1, 2]]
deconstruct limited deconstruct 3 of '<<predicate>>'
-functor lambda_deconstruct_arg_m_155 arity 1 [[1, 2]]
+functor lambda_deconstruct_arg_m_164 arity 1 [[1, 2]]
deconstruct functor: p/3
deconstruct argument 0 of '<<predicate>>' is 1
diff --git a/tests/hard_coded/deconstruct_arg.m b/tests/hard_coded/deconstruct_arg.m
index 286e66d..dcf08cc 100644
--- a/tests/hard_coded/deconstruct_arg.m
+++ b/tests/hard_coded/deconstruct_arg.m
@@ -118,6 +118,15 @@ main(!IO) :-
% test characters
test_all('a', !IO),
+ test_all('\a', !IO),
+ test_all('\b', !IO),
+ test_all('\r', !IO),
+ test_all('\f', !IO),
+ test_all('\t', !IO),
+ test_all('\n', !IO),
+ test_all('\v', !IO),
+ test_all('\\', !IO),
+ test_all('\'', !IO),
% test a float which requires 17 digits of precision
test_all(0.12345678901234566, !IO),
More information about the reviews
mailing list