[m-dev.] Help required with Erlang: Address review comments
Paul Bone
paul at bone.id.au
Wed Sep 7 14:46:34 AEST 2016
After Julien's feedback on my latest contribution I've modified the io.m
code for opening files to export a Mercury enumeration to foreign code.
However there is no support for this for Erlang. However I should be able
to use the Mercury symbols directly in erlang, AIUI there is very little
name mangling. This doesn't seem to work and therefore I cannot get the
read_dir_regression test case working in the Erlang grade. If anyone can
solve this that'd be great.
----
Address review comments
library/io.m:
As above.
---
library/io.m | 150 ++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 91 insertions(+), 59 deletions(-)
diff --git a/library/io.m b/library/io.m
index d5c9c87..2ff51db 100644
--- a/library/io.m
+++ b/library/io.m
@@ -5088,78 +5088,96 @@ read_binary(Result, !IO) :-
open_input(FileName, Result, !IO) :-
do_open_text(FileName, "r", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(input_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, input, text, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't open input file: ", Msg, !IO),
Result = error(io_error(Msg))
).
open_output(FileName, Result, !IO) :-
do_open_text(FileName, "w", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(output_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, output, text, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't open output file: ", Msg, !IO),
Result = error(io_error(Msg))
).
open_append(FileName, Result, !IO) :-
do_open_text(FileName, "a", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(output_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, append, text, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't append to file: ", Msg, !IO),
Result = error(io_error(Msg))
).
open_binary_input(FileName, Result, !IO) :-
do_open_binary(FileName, "rb", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(binary_input_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, input, binary, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't open input file: ", Msg, !IO),
Result = error(io_error(Msg))
).
open_binary_output(FileName, Result, !IO) :-
do_open_binary(FileName, "wb", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(binary_output_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, output, binary, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't open output file: ", Msg, !IO),
Result = error(io_error(Msg))
).
open_binary_append(FileName, Result, !IO) :-
do_open_binary(FileName, "ab", Result0, OpenCount, NewStream, !IO),
- ( if Result0 = 0 then
+ (
+ Result0 = ok,
Result = ok(binary_output_stream(NewStream)),
insert_stream_info(NewStream,
stream(OpenCount, append, binary, file(FileName)), !IO)
- else if Result0 = -2 then
+ ;
+ Result0 = failed_isdir,
Result = error(io_error("can't open directory as file"))
- else
+ ;
+ Result0 = failed_general,
make_err_msg("can't append to file: ", Msg, !IO),
Result = error(io_error(Msg))
).
@@ -7191,9 +7209,9 @@ mercury_open(const char *filename, const char *openmode,
#if defined(MR_HAVE_FSTAT) && \
(defined(MR_HAVE_FILENO) || defined(fileno)) && defined(S_ISDIR)
/*
- ** AFAIK this is only useful on Linux and FreeBSD. So if we don't have
- ** fstat or fileno then fall back to just opening the file without this
- ** check.
+ ** If fileno or fstat arn't available it's okay to open the file without
+ ** this check. AFAIK if these arn't available then the OS probably won't
+ ** let us open a directory as a file anyway.
*/
if (0 != fstat(fileno(f), &stat_info)) {
fclose(f);
@@ -9623,30 +9641,42 @@ set_binary_output_stream(binary_output_stream(NewStream),
% Stream open/close predicates.
- % io.do_open_binary(File, Mode, ResultCode, StreamId, Stream, !IO):
- % io.do_open_text(File, Mode, ResultCode, StreamId, Stream, !IO):
+:- type open_result
+ ---> ok
+ ; failed_general
+
+ % The failed_isdir result is separate because some OSs (Linux and
+ % FreeBSD) will willingly open a directory, and FreeBSD will allow
+ % you to read from it. This could cause confusion so we use fstat
+ % to detect the problem.
+ %
+ ; failed_isdir.
+
+:- pragma foreign_export_enum("C", open_result/0,
+ [prefix("ML_OR_"), uppercase]).
+:- pragma foreign_export_enum("Java", open_result/0,
+ [prefix("ML_OR_"), uppercase]).
+:- pragma foreign_export_enum("C#", open_result/0,
+ [prefix("ML_OR_"), uppercase]).
+
+ % io.do_open_binary(File, Mode, Result, StreamId, Stream, !IO):
+ % io.do_open_text(File, Mode, Result, StreamId, Stream, !IO):
%
% Attempts to open a file in the specified mode.
- % The Mode is a string suitable for passing to fopen().
- % Result is
- % 0 -- success,
- % -1 -- general failure,
- % -2 -- failed because the file is a directory (C backends on some OSs)
+ % The Mode is a string suitable for pssing to fopen().
+ % Result describes the result of the operation.
% StreamId is a unique integer identifying the open.
- % Both StreamId and Stream are valid only if Result == 0.
- %
- % The -2 result is separate because some OSs (Linux and FreeBSD) will
- % willingly open a directory, and FreeBSD will allow you to read from it.
- % This could cause confusion so we use fstat to detect the problem.
+ % Both StreamId and Stream are valid only if Result = ok.
+ % make_err_msg should be called iff Result = failed_general.
%
-:- pred do_open_binary(string::in, string::in, int::out, int::out,
+:- pred do_open_binary(string::in, string::in, open_result::out, int::out,
stream::out, io::di, io::uo) is det.
-:- pred do_open_text(string::in, string::in, int::out, int::out,
+:- pred do_open_text(string::in, string::in, open_result::out, int::out,
stream::out, io::di, io::uo) is det.
:- pragma foreign_proc("C",
- do_open_text(FileName::in, Mode::in, ResultCode::out,
+ do_open_text(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
does_not_affect_liveness, no_sharing],
@@ -9655,16 +9685,17 @@ set_binary_output_stream(binary_output_stream(NewStream),
Stream = mercury_open(FileName, Mode, &is_dir, MR_ALLOC_ID);
if (Stream != NULL) {
- ResultCode = 0;
+ Result = ML_OR_OK;
StreamId = mercury_next_stream_id();
} else {
- ResultCode = (MR_TRUE == is_dir) ? -2 : -1;
+ Result = (MR_TRUE == is_dir) ?
+ ML_OR_FAILED_ISDIR : ML_OR_FAILED_GENERAL;
StreamId = -1;
}
").
:- pragma foreign_proc("C",
- do_open_binary(FileName::in, Mode::in, ResultCode::out,
+ do_open_binary(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
does_not_affect_liveness, no_sharing],
@@ -9673,16 +9704,17 @@ set_binary_output_stream(binary_output_stream(NewStream),
Stream = mercury_open(FileName, Mode, &is_dir, MR_ALLOC_ID);
if (Stream != NULL) {
- ResultCode = 0;
+ Result = ML_OR_OK;
StreamId = mercury_next_stream_id();
} else {
- ResultCode = (MR_TRUE == is_dir) ? -2 : -1;
+ Result = (MR_TRUE == is_dir) ?
+ ML_OR_FAILED_ISDIR : ML_OR_FAILED_GENERAL;
StreamId = -1;
}
").
:- pragma foreign_proc("C#",
- do_open_text(FileName::in, Mode::in, ResultCode::out,
+ do_open_text(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"
@@ -9690,16 +9722,16 @@ set_binary_output_stream(binary_output_stream(NewStream),
io.ML_default_line_ending);
Stream = mf;
if (mf != null) {
- ResultCode = 0;
+ Result = ML_OR_OK;
StreamId = mf.id;
} else {
- ResultCode = -1;
+ Result = ML_OR_FAILED_GENERAL;
StreamId = -1;
}
").
:- pragma foreign_proc("C#",
- do_open_binary(FileName::in, Mode::in, ResultCode::out,
+ do_open_binary(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"
@@ -9707,16 +9739,16 @@ set_binary_output_stream(binary_output_stream(NewStream),
io.ML_line_ending_kind.ML_raw_binary);
Stream = mf;
if (mf != null) {
- ResultCode = 0;
+ Result = ML_OR_OK;
StreamId = mf.id;
} else {
- ResultCode = -1;
+ Result = ML_OR_FAILED_GENERAL;
StreamId = -1;
}
").
:- pragma foreign_proc("Java",
- do_open_text(FileName::in, Mode::in, ResultCode::out,
+ do_open_text(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
may_not_duplicate],
@@ -9737,17 +9769,17 @@ set_binary_output_stream(binary_output_stream(NewStream),
throw new Error(""unreachable"");
}
StreamId = Stream.id;
- ResultCode = 0;
+ Result = ML_OR_OK;
} catch (java.lang.Exception e) {
io.MR_io_exception.set(e);
Stream = null;
StreamId = -1;
- ResultCode = -1;
+ Result = ML_OR_FAILED_GENERAL;
}
").
:- pragma foreign_proc("Java",
- do_open_binary(FileName::in, Mode::in, ResultCode::out,
+ do_open_binary(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
may_not_duplicate],
@@ -9772,17 +9804,17 @@ set_binary_output_stream(binary_output_stream(NewStream),
break;
}
StreamId = Stream.id;
- ResultCode = 0;
+ Result = ML_OR_OK;
} catch (java.lang.Exception e) {
io.MR_io_exception.set(e);
Stream = null;
StreamId = -1;
- ResultCode = -1;
+ Result = ML_OR_FAILED_GENERAL;
}
").
:- pragma foreign_proc("Erlang",
- do_open_text(FileName::in, Mode::in, ResultCode::out,
+ do_open_text(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"
@@ -9793,17 +9825,17 @@ set_binary_output_stream(binary_output_stream(NewStream),
case mercury__io:mercury_open_stream(FileNameStr, ModeStr) of
{ok, Stream} ->
{'ML_stream', StreamId, _Pid} = Stream,
- ResultCode = 0;
+ Result = ok;
{error, Reason} ->
put('MR_io_exception', Reason),
StreamId = -1,
Stream = null,
- ResultCode = -1
+ Result = failed_general
end
").
:- pragma foreign_proc("Erlang",
- do_open_binary(FileName::in, Mode::in, ResultCode::out,
+ do_open_binary(FileName::in, Mode::in, Result::out,
StreamId::out, Stream::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"
@@ -9814,12 +9846,12 @@ set_binary_output_stream(binary_output_stream(NewStream),
case mercury__io:mercury_open_stream(FileNameStr, ModeStr) of
{ok, Stream} ->
{'ML_stream', StreamId, _Pid} = Stream,
- ResultCode = 0;
+ Result = ok;
{error, Reason} ->
put('MR_io_exception', Reason),
StreamId = -1,
Stream = null,
- ResultCode = -1
+ Result = failed_general
end
").
--
2.7.4
More information about the developers
mailing list