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