Skip to content

Commit 37dfddc

Browse files
committed
SequencesExt!ReplaceFirstSubSeq
[Feature]
1 parent feaf6f9 commit 37dfddc

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

modules/SequencesExt.tla

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,34 @@ SubSeqs(s) ==
288288
(**************************************************************************)
289289
{ SubSeq(s, i+1, j) : i, j \in 0..Len(s) }
290290

291+
292+
IndexFirstSubSeq(s, t) ==
293+
(**************************************************************************)
294+
(* The (1-based) index of the beginning of the subsequence s of the *)
295+
(* sequence t . If s appears in t multiple times, this equals the *)
296+
(* lowest index. *)
297+
(* For example: IndexFirstSubSeq(<<1>>, <<1,1,1>>) = 1 *)
298+
(**************************************************************************)
299+
LET last == CHOOSE i \in 0..Len(t) :
300+
/\ s \in SubSeqs(SubSeq(t, 1, i))
301+
/\ \A j \in 0..i-1 : s \notin SubSeqs(SubSeq(t, 1, j))
302+
IN last - (Len(s) - 1)
303+
304+
ReplaceSubSeqAt(i, r, s, t) ==
305+
(**************************************************************************)
306+
(* The sequence t with its subsequence s at position i replaced by *)
307+
(* the sequence r . *)
308+
(**************************************************************************)
309+
LET prefix == SubSeq(t, 1, i - 1)
310+
suffix == SubSeq(t, i + Len(s), Len(t))
311+
IN prefix \o r \o suffix
312+
313+
ReplaceFirstSubSeq(r, s, t) ==
314+
(**************************************************************************)
315+
(* The sequence t with its subsequence s replaced by the sequence r *)
316+
(**************************************************************************)
317+
IF s \in SubSeqs(t)
318+
THEN ReplaceSubSeqAt(IndexFirstSubSeq(s, t), r, s, t)
319+
ELSE t
320+
291321
=============================================================================

modules/tlc2/overrides/SequencesExt.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,17 @@
2525
* Markus Alexander Kuppe - initial API and implementation
2626
******************************************************************************/
2727

28+
import java.util.regex.Pattern;
29+
30+
import tla2sany.semantic.ExprOrOpArgNode;
2831
import tlc2.output.EC;
2932
import tlc2.tool.EvalControl;
3033
import tlc2.tool.EvalException;
34+
import tlc2.tool.TLCState;
35+
import tlc2.tool.coverage.CostModel;
36+
import tlc2.tool.impl.Tool;
37+
import tlc2.util.Context;
38+
import tlc2.value.IValue;
3139
import tlc2.value.Values;
3240
import tlc2.value.impl.Applicable;
3341
import tlc2.value.impl.BoolValue;
@@ -231,4 +239,22 @@ public static Value foldRight(final OpValue op, final Value val, final Value bas
231239

232240
return args[1];
233241
}
242+
243+
@Evaluation(definition = "ReplaceFirstSubSeq", module = "SequencesExt", warn = false, silent = true)
244+
public static Value replaceFirstSubSeq(final Tool tool, final ExprOrOpArgNode[] args, final Context c,
245+
final TLCState s0, final TLCState s1, final int control, final CostModel cm) {
246+
final IValue r = tool.eval(args[0], c, s0, s1, control, cm);
247+
final IValue s = tool.eval(args[1], c, s0, s1, control, cm);
248+
final IValue t = tool.eval(args[2], c, s0, s1, control, cm);
249+
250+
if (r instanceof StringValue && s instanceof StringValue && t instanceof StringValue) {
251+
final String st = ((StringValue) t).toUnquotedString();
252+
final String ss = ((StringValue) s).toUnquotedString();
253+
final String sr = ((StringValue) r).toUnquotedString();
254+
255+
return new StringValue(st.replaceFirst(Pattern.quote(ss), sr));
256+
}
257+
258+
return null; // Non-string functions handled by pure TLA+ definition of operator.
259+
}
234260
}

tests/SequencesExtTests.tla

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,39 @@ ASSUME \A seq \in BoundedSeq(1..5, 5) :
192192
/\ Len(s) <= Len(seq)
193193
/\ Range(s) \subseteq Range(seq)
194194

195+
-----------------------------------------------------------------------------
196+
197+
ASSUME ReplaceFirstSubSeq(<<>>,<<>>,<<>>) = <<>>
198+
ASSUME ReplaceFirstSubSeq(<<4>>,<<>>,<<>>) = <<4>>
199+
ASSUME ReplaceFirstSubSeq(<<4>>,<<4>>,<<>>) = <<>>
200+
ASSUME ReplaceFirstSubSeq(<<>>,<<>>,<<3,2,3,4>>) = <<3,2,3,4>>
201+
ASSUME ReplaceFirstSubSeq(<<4,4>>,<<3,2,3,4>>,<<3,2,3,4>>) = <<4,4>>
202+
ASSUME ReplaceFirstSubSeq(<<4,4>>,<<>>,<<3,2,3,4>>) = <<4,4,3,2,3,4>>
203+
204+
ASSUME ReplaceFirstSubSeq(<<4,4>>,<<4>>,<<3,2,3,4>>) = <<3,2,3,4,4>>
205+
ASSUME ReplaceFirstSubSeq(<<>>,<<4>>,<<3,2,3,4>>) = <<3,2,3>>
206+
ASSUME ReplaceFirstSubSeq(<<>>,<<4>>,<<3,2,3,4,4>>) = <<3,2,3,4>>
207+
ASSUME ReplaceFirstSubSeq(<<4,4>>,<<3>>,<<3,2,3,4>>) = <<4,4,2,3,4>>
208+
ASSUME ReplaceFirstSubSeq(<<4>>, <<1,2>>, <<1,2,1,2>>) = <<4,1,2>>
209+
ASSUME ReplaceFirstSubSeq(<<4,4>>, <<1,2>>, <<1,2,1,2>>) = <<4,4,1,2>>
210+
ASSUME ReplaceFirstSubSeq(<<4,4,4>>, <<1,2>>, <<1,2,1,2>>) = <<4,4,4,1,2>>
211+
212+
ASSUME ReplaceFirstSubSeq(<<1,2>>, <<1,2>>, <<1,2,2,1>>) = <<1,2,2,1>>
213+
ASSUME ReplaceFirstSubSeq(<<2,1>>, <<1,2>>, <<1,2,2,1>>) = <<2,1,2,1>>
214+
215+
ASSUME \A seq \in (BoundedSeq(1..5, 5) \ {<<>>}):
216+
/\ ReplaceFirstSubSeq(<<6>>, <<>>, seq) = <<6>> \o seq
217+
/\ ReplaceFirstSubSeq(<<6>>, <<Head(seq)>>, seq) = <<6>> \o Tail(seq)
218+
219+
ASSUME ReplaceFirstSubSeq("", "", "") = ""
220+
ASSUME ReplaceFirstSubSeq("a", "", "") = "a"
221+
ASSUME ReplaceFirstSubSeq("a", "b", "") = ""
222+
ASSUME ReplaceFirstSubSeq("a", "d", "abc") = "abc"
223+
ASSUME ReplaceFirstSubSeq("ddd", "ab", "abab") = "dddab"
224+
ASSUME ReplaceFirstSubSeq("ddd", "aa", "aaa") = "ddda"
225+
ASSUME ReplaceFirstSubSeq("ddd", "abab", "abab") = "ddd"
226+
227+
ASSUME ReplaceFirstSubSeq("\\\\", "\\", "Properly escape the \\quotes") = "Properly escape the \\\\quotes"
228+
ASSUME ReplaceFirstSubSeq("replaces", "%pattern%", "This %pattern% the pattern") = "This replaces the pattern"
229+
195230
=============================================================================

0 commit comments

Comments
 (0)