Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 79.1% 110 / 0 / 139
Functions: -% 0 / 1 / 1
Branches: 67.8% 103 / 0 / 152

OMCompiler/Compiler/Util/DiffAlgorithm.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package DiffAlgorithm
37 "Compares text and other sequences, generating a sequence of additions
38 and deletions.
39
40 Based on:
41 Eugene Myers, An O(ND) Difference Algorithm and Its Variations,
42 Algorithmica, November 1986
43 http://xmailserver.org/diff2.pdf
44
45 Other resources used to understand the paper and optimize the algorithm:
46 https://www.codeproject.com/Articles/42279/Investigating-Myers-diff-algorithm-Part-1-of-2
47 https://code.google.com/p/google-diff-match-patch/
48 "
49
50 import Print;
51
52 protected
53
54 import List;
55 import System;
56
57 public
58
59 type Diff = enumeration(Add,Delete,Equal);
60
61 function diff<T>
62 input list<T> seq1;
63 input list<T> seq2;
64 input FunEquals equals;
65 input FunWhitespace isWhitespace, isWhitespaceNotComment;
66 input ToString toString;
67 output list<tuple<Diff,list<T>>> out;
68 partial function FunEquals
69 input T t1,t2;
70 output Boolean b;
71 end FunEquals;
72 partial function FunWhitespace
73 input T t;
74 output Boolean b;
75 end FunWhitespace;
76 partial function ToString
77 input T t;
78 output String o;
79 end ToString;
80 protected
81 Integer start1, end1, start2, end2;
82 array<T> arr1, arr2;
83 algorithm
84 151 arr1 := listArray(seq1);
85 151 arr2 := listArray(seq2);
86 start1 := 1;
87 start2 := 1;
88 end1 := arrayLength(arr1);
89 end2 := arrayLength(arr2);
90 151 out := diffSeq(arr1, arr2, equals, isWhitespace, isWhitespaceNotComment, toString, start1, end1, start2, end2);
91 end diff;
92
93 partial function partialPrintDiff<T>
94 input list<tuple<Diff,list<T>>> seq;
95 input ToString toString;
96 output String res;
97 partial function ToString
98 input T t;
99 output String o;
100 end ToString;
101 replaceable package DiffStrings
102 // Cannot put public constants in a function declaration...
103 // So we use this package instead
104 constant String equalOpen;
105 constant String equalClose;
106 constant String addOpen;
107 constant String addClose;
108 constant String delOpen;
109 constant String delClose;
110 constant Boolean printAdd=true;
111 constant Boolean printEqual=true;
112 constant Boolean printDelete=true;
113 end DiffStrings;
114 protected
115 String open, close;
116 list<T> ts;
117 Boolean b;
118 Integer i;
119 algorithm
120 92 i:=Print.saveAndClearBuf();
121
6/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 152 times.
✓ Branch 5 taken 65 times.
306 for d in seq loop
122 (open,close,ts,b) := match d
123 case (Diff.Equal,ts)
124 then (DiffStrings.equalOpen,DiffStrings.equalClose,ts,DiffStrings.printEqual);
125 case (Diff.Add,ts)
126 then (DiffStrings.addOpen,DiffStrings.addClose,ts,DiffStrings.printAdd);
127 case (Diff.Delete,ts)
128 then (DiffStrings.delOpen,DiffStrings.delClose,ts,DiffStrings.printDelete);
129 end match;
130
5/8
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 152 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 143 times.
✓ Branch 7 taken 9 times.
214 if not listEmpty(ts) and (b or (DiffStrings.printEqual and DiffStrings.printAdd and DiffStrings.printDelete /* optimization */)) then
131 205 Print.printBuf(open);
132
6/6
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 671 times.
✓ Branch 5 taken 143 times.
1149 for t in ts loop
133
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 671 times.
944 Print.printBuf(toString(t));
134 end for;
135 205 Print.printBuf(close);
136 end if;
137 end for;
138 92 res := Print.getString();
139 92 Print.restoreBuf(i);
140 end partialPrintDiff;
141
142 function printDiffTerminalColor
143 extends partialPrintDiff(DiffStrings(
144 equalOpen="",
145 equalClose="",
146 addOpen="",
147 addClose="",
148 delOpen="",
149 delClose=""
150 ));
151 end printDiffTerminalColor;
152
153 function printDiffXml
154 extends partialPrintDiff(DiffStrings(
155 equalOpen="<equal>",
156 equalClose="</equal>",
157 addOpen="<add>",
158 addClose="</add>",
159 delOpen="<del>",
160 delClose="</del>"
161 ));
162 end printDiffXml;
163
164 function printActual
165 extends partialPrintDiff(DiffStrings(
166 equalOpen="",
167 equalClose="",
168 addOpen="",
169 addClose="",
170 delOpen="",
171 delClose="",
172 printDelete=false
173 ));
174 end printActual;
175
176 protected
177
178 function diffSeq<T>
179 input array<T> arr1;
180 input array<T> arr2;
181 input FunEquals equals;
182 input FunWhitespace isWhitespace;
183 input FunWhitespace isWhitespaceNotComment;
184 input ToString toString;
185 input Integer inStart1, inEnd1, inStart2, inEnd2;
186 input list<tuple<Diff,list<T>>> inPrefixes = {}, inSuffixes = {};
187 output list<tuple<Diff,list<T>>> out;
188 partial function FunEquals
189 input T t1,t2;
190 output Boolean b;
191 end FunEquals;
192 partial function FunWhitespace
193 input T t;
194 output Boolean b;
195 end FunWhitespace;
196 partial function ToString
197 input T t;
198 output String o;
199 end ToString;
200 protected
201 Integer start1=inStart1, end1=inEnd1, start2=inStart2, end2=inEnd2, len1, len2;
202 list<tuple<Diff,list<T>>> prefixes = inPrefixes, suffixes = inSuffixes;
203 algorithm
204 289 len1 := end1-start1+1;
205 289 len2 := end2-start2+1;
206 // Some of these tricks were inspired by diff-match-patch:
207 // https://code.google.com/p/google-diff-match-patch/
208 // They do checks that are trivial and optimal, but could significantly
209 // slow down the rest of Myer's diff algorithm
210 // Check if either sequence is empty. Trivial to diff.
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
289 if len1 < 1 and len2 < 1 then
212 ✗ out := List.append_reverse(prefixes, suffixes);
213 ✗ return;
214 elseif len1 < 1 then
215
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
32 out := List.append_reverse(prefixes, (Diff.Add, list(arr2[e] for e in start2:end2))::suffixes);
216 10 return;
217 elseif len2 < 1 then
218
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
3 out := List.append_reverse(prefixes, (Diff.Delete, list(arr1[e] for e in start1:end1))::suffixes);
219 1 return;
220 end if;
221 // Note the horrible syntax for short-circuit evaluation
222 // Check if the sequences are equal. Trivial diff.
223
6/8
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 514 times.
✓ Branch 3 taken 218 times.
✓ Branch 4 taken 514 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 218 times.
792 if if len1==len2 then min(equals(arr1[e+start1-1],arr2[e+start2-1]) threaded for e in 1:len1) else false then
224 ✗ out := {(Diff.Equal, list(arr1[e] for e in start1:end1))};
225 ✗ return;
226 end if;
227
228 // trim off common prefix; guaranteed to be a good solution
229 278 (prefixes, start1, start2) := trimCommonPrefix(arr1, start1, end1, arr2, start2, end2, equals, prefixes, isWhitespaceNotComment, toString);
230 // trim off common suffix; guaranteed to be a good solution
231 278 (suffixes, end1, end2) := trimCommonSuffix(arr1, start1, end1, arr2, start2, end2, equals, suffixes, isWhitespaceNotComment);
232 // Check if anything changed and iterate. A sequence could now be empty.
233
6/8
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 179 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✓ Branch 5 taken 39 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
278 if start1<>inStart1 or start2<>inStart2 or end1<>inEnd1 or end2<>inEnd2 then
234 138 out := diffSeq(arr1,arr2,equals,isWhitespace,isWhitespaceNotComment,toString,start1,end1,start2,end2,inPrefixes=prefixes,inSuffixes=suffixes);
235 138 return;
236 else
237 out := matchcontinue ()
238 140 case () then onlyAdditions(arr1,arr2,equals,isWhitespace,toString,start1,end1,start2,end2);
239 140 case () then onlyRemovals(arr1,arr2,equals,isWhitespace,toString,start1,end1,start2,end2);
240 140 else myersGreedyDiff(arr1,arr2,equals,start1,end1,start2,end2);
241 end matchcontinue;
242 // TODO: cleanup
243 140 out := List.append_reverse(prefixes, listAppend(out, suffixes));
244 140 return;
245 end if;
246 fail();
247 end diffSeq;
248
249 function addToList<T>
250 input list<tuple<Diff,list<T>>> inlst;
251 input Diff ind;
252 input list<T> inacc;
253 input Diff newd;
254 input T t;
255 output list<tuple<Diff,list<T>>> lst=inlst;
256 output Diff d=newd;
257 output list<T> acc=inacc;
258 algorithm
259
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 331 times.
426 if ind==newd then
260 acc := t::acc;
261 else
262
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 280 times.
331 if not listEmpty(inacc) then
263 51 lst := (ind,listReverse(acc))::lst;
264 end if;
265 acc := {t};
266 end if;
267 end addToList;
268
269 function endList<T>
270 input list<tuple<Diff,list<T>>> inlst;
271 input Diff ind;
272 input list<T> inacc;
273 output list<tuple<Diff,list<T>>> lst=inlst;
274 algorithm
275 ✗ if not listEmpty(inacc) then
276 ✗ lst := (ind,listReverse(inacc))::lst;
277 end if;
278 end endList;
279
280 function onlyAdditions<T>
281 input array<T> arr1;
282 input array<T> arr2;
283 input FunEquals equals;
284 input FunWhitespace isWhitespace;
285 input ToString toString;
286 input Integer start1, end1, start2, end2;
287 output list<tuple<Diff,list<T>>> out;
288 partial function FunEquals
289 input T t1,t2;
290 output Boolean b;
291 end FunEquals;
292 partial function FunWhitespace
293 input T t;
294 output Boolean b;
295 end FunWhitespace;
296 partial function ToString
297 input T t;
298 output String o;
299 end ToString;
300 protected
301 Integer x=0,y=0;
302 Diff d=Diff.Equal;
303 list<T> lst={};
304 algorithm
305 out := {};
306 // print("Try only additions\n");
307
3/4
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 140 times.
354 while start1+x<=end1 and start2+y<=end2 loop
308 // print("Try only additions"+String(x)+","+String(y)+"\n");
309 // print("1: " + System.trim(toString(arr1[start1+x]))+"\n");
310 // print("2: " + System.trim(toString(arr2[start2+y]))+"\n");
311
3/4
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 208 times.
214 if equals(arr1[start1+x],arr2[start2+y]) then
312 6 (out,d,lst) := addToList(out,d,lst,Diff.Equal,arr1[start1+x]);
313 6 x:=x+1;
314 6 y:=y+1;
315 // print("Both equal\n");
316 elseif isWhitespace(arr1[start1+x]) then
317 22 (out,d,lst) := addToList(out,d,lst,Diff.Delete,arr1[start1+x]);
318 // print("Deleting: " + toString(arr1[start1+x])+"\n");
319 22 x:=x+1;
320 else
321 186 (out,d,lst) := addToList(out,d,lst,Diff.Add,arr2[start2+y]);
322 // print("Adding: " + toString(arr2[start2+y])+"\n");
323 186 y:=y+1;
324 end if;
325 end while;
326
327
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 while start1+x<=end1 loop
328
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
140 if isWhitespace(arr1[start1+x]) then
329 ✗ (out,d,lst) := addToList(out,d,lst,Diff.Delete,arr1[start1+x]);
330 ✗ x:=x+1;
331 else
332 140 fail();
333 end if;
334 end while;
335
336 ✗ while start2+y<=end2 loop
337 ✗ if isWhitespace(arr2[start2+y]) then
338 ✗ (out,d,lst) := addToList(out,d,lst,Diff.Add,arr2[start2+y]);
339 ✗ y:=y+1;
340 else
341 ✗ fail();
342 end if;
343 end while;
344
345 ✗ out := endList(out, d, lst);
346
347 // print("It is only additions :)\n");
348 ✗ out := listReverse(out);
349 end onlyAdditions;
350
351 function onlyRemovals<T>
352 input array<T> arr1;
353 input array<T> arr2;
354 input FunEquals equals;
355 input FunWhitespace isWhitespace;
356 input ToString toString;
357 input Integer start1, end1, start2, end2;
358 output list<tuple<Diff,list<T>>> out;
359 partial function FunEquals
360 input T t1,t2;
361 output Boolean b;
362 end FunEquals;
363 partial function FunWhitespace
364 input T t;
365 output Boolean b;
366 end FunWhitespace;
367 partial function ToString
368 input T t;
369 output String o;
370 end ToString;
371 protected
372 Integer x=0,y=0;
373 Diff d=Diff.Equal;
374 list<T> lst={};
375 algorithm
376 out := {};
377 // print("Try only removals\n");
378
3/4
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 140 times.
✓ Branch 2 taken 212 times.
✗ Branch 3 not taken.
352 while start1+x<=end1 and start2+y<=end2 loop
379 // print("Try only removals"+String(x)+","+String(y)+"\n");
380 // print("1: " + System.trim(toString(arr1[start1+x]))+"\n");
381 // print("2: " + System.trim(toString(arr2[start2+y]))+"\n");
382
3/4
✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 206 times.
212 if equals(arr1[start1+x],arr2[start2+y]) then
383 6 (out,d,lst) := addToList(out,d,lst,Diff.Equal,arr1[start1+x]);
384 6 x:=x+1;
385 6 y:=y+1;
386 // print("Both equal\n");
387 elseif isWhitespace(arr2[start2+y]) then
388 17 (out,d,lst) := addToList(out,d,lst,Diff.Add,arr2[start2+y]);
389 // print("Deleting: " + toString(arr1[start1+x])+"\n");
390 17 y:=y+1;
391 else
392 189 (out,d,lst) := addToList(out,d,lst,Diff.Delete,arr1[start1+x]);
393 // print("Adding: " + toString(arr2[start2+y])+"\n");
394 189 x:=x+1;
395 end if;
396 end while;
397
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 while start1+x<=end1 loop
399 ✗ if isWhitespace(arr1[start1+x]) then
400 ✗ (out,d,lst) := addToList(out,d,lst,Diff.Delete,arr1[start1+x]);
401 ✗ x:=x+1;
402 else
403 ✗ fail();
404 end if;
405 end while;
406
407
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 while start2+y<=end2 loop
408
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
140 if isWhitespace(arr2[start2+y]) then
409 ✗ (out,d,lst) := addToList(out,d,lst,Diff.Add,arr2[start2+y]);
410 ✗ y:=y+1;
411 else
412 140 fail();
413 end if;
414 end while;
415
416 ✗ out := endList(out, d, lst);
417
418 // print("It is only additions :)\n");
419 ✗ out := listReverse(out);
420 end onlyRemovals;
421
422 function myersGreedyDiff<T>
423 input array<T> arr1;
424 input array<T> arr2;
425 input FunEquals equals;
426 input Integer start1, end1, start2, end2;
427 output list<tuple<Diff,list<T>>> out;
428 partial function FunEquals
429 input T t1,t2;
430 output Boolean b;
431 end FunEquals;
432 protected
433 Integer len1, len2, maxIter, sz, middle, x, y;
434 array<Integer> V;
435 array<list<tuple<Integer,Integer>>> paths;
436 list<tuple<Integer,Integer>> prevPath;
437 algorithm
438 // Greedy LCS/SES
439 140 len1 := end1-start1+1;
440 140 len2 := end2-start2+1;
441 140 maxIter := len1+len2;
442 140 sz := 2*maxIter+1;
443 140 middle := maxIter+1;
444 140 V := arrayCreate(sz, 0);
445 140 paths := arrayCreate(sz, {});
446
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
483 for D in 0:maxIter loop
447 1314 for k in -D:2:D loop
448
6/6
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 483 times.
✓ Branch 2 taken 285 times.
✓ Branch 3 taken 203 times.
✓ Branch 6 taken 266 times.
✓ Branch 7 taken 19 times.
971 if k == -D or k <> D and V[k-1+middle]<V[k+1+middle] then
449 749 x := V[k+1+middle];
450 749 prevPath := paths[k+1+middle];
451 else
452 222 x := V[k-1+middle]+1;
453 222 prevPath := paths[k-1+middle];
454 end if;
455 971 y := x-k;
456 1942 paths[k+middle]:=(x,y)::prevPath;
457
5/6
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 711 times.
✓ Branch 2 taken 284 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 24 times.
✓ Branch 11 taken 260 times.
995 while if x<len1 and y<len2 then equals(arr1[start1+x], arr2[start2+y]) else false loop
458 24 x:=x+1;
459 24 y:=y+1;
460 48 paths[k+middle]:=(x,y)::paths[k+middle];
461 end while;
462 971 V[k+middle]:=x;
463
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 831 times.
971 if x>=len1 and y>=len2 then
464 // Length of an SES is D
465 140 out := myersGreedyPathToDiff(arr1,arr2,start1,start2,paths[k+middle]);
466 140 return;
467 end if;
468 end for;
469 end for;
470 ✗ print("myersDiff: This cannot happen");
471 ✗ fail();
472 end myersGreedyDiff;
473
474 function myersGreedyPathToDiff<T>
475 input array<T> arr1, arr2;
476 input Integer start1, start2;
477 input list<tuple<Integer,Integer>> paths;
478 output list<tuple<Diff,list<T>>> out = {};
479 protected
480 Integer x1,x2,y1,y2;
481 Diff d1 = Diff.Equal, d2 = Diff.Equal;
482 list<T> lst = {};
483 T t;
484 algorithm
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 (x2,y2)::_ := paths; // starting point
486
2/2
✓ Branch 1 taken 365 times.
✓ Branch 2 taken 140 times.
505 for path in listRest(paths) loop
487 365 (x1,y1) := path;
488
4/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 173 times.
365 if x2-x1==1 and y2-y1==1 then
489 // Diagonal
490 d1 := Diff.Equal;
491 22 t := arr1[start1+x1];
492 elseif x2-x1==1 and y2==y1 then
493 // Horizontal is addition
494 d1 := Diff.Delete;
495 173 t := arr1[start1+x1];
496 elseif y2-y1==1 and x2==x1 then
497 // Vertical is deletion
498 d1 := Diff.Add;
499 170 t := arr2[start2+y1];
500 else
501 // Else is WTF?
502 ✗ print("myersGreedyPathToDiff: This cannot happen\n");
503 ✗ fail();
504 end if;
505
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 225 times.
365 if listEmpty(lst) then
506 lst := {t};
507 elseif d1==d2 then
508 lst := t::lst;
509 else
510 180 out := (d2,lst)::out;
511 lst := {t};
512 end if;
513 d2 := d1;
514 x2 := x1;
515 y2 := y1;
516 end for;
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if not listEmpty(lst) then
518 140 out := (d2,lst)::out;
519 end if;
520 end myersGreedyPathToDiff;
521
522 function trimCommonPrefix<T>
523 input array<T> arr1;
524 input Integer inStart1;
525 input Integer end1;
526 input array<T> arr2;
527 input Integer inStart2;
528 input Integer end2;
529 input FunEquals equals;
530 input list<tuple<Diff,list<T>>> acc;
531 input FunWhitespace isWhitespaceNotComment;
532 input ToString toString;
533 output list<tuple<Diff,list<T>>> prefixes = acc;
534 output Integer start1=inStart1, start2=inStart2;
535 partial function ToString
536 input T t;
537 output String o;
538 end ToString;
539 partial function FunEquals
540 input T t1,t2;
541 output Boolean b;
542 end FunEquals;
543 partial function FunWhitespace
544 input T t;
545 output Boolean b;
546 end FunWhitespace;
547 protected
548 list<T> lst = {};
549 algorithm
550
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 2 times.
474 while start1<=end1 and start2<=end2 loop
551
3/4
✓ Branch 0 taken 472 times.
✗ Branch 1 not taken.
✓ Branch 8 taken 194 times.
✓ Branch 9 taken 278 times.
472 if equals(arr1[start1], arr2[start2]) then
552 194 lst := arr1[start1]::lst;
553 194 start1 := start1 + 1;
554 194 start2 := start2 + 1;
555 elseif start2+1 <= end2 and isWhitespaceNotComment(arr2[start2]) then
556
3/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 25 times.
27 if not equals(arr1[start1], arr2[start2+1]) then
557 break;
558 end if;
559 2 start2 := start2 + 1;
560 else
561 break;
562 end if;
563 end while;
564
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 99 times.
278 if not listEmpty(lst) then
565 99 prefixes := (Diff.Equal,listReverse(lst))::prefixes;
566 end if;
567 end trimCommonPrefix;
568
569 function trimCommonSuffix<T>
570 input array<T> arr1;
571 input Integer start1;
572 input Integer inEnd1;
573 input array<T> arr2;
574 input Integer start2;
575 input Integer inEnd2;
576 input FunEquals equals;
577 input list<tuple<Diff,list<T>>> acc;
578 input FunWhitespace isWhitespaceNotComment;
579 output list<tuple<Diff,list<T>>> suffixes = acc;
580 output Integer end1=inEnd1, end2=inEnd2;
581 partial function FunEquals
582 input T t1,t2;
583 output Boolean b;
584 end FunEquals;
585 partial function FunWhitespace
586 input T t;
587 output Boolean b;
588 end FunWhitespace;
589 protected
590 list<T> lst = {};
591 algorithm
592
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 11 times.
439 while start1<=end1 and start2<=end2 loop
593
3/4
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
✓ Branch 8 taken 161 times.
✓ Branch 9 taken 267 times.
428 if equals(arr1[end1], arr2[end2]) then
594 161 lst := arr1[end1]::lst;
595 161 end1 := end1 - 1;
596 161 end2 := end2 - 1;
597 elseif start2 <= end2-1 and isWhitespaceNotComment(arr2[end2]) then
598
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
3 if not equals(arr1[end1], arr2[end2-1]) then
599 break;
600 end if;
601 ✗ end2 := end2 - 1;
602 else
603 break;
604 end if;
605 end while;
606
607
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 88 times.
278 if not listEmpty(lst) then
608 88 suffixes := (Diff.Equal,lst)::suffixes;
609 end if;
610 end trimCommonSuffix;
611
612 function printStartToEnd<T>
613 input array<T> arr;
614 input Integer startIndex, endIndex;
615 input ToString toString;
616 partial function ToString
617 input T t;
618 output String o;
619 end ToString;
620 output String res;
621 algorithm
622 ✗ res := stringAppendList(list(toString(arrayGet(arr, index)) for index in startIndex:endIndex));
623 end printStartToEnd;
624
625 annotation(__OpenModelica_Interface="util");
626 end DiffAlgorithm;
627