[m-rev.] For review (needs committing): Cleanup samples/diff and samples/rot13
Jonathan Morgan
jonmmorgan at gmail.com
Mon Apr 24 15:52:46 AEST 2006
Estimated hours taken: 3
Branches: main
samples/diff/*.m:
samples/rot13/*.m:
Convert these modules to four-space indentation.
Use state variables for threading the I/O state.
Replace separate pred/mode declaration with predmode declarations.
Replace __ with . as the module qualifier.
Index: samples/diff/diff.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/diff.m,v
retrieving revision 1.10
diff -u -r1.10 diff.m
--- samples/diff/diff.m 15 Sep 1998 04:54:16 -0000 1.10
+++ samples/diff/diff.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1995-1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -15,7 +17,7 @@
:- interface.
:- import_module io.
-:- pred main(io__state :: di, io__state :: uo) is det.
+:- pred main(io.state :: di, io.state :: uo) is det.
%-----------------------------------------------------------------------------%
@@ -25,126 +27,123 @@
%-----------------------------------------------------------------------------%
- % main: top-level predicate.
-main -->
- io__command_line_arguments(Args0),
- { options__get_option_ops(OptionOps) },
- { getopt__process_options(OptionOps, Args0, Args, Result0) },
- postprocess_options(Result0, Result),
- ( { Result = yes(Msg) },
- usage_error(Msg)
- ; { Result = no },
- globals__io_get_output_style(OutputStyle),
- ( { OutputStyle = help_only } ->
- usage
- ; { OutputStyle = version_only } ->
- version
- ;
- main_2(Args)
- )
- ).
-
-%-----------------------------------------------------------------------------%
-
-:- pred usage_error(string :: in, io__state :: di, io__state :: uo) is det.
-usage_error(Msg) -->
- io__progname_base("diff", ProgName),
- io__stderr_stream(StdErr),
- io__write_strings(StdErr, [ProgName, ": ", Msg, "\n"]),
- io__set_exit_status(1),
- usage.
-
-:- pred usage_io_error(io__error, io__state, io__state).
-:- mode usage_io_error(in, di, uo) is det.
-usage_io_error(Error) -->
- { io__error_message(Error, Msg) },
- usage_error(Msg).
-
-:- pred usage(io__state :: di, io__state :: uo) is det.
-usage -->
- io__write_string("Usage: diff [options] from-file to-file\n\n"),
- options_help.
-
-:- pred version(io__state :: di, io__state :: uo) is det.
-version -->
- io__write_string("diff - Mercury diff version 0.4\n").
-
-%-----------------------------------------------------------------------------%
-
- % main_2 analyses the command-line arguments which are not
- % options and calls diff__do_diff.
-:- pred main_2(list(string), io__state, io__state).
-:- mode main_2(in, di, uo) is det.
-main_2([]) -->
- usage_error("missing operand").
-main_2([Fname1 | Rest]) -->
- ( { Rest = [Fname2 | _] },
- ( { Fname1 = Fname2 } ->
- % Not sure why anyone would want to diff two
- % files with the same name, but just in case...
- ( { Fname1 = "-" } ->
- file__read_input(Fname1, Contents1),
- { Contents1 = Contents2 }
- ;
- file__read_file(Fname1, Contents1),
- { Contents1 = Contents2 }
- )
- ;
- % If either file is "-", simply use standard input.
- % (Note: Both can't be "-" since that was dealt with
- % in the previous case.)
- ( { Fname1 = "-" } ->
- file__read_input(Fname1, Contents1),
- file__read_file(Fname2, Contents2)
- ; { Fname2 = "-" } ->
- file__read_file(Fname1, Contents1),
- file__read_input(Fname2, Contents2)
- ;
- % Otherwise read the files normally.
- file__read_file(Fname1, Contents1),
- file__read_file(Fname2, Contents2)
- )
- ),
- % Now do the diff.
- ( { Contents1 = ok(File1), Contents2 = ok(File2) } ->
- diff__do_diff(File1, File2)
- ; { Contents1 = error(Msg) } ->
- usage_io_error(Msg)
- ; { Contents2 = error(Msg) } ->
- usage_io_error(Msg)
- ;
- { error("main2") }
- )
- ; { Rest = [] },
- usage_error("missing operand")
- ).
-
-%-----------------------------------------------------------------------------%
-
- % diff__do_diff takes the files plus all the command
- % line options and determines what to do with them.
- %
- % At the moment, we're organised into four passes:
- %
- % - build_matches determines which lines from the
- % input files match (using the appropriate command-
- % line options).
- % - diff_by_myers takes the matches produced and
- % computes a diff between them.
- % - filter_diff analyses the diff, filtering out
- % any edits which the user said that they didn't
- % want to see (using the appropriate command-line
- % options).
- % - display_diff outputs the diff in whatever output
- % format the user chose.
- %
-:- pred diff__do_diff(file, file, io__state, io__state).
-:- mode diff__do_diff(in, in, di, uo) is det.
-diff__do_diff(File1, File2) -->
- build_matches(File1, File2, FileX, FileY),
- diff_by_myers(FileX, FileY, Diff0),
- filter_diff(Diff0, File1, File2, Diff),
- display_diff(File1, File2, Diff).
+ % main: top-level predicate.
+main(!IO) :-
+ io.command_line_arguments(Args0, !IO),
+ options.get_option_ops(OptionOps),
+ getopt.process_options(OptionOps, Args0, Args, Result0),
+ postprocess_options(Result0, Result, !IO),
+ ( Result = yes(Msg),
+ usage_error(Msg, !IO)
+ ; Result = no,
+ globals.io_get_output_style(OutputStyle, !IO),
+ ( OutputStyle = help_only ->
+ usage(!IO)
+ ; OutputStyle = version_only ->
+ version(!IO)
+ ;
+ main_2(Args, !IO)
+ )
+ ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred usage_error(string :: in, io.state :: di, io.state :: uo) is det.
+usage_error(Msg, !IO) :-
+ io.progname_base("diff", ProgName, !IO),
+ io.stderr_stream(StdErr, !IO),
+ io.write_strings(StdErr, [ProgName, ": ", Msg, "\n"], !IO),
+ io.set_exit_status(1, !IO),
+ usage(!IO).
+
+:- pred usage_io_error(io.error::in, io.state::di, io.state::uo) is det.
+usage_io_error(Error, !IO) :-
+ io.error_message(Error, Msg),
+ usage_error(Msg, !IO).
+
+:- pred usage(io.state :: di, io.state :: uo) is det.
+usage(!IO) :-
+ io.write_string("Usage: diff [options] from-file to-file\n\n", !IO),
+ options_help(!IO).
+
+:- pred version(io.state :: di, io.state :: uo) is det.
+version(!IO) :-
+ io.write_string("diff - Mercury diff version 0.4\n", !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % main_2 analyses the command-line arguments which are not
+ % options and calls diff.do_diff.
+:- pred main_2(list(string)::in, io.state::di, io.state::uo) is det.
+main_2([], !IO) :-
+ usage_error("missing operand", !IO).
+main_2([Fname1 | Rest], !IO) :-
+ ( Rest = [Fname2 | _],
+ ( Fname1 = Fname2 ->
+ % Not sure why anyone would want to diff two
+ % files with the same name, but just in case...
+ ( Fname1 = "-" ->
+ file.read_input(Fname1, Contents1, !IO),
+ Contents1 = Contents2
+ ;
+ file.read_file(Fname1, Contents1, !IO),
+ Contents1 = Contents2
+ )
+ ;
+ % If either file is "-", simply use standard input.
+ % (Note: Both can't be "-" since that was dealt with
+ % in the previous case.)
+ ( Fname1 = "-" ->
+ file.read_input(Fname1, Contents1, !IO),
+ file.read_file(Fname2, Contents2, !IO)
+ ; Fname2 = "-" ->
+ file.read_file(Fname1, Contents1, !IO),
+ file.read_input(Fname2, Contents2, !IO)
+ ;
+ % Otherwise read the files normally.
+ file.read_file(Fname1, Contents1, !IO),
+ file.read_file(Fname2, Contents2, !IO)
+ )
+ ),
+ % Now do the diff.
+ ( Contents1 = ok(File1), Contents2 = ok(File2) ->
+ diff.do_diff(File1, File2, !IO)
+ ; Contents1 = error(Msg) ->
+ usage_io_error(Msg, !IO)
+ ; Contents2 = error(Msg) ->
+ usage_io_error(Msg, !IO)
+ ;
+ error("main2")
+ )
+ ; Rest = [],
+ usage_error("missing operand", !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+
+ % diff.do_diff takes the files plus all the command
+ % line options and determines what to do with them.
+ %
+ % At the moment, we're organised into four passes:
+ %
+ % - build_matches determines which lines from the
+ % input files match (using the appropriate command-
+ % line options).
+ % - diff_by_myers takes the matches produced and
+ % computes a diff between them.
+ % - filter_diff analyses the diff, filtering out
+ % any edits which the user said that they didn't
+ % want to see (using the appropriate command-line
+ % options).
+ % - display_diff outputs the diff in whatever output
+ % format the user chose.
+ %
+:- pred diff.do_diff(file::in, file::in, io.state::di, io.state::uo) is det.
+diff.do_diff(File1, File2, !IO) :-
+ build_matches(File1, File2, FileX, FileY, !IO),
+ diff_by_myers(FileX, FileY, Diff0, !IO),
+ filter_diff(Diff0, File1, File2, Diff, !IO),
+ display_diff(File1, File2, Diff, !IO).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/diff_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/diff_out.m,v
retrieving revision 1.2
diff -u -r1.2 diff_out.m
--- samples/diff/diff_out.m 15 Sep 1998 04:54:22 -0000 1.2
+++ samples/diff/diff_out.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1995-1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -20,44 +22,39 @@
%-----------------------------------------------------------------------------%
-:- type diff_out__output_style
- ---> normal
- ; help_only
- ; version_only
- ; context(int)
- ; unified(int)
- ; ed
- ; forward_ed
- ; rcs
- ; ifdef(string)
- ; brief
- ; side_by_side
- ; cvs_merge_conflict.
-
- % The default output style.
-:- pred diff_out__default_output_style(diff_out__output_style).
-:- mode diff_out__default_output_style(out) is det.
-
- % Succeeds if, for this output style, an absence of differences
- % means that no output should be generated.
-:- pred diff_out__no_diff_implies_no_output(diff_out__output_style).
-:- mode diff_out__no_diff_implies_no_output(in) is semidet.
-
- % Succeeds if the user only wants to know about the presence
- % of any differences, not what they actually are.
-:- pred diff_out__full_diff_not_required(diff_out__output_style).
-:- mode diff_out__full_diff_not_required(in) is semidet.
-
- % Succeeds if the output style is "robust", that is, the
- % absence of a newline at the end of the file actually
- % matters.
-:- pred diff_out__robust(diff_out__output_style).
-:- mode diff_out__robust(in) is semidet.
-
- % display_diff takes a diff and displays it
- % in the user's specified output format.
-:- pred display_diff(file, file, diff, io__state, io__state).
-:- mode display_diff(in, in, in, di, uo) is det.
+:- type diff_out.output_style
+ ---> normal
+ ; help_only
+ ; version_only
+ ; context(int)
+ ; unified(int)
+ ; ed
+ ; forward_ed
+ ; rcs
+ ; ifdef(string)
+ ; brief
+ ; side_by_side
+ ; cvs_merge_conflict.
+
+ % The default output style.
+:- pred diff_out.default_output_style(diff_out.output_style::out) is det.
+
+ % Succeeds if, for this output style, an absence of differences
+ % means that no output should be generated.
+:- pred diff_out.no_diff_implies_no_output(output_style::in) is semidet.
+
+ % Succeeds if the user only wants to know about the presence
+ % of any differences, not what they actually are.
+:- pred diff_out.full_diff_not_required(diff_out.output_style::in) is semidet.
+
+ % Succeeds if the output style is "robust", that is, the
+ % absence of a newline at the end of the file actually
+ % matters.
+:- pred diff_out.robust(diff_out.output_style::in) is semidet.
+
+ % display_diff takes a diff and displays it
+ % in the user's specified output format.
+:- pred display_diff(file::in, file::in, diff::in, io::di, io::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -66,968 +63,956 @@
:- import_module globals, options.
:- import_module require, std_util, int, list, char, string, bool.
-diff_out__default_output_style(normal).
+diff_out.default_output_style(normal).
%-----------------------------------------------------------------------------%
-diff_out__no_diff_implies_no_output(normal).
-diff_out__no_diff_implies_no_output(context(_)).
-diff_out__no_diff_implies_no_output(unified(_)).
-diff_out__no_diff_implies_no_output(ed).
-diff_out__no_diff_implies_no_output(forward_ed).
-diff_out__no_diff_implies_no_output(rcs).
-diff_out__no_diff_implies_no_output(brief).
-
-%-----------------------------------------------------------------------------%
-
-diff_out__full_diff_not_required(brief).
-
-%-----------------------------------------------------------------------------%
-
-diff_out__robust(normal).
-diff_out__robust(context(_)).
-diff_out__robust(unified(_)).
-diff_out__robust(rcs).
-diff_out__robust(ifdef(_)).
-diff_out__robust(side_by_side).
-diff_out__robust(cvs_merge_conflict).
-
-%-----------------------------------------------------------------------------%
-
- % diff_out__show_file shows the segment of the file
- % from Low to High, with each line preceeded by
- % the Prefix characher and a space. The diff(1)
- % format specifies that the lines effected in the
- % first file should be flagged by '<' and the
- % lines effected in the second file should be
- % flagged by '>'.
- %
-:- pred diff_out__show_file(file, string, pos, pos, io__state, io__state).
-:- mode diff_out__show_file(in, in, in, in, di, uo) is det.
-
-diff_out__show_file(File, Prefix, Low, High) -->
- globals__io_lookup_bool_option(expand_tabs, ExpandTabs),
- diff_out__show_file_2(ExpandTabs, File, Prefix, Low, High).
-
- % NOTE: GCC 2.7.2 under Digital Unix 3.2 doesn't compile
- % this predicate correctly with optimisation turned on.
-:- pred diff_out__show_file_2(bool, file, string, pos, pos,
- io__state, io__state).
-:- mode diff_out__show_file_2(in, in, in, in, in, di, uo) is det.
-
-diff_out__show_file_2(ExpandTabs, File, Prefix, Low, High) -->
- ( { Low < High } ->
- ( { file__get_line(File, Low, Line) } ->
- io__write_string(Prefix),
- ( { ExpandTabs = yes },
- { string__to_char_list(Line, LineList) },
- diff_out__expand_tabs(LineList, 0)
- ; { ExpandTabs = no },
- io__write_string(Line)
- ),
- diff_out__show_file_2(ExpandTabs, File, Prefix,
- Low + 1, High)
- ;
- { error("diff_out_show_file: file ended prematurely") }
- )
- ;
- []
- ).
-
-:- pred diff_out__expand_tabs(list(char), int, io__state, io__state).
-:- mode diff_out__expand_tabs(in, in, di, uo) is det.
-
-diff_out__expand_tabs([], _) --> [].
-diff_out__expand_tabs([C | Cs], Pos) -->
- ( { C = '\t' } ->
- { Spaces = tab_width - (Pos rem tab_width) },
- put_spaces(Spaces, Pos, NewPos),
- diff_out__expand_tabs(Cs, NewPos)
- ;
- io__write_char(C),
- diff_out__expand_tabs(Cs, Pos + 1)
- ).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-
- % display_diff: Determine which output style to use, then call
- % the predicate to display that output.
- %
- % Some of these options (notably the ones which require no
- % output) should have been handled already by the time we
- % reach here. In those cases, we just call error/1.
-display_diff(File1, File2, Diff) -->
- globals__io_get_output_style(OutputStyle),
- (
- { Diff = [],
- diff_out__no_diff_implies_no_output(OutputStyle)
- }
- ->
- []
- ;
- display_diff_2(OutputStyle, File1, File2, Diff)
- ).
-
-
-:- pred display_diff_2(diff_out__output_style, file, file, diff,
- io__state, io__state).
-:- mode display_diff_2(in, in, in, in, di, uo) is det.
-
-display_diff_2(normal, File1, File2, Diff) -->
- display_diff_normal(File1, File2, Diff).
-
-display_diff_2(help_only, _File1, _File2, _Diff) -->
- { error("display_diff: help_only") }.
-
-display_diff_2(version_only, _File1, _File2, _Diff) -->
- { error("display_diff: version_only") }.
-
-display_diff_2(context(Context), File1, File2, Diff) -->
- display_context_diff(Context, File1, File2, Diff).
-
-display_diff_2(unified(Context), File1, File2, Diff) -->
- display_unified_diff(Context, File1, File2, Diff).
-
-display_diff_2(ed, File1, File2, Diff) -->
- display_diff_ed(File1, File2, Diff).
-
-display_diff_2(forward_ed, File1, File2, Diff) -->
- display_diff_forward_ed(File1, File2, Diff).
-
-display_diff_2(rcs, File1, File2, Diff) -->
- display_diff_rcs(File1, File2, Diff).
-
-display_diff_2(ifdef(Sym), File1, File2, Diff) -->
- display_diff_ifdef(Sym, File1, File2, Diff).
-
-display_diff_2(brief, File1, File2, _Diff) -->
- % XXX For this output style, we really don't need to
- % perform a complete diff. This should be handled
- % higher up for efficiency.
- { file__get_file_name(File1, FileName1) },
- { file__get_file_name(File2, FileName2) },
- io__write_strings(["Files ", FileName1, " and ",
- FileName2, " differ\n"]).
-
-display_diff_2(side_by_side, File1, File2, Diff) -->
- display_diff_side_by_side(File1, File2, Diff).
-
-display_diff_2(cvs_merge_conflict, File1, File2, Diff) -->
- display_diff_cvs_merge_conflict(File1, File2, Diff).
-
-%-----------------------------------------------------------------------------%
-
- % display_diff_normal takes a diff and displays it
- % in the standard diff(1) output format.
-:- pred display_diff_normal(file, file, diff, io__state, io__state).
-:- mode display_diff_normal(in, in, in, di, uo) is det.
-
-display_diff_normal(File1, File2, Diff) -->
- globals__io_lookup_bool_option(initial_tab, InitialTab),
- { InitialTab = no,
- FromStr = "< ",
- ToStr = "> "
- ; InitialTab = yes,
- FromStr = "<\t",
- ToStr = ">\t"
- },
- display_diff_normal_2(File1, File2, Diff, FromStr, ToStr).
-
- % display_diff_normal takes a diff and displays it
- % in the standard diff(1) output format.
-:- pred display_diff_normal_2(file, file, diff, string, string,
- io__state, io__state).
-:- mode display_diff_normal_2(in, in, in, in, in, di, uo) is det.
-
-display_diff_normal_2(_, _, [], _, _) --> [].
-display_diff_normal_2(File1, File2, [SingDiff | Diff], FromStr, ToStr) -->
- ( { SingDiff = add(X, Y1 - Y2) },
- diff_out__write_command(X - X, 'a', Y1 - Y2),
- diff_out__show_file(File2, ToStr, Y1, Y2)
- ; { SingDiff = delete(X1 - X2, Y) },
- diff_out__write_command(X1 - X2, 'd', Y - Y),
- diff_out__show_file(File1, FromStr, X1, X2)
- ; { SingDiff = change(X1 - X2, Y1 - Y2) },
- diff_out__write_command(X1 - X2, 'c', Y1 - Y2),
- diff_out__show_file(File1, FromStr, X1, X2),
- io__write_string("---\n"),
- diff_out__show_file(File2, ToStr, Y1, Y2)
- ),
- display_diff_normal_2(File1, File2, Diff, FromStr, ToStr).
-
-
- % diff_out__write_command displays a diff(1) command.
- % Like ed(1), a pair of numbers which are identical
- % are abbreviated by a single number.
- % MK: Assumption X=<X2
- % AJB: And, similarly, Y=<Y2. This is actually an
- % invariant of the segment type. See difftype.m.
-:- pred diff_out__write_command(segment, char, segment, io__state, io__state).
-:- mode diff_out__write_command(in, in, in, di, uo) is det.
-
-diff_out__write_command(X - X2, C, Y - Y2) -->
- { X1 is X + 1 }, % Convert from pos to line number
- ( { X1 >= X2 } ->
- % either empty or singleton segment
- io__write_int(X2)
- ;
- io__write_int(X1),
- io__write_char(','),
- io__write_int(X2)
- ),
- io__write_char(C),
- { Y1 is Y + 1 }, % Convert from pos to line number
- ( { Y1 >= Y2 } ->
- % either empty or singleton segment
- io__write_int(Y2)
- ;
- io__write_int(Y1),
- io__write_char(','),
- io__write_int(Y2)
- ),
- io__write_char('\n').
-
-%-----------------------------------------------------------------------------%
-
- % display_diff_rcs takes a diff and displays it
- % in the RCS difference format.
-:- pred display_diff_rcs(file, file, diff, io__state, io__state).
-:- mode display_diff_rcs(in, in, in, di, uo) is det.
-
-display_diff_rcs(_File1, _File2, []) --> [].
-display_diff_rcs(File1, File2, [Cmd | Diff]) -->
- ( { Cmd = add(X, Y1 - Y2) },
- diff_out__write_command_rcs('a', X, Y2-Y1),
- diff_out__show_file(File2, "", Y1, Y2)
- ; { Cmd = delete(X1 - X2, _Y) },
- diff_out__write_command_rcs('d', X1, X2-X1)
- ; { Cmd = change(X1 - X2, Y1 - Y2) },
- diff_out__write_command_rcs('d', X1, X2-X1),
- diff_out__write_command_rcs('a', X1, Y2-Y1),
- diff_out__show_file(File2, "", Y1, Y2)
- ),
- display_diff_rcs(File1, File2, Diff).
-
-
- % diff_out__write_command_rcs displays a diff command in
- % the RCS ,v format.
-:- pred diff_out__write_command_rcs(char, int, int, io__state, io__state).
-:- mode diff_out__write_command_rcs(in, in, in, di, uo) is det.
-
-diff_out__write_command_rcs(C, X, Y) -->
- io__write_char(C),
- io__write_int(X + 1), % Convert from pos to line number
- io__write_char(' '),
- io__write_int(Y),
- io__write_char('\n').
-
-%-----------------------------------------------------------------------------%
-
- % display_diff_ed takes a diff and displays it
- % in ed(1) format, but with all diffs backward.
-:- pred display_diff_ed(file, file, diff, io__state, io__state).
-:- mode display_diff_ed(in, in, in, di, uo) is det.
-
-display_diff_ed(_File1, _File2, []) --> [].
-display_diff_ed(File1, File2, [Cmd | Diff]) -->
- display_diff_ed(File1, File2, Diff),
- ( { Cmd = add(X, Y1 - Y2) },
- diff_out__write_command_ed(X - X, 'a'),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_string(".\n")
- ; { Cmd = delete(X, _Y) },
- diff_out__write_command_ed(X, 'd')
- ; { Cmd = change(X, Y1 - Y2) },
- diff_out__write_command_ed(X, 'c'),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_string(".\n")
- ).
-
-
- % diff_out__write_command_ed displays an ed(1) command.
-:- pred diff_out__write_command_ed(segment, char, io__state, io__state).
-:- mode diff_out__write_command_ed(in, in, di, uo) is det.
-
-diff_out__write_command_ed(X - X2, C) -->
- { X1 is X + 1 }, % Convert from pos to line number
- ( { X1 >= X2 } ->
- % either empty or singleton segment
- io__write_int(X2)
- ;
- io__write_int(X1),
- io__write_char(','),
- io__write_int(X2)
- ),
- io__write_char(C),
- io__write_char('\n').
-
-%-----------------------------------------------------------------------------%
-
- % display_diff_forward_ed takes a diff and displays it
- % in ed(1) format, but with all diff_out forward. This
- % is actually useless for feeding to ed(1), but nicer
- % to read.
-:- pred display_diff_forward_ed(file, file, diff, io__state, io__state).
-:- mode display_diff_forward_ed(in, in, in, di, uo) is det.
-
-display_diff_forward_ed(_File1, _File2, []) --> { true }.
-display_diff_forward_ed(File1, File2, [Cmd | Diff]) -->
- ( { Cmd = add(X, Y1 - Y2) },
- diff_out__write_command_forward_ed(X - X, 'a'),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_string(".\n")
- ; { Cmd = delete(X, _Y) },
- diff_out__write_command_forward_ed(X, 'd')
- ; { Cmd = change(X, Y1 - Y2) },
- diff_out__write_command_forward_ed(X, 'c'),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_string(".\n")
- ),
- display_diff_forward_ed(File1, File2, Diff).
-
- % diff_out__write_command_forward_ed displays a forward ed(1)
- % command. The difference between this and write_command_ed is
- % that the command char comes first here. Who comes up with
- % these dumb formats anyway?
-:- pred diff_out__write_command_forward_ed(segment, char, io__state,
io__state).
-:- mode diff_out__write_command_forward_ed(in, in, di, uo) is det.
-diff_out__write_command_forward_ed(X - X2, C) -->
- io__write_char(C),
- { X1 is X + 1 }, % Convert from pos to line number
- ( { X1 >= X2 } ->
- % either empty or singleton segment
- io__write_int(X2)
- ;
- io__write_int(X1),
- io__write_char(' '),
- io__write_int(X2)
- ),
- io__write_char('\n').
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
- % display_diff_ifdef writes out the files in a unified diff,
- % using #ifdefs around each edit.
- %
- % TO DO: GNU diff makes this output style much more
- % configurable. We should too.
-:- pred display_diff_ifdef(string, file, file, diff, io__state, io__state).
-:- mode display_diff_ifdef(in, in, in, in, di, uo) is det.
-
-display_diff_ifdef(Sym, File1, File2, Diff) -->
- display_diff_ifdef_2(0, Sym, File1, File2, Diff).
-
- % Argument 1 (prev) is the last pos displayed before
- % the current edit (or end of edits, in the base case).
- % This is important for when we have to display the
- % "non-diffed" text between edits.
-:- pred display_diff_ifdef_2(int, string, file, file, diff,
- io__state, io__state).
-:- mode display_diff_ifdef_2(in, in, in, in, in, di, uo) is det.
-
-display_diff_ifdef_2(Prev, _Sym, File1, _File2, []) -->
- { file__get_numlines(File1, SegEnd) },
- diff_out__show_file(File1, "", Prev, SegEnd).
-display_diff_ifdef_2(Prev, Sym, File1, File2, [Edit | Diff]) -->
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- diff_out__show_file(File1, "", Prev, StartOfEdit),
- ( { Edit = add(X, Y1 - Y2) },
- io__write_strings(["#ifdef ", Sym, "\n"]),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_strings(["#endif /* ", Sym, " */\n"]),
- { Next = X }
- ; { Edit = delete(X1 - X2, _) },
- io__write_strings(["#ifndef ", Sym, "\n"]),
- diff_out__show_file(File1, "", X1, X2),
- io__write_strings(["#endif /* not ", Sym, " */\n"]),
- { Next = X2 }
- ; { Edit = change(X1 - X2, Y1 - Y2) },
- io__write_strings(["#ifndef ", Sym, "\n"]),
- diff_out__show_file(File1, "", X1, X2),
- io__write_strings(["#else /* ", Sym, " */\n"]),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_strings(["#endif /* ", Sym, " */\n"]),
- { Next = X2 }
- ),
- display_diff_ifdef_2(Next, Sym, File1, File2, Diff).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
- % display_diff_cvs_merge_conflict writes out the files in a
- % unified diff, using CVS merge conflict marks around each edit.
- %
-:- pred display_diff_cvs_merge_conflict(file, file, diff, io__state,
io__state).
-:- mode display_diff_cvs_merge_conflict(in, in, in, di, uo) is det.
-
-display_diff_cvs_merge_conflict(File1, File2, Diff) -->
- display_diff_cvs_merge_conflict_2(0, File1, File2, Diff).
-
- % Argument 1 (prev) is the last pos displayed before
- % the current edit (or end of edits, in the base case).
- % This is important for when we have to display the
- % "non-diffed" text between edits.
-:- pred display_diff_cvs_merge_conflict_2(int, file, file, diff,
- io__state, io__state).
-:- mode display_diff_cvs_merge_conflict_2(in, in, in, in, di, uo) is det.
-
-display_diff_cvs_merge_conflict_2(Prev, File1, _File2, []) -->
- { file__get_numlines(File1, SegEnd) },
- diff_out__show_file(File1, "", Prev, SegEnd).
-display_diff_cvs_merge_conflict_2(Prev, File1, File2, [Edit | Diff]) -->
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- diff_out__show_file(File1, "", Prev, StartOfEdit),
- { file__get_file_name(File1, FileName1) },
- { file__get_file_name(File2, FileName2) },
- ( { Edit = add(X, Y1 - Y2) },
- io__write_strings(["<<<<<<< ", FileName1, "\n"]),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_string("=======\n"),
- io__write_strings([">>>>>>> ", FileName2, "\n"]),
- { Next = X }
- ; { Edit = delete(X1 - X2, _) },
- io__write_strings(["<<<<<<< ", FileName1, "\n"]),
- io__write_string("=======\n"),
- diff_out__show_file(File1, "", X1, X2),
- io__write_strings([">>>>>>> ", FileName2, "\n"]),
- { Next = X2 }
- ; { Edit = change(X1 - X2, Y1 - Y2) },
- io__write_strings(["<<<<<<< ", FileName1, "\n"]),
- diff_out__show_file(File1, "", X1, X2),
- io__write_string("=======\n"),
- diff_out__show_file(File2, "", Y1, Y2),
- io__write_strings([">>>>>>> ", FileName2, "\n"]),
- { Next = X2 }
- ),
- display_diff_cvs_merge_conflict_2(Next, File1, File2, Diff).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
- % Types for context/unified diffs.
-
- % A context diff is a bit more complicated than a "standard"
- % diff, because it requires the display of some parts of the
- % files which are not actually part of the diff, but not all
- % of it.
- %
- % Because context and unified diffs both require the same
- % kind of information, we factor out the code to turn a
- % normal diff into a context diff.
+diff_out.no_diff_implies_no_output(normal).
+diff_out.no_diff_implies_no_output(context(_)).
+diff_out.no_diff_implies_no_output(unified(_)).
+diff_out.no_diff_implies_no_output(ed).
+diff_out.no_diff_implies_no_output(forward_ed).
+diff_out.no_diff_implies_no_output(rcs).
+diff_out.no_diff_implies_no_output(brief).
+
+%-----------------------------------------------------------------------------%
+
+diff_out.full_diff_not_required(brief).
+
+%-----------------------------------------------------------------------------%
+
+diff_out.robust(normal).
+diff_out.robust(context(_)).
+diff_out.robust(unified(_)).
+diff_out.robust(rcs).
+diff_out.robust(ifdef(_)).
+diff_out.robust(side_by_side).
+diff_out.robust(cvs_merge_conflict).
+
+%-----------------------------------------------------------------------------%
+
+ % diff_out.show_file shows the segment of the file
+ % from Low to High, with each line preceeded by
+ % the Prefix characher and a space. The diff(1)
+ % format specifies that the lines effected in the
+ % first file should be flagged by '<' and the
+ % lines effected in the second file should be
+ % flagged by '>'.
+ %
+:- pred diff_out.show_file(file::in, string::in, pos::in, pos::in,
+ io.state::di, io.state::uo) is det.
+
+diff_out.show_file(File, Prefix, Low, High, !IO) :-
+ globals.io_lookup_bool_option(expand_tabs, ExpandTabs, !IO),
+ diff_out.show_file_2(ExpandTabs, File, Prefix, Low, High, !IO).
+
+ % NOTE: GCC 2.7.2 under Digital Unix 3.2 doesn't compile
+ % this predicate correctly with optimisation turned on.
+:- pred diff_out.show_file_2(bool::in, file::in, string::in, pos::in, pos::in,
+ io.state::di, io.state::uo) is det.
+
+diff_out.show_file_2(ExpandTabs, File, Prefix, Low, High, !IO) :-
+ ( Low < High ->
+ ( file.get_line(File, Low, Line) ->
+ io.write_string(Prefix, !IO),
+ ( ExpandTabs = yes,
+ string.to_char_list(Line, LineList),
+ diff_out.expand_tabs(LineList, 0, !IO)
+ ; ExpandTabs = no,
+ io.write_string(Line, !IO)
+ ),
+ diff_out.show_file_2(ExpandTabs, File, Prefix,
+ Low + 1, High, !IO)
+ ;
+ error("diff_out_show_file: file ended prematurely")
+ )
+ ;
+ true
+ ).
+
+:- pred diff_out.expand_tabs(list(char)::in, int::in, io.state::di,
+ io.state::uo) is det.
+
+diff_out.expand_tabs([], _, !IO).
+diff_out.expand_tabs([C | Cs], Pos, !IO) :-
+ ( C = '\t' ->
+ Spaces = tab_width - (Pos rem tab_width),
+ put_spaces(Spaces, Pos, NewPos, !IO),
+ diff_out.expand_tabs(Cs, NewPos, !IO)
+ ;
+ io.write_char(C, !IO),
+ diff_out.expand_tabs(Cs, Pos + 1, !IO)
+ ).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+
+ % display_diff: Determine which output style to use, then call
+ % the predicate to display that output.
+ %
+ % Some of these options (notably the ones which require no
+ % output) should have been handled already by the time we
+ % reach here. In those cases, we just call error/1.
+display_diff(File1, File2, Diff, !IO) :-
+ globals.io_get_output_style(OutputStyle, !IO),
+ (
+ Diff = [],
+ diff_out.no_diff_implies_no_output(OutputStyle)
+ ->
+ true
+ ;
+ display_diff_2(OutputStyle, File1, File2, Diff, !IO)
+ ).
+
+
+:- pred display_diff_2(diff_out.output_style::in, file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_2(normal, File1, File2, Diff, !IO) :-
+ display_diff_normal(File1, File2, Diff, !IO).
+
+display_diff_2(help_only, _File1, _File2, _Diff, !IO) :-
+ error("display_diff: help_only").
+
+display_diff_2(version_only, _File1, _File2, _Diff, !IO) :-
+ error("display_diff: version_only").
+
+display_diff_2(context(Context), File1, File2, Diff, !IO) :-
+ display_context_diff(Context, File1, File2, Diff, !IO).
+
+display_diff_2(unified(Context), File1, File2, Diff, !IO) :-
+ display_unified_diff(Context, File1, File2, Diff, !IO).
+
+display_diff_2(ed, File1, File2, Diff, !IO) :-
+ display_diff_ed(File1, File2, Diff, !IO).
+
+display_diff_2(forward_ed, File1, File2, Diff, !IO) :-
+ display_diff_forward_ed(File1, File2, Diff, !IO).
+
+display_diff_2(rcs, File1, File2, Diff, !IO) :-
+ display_diff_rcs(File1, File2, Diff, !IO).
+
+display_diff_2(ifdef(Sym), File1, File2, Diff, !IO) :-
+ display_diff_ifdef(Sym, File1, File2, Diff, !IO).
+
+display_diff_2(brief, File1, File2, _Diff, !IO) :-
+ % XXX For this output style, we really don't need to
+ % perform a complete diff. This should be handled
+ % higher up for efficiency.
+ file.get_file_name(File1, FileName1),
+ file.get_file_name(File2, FileName2),
+ io.write_strings(["Files ", FileName1, " and ",
+ FileName2, " differ\n"], !IO).
+
+display_diff_2(side_by_side, File1, File2, Diff, !IO) :-
+ display_diff_side_by_side(File1, File2, Diff, !IO).
+
+display_diff_2(cvs_merge_conflict, File1, File2, Diff, !IO) :-
+ display_diff_cvs_merge_conflict(File1, File2, Diff, !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % display_diff_normal takes a diff and displays it
+ % in the standard diff(1) output format.
+:- pred display_diff_normal(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_normal(File1, File2, Diff, !IO) :-
+ globals.io_lookup_bool_option(initial_tab, InitialTab, !IO),
+ ( InitialTab = no,
+ FromStr = "< ",
+ ToStr = "> "
+ ; InitialTab = yes,
+ FromStr = "<\t",
+ ToStr = ">\t"
+ ),
+ display_diff_normal_2(File1, File2, Diff, FromStr, ToStr, !IO).
+
+ % display_diff_normal takes a diff and displays it
+ % in the standard diff(1) output format.
+:- pred display_diff_normal_2(file::in, file::in, diff::in, string::in,
+ string::in, io.state::di, io.state::uo) is det.
+
+display_diff_normal_2(_, _, [], _, _, !IO).
+display_diff_normal_2(File1, File2, [SingDiff | Diff], FromStr, ToStr, !IO) :-
+ ( SingDiff = add(X, Y1 - Y2),
+ diff_out.write_command(X - X, 'a', Y1 - Y2, !IO),
+ diff_out.show_file(File2, ToStr, Y1, Y2, !IO)
+ ; SingDiff = delete(X1 - X2, Y),
+ diff_out.write_command(X1 - X2, 'd', Y - Y, !IO),
+ diff_out.show_file(File1, FromStr, X1, X2, !IO)
+ ; SingDiff = change(X1 - X2, Y1 - Y2),
+ diff_out.write_command(X1 - X2, 'c', Y1 - Y2, !IO),
+ diff_out.show_file(File1, FromStr, X1, X2, !IO),
+ io.write_string("---\n", !IO),
+ diff_out.show_file(File2, ToStr, Y1, Y2, !IO)
+ ),
+ display_diff_normal_2(File1, File2, Diff, FromStr, ToStr, !IO).
+
+
+ % diff_out.write_command displays a diff(1) command.
+ % Like ed(1), a pair of numbers which are identical
+ % are abbreviated by a single number.
+ % MK: Assumption X=<X2
+ % AJB: And, similarly, Y=<Y2. This is actually an
+ % invariant of the segment type. See difftype.m.
+:- pred diff_out.write_command(segment::in, char::in, segment::in,
+ io.state::di, io.state::uo) is det.
+
+diff_out.write_command(X - X2, C, Y - Y2, !IO) :-
+ X1 is X + 1, % Convert from pos to line number
+ ( X1 >= X2 ->
+ % either empty or singleton segment
+ io.write_int(X2, !IO)
+ ;
+ io.write_int(X1, !IO),
+ io.write_char(',', !IO),
+ io.write_int(X2, !IO)
+ ),
+ io.write_char(C, !IO),
+ Y1 is Y + 1, % Convert from pos to line number
+ ( Y1 >= Y2 ->
+ % either empty or singleton segment
+ io.write_int(Y2, !IO)
+ ;
+ io.write_int(Y1, !IO),
+ io.write_char(',', !IO),
+ io.write_int(Y2, !IO)
+ ),
+ io.write_char('\n', !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % display_diff_rcs takes a diff and displays it
+ % in the RCS difference format.
+:- pred display_diff_rcs(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_rcs(_File1, _File2, [], !IO).
+display_diff_rcs(File1, File2, [Cmd | Diff], !IO) :-
+ ( Cmd = add(X, Y1 - Y2),
+ diff_out.write_command_rcs('a', X, Y2-Y1, !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO)
+ ; Cmd = delete(X1 - X2, _Y),
+ diff_out.write_command_rcs('d', X1, X2-X1, !IO)
+ ; Cmd = change(X1 - X2, Y1 - Y2),
+ diff_out.write_command_rcs('d', X1, X2-X1, !IO),
+ diff_out.write_command_rcs('a', X1, Y2-Y1, !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO)
+ ),
+ display_diff_rcs(File1, File2, Diff, !IO).
+
+
+ % diff_out.write_command_rcs displays a diff command in
+ % the RCS ,v format.
+:- pred diff_out.write_command_rcs(char::in, int::in, int::in,
+ io.state::di, io.state::uo) is det.
+
+diff_out.write_command_rcs(C, X, Y, !IO) :-
+ io.write_char(C, !IO),
+ io.write_int(X + 1, !IO), % Convert from pos to line number
+ io.write_char(' ', !IO),
+ io.write_int(Y, !IO),
+ io.write_char('\n', !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % display_diff_ed takes a diff and displays it
+ % in ed(1) format, but with all diffs backward.
+:- pred display_diff_ed(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_ed(_File1, _File2, [], !IO).
+display_diff_ed(File1, File2, [Cmd | Diff], !IO) :-
+ display_diff_ed(File1, File2, Diff, !IO),
+ ( Cmd = add(X, Y1 - Y2),
+ diff_out.write_command_ed(X - X, 'a', !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_string(".\n", !IO)
+ ; Cmd = delete(X, _Y),
+ diff_out.write_command_ed(X, 'd', !IO)
+ ; Cmd = change(X, Y1 - Y2),
+ diff_out.write_command_ed(X, 'c', !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_string(".\n", !IO)
+ ).
+
+
+ % diff_out.write_command_ed displays an ed(1) command.
+:- pred diff_out.write_command_ed(segment::in, char::in,
+ io.state::di, io.state::uo) is det.
+
+diff_out.write_command_ed(X - X2, C, !IO) :-
+ X1 is X + 1, % Convert from pos to line number
+ ( X1 >= X2 ->
+ % either empty or singleton segment
+ io.write_int(X2, !IO)
+ ;
+ io.write_int(X1, !IO),
+ io.write_char(',', !IO),
+ io.write_int(X2, !IO)
+ ),
+ io.write_char(C, !IO),
+ io.write_char('\n', !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % display_diff_forward_ed takes a diff and displays it
+ % in ed(1) format, but with all diff_out forward. This
+ % is actually useless for feeding to ed(1), but nicer
+ % to read.
+:- pred display_diff_forward_ed(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_forward_ed(_File1, _File2, [], !IO).
+display_diff_forward_ed(File1, File2, [Cmd | Diff], !IO) :-
+ ( Cmd = add(X, Y1 - Y2),
+ diff_out.write_command_forward_ed(X - X, 'a', !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_string(".\n", !IO)
+ ; Cmd = delete(X, _Y),
+ diff_out.write_command_forward_ed(X, 'd', !IO)
+ ; Cmd = change(X, Y1 - Y2),
+ diff_out.write_command_forward_ed(X, 'c', !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_string(".\n", !IO)
+ ),
+ display_diff_forward_ed(File1, File2, Diff, !IO).
+
+ % diff_out.write_command_forward_ed displays a forward ed(1)
+ % command. The difference between this and write_command_ed is
+ % that the command char comes first here. Who comes up with
+ % these dumb formats anyway?
+:- pred diff_out.write_command_forward_ed(segment::in, char::in,
+ io.state::di, io.state::uo) is det.
+diff_out.write_command_forward_ed(X - X2, C, !IO) :-
+ io.write_char(C, !IO),
+ X1 is X + 1, % Convert from pos to line number
+ ( X1 >= X2 ->
+ % either empty or singleton segment
+ io.write_int(X2, !IO)
+ ;
+ io.write_int(X1, !IO),
+ io.write_char(' ', !IO),
+ io.write_int(X2, !IO)
+ ),
+ io.write_char('\n', !IO).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+ % display_diff_ifdef writes out the files in a unified diff,
+ % using #ifdefs around each edit.
+ %
+ % TO DO: GNU diff makes this output style much more
+ % configurable. We should too.
+:- pred display_diff_ifdef(string::in, file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_ifdef(Sym, File1, File2, Diff, !IO) :-
+ display_diff_ifdef_2(0, Sym, File1, File2, Diff, !IO).
+
+ % Argument 1 (prev) is the last pos displayed before
+ % the current edit (or end of edits, in the base case).
+ % This is important for when we have to display the
+ % "non-diffed" text between edits.
+:- pred display_diff_ifdef_2(int::in, string::in, file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_ifdef_2(Prev, _Sym, File1, _File2, [], !IO) :-
+ file.get_numlines(File1, SegEnd),
+ diff_out.show_file(File1, "", Prev, SegEnd, !IO).
+display_diff_ifdef_2(Prev, Sym, File1, File2, [Edit | Diff], !IO) :-
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ diff_out.show_file(File1, "", Prev, StartOfEdit, !IO),
+ ( Edit = add(X, Y1 - Y2),
+ io.write_strings(["#ifdef ", Sym, "\n"], !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_strings(["#endif /* ", Sym, " */\n"], !IO),
+ Next = X
+ ; Edit = delete(X1 - X2, _),
+ io.write_strings(["#ifndef ", Sym, "\n"], !IO),
+ diff_out.show_file(File1, "", X1, X2, !IO),
+ io.write_strings(["#endif /* not ", Sym, " */\n"], !IO),
+ Next = X2
+ ; Edit = change(X1 - X2, Y1 - Y2),
+ io.write_strings(["#ifndef ", Sym, "\n"], !IO),
+ diff_out.show_file(File1, "", X1, X2, !IO),
+ io.write_strings(["#else /* ", Sym, " */\n"], !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_strings(["#endif /* ", Sym, " */\n"], !IO),
+ Next = X2
+ ),
+ display_diff_ifdef_2(Next, Sym, File1, File2, Diff, !IO).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+ % display_diff_cvs_merge_conflict writes out the files in a
+ % unified diff, using CVS merge conflict marks around each edit.
+ %
+:- pred display_diff_cvs_merge_conflict(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_cvs_merge_conflict(File1, File2, Diff, !IO) :-
+ display_diff_cvs_merge_conflict_2(0, File1, File2, Diff, !IO).
+
+ % Argument 1 (prev) is the last pos displayed before
+ % the current edit (or end of edits, in the base case).
+ % This is important for when we have to display the
+ % "non-diffed" text between edits.
+:- pred display_diff_cvs_merge_conflict_2(int::in, file::in, file::in,
+ diff::in, io.state::di, io.state::uo) is det.
+
+display_diff_cvs_merge_conflict_2(Prev, File1, _File2, [], !IO) :-
+ file.get_numlines(File1, SegEnd),
+ diff_out.show_file(File1, "", Prev, SegEnd, !IO).
+display_diff_cvs_merge_conflict_2(Prev, File1, File2, [Edit | Diff], !IO) :-
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ diff_out.show_file(File1, "", Prev, StartOfEdit, !IO),
+ file.get_file_name(File1, FileName1),
+ file.get_file_name(File2, FileName2),
+ ( Edit = add(X, Y1 - Y2),
+ io.write_strings(["<<<<<<< ", FileName1, "\n"], !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_string("=======\n", !IO),
+ io.write_strings([">>>>>>> ", FileName2, "\n"], !IO),
+ Next = X
+ ; Edit = delete(X1 - X2, _),
+ io.write_strings(["<<<<<<< ", FileName1, "\n"], !IO),
+ io.write_string("=======\n", !IO),
+ diff_out.show_file(File1, "", X1, X2, !IO),
+ io.write_strings([">>>>>>> ", FileName2, "\n"], !IO),
+ Next = X2
+ ; Edit = change(X1 - X2, Y1 - Y2),
+ io.write_strings(["<<<<<<< ", FileName1, "\n"], !IO),
+ diff_out.show_file(File1, "", X1, X2, !IO),
+ io.write_string("=======\n", !IO),
+ diff_out.show_file(File2, "", Y1, Y2, !IO),
+ io.write_strings([">>>>>>> ", FileName2, "\n"], !IO),
+ Next = X2
+ ),
+ display_diff_cvs_merge_conflict_2(Next, File1, File2, Diff, !IO).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+ % Types for context/unified diffs.
+
+ % A context diff is a bit more complicated than a "standard"
+ % diff, because it requires the display of some parts of the
+ % files which are not actually part of the diff, but not all
+ % of it.
+ %
+ % Because context and unified diffs both require the same
+ % kind of information, we factor out the code to turn a
+ % normal diff into a context diff.
:- type context_edit
- ---> context_edit(segment, segment, diff).
+ ---> context_edit(segment, segment, diff).
:- type context_diff == list(context_edit).
%-----------------------------------------------------------------------------%
:- pred diff_to_context_diff(int :: in, int :: in, int :: in, diff :: in,
- context_diff :: out) is det.
+ context_diff :: out) is det.
diff_to_context_diff(_Xsize, _Ysize, _Context, [], []).
diff_to_context_diff(Xsize, Ysize, Context, [Edit | Diff], CDiff) :-
- diff_to_context_diff(Xsize, Ysize, Context, Diff, CDiff0),
+ diff_to_context_diff(Xsize, Ysize, Context, Diff, CDiff0),
- % Work out how far the context of this edit reaches.
- first_mentioned_positions(Edit, Xfirst0, Yfirst0),
- int__max(Xfirst0 - Context, 0, Xfirst),
- int__max(Yfirst0 - Context, 0, Yfirst),
- last_mentioned_positions(Edit, Xlast0, Ylast0),
- int__min(Xlast0 + Context, Xsize, Xlast),
- int__min(Ylast0 + Context, Ysize, Ylast),
-
- ( CDiff0 = [],
- CDiff = [context_edit(Xfirst - Xlast, Yfirst - Ylast, [Edit])]
- ; CDiff0 = [context_edit(XsegLo - XsegHi, YsegLo - YsegHi, DDiff) |
- CDiff1],
- % Should we merge this edit into the next one?
- (
- ( XsegLo =< Xlast
- ; YsegLo =< Ylast
- )
- ->
- CDiff = [context_edit(Xfirst - XsegHi, Yfirst - YsegHi,
- [Edit | DDiff]) | CDiff1]
- ;
- CDiff = [context_edit(Xfirst - Xlast, Yfirst - Ylast,
- [Edit]) | CDiff0]
- )
- ).
+ % Work out how far the context of this edit reaches.
+ first_mentioned_positions(Edit, Xfirst0, Yfirst0),
+ int.max(Xfirst0 - Context, 0, Xfirst),
+ int.max(Yfirst0 - Context, 0, Yfirst),
+ last_mentioned_positions(Edit, Xlast0, Ylast0),
+ int.min(Xlast0 + Context, Xsize, Xlast),
+ int.min(Ylast0 + Context, Ysize, Ylast),
+
+ ( CDiff0 = [],
+ CDiff = [context_edit(Xfirst - Xlast, Yfirst - Ylast, [Edit])]
+ ; CDiff0 = [context_edit(XsegLo - XsegHi, YsegLo - YsegHi, DDiff) |
+ CDiff1],
+ % Should we merge this edit into the next one?
+ (
+ ( XsegLo =< Xlast
+ ; YsegLo =< Ylast
+ )
+ ->
+ CDiff = [context_edit(Xfirst - XsegHi, Yfirst - YsegHi,
+ [Edit | DDiff]) | CDiff1]
+ ;
+ CDiff = [context_edit(Xfirst - Xlast, Yfirst - Ylast,
+ [Edit]) | CDiff0]
+ )
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
- % Display a diff in unified format.
-:- pred display_unified_diff(int, file, file, diff, io__state, io__state).
-:- mode display_unified_diff(in, in, in, in, di, uo) is det.
-
-display_unified_diff(Context, File1, File2, Diff) -->
- { file__get_numlines(File1, Size1) },
- { file__get_numlines(File2, Size2) },
- { diff_to_context_diff(Size1, Size2, Context, Diff, CDiff) },
- { file__get_file_name(File1, Name1) },
- { file__get_file_name(File2, Name2) },
- % XXX Should also print out file dates. But how?
- io__write_strings(["--- ", Name1, "\n"]),
- io__write_strings(["+++ ", Name2, "\n"]),
- globals__io_lookup_bool_option(initial_tab, InitialTab),
- { InitialTab = no,
- NoneStr = " ",
- AddStr = "+",
- DelStr = "-"
- ; InitialTab = yes,
- NoneStr = "\t",
- AddStr = "+\t",
- DelStr = "-\t"
- },
- display_unified_diff_2(File1, File2, CDiff, NoneStr, AddStr, DelStr).
-
-:- pred display_unified_diff_2(file, file, context_diff, string,
string, string,
- io__state, io__state).
-:- mode display_unified_diff_2(in, in, in, in, in, in, di, uo) is det.
+ % Display a diff in unified format.
+:- pred display_unified_diff(int::in, file::in, file::in, diff::in,
+ io.state::di, io.state::uo).
+
+display_unified_diff(Context, File1, File2, Diff, !IO) :-
+ file.get_numlines(File1, Size1),
+ file.get_numlines(File2, Size2),
+ diff_to_context_diff(Size1, Size2, Context, Diff, CDiff),
+ file.get_file_name(File1, Name1),
+ file.get_file_name(File2, Name2),
+ % XXX Should also print out file dates. But how?
+ io.write_strings(["--- ", Name1, "\n"], !IO),
+ io.write_strings(["+++ ", Name2, "\n"], !IO),
+ globals.io_lookup_bool_option(initial_tab, InitialTab, !IO),
+ ( InitialTab = no,
+ NoneStr = " ",
+ AddStr = "+",
+ DelStr = "-"
+ ; InitialTab = yes,
+ NoneStr = "\t",
+ AddStr = "+\t",
+ DelStr = "-\t"
+ ),
+ display_unified_diff_2(File1, File2, CDiff, NoneStr, AddStr,
+ DelStr, !IO).
+
+:- pred display_unified_diff_2(file::in, file::in, context_diff::in,
+ string::in, string::in, string::in,
+ io.state::di, io.state::uo) is det.
-display_unified_diff_2(_File1, _File2, [], _, _, _) --> [].
+display_unified_diff_2(_File1, _File2, [], _, _, _, !IO).
display_unified_diff_2(File1, File2, [Edit | CDiff],
- NoneStr, AddStr, DelStr) -->
- { Edit = context_edit(Xlow - Xhigh, Ylow - Yhigh, Diff) },
- io__format("@@ -%d,%d +%d,%d @@\n",
- [i(Xlow + 1), i(Xhigh - Xlow), i(Ylow + 1), i(Yhigh - Ylow)]),
- display_unified_diff_3(Xlow, Xhigh, File1, File2, Diff,
- NoneStr, AddStr, DelStr),
- display_unified_diff_2(File1, File2, CDiff, NoneStr, AddStr, DelStr).
-
-:- pred display_unified_diff_3(int, int, file, file, diff,
- string, string, string, io__state, io__state).
-:- mode display_unified_diff_3(in, in, in, in, in, in, in, in, di, uo) is det.
+ NoneStr, AddStr, DelStr, !IO) :-
+ Edit = context_edit(Xlow - Xhigh, Ylow - Yhigh, Diff),
+ io.format("@@ -%d,%d +%d,%d @@\n",
+ [i(Xlow + 1), i(Xhigh - Xlow), i(Ylow + 1), i(Yhigh - Ylow)],
+ !IO),
+ display_unified_diff_3(Xlow, Xhigh, File1, File2, Diff,
+ NoneStr, AddStr, DelStr, !IO),
+ display_unified_diff_2(File1, File2, CDiff, NoneStr, AddStr,
+ DelStr, !IO).
+
+:- pred display_unified_diff_3(int::in, int::in, file::in, file::in, diff::in,
+ string::in, string::in, string::in, io.state::di, io.state::uo) is det.
-display_unified_diff_3(Prev, Size1, File1, _File2, [], NoneStr, _, _) -->
- diff_out__show_file(File1, NoneStr, Prev, Size1).
+display_unified_diff_3(Prev, Size1, File1, _File2, [], NoneStr, _, _, !IO) :-
+ diff_out.show_file(File1, NoneStr, Prev, Size1, !IO).
display_unified_diff_3(Prev, Size1, File1, File2, [Edit | Diff],
- NoneStr, AddStr, DelStr) -->
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- diff_out__show_file(File1, NoneStr, Prev, StartOfEdit),
- ( { Edit = add(X, Y1 - Y2) },
- diff_out__show_file(File2, AddStr, Y1, Y2),
- { Next = X }
- ; { Edit = delete(X1 - X2, _) },
- diff_out__show_file(File1, DelStr, X1, X2),
- { Next = X1 }
- ; { Edit = change(X1 - X2, Y1 - Y2) },
- diff_out__show_file(File1, DelStr, X1, X2),
- diff_out__show_file(File2, AddStr, Y1, Y2),
- { Next = X1 }
- ),
- display_unified_diff_3(Next, Size1, File1, File2, Diff,
- NoneStr, AddStr, DelStr).
+ NoneStr, AddStr, DelStr, !IO) :-
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ diff_out.show_file(File1, NoneStr, Prev, StartOfEdit, !IO),
+ ( Edit = add(X, Y1 - Y2),
+ diff_out.show_file(File2, AddStr, Y1, Y2, !IO),
+ Next = X
+ ; Edit = delete(X1 - X2, _),
+ diff_out.show_file(File1, DelStr, X1, X2, !IO),
+ Next = X1
+ ; Edit = change(X1 - X2, Y1 - Y2),
+ diff_out.show_file(File1, DelStr, X1, X2, !IO),
+ diff_out.show_file(File2, AddStr, Y1, Y2, !IO),
+ Next = X1
+ ),
+ display_unified_diff_3(Next, Size1, File1, File2, Diff,
+ NoneStr, AddStr, DelStr, !IO).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
- % Display a diff in context format.
-:- pred display_context_diff(int, file, file, diff, io__state, io__state).
-:- mode display_context_diff(in, in, in, in, di, uo) is det.
-
-display_context_diff(Context, File1, File2, Diff) -->
- { file__get_numlines(File1, Size1) },
- { file__get_numlines(File2, Size2) },
- { diff_to_context_diff(Size1, Size2, Context, Diff, CDiff) },
- { file__get_file_name(File1, Name1) },
- { file__get_file_name(File2, Name2) },
- % XXX Should also print out file dates. But how??
- io__write_strings(["*** ", Name1, "\n"]),
- io__write_strings(["--- ", Name2, "\n"]),
-
- globals__io_lookup_bool_option(initial_tab, InitialTab),
- { InitialTab = no,
- NoneStr = " ",
- AddStr = "+ ",
- DelStr = "- ",
- ChgStr = "! "
- ; InitialTab = yes,
- NoneStr = "\t",
- AddStr = "+\t",
- DelStr = "-\t",
- ChgStr = "!\t"
- },
- display_context_diff_2(File1, File2, CDiff,
- NoneStr, AddStr, DelStr, ChgStr).
-
-:- pred display_context_diff_2(file, file, context_diff,
- string, string, string, string, io__state, io__state).
-:- mode display_context_diff_2(in, in, in, in, in, in, in, di, uo) is det.
+ % Display a diff in context format.
+:- pred display_context_diff(int::in, file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_context_diff(Context, File1, File2, Diff, !IO) :-
+ file.get_numlines(File1, Size1),
+ file.get_numlines(File2, Size2),
+ diff_to_context_diff(Size1, Size2, Context, Diff, CDiff),
+ file.get_file_name(File1, Name1),
+ file.get_file_name(File2, Name2),
+ % XXX Should also print out file dates. But how??
+ io.write_strings(["*** ", Name1, "\n"], !IO),
+ io.write_strings(["--- ", Name2, "\n"], !IO),
+
+ globals.io_lookup_bool_option(initial_tab, InitialTab, !IO),
+ ( InitialTab = no,
+ NoneStr = " ",
+ AddStr = "+ ",
+ DelStr = "- ",
+ ChgStr = "! "
+ ; InitialTab = yes,
+ NoneStr = "\t",
+ AddStr = "+\t",
+ DelStr = "-\t",
+ ChgStr = "!\t"
+ ),
+ display_context_diff_2(File1, File2, CDiff,
+ NoneStr, AddStr, DelStr, ChgStr, !IO).
+
+:- pred display_context_diff_2(file::in, file::in, context_diff::in,
+ string::in, string::in, string::in, string::in,
+ io.state::di, io.state::uo) is det.
-display_context_diff_2(_File1, _File2, [], _, _, _, _) --> [].
+display_context_diff_2(_File1, _File2, [], _, _, _, _, !IO).
display_context_diff_2(File1, File2, [Edit | CDiff],
- NoneStr, AddStr, DelStr, ChgStr) -->
- { Edit = context_edit(Xlow - Xhigh, Ylow - Yhigh, Diff) },
- io__write_string("***************\n"),
- io__format("*** %d,%d ****\n", [i(Xlow + 1), i(Xhigh)]),
-
- % Don't display the "context from" lines if there's
- % nothing deleted or changed.
- ( { all [AEdit] list__member(AEdit, Diff) => AEdit = add(_, _) } ->
- []
- ;
- display_context_diff_left(Xlow, Xhigh, File1, Diff,
- NoneStr, DelStr, ChgStr)
- ),
- io__format("--- %d,%d ----\n", [i(Ylow + 1), i(Yhigh)]),
-
- % Don't display the "context to" lines if there's
- % nothing added or changed.
- ( { all [DEdit] list__member(DEdit, Diff) => DEdit = delete(_, _) } ->
- []
- ;
- display_context_diff_right(Ylow, Yhigh, File2, Diff,
- NoneStr, AddStr, ChgStr)
- ),
- display_context_diff_2(File1, File2, CDiff,
- NoneStr, AddStr, DelStr, ChgStr).
-
-:- pred display_context_diff_left(int, int, file, diff, string, string, string,
- io__state, io__state).
-:- mode display_context_diff_left(in, in, in, in, in, in, in, di, uo) is det.
+ NoneStr, AddStr, DelStr, ChgStr, !IO) :-
+ Edit = context_edit(Xlow - Xhigh, Ylow - Yhigh, Diff),
+ io.write_string("***************\n", !IO),
+ io.format("*** %d,%d ****\n", [i(Xlow + 1), i(Xhigh)], !IO),
+
+ % Don't display the "context from" lines if there's
+ % nothing deleted or changed.
+ ( all [AEdit] list.member(AEdit, Diff) => AEdit = add(_, _) ->
+ true
+ ;
+ display_context_diff_left(Xlow, Xhigh, File1, Diff,
+ NoneStr, DelStr, ChgStr, !IO)
+ ),
+ io.format("--- %d,%d ----\n", [i(Ylow + 1), i(Yhigh)], !IO),
+
+ % Don't display the "context to" lines if there's
+ % nothing added or changed.
+ ( all [DEdit] list.member(DEdit, Diff) => DEdit = delete(_, _) ->
+ true
+ ;
+ display_context_diff_right(Ylow, Yhigh, File2, Diff,
+ NoneStr, AddStr, ChgStr, !IO)
+ ),
+ display_context_diff_2(File1, File2, CDiff,
+ NoneStr, AddStr, DelStr, ChgStr, !IO).
+
+:- pred display_context_diff_left(int::in, int::in, file::in, diff::in,
+ string::in, string::in, string::in,
+ io.state::di, io.state::uo) is det.
-display_context_diff_left(Prev, Size1, File1, [], NoneStr, _, _) -->
- diff_out__show_file(File1, NoneStr, Prev, Size1).
+display_context_diff_left(Prev, Size1, File1, [], NoneStr, _, _, !IO) :-
+ diff_out.show_file(File1, NoneStr, Prev, Size1, !IO).
display_context_diff_left(Prev, Size1, File1, [Edit | Diff],
- NoneStr, DelStr, ChgStr) -->
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- diff_out__show_file(File1, NoneStr, Prev, StartOfEdit),
- ( { Edit = add(X, _) },
- { Next = X }
- ; { Edit = delete(X1 - X2, _) },
- diff_out__show_file(File1, DelStr, X1, X2),
- { Next = X2 }
- ; { Edit = change(X1 - X2, _) },
- diff_out__show_file(File1, ChgStr, X1, X2),
- { Next = X2 }
- ),
- display_context_diff_left(Next, Size1, File1, Diff,
- NoneStr, DelStr, ChgStr).
-
-:- pred display_context_diff_right(int, int, file, diff,
- string, string, string, io__state, io__state).
-:- mode display_context_diff_right(in, in, in, in, in, in, in, di, uo) is det.
+ NoneStr, DelStr, ChgStr, !IO) :-
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ diff_out.show_file(File1, NoneStr, Prev, StartOfEdit, !IO),
+ ( Edit = add(X, _),
+ Next = X
+ ; Edit = delete(X1 - X2, _),
+ diff_out.show_file(File1, DelStr, X1, X2, !IO),
+ Next = X2
+ ; Edit = change(X1 - X2, _),
+ diff_out.show_file(File1, ChgStr, X1, X2, !IO),
+ Next = X2
+ ),
+ display_context_diff_left(Next, Size1, File1, Diff,
+ NoneStr, DelStr, ChgStr, !IO).
+
+:- pred display_context_diff_right(int::in, int::in, file::in, diff::in,
+ string::in, string::in, string::in,
+ io.state::di, io.state::uo) is det.
-display_context_diff_right(Prev, Size2, File2, [], NoneStr, _, _) -->
- diff_out__show_file(File2, NoneStr, Prev, Size2).
+display_context_diff_right(Prev, Size2, File2, [], NoneStr, _, _, !IO) :-
+ diff_out.show_file(File2, NoneStr, Prev, Size2, !IO).
display_context_diff_right(Prev, Size2, File2, [Edit | Diff],
- NoneStr, AddStr, ChgStr) -->
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- diff_out__show_file(File2, NoneStr, Prev, StartOfEdit),
- ( { Edit = add(_, Y1 - Y2) },
- diff_out__show_file(File2, AddStr, Y1, Y2),
- { Next = Y2 }
- ; { Edit = delete(_, Y) },
- { Next = Y }
- ; { Edit = change(_, Y1 - Y2) },
- diff_out__show_file(File2, ChgStr, Y1, Y2),
- { Next = Y2 }
- ),
- display_context_diff_right(Next, Size2, File2, Diff,
- NoneStr, AddStr, ChgStr).
+ NoneStr, AddStr, ChgStr, !IO) :-
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ diff_out.show_file(File2, NoneStr, Prev, StartOfEdit, !IO),
+ ( Edit = add(_, Y1 - Y2),
+ diff_out.show_file(File2, AddStr, Y1, Y2, !IO),
+ Next = Y2
+ ; Edit = delete(_, Y),
+ Next = Y
+ ; Edit = change(_, Y1 - Y2),
+ diff_out.show_file(File2, ChgStr, Y1, Y2, !IO),
+ Next = Y2
+ ),
+ display_context_diff_right(Next, Size2, File2, Diff,
+ NoneStr, AddStr, ChgStr, !IO).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
- % Side-by-side diffs are incredibly complex, as you'll see if
- % you inspect the code below.
- %
- % TO DO: GNU diff has --sdiff-merge-assist, but I can find no
- % documentation on what this actually does, and haven't
- % had the time to investigate. For the moment, we accept
- % the option and note here whether or not it's turned on,
- % but do nothing with it.
+ % Side-by-side diffs are incredibly complex, as you'll see if
+ % you inspect the code below.
+ %
+ % TO DO: GNU diff has --sdiff-merge-assist, but I can find no
+ % documentation on what this actually does, and haven't
+ % had the time to investigate. For the moment, we accept
+ % the option and note here whether or not it's turned on,
+ % but do nothing with it.
- % Parameters to pass around.
+ % Parameters to pass around.
:- type side_by_side_info
- ---> side_by_side_info(
- int, % Half width
- int, % Column 2 offset
- bool, % Left column only
- bool, % Suppress common lines
- bool % Help sdiff
- ).
-
-:- pred display_diff_side_by_side(file, file, diff, io__state, io__state).
-:- mode display_diff_side_by_side(in, in, in, di, uo) is det.
-
-display_diff_side_by_side(File1, File2, Diff) -->
- globals__io_lookup_int_option(width, Width0),
-
- % Calculate the half-width and offset stuff.
-
- % XXX If we're expanding tabs, we should
- % factor this in.
- { Off is (Width0 + 4) // 8 * 4 },
- { Max is Off - 3 },
- { HalfWidth0 is Width0 - Off + 1 },
- { HalfWidth0 =< 0 ->
- HalfWidth = 0
- ; HalfWidth0 > Max ->
- HalfWidth = Max
- ;
- HalfWidth = HalfWidth0
- },
- { HalfWidth > 0 ->
- Col2Off = Off
- ;
- Col2Off = Width0
- },
- globals__io_lookup_bool_option(left_column, LeftCol),
- globals__io_lookup_bool_option(suppress_common_lines, Suppress),
- globals__io_lookup_bool_option(sdiff_merge_assist, Sdiff),
- { SBS = side_by_side_info(HalfWidth, Col2Off, LeftCol,
- Suppress, Sdiff) },
- display_diff_side_by_side_2(0, SBS, File1, File2, Diff).
-
-:- pred display_diff_side_by_side_2(int, side_by_side_info, file, file, diff,
- io__state, io__state).
-:- mode display_diff_side_by_side_2(in, in, in, in, in, di, uo) is det.
-
-display_diff_side_by_side_2(Prev, SBS, File1, _File2, []) -->
- { SBS = side_by_side_info(_, _, _, Suppress, _) },
- ( { Suppress = no } ->
- { file__get_numlines(File1, SegEnd) },
- show_sbs_same_lines(File1, SBS, Prev - SegEnd)
- ;
- []
- ).
-display_diff_side_by_side_2(Prev, SBS, File1, File2, [Edit | Diff]) -->
- { SBS = side_by_side_info(_, _, _, Suppress, _) },
- { first_mentioned_positions(Edit, StartOfEdit, _) },
- ( { Suppress = no } ->
- show_sbs_same_lines(File1, SBS, Prev - StartOfEdit)
- ;
- []
- ),
- ( { Edit = add(X, Seg2) },
- show_sbs_added_lines(File2, SBS, Seg2),
- { Next = X }
- ; { Edit = delete(X1 - X2, _) },
- show_sbs_deleted_lines(File1, SBS, X1 - X2),
- { Next = X2 }
- ; { Edit = change(X1 - X2, Y1 - Y2) },
- % The side-by-side change diff format is sort of weird.
- % We have to compute the minimum of the two change sizes,
- % and display "changed" lines for the minimum of these
- % sizes. Then we display "added" or "deleted" lines for
- % whatever is left over.
- { int__min(X2 - X1, Y2 - Y1, Size) },
- show_sbs_changed_lines(File1, File2, SBS, X1, Y1, Size),
- show_sbs_deleted_lines(File1, SBS, (X1 + Size) - X2),
- show_sbs_added_lines(File2, SBS, (Y1 + Size) - Y2),
- { Next = X2 }
- ),
- display_diff_side_by_side_2(Next, SBS, File1, File2, Diff).
-
-:- pred show_sbs_changed_lines(file, file, side_by_side_info, int, int, int,
- io__state, io__state).
-:- mode show_sbs_changed_lines(in, in, in, in, in, in, di, uo) is det.
-
-show_sbs_changed_lines(File1, File2, SBS, X1, Y1, Size) -->
- ( { Size > 0 } ->
- (
- { file__get_line(File1, X1, Line1),
- file__get_line(File2, Y1, Line2)
- }
- ->
- { SBS = side_by_side_info(Width, _, _, _, _) },
- { string__to_char_list(Line1, Chars1) },
- print_half_line(Chars1, SBS, 0, 0, Width, OutPos),
- tab_to_column(OutPos, Width),
- io__write_string("|"),
- tab_to_column(Width + 1, Width + 2),
- { string__to_char_list(Line2, Chars2) },
- print_half_line(Chars2, SBS, 0, 0, Width, _),
- io__write_string("\n"),
- show_sbs_changed_lines(File1, File2, SBS,
- X1 + 1, Y1 + 1, Size - 1)
- ;
- { error("show_sbs_changed_lines: file ended prematurely") }
- )
- ;
- []
- ).
-
-:- pred show_sbs_same_lines(file, side_by_side_info, segment,
- io__state, io__state).
-:- mode show_sbs_same_lines(in, in, in, di, uo) is det.
-
-show_sbs_same_lines(File, SBS, Low - High) -->
- ( { Low < High } ->
- ( { file__get_line(File, Low, Line) } ->
- { SBS = side_by_side_info(Width, _, LeftCol, _, _) },
- { string__to_char_list(Line, Chars) },
- print_half_line(Chars, SBS, 0, 0, Width, OutPos),
-
- % If the user specified --left, don't
- % display the right column here.
- ( { LeftCol = yes } ->
- tab_to_column(OutPos, Width),
- io__write_string("(")
- ;
- tab_to_column(OutPos, Width + 2),
- print_half_line(Chars, SBS, 0, 0, Width, _)
- ),
- io__write_string("\n"),
- show_sbs_same_lines(File, SBS, (Low + 1) - High)
- ;
- { error("show_sbs_same_lines: file ended prematurely") }
- )
- ;
- []
- ).
-
-:- pred show_sbs_added_lines(file, side_by_side_info, segment,
- io__state, io__state).
-:- mode show_sbs_added_lines(in, in, in, di, uo) is det.
-
-show_sbs_added_lines(File, SBS, Low - High) -->
- ( { Low < High } ->
- ( { file__get_line(File, Low, Line) } ->
- { SBS = side_by_side_info(Width, _, _, _, _) },
- { string__to_char_list(Line, Chars) },
- tab_to_column(0, Width),
- io__write_string("> "),
- print_half_line(Chars, SBS, 0, 0, Width, _),
- io__write_string("\n"),
- show_sbs_added_lines(File, SBS, (Low + 1) - High)
- ;
- { error("show_sbs_added_lines: file ended prematurely") }
- )
- ;
- []
- ).
-
-:- pred show_sbs_deleted_lines(file, side_by_side_info, segment,
- io__state, io__state).
-:- mode show_sbs_deleted_lines(in, in, in, di, uo) is det.
-
-show_sbs_deleted_lines(File, SBS, Low - High) -->
- ( { Low < High } ->
- ( { file__get_line(File, Low, Line) } ->
- { SBS = side_by_side_info(Width, _, _, _, _) },
- { string__to_char_list(Line, Chars) },
- print_half_line(Chars, SBS, 0, 0, Width, OutPos),
- tab_to_column(OutPos, Width),
- io__write_string("<\n"),
- show_sbs_deleted_lines(File, SBS, (Low + 1) - High)
- ;
- { error("show_sbs_deleted_lines: file ended prematurely") }
- )
- ;
- []
- ).
+ ---> side_by_side_info(
+ int, % Half width
+ int, % Column 2 offset
+ bool, % Left column only
+ bool, % Suppress common lines
+ bool % Help sdiff
+ ).
+
+:- pred display_diff_side_by_side(file::in, file::in, diff::in,
+ io.state::di, io.state::uo) is det.
+
+display_diff_side_by_side(File1, File2, Diff, !IO) :-
+ globals.io_lookup_int_option(width, Width0, !IO),
+
+ % Calculate the half-width and offset stuff.
+
+ % XXX If we're expanding tabs, we should
+ % factor this in.
+ Off is (Width0 + 4) // 8 * 4,
+ Max is Off - 3,
+ HalfWidth0 is Width0 - Off + 1,
+ ( HalfWidth0 =< 0 ->
+ HalfWidth = 0
+ ; HalfWidth0 > Max ->
+ HalfWidth = Max
+ ;
+ HalfWidth = HalfWidth0
+ ),
+ ( HalfWidth > 0 ->
+ Col2Off = Off
+ ;
+ Col2Off = Width0
+ ),
+ globals.io_lookup_bool_option(left_column, LeftCol, !IO),
+ globals.io_lookup_bool_option(suppress_common_lines, Suppress, !IO),
+ globals.io_lookup_bool_option(sdiff_merge_assist, Sdiff, !IO),
+ SBS = side_by_side_info(HalfWidth, Col2Off, LeftCol,
+ Suppress, Sdiff),
+ display_diff_side_by_side_2(0, SBS, File1, File2, Diff, !IO).
+
+:- pred display_diff_side_by_side_2(int::in, side_by_side_info::in, file::in,
+ file::in, diff::in, io.state::di, io.state::uo) is det.
+
+display_diff_side_by_side_2(Prev, SBS, File1, _File2, [], !IO) :-
+ SBS = side_by_side_info(_, _, _, Suppress, _),
+ ( Suppress = no ->
+ file.get_numlines(File1, SegEnd),
+ show_sbs_same_lines(File1, SBS, Prev - SegEnd, !IO)
+ ;
+ true
+ ).
+display_diff_side_by_side_2(Prev, SBS, File1, File2, [Edit | Diff], !IO) :-
+ SBS = side_by_side_info(_, _, _, Suppress, _),
+ first_mentioned_positions(Edit, StartOfEdit, _),
+ ( Suppress = no ->
+ show_sbs_same_lines(File1, SBS, Prev - StartOfEdit, !IO)
+ ;
+ true
+ ),
+ ( Edit = add(X, Seg2),
+ show_sbs_added_lines(File2, SBS, Seg2, !IO),
+ Next = X
+ ; Edit = delete(X1 - X2, _),
+ show_sbs_deleted_lines(File1, SBS, X1 - X2, !IO),
+ Next = X2
+ ; Edit = change(X1 - X2, Y1 - Y2),
+ % The side-by-side change diff format is sort of weird.
+ % We have to compute the minimum of the two change sizes,
+ % and display "changed" lines for the minimum of these
+ % sizes. Then we display "added" or "deleted" lines for
+ % whatever is left over.
+ int.min(X2 - X1, Y2 - Y1, Size),
+ show_sbs_changed_lines(File1, File2, SBS, X1, Y1, Size, !IO),
+ show_sbs_deleted_lines(File1, SBS, (X1 + Size) - X2, !IO),
+ show_sbs_added_lines(File2, SBS, (Y1 + Size) - Y2, !IO),
+ Next = X2
+ ),
+ display_diff_side_by_side_2(Next, SBS, File1, File2, Diff, !IO).
+
+:- pred show_sbs_changed_lines(file::in, file::in, side_by_side_info::in,
+ int::in, int::in, int::in, io.state::di, io.state::uo) is det.
+
+show_sbs_changed_lines(File1, File2, SBS, X1, Y1, Size, !IO) :-
+ ( Size > 0 ->
+ (
+ file.get_line(File1, X1, Line1),
+ file.get_line(File2, Y1, Line2)
+ ->
+ SBS = side_by_side_info(Width, _, _, _, _),
+ string.to_char_list(Line1, Chars1),
+ print_half_line(Chars1, SBS, 0, 0, Width, OutPos, !IO),
+ tab_to_column(OutPos, Width, !IO),
+ io.write_string("|", !IO),
+ tab_to_column(Width + 1, Width + 2, !IO),
+ string.to_char_list(Line2, Chars2),
+ print_half_line(Chars2, SBS, 0, 0, Width, _, !IO),
+ io.write_string("\n", !IO),
+ show_sbs_changed_lines(File1, File2, SBS,
+ X1 + 1, Y1 + 1, Size - 1, !IO)
+ ;
+ error("show_sbs_changed_lines: file ended prematurely")
+ )
+ ;
+ true
+ ).
+
+:- pred show_sbs_same_lines(file::in, side_by_side_info::in, segment::in,
+ io.state::di, io.state::uo) is det.
+
+show_sbs_same_lines(File, SBS, Low - High, !IO) :-
+ ( Low < High ->
+ ( file.get_line(File, Low, Line) ->
+ SBS = side_by_side_info(Width, _, LeftCol, _, _),
+ string.to_char_list(Line, Chars),
+ print_half_line(Chars, SBS, 0, 0, Width, OutPos, !IO),
+
+ % If the user specified --left, don't
+ % display the right column here.
+ ( LeftCol = yes ->
+ tab_to_column(OutPos, Width, !IO),
+ io.write_string("(", !IO)
+ ;
+ tab_to_column(OutPos, Width + 2, !IO),
+ print_half_line(Chars, SBS, 0, 0, Width, _, !IO)
+ ),
+ io.write_string("\n", !IO),
+ show_sbs_same_lines(File, SBS, (Low + 1) - High, !IO)
+ ;
+ error("show_sbs_same_lines: file ended prematurely")
+ )
+ ;
+ true
+ ).
+
+:- pred show_sbs_added_lines(file::in, side_by_side_info::in, segment::in,
+ io.state::di, io.state::uo) is det.
+
+show_sbs_added_lines(File, SBS, Low - High, !IO) :-
+ ( Low < High ->
+ ( file.get_line(File, Low, Line) ->
+ SBS = side_by_side_info(Width, _, _, _, _),
+ string.to_char_list(Line, Chars),
+ tab_to_column(0, Width, !IO),
+ io.write_string("> ", !IO),
+ print_half_line(Chars, SBS, 0, 0, Width, _, !IO),
+ io.write_string("\n", !IO),
+ show_sbs_added_lines(File, SBS, (Low + 1) - High, !IO)
+ ;
+ error("show_sbs_added_lines: file ended prematurely")
+ )
+ ;
+ true
+ ).
+
+:- pred show_sbs_deleted_lines(file::in, side_by_side_info::in, segment::in,
+ io.state::di, io.state::uo) is det.
+
+show_sbs_deleted_lines(File, SBS, Low - High, !IO) :-
+ ( Low < High ->
+ ( file.get_line(File, Low, Line) ->
+ SBS = side_by_side_info(Width, _, _, _, _),
+ string.to_char_list(Line, Chars),
+ print_half_line(Chars, SBS, 0, 0, Width, OutPos, !IO),
+ tab_to_column(OutPos, Width, !IO),
+ io.write_string("<\n", !IO),
+ show_sbs_deleted_lines(File, SBS, (Low + 1) - High, !IO)
+ ;
+ error("show_sbs_deleted_lines: file ended prematurely")
+ )
+ ;
+ true
+ ).
:- func tab_width = int.
tab_width = 8.
- % Put a number of spaces on the output stream. Update
- % the output column as we go.
-:- pred put_spaces(int, int, int, io__state, io__state).
-:- mode put_spaces(in, in, out, di, uo) is det.
-
-put_spaces(Spaces, OutPos0, OutPos) -->
- ( { Spaces =< 0 } ->
- { OutPos = OutPos0 }
- ;
- io__write_char(' '),
- put_spaces(Spaces - 1, OutPos0 + 1, OutPos)
- ).
-
- % Given a "from" column and a "to" column, put sufficient
- % spaces on the output stream to reach that column. Use
- % tabs if we can.
-:- pred tab_to_column(int, int, io__state, io__state).
-:- mode tab_to_column(in, in, di, uo) is det.
-
-tab_to_column(From, To) -->
- { AfterTab is From + tab_width - (From rem tab_width) },
- ( { AfterTab > To } ->
- ( { From < To } ->
- io__write_char(' '),
- tab_to_column(From + 1, To)
- ;
- []
- )
- ;
- io__write_char('\t'),
- tab_to_column(AfterTab, To)
- ).
-
- % Display half a line in a side-by-side diff, stopping when
- % we reach a certain column.
- %
- % This is actually a very simple thing to do, except for one
- % complication, which is the displaying of tab characters.
- %
- % The important variables are:
- %
- % InPos: The current column in the input line.
- % OutPos: The current column in the output line.
- % OutBound: The column that we must stop at.
- %
+ % Put a number of spaces on the output stream. Update
+ % the output column as we go.
+:- pred put_spaces(int::in, int::in, int::out, io.state::di,
io.state::uo) is det.
+
+put_spaces(Spaces, OutPos0, OutPos, !IO) :-
+ ( Spaces =< 0 ->
+ OutPos = OutPos0
+ ;
+ io.write_char(' ', !IO),
+ put_spaces(Spaces - 1, OutPos0 + 1, OutPos, !IO)
+ ).
+
+ % Given a "from" column and a "to" column, put sufficient
+ % spaces on the output stream to reach that column. Use
+ % tabs if we can.
+:- pred tab_to_column(int::in, int::in, io.state::di, io.state::uo) is det.
+
+tab_to_column(From, To, !IO) :-
+ AfterTab is From + tab_width - (From rem tab_width),
+ ( AfterTab > To ->
+ ( From < To ->
+ io.write_char(' ', !IO),
+ tab_to_column(From + 1, To, !IO)
+ ;
+ true
+ )
+ ;
+ io.write_char('\t', !IO),
+ tab_to_column(AfterTab, To, !IO)
+ ).
+
+ % Display half a line in a side-by-side diff, stopping when
+ % we reach a certain column.
+ %
+ % This is actually a very simple thing to do, except for one
+ % complication, which is the displaying of tab characters.
+ %
+ % The important variables are:
+ %
+ % InPos: The current column in the input line.
+ % OutPos: The current column in the output line.
+ % OutBound: The column that we must stop at.
+ %
:- pred print_half_line(list(char) :: in, side_by_side_info :: in,
- int :: in, int :: in, int :: in, int :: out,
- io__state :: di, io__state :: uo) is det.
+ int :: in, int :: in, int :: in, int :: out,
+ io.state :: di, io.state :: uo) is det.
print_half_line([], _SBS, _InPos, OutPos, _OutBound, OutPos) --> [].
print_half_line([C | Cs], SBS, InPos0, OutPos0, OutBound, OutPos) -->
- ( { C = '\t' } ->
- % Calculate how many spaces this tab is worth.
- { Spaces is tab_width - InPos0 rem tab_width },
- ( { InPos0 = OutPos0 } ->
- globals__io_lookup_bool_option(expand_tabs, ExpandTabs),
- ( { ExpandTabs = yes } ->
- % If we're expanding tabs, we just pretend that
- % we had Spaces spaces and write them.
- { TabStop0 is OutPos0 + Spaces },
- { TabStop0 > OutBound ->
- TabStop = OutBound
- ;
- TabStop = TabStop0
- },
- put_spaces(TabStop - OutPos0, OutPos0, OutPos1)
- ;
- % If we're not exanding tabs, just print it and
- % hope everything lines up okay.
- io__write_char('\t'),
- { OutPos1 is OutPos0 + Spaces }
- )
- ;
- { OutPos1 = OutPos0 }
- ),
- { InPos is InPos0 + Spaces }
- ; { C = '\r' ; C = '\b' ; C = '\n' } ->
- % XXX What to do? For the moment, we'll just ignore it.
- { InPos = InPos0, OutPos1 = OutPos0 }
- /***********
- % XXX Binary files aren't really supported.
- ; { \+ char__is_print(C) } ->
- { InPos = InPos0, OutPos1 = OutPos0 }
- ( { InPos < OutBound } ->
- io__write_char(C)
- ;
- []
- )
- ***********/
- ;
- % The default case. Print and be done with it.
- { InPos is InPos0 + 1 },
- ( { InPos < OutBound } ->
- { OutPos1 = InPos },
- io__write_char(C)
- ;
- { OutPos1 = OutPos0 }
- )
- ),
- print_half_line(Cs, SBS, InPos, OutPos1, OutBound, OutPos).
+ ( { C = '\t' } ->
+ % Calculate how many spaces this tab is worth.
+ { Spaces is tab_width - InPos0 rem tab_width },
+ ( { InPos0 = OutPos0 } ->
+ globals.io_lookup_bool_option(expand_tabs, ExpandTabs),
+ ( { ExpandTabs = yes } ->
+ % If we're expanding tabs, we just pretend that
+ % we had Spaces spaces and write them.
+ { TabStop0 is OutPos0 + Spaces },
+ { TabStop0 > OutBound ->
+ TabStop = OutBound
+ ;
+ TabStop = TabStop0
+ },
+ put_spaces(TabStop - OutPos0, OutPos0, OutPos1)
+ ;
+ % If we're not exanding tabs, just print it and
+ % hope everything lines up okay.
+ io.write_char('\t'),
+ { OutPos1 is OutPos0 + Spaces }
+ )
+ ;
+ { OutPos1 = OutPos0 }
+ ),
+ { InPos is InPos0 + Spaces }
+ ; { C = '\r' ; C = '\b' ; C = '\n' } ->
+ % XXX What to do? For the moment, we'll just ignore it.
+ { InPos = InPos0, OutPos1 = OutPos0 }
+ /***********
+ % XXX Binary files aren't really supported.
+ ; { \+ char.is_print(C) } ->
+ { InPos = InPos0, OutPos1 = OutPos0 }
+ ( { InPos < OutBound } ->
+ io.write_char(C)
+ ;
+ []
+ )
+ ***********/
+ ;
+ % The default case. Print and be done with it.
+ { InPos is InPos0 + 1 },
+ ( { InPos < OutBound } ->
+ { OutPos1 = InPos },
+ io.write_char(C)
+ ;
+ { OutPos1 = OutPos0 }
+ )
+ ),
+ print_half_line(Cs, SBS, InPos, OutPos1, OutBound, OutPos).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/difftype.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/difftype.m,v
retrieving revision 1.2
diff -u -r1.2 difftype.m
--- samples/diff/difftype.m 15 Sep 1998 04:54:24 -0000 1.2
+++ samples/diff/difftype.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1995-1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -17,32 +19,32 @@
:- interface.
:- import_module std_util, list.
- % A pos is a non-negative number representing a position in a
- % list. The position before all elements is 0, the one
- % between the first and second elements is 1, etc.
+ % A pos is a non-negative number representing a position in a
+ % list. The position before all elements is 0, the one
+ % between the first and second elements is 1, etc.
:- type pos == int.
%-----------------------------------------------------------------------------%
- % A segment is a pair of positions. Numbering items from 0,
- % segment P-Q stands for items P up to, but not including, Q.
- % (Rationale: see the interpretation of type pos above.)
- %
- % Invariant: In any segment X - Y, it should always be true
- % that X =< Y. If X=Y, the segment is empty.
+ % A segment is a pair of positions. Numbering items from 0,
+ % segment P-Q stands for items P up to, but not including, Q.
+ % (Rationale: see the interpretation of type pos above.)
+ %
+ % Invariant: In any segment X - Y, it should always be true
+ % that X =< Y. If X=Y, the segment is empty.
:- type segment == pair(pos,pos).
- % An edit operation is an addition, a deletion or a change.
+ % An edit operation is an addition, a deletion or a change.
:- type edit --->
- add(pos,segment)
- ; delete(segment,pos)
- ; change(segment,segment).
-
- % The complete diff of two file is a list of edit
- % operations.
- %
- % Invariant: The edits must be in order, and must
- % not overlap or touch.
+ add(pos,segment)
+ ; delete(segment,pos)
+ ; change(segment,segment).
+
+ % The complete diff of two file is a list of edit
+ % operations.
+ %
+ % Invariant: The edits must be in order, and must
+ % not overlap or touch.
:- type diff == list(edit).
%-----------------------------------------------------------------------------%
@@ -53,11 +55,10 @@
%-----------------------------------------------------------------------------%
- % Add an edit to the start of a diff, producing a new diff.
- % This predicate determines what kind of edit this is, and
- % merges with the adjacent edits if appropriate.
-:- pred difftype__add_edit(segment, segment, diff, diff).
-:- mode difftype__add_edit(in, in, in, out) is det.
+ % Add an edit to the start of a diff, producing a new diff.
+ % This predicate determines what kind of edit this is, and
+ % merges with the adjacent edits if appropriate.
+:- pred difftype.add_edit(segment::in, segment::in, diff::in,
diff::out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -75,51 +76,51 @@
%-----------------------------------------------------------------------------%
-difftype__add_edit(X1 - X2, Y1 - Y2, [], Diff) :-
- ( X1 = X2 ->
- ( Y1 = Y2 ->
- Diff = []
- ;
- Diff = [add(X1, Y1 - Y2)]
- )
- ;
- ( Y1 = Y2 ->
- Diff = [delete(X1 - X2, Y1)]
- ;
- Diff = [change(X1 - X2, Y1 - Y2)]
- )
- ).
-difftype__add_edit(X1 - X2, Y1 - Y2, [Edit0 | Diff0], Diff) :-
- ( Edit0 = add(X2, Y2 - Y3) ->
- ( X1 = X2 ->
- Diff = [add(X1, Y1 - Y3) | Diff0]
- ;
- Diff = [change(X1 - X2, Y1 - Y3) | Diff0]
- )
- ; Edit0 = delete(X2 - X3, Y2) ->
- ( Y1 = Y2 ->
- Diff = [delete(X1 - X3, Y1) | Diff0]
- ;
- Diff = [change(X1 - X3, Y1 - Y2) | Diff0]
- )
- ; Edit0 = change(X2 - X3, Y2 - Y3) ->
- Diff = [change(X1 - X3, Y1 - Y3) | Diff0]
- ;
- % This is just copied from the base case. Pretty much.
- ( X1 = X2 ->
- ( Y1 = Y2 ->
- Diff = [Edit0 | Diff0]
- ;
- Diff = [add(X1, Y1 - Y2), Edit0 | Diff0]
- )
- ;
- ( Y1 = Y2 ->
- Diff = [delete(X1 - X2, Y1), Edit0 | Diff0]
- ;
- Diff = [change(X1 - X2, Y1 - Y2), Edit0 | Diff0]
- )
- )
- ).
+difftype.add_edit(X1 - X2, Y1 - Y2, [], Diff) :-
+ ( X1 = X2 ->
+ ( Y1 = Y2 ->
+ Diff = []
+ ;
+ Diff = [add(X1, Y1 - Y2)]
+ )
+ ;
+ ( Y1 = Y2 ->
+ Diff = [delete(X1 - X2, Y1)]
+ ;
+ Diff = [change(X1 - X2, Y1 - Y2)]
+ )
+ ).
+difftype.add_edit(X1 - X2, Y1 - Y2, [Edit0 | Diff0], Diff) :-
+ ( Edit0 = add(X2, Y2 - Y3) ->
+ ( X1 = X2 ->
+ Diff = [add(X1, Y1 - Y3) | Diff0]
+ ;
+ Diff = [change(X1 - X2, Y1 - Y3) | Diff0]
+ )
+ ; Edit0 = delete(X2 - X3, Y2) ->
+ ( Y1 = Y2 ->
+ Diff = [delete(X1 - X3, Y1) | Diff0]
+ ;
+ Diff = [change(X1 - X3, Y1 - Y2) | Diff0]
+ )
+ ; Edit0 = change(X2 - X3, Y2 - Y3) ->
+ Diff = [change(X1 - X3, Y1 - Y3) | Diff0]
+ ;
+ % This is just copied from the base case. Pretty much.
+ ( X1 = X2 ->
+ ( Y1 = Y2 ->
+ Diff = [Edit0 | Diff0]
+ ;
+ Diff = [add(X1, Y1 - Y2), Edit0 | Diff0]
+ )
+ ;
+ ( Y1 = Y2 ->
+ Diff = [delete(X1 - X2, Y1), Edit0 | Diff0]
+ ;
+ Diff = [change(X1 - X2, Y1 - Y2), Edit0 | Diff0]
+ )
+ )
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/file.m,v
retrieving revision 1.11
diff -u -r1.11 file.m
--- samples/diff/file.m 15 Sep 1998 04:54:26 -0000 1.11
+++ samples/diff/file.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1995-1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -22,42 +24,36 @@
:- type file.
- % file__read_file reads a file from a filename.
-:- pred file__read_file(string, io__res(file), io__state, io__state).
-:- mode file__read_file(in, out, di, uo) is det.
-
- % file__read_input reads a file from the input
- % stream.
-:- pred file__read_input(string, io__res(file), io__state, io__state).
-:- mode file__read_input(in, out, di, uo) is det.
-
- % file__get_line retrieves a line from a file.
- % (Lines are numbered from 0.)
- % Fails if the line is out of bounds.
-:- pred file__get_line(file, int, string).
-:- mode file__get_line(in, in, out) is semidet.
-
- % file__get_numlines returns the number of lines
- % in a file.
-:- pred file__get_numlines(file, int).
-:- mode file__get_numlines(in, out) is det.
-
- % file__from_list converts a list of lines to a file.
-:- pred file__from_list(string, list(string), file).
-:- mode file__from_list(in, in, out) is det.
-
- % file__to_list converts a file into a list of
- % lines.
-:- pred file__to_list(file, list(string)).
-:- mode file__to_list(in, out) is det.
-
- % file__get_file_name returns the name of the file.
-:- pred file__get_file_name(file, string).
-:- mode file__get_file_name(in, out) is det.
-
- % file__set_file_name sets the name of the file.
-:- pred file__set_file_name(file, string, file).
-:- mode file__set_file_name(in, in, out) is det.
+ % file.read_file reads a file from a filename.
+:- pred file.read_file(string::in, io.res(file)::out, io.state::di,
+ io.state::uo) is det.
+
+ % file.read_input reads a file from the input
+ % stream.
+:- pred file.read_input(string::in, io.res(file)::out, io.state::di,
+ io.state::uo) is det.
+
+ % file.get_line retrieves a line from a file.
+ % (Lines are numbered from 0.)
+ % Fails if the line is out of bounds.
+:- pred file.get_line(file::in, int::in, string::out) is semidet.
+
+ % file.get_numlines returns the number of lines
+ % in a file.
+:- pred file.get_numlines(file::in, int::out) is det.
+
+ % file.from_list converts a list of lines to a file.
+:- pred file.from_list(string::in, list(string)::in, file::out) is det.
+
+ % file.to_list converts a file into a list of
+ % lines.
+:- pred file.to_list(file::in, list(string)::out) is det.
+
+ % file.get_file_name returns the name of the file.
+:- pred file.get_file_name(file::in, string::out) is det.
+
+ % file.set_file_name sets the name of the file.
+:- pred file.set_file_name(file::in, string::in, file::out) is det.
%-----------------------------------------------------------------------------%
@@ -67,75 +63,73 @@
%-----------------------------------------------------------------------------%
:- type file
- ---> file(
- string, % File name
- array(string) % Contents
- ).
-
- % Open the stream, read from the stream, then close
- % the stream.
-file__read_file(FileName, File) -->
- io__open_input(FileName, Res),
- ( { Res = ok(InputStream) },
- file__read_stream(InputStream, Contents),
- io__close_input(InputStream),
- { File = ok(file(FileName, Contents)) }
- ; { Res = error(Error) },
- { File = error(Error) }
- ).
-
- % Get the input stream, then read from it.
-file__read_input(FileName, ok(file(FileName, Contents))) -->
- io__input_stream(InputStream),
- file__read_stream(InputStream, Contents).
-
- % file__read_stream is the "real" file reader.
-:- pred file__read_stream(io__input_stream, array(string),
- io__state, io__state).
-:- mode file__read_stream(in, array_uo, di, uo) is det.
-file__read_stream(Stream, File) -->
- file__read_stream2(Stream, 0, File).
-
- % Given a Stream from which LinesIn lines have already been
- % read, fill File[LinesIn] to File[LinesOut-1] with the rest
- % of the lines. LinesOut is the number of lines in the file.
- % (Note that line numbering starts at zero.)
-:- pred file__read_stream2(io__input_stream, int, array(string),
- io__state, io__state).
-:- mode file__read_stream2(in, in, array_uo, di, uo) is det.
-file__read_stream2(Stream, LineNo, File) -->
- io__read_line_as_string(Stream, Res),
- ( { Res = eof },
- { array__init(LineNo, "", File) }
- ; { Res = ok(Line) },
- file__read_stream2(Stream, LineNo + 1, File1),
- { array__set(File1, LineNo, Line, File) }
- ; { Res = error(Error) },
- { io__error_message(Error, Msg) },
- { error(Msg) }
- ).
-
-%-----------------------------------------------------------------------------%
-
-file__get_line(file(_, Contents), LineNo, Line) :-
- array__semidet_lookup(Contents, LineNo, Line).
-
-file__get_numlines(file(_, Contents), NumLines1 + 1) :-
- array__bounds(Contents, _, NumLines1).
-
-%-----------------------------------------------------------------------------%
-
-file__to_list(file(_, Contents), List) :-
- array__to_list(Contents, List).
+ ---> file(
+ string, % File name
+ array(string) % Contents
+ ).
+
+ % Open the stream, read from the stream, then close
+ % the stream.
+file.read_file(FileName, File, !IO) :-
+ io.open_input(FileName, Res, !IO),
+ ( Res = ok(InputStream),
+ file.read_stream(InputStream, Contents, !IO),
+ io.close_input(InputStream, !IO),
+ File = ok(file(FileName, Contents))
+ ; Res = error(Error),
+ File = error(Error)
+ ).
+
+ % Get the input stream, then read from it.
+file.read_input(FileName, ok(file(FileName, Contents)), !IO) :-
+ io.input_stream(InputStream, !IO),
+ file.read_stream(InputStream, Contents, !IO).
+
+ % file.read_stream is the "real" file reader.
+:- pred file.read_stream(io.input_stream::in, array(string)::array_uo,
+ io.state::di, io.state::uo) is det.
+file.read_stream(Stream, File, !IO) :-
+ file.read_stream2(Stream, 0, File, !IO).
+
+ % Given a Stream from which LinesIn lines have already been
+ % read, fill File[LinesIn] to File[LinesOut-1] with the rest
+ % of the lines. LinesOut is the number of lines in the file.
+ % (Note that line numbering starts at zero.)
+:- pred file.read_stream2(io.input_stream::in, int::in,
+ array(string)::array_uo, io.state::di, io.state::uo) is det.
+file.read_stream2(Stream, LineNo, File, !IO) :-
+ io.read_line_as_string(Stream, Res, !IO),
+ ( Res = eof,
+ array.init(LineNo, "", File)
+ ; Res = ok(Line),
+ file.read_stream2(Stream, LineNo + 1, File1, !IO),
+ array.set(File1, LineNo, Line, File)
+ ; Res = error(Error),
+ io.error_message(Error, Msg),
+ error(Msg)
+ ).
+
+%-----------------------------------------------------------------------------%
+
+file.get_line(file(_, Contents), LineNo, Line) :-
+ array.semidet_lookup(Contents, LineNo, Line).
+
+file.get_numlines(file(_, Contents), NumLines1 + 1) :-
+ array.bounds(Contents, _, NumLines1).
+
+%-----------------------------------------------------------------------------%
+
+file.to_list(file(_, Contents), List) :-
+ array.to_list(Contents, List).
-file__from_list(FileName, List, file(FileName, Contents)) :-
- array__from_list(List, Contents).
+file.from_list(FileName, List, file(FileName, Contents)) :-
+ array.from_list(List, Contents).
%-----------------------------------------------------------------------------%
-file__get_file_name(file(FileName, _), FileName).
+file.get_file_name(file(FileName, _), FileName).
-file__set_file_name(file(_, B), FileName, file(FileName, B)).
+file.set_file_name(file(_, B), FileName, file(FileName, B)).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/filter.m,v
retrieving revision 1.2
diff -u -r1.2 filter.m
--- samples/diff/filter.m 15 Sep 1998 04:54:28 -0000 1.2
+++ samples/diff/filter.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -27,7 +29,7 @@
:- import_module difftype, file, io.
:- pred filter_diff(diff :: in, file :: in, file :: in, diff :: out,
- io__state :: di, io__state :: uo) is det.
+ io.state :: di, io.state :: uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -36,66 +38,65 @@
:- import_module globals, options.
:- import_module bool, list, int, std_util, string, char.
-filter_diff(Diff0, File1, File2, Diff) -->
- globals__io_lookup_bool_option(ignore_blank_lines, FilterBlank),
+filter_diff(Diff0, File1, File2, Diff, !IO) :-
+ globals.io_lookup_bool_option(ignore_blank_lines, FilterBlank, !IO),
- { FilterBlank = no ->
- % If we didn't request a filter, skip this pass.
+ ( FilterBlank = no ->
+ % If we didn't request a filter, skip this pass.
- Diff = Diff0
- ;
- filter__blank_lines(Diff0, File1, File2, Diff)
- }.
-
-:- pred filter__blank_lines(diff :: in, file :: in, file :: in, diff :: out)
- is det.
-
-filter__blank_lines([], _, _, []).
-filter__blank_lines([Edit | Diff0], File1, File2, Diff) :-
- filter__blank_lines(Diff0, File1, File2, Diff1),
- ( Edit = add(_, Y1 - Y2),
- ( range_has_only_blank_lines(Y1, Y2, File2) ->
- Diff = Diff1
- ;
- Diff = [Edit | Diff1]
- )
- ; Edit = delete(X1 - X2, _),
- ( range_has_only_blank_lines(X1, X2, File1) ->
- Diff = Diff1
- ;
- Diff = [Edit | Diff1]
- )
- ; Edit = change(X1 - X2, Y1 - Y2),
- (
- range_has_only_blank_lines(X1, X2, File1),
- range_has_only_blank_lines(Y1, Y2, File2)
- ->
- Diff = Diff1
- ;
- Diff = [Edit | Diff1]
- )
- ).
+ Diff = Diff0
+ ;
+ filter.blank_lines(Diff0, File1, File2, Diff)
+ ).
+
+:- pred filter.blank_lines(diff :: in, file :: in, file :: in, diff :: out)
+ is det.
+
+filter.blank_lines([], _, _, []).
+filter.blank_lines([Edit | Diff0], File1, File2, Diff) :-
+ filter.blank_lines(Diff0, File1, File2, Diff1),
+ ( Edit = add(_, Y1 - Y2),
+ ( range_has_only_blank_lines(Y1, Y2, File2) ->
+ Diff = Diff1
+ ;
+ Diff = [Edit | Diff1]
+ )
+ ; Edit = delete(X1 - X2, _),
+ ( range_has_only_blank_lines(X1, X2, File1) ->
+ Diff = Diff1
+ ;
+ Diff = [Edit | Diff1]
+ )
+ ; Edit = change(X1 - X2, Y1 - Y2),
+ (
+ range_has_only_blank_lines(X1, X2, File1),
+ range_has_only_blank_lines(Y1, Y2, File2)
+ ->
+ Diff = Diff1
+ ;
+ Diff = [Edit | Diff1]
+ )
+ ).
%-----------------------------------------------------------------------------%
-:- pred range_has_only_blank_lines(int, int, file).
-:- mode range_has_only_blank_lines(in, in, in) is semidet.
+:- pred range_has_only_blank_lines(int::in, int::in, file::in) is semidet.
range_has_only_blank_lines(First, Last, File) :-
- (
- First < Last
- =>
- (
- file__get_line(File, First, Line),
- string__to_char_list(Line, Chars),
- all [C] (
- list__member(C, Chars)
- =>
- char__is_whitespace(C)
- ),
- range_has_only_blank_lines(First + 1, Last, File)
- )
- ).
+ (
+ First < Last
+ =>
+ (
+ file.get_line(File, First, Line),
+ string.to_char_list(Line, Chars),
+ all [C] (
+ list.member(C, Chars)
+ =>
+ char.is_whitespace(C)
+ ),
+ range_has_only_blank_lines(First + 1, Last, File)
+ )
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/globals.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/globals.m,v
retrieving revision 1.3
diff -u -r1.3 globals.m
--- samples/diff/globals.m 8 Feb 2001 11:37:53 -0000 1.3
+++ samples/diff/globals.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1994-1998, 2001 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -11,7 +13,7 @@
% This module exports the `globals' type and associated access predicates.
% The globals type is used to collect together all the various data
% that would be global variables in an imperative language.
-% This global data is stored in the io__state.
+% This global data is stored in the io.state.
%-----------------------------------------------------------------------------%
@@ -24,69 +26,68 @@
%-----------------------------------------------------------------------------%
- % Access predicates for the `globals' structure.
+ % Access predicates for the `globals' structure.
-:- pred globals__init(option_table::in, globals::out) is det.
+:- pred globals.init(option_table::in, globals::out) is det.
-:- pred globals__get_options(globals::in, option_table::out) is det.
+:- pred globals.get_options(globals::in, option_table::out) is det.
-:- pred globals__set_options(globals::in, option_table::in, globals::out)
- is det.
+:- pred globals.set_options(globals::in, option_table::in, globals::out)
+ is det.
-:- pred globals__get_output_style(globals::in, diff_out__output_style::out)
- is det.
+:- pred globals.get_output_style(globals::in, diff_out.output_style::out)
+ is det.
-:- pred globals__set_output_style(globals::in, diff_out__output_style::in,
- globals::out) is det.
+:- pred globals.set_output_style(globals::in, diff_out.output_style::in,
+ globals::out) is det.
-:- pred globals__lookup_option(globals::in, option::in, option_data::out)
- is det.
+:- pred globals.lookup_option(globals::in, option::in, option_data::out)
+ is det.
-:- pred globals__lookup_bool_option(globals, option, bool).
-:- mode globals__lookup_bool_option(in, in, out) is det.
-:- pred globals__lookup_int_option(globals::in, option::in, int::out) is det.
-:- pred globals__lookup_string_option(globals::in, option::in, string::out)
- is det.
-:- pred globals__lookup_accumulating_option(globals::in, option::in,
- list(string)::out) is det.
+:- pred globals.lookup_bool_option(globals::in, option::in, bool::out) is det.
+:- pred globals.lookup_int_option(globals::in, option::in, int::out) is det.
+:- pred globals.lookup_string_option(globals::in, option::in, string::out)
+ is det.
+:- pred globals.lookup_accumulating_option(globals::in, option::in,
+ list(string)::out) is det.
%-----------------------------------------------------------------------------%
- % Access predicates for storing a `globals' structure in the
- % io__state using io__set_globals and io__get_globals.
+ % Access predicates for storing a `globals' structure in the
+ % io.state using io.set_globals and io.get_globals.
-:- pred globals__io_init(option_table::in,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_init(option_table::in,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_get_globals(globals::out, io__state::di, io__state::uo)
- is det.
+:- pred globals.io_get_globals(globals::out, io.state::di, io.state::uo)
+ is det.
-:- pred globals__io_set_globals(globals::in, io__state::di, io__state::uo)
- is det.
+:- pred globals.io_set_globals(globals::in, io.state::di, io.state::uo)
+ is det.
-:- pred globals__io_get_output_style(diff_out__output_style::out,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_get_output_style(diff_out.output_style::out,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_set_output_style(diff_out__output_style::in,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_set_output_style(diff_out.output_style::in,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_lookup_option(option::in, option_data::out,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_lookup_option(option::in, option_data::out,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_set_option(option::in, option_data::in,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_set_option(option::in, option_data::in,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_lookup_bool_option(option, bool, io__state, io__state).
-:- mode globals__io_lookup_bool_option(in, out, di, uo) is det.
+:- pred globals.io_lookup_bool_option(option::in, bool::out,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_lookup_int_option(option::in, int::out,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_lookup_int_option(option::in, int::out,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_lookup_string_option(option::in, string::out,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_lookup_string_option(option::in, string::out,
+ io.state::di, io.state::uo) is det.
-:- pred globals__io_lookup_accumulating_option(option::in, list(string)::out,
- io__state::di, io__state::uo) is det.
+:- pred globals.io_lookup_accumulating_option(option::in, list(string)::out,
+ io.state::di, io.state::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -97,124 +98,124 @@
%-----------------------------------------------------------------------------%
:- type globals
- ---> globals(
- option_table, % Current options
- diff_out__output_style % Current module name
- ).
+ ---> globals(
+ option_table, % Current options
+ diff_out.output_style % Current module name
+ ).
-globals__init(Options, globals(Options, OutputType)) :-
- diff_out__default_output_style(OutputType).
+globals.init(Options, globals(Options, OutputType)) :-
+ diff_out.default_output_style(OutputType).
-globals__get_options(globals(Options, _), Options).
+globals.get_options(globals(Options, _), Options).
-globals__set_options(globals(_, Scanner), Options, globals(Options, Scanner)).
+globals.set_options(globals(_, Scanner), Options, globals(Options, Scanner)).
-globals__get_output_style(globals(_, Output), Output).
+globals.get_output_style(globals(_, Output), Output).
-globals__set_output_style(globals(A, _), Output, globals(A, Output)).
+globals.set_output_style(globals(A, _), Output, globals(A, Output)).
-globals__lookup_option(Globals, Option, OptionData) :-
- globals__get_options(Globals, OptionTable),
- map__lookup(OptionTable, Option, OptionData).
+globals.lookup_option(Globals, Option, OptionData) :-
+ globals.get_options(Globals, OptionTable),
+ map.lookup(OptionTable, Option, OptionData).
%-----------------------------------------------------------------------------%
-globals__lookup_bool_option(Globals, Option, Value) :-
- globals__lookup_option(Globals, Option, OptionData),
- ( OptionData = bool(Bool) ->
- Value = Bool
- ;
- error("globals__lookup_bool_option: invalid bool option")
- ).
+globals.lookup_bool_option(Globals, Option, Value) :-
+ globals.lookup_option(Globals, Option, OptionData),
+ ( OptionData = bool(Bool) ->
+ Value = Bool
+ ;
+ error("globals.lookup_bool_option: invalid bool option")
+ ).
-globals__lookup_string_option(Globals, Option, Value) :-
- globals__lookup_option(Globals, Option, OptionData),
- ( OptionData = string(String) ->
- Value = String
- ;
- error("globals__lookup_string_option: invalid string option")
- ).
+globals.lookup_string_option(Globals, Option, Value) :-
+ globals.lookup_option(Globals, Option, OptionData),
+ ( OptionData = string(String) ->
+ Value = String
+ ;
+ error("globals.lookup_string_option: invalid string option")
+ ).
-globals__lookup_int_option(Globals, Option, Value) :-
- globals__lookup_option(Globals, Option, OptionData),
- ( OptionData = int(Int) ->
- Value = Int
- ;
- error("globals__lookup_int_option: invalid int option")
- ).
+globals.lookup_int_option(Globals, Option, Value) :-
+ globals.lookup_option(Globals, Option, OptionData),
+ ( OptionData = int(Int) ->
+ Value = Int
+ ;
+ error("globals.lookup_int_option: invalid int option")
+ ).
-globals__lookup_accumulating_option(Globals, Option, Value) :-
- globals__lookup_option(Globals, Option, OptionData),
- ( OptionData = accumulating(Accumulating) ->
- Value = Accumulating
- ;
- error("globals__lookup_accumulating_option: invalid accumulating option")
- ).
+globals.lookup_accumulating_option(Globals, Option, Value) :-
+ globals.lookup_option(Globals, Option, OptionData),
+ ( OptionData = accumulating(Accumulating) ->
+ Value = Accumulating
+ ;
+ error("globals.lookup_accumulating_option: invalid
accumulating option")
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
-globals__io_init(Options) -->
- { globals__init(Options, Globals) },
- globals__io_set_globals(Globals).
+globals.io_init(Options, !IO) :-
+ globals.init(Options, Globals),
+ globals.io_set_globals(Globals, !IO).
-globals__io_get_globals(Globals) -->
- io__get_globals(UnivGlobals),
- {
- univ_to_type(UnivGlobals, Globals0)
- ->
- Globals = Globals0
- ;
- error("globals__io_get_globals: univ_to_type failed")
- }.
+globals.io_get_globals(Globals, !IO) :-
+ io.get_globals(UnivGlobals, !IO),
+ (
+ univ_to_type(UnivGlobals, Globals0)
+ ->
+ Globals = Globals0
+ ;
+ error("globals.io_get_globals: univ_to_type failed")
+ ).
-globals__io_set_globals(Globals) -->
- { unsafe_promise_unique(Globals, UniqGlobals) },
- { type_to_univ(UniqGlobals, UnivGlobals) },
- io__set_globals(UnivGlobals).
+globals.io_set_globals(Globals, !IO) :-
+ unsafe_promise_unique(Globals, UniqGlobals),
+ type_to_univ(UniqGlobals, UnivGlobals),
+ io.set_globals(UnivGlobals, !IO).
%-----------------------------------------------------------------------------%
-globals__io_lookup_option(Option, OptionData) -->
- globals__io_get_globals(Globals),
- { globals__get_options(Globals, OptionTable) },
- { map__lookup(OptionTable, Option, OptionData) }.
+globals.io_lookup_option(Option, OptionData, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.get_options(Globals, OptionTable),
+ map.lookup(OptionTable, Option, OptionData).
-globals__io_set_option(Option, OptionData) -->
- globals__io_get_globals(Globals0),
- { globals__get_options(Globals0, OptionTable0) },
- { map__set(OptionTable0, Option, OptionData, OptionTable) },
- { globals__set_options(Globals0, OptionTable, Globals) },
- globals__io_set_globals(Globals).
+globals.io_set_option(Option, OptionData, !IO) :-
+ globals.io_get_globals(Globals0, !IO),
+ globals.get_options(Globals0, OptionTable0),
+ map.set(OptionTable0, Option, OptionData, OptionTable),
+ globals.set_options(Globals0, OptionTable, Globals),
+ globals.io_set_globals(Globals, !IO).
%-----------------------------------------------------------------------------%
-globals__io_lookup_bool_option(Option, Value) -->
- globals__io_get_globals(Globals),
- { globals__lookup_bool_option(Globals, Option, Value) }.
+globals.io_lookup_bool_option(Option, Value, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.lookup_bool_option(Globals, Option, Value).
-globals__io_lookup_int_option(Option, Value) -->
- globals__io_get_globals(Globals),
- { globals__lookup_int_option(Globals, Option, Value) }.
+globals.io_lookup_int_option(Option, Value, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.lookup_int_option(Globals, Option, Value).
-globals__io_lookup_string_option(Option, Value) -->
- globals__io_get_globals(Globals),
- { globals__lookup_string_option(Globals, Option, Value) }.
+globals.io_lookup_string_option(Option, Value, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.lookup_string_option(Globals, Option, Value).
-globals__io_lookup_accumulating_option(Option, Value) -->
- globals__io_get_globals(Globals),
- { globals__lookup_accumulating_option(Globals, Option, Value) }.
+globals.io_lookup_accumulating_option(Option, Value, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.lookup_accumulating_option(Globals, Option, Value).
%-----------------------------------------------------------------------------%
-globals__io_get_output_style(Output) -->
- globals__io_get_globals(Globals),
- { globals__get_output_style(Globals, Output) }.
+globals.io_get_output_style(Output, !IO) :-
+ globals.io_get_globals(Globals, !IO),
+ globals.get_output_style(Globals, Output).
-globals__io_set_output_style(Output) -->
- globals__io_get_globals(Globals0),
- { globals__set_output_style(Globals0, Output, Globals) },
- globals__io_set_globals(Globals).
+globals.io_set_output_style(Output, !IO) :-
+ globals.io_get_globals(Globals0, !IO),
+ globals.set_output_style(Globals0, Output, Globals),
+ globals.io_set_globals(Globals, !IO).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/match.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/match.m,v
retrieving revision 1.1
diff -u -r1.1 match.m
--- samples/diff/match.m 15 Sep 1998 04:54:33 -0000 1.1
+++ samples/diff/match.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -20,9 +22,9 @@
% file and pretend the whole sequence is just one line. (GNU
% diff does the same thing a slightly different way, but this
% approach seems a bit more Mercury-esque.) Since Myers'
-% algorithm runs in O(ND) time, and performing this pre-filtering
-% here would reduce the value of D (by quite a lot in real-world
-% cases), things should speed up.
+% algorithm runs in O(ND) time, and performing this pre-filtering
+% here would reduce the value of D (by quite a lot in real-world
+% cases), things should speed up.
%-----------------------------------------------------------------------------%
@@ -32,8 +34,8 @@
:- import_module file, io, array.
:- pred build_matches(file :: in, file :: in,
- array(int) :: out, array(int) :: out,
- io__state :: di, io__state :: uo) is det.
+ array(int) :: out, array(int) :: out,
+ io.state :: di, io.state :: uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -43,110 +45,109 @@
:- import_module bool, list, int, std_util, string, char, map, require.
:- type match_options
- ---> match_options(
- bool, % No options set
- bool, % --ignore-case
- bool, % --ignore-all-space
- bool % --ignore-space-change
- ).
-
-build_matches(File1, File2, FileX, FileY) -->
- globals__io_lookup_bool_option(ignore_case, IgnCase),
- globals__io_lookup_bool_option(ignore_all_space, IgnAllSpc),
- globals__io_lookup_bool_option(ignore_space_change, IgnSpcChg),
- {
- bool__or_list([IgnCase, IgnAllSpc, IgnSpcChg], AnyOpts),
- bool__not(AnyOpts, NoOpts),
- Opts = match_options(NoOpts, IgnCase, IgnAllSpc, IgnSpcChg),
- map__init(MatchMap0),
- file__get_numlines(File1, SizeX),
- array__init(SizeX, -1, FileX0),
- build_matches_for_file(Opts, File1, SizeX - 1, MatchMap0,
- MatchMap1, 0, ID1, FileX0, FileX),
- file__get_numlines(File2, SizeY),
- array__init(SizeY, -1, FileY0),
- build_matches_for_file(Opts, File2, SizeY - 1, MatchMap1, _,
- ID1, _, FileY0, FileY)
- }.
-
-:- pred build_matches_for_file(match_options, file, int,
- map(string, int), map(string, int), int, int, array(int), array(int)).
-:- mode build_matches_for_file(in, in, in, in, out, in, out,
- array_di, array_uo) is det.
+ ---> match_options(
+ bool, % No options set
+ bool, % --ignore-case
+ bool, % --ignore-all-space
+ bool % --ignore-space-change
+ ).
+
+build_matches(File1, File2, FileX, FileY, !IO) :-
+ globals.io_lookup_bool_option(ignore_case, IgnCase, !IO),
+ globals.io_lookup_bool_option(ignore_all_space, IgnAllSpc, !IO),
+ globals.io_lookup_bool_option(ignore_space_change, IgnSpcChg, !IO),
+ (
+ bool.or_list([IgnCase, IgnAllSpc, IgnSpcChg], AnyOpts),
+ bool.not(AnyOpts, NoOpts),
+ Opts = match_options(NoOpts, IgnCase, IgnAllSpc, IgnSpcChg),
+ map.init(MatchMap0),
+ file.get_numlines(File1, SizeX),
+ array.init(SizeX, -1, FileX0),
+ build_matches_for_file(Opts, File1, SizeX - 1, MatchMap0,
+ MatchMap1, 0, ID1, FileX0, FileX),
+ file.get_numlines(File2, SizeY),
+ array.init(SizeY, -1, FileY0),
+ build_matches_for_file(Opts, File2, SizeY - 1, MatchMap1, _,
+ ID1, _, FileY0, FileY)
+ ).
+
+:- pred build_matches_for_file(match_options::in, file::in, int::in,
+ map(string, int)::in, map(string, int)::out, int::in, int::out,
+ array(int)::array_di, array(int)::array_uo) is det.
build_matches_for_file(Opts, OrigFile, I, MatchMap0, MatchMap, ID0, ID,
- File0, File) :-
- ( I < 0 ->
- MatchMap = MatchMap0,
- ID = ID0,
- File = File0
- ;
- ( file__get_line(OrigFile, I, Line0) ->
- Line1 = Line0
- ;
- error("build_matches_for_file")
- ),
- Opts = match_options(NoOpts, IgnCase, IgnAllSpc, IgnSpcChg),
- ( NoOpts = yes ->
- Line = Line1
- ;
- string__to_char_list(Line1, Chars0),
- normalise_line(no, IgnCase, IgnAllSpc, IgnSpcChg,
- Chars0, Chars1),
- string__from_char_list(Chars1, Line)
- ),
- ( map__search(MatchMap0, Line, MaybeID) ->
- array__set(File0, I, MaybeID, File1),
- MatchMap1 = MatchMap0,
- ID1 = ID0
- ;
- array__set(File0, I, ID0, File1),
- map__det_insert(MatchMap0, Line, ID0, MatchMap1),
- ID1 is ID0 + 1
- ),
- build_matches_for_file(Opts, OrigFile, I - 1, MatchMap1,
- MatchMap, ID1, ID, File1, File)
- ).
+ File0, File) :-
+ ( I < 0 ->
+ MatchMap = MatchMap0,
+ ID = ID0,
+ File = File0
+ ;
+ ( file.get_line(OrigFile, I, Line0) ->
+ Line1 = Line0
+ ;
+ error("build_matches_for_file")
+ ),
+ Opts = match_options(NoOpts, IgnCase, IgnAllSpc, IgnSpcChg),
+ ( NoOpts = yes ->
+ Line = Line1
+ ;
+ string.to_char_list(Line1, Chars0),
+ normalise_line(no, IgnCase, IgnAllSpc, IgnSpcChg,
+ Chars0, Chars1),
+ string.from_char_list(Chars1, Line)
+ ),
+ ( map.search(MatchMap0, Line, MaybeID) ->
+ array.set(File0, I, MaybeID, File1),
+ MatchMap1 = MatchMap0,
+ ID1 = ID0
+ ;
+ array.set(File0, I, ID0, File1),
+ map.det_insert(MatchMap0, Line, ID0, MatchMap1),
+ ID1 is ID0 + 1
+ ),
+ build_matches_for_file(Opts, OrigFile, I - 1, MatchMap1,
+ MatchMap, ID1, ID, File1, File)
+ ).
-:- pred normalise_line(bool, bool, bool, bool, list(char), list(char)).
-:- mode normalise_line(in, in, in, in, in, out) is det.
+:- pred normalise_line(bool::in, bool::in, bool::in, bool::in,
+ list(char)::in, list(char)::out) is det.
normalise_line(_, _, _, _, [], []).
normalise_line(LastSpace, IgnCase, IgnAllSpc, IgnSpcChg, [C0 | Cs0], Cs) :-
- ( IgnCase = yes ->
- char__to_lower(C0, C)
- ;
- C = C0
- ),
- (
- char__is_whitespace(C),
- (
- IgnAllSpc = yes
- ->
- normalise_line(LastSpace, IgnCase, IgnAllSpc, IgnSpcChg,
- Cs0, CsX)
- ;
- IgnSpcChg = yes
- ->
- ( LastSpace = yes ->
- normalise_line(yes, IgnCase, IgnAllSpc,
- IgnSpcChg, Cs0, CsX)
- ;
- normalise_line(yes, IgnCase, IgnAllSpc,
- IgnSpcChg, Cs0, Cs1),
- CsX = [' ' | Cs1]
-
- )
- ;
- fail
- )
- ->
- Cs = CsX
- ;
- normalise_line(no, IgnCase, IgnAllSpc, IgnSpcChg,
- Cs0, Cs1),
- Cs = [C | Cs1]
- ).
+ ( IgnCase = yes ->
+ char.to_lower(C0, C)
+ ;
+ C = C0
+ ),
+ (
+ char.is_whitespace(C),
+ (
+ IgnAllSpc = yes
+ ->
+ normalise_line(LastSpace, IgnCase, IgnAllSpc, IgnSpcChg,
+ Cs0, CsX)
+ ;
+ IgnSpcChg = yes
+ ->
+ ( LastSpace = yes ->
+ normalise_line(yes, IgnCase, IgnAllSpc,
+ IgnSpcChg, Cs0, CsX)
+ ;
+ normalise_line(yes, IgnCase, IgnAllSpc,
+ IgnSpcChg, Cs0, Cs1),
+ CsX = [' ' | Cs1]
+
+ )
+ ;
+ fail
+ )
+ ->
+ Cs = CsX
+ ;
+ normalise_line(no, IgnCase, IgnAllSpc, IgnSpcChg,
+ Cs0, Cs1),
+ Cs = [C | Cs1]
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/myers.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/myers.m,v
retrieving revision 1.1
diff -u -r1.1 myers.m
--- samples/diff/myers.m 15 Sep 1998 04:54:36 -0000 1.1
+++ samples/diff/myers.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -7,14 +9,14 @@
% Main author: bromage
% TO DO: We should implement the big-snake heuristic (a.k.a.
-% --speed-large-files).
+% --speed-large-files).
%
% ALSO TO DO: Gene Myers et al have since produced another algorithm
-% which takes O(NP) time where P is the number of deletions in
-% the edit script. If the `too expensive' heuristic can be
-% retro-fitted onto that algorithm easily enough, we should try
-% out this algorithm and see how fast it runs. In theory, we
-% should be looking at about a 2x speedup.
+% which takes O(NP) time where P is the number of deletions in
+% the edit script. If the `too expensive' heuristic can be
+% retro-fitted onto that algorithm easily enough, we should try
+% out this algorithm and see how fast it runs. In theory, we
+% should be looking at about a 2x speedup.
%-----------------------------------------------------------------------------%
@@ -23,8 +25,8 @@
:- interface.
:- import_module difftype, array, io.
-:- pred diff_by_myers(array(int), array(int), diff, io__state, io__state).
-:- mode diff_by_myers(in, in, out, di, uo) is det.
+:- pred diff_by_myers(array(int)::in, array(int)::in, diff::out,
+ io.state::di, io.state::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -34,466 +36,454 @@
:- import_module map, require, std_util, int, list, char, bool.
% The basic algorithm is described in:
-% "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
-% Algorithmica Vol. 1 No. 2, 1986, pp. 251-266.
+% "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
+% Algorithmica Vol. 1 No. 2, 1986, pp. 251-266.
%
% This uses the variation in section 4b.
-diff_by_myers(FileX, FileY, Diff) -->
- globals__io_lookup_bool_option(minimal, Minimal),
- {
- array__size(FileX, SizeX),
- array__size(FileY, SizeY),
- SizeMax = SizeX + SizeY + 3,
- DOffset = SizeY + 1,
-
- % If we don't insist on --minimal, calculate the
- % approximate square root of the input size for
- % the "too expensive" heuristic. The effect of
- % this is to limit the amount of work to about
- % O(n ** (1.5 log n)) at the expense of finding a
- % possibly non-minimal diff.
-
- ( Minimal = yes,
- Heur = none
- ; Minimal = no,
- int__log2(SizeMax, SizeLog2),
- int__max(minimum_too_expensive, 1 << (SizeLog2 // 2),
- SizeHeuristic),
- Heur = too_expensive(SizeHeuristic)
- ),
-
- % Fill the arrays with nondescript numbers which
- % the algorithm shouldn't produce. (For debugging
- % purposes.)
- array__init(SizeMax, -65537, Fwd),
- array__init(SizeMax, -65537, Bwd),
- myers__bsearch(DOffset, FileX, FileY, 0, SizeX, 0, SizeY,
- Heur, Fwd, _, Bwd, _, [], Diff)
- }.
+diff_by_myers(FileX, FileY, Diff, !IO) :-
+ globals.io_lookup_bool_option(minimal, Minimal, !IO),
+ (
+ array.size(FileX, SizeX),
+ array.size(FileY, SizeY),
+ SizeMax = SizeX + SizeY + 3,
+ DOffset = SizeY + 1,
+
+ % If we don't insist on --minimal, calculate the
+ % approximate square root of the input size for
+ % the "too expensive" heuristic. The effect of
+ % this is to limit the amount of work to about
+ % O(n ** (1.5 log n)) at the expense of finding a
+ % possibly non-minimal diff.
+
+ ( Minimal = yes,
+ Heur = none
+ ; Minimal = no,
+ int.log2(SizeMax, SizeLog2),
+ int.max(minimum_too_expensive, 1 << (SizeLog2 // 2),
+ SizeHeuristic),
+ Heur = too_expensive(SizeHeuristic)
+ ),
+
+ % Fill the arrays with nondescript numbers which
+ % the algorithm shouldn't produce. (For debugging
+ % purposes.)
+ array.init(SizeMax, -65537, Fwd),
+ array.init(SizeMax, -65537, Bwd),
+ myers.bsearch(DOffset, FileX, FileY, 0, SizeX, 0, SizeY,
+ Heur, Fwd, _, Bwd, _, [], Diff)
+ ).
- % XXX This lower bound is a guess. Need to do some measurements
- % to see if it's good or not.
+ % XXX This lower bound is a guess. Need to do some measurements
+ % to see if it's good or not.
:- func minimum_too_expensive = int.
minimum_too_expensive = 256.
-:- pred myers__bsearch(int, array(int), array(int), int, int, int, int, heur,
- array(int), array(int), array(int), array(int),
- diff, diff).
-:- mode myers__bsearch(in, in, in, in, in, in, in, in,
- array_di, array_uo, array_di, array_uo,
- in, out) is det.
-
-myers__bsearch(DOffset, FileX, FileY, Xlow0, Xhigh0, Ylow0, Yhigh0, Heur,
- Fwd0, Fwd, Bwd0, Bwd, Diff0, Diff) :-
- myers__scan_forward(FileX, FileY, Xhigh0, Yhigh0,
- Xlow0, Xlow, Ylow0, Ylow),
- myers__scan_backward(FileX, FileY, Xlow, Ylow,
- Xhigh0, Xhigh, Yhigh0, Yhigh),
-
- (
- ( Xlow >= Xhigh
- ; Ylow >= Yhigh
- )
- ->
- Fwd = Fwd0, Bwd = Bwd0,
- difftype__add_edit(Xlow - Xhigh, Ylow - Yhigh, Diff0, Diff)
- ;
- myers__find_middle(DOffset, FileX, FileY,
- Xlow, Xhigh, Ylow, Yhigh, Heur,
- Fwd0, Fwd1, Bwd0, Bwd1, Xmid, Ymid, Cost,
- LeftHeur - RightHeur),
- (
- Cost > 0
- ->
- myers__bsearch(DOffset, FileX, FileY,
- Xmid, Xhigh, Ymid, Yhigh, LeftHeur,
- Fwd1, Fwd2, Bwd1, Bwd2, Diff0, Diff1),
- myers__bsearch(DOffset, FileX, FileY,
- Xlow, Xmid, Ylow, Ymid, RightHeur,
- Fwd2, Fwd, Bwd2, Bwd, Diff1, Diff)
- ;
- error("myers__bsearch")
- )
- ).
+:- pred myers.bsearch(int::in, array(int)::in, array(int)::in, int::in,
+ int::in, int::in, int::in, heur::in,
+ array(int)::array_di, array(int)::array_uo,
+ array(int)::array_di, array(int)::array_uo,
+ diff::in, diff::out) is det.
+
+myers.bsearch(DOffset, FileX, FileY, Xlow0, Xhigh0, Ylow0, Yhigh0, Heur,
+ Fwd0, Fwd, Bwd0, Bwd, Diff0, Diff) :-
+ myers.scan_forward(FileX, FileY, Xhigh0, Yhigh0,
+ Xlow0, Xlow, Ylow0, Ylow),
+ myers.scan_backward(FileX, FileY, Xlow, Ylow,
+ Xhigh0, Xhigh, Yhigh0, Yhigh),
+
+ (
+ ( Xlow >= Xhigh
+ ; Ylow >= Yhigh
+ )
+ ->
+ Fwd = Fwd0, Bwd = Bwd0,
+ difftype.add_edit(Xlow - Xhigh, Ylow - Yhigh, Diff0, Diff)
+ ;
+ myers.find_middle(DOffset, FileX, FileY,
+ Xlow, Xhigh, Ylow, Yhigh, Heur,
+ Fwd0, Fwd1, Bwd0, Bwd1, Xmid, Ymid, Cost,
+ LeftHeur - RightHeur),
+ (
+ Cost > 0
+ ->
+ myers.bsearch(DOffset, FileX, FileY,
+ Xmid, Xhigh, Ymid, Yhigh, LeftHeur,
+ Fwd1, Fwd2, Bwd1, Bwd2, Diff0, Diff1),
+ myers.bsearch(DOffset, FileX, FileY,
+ Xlow, Xmid, Ylow, Ymid, RightHeur,
+ Fwd2, Fwd, Bwd2, Bwd, Diff1, Diff)
+ ;
+ error("myers.bsearch")
+ )
+ ).
:- type myers_constants
- ---> constants(
- int, % DOffset
- array(int), % X
- array(int), % Y
- int, % Xlow
- int, % Xhigh
- int, % Ylow
- int, % Yhigh
- int, % Dmin
- int, % Dmax
- bool, % DeltaOdd
- heur % "Too expensive" heuristic.
- ).
+ ---> constants(
+ int, % DOffset
+ array(int), % X
+ array(int), % Y
+ int, % Xlow
+ int, % Xhigh
+ int, % Ylow
+ int, % Yhigh
+ int, % Dmin
+ int, % Dmax
+ bool, % DeltaOdd
+ heur % "Too expensive" heuristic.
+ ).
:- type heur
- ---> too_expensive(int)
- ; none.
+ ---> too_expensive(int)
+ ; none.
- % The best part about this algorithm is: We don't actually
- % need to find the middle of the diff. We only have to find
- % an estimate to it. If we don't find the exact middle,
- % we will have a correct diff, but it won't necessarily be
- % minimal.
-:- pred myers__find_middle(int, array(int), array(int), pos, pos, pos, pos,
- heur,
- array(int), array(int), array(int), array(int),
- pos, pos, int, pair(heur)).
-:- mode myers__find_middle(in, in, in, in, in, in, in, in,
- array_di, array_uo, array_di, array_uo,
- out, out, out, out) is det.
-
-myers__find_middle(DOffset, FileX, FileY, Xlow, Xhigh, Ylow, Yhigh, Heur,
- Fwd0, Fwd, Bwd0, Bwd, Xmid, Ymid, Cost, HeurReq) :-
-
- Dmin = Xlow - Yhigh,
- Dmax = Xhigh - Ylow,
-
- Fmid = Xlow - Ylow,
- array__set(Fwd0, Fmid + DOffset, Xlow, Fwd1),
- Bmid = Xhigh - Yhigh,
- array__set(Bwd0, Bmid + DOffset, Xhigh, Bwd1),
-
- ( 1 = (Fmid - Bmid) /\ 1 ->
- DeltaOdd = yes
- ;
- DeltaOdd = no
- ),
-
- Constants = constants(
- DOffset, FileX, FileY, Xlow, Xhigh, Ylow, Yhigh,
- Dmin, Dmax, DeltaOdd, Heur
- ),
-
- myers__find_middle_2(Constants, Fwd1, Fwd, Bwd1, Bwd,
- Fmid, Fmid, Bmid, Bmid, 1, Cost, Xmid - Ymid, HeurReq).
-
-
-:- pred myers__find_middle_2(myers_constants,
- array(int), array(int), array(int), array(int),
- int, int, int, int, int, int, pair(pos), pair(heur)).
-:- mode myers__find_middle_2(in, array_di, array_uo, array_di, array_uo,
- in, in, in, in, in, out, out, out) is det.
-
-myers__find_middle_2(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
- Constants = constants(DOffset, _, _, _, _, _, _, Dmin, Dmax, _, _),
- ( Fmin > Dmin ->
- Fmin1 = Fmin - 1,
- array__set(Fwd0, Fmin1 + DOffset - 1, -1, Fwd1)
- ;
- Fmin1 = Fmin + 1,
- Fwd1 = Fwd0
- ),
- ( Fmax < Dmax ->
- Fmax1 = Fmax + 1,
- array__set(Fwd1, Fmax1 + DOffset + 1, -1, Fwd2)
- ;
- Fmax1 = Fmax - 1,
- Fwd2 = Fwd1
- ),
- myers__find_forward_reaching_path(Constants, Fwd2, Fwd, Bwd0, Bwd,
- Fmin1, Fmax1, Bmin, Bmax, Fmax1, Cost0, Cost, Mid, HeurReq).
-
-
-:- pred myers__find_forward_reaching_path(myers_constants,
- array(int), array(int), array(int), array(int),
- int, int, int, int, int, int, int, pair(pos), pair(heur)).
-:- mode myers__find_forward_reaching_path(in, array_di, array_uo,
- array_di, array_uo, in, in, in, in, in, in, out, out, out)
- is det.
-
-myers__find_forward_reaching_path(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, SearchCost, Cost0, Cost, Mid,
- HeurReq) :-
- ( SearchCost < Fmin ->
- Constants = constants(DOffset, _, _, _, _, _, _, Dmin, Dmax, _,
- _),
- int__max_int(MaxInt),
- ( Bmin > Dmin ->
- Bmin1 = Bmin - 1,
- array__set(Bwd0, Bmin1 + DOffset - 1, MaxInt, Bwd1)
- ;
- Bmin1 = Bmin + 1,
- Bwd1 = Bwd0
- ),
- ( Bmax < Dmax ->
- Bmax1 = Bmax + 1,
- array__set(Bwd1, Bmax1 + DOffset + 1, MaxInt, Bwd2)
- ;
- Bmax1 = Bmax - 1,
- Bwd2 = Bwd1
- ),
- myers__find_backward_reaching_path(Constants,
- Fwd0, Fwd, Bwd2, Bwd, Fmin, Fmax, Bmin1, Bmax1,
- Bmax1, Cost0, Cost, Mid, HeurReq)
- ;
- Constants = constants(DOffset, _, _, _, _, _, _, _, _, _, _),
- array__lookup(Fwd0, SearchCost + DOffset - 1, Tlo),
- array__lookup(Fwd0, SearchCost + DOffset + 1, Thi),
- ( Tlo >= Thi ->
- X0 = Tlo + 1
- ;
- X0 = Thi
- ),
- Y0 = X0 - SearchCost,
- Constants = constants(_, FileX, FileY, _, Xhigh, _, Yhigh,
- _, _, _, _),
- myers__scan_forward(FileX, FileY, Xhigh, Yhigh, X0, X, Y0, Y),
- array__set(Fwd0, SearchCost + DOffset, X, Fwd1),
-
- Constants = constants(_, _, _, _, _, _, _, _, _, DeltaOdd, _),
- (
- DeltaOdd = yes,
- Bmin =< SearchCost,
- SearchCost =< Bmax,
- array__lookup(Bwd0, SearchCost + DOffset, BB),
- BB =< X
- ->
- Mid = X - Y,
- Cost = 2 * Cost0 + 1,
- Fwd = Fwd1,
- Bwd = Bwd0,
- HeurReq = none - none
- ;
- myers__find_forward_reaching_path(Constants,
- Fwd1, Fwd, Bwd0, Bwd, Fmin, Fmax, Bmin, Bmax,
- SearchCost - 2, Cost0, Cost, Mid, HeurReq)
- )
- ).
-
-
-:- pred myers__find_backward_reaching_path(myers_constants,
- array(int), array(int), array(int), array(int),
- int, int, int, int, int, int, int, pair(pos), pair(heur)).
-:- mode myers__find_backward_reaching_path(in, array_di, array_uo,
- array_di, array_uo, in, in, in, in, in, in,
- out, out, out) is det.
-
-myers__find_backward_reaching_path(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, SearchCost, Cost0, Cost, Mid,
- HeurReq) :-
- ( SearchCost < Bmin ->
- myers__try_heuristics(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq)
- ;
- Constants = constants(DOffset, _, _, _, _, _, _, _, _, _, _),
- array__lookup(Bwd0, SearchCost + DOffset - 1, Tlo),
- array__lookup(Bwd0, SearchCost + DOffset + 1, Thi),
- ( Tlo < Thi ->
- X0 = Tlo
- ;
- X0 = Thi - 1
- ),
- Y0 = X0 - SearchCost,
- Constants = constants(_, FileX, FileY, Xlow, _, Ylow, _,
- _, _, _, _),
- myers__scan_backward(FileX, FileY, Xlow, Ylow, X0, X, Y0, Y),
- array__set(Bwd0, SearchCost + DOffset, X, Bwd1),
-
- Constants = constants(_, _, _, _, _, _, _, _, _, DeltaOdd, _),
- (
- DeltaOdd = no,
- Fmin =< SearchCost,
- SearchCost =< Fmax,
- array__lookup(Fwd0, SearchCost + DOffset, FF),
- X =< FF
- ->
- Mid = X - Y,
- Cost = 2 * Cost0,
- Fwd = Fwd0,
- Bwd = Bwd1,
- HeurReq = none - none
- ;
- myers__find_backward_reaching_path(Constants,
- Fwd0, Fwd, Bwd1, Bwd, Fmin, Fmax, Bmin, Bmax,
- SearchCost - 2, Cost0, Cost, Mid, HeurReq)
- )
- ).
-
-
- % Try applying some heuristics to see if we can avoid some work.
-:- pred myers__try_heuristics(myers_constants,
- array(int), array(int), array(int), array(int),
- int, int, int, int, int, int, pair(pos), pair(heur)).
-:- mode myers__try_heuristics(in, array_di, array_uo,
- array_di, array_uo, in, in, in, in, in, out, out, out) is det.
-
-myers__try_heuristics(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
- Constants = constants(_, _, _, _, _, _, _, _, _, _, Heur),
- (
- Heur = too_expensive(Cutoff),
- Cost0 >= Cutoff
- ->
- % If we've done too much work, stop here.
- Fwd = Fwd0, Bwd = Bwd0,
- myers__too_expensive_heuristic(Constants, Fwd, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq)
- ;
- % Can't apply heuristic, so try looking for a diff of size
- % Cost0 + 1.
-
- myers__find_middle_2(Constants, Fwd0, Fwd, Bwd0, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0 + 1, Cost, Mid, HeurReq)
- ).
+ % The best part about this algorithm is: We don't actually
+ % need to find the middle of the diff. We only have to find
+ % an estimate to it. If we don't find the exact middle,
+ % we will have a correct diff, but it won't necessarily be
+ % minimal.
+:- pred myers.find_middle(int::in, array(int)::in, array(int)::in, pos::in,
+ pos::in, pos::in, pos::in, heur::in, array(int)::array_di,
+ array(int)::array_uo, array(int)::array_di, array(int)::array_uo,
+ pos::out, pos::out, int::out, pair(heur)::out) is det.
+
+myers.find_middle(DOffset, FileX, FileY, Xlow, Xhigh, Ylow, Yhigh, Heur,
+ Fwd0, Fwd, Bwd0, Bwd, Xmid, Ymid, Cost, HeurReq) :-
+
+ Dmin = Xlow - Yhigh,
+ Dmax = Xhigh - Ylow,
+
+ Fmid = Xlow - Ylow,
+ array.set(Fwd0, Fmid + DOffset, Xlow, Fwd1),
+ Bmid = Xhigh - Yhigh,
+ array.set(Bwd0, Bmid + DOffset, Xhigh, Bwd1),
+
+ ( 1 = (Fmid - Bmid) /\ 1 ->
+ DeltaOdd = yes
+ ;
+ DeltaOdd = no
+ ),
+
+ Constants = constants(
+ DOffset, FileX, FileY, Xlow, Xhigh, Ylow, Yhigh,
+ Dmin, Dmax, DeltaOdd, Heur
+ ),
+
+ myers.find_middle_2(Constants, Fwd1, Fwd, Bwd1, Bwd,
+ Fmid, Fmid, Bmid, Bmid, 1, Cost, Xmid - Ymid, HeurReq).
+
+
+:- pred myers.find_middle_2(myers_constants::in,
+ array(int)::array_di, array(int)::array_uo,
+ array(int)::array_di, array(int)::array_uo,
+ int::in, int::in, int::in, int::in, int::in, int::out,
+ pair(pos)::out, pair(heur)::out) is det.
+
+myers.find_middle_2(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
+ Constants = constants(DOffset, _, _, _, _, _, _, Dmin, Dmax, _, _),
+ ( Fmin > Dmin ->
+ Fmin1 = Fmin - 1,
+ array.set(Fwd0, Fmin1 + DOffset - 1, -1, Fwd1)
+ ;
+ Fmin1 = Fmin + 1,
+ Fwd1 = Fwd0
+ ),
+ ( Fmax < Dmax ->
+ Fmax1 = Fmax + 1,
+ array.set(Fwd1, Fmax1 + DOffset + 1, -1, Fwd2)
+ ;
+ Fmax1 = Fmax - 1,
+ Fwd2 = Fwd1
+ ),
+ myers.find_forward_reaching_path(Constants, Fwd2, Fwd, Bwd0, Bwd,
+ Fmin1, Fmax1, Bmin, Bmax, Fmax1, Cost0, Cost, Mid, HeurReq).
+
+
+:- pred myers.find_forward_reaching_path(myers_constants::in,
+ array(int)::array_di, array(int)::array_uo,
+ array(int)::array_di, array(int)::array_uo,
+ int::in, int::in, int::in, int::in, int::in, int::in,
+ int::out, pair(pos)::out, pair(heur)::out) is det.
+
+myers.find_forward_reaching_path(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, SearchCost, Cost0, Cost, Mid,
+ HeurReq) :-
+ ( SearchCost < Fmin ->
+ Constants = constants(DOffset, _, _, _, _, _, _, Dmin, Dmax, _,
+ _),
+ int.max_int(MaxInt),
+ ( Bmin > Dmin ->
+ Bmin1 = Bmin - 1,
+ array.set(Bwd0, Bmin1 + DOffset - 1, MaxInt, Bwd1)
+ ;
+ Bmin1 = Bmin + 1,
+ Bwd1 = Bwd0
+ ),
+ ( Bmax < Dmax ->
+ Bmax1 = Bmax + 1,
+ array.set(Bwd1, Bmax1 + DOffset + 1, MaxInt, Bwd2)
+ ;
+ Bmax1 = Bmax - 1,
+ Bwd2 = Bwd1
+ ),
+ myers.find_backward_reaching_path(Constants,
+ Fwd0, Fwd, Bwd2, Bwd, Fmin, Fmax, Bmin1, Bmax1,
+ Bmax1, Cost0, Cost, Mid, HeurReq)
+ ;
+ Constants = constants(DOffset, _, _, _, _, _, _, _, _, _, _),
+ array.lookup(Fwd0, SearchCost + DOffset - 1, Tlo),
+ array.lookup(Fwd0, SearchCost + DOffset + 1, Thi),
+ ( Tlo >= Thi ->
+ X0 = Tlo + 1
+ ;
+ X0 = Thi
+ ),
+ Y0 = X0 - SearchCost,
+ Constants = constants(_, FileX, FileY, _, Xhigh, _, Yhigh,
+ _, _, _, _),
+ myers.scan_forward(FileX, FileY, Xhigh, Yhigh, X0, X, Y0, Y),
+ array.set(Fwd0, SearchCost + DOffset, X, Fwd1),
+
+ Constants = constants(_, _, _, _, _, _, _, _, _, DeltaOdd, _),
+ (
+ DeltaOdd = yes,
+ Bmin =< SearchCost,
+ SearchCost =< Bmax,
+ array.lookup(Bwd0, SearchCost + DOffset, BB),
+ BB =< X
+ ->
+ Mid = X - Y,
+ Cost = 2 * Cost0 + 1,
+ Fwd = Fwd1,
+ Bwd = Bwd0,
+ HeurReq = none - none
+ ;
+ myers.find_forward_reaching_path(Constants,
+ Fwd1, Fwd, Bwd0, Bwd, Fmin, Fmax, Bmin, Bmax,
+ SearchCost - 2, Cost0, Cost, Mid, HeurReq)
+ )
+ ).
+
+
+:- pred myers.find_backward_reaching_path(myers_constants::in,
+ array(int)::array_di, array(int)::array_uo,
+ array(int)::array_di, array(int)::array_uo,
+ int::in, int::in, int::in, int::in, int::in, int::in,
+ int::out, pair(pos)::out, pair(heur)::out) is det.
+
+myers.find_backward_reaching_path(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, SearchCost, Cost0, Cost, Mid,
+ HeurReq) :-
+ ( SearchCost < Bmin ->
+ myers.try_heuristics(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq)
+ ;
+ Constants = constants(DOffset, _, _, _, _, _, _, _, _, _, _),
+ array.lookup(Bwd0, SearchCost + DOffset - 1, Tlo),
+ array.lookup(Bwd0, SearchCost + DOffset + 1, Thi),
+ ( Tlo < Thi ->
+ X0 = Tlo
+ ;
+ X0 = Thi - 1
+ ),
+ Y0 = X0 - SearchCost,
+ Constants = constants(_, FileX, FileY, Xlow, _, Ylow, _,
+ _, _, _, _),
+ myers.scan_backward(FileX, FileY, Xlow, Ylow, X0, X, Y0, Y),
+ array.set(Bwd0, SearchCost + DOffset, X, Bwd1),
+
+ Constants = constants(_, _, _, _, _, _, _, _, _, DeltaOdd, _),
+ (
+ DeltaOdd = no,
+ Fmin =< SearchCost,
+ SearchCost =< Fmax,
+ array.lookup(Fwd0, SearchCost + DOffset, FF),
+ X =< FF
+ ->
+ Mid = X - Y,
+ Cost = 2 * Cost0,
+ Fwd = Fwd0,
+ Bwd = Bwd1,
+ HeurReq = none - none
+ ;
+ myers.find_backward_reaching_path(Constants,
+ Fwd0, Fwd, Bwd1, Bwd, Fmin, Fmax, Bmin, Bmax,
+ SearchCost - 2, Cost0, Cost, Mid, HeurReq)
+ )
+ ).
+
+
+ % Try applying some heuristics to see if we can avoid some work.
+:- pred myers.try_heuristics(myers_constants::in,
+ array(int)::array_di, array(int)::array_uo,
+ array(int)::array_di, array(int)::array_uo, int::in, int::in, int::in,
+ int::in, int::in, int::out, pair(pos)::out, pair(heur)::out) is det.
+
+myers.try_heuristics(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
+ Constants = constants(_, _, _, _, _, _, _, _, _, _, Heur),
+ (
+ Heur = too_expensive(Cutoff),
+ Cost0 >= Cutoff
+ ->
+ % If we've done too much work, stop here.
+ Fwd = Fwd0, Bwd = Bwd0,
+ myers.too_expensive_heuristic(Constants, Fwd, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq)
+ ;
+ % Can't apply heuristic, so try looking for a diff of size
+ % Cost0 + 1.
+
+ myers.find_middle_2(Constants, Fwd0, Fwd, Bwd0, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0 + 1, Cost, Mid, HeurReq)
+ ).
%-----------------------------------------------------------------------------%
- % We've done too much work, so make our best guess.
-:- pred myers__too_expensive_heuristic(myers_constants, array(int), array(int),
- int, int, int, int, int, int, pair(pos), pair(heur)).
-:- mode myers__too_expensive_heuristic(in, array_ui, array_ui,
- in, in, in, in, in, out, out, out) is det.
-
-myers__too_expensive_heuristic(Constants, Fwd, Bwd,
- Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
- % Find the best diagonal that we can, take the end of
- % that diagonal as the "middle". Do not apply the
- % heuristic recursively to that best diagonal.
-
- Constants = constants(DOffset, _, _, Xlow, Xhigh, Ylow, Yhigh,
- _, _, _, Heur),
-
- % Find the best forward diagonal.
- myers__find_best_forward_diagonal(Fmax, Fmin, Fwd,
- Xhigh, Yhigh, DOffset, -1, FXYBest, 0, FXBest),
-
- % Find the best backward diagonal.
- int__max_int(MaxInt),
- myers__find_best_backward_diagonal(Bmax, Bmin, Bwd,
- Xlow, Ylow, DOffset, MaxInt, BXYBest, 0, BXBest),
-
- % Choose which of these diagonals is the better one
- % and return that as the "middle" point.
- (
- FXYBest - (Xhigh + Yhigh) < (Xlow + Ylow) - BXYBest
- ->
- Xmid = FXBest,
- Ymid = FXYBest - FXBest,
- HeurReq = none - Heur
- ;
- Xmid = BXBest,
- Ymid = BXYBest - BXBest,
- HeurReq = Heur - none
- ),
- Mid = Xmid - Ymid,
- Cost = 2 * Cost0 - 1.
-
-:- pred myers__find_best_forward_diagonal(int, int, array(int), int, int, int,
- int, int, int, int).
-:- mode myers__find_best_forward_diagonal(in, in, array_ui, in, in, in,
- in, out, in, out) is det.
-
-myers__find_best_forward_diagonal(D, Fmin, Fwd, Xhigh, Yhigh, DOffset,
- FXYBest0, FXYBest, FXBest0, FXBest) :-
- ( D < Fmin ->
- FXYBest = FXYBest0,
- FXBest = FXBest0
- ;
- array__lookup(Fwd, D + DOffset, X0),
- int__min(Xhigh, X0, X1),
- Y0 = X1 - D,
-
- ( Yhigh < Y0 ->
- X = Yhigh + D,
- Y = Yhigh
- ;
- X = X1,
- Y = Y0
- ),
-
- NewFXY = X + Y,
- ( FXYBest0 < NewFXY ->
- myers__find_best_forward_diagonal(D - 2, Fmin, Fwd,
- Xhigh, Yhigh, DOffset, NewFXY, FXYBest,
- X, FXBest)
- ;
- myers__find_best_forward_diagonal(D - 2, Fmin, Fwd,
- Xhigh, Yhigh, DOffset, FXYBest0, FXYBest,
- FXBest0, FXBest)
- )
- ).
-
-:- pred myers__find_best_backward_diagonal(int, int, array(int), int, int, int,
- int, int, int, int).
-:- mode myers__find_best_backward_diagonal(in, in, array_ui, in, in, in,
- in, out, in, out) is det.
-
-myers__find_best_backward_diagonal(D, Bmin, Bwd, Xlow, Ylow, DOffset,
- BXYBest0, BXYBest, BXBest0, BXBest) :-
- ( D < Bmin ->
- BXYBest = BXYBest0,
- BXBest = BXBest0
- ;
- array__lookup(Bwd, D + DOffset, X0),
- int__max(Xlow, X0, X1),
- Y0 = X1 - D,
-
- ( Y0 < Ylow ->
- X = Ylow + D,
- Y = Ylow
- ;
- X = X1,
- Y = Y0
- ),
-
- NewBXY = X + Y,
- ( NewBXY < BXYBest0 ->
- myers__find_best_backward_diagonal(D - 2, Bmin, Bwd,
- Xlow, Ylow, DOffset, NewBXY, BXYBest,
- X, BXBest)
- ;
- myers__find_best_backward_diagonal(D - 2, Bmin, Bwd,
- Xlow, Ylow, DOffset, BXYBest0, BXYBest,
- BXBest0, BXBest)
- )
- ).
+ % We've done too much work, so make our best guess.
+:- pred myers.too_expensive_heuristic(myers_constants::in,
+ array(int)::array_ui, array(int)::array_ui, int::in, int::in, int::in,
+ int::in, int::in, int::out, pair(pos)::out, pair(heur)::out) is det.
+
+myers.too_expensive_heuristic(Constants, Fwd, Bwd,
+ Fmin, Fmax, Bmin, Bmax, Cost0, Cost, Mid, HeurReq) :-
+ % Find the best diagonal that we can, take the end of
+ % that diagonal as the "middle". Do not apply the
+ % heuristic recursively to that best diagonal.
+
+ Constants = constants(DOffset, _, _, Xlow, Xhigh, Ylow, Yhigh,
+ _, _, _, Heur),
+
+ % Find the best forward diagonal.
+ myers.find_best_forward_diagonal(Fmax, Fmin, Fwd,
+ Xhigh, Yhigh, DOffset, -1, FXYBest, 0, FXBest),
+
+ % Find the best backward diagonal.
+ int.max_int(MaxInt),
+ myers.find_best_backward_diagonal(Bmax, Bmin, Bwd,
+ Xlow, Ylow, DOffset, MaxInt, BXYBest, 0, BXBest),
+
+ % Choose which of these diagonals is the better one
+ % and return that as the "middle" point.
+ (
+ FXYBest - (Xhigh + Yhigh) < (Xlow + Ylow) - BXYBest
+ ->
+ Xmid = FXBest,
+ Ymid = FXYBest - FXBest,
+ HeurReq = none - Heur
+ ;
+ Xmid = BXBest,
+ Ymid = BXYBest - BXBest,
+ HeurReq = Heur - none
+ ),
+ Mid = Xmid - Ymid,
+ Cost = 2 * Cost0 - 1.
+
+:- pred myers.find_best_forward_diagonal(int::in, int::in,
+ array(int)::array_ui, int::in, int::in, int::in, int::in, int::out,
+ int::in, int::out) is det.
+
+myers.find_best_forward_diagonal(D, Fmin, Fwd, Xhigh, Yhigh, DOffset,
+ FXYBest0, FXYBest, FXBest0, FXBest) :-
+ ( D < Fmin ->
+ FXYBest = FXYBest0,
+ FXBest = FXBest0
+ ;
+ array.lookup(Fwd, D + DOffset, X0),
+ int.min(Xhigh, X0, X1),
+ Y0 = X1 - D,
+
+ ( Yhigh < Y0 ->
+ X = Yhigh + D,
+ Y = Yhigh
+ ;
+ X = X1,
+ Y = Y0
+ ),
+
+ NewFXY = X + Y,
+ ( FXYBest0 < NewFXY ->
+ myers.find_best_forward_diagonal(D - 2, Fmin, Fwd,
+ Xhigh, Yhigh, DOffset, NewFXY, FXYBest,
+ X, FXBest)
+ ;
+ myers.find_best_forward_diagonal(D - 2, Fmin, Fwd,
+ Xhigh, Yhigh, DOffset, FXYBest0, FXYBest,
+ FXBest0, FXBest)
+ )
+ ).
+
+:- pred myers.find_best_backward_diagonal(int::in, int::in,
+ array(int)::array_ui, int::in, int::in, int::in, int::in, int::out,
+ int::in, int::out) is det.
+
+myers.find_best_backward_diagonal(D, Bmin, Bwd, Xlow, Ylow, DOffset,
+ BXYBest0, BXYBest, BXBest0, BXBest) :-
+ ( D < Bmin ->
+ BXYBest = BXYBest0,
+ BXBest = BXBest0
+ ;
+ array.lookup(Bwd, D + DOffset, X0),
+ int.max(Xlow, X0, X1),
+ Y0 = X1 - D,
+
+ ( Y0 < Ylow ->
+ X = Ylow + D,
+ Y = Ylow
+ ;
+ X = X1,
+ Y = Y0
+ ),
+
+ NewBXY = X + Y,
+ ( NewBXY < BXYBest0 ->
+ myers.find_best_backward_diagonal(D - 2, Bmin, Bwd,
+ Xlow, Ylow, DOffset, NewBXY, BXYBest,
+ X, BXBest)
+ ;
+ myers.find_best_backward_diagonal(D - 2, Bmin, Bwd,
+ Xlow, Ylow, DOffset, BXYBest0, BXYBest,
+ BXBest0, BXBest)
+ )
+ ).
%-----------------------------------------------------------------------------%
- % Travel forwards along a snake.
-:- pred myers__scan_forward(array(int), array(int), int, int,
- int, int, int, int).
-:- mode myers__scan_forward(in, in, in, in, in, out, in, out) is det.
-
-myers__scan_forward(FileX, FileY, Xhigh, Yhigh, Xlow0, Xlow, Ylow0, Ylow) :-
- (
- Xlow0 < Xhigh,
- Ylow0 < Yhigh,
- array__lookup(FileX, Xlow0, Line),
- array__lookup(FileY, Ylow0, Line)
- ->
- myers__scan_forward(FileX, FileY, Xhigh, Yhigh,
- Xlow0 + 1, Xlow, Ylow0 + 1, Ylow)
- ;
- Xlow = Xlow0, Ylow = Ylow0
- ).
-
-
- % Travel backwards along a snake.
-:- pred myers__scan_backward(array(int), array(int), int, int,
- int, int, int, int).
-:- mode myers__scan_backward(in, in, in, in, in, out, in, out) is det.
-
-myers__scan_backward(FileX, FileY, Xlow, Ylow, Xhigh0, Xhigh, Yhigh0, Yhigh) :-
- (
- Xhigh0 > Xlow,
- Yhigh0 > Ylow,
- array__lookup(FileX, Xhigh0 - 1, Line),
- array__lookup(FileY, Yhigh0 - 1, Line)
- ->
- myers__scan_backward(FileX, FileY, Xlow, Ylow,
- Xhigh0 - 1, Xhigh, Yhigh0 - 1, Yhigh)
- ;
- Xhigh = Xhigh0, Yhigh = Yhigh0
- ).
+ % Travel forwards along a snake.
+:- pred myers.scan_forward(array(int)::in, array(int)::in, int::in, int::in,
+ int::in, int::out, int::in, int::out) is det.
+
+myers.scan_forward(FileX, FileY, Xhigh, Yhigh, Xlow0, Xlow, Ylow0, Ylow) :-
+ (
+ Xlow0 < Xhigh,
+ Ylow0 < Yhigh,
+ array.lookup(FileX, Xlow0, Line),
+ array.lookup(FileY, Ylow0, Line)
+ ->
+ myers.scan_forward(FileX, FileY, Xhigh, Yhigh,
+ Xlow0 + 1, Xlow, Ylow0 + 1, Ylow)
+ ;
+ Xlow = Xlow0, Ylow = Ylow0
+ ).
+
+
+ % Travel backwards along a snake.
+:- pred myers.scan_backward(array(int)::in, array(int)::in, int::in, int::in,
+ int::in, int::out, int::in, int::out) is det.
+
+myers.scan_backward(FileX, FileY, Xlow, Ylow, Xhigh0, Xhigh, Yhigh0, Yhigh) :-
+ (
+ Xhigh0 > Xlow,
+ Yhigh0 > Ylow,
+ array.lookup(FileX, Xhigh0 - 1, Line),
+ array.lookup(FileY, Yhigh0 - 1, Line)
+ ->
+ myers.scan_backward(FileX, FileY, Xlow, Ylow,
+ Xhigh0 - 1, Xhigh, Yhigh0 - 1, Yhigh)
+ ;
+ Xhigh = Xhigh0, Yhigh = Yhigh0
+ ).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/diff/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/diff/options.m,v
retrieving revision 1.2
diff -u -r1.2 options.m
--- samples/diff/options.m 15 Sep 1998 04:54:41 -0000 1.2
+++ samples/diff/options.m 24 Apr 2006 05:48:16 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1998 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -16,95 +18,95 @@
%-----------------------------------------------------------------------------%
-:- pred options__get_option_ops(option_ops(option) :: out(option_ops)) is det.
+:- pred options.get_option_ops(option_ops(option) :: out(option_ops)) is det.
- % Process the option table, perhaps returning an error message
- % if there was some inconsistentcy or other error.
+ % Process the option table, perhaps returning an error message
+ % if there was some inconsistentcy or other error.
:- pred postprocess_options(maybe_option_table :: in, maybe(string) :: out,
- io__state::di, io__state::uo) is det.
+ io.state::di, io.state::uo) is det.
%-----------------------------------------------------------------------------%
- % Info on the accepted options, displayed in response to --help.
-:- pred options_help(io__state::di, io__state::uo) is det.
+ % Info on the accepted options, displayed in response to --help.
+:- pred options_help(io.state::di, io.state::uo) is det.
%-----------------------------------------------------------------------------%
-:- type option_table == option_table(option).
-:- type maybe_option_table == maybe_option_table(option).
+:- type option_table == option_table(option).
+:- type maybe_option_table == maybe_option_table(option).
- % The master list of options.
+ % The master list of options.
:- type option --->
- % Output styles
- help
- ; version
- ; context
- ; context_style_output
- ; unified
- ; unified_style_output
- ; ed
- ; forward_ed
- ; rcs
- ; brief
- ; ifdef
- ; side_by_side
- ; cvs_merge_conflict
-
- % Output options
- ; show_c_function % Not handled (and unlikely to be soon)
- ; show_function_line % Not handled (and unlikely to be soon)
- ; label
- ; width
- ; expand_tabs
- ; initial_tab
- ; paginate % Not handled (and unlikely to be soon)
- ; left_column
- ; suppress_common_lines
- ; sdiff_merge_assist % Accepted but ignored
-
- % Matching options
- ; new_file % Not handled (and unlikely to be soon)
- ; unidirectional_new_file % Not handled (and unlikely to be soon)
- ; ignore_case
- ; ignore_all_space
- ; ignore_space_change
-
- % Diff options
- ; minimal
- ; speed_large_files % Accepted but ignored
- ; file_split_speed_hack % Accepted but ignored (GNU diff
- % ignores this too, so let's not
- % feel too bad about it)
-
- % Change filter options
- ; ignore_matching_lines % Not handled (and unlikely to be soon)
- ; ignore_blank_lines
-
- % Directory comparison options
- % None of these are likely to be handled in the near future.
- ; starting_file % Not handled
- ; recursive % Not handled
- ; report_identical_files % Not handled
- ; exclude % Not handled
- ; exclude_from % Not handled
-
- % #ifdef format options
- % None of these are likely to be handled in the very near future.
- ; old_line_format % Not handled
- ; new_line_format % Not handled
- ; unchanged_line_format % Not handled
- ; line_format % Not handled
- ; old_group_format % Not handled
- ; new_group_format % Not handled
- ; unchanged_group_format % Not handled
- ; changed_group_format % Not handled
- ; horizon_lines % Not handled
-
- % File input options
- % Neither of these are likely to be handled in the near future.
- ; text % Not handled
- ; binary. % Not handled
+ % Output styles
+ help
+ ; version
+ ; context
+ ; context_style_output
+ ; unified
+ ; unified_style_output
+ ; ed
+ ; forward_ed
+ ; rcs
+ ; brief
+ ; ifdef
+ ; side_by_side
+ ; cvs_merge_conflict
+
+ % Output options
+ ; show_c_function % Not handled (and unlikely to be soon)
+ ; show_function_line % Not handled (and unlikely to be soon)
+ ; label
+ ; width
+ ; expand_tabs
+ ; initial_tab
+ ; paginate % Not handled (and unlikely to be soon)
+ ; left_column
+ ; suppress_common_lines
+ ; sdiff_merge_assist % Accepted but ignored
+
+ % Matching options
+ ; new_file % Not handled (and unlikely to be soon)
+ ; unidirectional_new_file % Not handled (and unlikely to be soon)
+ ; ignore_case
+ ; ignore_all_space
+ ; ignore_space_change
+
+ % Diff options
+ ; minimal
+ ; speed_large_files % Accepted but ignored
+ ; file_split_speed_hack % Accepted but ignored (GNU diff
+ % ignores this too, so let's not
+ % feel too bad about it)
+
+ % Change filter options
+ ; ignore_matching_lines % Not handled (and unlikely to be soon)
+ ; ignore_blank_lines
+
+ % Directory comparison options
+ % None of these are likely to be handled in the near future.
+ ; starting_file % Not handled
+ ; recursive % Not handled
+ ; report_identical_files % Not handled
+ ; exclude % Not handled
+ ; exclude_from % Not handled
+
+ % #ifdef format options
+ % None of these are likely to be handled in the very near future.
+ ; old_line_format % Not handled
+ ; new_line_format % Not handled
+ ; unchanged_line_format % Not handled
+ ; line_format % Not handled
+ ; old_group_format % Not handled
+ ; new_group_format % Not handled
+ ; unchanged_group_format % Not handled
+ ; changed_group_format % Not handled
+ ; horizon_lines % Not handled
+
+ % File input options
+ % Neither of these are likely to be handled in the near future.
+ ; text % Not handled
+ ; binary. % Not handled
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -114,56 +116,56 @@
:- import_module list, int, bool, string, map, require.
:- pred long_option(string::in, option::out) is semidet.
-long_option("ignore-blank-lines", ignore_blank_lines).
-long_option("context", context).
-long_option("ifdef", ifdef).
-long_option("show-function-line", show_function_line).
-long_option("speed-large-files", speed_large_files).
-long_option("ignore-matching-lines", ignore_matching_lines).
-long_option("file-label", label).
-long_option("label", label).
-long_option("new-file", new_file).
-long_option("entire-new-file", new_file).
-long_option("unidirectional-new-file", unidirectional_new_file).
-long_option("starting-file", starting_file).
-long_option("initial-tab", initial_tab).
-long_option("unified", unified).
-long_option("width", width).
-long_option("exclude-from", exclude_from).
-long_option("text", text).
-long_option("ascii", text).
-long_option("ignore-space-change", ignore_space_change).
-long_option("minimal", minimal).
-long_option("ed", ed).
-long_option("forward-ed", forward_ed).
-long_option("ignore-case", ignore_case).
-long_option("paginate", paginate).
-long_option("print", paginate).
-long_option("rcs", rcs).
-long_option("show-c-function", show_c_function).
-long_option("brief", brief).
-long_option("recursive", recursive).
-long_option("report-identical-files", report_identical_files).
-long_option("expand-tabs", expand_tabs).
-long_option("version", version).
-long_option("ignore-all-space", ignore_all_space).
-long_option("exclude", exclude).
-long_option("side-by-side", side_by_side).
-long_option("cvs-merge-conflict", cvs_merge_conflict).
-long_option("left-column", left_column).
-long_option("suppress-common-lines", suppress_common_lines).
-long_option("sdiff-merge-assist", sdiff_merge_assist).
-long_option("old-line-format", old_line_format).
-long_option("new-line-format", new_line_format).
-long_option("unchanged-line-format", unchanged_line_format).
-long_option("line-format", line_format).
-long_option("old-group-format", old_group_format).
-long_option("new-group-format", new_group_format).
-long_option("unchanged-group-format", unchanged_group_format).
-long_option("changed-group-format", changed_group_format).
-long_option("horizon-lines", horizon_lines).
-long_option("help", help).
-long_option("binary", binary).
+long_option("ignore-blank-lines", ignore_blank_lines).
+long_option("context", context).
+long_option("ifdef", ifdef).
+long_option("show-function-line", show_function_line).
+long_option("speed-large-files", speed_large_files).
+long_option("ignore-matching-lines", ignore_matching_lines).
+long_option("file-label", label).
+long_option("label", label).
+long_option("new-file", new_file).
+long_option("entire-new-file", new_file).
+long_option("unidirectional-new-file", unidirectional_new_file).
+long_option("starting-file", starting_file).
+long_option("initial-tab", initial_tab).
+long_option("unified", unified).
+long_option("width", width).
+long_option("exclude-from", exclude_from).
+long_option("text", text).
+long_option("ascii", text).
+long_option("ignore-space-change", ignore_space_change).
+long_option("minimal", minimal).
+long_option("ed", ed).
+long_option("forward-ed", forward_ed).
+long_option("ignore-case", ignore_case).
+long_option("paginate", paginate).
+long_option("print", paginate).
+long_option("rcs", rcs).
+long_option("show-c-function", show_c_function).
+long_option("brief", brief).
+long_option("recursive", recursive).
+long_option("report-identical-files", report_identical_files).
+long_option("expand-tabs", expand_tabs).
+long_option("version", version).
+long_option("ignore-all-space", ignore_all_space).
+long_option("exclude", exclude).
+long_option("side-by-side", side_by_side).
+long_option("cvs-merge-conflict", cvs_merge_conflict).
+long_option("left-column", left_column).
+long_option("suppress-common-lines", suppress_common_lines).
+long_option("sdiff-merge-assist", sdiff_merge_assist).
+long_option("old-line-format", old_line_format).
+long_option("new-line-format", new_line_format).
+long_option("unchanged-line-format", unchanged_line_format).
+long_option("line-format", line_format).
+long_option("old-group-format", old_group_format).
+long_option("new-group-format", new_group_format).
+long_option("unchanged-group-format", unchanged_group_format).
+long_option("changed-group-format", changed_group_format).
+long_option("horizon-lines", horizon_lines).
+long_option("help", help).
+long_option("binary", binary).
%-----------------------------------------------------------------------------%
@@ -207,262 +209,260 @@
:- pred option_defaults(option :: out, option_data :: out) is nondet.
- % Output styles
-option_defaults(help, bool(no)).
-option_defaults(version, bool(no)).
-option_defaults(context, maybe_int(no)).
-option_defaults(context_style_output, bool_special).
-option_defaults(unified, maybe_int(no)).
-option_defaults(unified_style_output, bool_special).
-option_defaults(ed, bool(no)).
-option_defaults(forward_ed, bool(no)).
-option_defaults(rcs, bool(no)).
-option_defaults(brief, bool(no)).
-option_defaults(ifdef, maybe_string(no)).
-option_defaults(side_by_side, bool(no)).
-option_defaults(cvs_merge_conflict, bool(no)).
-
- % Output options
-option_defaults(show_c_function, bool_special).
-option_defaults(show_function_line, string_special).
-option_defaults(label, accumulating([])).
-option_defaults(width, int(130)).
-option_defaults(expand_tabs, bool(no)).
-option_defaults(initial_tab, bool(no)).
-option_defaults(paginate, bool_special).
-option_defaults(left_column, bool(no)).
-option_defaults(suppress_common_lines, bool(no)).
-option_defaults(sdiff_merge_assist, bool(no)).
-
- % Matching options
-option_defaults(new_file, bool_special).
-option_defaults(unidirectional_new_file, bool_special).
-option_defaults(ignore_case, bool(no)).
-option_defaults(ignore_all_space, bool(no)).
-option_defaults(ignore_space_change, bool(no)).
-
- % Diff options
-option_defaults(minimal, bool(no)).
-option_defaults(speed_large_files, bool(no)).
-option_defaults(file_split_speed_hack, bool(no)).
-
- % Change filter options
-option_defaults(ignore_matching_lines, string_special).
-option_defaults(ignore_blank_lines, bool(no)).
-
- % Directory comparison options (none of these are handled)
-option_defaults(starting_file, string_special).
-option_defaults(recursive, bool_special).
-option_defaults(report_identical_files, bool_special).
-option_defaults(exclude, string_special).
-option_defaults(exclude_from, string_special).
-
- % Format options (none of these are handled)
-option_defaults(old_line_format, string_special).
-option_defaults(new_line_format, string_special).
-option_defaults(unchanged_line_format, string_special).
-option_defaults(line_format, string_special).
-option_defaults(old_group_format, string_special).
-option_defaults(new_group_format, string_special).
-option_defaults(unchanged_group_format, string_special).
-option_defaults(changed_group_format, string_special).
-option_defaults(horizon_lines, int_special).
-
- % File input options (none of these are handled)
-option_defaults(text, bool_special).
-option_defaults(binary, bool_special).
+ % Output styles
+option_defaults(help, bool(no)).
+option_defaults(version, bool(no)).
+option_defaults(context, maybe_int(no)).
+option_defaults(context_style_output, bool_special).
+option_defaults(unified, maybe_int(no)).
+option_defaults(unified_style_output, bool_special).
+option_defaults(ed, bool(no)).
+option_defaults(forward_ed, bool(no)).
+option_defaults(rcs, bool(no)).
+option_defaults(brief, bool(no)).
+option_defaults(ifdef, maybe_string(no)).
+option_defaults(side_by_side, bool(no)).
+option_defaults(cvs_merge_conflict, bool(no)).
+
+ % Output options
+option_defaults(show_c_function, bool_special).
+option_defaults(show_function_line, string_special).
+option_defaults(label, accumulating([])).
+option_defaults(width, int(130)).
+option_defaults(expand_tabs, bool(no)).
+option_defaults(initial_tab, bool(no)).
+option_defaults(paginate, bool_special).
+option_defaults(left_column, bool(no)).
+option_defaults(suppress_common_lines, bool(no)).
+option_defaults(sdiff_merge_assist, bool(no)).
+
+ % Matching options
+option_defaults(new_file, bool_special).
+option_defaults(unidirectional_new_file, bool_special).
+option_defaults(ignore_case, bool(no)).
+option_defaults(ignore_all_space, bool(no)).
+option_defaults(ignore_space_change, bool(no)).
+
+ % Diff options
+option_defaults(minimal, bool(no)).
+option_defaults(speed_large_files, bool(no)).
+option_defaults(file_split_speed_hack, bool(no)).
+
+ % Change filter options
+option_defaults(ignore_matching_lines, string_special).
+option_defaults(ignore_blank_lines, bool(no)).
+
+ % Directory comparison options (none of these are handled)
+option_defaults(starting_file, string_special).
+option_defaults(recursive, bool_special).
+option_defaults(report_identical_files, bool_special).
+option_defaults(exclude, string_special).
+option_defaults(exclude_from, string_special).
+
+ % Format options (none of these are handled)
+option_defaults(old_line_format, string_special).
+option_defaults(new_line_format, string_special).
+option_defaults(unchanged_line_format, string_special).
+option_defaults(line_format, string_special).
+option_defaults(old_group_format, string_special).
+option_defaults(new_group_format, string_special).
+option_defaults(unchanged_group_format, string_special).
+option_defaults(changed_group_format, string_special).
+option_defaults(horizon_lines, int_special).
+
+ % File input options (none of these are handled)
+option_defaults(text, bool_special).
+option_defaults(binary, bool_special).
%-----------------------------------------------------------------------------%
:- pred special_handler(option :: in, special_data :: in, option_table :: in,
- maybe_option_table :: out) is semidet.
+ maybe_option_table :: out) is semidet.
special_handler(context_style_output, bool(yes), Options0, ok(Options)) :-
- map__lookup(Options0, context, maybe_int(Context0)),
- ( Context0 = no,
- Context = yes(3)
- ; Context0 = yes(C),
- Context = yes(C)
- ),
- map__set(Options0, context, maybe_int(Context), Options).
+ map.lookup(Options0, context, maybe_int(Context0)),
+ ( Context0 = no,
+ Context = yes(3)
+ ; Context0 = yes(C),
+ Context = yes(C)
+ ),
+ map.set(Options0, context, maybe_int(Context), Options).
special_handler(unified_style_output, bool(yes), Options0, ok(Options)) :-
- map__lookup(Options0, unified, maybe_int(Unified0)),
- ( Unified0 = no,
- Unified = yes(3)
- ; Unified0 = yes(C),
- Unified = yes(C)
- ),
- map__set(Options0, unified, maybe_int(Unified), Options).
+ map.lookup(Options0, unified, maybe_int(Unified0)),
+ ( Unified0 = no,
+ Unified = yes(3)
+ ; Unified0 = yes(C),
+ Unified = yes(C)
+ ),
+ map.set(Options0, unified, maybe_int(Unified), Options).
- % Special handlers for unhandled options
+ % Special handlers for unhandled options
special_handler(show_c_function, _, _, error(Msg)) :-
- Msg = "Option not handled: --show-c-function".
+ Msg = "Option not handled: --show-c-function".
special_handler(show_function_line, _, _, error(Msg)) :-
- Msg = "Option not handled: --show-function-line".
+ Msg = "Option not handled: --show-function-line".
special_handler(paginate, _, _, error(Msg)) :-
- Msg = "Option not handled: --paginate".
+ Msg = "Option not handled: --paginate".
special_handler(sdiff_merge_assist, _, _, error(Msg)) :-
- Msg = "Option not handled: --sdiff-merge-assist".
+ Msg = "Option not handled: --sdiff-merge-assist".
special_handler(new_file, _, _, error(Msg)) :-
- Msg = "Option not handled: --new-file".
+ Msg = "Option not handled: --new-file".
special_handler(unidirectional_new_file, _, _, error(Msg)) :-
- Msg = "Option not handled: --unidirectional-new-file".
+ Msg = "Option not handled: --unidirectional-new-file".
special_handler(speed_large_files, _, _, error(Msg)) :-
- Msg = "Option not handled: --speed-large-files".
+ Msg = "Option not handled: --speed-large-files".
special_handler(ignore_matching_lines, _, _, error(Msg)) :-
- Msg = "Option not handled: --ignore-matching-lines".
+ Msg = "Option not handled: --ignore-matching-lines".
special_handler(ignore_blank_lines, _, _, error(Msg)) :-
- Msg = "Option not handled: --ignore-blank-lines".
+ Msg = "Option not handled: --ignore-blank-lines".
special_handler(starting_file, _, _, error(Msg)) :-
- Msg = "Option not handled: --starting-file".
+ Msg = "Option not handled: --starting-file".
special_handler(recursive, _, _, error(Msg)) :-
- Msg = "Option not handled: --recursive".
+ Msg = "Option not handled: --recursive".
special_handler(report_identical_files, _, _, error(Msg)) :-
- Msg = "Option not handled: --report-identical-files".
+ Msg = "Option not handled: --report-identical-files".
special_handler(exclude, _, _, error(Msg)) :-
- Msg = "Option not handled: --exclude".
+ Msg = "Option not handled: --exclude".
special_handler(exclude_from, _, _, error(Msg)) :-
- Msg = "Option not handled: --exclude-from".
+ Msg = "Option not handled: --exclude-from".
special_handler(old_line_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --old-line-format".
+ Msg = "Option not handled: --old-line-format".
special_handler(new_line_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --new-line-format".
+ Msg = "Option not handled: --new-line-format".
special_handler(unchanged_line_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --unchangedline-format".
+ Msg = "Option not handled: --unchangedline-format".
special_handler(line_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --line-format".
+ Msg = "Option not handled: --line-format".
special_handler(old_group_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --old-group-format".
+ Msg = "Option not handled: --old-group-format".
special_handler(new_group_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --new-group-format".
+ Msg = "Option not handled: --new-group-format".
special_handler(unchanged_group_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --unchanged-group-format".
+ Msg = "Option not handled: --unchanged-group-format".
special_handler(changed_group_format, _, _, error(Msg)) :-
- Msg = "Option not handled: --changed-group-format".
+ Msg = "Option not handled: --changed-group-format".
special_handler(horizon_lines, _, _, error(Msg)) :-
- Msg = "Option not handled: --horizon-lines".
+ Msg = "Option not handled: --horizon-lines".
special_handler(text, _, _, error(Msg)) :-
- Msg = "Option not handled: --text".
+ Msg = "Option not handled: --text".
special_handler(binary, _, _, error(Msg)) :-
- Msg = "Option not handled: --binary".
+ Msg = "Option not handled: --binary".
%-----------------------------------------------------------------------------%
-options__get_option_ops(OptionOps) :-
- OptionOps = option_ops(
- short_option,
- long_option,
- option_defaults,
- special_handler
- ).
+options.get_option_ops(OptionOps) :-
+ OptionOps = option_ops(
+ short_option,
+ long_option,
+ option_defaults,
+ special_handler
+ ).
%-----------------------------------------------------------------------------%
- % Postprocess the options
-postprocess_options(ok(OptionTable0), Result) -->
- ( { postprocess_output_style(OptionTable0, OutputStyle) } ->
- globals__io_init(OptionTable0),
- globals__io_set_output_style(OutputStyle),
- { Result = no }
- ;
- { Result = yes("Can't set more than one output style.") }
- ).
-postprocess_options(error(Msg), yes(Msg)) --> [].
+ % Postprocess the options
+postprocess_options(ok(OptionTable0), Result, !IO) :-
+ ( postprocess_output_style(OptionTable0, OutputStyle) ->
+ globals.io_init(OptionTable0, !IO),
+ globals.io_set_output_style(OutputStyle, !IO),
+ Result = no
+ ;
+ Result = yes("Can't set more than one output style.")
+ ).
+postprocess_options(error(Msg), yes(Msg), !IO).
- % Determine which output style to use from the provided
- % options.
+ % Determine which output style to use from the provided
+ % options.
:- pred postprocess_output_style(option_table :: in,
- diff_out__output_style :: out) is semidet.
+ diff_out.output_style :: out) is semidet.
postprocess_output_style(OptionTable, Style) :-
- (
- map__search(OptionTable, help, bool(UseHelp)),
- map__search(OptionTable, version, bool(UseVersion)),
- map__search(OptionTable, context, maybe_int(UseContext)),
- map__search(OptionTable, unified, maybe_int(UseUnified)),
- map__search(OptionTable, ed, bool(UseEd)),
- map__search(OptionTable, forward_ed, bool(UseForwardEd)),
- map__search(OptionTable, rcs, bool(UseRCS)),
- map__search(OptionTable, brief, bool(UseBrief)),
- map__search(OptionTable, ifdef, maybe_string(UseIfdef)),
- map__search(OptionTable, side_by_side, bool(UseSideBySide)),
- map__search(OptionTable, cvs_merge_conflict, bool(CVS))
- ->
- postprocess_output_style_2(UseHelp, UseVersion, UseContext,
- UseUnified, UseEd, UseForwardEd, UseRCS, UseBrief,
- UseIfdef, UseSideBySide, CVS,
- Style)
- ;
- error("postprocess_output_style")
- ).
-
-:- pred postprocess_output_style_2(bool, bool, maybe(int), maybe(int), bool,
- bool, bool, bool, maybe(string), bool, bool,
- diff_out__output_style).
-:- mode postprocess_output_style_2(in, in, in, in, in, in, in, in, in, in, in,
- out) is semidet.
-
+ (
+ map.search(OptionTable, help, bool(UseHelp)),
+ map.search(OptionTable, version, bool(UseVersion)),
+ map.search(OptionTable, context, maybe_int(UseContext)),
+ map.search(OptionTable, unified, maybe_int(UseUnified)),
+ map.search(OptionTable, ed, bool(UseEd)),
+ map.search(OptionTable, forward_ed, bool(UseForwardEd)),
+ map.search(OptionTable, rcs, bool(UseRCS)),
+ map.search(OptionTable, brief, bool(UseBrief)),
+ map.search(OptionTable, ifdef, maybe_string(UseIfdef)),
+ map.search(OptionTable, side_by_side, bool(UseSideBySide)),
+ map.search(OptionTable, cvs_merge_conflict, bool(CVS))
+ ->
+ postprocess_output_style_2(UseHelp, UseVersion, UseContext,
+ UseUnified, UseEd, UseForwardEd, UseRCS, UseBrief,
+ UseIfdef, UseSideBySide, CVS,
+ Style)
+ ;
+ error("postprocess_output_style")
+ ).
+
+:- pred postprocess_output_style_2(bool::in, bool::in, maybe(int)::in,
+ maybe(int)::in, bool::in, bool::in, bool::in, bool::in,
+ maybe(string)::in, bool::in, bool::in,
+ diff_out.output_style::out) is semidet.
postprocess_output_style_2(no, no, no, no, no, no, no, no, no, no, no,
- normal).
+ normal).
postprocess_output_style_2(yes, no, no, no, no, no, no, no, no, no, no,
- help_only).
+ help_only).
postprocess_output_style_2(no, yes, no, no, no, no, no, no, no, no, no,
- version_only).
+ version_only).
postprocess_output_style_2(no, no, yes(C), no, no, no, no, no, no, no, no,
- context(C)).
+ context(C)).
postprocess_output_style_2(no, no, no, yes(U), no, no, no, no, no, no, no,
- unified(U)).
+ unified(U)).
postprocess_output_style_2(no, no, no, no, yes, no, no, no, no, no, no,
- ed).
+ ed).
postprocess_output_style_2(no, no, no, no, no, yes, no, no, no, no, no,
- forward_ed).
+ forward_ed).
postprocess_output_style_2(no, no, no, no, no, no, yes, no, no, no, no,
- rcs).
+ rcs).
postprocess_output_style_2(no, no, no, no, no, no, no, yes, no, no, no,
- brief).
+ brief).
postprocess_output_style_2(no, no, no, no, no, no, no, no, yes(Sym), no, no,
- ifdef(Sym)).
+ ifdef(Sym)).
postprocess_output_style_2(no, no, no, no, no, no, no, no, no, yes, no,
- side_by_side).
+ side_by_side).
postprocess_output_style_2(no, no, no, no, no, no, no, no, no, no, yes,
- cvs_merge_conflict).
+ cvs_merge_conflict).
%-----------------------------------------------------------------------------%
- % Help text for the options.
-options_help -->
- io__write_string("Output styles:\n"),
- io__write_string("\t--help\n"),
- io__write_string("\t\tOutput this help.\n"),
- io__write_string("\t-v, --version\n"),
- io__write_string("\t\tOutput version info.\n"),
- io__write_string("\t-c, -C <num>, --context <num>\n"),
- io__write_string("\t\tOutput <num> (default 2) lines of copied context.\n"),
- io__write_string("\t-u, -U <num>, --unified <num>\n"),
- io__write_string("\t\tOutput <num> (default 2) lines of unified context.\n"),
- io__write_string("\t\t-L <label>, --label <label> Use <label>
instead of file name.\n"),
- io__write_string("\t-e, --ed\n"),
- io__write_string("\t\tOutput an ed script.\n"),
- io__write_string("\t-f, --forward-ed\n"),
- io__write_string("\t\tProduce output similar to --ed, not useful to
ed(1),\n"),
- io__write_string("\t\tand in the opposite order.\n"),
- io__write_string("\t-n, --rcs\n"),
- io__write_string("\t\tOutput an RCS format diff.\n"),
- io__write_string("\t-q, --brief\n"),
- io__write_string("\t\tOutput only whether or not files differ.\n"),
- io__write_string("\t-D <name>, --ifdef <name>\n"),
- io__write_string("\t\tProduce output in #ifdef <name> format.\n"),
- io__write_string("\t-y, --side-by-side\n"),
- io__write_string("\t\tProduce output in side-by-side format.\n"),
- io__write_string("\t\t-w <num>, --width <num> Output at most <num>
(default 130)\n"),
- io__write_string("\t\t\tcharacters per line.\n"),
- io__write_string("\t\t--left-column Output only the left column of
common lines.\n"),
- io__write_string("\t\t--suppress-common-lines Do not output common
lines.\n"),
- io__write_string("\nMatching options:\n"),
- io__write_string("\t-d, --minimal\n"),
- io__write_string("\t\tTry hard to find as small a set of changes as
possible.\n"),
- io__write_string("\t-B, --ignore-blank-lines\n"),
- io__write_string("\t\tIgnore changes whose lines are all blank.\n").
+ % Help text for the options.
+options_help(!IO) :-
+ io.write_string("Output styles:\n", !IO),
+ io.write_string("\t--help\n", !IO),
+ io.write_string("\t\tOutput this help.\n", !IO),
+ io.write_string("\t-v, --version\n", !IO),
+ io.write_string("\t\tOutput version info.\n", !IO),
+ io.write_string("\t-c, -C <num>, --context <num>\n", !IO),
+ io.write_string("\t\tOutput <num> (default 2) lines of copied
context.\n", !IO),
+ io.write_string("\t-u, -U <num>, --unified <num>\n", !IO),
+ io.write_string("\t\tOutput <num> (default 2) lines of unified
context.\n", !IO),
+ io.write_string("\t\t-L <label>, --label <label> Use <label>
instead of file name.\n", !IO),
+ io.write_string("\t-e, --ed\n", !IO),
+ io.write_string("\t\tOutput an ed script.\n", !IO),
+ io.write_string("\t-f, --forward-ed\n", !IO),
+ io.write_string("\t\tProduce output similar to --ed, not useful
to ed(1),\n", !IO),
+ io.write_string("\t\tand in the opposite order.\n", !IO),
+ io.write_string("\t-n, --rcs\n", !IO),
+ io.write_string("\t\tOutput an RCS format diff.\n", !IO),
+ io.write_string("\t-q, --brief\n", !IO),
+ io.write_string("\t\tOutput only whether or not files differ.\n", !IO),
+ io.write_string("\t-D <name>, --ifdef <name>\n", !IO),
+ io.write_string("\t\tProduce output in #ifdef <name> format.\n", !IO),
+ io.write_string("\t-y, --side-by-side\n", !IO),
+ io.write_string("\t\tProduce output in side-by-side format.\n", !IO),
+ io.write_string("\t\t-w <num>, --width <num> Output at most
<num> (default 130)\n", !IO),
+ io.write_string("\t\t\tcharacters per line.\n", !IO),
+ io.write_string("\t\t--left-column Output only the left column
of common lines.\n", !IO),
+ io.write_string("\t\t--suppress-common-lines Do not output
common lines.\n", !IO),
+ io.write_string("\nMatching options:\n", !IO),
+ io.write_string("\t-d, --minimal\n", !IO),
+ io.write_string("\t\tTry hard to find as small a set of changes
as possible.\n", !IO),
+ io.write_string("\t-B, --ignore-blank-lines\n", !IO),
+ io.write_string("\t\tIgnore changes whose lines are all blank.\n", !IO).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: samples/rot13/rot13_concise.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/rot13/rot13_concise.m,v
retrieving revision 1.1
diff -u -r1.1 rot13_concise.m
--- samples/rot13/rot13_concise.m 19 Nov 1998 06:18:21 -0000 1.1
+++ samples/rot13/rot13_concise.m 24 Apr 2006 05:48:16 -0000
@@ -1,3 +1,6 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% File: rot13_concise.m
% Main authors: Warwick Harvey <wharvey at cs.monash.edu.au>
% Fergus Henderson <fjh at cs.mu.oz.au>
@@ -20,8 +23,7 @@
:- interface.
:- import_module io.
-:- pred main(state, state).
-:- mode main(di, uo) is det.
+:- pred main(state::di, state::uo) is det.
:- implementation.
:- import_module char, int, string.
@@ -31,28 +33,28 @@
cycle = 26.
rot_n(N, Char) = RotChar :-
- char_to_string(Char, CharString),
- ( if sub_string_search(alphabet, CharString, Index) then
- NewIndex = (Index + N) mod cycle + cycle * (Index // cycle),
- index_det(alphabet, NewIndex, RotChar)
- else
- RotChar = Char
- ).
+ char_to_string(Char, CharString),
+ ( if sub_string_search(alphabet, CharString, Index) then
+ NewIndex = (Index + N) mod cycle + cycle * (Index // cycle),
+ index_det(alphabet, NewIndex, RotChar)
+ else
+ RotChar = Char
+ ).
rot13(Char) = rot_n(13, Char).
-main -->
- read_char(Res),
- ( { Res = ok(Char) },
- print(rot13(Char)),
- main
- ; { Res = eof }
- ; { Res = error(ErrorCode) },
- { error_message(ErrorCode, ErrorMessage) },
- stderr_stream(StdErr),
- print(StdErr, "rot13: error reading input: "),
- print(StdErr, ErrorMessage),
- nl(StdErr)
- ).
+main(!IO) :-
+ read_char(Res, !IO),
+ ( Res = ok(Char),
+ print(rot13(Char), !IO),
+ main(!IO)
+ ; Res = eof
+ ; Res = error(ErrorCode),
+ error_message(ErrorCode, ErrorMessage),
+ stderr_stream(StdErr, !IO),
+ print(StdErr, "rot13: error reading input: ", !IO),
+ print(StdErr, ErrorMessage, !IO),
+ nl(StdErr, !IO)
+ ).
Index: samples/rot13/rot13_gustavo.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/rot13/rot13_gustavo.m,v
retrieving revision 1.1
diff -u -r1.1 rot13_gustavo.m
--- samples/rot13/rot13_gustavo.m 19 Nov 1998 06:18:22 -0000 1.1
+++ samples/rot13/rot13_gustavo.m 24 Apr 2006 05:48:16 -0000
@@ -1,3 +1,6 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% I have another version of rot13.
%
% Gustavo A. Ospina <g-ospina at uniandes.edu.co>
@@ -7,7 +10,7 @@
% on your char library. Maybe my version is slower, but it can be discussed.
%
% This source file is hereby placed in the public domain.
-% - Gustavo Ospina
+% - Gustavo Ospina
:- module rot13_gustavo.
@@ -15,7 +18,7 @@
:- import_module io.
-:- pred main(io__state::di,io__state::uo) is det.
+:- pred main(io.state::di,io.state::uo) is det.
:- implementation.
@@ -24,10 +27,10 @@
:- pred rot13(char::in,char::out) is det.
rot13(Char,RotChar) :-
- char__is_upper(Char) ->
+ char.is_upper(Char) ->
rot13(Char,0'A,RotChar)
;
- char__is_lower(Char) ->
+ char.is_lower(Char) ->
rot13(Char,0'a,RotChar)
;
RotChar = Char.
@@ -35,38 +38,38 @@
:- pred rot13(char::in,int::in,char::out) is det.
rot13(Char,CodeLetterA,RotChar) :-
- char__to_int(Char,CodeChar),
+ char.to_int(Char,CodeChar),
RotCode = (CodeChar - CodeLetterA + 13) mod 26 + CodeLetterA,
- char__to_int(RChar,RotCode) ->
+ char.to_int(RChar,RotCode) ->
RotChar = RChar
;
RotChar = '\a'.
/* Alert character (Error case. To satisfy mode check) */
-:- pred printRotChars(list(char)::in,io__state::di,io__state::uo) is det.
+:- pred printRotChars(list(char)::in,io.state::di,io.state::uo) is det.
-printRotChars([]) -->
- [].
+printRotChars([], !IO) :-
+ true.
-printRotChars([Ch|Chs]) -->
- {rot13(Ch,RotCh)},
- io__write_char(RotCh),
- printRotChars(Chs).
+printRotChars([Ch|Chs], !IO) :-
+ rot13(Ch,RotCh),
+ io.write_char(RotCh, !IO),
+ printRotChars(Chs, !IO).
% Main Program
-main -->
- io__read_line(Result),
+main(!IO) :-
+ io.read_line(Result, !IO),
(
- {Result = ok(Line)},
- printRotChars(Line),
- main
+ Result = ok(Line),
+ printRotChars(Line, !IO),
+ main(!IO)
;
- {Result = eof,
- true}
+ Result = eof,
+ true
;
- {Result = error(Error),
- io__error_message(Error,Message)},
- io__stderr_stream(Stderr),
- io__write_string(Stderr,Message)
+ Result = error(Error),
+ io.error_message(Error,Message),
+ io.stderr_stream(Stderr, !IO),
+ io.write_string(Stderr,Message, !IO)
).
Index: samples/rot13/rot13_juergen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/rot13/rot13_juergen.m,v
retrieving revision 1.1
diff -u -r1.1 rot13_juergen.m
--- samples/rot13/rot13_juergen.m 19 Nov 1998 06:18:23 -0000 1.1
+++ samples/rot13/rot13_juergen.m 24 Apr 2006 05:48:16 -0000
@@ -1,38 +1,41 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
%
% Copyright (C) 1998 Jürgen Stuber <juergen at mpi-sb.mpg.de>
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%
% I couldn't resist:
-% Jürgen Stuber <juergen at mpi-sb.mpg.de>
-% http://www.mpi-sb.mpg.de/~juergen/
+% Jürgen Stuber <juergen at mpi-sb.mpg.de>
+% http://www.mpi-sb.mpg.de/~juergen/
:- module rot13_juergen.
:- interface.
:- import_module io.
-:- pred main(io__state::di, io__state::uo) is det.
+:- pred main(io.state::di, io.state::uo) is det.
:- implementation.
:- import_module char, int, require.
:- pred rot13( char::in, char::out) is det.
-main -->
- io__read_char( Result ),
- ( { Result = ok( Char ) } ->
- { rot13( Char, Rot13Char ) },
- io__write_char( Rot13Char ),
- main
+main(!IO) :-
+ io.read_char( Result, !IO ),
+ ( Result = ok( Char ) ->
+ rot13( Char, Rot13Char ),
+ io.write_char( Rot13Char, !IO ),
+ main(!IO)
- ; { Result = eof } ->
- { true }
+ ; Result = eof ->
+ true
;
- { error( "read failed" ) }
+ error( "read failed" )
).
rot13( Char, Rot13Char ) :-
- char__to_int( Char, Code ),
+ char.to_int( Char, Code ),
( 0'A =< Code, Code =< 0'Z ->
Rot13Code = (Code - 0'A + 13) mod 26 + 0'A
; 0'a =< Code, Code =< 0'z ->
@@ -40,7 +43,7 @@
;
Rot13Code = Code
),
- ( char__to_int( Ch, Rot13Code ) ->
+ ( char.to_int( Ch, Rot13Code ) ->
Rot13Char = Ch
;
error("too offensive, censored")
Index: samples/rot13/rot13_ralph.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/rot13/rot13_ralph.m,v
retrieving revision 1.1
diff -u -r1.1 rot13_ralph.m
--- samples/rot13/rot13_ralph.m 31 Jan 2001 09:22:07 -0000 1.1
+++ samples/rot13/rot13_ralph.m 24 Apr 2006 05:48:16 -0000
@@ -16,7 +16,7 @@
-:- pred main(io__state::di, io__state::uo) is det.
+:- pred main(io.state::di, io.state::uo) is det.
% ----------------------------------------------------------------------------
%
% ----------------------------------------------------------------------------
%
@@ -27,11 +27,11 @@
% ----------------------------------------------------------------------------
%
-main -->
- io__read_byte(Result),
- ( { Result = ok(X) }, io__write_byte(rot13(X)), main
- ; { Result = eof }
- ; { Result = error(ErrNo)}, { error(io__error_message(ErrNo)) }
+main(!IO) :-
+ io.read_byte(Result, !IO),
+ ( Result = ok(X), io.write_byte(rot13(X), !IO), main(!IO)
+ ; Result = eof
+ ; Result = error(ErrNo), error(io.error_message(ErrNo))
).
% ----------------------------------------------------------------------------
%
Index: samples/rot13/rot13_verbose.m
===================================================================
RCS file: /home/mercury1/repository/mercury/samples/rot13/rot13_verbose.m,v
retrieving revision 1.1
diff -u -r1.1 rot13_verbose.m
--- samples/rot13/rot13_verbose.m 19 Nov 1998 06:18:23 -0000 1.1
+++ samples/rot13/rot13_verbose.m 24 Apr 2006 05:48:16 -0000
@@ -1,3 +1,6 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% File: rot13_verbose.m
% Main author: Warwick Harvey <wharvey at cs.monash.edu.au>
% Additional input: Fergus Henderson <fjh at cs.mu.oz.au>
@@ -22,17 +25,15 @@
:- interface.
:- import_module io.
-:- pred main(io__state, io__state).
-:- mode main(di, uo) is det.
+:- pred main(io.state::di, io.state::uo) is det.
:- implementation.
:- import_module char, int, require.
- % rot13a/2
- % A table to map the alphabetic characters to their rot13 equivalents
- % (fails if the input is not alphabetic).
-:- pred rot13a(char, char).
-:- mode rot13a(in, out) is semidet.
+ % rot13a/2
+ % A table to map the alphabetic characters to their rot13 equivalents
+ % (fails if the input is not alphabetic).
+:- pred rot13a(char::in, char::out) is semidet.
rot13a('a', 'n').
rot13a('b', 'o').
@@ -87,30 +88,29 @@
rot13a('Y', 'L').
rot13a('Z', 'M').
- % rot13/2
- % Applies the rot13 algorithm to a character.
-:- pred rot13(char, char).
-:- mode rot13(in, out) is det.
+ % rot13/2
+ % Applies the rot13 algorithm to a character.
+:- pred rot13(char::in, char::out) is det.
rot13(Char, RotChar) :-
- ( if rot13a(Char, TmpChar) then
- RotChar = TmpChar
- else
- RotChar = Char
- ).
-
-main -->
- io__read_char(Res),
- ( { Res = ok(Char) },
- { rot13(Char, RotChar) },
- io__write_char(RotChar),
- main
- ; { Res = eof }
- ; { Res = error(ErrorCode) },
- { io__error_message(ErrorCode, ErrorMessage) },
- io__stderr_stream(StdErr),
- io__write_string(StdErr, "rot13: error reading input: "),
- io__write_string(StdErr, ErrorMessage),
- io__nl(StdErr)
- ).
+ ( if rot13a(Char, TmpChar) then
+ RotChar = TmpChar
+ else
+ RotChar = Char
+ ).
+
+main(!IO) :-
+ io.read_char(Res, !IO),
+ ( Res = ok(Char),
+ rot13(Char, RotChar),
+ io.write_char(RotChar, !IO),
+ main(!IO)
+ ; Res = eof
+ ; Res = error(ErrorCode),
+ io.error_message(ErrorCode, ErrorMessage),
+ io.stderr_stream(StdErr, !IO),
+ io.write_string(StdErr, "rot13: error reading input: ", !IO),
+ io.write_string(StdErr, ErrorMessage, !IO),
+ io.nl(StdErr, !IO)
+ ).
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list