Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/StringExpressions.cs @ 15032

Last change on this file since 15032 was 15032, checked in by pkimmesw, 7 years ago

#2665 Fixed bias 0 issue, PushExpressionFrequencyAnalyzer, Fixed probability for ERC settings, Fixed enable/disable instructions, Added expression descriptions

File size: 27.9 KB
Line 
1namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
2  using System;
3  using System.Globalization;
4  using System.Linq;
5
6  using Attributes;
7
8  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9  using HeuristicLab.Problems.ProgramSynthesis.Push.Extensions;
10
11  using Interpreter;
12  using Stack;
13
14  /// <summary>
15  /// Stringifies and pushes the top INTEGER.,
16  /// </summary>
17  [StorableClass]
18  [PushExpression(
19    StackTypes.String,
20    "STRING.FROMINTEGER",
21    "Stringifies and pushes the top INTEGER.",
22    StackTypes.Integer)]
23  public class StringFromIntegerExpression : StatelessExpression {
24    public StringFromIntegerExpression() { }
25    [StorableConstructor]
26    protected StringFromIntegerExpression(bool deserializing) : base(deserializing) { }
27
28    public override bool IsNoop(IInternalPushInterpreter interpreter) {
29      return interpreter.IntegerStack.IsEmpty;
30    }
31
32    public override void Eval(IInternalPushInterpreter interpreter) {
33      var value = interpreter.IntegerStack.Pop();
34      interpreter.StringStack.Push(value.ToString());
35    }
36  }
37
38  [StorableClass]
39  [PushExpression(
40    StackTypes.String,
41    "STRING.FROMFLOAT",
42    "Stringifies and pushes the top FLOAT.",
43    StackTypes.Float)]
44  public class StringFromFloatExpression : StatelessExpression {
45    public StringFromFloatExpression() { }
46    [StorableConstructor]
47    protected StringFromFloatExpression(bool deserializing) : base(deserializing) { }
48
49    public override bool IsNoop(IInternalPushInterpreter interpreter) {
50      return interpreter.FloatStack.IsEmpty;
51    }
52
53    public override void Eval(IInternalPushInterpreter interpreter) {
54      var value = interpreter.FloatStack.Pop();
55      var str = value.ToString(interpreter.Configuration.FloatStringFormat, CultureInfo.InvariantCulture);
56
57      interpreter.StringStack.Push(str);
58    }
59  }
60
61  /// <summary>
62  /// Stringifies and pushes the top BOOLEAN.
63  /// </summary>
64  [StorableClass]
65  [PushExpression(
66    StackTypes.String,
67    "STRING.FROMBOOLEAN",
68    "Stringifies and pushes the top BOOLEAN.",
69    StackTypes.Boolean)]
70  public class StringFromBooleanExpression : StatelessExpression {
71    public StringFromBooleanExpression() { }
72    [StorableConstructor]
73    protected StringFromBooleanExpression(bool deserializing) : base(deserializing) { }
74
75    public override bool IsNoop(IInternalPushInterpreter interpreter) {
76      return interpreter.BooleanStack.IsEmpty;
77    }
78
79    public override void Eval(IInternalPushInterpreter interpreter) {
80      var value = interpreter.BooleanStack.Pop();
81      interpreter.StringStack.Push(value.ToString());
82    }
83  }
84
85  /// <summary>
86  /// Stringifies and pushes the top CHAR.
87  /// </summary>
88  [StorableClass]
89  [PushExpression(
90    StackTypes.String,
91    "STRING.FROMCHAR",
92    "Stringifies and pushes the top CHAR.",
93    StackTypes.Char)]
94  public class StringFromCharExpression : StatelessExpression {
95    public StringFromCharExpression() { }
96    [StorableConstructor]
97    protected StringFromCharExpression(bool deserializing) : base(deserializing) { }
98
99    public override bool IsNoop(IInternalPushInterpreter interpreter) {
100      return interpreter.CharStack.IsEmpty;
101    }
102
103    public override void Eval(IInternalPushInterpreter interpreter) {
104      var value = interpreter.CharStack.Pop();
105      interpreter.StringStack.Push(value.ToString());
106    }
107  }
108
109  /// <summary>
110  /// Concats the top 2 strings.
111  /// </summary>
112  [StorableClass]
113  [PushExpression(
114    StackTypes.String,
115    "STRING.CONCAT",
116    "Concats the top 2 strings.")]
117  public class StringConcatExpression : StatelessExpression {
118    public StringConcatExpression() { }
119    [StorableConstructor]
120    protected StringConcatExpression(bool deserializing) : base(deserializing) { }
121
122    public override bool IsNoop(IInternalPushInterpreter interpreter) {
123      return interpreter.StringStack.Count < 2 ||
124             interpreter.StringStack.Top.Length + interpreter.StringStack[1].Length >= interpreter.Configuration.MaxStringLength;
125    }
126
127    public override void Eval(IInternalPushInterpreter interpreter) {
128      var str = interpreter.StringStack.Pop();
129      interpreter.StringStack.Top += str;
130    }
131  }
132
133  /// <summary>
134  /// Conj char onto string
135  /// </summary>
136  [StorableClass]
137  [PushExpression(
138    StackTypes.String,
139    "STRING.CONJCHAR",
140    "Conj top CHAR onto top STRING",
141    StackTypes.Char)]
142  public class StringConjCharExpression : StatelessExpression {
143    public StringConjCharExpression() { }
144    [StorableConstructor]
145    protected StringConjCharExpression(bool deserializing) : base(deserializing) { }
146
147    public override bool IsNoop(IInternalPushInterpreter interpreter) {
148      return interpreter.StringStack.IsEmpty ||
149             interpreter.CharStack.IsEmpty ||
150             interpreter.StringStack.Top.Length + 1 >= interpreter.Configuration.MaxStringLength;
151    }
152
153    public override void Eval(IInternalPushInterpreter interpreter) {
154      var c = interpreter.CharStack.Pop();
155      interpreter.StringStack.Top += c;
156    }
157  }
158
159  /// <summary>
160  /// Same as substring 0-n, whereby n is taken from the INTEGER stack.
161  /// </summary>
162  [StorableClass]
163  [PushExpression(
164    StackTypes.String,
165    "STRING.TAKE",
166    "Same as substring 0-n, whereby n is taken from the INTEGER stack.",
167    StackTypes.Integer)]
168  public class StringTakeExpression : StatelessExpression {
169    public StringTakeExpression() { }
170    [StorableConstructor]
171    protected StringTakeExpression(bool deserializing) : base(deserializing) { }
172
173    public override bool IsNoop(IInternalPushInterpreter interpreter) {
174      return interpreter.StringStack.IsEmpty ||
175             interpreter.IntegerStack.IsEmpty;
176    }
177
178    public override void Eval(IInternalPushInterpreter interpreter) {
179      var str = interpreter.StringStack.Top;
180
181      if (str.Length == 0)
182        return;
183
184      var endIndex = interpreter.IntegerStack.Pop().AsInt(str.Length);
185      interpreter.StringStack.Top = str.Substring(0, endIndex);
186    }
187  }
188
189  /// <summary>
190  /// Replaces top STRING with a substring from index A to B, whereby A and B are taken from the INTEGER STACK.
191  /// </summary>
192  [StorableClass]
193  [PushExpression(
194    StackTypes.String,
195    "STRING.SUBSTRING",
196    "Replaces top STRING with a substring from index A to B, whereby A and B are taken from the INTEGER STACK.",
197    StackTypes.Integer)]
198  public class StringSubstringExpression : StatelessExpression {
199    public StringSubstringExpression() { }
200    [StorableConstructor]
201    protected StringSubstringExpression(bool deserializing) : base(deserializing) { }
202
203    public override bool IsNoop(IInternalPushInterpreter interpreter) {
204      return interpreter.StringStack.IsEmpty ||
205             interpreter.IntegerStack.Count < 2;
206    }
207
208    public override void Eval(IInternalPushInterpreter interpreter) {
209      var str = interpreter.StringStack.Top;
210      var firstValue = interpreter.IntegerStack[1];
211      var secondValue = interpreter.IntegerStack.Top;
212      interpreter.IntegerStack.Remove(2);
213
214      var first = Math.Min(str.Length - 1, Math.Max(firstValue, 0));
215      var second = Math.Min(str.Length - 1, Math.Max(secondValue, first));
216      var length = second - first;
217
218      if (length > 0)
219        interpreter.StringStack.Top = str.Substring((int)first, (int)length);
220    }
221  }
222
223  /// <summary>
224  /// Pushes first char of top STRING.
225  /// </summary>
226  [StorableClass]
227  [PushExpression(
228    StackTypes.String,
229    "STRING.FIRST",
230    "Pushes first char of top STRING.")]
231  public class StringFirstExpression : StatelessExpression {
232    public StringFirstExpression() { }
233    [StorableConstructor]
234    protected StringFirstExpression(bool deserializing) : base(deserializing) { }
235
236    public override bool IsNoop(IInternalPushInterpreter interpreter) {
237      return interpreter.StringStack.IsEmpty ||
238             interpreter.StringStack.Top.Length == 0;
239    }
240
241    public override void Eval(IInternalPushInterpreter interpreter) {
242      interpreter.StringStack.Top = interpreter.StringStack.Top[0].ToString();
243    }
244  }
245
246  /// <summary>
247  /// Pushes last char of top STRING.
248  /// </summary>
249  [StorableClass]
250  [PushExpression(
251    StackTypes.String,
252    "STRING.LAST",
253    "Pushes last char of top STRING.")]
254  public class StringLastExpression : StatelessExpression {
255    public StringLastExpression() { }
256    [StorableConstructor]
257    protected StringLastExpression(bool deserializing) : base(deserializing) { }
258
259    public override bool IsNoop(IInternalPushInterpreter interpreter) {
260      return interpreter.StringStack.IsEmpty ||
261             interpreter.StringStack.Top.Length == 0;
262    }
263
264    public override void Eval(IInternalPushInterpreter interpreter) {
265      var str = interpreter.StringStack.Top;
266      var c = str[str.Length - 1].ToString();
267      interpreter.StringStack.Top = c;
268    }
269  }
270
271  /// <summary>
272  /// Pushes nth char of top STRING, whereby n is take from the INTEGER stack.
273  /// </summary>
274  [StorableClass]
275  [PushExpression(
276    StackTypes.String,
277    "STRING.NTH",
278    "Pushes nth char of top STRING, whereby n is take from the INTEGER stack.",
279    StackTypes.Integer)]
280  public class StringNthExpression : StatelessExpression {
281    public StringNthExpression() { }
282    [StorableConstructor]
283    protected StringNthExpression(bool deserializing) : base(deserializing) { }
284
285    public override bool IsNoop(IInternalPushInterpreter interpreter) {
286      return interpreter.StringStack.IsEmpty ||
287             interpreter.IntegerStack.IsEmpty ||
288             interpreter.StringStack.Top.Length == 0;
289    }
290
291    public override void Eval(IInternalPushInterpreter interpreter) {
292      var str = interpreter.StringStack.Top;
293      var index = str.Length == 1 ? 0 : interpreter.IntegerStack.Pop().AsInt(str.Length);
294      var c = str[index].ToString();
295      interpreter.StringStack.Top = c;
296    }
297  }
298
299  /// <summary>
300  /// Removes first char of top STRING.
301  /// </summary>
302  [StorableClass]
303  [PushExpression(
304    StackTypes.String,
305    "STRING.REST",
306    "Removes first char of top STRING.")]
307  public class StringRestExpression : StatelessExpression {
308    public StringRestExpression() { }
309    [StorableConstructor]
310    protected StringRestExpression(bool deserializing) : base(deserializing) { }
311
312    public override bool IsNoop(IInternalPushInterpreter interpreter) {
313      return interpreter.StringStack.IsEmpty ||
314             interpreter.StringStack.Top.Length == 0;
315    }
316
317    public override void Eval(IInternalPushInterpreter interpreter) {
318      var str = interpreter.StringStack.Top;
319      interpreter.StringStack.Top = str.Length == 1 ? string.Empty : str.Substring(1, str.Length - 1);
320    }
321  }
322
323  /// <summary>
324  /// Removes last char of top STRING.
325  /// </summary>
326  [StorableClass]
327  [PushExpression(
328    StackTypes.String,
329    "STRING.BUTLAST",
330    "Removes last char of top STRING.")]
331  public class StringButLastExpression : StatelessExpression {
332    public StringButLastExpression() { }
333    [StorableConstructor]
334    protected StringButLastExpression(bool deserializing) : base(deserializing) { }
335
336    public override bool IsNoop(IInternalPushInterpreter interpreter) {
337      return interpreter.StringStack.IsEmpty ||
338             interpreter.StringStack.Top.Length == 0;
339    }
340
341    public override void Eval(IInternalPushInterpreter interpreter) {
342      var str = interpreter.StringStack.Top;
343      interpreter.StringStack.Top = str.Length == 1 ? string.Empty : str.Substring(0, str.Length - 1);
344    }
345  }
346
347  /// <summary>
348  /// Pushes length of top STRING onto the INTEGER stack.
349  /// </summary>
350  [StorableClass]
351  [PushExpression(
352    StackTypes.String,
353    "STRING.LENGTH",
354    "Pushes length of top STRING onto the INTEGER stack.",
355    StackTypes.Integer)]
356  public class StringLengthExpression : StatelessExpression {
357    public StringLengthExpression() { }
358    [StorableConstructor]
359    protected StringLengthExpression(bool deserializing) : base(deserializing) { }
360
361    public override bool IsNoop(IInternalPushInterpreter interpreter) {
362      return interpreter.StringStack.IsEmpty;
363    }
364
365    public override void Eval(IInternalPushInterpreter interpreter) {
366      var str = interpreter.StringStack.Pop();
367      interpreter.IntegerStack.Push(str.Length);
368    }
369  }
370
371  /// <summary>
372  /// Reverses the top STRING.
373  /// </summary>
374  [StorableClass]
375  [PushExpression(
376    StackTypes.String,
377    "STRING.REVERSE",
378    "Reverses the top STRING.")]
379  public class StringReverseExpression : StatelessExpression {
380    public StringReverseExpression() { }
381    [StorableConstructor]
382    protected StringReverseExpression(bool deserializing) : base(deserializing) { }
383
384    public override bool IsNoop(IInternalPushInterpreter interpreter) {
385      return interpreter.StringStack.IsEmpty || interpreter.StringStack.Top.Length <= 1;
386    }
387
388    public override void Eval(IInternalPushInterpreter interpreter) {
389      var chars = interpreter.StringStack.Top.ToArray();
390      Array.Reverse(chars);
391      interpreter.StringStack.Top = new string(chars);
392    }
393  }
394
395  /// <summary>
396  /// Maps every char of top STRING as separate string.
397  /// </summary>
398  [StorableClass]
399  [PushExpression(
400    StackTypes.String,
401    "STRING.PARSETOCHARS",
402    "Maps every char of top STRING as separate string.")]
403  public class StringParseToCharsExpression : StatelessExpression {
404    public StringParseToCharsExpression() { }
405    [StorableConstructor]
406    protected StringParseToCharsExpression(bool deserializing) : base(deserializing) { }
407
408    public override bool IsNoop(IInternalPushInterpreter interpreter) {
409      return interpreter.StringStack.IsEmpty;
410    }
411
412    public override void Eval(IInternalPushInterpreter interpreter) {
413      if (interpreter.StringStack.Top.Length == 0) {
414        interpreter.StringStack.Pop();
415        return;
416      }
417
418      var str = interpreter.StringStack.Top;
419      interpreter.StringStack.Top = str[0].ToString();
420
421      if (str.Length > 1) {
422        var chars = new string[str.Length - 1];
423        for (var i = 0; i < str.Length - 1; i++) {
424          chars[i] = str[i + 1].ToString();
425        }
426
427        interpreter.StringStack.Push(chars);
428      }
429    }
430  }
431
432  /// <summary>
433  /// Splits top STRING by whitespace chars.
434  /// </summary>
435  [StorableClass]
436  [PushExpression(
437    StackTypes.String,
438    "STRING.SPLIT",
439    "Splits top STRING by whitespace chars.")]
440  public class StringSplitExpression : StatelessExpression {
441    public StringSplitExpression() { }
442    [StorableConstructor]
443    protected StringSplitExpression(bool deserializing) : base(deserializing) { }
444
445    public override bool IsNoop(IInternalPushInterpreter interpreter) {
446      return interpreter.StringStack.IsEmpty;
447    }
448
449    public override void Eval(IInternalPushInterpreter interpreter) {
450      var words = interpreter.StringStack.Top
451        .Trim()
452        .Split()
453        .Where(x => !string.IsNullOrWhiteSpace(x))
454        .Reverse()
455        .ToArray();
456
457      if (words.Length == 0) {
458        interpreter.StringStack.Pop();
459      } else {
460        interpreter.StringStack.Top = words[0];
461        interpreter.StringStack.Push(words, 1);
462      }
463    }
464  }
465
466  /// <summary>
467  /// True if top string is empty.
468  /// </summary>
469  [StorableClass]
470  [PushExpression(
471    StackTypes.String,
472    "STRING.EMPTYSTRING",
473    "True if top STRING is empty.",
474    StackTypes.Boolean)]
475  public class StringEmptyStringExpression : StatelessExpression {
476    public StringEmptyStringExpression() { }
477    [StorableConstructor]
478    protected StringEmptyStringExpression(bool deserializing) : base(deserializing) { }
479
480    public override bool IsNoop(IInternalPushInterpreter interpreter) {
481      return interpreter.StringStack.IsEmpty;
482    }
483
484    public override void Eval(IInternalPushInterpreter interpreter) {
485      var str = interpreter.StringStack.Pop();
486      interpreter.BooleanStack.Push(str.Length == 0);
487    }
488  }
489
490  /// <summary>
491  /// True if top string is a substring of second string; false otherwise
492  /// </summary>
493  [StorableClass]
494  [PushExpression(
495    StackTypes.String,
496    "STRING.CONTAINS",
497    "True if top STRING is a substring of second STRING, false otherwise.",
498    StackTypes.Boolean)]
499  public class StringContainsExpression : StatelessExpression {
500    public StringContainsExpression() { }
501    [StorableConstructor]
502    protected StringContainsExpression(bool deserializing) : base(deserializing) { }
503
504    public override bool IsNoop(IInternalPushInterpreter interpreter) {
505      return interpreter.StringStack.Count < 2;
506    }
507
508    public override void Eval(IInternalPushInterpreter interpreter) {
509      var first = interpreter.StringStack[1];
510      var second = interpreter.StringStack.Top;
511      interpreter.StringStack.Remove(2);
512
513      interpreter.BooleanStack.Push(first.IndexOf(second, StringComparison.Ordinal) >= 0);
514    }
515  }
516
517  /// <summary>
518  /// True if the top char is in the top string
519  /// </summary>
520  [StorableClass]
521  [PushExpression(
522    StackTypes.String,
523    "STRING.CONTAINSCHAR",
524    "True if the top CHAR is in the top STRING.",
525    StackTypes.Boolean | StackTypes.Char)]
526  public class StringContainsCharExpression : StatelessExpression {
527    public StringContainsCharExpression() { }
528    [StorableConstructor]
529    protected StringContainsCharExpression(bool deserializing) : base(deserializing) { }
530
531    public override bool IsNoop(IInternalPushInterpreter interpreter) {
532      return interpreter.StringStack.IsEmpty ||
533             interpreter.CharStack.IsEmpty;
534    }
535
536    public override void Eval(IInternalPushInterpreter interpreter) {
537      var str = interpreter.StringStack.Pop();
538      var c = interpreter.CharStack.Pop();
539
540      interpreter.BooleanStack.Push(str.IndexOf(c) >= 0);
541    }
542  }
543
544  /// <summary>
545  /// Puts on the integer stack the index of the top char in the top string
546  /// </summary>
547  [StorableClass]
548  [PushExpression(
549    StackTypes.String,
550    "STRING.INDEXOFCHAR",
551    "Puts on the INTEGER stack the index of the top CHAR in the top STRING.",
552    StackTypes.Integer | StackTypes.Char)]
553  public class StringIndexOfCharExpression : StatelessExpression {
554    public StringIndexOfCharExpression() { }
555    [StorableConstructor]
556    protected StringIndexOfCharExpression(bool deserializing) : base(deserializing) { }
557
558    public override bool IsNoop(IInternalPushInterpreter interpreter) {
559      return interpreter.StringStack.IsEmpty ||
560             interpreter.CharStack.IsEmpty;
561    }
562
563    public override void Eval(IInternalPushInterpreter interpreter) {
564      var str = interpreter.StringStack.Pop();
565      var c = interpreter.CharStack.Pop();
566
567      interpreter.IntegerStack.Push(str.IndexOf(c));
568    }
569  }
570
571  /// <summary>
572  /// The number of times the top char is in the top string
573  /// </summary>
574  [StorableClass]
575  [PushExpression(
576    StackTypes.String,
577    "STRING.OCCURRENCESOFCHAR",
578    "The number of times the top CHAR is in the top STRING.",
579    StackTypes.Integer | StackTypes.Char)]
580  public class StringOccurrencesOfCharExpression : StatelessExpression {
581    public StringOccurrencesOfCharExpression() { }
582    [StorableConstructor]
583    protected StringOccurrencesOfCharExpression(bool deserializing) : base(deserializing) { }
584
585    public override bool IsNoop(IInternalPushInterpreter interpreter) {
586      return interpreter.StringStack.IsEmpty ||
587             interpreter.CharStack.IsEmpty;
588    }
589
590    public override void Eval(IInternalPushInterpreter interpreter) {
591      var str = interpreter.StringStack.Pop();
592      var c = interpreter.CharStack.Pop();
593
594      var count = 0;
595      for (var i = 0; i < str.Length; i++)
596        if (str[i] == c) count++;
597
598      interpreter.IntegerStack.Push(count);
599    }
600  }
601
602  /// <summary>
603  /// In third STRING, replaces second string with first string
604  /// </summary>
605  [StorableClass]
606  [PushExpression(
607    StackTypes.String,
608    "STRING.REPLACE",
609    "In third STRING, replaces second STRING with first STRING.")]
610  public class StringReplaceExpression : StatelessExpression {
611    public StringReplaceExpression() { }
612    [StorableConstructor]
613    protected StringReplaceExpression(bool deserializing) : base(deserializing) { }
614
615    public override bool IsNoop(IInternalPushInterpreter interpreter) {
616      return interpreter.StringStack.Count < 3;
617    }
618
619    public override void Eval(IInternalPushInterpreter interpreter) {
620      var third = interpreter.StringStack[2];
621      var second = interpreter.StringStack[1];
622      var first = interpreter.StringStack[0];
623      interpreter.StringStack.Remove(2);
624
625      interpreter.StringStack.Top = third.Length == 0 || second.Length == 0
626        ? third
627        : third.Replace(second, first);
628    }
629  }
630
631  /// <summary>
632  /// In third STRING, replaces first occurrence of second string with first string
633  /// </summary>
634  [StorableClass]
635  [PushExpression(
636    StackTypes.String,
637    "STRING.REPLACEFIRST",
638    "In third STRING, replaces first occurrence of second STRING with first STRING")]
639  public class StringReplaceFirstExpression : StatelessExpression {
640    public StringReplaceFirstExpression() { }
641    [StorableConstructor]
642    protected StringReplaceFirstExpression(bool deserializing) : base(deserializing) { }
643
644    public override bool IsNoop(IInternalPushInterpreter interpreter) {
645      return interpreter.StringStack.Count < 3;
646    }
647
648    public override void Eval(IInternalPushInterpreter interpreter) {
649      var third = interpreter.StringStack[2];
650      var second = interpreter.StringStack[1];
651      var first = interpreter.StringStack[0];
652      interpreter.StringStack.Remove(2);
653
654      interpreter.StringStack.Top = third.Length == 0 || second.Length == 0
655        ? third
656        : ReplaceFirst(third, second, first);
657    }
658
659    private static string ReplaceFirst(string text, string search, string replace) {
660      var pos = text.IndexOf(search, StringComparison.Ordinal);
661      return pos < 0 ? text : text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
662    }
663  }
664
665  /// <summary>
666  /// In top STRING, replaces all occurrences of second char with first char
667  /// </summary>
668  [StorableClass]
669  [PushExpression(
670    StackTypes.String,
671    "STRING.REPLACECHAR",
672    "In top STRING, replaces all occurrences of second CHAR with first CHAR.",
673    StackTypes.Char)]
674  public class StringReplaceCharExpression : StatelessExpression {
675    public StringReplaceCharExpression() { }
676    [StorableConstructor]
677    protected StringReplaceCharExpression(bool deserializing) : base(deserializing) { }
678
679    public override bool IsNoop(IInternalPushInterpreter interpreter) {
680      return interpreter.StringStack.IsEmpty ||
681             interpreter.CharStack.Count < 2;
682    }
683
684    public override void Eval(IInternalPushInterpreter interpreter) {
685      var first = interpreter.CharStack[1];
686      var second = interpreter.CharStack.Top;
687      interpreter.CharStack.Remove(2);
688
689      var result = interpreter.StringStack.Top.Replace(first, second);
690      interpreter.StringStack.Top = result;
691    }
692  }
693
694  /// <summary>
695  /// In top STRING, replaces first occurrence of second char with first char
696  /// </summary>
697  [StorableClass]
698  [PushExpression(
699    StackTypes.String,
700    "STRING.REPLACEFIRSTCHAR",
701    "In top STRING, replaces first occurrence of second CHAR with first CHAR.",
702    StackTypes.Char)]
703  public class StringReplaceFirstCharExpression : StatelessExpression {
704    public StringReplaceFirstCharExpression() { }
705    [StorableConstructor]
706    protected StringReplaceFirstCharExpression(bool deserializing) : base(deserializing) { }
707
708    public override bool IsNoop(IInternalPushInterpreter interpreter) {
709      return interpreter.StringStack.IsEmpty ||
710             interpreter.CharStack.Count < 2;
711    }
712
713    public override void Eval(IInternalPushInterpreter interpreter) {
714      var str = interpreter.StringStack.Top;
715      var first = interpreter.CharStack[1];
716      var second = interpreter.CharStack.Top;
717      interpreter.CharStack.Remove(2);
718
719      var pos = str.IndexOf(first);
720
721      if (pos < 0)
722        return;
723
724      var result = str.Substring(0, pos) +
725                   second +
726                   str.Substring(Math.Min(pos + 1, str.Length - 1));
727
728      interpreter.StringStack.Top = result;
729    }
730  }
731
732  /// <summary>
733  /// In top STRING, remove all occurrences of char
734  /// </summary>
735  [StorableClass]
736  [PushExpression(
737    StackTypes.String,
738    "STRING.REMOVECHAR",
739    "In top STRING, remove all occurrences of top CHAR.",
740    StackTypes.Char)]
741  public class StringRemoveCharExpression : StatelessExpression {
742    public StringRemoveCharExpression() { }
743    [StorableConstructor]
744    protected StringRemoveCharExpression(bool deserializing) : base(deserializing) { }
745
746    public override bool IsNoop(IInternalPushInterpreter interpreter) {
747      return interpreter.StringStack.IsEmpty ||
748             interpreter.CharStack.IsEmpty;
749    }
750
751    public override void Eval(IInternalPushInterpreter interpreter) {
752      var c = interpreter.CharStack.Pop();
753      var result = interpreter.StringStack.Top.Trim(c);
754      interpreter.StringStack.Top = result;
755    }
756  }
757
758  /// <summary>
759  /// Sets char at index in string
760  /// </summary>
761  [StorableClass]
762  [PushExpression(
763    StackTypes.String,
764    "STRING.SETCHAR",
765    "Sets top CHAR at index in top STRING, whereby the index is taken from the INTEGER stack.",
766    StackTypes.Char | StackTypes.Integer)]
767  public class StringSetCharExpression : StatelessExpression {
768    public StringSetCharExpression() { }
769    [StorableConstructor]
770    protected StringSetCharExpression(bool deserializing) : base(deserializing) { }
771
772    public override bool IsNoop(IInternalPushInterpreter interpreter) {
773      return interpreter.StringStack.IsEmpty ||
774             interpreter.CharStack.IsEmpty ||
775             interpreter.IntegerStack.IsEmpty;
776    }
777
778    public override void Eval(IInternalPushInterpreter interpreter) {
779      var str = interpreter.StringStack.Top;
780      var c = interpreter.CharStack.Pop();
781      var x = interpreter.IntegerStack.Pop();
782
783      if (str.Length == 0) return;
784      if (str.Length == 1) {
785        interpreter.StringStack.Top = c.ToString();
786        return;
787      }
788
789      var pos = x.AsInt(str.Length);
790      var result = str.Substring(0, pos) + c + str.Substring(Math.Min(pos + 1, str.Length - 1));
791
792      interpreter.StringStack.Top = result;
793    }
794  }
795
796  /// <summary>
797  /// Iterates over a string using the code on the exec stack.
798  /// </summary>
799  [StorableClass]
800  [PushExpression(
801    StackTypes.String,
802    "STRING.ITERATE",
803    "Iterates over the top STRING using the CODE on the EXEC stack.",
804    StackTypes.Exec | StackTypes.Char, execIn: 1)]
805  public class StringIterateExpression : StatelessExpression {
806    public StringIterateExpression() { }
807    [StorableConstructor]
808    protected StringIterateExpression(bool deserializing) : base(deserializing) { }
809
810    public override bool IsNoop(IInternalPushInterpreter interpreter) {
811      return interpreter.StringStack.IsEmpty ||
812             interpreter.ExecStack.IsEmpty;
813    }
814
815    public override void Eval(IInternalPushInterpreter interpreter) {
816      var str = interpreter.StringStack.Pop();
817
818      if (str.Length == 0) {
819        interpreter.ExecStack.Pop();
820      }
821      // If the rest of the string is empty, we're done iterating.
822      else if (str.Length == 1) {
823        interpreter.CharStack.Push(str[0]);
824      } else {
825        var pool = interpreter.PoolContainer.GetStatefulExpressionPool<StringPushExpression>();
826
827        interpreter.CharStack.Push(str[0]);
828        interpreter.ExecStack.Push(
829          this,
830          StringPushExpression.Create(pool, str.Substring(1)),
831          interpreter.ExecStack.Top);
832      }
833    }
834  }
835}
Note: See TracBrowser for help on using the repository browser.