1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
%-----------------------------------------------------------------------------%
% 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.
%-----------------------------------------------------------------------------%
% Main author: bromage
% Based heavily on lcsstype.m, written by bromage and simplified by
% Marnix Klooster <marnix@worldonline.nl>
% This module contains the type of a diff.
%-----------------------------------------------------------------------------%
:- module difftype.
:- 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.
:- 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.
:- type segment == pair(pos,pos).
% 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.
:- type diff == list(edit).
%-----------------------------------------------------------------------------%
:- pred first_mentioned_positions(edit :: in, pos :: out, pos :: out) is det.
:- pred last_mentioned_positions(edit :: in, pos :: out, pos :: 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, segment, diff, diff).
:- mode difftype__add_edit(in, in, in, out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module int.
first_mentioned_positions(add(X, Y - _), X, Y).
first_mentioned_positions(delete(X - _, Y), X, Y).
first_mentioned_positions(change(X - _, Y - _), X, Y).
last_mentioned_positions(add(X, _ - Y), X, Y).
last_mentioned_positions(delete(_ - X, Y), X, Y).
last_mentioned_positions(change(_ - X, _ - Y), X, Y).
%-----------------------------------------------------------------------------%
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]
)
)
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
|