mittens 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +1 -0
  4. data/README.md +2 -2
  5. data/Rakefile +10 -3
  6. data/lib/mittens/version.rb +1 -1
  7. data/vendor/snowball/.github/workflows/ci.yml +144 -17
  8. data/vendor/snowball/.github/workflows/coverage.yml +117 -0
  9. data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
  10. data/vendor/snowball/.gitignore +33 -7
  11. data/vendor/snowball/CONTRIBUTING.rst +7 -0
  12. data/vendor/snowball/COPYING +1 -1
  13. data/vendor/snowball/GNUmakefile +736 -298
  14. data/vendor/snowball/NEWS +1394 -7
  15. data/vendor/snowball/README.rst +8 -8
  16. data/vendor/snowball/ada/generate/generate.adb +5 -5
  17. data/vendor/snowball/ada/src/stemmer.adb +177 -188
  18. data/vendor/snowball/ada/src/stemmer.ads +86 -89
  19. data/vendor/snowball/ada/src/stemwords.adb +21 -5
  20. data/vendor/snowball/algorithms/czech.sbl +255 -0
  21. data/vendor/snowball/algorithms/danish.sbl +22 -10
  22. data/vendor/snowball/algorithms/english.sbl +7 -4
  23. data/vendor/snowball/algorithms/esperanto.sbl +6 -7
  24. data/vendor/snowball/algorithms/estonian.sbl +9 -4
  25. data/vendor/snowball/algorithms/finnish.sbl +33 -21
  26. data/vendor/snowball/algorithms/german.sbl +5 -0
  27. data/vendor/snowball/algorithms/indonesian.sbl +115 -96
  28. data/vendor/snowball/algorithms/italian.sbl +26 -1
  29. data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
  30. data/vendor/snowball/algorithms/norwegian.sbl +17 -6
  31. data/vendor/snowball/algorithms/persian.sbl +387 -0
  32. data/vendor/snowball/algorithms/polish.sbl +177 -0
  33. data/vendor/snowball/algorithms/sesotho.sbl +115 -0
  34. data/vendor/snowball/algorithms/turkish.sbl +4 -4
  35. data/vendor/snowball/compiler/analyser.c +2002 -711
  36. data/vendor/snowball/compiler/driver.c +460 -298
  37. data/vendor/snowball/compiler/generator.c +439 -1965
  38. data/vendor/snowball/compiler/generator_ada.c +605 -430
  39. data/vendor/snowball/compiler/generator_c.c +2227 -0
  40. data/vendor/snowball/compiler/generator_csharp.c +365 -274
  41. data/vendor/snowball/compiler/generator_dart.c +1476 -0
  42. data/vendor/snowball/compiler/generator_go.c +348 -270
  43. data/vendor/snowball/compiler/generator_java.c +330 -233
  44. data/vendor/snowball/compiler/generator_js.c +534 -385
  45. data/vendor/snowball/compiler/generator_pascal.c +361 -320
  46. data/vendor/snowball/compiler/generator_php.c +1445 -0
  47. data/vendor/snowball/compiler/generator_python.c +399 -299
  48. data/vendor/snowball/compiler/generator_rust.c +370 -261
  49. data/vendor/snowball/compiler/generator_zig.c +1474 -0
  50. data/vendor/snowball/compiler/header.h +153 -86
  51. data/vendor/snowball/compiler/space.c +121 -63
  52. data/vendor/snowball/compiler/tokeniser.c +286 -182
  53. data/vendor/snowball/compiler/tokens.h +71 -0
  54. data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
  55. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
  56. data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
  57. data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
  58. data/vendor/snowball/cxx/.gitignore +4 -0
  59. data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
  60. data/vendor/snowball/cxx/stemmer.h +12 -0
  61. data/vendor/snowball/cxx/stemwords.cxx +176 -0
  62. data/vendor/snowball/cxx/utilities.cxx +2 -0
  63. data/vendor/snowball/dart/.gitignore +4 -0
  64. data/vendor/snowball/dart/analysis_options.yaml +1 -0
  65. data/vendor/snowball/dart/example/test_app.dart +65 -0
  66. data/vendor/snowball/dart/generate_algorithms.pl +21 -0
  67. data/vendor/snowball/dart/lib/snowball.dart +18 -0
  68. data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
  69. data/vendor/snowball/dart/pubspec.yaml +17 -0
  70. data/vendor/snowball/doc/libstemmer_dart_README +37 -0
  71. data/vendor/snowball/doc/libstemmer_js_README +2 -2
  72. data/vendor/snowball/doc/libstemmer_php_README +38 -0
  73. data/vendor/snowball/doc/libstemmer_python_README +3 -3
  74. data/vendor/snowball/examples/stemwords.c +18 -3
  75. data/vendor/snowball/go/README.md +12 -4
  76. data/vendor/snowball/go/env.go +12 -14
  77. data/vendor/snowball/go/stemwords/main.go +2 -1
  78. data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
  79. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
  80. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
  81. data/vendor/snowball/javascript/base-stemmer.js +219 -252
  82. data/vendor/snowball/javascript/stemwords.js +86 -58
  83. data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
  84. data/vendor/snowball/libstemmer/modules.txt +4 -0
  85. data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
  86. data/vendor/snowball/php/base-stemmer.php +453 -0
  87. data/vendor/snowball/php/stemwords.php +25 -0
  88. data/vendor/snowball/python/create_init.py +16 -21
  89. data/vendor/snowball/python/pyproject.toml +3 -0
  90. data/vendor/snowball/python/setup.py +5 -7
  91. data/vendor/snowball/python/snowballstemmer/among.py +1 -2
  92. data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
  93. data/vendor/snowball/python/stemwords.py +72 -63
  94. data/vendor/snowball/runtime/api.c +11 -42
  95. data/vendor/snowball/runtime/api.h +11 -9
  96. data/vendor/snowball/runtime/snowball_runtime.h +110 -0
  97. data/vendor/snowball/runtime/utilities.c +282 -106
  98. data/vendor/snowball/rust/src/main.rs +2 -2
  99. data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
  100. data/vendor/snowball/tests/compilertest +62 -0
  101. data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
  102. data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
  103. data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
  104. data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
  105. data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
  106. data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
  107. data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
  108. data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
  109. data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
  110. data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
  111. data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
  112. data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
  113. data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
  114. data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
  115. data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
  116. data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
  117. data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
  118. data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
  119. data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
  120. data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
  121. data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
  122. data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
  123. data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
  124. data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
  125. data/vendor/snowball/tests/runtime/among.sbl +19 -0
  126. data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
  127. data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
  128. data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
  129. data/vendor/snowball/tests/runtime/externals.sbl +22 -0
  130. data/vendor/snowball/tests/runtime/hop.sbl +12 -0
  131. data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
  132. data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
  133. data/vendor/snowball/tests/runtime/naming.sbl +20 -0
  134. data/vendor/snowball/tests/runtime/not.sbl +30 -0
  135. data/vendor/snowball/tests/runtime/or.sbl +17 -0
  136. data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
  137. data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
  138. data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
  139. data/vendor/snowball/tests/runtime/slice.sbl +27 -0
  140. data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
  141. data/vendor/snowball/tests/runtime/strings.sbl +66 -0
  142. data/vendor/snowball/tests/runtime/test.sbl +19 -0
  143. data/vendor/snowball/tests/stemtest.c +41 -1
  144. data/vendor/snowball/tests/syntax/canon.sbl +32 -0
  145. data/vendor/snowball/tests/syntax/canon.stderr +0 -0
  146. data/vendor/snowball/tests/syntax/canon.syntax +57 -0
  147. data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
  148. data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
  149. data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
  150. data/vendor/snowball/tests/syntax/inline.sbl +144 -0
  151. data/vendor/snowball/tests/syntax/inline.stderr +0 -0
  152. data/vendor/snowball/tests/syntax/inline.syntax +121 -0
  153. data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
  154. data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
  155. data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
  156. data/vendor/snowball/tests/syntax/loops.sbl +14 -0
  157. data/vendor/snowball/tests/syntax/loops.stderr +9 -0
  158. data/vendor/snowball/tests/syntax/loops.syntax +29 -0
  159. data/vendor/snowball/tests/syntax/noops.sbl +76 -0
  160. data/vendor/snowball/tests/syntax/noops.stderr +27 -0
  161. data/vendor/snowball/tests/syntax/noops.syntax +135 -0
  162. data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
  163. data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
  164. data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
  165. data/vendor/snowball/tests/syntax/unused.sbl +18 -0
  166. data/vendor/snowball/tests/syntax/unused.stderr +7 -0
  167. data/vendor/snowball/tests/syntax/unused.syntax +3 -0
  168. data/vendor/snowball/zig/env.zig +599 -0
  169. data/vendor/snowball/zig/generate_algorithms.pl +19 -0
  170. data/vendor/snowball/zig/stemwords.zig +123 -0
  171. metadata +102 -4
  172. data/vendor/snowball/compiler/syswords.h +0 -86
  173. data/vendor/snowball/runtime/header.h +0 -62
@@ -1,113 +1,90 @@
1
1
  #include <assert.h>
2
+ #include <ctype.h>
3
+ #include <stdio.h> /* for fprintf etc */
2
4
  #include <stdlib.h> /* for exit */
3
5
  #include <string.h> /* for strlen */
4
- #include <stdio.h> /* for fprintf etc */
5
6
  #include "header.h"
6
7
 
7
8
  #define BASE_UNIT "SnowballProgram"
8
9
  #define BASE_CLASS "T" BASE_UNIT
9
10
 
10
- /* prototypes */
11
+ /* prototype functions for recursive use: */
11
12
 
12
13
  static void generate(struct generator * g, struct node * p);
13
14
  static void w(struct generator * g, const char * s);
14
15
  static void writef(struct generator * g, const char * s, struct node * p);
15
16
 
16
- static int new_label(struct generator * g) {
17
- return g->next_label++;
18
- }
17
+ /* Write routines for items from the syntax tree */
19
18
 
20
- static struct str * vars_newname(struct generator * g) {
21
- struct str * output;
22
- g->var_number++;
23
- output = str_new();
24
- str_append_string(output, "v_");
25
- str_append_int(output, g->var_number);
26
- return output;
19
+ static void write_relop(struct generator * g, int relop) {
20
+ // Relational operators are the same as C, save for (in-)equality.
21
+ switch (relop) {
22
+ case c_eq: write_string(g, " = "); break;
23
+ case c_ne: write_string(g, " <> "); break;
24
+ default: write_c_relop(g, relop);
25
+ }
27
26
  }
28
27
 
29
- /* Write routines for items from the syntax tree */
30
-
31
28
  static void write_varname(struct generator * g, struct name * p) {
32
- if (p->type != t_external) {
29
+ if (p->type == t_external) {
30
+ if (g->options->externals_prefix) {
31
+ write_string(g, g->options->externals_prefix);
32
+ }
33
+ } else {
33
34
  /* Pascal identifiers are case-insensitive but Snowball identifiers
34
- * should be case-sensitive. To address this, we encode the case of
35
- * the identifier. For readability of the generated code, the
36
- * encoding tries to be minimally intrusive for common cases.
37
- *
38
- * After the letter which indicates the type and before the "_" we
39
- * encode the case pattern in the Snowball identifier using "U" for
40
- * an upper-case letter, "l" for a lower-case letter and nothing for
41
- * other characters. Any trailing string of "l" is omitted (since
42
- * it's redundant and decreases readability).
43
- *
44
- * Identifiers without any upper-case encode most simply, e.g. I_foo2
35
+ * should be case-sensitive. To address this, if any groups of
36
+ * identifiers of the same type have the same case, we insert a counter
37
+ * after the type-code for all but one of them. This count is unique
38
+ * within each type of variable so this avoid collisions while being
39
+ * minimally intrusive on the readability of the generated code.
45
40
  *
46
- * A capitalised identifier is also concise, e.g. IU_Foo2
41
+ * So for example:
47
42
  *
48
- * All-caps gives a string of Us, e.g. IUUUUUUUU_SHOUTING
49
- *
50
- * But any example can be handled, e.g. IUllU_Foo79_Bar
43
+ * Snowball integer `i` -> Pascal `I_i`
44
+ * Snowball integer `I` -> Pascal `I2_i`
51
45
  *
52
46
  * We don't try to solve this problem for external identifiers - it
53
47
  * seems more helpful to leave those alone and encourage snowball
54
48
  * program authors to avoid naming externals which only differ by
55
49
  * case.
50
+ *
51
+ * We use the same naming scheme for both global and local variables.
56
52
  */
57
- int len = SIZE(p->s);
58
- int lower_pending = 0;
59
53
  write_char(g, "SBIrxg"[p->type]);
60
- for (int i = 0; i != len; ++i) {
61
- int ch = p->s[i];
62
- if (ch >= 'a' && ch <= 'z') {
63
- ++lower_pending;
64
- } else if (ch >= 'A' && ch <= 'Z') {
65
- while (lower_pending) {
66
- write_char(g, 'l');
67
- --lower_pending;
68
- }
69
- write_char(g, 'U');
70
- }
54
+ if (p->case_collision) {
55
+ write_int(g, p->count);
71
56
  }
72
-
73
57
  write_char(g, '_');
74
58
  }
75
59
  write_s(g, p->s);
76
60
  }
77
61
 
78
62
  static void write_literal_string(struct generator * g, symbol * p) {
79
- write_char(g, '\'');
63
+ if (SIZE(p) == 0) {
64
+ write_string(g, "''");
65
+ return;
66
+ }
67
+ bool in_quotes = false;
80
68
  for (int i = 0; i < SIZE(p); i++) {
81
69
  int ch = p[i];
82
- if (ch == '\'') {
83
- write_string(g, "''");
84
- } else if (32 <= ch && ch < 127) {
70
+ if (32 <= ch && ch < 127) {
71
+ if (!in_quotes) {
72
+ write_char(g, '\'');
73
+ in_quotes = true;
74
+ }
75
+ if (ch == '\'') write_char(g, '\'');
85
76
  write_char(g, ch);
86
77
  } else {
87
- write_char(g, '\'');
78
+ if (in_quotes) {
79
+ write_char(g, '\'');
80
+ in_quotes = false;
81
+ }
88
82
  write_char(g, '#');
89
- write_int (g, ch);
90
- write_char(g, '\'');
83
+ write_int(g, ch);
91
84
  }
92
85
  }
93
- write_char(g, '\'');
94
- }
95
-
96
- static void write_margin(struct generator * g) {
97
- for (int i = 0; i < g->margin; i++) write_string(g, " ");
98
- }
99
-
100
- static void write_relop(struct generator * g, int relop) {
101
- switch (relop) {
102
- case c_eq: write_string(g, " = "); break;
103
- case c_ne: write_string(g, " <> "); break;
104
- case c_gt: write_string(g, " > "); break;
105
- case c_ge: write_string(g, " >= "); break;
106
- case c_lt: write_string(g, " < "); break;
107
- case c_le: write_string(g, " <= "); break;
108
- default:
109
- fprintf(stderr, "Unexpected type #%d in generate_integer_test\n", relop);
110
- exit(1);
86
+ if (in_quotes) {
87
+ write_char(g, '\'');
111
88
  }
112
89
  }
113
90
 
@@ -119,7 +96,7 @@ static void write_declare(struct generator * g,
119
96
  g->outbuf = g->declarations;
120
97
  write_string(g, " ");
121
98
  writef(g, declaration, p);
122
- write_string(g, ";");
99
+ write_char(g, ';');
123
100
  write_newline(g);
124
101
  g->outbuf = temp;
125
102
  }
@@ -127,9 +104,8 @@ static void write_declare(struct generator * g,
127
104
  static void write_comment(struct generator * g, struct node * p) {
128
105
  if (!g->options->comments) return;
129
106
  write_margin(g);
130
- write_string(g, "{ ");
131
- write_comment_content(g, p);
132
- write_string(g, " }");
107
+ write_string(g, "// ");
108
+ write_comment_content(g, p, NULL);
133
109
  write_newline(g);
134
110
  }
135
111
 
@@ -154,7 +130,7 @@ static void append_restore_string(struct node * p, struct str * out, struct str
154
130
  str_append_string(out, "FCursor := ");
155
131
  if (p->mode != m_forward) str_append_string(out, "FLimit - ");
156
132
  str_append(out, savevar);
157
- str_append_string(out, ";");
133
+ str_append_ch(out, ';');
158
134
  }
159
135
 
160
136
  static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
@@ -169,25 +145,12 @@ static void write_inc_cursor(struct generator * g, struct node * p) {
169
145
  write_newline(g);
170
146
  }
171
147
 
172
- static void wsetlab_begin(struct generator * g) {
173
- w(g, "~MRepeat~N~+");
174
- }
175
-
176
- static void wsetlab_end(struct generator * g, int n) {
177
- w(g, "~-~MUntil True;~N");
148
+ static void wsetl(struct generator * g, int n) {
178
149
  w(g, "lab");
179
150
  write_int(g, n);
180
151
  w(g, ":~N");
181
152
  }
182
153
 
183
- static void wgotol(struct generator * g, int n) {
184
- write_margin(g);
185
- write_string(g, "goto lab");
186
- write_int(g, n);
187
- write_string(g, ";");
188
- write_newline(g);
189
- }
190
-
191
154
  static void write_failure(struct generator * g) {
192
155
  if (str_len(g->failure_str) != 0) {
193
156
  write_margin(g);
@@ -198,15 +161,15 @@ static void write_failure(struct generator * g) {
198
161
  switch (g->failure_label) {
199
162
  case x_return:
200
163
  write_string(g, "Begin Result := False; Exit; End;");
201
- g->unreachable = true;
202
164
  break;
203
165
  default:
204
166
  write_string(g, "goto lab");
205
167
  write_int(g, g->failure_label);
206
- write_string(g, ";");
207
- g->unreachable = true;
168
+ write_char(g, ';');
169
+ g->label_used = 1;
208
170
  }
209
171
  write_newline(g);
172
+ g->unreachable = true;
210
173
  }
211
174
 
212
175
  static void write_failure_if(struct generator * g, const char * s, struct node * p) {
@@ -230,7 +193,6 @@ static void write_check_limit(struct generator * g, struct node * p) {
230
193
 
231
194
  /* Formatted write. */
232
195
  static void writef(struct generator * g, const char * input, struct node * p) {
233
- (void)p;
234
196
  int i = 0;
235
197
 
236
198
  while (input[i]) {
@@ -276,23 +238,18 @@ static void writef(struct generator * g, const char * input, struct node * p) {
276
238
  continue;
277
239
  }
278
240
  case 'V':
279
- case 'W': {
280
- int j = input[i++] - '0';
281
- if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
282
- goto invalid_escape2;
283
- write_varname(g, g->V[j]);
241
+ case 'W':
242
+ write_varname(g, p->name);
284
243
  continue;
285
- }
286
- case 'L': {
287
- int j = input[i++] - '0';
288
- if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
289
- goto invalid_escape2;
290
- write_literal_string(g, g->L[j]);
244
+ case 'L':
245
+ write_literal_string(g, p->literalstring);
246
+ continue;
247
+ case 's':
248
+ write_int(g, SIZE(p->literalstring));
291
249
  continue;
292
- }
293
250
  case '+': g->margin++; continue;
294
251
  case '-': g->margin--; continue;
295
- case 'n': write_string(g, g->options->name); continue;
252
+ case 'n': write_s(g, g->options->name); continue;
296
253
  default:
297
254
  printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
298
255
  ch, input);
@@ -313,38 +270,52 @@ static void generate_AE(struct generator * g, struct node * p) {
313
270
  const char * s;
314
271
  switch (p->type) {
315
272
  case c_name:
316
- write_varname(g, p->name); break;
273
+ write_varname(g, p->name);
274
+ break;
317
275
  case c_number:
318
- write_int(g, p->number); break;
276
+ write_int(g, p->number);
277
+ break;
319
278
  case c_maxint:
320
- write_string(g, "MAXINT"); break;
279
+ write_string(g, "MAXINT");
280
+ break;
321
281
  case c_minint:
322
- write_string(g, "(-MAXINT - 1)"); break;
282
+ write_string(g, "(-MAXINT - 1)");
283
+ break;
323
284
  case c_neg:
324
- write_char(g, '-'); generate_AE(g, p->right); break;
285
+ write_char(g, '-');
286
+ generate_AE(g, p->right);
287
+ break;
325
288
  case c_multiply:
326
- s = " * "; goto label0;
327
- case c_plus:
328
- s = " + "; goto label0;
329
- case c_minus:
330
- s = " - "; goto label0;
289
+ s = " * ";
290
+ goto label0;
331
291
  case c_divide:
332
292
  s = " div ";
293
+ goto label0;
294
+ case c_plus:
295
+ s = " + ";
296
+ goto label0;
297
+ case c_minus:
298
+ s = " - ";
333
299
  label0:
334
- write_char(g, '('); generate_AE(g, p->left);
335
- write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
300
+ write_char(g, '(');
301
+ generate_AE(g, p->left);
302
+ write_string(g, s);
303
+ generate_AE(g, p->right);
304
+ write_char(g, ')');
305
+ break;
336
306
  case c_cursor:
337
- w(g, "FCursor"); break;
307
+ w(g, "FCursor");
308
+ break;
338
309
  case c_limit:
339
- w(g, p->mode == m_forward ? "FLimit" : "FBkLimit"); break;
310
+ w(g, p->mode == m_forward ? "FLimit" : "FBkLimit");
311
+ break;
340
312
  case c_len:
341
313
  case c_size:
342
314
  w(g, "Length(current)");
343
315
  break;
344
316
  case c_lenof:
345
317
  case c_sizeof:
346
- g->V[0] = p->name;
347
- w(g, "Length(~V0)");
318
+ writef(g, "Length(~V)", p);
348
319
  break;
349
320
  }
350
321
  }
@@ -360,13 +331,15 @@ static void generate_bra(struct generator * g, struct node * p) {
360
331
 
361
332
  static void generate_and(struct generator * g, struct node * p) {
362
333
  struct str * savevar = NULL;
363
- if (K_needed(g, p->left)) {
334
+ if (K_needed_for_and(p->left)) {
364
335
  savevar = vars_newname(g);
365
336
  }
366
337
 
367
338
  write_comment(g, p);
368
339
 
369
- if (savevar) write_savecursor(g, p, savevar);
340
+ if (savevar) {
341
+ write_savecursor(g, p, savevar);
342
+ }
370
343
 
371
344
  p = p->left;
372
345
  while (p) {
@@ -383,20 +356,22 @@ static void generate_and(struct generator * g, struct node * p) {
383
356
 
384
357
  static void generate_or(struct generator * g, struct node * p) {
385
358
  struct str * savevar = NULL;
386
- if (K_needed(g, p->left)) {
359
+ if (K_needed_for_or(p->left)) {
387
360
  savevar = vars_newname(g);
388
361
  }
389
362
 
363
+ int used = g->label_used;
390
364
  int a0 = g->failure_label;
391
365
  struct str * a1 = str_copy(g->failure_str);
392
366
 
393
- int out_lab = new_label(g);
394
- int end_unreachable = true;
367
+ bool end_unreachable = true;
395
368
 
396
369
  write_comment(g, p);
397
- wsetlab_begin(g);
370
+ w(g, "~MRepeat~N~+");
398
371
 
399
- if (savevar) write_savecursor(g, p, savevar);
372
+ if (savevar && K_needed_node_on_f(p)) {
373
+ write_savecursor(g, p, savevar);
374
+ }
400
375
 
401
376
  p = p->left;
402
377
  str_clear(g->failure_str);
@@ -407,26 +382,33 @@ static void generate_or(struct generator * g, struct node * p) {
407
382
  fprintf(stderr, "Error: \"or\" node without children nodes.");
408
383
  exit(1);
409
384
  }
410
- while (p->right) {
411
- g->failure_label = new_label(g);
412
- wsetlab_begin(g);
385
+ while (p->right != NULL) {
386
+ int label = new_label(g);
387
+ g->failure_label = label;
388
+ g->label_used = 0;
413
389
  generate(g, p);
414
390
  if (!g->unreachable) {
415
- wgotol(g, out_lab);
391
+ w(g, "~MBreak;~N");
416
392
  end_unreachable = false;
417
393
  }
418
- wsetlab_end(g, g->failure_label);
394
+
395
+ if (g->label_used)
396
+ wsetl(g, g->failure_label);
419
397
  g->unreachable = false;
420
- if (savevar) write_restorecursor(g, p, savevar);
398
+ if (savevar) {
399
+ write_restorecursor(g, p, savevar);
400
+ }
421
401
  p = p->right;
422
402
  }
423
403
 
404
+ g->label_used = used;
424
405
  g->failure_label = a0;
425
406
  str_delete(g->failure_str);
426
407
  g->failure_str = a1;
427
408
 
428
409
  generate(g, p);
429
- wsetlab_end(g, out_lab);
410
+
411
+ w(g, "~-~MUntil True;~N");
430
412
  if (!end_unreachable) {
431
413
  g->unreachable = false;
432
414
  }
@@ -443,10 +425,9 @@ static void generate_backwards(struct generator * g, struct node * p) {
443
425
  w(g, "~MFCursor := FBkLimit;~N");
444
426
  }
445
427
 
446
-
447
428
  static void generate_not(struct generator * g, struct node * p) {
448
429
  struct str * savevar = NULL;
449
- if (K_needed(g, p->left)) {
430
+ if (K_needed_node_on_f(p->left)) {
450
431
  savevar = vars_newname(g);
451
432
  }
452
433
 
@@ -459,12 +440,10 @@ static void generate_not(struct generator * g, struct node * p) {
459
440
  write_savecursor(g, p, savevar);
460
441
  }
461
442
 
462
- g->failure_label = new_label(g);
443
+ int label = new_label(g);
444
+ g->failure_label = label;
463
445
  str_clear(g->failure_str);
464
446
 
465
- wsetlab_begin(g);
466
- int l = g->failure_label;
467
-
468
447
  generate(g, p->left);
469
448
 
470
449
  g->failure_label = a0;
@@ -473,7 +452,9 @@ static void generate_not(struct generator * g, struct node * p) {
473
452
 
474
453
  if (!g->unreachable) write_failure(g);
475
454
 
476
- wsetlab_end(g, l);
455
+ if (g->label_used)
456
+ wsetl(g, label);
457
+
477
458
  g->unreachable = false;
478
459
 
479
460
  if (savevar) {
@@ -483,14 +464,15 @@ static void generate_not(struct generator * g, struct node * p) {
483
464
  }
484
465
  }
485
466
 
486
-
487
467
  static void generate_try(struct generator * g, struct node * p) {
488
468
  struct str * savevar = NULL;
489
- if (K_needed(g, p->left)) {
469
+ if (K_needed(p->left)) {
490
470
  savevar = vars_newname(g);
491
471
  }
492
472
 
493
- g->failure_label = new_label(g);
473
+ int label = new_label(g);
474
+ g->failure_label = label;
475
+ g->label_used = 0;
494
476
  str_clear(g->failure_str);
495
477
 
496
478
  write_comment(g, p);
@@ -499,9 +481,10 @@ static void generate_try(struct generator * g, struct node * p) {
499
481
  append_restore_string(p, g->failure_str, savevar);
500
482
  }
501
483
 
502
- wsetlab_begin(g);
503
484
  generate(g, p->left);
504
- wsetlab_end(g, g->failure_label);
485
+
486
+ if (g->label_used)
487
+ wsetl(g, g->failure_label);
505
488
  g->unreachable = false;
506
489
 
507
490
  if (savevar) {
@@ -511,14 +494,12 @@ static void generate_try(struct generator * g, struct node * p) {
511
494
 
512
495
  static void generate_set(struct generator * g, struct node * p) {
513
496
  write_comment(g, p);
514
- g->V[0] = p->name;
515
- writef(g, "~M~V0 := True;~N", p);
497
+ writef(g, "~M~V := True;~N", p);
516
498
  }
517
499
 
518
500
  static void generate_unset(struct generator * g, struct node * p) {
519
501
  write_comment(g, p);
520
- g->V[0] = p->name;
521
- writef(g, "~M~V0 := False;~N", p);
502
+ writef(g, "~M~V := False;~N", p);
522
503
  }
523
504
 
524
505
  static void generate_fail(struct generator * g, struct node * p) {
@@ -528,10 +509,9 @@ static void generate_fail(struct generator * g, struct node * p) {
528
509
  }
529
510
 
530
511
  /* generate_test() also implements 'reverse' */
531
-
532
512
  static void generate_test(struct generator * g, struct node * p) {
533
513
  struct str * savevar = NULL;
534
- if (K_needed(g, p->left)) {
514
+ if (K_needed(p->left)) {
535
515
  savevar = vars_newname(g);
536
516
  }
537
517
 
@@ -553,25 +533,28 @@ static void generate_test(struct generator * g, struct node * p) {
553
533
 
554
534
  static void generate_do(struct generator * g, struct node * p) {
555
535
  struct str * savevar = NULL;
556
- if (K_needed(g, p->left)) {
536
+ if (K_needed(p->left)) {
557
537
  savevar = vars_newname(g);
558
538
  }
559
539
 
560
540
  write_comment(g, p);
561
- if (savevar) write_savecursor(g, p, savevar);
541
+ if (savevar) {
542
+ write_savecursor(g, p, savevar);
543
+ }
562
544
 
563
545
  if (p->left->type == c_call) {
564
546
  /* Optimise do <call> */
565
547
  write_comment(g, p->left);
566
- g->V[0] = p->left->name;
567
- w(g, "~M~V0();~N");
548
+ writef(g, "~M~V();~N", p->left);
568
549
  } else {
569
- g->failure_label = new_label(g);
550
+ int label = new_label(g);
551
+ g->failure_label = label;
570
552
  str_clear(g->failure_str);
571
553
 
572
- wsetlab_begin(g);
573
554
  generate(g, p->left);
574
- wsetlab_end(g, g->failure_label);
555
+
556
+ if (g->label_used)
557
+ wsetl(g, g->failure_label);
575
558
  g->unreachable = false;
576
559
  }
577
560
 
@@ -593,37 +576,36 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
593
576
  struct grouping * q = p->name->grouping;
594
577
  g->S[0] = p->mode == m_forward ? "" : "Bk";
595
578
  g->S[1] = complement ? "In" : "Out";
596
- g->V[0] = p->name;
597
579
  g->I[0] = q->smallest_ch;
598
580
  g->I[1] = q->largest_ch;
599
- write_failure_if(g, "Not (Go~S1Grouping~S0(~V0, ~I0, ~I1))", p);
581
+ write_failure_if(g, "Not (Go~S1Grouping~S0(~V, ~I0, ~I1))", p);
600
582
  if (!is_goto) {
601
- write_string(g, p->mode == m_forward ? "Inc(FCursor);" : "Dec(FCursor);");
583
+ w(g, p->mode == m_forward ? "~MInc(FCursor);~N" : "~MDec(FCursor);~N");
602
584
  }
603
585
  }
604
586
 
605
- static void generate_GO(struct generator * g, struct node * p, int style) {
587
+ static void generate_GO(struct generator * g, struct node * p, int is_goto) {
606
588
  write_comment(g, p);
607
589
 
590
+ int used = g->label_used;
608
591
  int a0 = g->failure_label;
609
592
  struct str * a1 = str_copy(g->failure_str);
610
593
 
611
- int end_unreachable = false;
612
-
613
- int golab = new_label(g);
594
+ bool end_unreachable = false;
614
595
 
615
596
  w(g, "~MWhile True Do~N");
616
- w(g, "~{");
597
+ write_block_start(g);
617
598
 
618
599
  struct str * savevar = NULL;
619
- if (style == 1 || repeat_restore(g, p->left)) {
600
+ if (is_goto || repeat_restore(p->left)) {
620
601
  savevar = vars_newname(g);
621
602
  write_savecursor(g, p, savevar);
622
603
  }
623
604
 
624
- g->failure_label = new_label(g);
605
+ int label = new_label(g);
606
+ g->failure_label = label;
607
+ g->label_used = 0;
625
608
  str_clear(g->failure_str);
626
- wsetlab_begin(g);
627
609
  generate(g, p->left);
628
610
 
629
611
  if (g->unreachable) {
@@ -632,32 +614,32 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
632
614
  end_unreachable = true;
633
615
  } else {
634
616
  /* include for goto; omit for gopast */
635
- if (style == 1) write_restorecursor(g, p, savevar);
636
- g->I[0] = golab;
637
- w(g, "~Mgoto lab~I0;~N");
617
+ if (is_goto) write_restorecursor(g, p, savevar);
618
+ w(g, "~MBreak;~N");
638
619
  }
620
+
639
621
  g->unreachable = false;
640
- wsetlab_end(g, g->failure_label);
622
+ if (g->label_used)
623
+ wsetl(g, g->failure_label);
641
624
  if (savevar) {
642
625
  write_restorecursor(g, p, savevar);
643
626
  str_delete(savevar);
644
627
  }
645
628
 
629
+ g->label_used = used;
646
630
  g->failure_label = a0;
647
631
  str_delete(g->failure_str);
648
632
  g->failure_str = a1;
649
633
 
650
634
  write_check_limit(g, p);
651
635
  write_inc_cursor(g, p);
652
-
653
- g->I[0] = golab;
654
- w(g, "~}lab~I0:~N");
636
+ write_block_end(g);
655
637
  g->unreachable = end_unreachable;
656
638
  }
657
639
 
658
640
  static void generate_loop(struct generator * g, struct node * p) {
659
- struct str * loopvar = vars_newname(g);
660
641
  write_comment(g, p);
642
+ struct str * loopvar = vars_newname(g);
661
643
  g->B[0] = str_data(loopvar);
662
644
  write_declare(g, "~B0 : Integer", p);
663
645
  w(g, "~MFor ~B0 := ");
@@ -675,17 +657,18 @@ static void generate_loop(struct generator * g, struct node * p) {
675
657
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
676
658
  int replab = new_label(g);
677
659
  g->I[0] = replab;
678
- writef(g, "lab~I0:~N~MWhile True Do~N~{", p);
660
+ writef(g, "lab~I0:~N~{", p);
679
661
 
680
662
  struct str * savevar = NULL;
681
- if (repeat_restore(g, p->left)) {
663
+ if (repeat_restore(p->left)) {
682
664
  savevar = vars_newname(g);
683
665
  write_savecursor(g, p, savevar);
684
666
  }
685
667
 
686
- g->failure_label = new_label(g);
668
+ int label = new_label(g);
669
+ g->failure_label = label;
670
+ g->label_used = 0;
687
671
  str_clear(g->failure_str);
688
- wsetlab_begin(g);
689
672
  generate(g, p->left);
690
673
 
691
674
  if (!g->unreachable) {
@@ -697,8 +680,8 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
697
680
  g->I[0] = replab;
698
681
  w(g, "~Mgoto lab~I0;~N");
699
682
  }
700
-
701
- wsetlab_end(g, g->failure_label);
683
+ if (g->label_used)
684
+ wsetl(g, g->failure_label);
702
685
  g->unreachable = false;
703
686
 
704
687
  if (savevar) {
@@ -706,7 +689,7 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
706
689
  str_delete(savevar);
707
690
  }
708
691
 
709
- w(g, "~MBreak;~N~}");
692
+ w(g, "~}");
710
693
  }
711
694
 
712
695
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -715,10 +698,10 @@ static void generate_repeat(struct generator * g, struct node * p) {
715
698
  }
716
699
 
717
700
  static void generate_atleast(struct generator * g, struct node * p) {
718
- struct str * loopvar = vars_newname(g);
719
-
720
701
  write_comment(g, p);
702
+
721
703
  w(g, "~{");
704
+ struct str * loopvar = vars_newname(g);
722
705
  g->B[0] = str_data(loopvar);
723
706
  write_declare(g, "~B0 : Integer", p);
724
707
  w(g, "~M~B0 := ");
@@ -740,12 +723,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
740
723
  str_delete(loopvar);
741
724
  }
742
725
 
743
- static void generate_setmark(struct generator * g, struct node * p) {
744
- write_comment(g, p);
745
- g->V[0] = p->name;
746
- writef(g, "~M~W0 := FCursor;~N", p);
747
- }
748
-
749
726
  static void generate_tomark(struct generator * g, struct node * p) {
750
727
  write_comment(g, p);
751
728
  g->S[0] = p->mode == m_forward ? ">" : "<";
@@ -758,15 +735,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
758
735
  w(g, "~MFCursor := "); generate_AE(g, p->AE); writef(g, ";~N", p);
759
736
  }
760
737
 
761
- static void generate_atmark(struct generator * g, struct node * p) {
762
- write_comment(g, p);
763
- w(g, "~MIf (FCursor <> "); generate_AE(g, p->AE); writef(g, ") Then~N", p);
764
- write_block_start(g);
765
- write_failure(g);
766
- write_block_end(g);
767
- g->unreachable = false;
768
- }
769
-
770
738
  static void generate_hop(struct generator * g, struct node * p) {
771
739
  write_comment(g, p);
772
740
  g->S[0] = p->mode == m_forward ? "+" : "-";
@@ -791,24 +759,12 @@ static void generate_hop(struct generator * g, struct node * p) {
791
759
  g->temporary_used = true;
792
760
  }
793
761
 
794
- static void generate_delete(struct generator * g, struct node * p) {
795
- write_comment(g, p);
796
- writef(g, "~MSliceDel;~N", p);
797
- }
798
-
799
762
  static void generate_tolimit(struct generator * g, struct node * p) {
800
763
  write_comment(g, p);
801
764
  g->S[0] = p->mode == m_forward ? "FLimit" : "FBkLimit";
802
765
  writef(g, "~MFCursor := ~S0;~N", p);
803
766
  }
804
767
 
805
- static void generate_atlimit(struct generator * g, struct node * p) {
806
- write_comment(g, p);
807
- g->S[0] = p->mode == m_forward ? "FLimit" : "FBkLimit";
808
- g->S[1] = p->mode == m_forward ? "<" : ">";
809
- write_failure_if(g, "FCursor ~S1 ~S0", p);
810
- }
811
-
812
768
  static void generate_leftslice(struct generator * g, struct node * p) {
813
769
  write_comment(g, p);
814
770
  g->S[0] = p->mode == m_forward ? "FBra" : "FKet";
@@ -823,14 +779,12 @@ static void generate_rightslice(struct generator * g, struct node * p) {
823
779
 
824
780
  static void generate_assignto(struct generator * g, struct node * p) {
825
781
  write_comment(g, p);
826
- g->V[0] = p->name;
827
- writef(g, "~M~V0 := AssignTo();~N", p);
782
+ writef(g, "~M~V := AssignTo();~N", p);
828
783
  }
829
784
 
830
785
  static void generate_sliceto(struct generator * g, struct node * p) {
831
786
  write_comment(g, p);
832
- g->V[0] = p->name;
833
- writef(g, "~M~V0 := SliceTo();~N", p);
787
+ writef(g, "~M~V := SliceTo();~N", p);
834
788
  }
835
789
 
836
790
  static void generate_address(struct generator * g, struct node * p) {
@@ -843,8 +797,8 @@ static void generate_address(struct generator * g, struct node * p) {
843
797
  }
844
798
 
845
799
  static void generate_insert(struct generator * g, struct node * p, int style) {
846
- int keep_c = style == c_attach;
847
800
  write_comment(g, p);
801
+ int keep_c = style == c_attach;
848
802
  if (p->mode == m_backward) keep_c = !keep_c;
849
803
  if (keep_c) {
850
804
  w(g, "~{~MC := FCursor;~N");
@@ -856,10 +810,9 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
856
810
  if (keep_c) w(g, "~MFCursor := C;~N~}");
857
811
  }
858
812
 
859
- static void generate_assignfrom(struct generator * g, struct node * p) {
860
- int keep_c = p->mode == m_forward; /* like 'attach' */
861
-
813
+ static void generate_stringassign(struct generator * g, struct node * p) {
862
814
  write_comment(g, p);
815
+ int keep_c = p->mode == m_forward; /* like 'attach' */
863
816
  if (keep_c) {
864
817
  writef(g, "~{~MC := FCursor;~N", p);
865
818
  g->temporary_used = true;
@@ -871,19 +824,26 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
871
824
  }
872
825
  generate_address(g, p);
873
826
  writef(g, ");~N", p);
874
- if (keep_c) w(g, "~MFCursor := c;~N~}");
827
+ if (keep_c) {
828
+ w(g, "~MFCursor := c;~N~}");
829
+ }
875
830
  }
876
831
 
877
832
  static void generate_slicefrom(struct generator * g, struct node * p) {
878
833
  write_comment(g, p);
834
+ if (p->literalstring && SIZE(p->literalstring) == 0) {
835
+ w(g, "~MSliceDel;~N");
836
+ return;
837
+ }
879
838
  w(g, "~MSliceFrom(");
880
839
  generate_address(g, p);
881
- writef(g, ");~N", p);
840
+ w(g, ");~N");
882
841
  }
883
842
 
884
843
  static void generate_setlimit(struct generator * g, struct node * p) {
885
- struct str * varname = vars_newname(g);
886
844
  write_comment(g, p);
845
+ struct str * varname = vars_newname(g);
846
+
887
847
  if (p->left && p->left->type == c_tomark) {
888
848
  /* Special case for:
889
849
  *
@@ -895,6 +855,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
895
855
  */
896
856
  struct node * q = p->left;
897
857
  write_comment(g, q);
858
+
898
859
  g->S[0] = q->mode == m_forward ? ">" : "<";
899
860
  w(g, "~MIf (FCursor ~S0 "); generate_AE(g, q->AE); w(g, ") Then~N");
900
861
  write_block_start(g);
@@ -905,14 +866,17 @@ static void generate_setlimit(struct generator * g, struct node * p) {
905
866
  g->B[0] = str_data(varname);
906
867
  write_declare(g, "~B0 : Integer", p);
907
868
  if (p->mode == m_forward) {
908
- w(g, "~M~B0 := FLimit - FCursor;~N");
869
+ w(g, "~M~B0 := FLimit;~N");
909
870
  w(g, "~MFLimit := ");
871
+ generate_AE(g, q->AE);
872
+ w(g, ";~N");
873
+ w(g, "~M~B0 := ~B0 - FLimit;~N");
910
874
  } else {
911
875
  w(g, "~M~B0 := FBkLimit;~N");
912
876
  w(g, "~MFBkLimit := ");
877
+ generate_AE(g, q->AE);
878
+ w(g, ";~N");
913
879
  }
914
- generate_AE(g, q->AE);
915
- writef(g, ";~N", q);
916
880
 
917
881
  if (p->mode == m_forward) {
918
882
  str_assign(g->failure_str, "FLimit := FLimit + ");
@@ -971,24 +935,16 @@ static void generate_setlimit(struct generator * g, struct node * p) {
971
935
  static void generate_dollar(struct generator * g, struct node * p) {
972
936
  write_comment(g, p);
973
937
 
938
+ int used = g->label_used;
939
+ int a0 = g->failure_label;
940
+ struct str * a1 = str_copy(g->failure_str);
941
+ int label = new_label(g);
942
+ g->failure_label = label;
943
+ g->label_used = 0;
944
+ str_clear(g->failure_str);
945
+
974
946
  struct str * savevar = vars_newname(g);
975
947
  g->B[0] = str_data(savevar);
976
- g->V[0] = p->name;
977
-
978
- {
979
- struct str * saved_output = g->outbuf;
980
- str_clear(g->failure_str);
981
- g->outbuf = g->failure_str;
982
- writef(g, "~V0 := FCurrent; "
983
- "FCurrent := ~B0_Current; "
984
- "FCursor := ~B0_Cursor; "
985
- "FLimit := ~B0_Limit; "
986
- "FBkLimit := ~B0_BkLimit; "
987
- "FBra := ~B0_Bra; "
988
- "FKet := ~B0_Ket;", p);
989
- g->failure_str = g->outbuf;
990
- g->outbuf = saved_output;
991
- }
992
948
 
993
949
  write_declare(g, "~B0_Current : AnsiString", p);
994
950
  write_declare(g, "~B0_Cursor : Integer", p);
@@ -1003,27 +959,58 @@ static void generate_dollar(struct generator * g, struct node * p) {
1003
959
  "~M~B0_BkLimit := FBkLimit;~N"
1004
960
  "~M~B0_Bra := FBra;~N"
1005
961
  "~M~B0_Ket := FKet;~N"
1006
- "~MFCurrent := ~V0;~N"
962
+ "~MFCurrent := ~V;~N"
1007
963
  "~MFCursor := 0;~N"
1008
964
  "~MFLimit := Length(current);~N", p);
965
+ if (p->left->possible_signals == -1) {
966
+ /* Assume failure. */
967
+ write_declare(g, "~B0_F : Boolean", p);
968
+ w(g, "~M~B0_F := True;~N");
969
+ }
970
+
1009
971
  generate(g, p->left);
1010
- if (!g->unreachable) {
1011
- write_margin(g);
1012
- write_str(g, g->failure_str);
1013
- write_newline(g);
972
+
973
+ if (!g->unreachable && p->left->possible_signals == -1) {
974
+ /* Mark success. */
975
+ g->B[0] = str_data(savevar);
976
+ w(g, "~M~B0_F := False;~N");
977
+ }
978
+
979
+ if (g->label_used)
980
+ wsetl(g, g->failure_label);
981
+
982
+ g->label_used = used;
983
+ g->failure_label = a0;
984
+ str_delete(g->failure_str);
985
+ g->failure_str = a1;
986
+
987
+ g->B[0] = str_data(savevar);
988
+ writef(g, "~M~V := FCurrent;~N"
989
+ "~MFCurrent := ~B0_Current;~N"
990
+ "~MFCursor := ~B0_Cursor;~N"
991
+ "~MFLimit := ~B0_Limit;~N"
992
+ "~MFBkLimit := ~B0_BkLimit;~N"
993
+ "~MFBra := ~B0_Bra;~N"
994
+ "~MFKet := ~B0_Ket;~N", p);
995
+
996
+ if (p->left->possible_signals == 0) {
997
+ // p->left always signals f.
998
+ w(g, "~M~f~N");
999
+ } else if (p->left->possible_signals == -1) {
1000
+ write_failure_if(g, "~B0_F", p);
1014
1001
  }
1015
1002
  w(g, "~}");
1003
+
1016
1004
  str_delete(savevar);
1017
1005
  }
1018
1006
 
1019
1007
  static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
1020
1008
  write_comment(g, p);
1021
- g->V[0] = p->name;
1022
- w(g, "~M~W0 := ");
1009
+ writef(g, "~M~W := ", p);
1023
1010
 
1024
1011
  if (s != NULL) {
1025
1012
  g->S[0] = s;
1026
- w(g, "~W0 ~S0 ");
1013
+ writef(g, "~W ~S0 ", p);
1027
1014
  }
1028
1015
 
1029
1016
  generate_AE(g, p->AE);
@@ -1033,7 +1020,7 @@ static void generate_integer_assign(struct generator * g, struct node * p, const
1033
1020
  static void generate_integer_test(struct generator * g, struct node * p) {
1034
1021
  write_comment(g, p);
1035
1022
  int relop = p->type;
1036
- int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
1023
+ int optimise_to_return = tailcallable(g, p);
1037
1024
  if (optimise_to_return) {
1038
1025
  w(g, "~MResult := ");
1039
1026
  p->right = NULL;
@@ -1057,30 +1044,29 @@ static void generate_integer_test(struct generator * g, struct node * p) {
1057
1044
  }
1058
1045
 
1059
1046
  static void generate_call(struct generator * g, struct node * p) {
1060
- int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
1047
+ int signals = p->name->definition->possible_signals;
1061
1048
  write_comment(g, p);
1062
- g->V[0] = p->name;
1063
- if (g->failure_label == x_return) {
1064
- if (p->right && p->right->type == c_functionend) {
1065
- /* Tail call. */
1066
- writef(g, "~MResult = ~V0;~N", p);
1067
- return;
1068
- }
1069
- if (signals == 0) {
1070
- /* Always fails. */
1071
- writef(g, "~MBegin; Result = ~V0; Exit; End;~N", p);
1072
- return;
1073
- }
1049
+ if (tailcallable(g, p)) {
1050
+ /* Tail call. */
1051
+ writef(g, "~MResult := ~V;~N", p);
1052
+ p->right = NULL;
1053
+ return;
1054
+ }
1055
+ if (just_return_on_fail(g) && signals == 0) {
1056
+ /* Always fails. */
1057
+ writef(g, "~MBegin; Result := ~V; Exit; End;~N", p);
1058
+ g->unreachable = true;
1059
+ return;
1074
1060
  }
1075
1061
  if (signals == 1) {
1076
1062
  /* Always succeeds. */
1077
- writef(g, "~M~V0;~N", p);
1063
+ writef(g, "~M~V;~N", p);
1078
1064
  } else if (signals == 0) {
1079
1065
  /* Always fails. */
1080
- writef(g, "~M~V0;~N", p);
1066
+ writef(g, "~M~V;~N", p);
1081
1067
  write_failure(g);
1082
1068
  } else {
1083
- write_failure_if(g, "Not ~V0", p);
1069
+ write_failure_if(g, "Not ~V", p);
1084
1070
  }
1085
1071
  }
1086
1072
 
@@ -1090,42 +1076,50 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
1090
1076
  struct grouping * q = p->name->grouping;
1091
1077
  g->S[0] = p->mode == m_forward ? "" : "Bk";
1092
1078
  g->S[1] = complement ? "Out" : "In";
1093
- g->V[0] = p->name;
1094
1079
  g->I[0] = q->smallest_ch;
1095
1080
  g->I[1] = q->largest_ch;
1096
- write_failure_if(g, "Not (~S1Grouping~S0(~V0, ~I0, ~I1))", p);
1081
+ if (tailcallable(g, p)) {
1082
+ writef(g, "~MResult := ~S1Grouping~S0(~V, ~I0, ~I1);~N", p);
1083
+ p->right = NULL;
1084
+ } else {
1085
+ write_failure_if(g, "Not (~S1Grouping~S0(~V, ~I0, ~I1))", p);
1086
+ }
1097
1087
  }
1098
1088
 
1099
1089
  static void generate_namedstring(struct generator * g, struct node * p) {
1100
1090
  write_comment(g, p);
1101
1091
  g->S[0] = p->mode == m_forward ? "" : "Bk";
1102
- g->V[0] = p->name;
1103
- write_failure_if(g, "Not (EqV~S0(~V0))", p);
1092
+ if (tailcallable(g, p)) {
1093
+ writef(g, "~MResult := EqS~S0(~V);~N", p);
1094
+ p->right = NULL;
1095
+ } else {
1096
+ write_failure_if(g, "Not (EqS~S0(~V))", p);
1097
+ }
1104
1098
  }
1105
1099
 
1106
1100
  static void generate_literalstring(struct generator * g, struct node * p) {
1107
- symbol * b = p->literalstring;
1108
1101
  write_comment(g, p);
1109
1102
  g->S[0] = p->mode == m_forward ? "" : "Bk";
1110
- g->I[0] = SIZE(b);
1111
- g->L[0] = b;
1112
- write_failure_if(g, "Not (EqS~S0(~I0, ~L0))", p);
1103
+ if (tailcallable(g, p)) {
1104
+ writef(g, "~MResult := EqS~S0(~L);~N", p);
1105
+ p->right = NULL;
1106
+ } else {
1107
+ write_failure_if(g, "Not (EqS~S0(~L))", p);
1108
+ }
1113
1109
  }
1114
1110
 
1115
1111
  static void generate_define(struct generator * g, struct node * p) {
1116
1112
  struct name * q = p->name;
1117
- if (q->type == t_routine && !q->used) return;
1118
1113
 
1119
1114
  write_newline(g);
1120
1115
  write_comment(g, p);
1121
1116
 
1122
1117
  /* Generate function header. */
1123
- g->V[0] = q;
1124
- w(g, "~MFunction T~n.~W0 : Boolean;~N");
1118
+ writef(g, "~MFunction T~n.~W : Boolean;~N", p);
1125
1119
 
1126
1120
  /* Save output. */
1127
- struct str *saved_output = g->outbuf;
1128
- struct str *saved_declarations = g->declarations;
1121
+ struct str * saved_output = g->outbuf;
1122
+ struct str * saved_declarations = g->declarations;
1129
1123
  g->outbuf = str_new();
1130
1124
  g->declarations = str_new();
1131
1125
 
@@ -1138,24 +1132,49 @@ static void generate_define(struct generator * g, struct node * p) {
1138
1132
 
1139
1133
  /* Generate function body. */
1140
1134
  w(g, "~{");
1141
- int signals = check_possible_signals_list(g, p->left, c_define, 0);
1142
1135
  g->temporary_used = false;
1143
1136
  generate(g, p->left);
1144
1137
  if (p->left->right) {
1145
1138
  assert(p->left->right->type == c_functionend);
1146
- if (signals) {
1139
+ if (p->left->possible_signals) {
1147
1140
  generate(g, p->left->right);
1148
1141
  }
1149
1142
  }
1150
1143
  w(g, "~}");
1151
1144
 
1145
+ if (q->amongvar_needed) {
1146
+ str_append_string(g->declarations, " AmongVar : Integer;\n");
1147
+ }
1148
+
1152
1149
  if (g->temporary_used) {
1153
1150
  str_append_string(g->declarations, " C : Integer;\n");
1154
1151
  }
1155
1152
 
1156
- if (p->amongvar_needed) {
1157
- str_append_string(g->declarations, " AmongVar : Integer;\n");
1153
+ /* Declare localised variables. */
1154
+ struct str * temp = g->outbuf;
1155
+ g->outbuf = g->declarations;
1156
+ for (struct name * name = g->analyser->names; name; name = name->next) {
1157
+ if (name->local_to == q) {
1158
+ switch (name->type) {
1159
+ case t_string:
1160
+ w(g, " ");
1161
+ write_varname(g, name);
1162
+ w(g, " : AnsiString;\n");
1163
+ break;
1164
+ case t_integer:
1165
+ w(g, " ");
1166
+ write_varname(g, name);
1167
+ w(g, " : Integer;\n");
1168
+ break;
1169
+ case t_boolean:
1170
+ w(g, " ");
1171
+ write_varname(g, name);
1172
+ w(g, " : Boolean;\n");
1173
+ break;
1174
+ }
1175
+ }
1158
1176
  }
1177
+ g->outbuf = temp;
1159
1178
 
1160
1179
  if (str_len(g->declarations) > 0) {
1161
1180
  str_append_string(saved_output, "Var\n");
@@ -1201,6 +1220,9 @@ static void generate_substring(struct generator * g, struct node * p) {
1201
1220
  }
1202
1221
  } else if (x->always_matches) {
1203
1222
  writef(g, "~MFindAmong~S0(a_~I0, ~I1);~N", p);
1223
+ } else if (x->command_count == 0 && tailcallable(g, p)) {
1224
+ writef(g, "~MResult := FindAmong~S0(a_~I0, ~I1) <> 0;~N", p);
1225
+ x->node->right = NULL;
1204
1226
  } else {
1205
1227
  write_failure_if(g, "FindAmong~S0(a_~I0, ~I1) = 0", p);
1206
1228
  }
@@ -1231,10 +1253,23 @@ static void generate_among(struct generator * g, struct node * p) {
1231
1253
  }
1232
1254
  }
1233
1255
 
1234
- static void generate_booltest(struct generator * g, struct node * p) {
1256
+ static void generate_booltest(struct generator * g, struct node * p, int inverted) {
1235
1257
  write_comment(g, p);
1236
- g->V[0] = p->name;
1237
- write_failure_if(g, "Not (~V0)", p);
1258
+ if (tailcallable(g, p)) {
1259
+ // Optimise at end of function.
1260
+ if (inverted) {
1261
+ writef(g, "~MResult := !~V;~N", p);
1262
+ } else {
1263
+ writef(g, "~MResult := ~V;~N", p);
1264
+ }
1265
+ p->right = NULL;
1266
+ return;
1267
+ }
1268
+ if (inverted) {
1269
+ write_failure_if(g, "~V", p);
1270
+ } else {
1271
+ write_failure_if(g, "Not (~V)", p);
1272
+ }
1238
1273
  }
1239
1274
 
1240
1275
  static void generate_false(struct generator * g, struct node * p) {
@@ -1279,25 +1314,21 @@ static void generate(struct generator * g, struct node * p) {
1279
1314
  case c_repeat: generate_repeat(g, p); break;
1280
1315
  case c_loop: generate_loop(g, p); break;
1281
1316
  case c_atleast: generate_atleast(g, p); break;
1282
- case c_setmark: generate_setmark(g, p); break;
1283
1317
  case c_tomark: generate_tomark(g, p); break;
1284
- case c_atmark: generate_atmark(g, p); break;
1285
1318
  case c_hop: generate_hop(g, p); break;
1286
- case c_delete: generate_delete(g, p); break;
1287
1319
  case c_next: generate_next(g, p); break;
1288
1320
  case c_tolimit: generate_tolimit(g, p); break;
1289
- case c_atlimit: generate_atlimit(g, p); break;
1290
1321
  case c_leftslice: generate_leftslice(g, p); break;
1291
1322
  case c_rightslice: generate_rightslice(g, p); break;
1292
1323
  case c_assignto: generate_assignto(g, p); break;
1293
1324
  case c_sliceto: generate_sliceto(g, p); break;
1294
- case c_assign: generate_assignfrom(g, p); break;
1325
+ case c_stringassign: generate_stringassign(g, p); break;
1295
1326
  case c_insert:
1296
1327
  case c_attach: generate_insert(g, p, p->type); break;
1297
1328
  case c_slicefrom: generate_slicefrom(g, p); break;
1298
1329
  case c_setlimit: generate_setlimit(g, p); break;
1299
1330
  case c_dollar: generate_dollar(g, p); break;
1300
- case c_mathassign: generate_integer_assign(g, p, NULL); break;
1331
+ case c_assign: generate_integer_assign(g, p, NULL); break;
1301
1332
  case c_plusassign: generate_integer_assign(g, p, "+"); break;
1302
1333
  case c_minusassign: generate_integer_assign(g, p, "-"); break;
1303
1334
  case c_multiplyassign:generate_integer_assign(g, p, "*"); break;
@@ -1317,7 +1348,8 @@ static void generate(struct generator * g, struct node * p) {
1317
1348
  case c_literalstring: generate_literalstring(g, p); break;
1318
1349
  case c_among: generate_among(g, p); break;
1319
1350
  case c_substring: generate_substring(g, p); break;
1320
- case c_booltest: generate_booltest(g, p); break;
1351
+ case c_booltest: generate_booltest(g, p, false); break;
1352
+ case c_not_booltest: generate_booltest(g, p, true); break;
1321
1353
  case c_false: generate_false(g, p); break;
1322
1354
  case c_true: break;
1323
1355
  case c_debug: generate_debug(g, p); break;
@@ -1333,7 +1365,7 @@ static void generate(struct generator * g, struct node * p) {
1333
1365
 
1334
1366
  /* Class declaration generation. */
1335
1367
  static void generate_unit_start(struct generator * g) {
1336
- write_start_comment(g, "{ ", " }");
1368
+ write_start_comment(g, "// ", NULL);
1337
1369
  w(g, "Unit ~n;~N~N{$HINTS OFF}~N~NInterface~N~NUses " BASE_UNIT ";~N");
1338
1370
  }
1339
1371
 
@@ -1350,10 +1382,13 @@ static void generate_class_end(struct generator * g) {
1350
1382
  }
1351
1383
 
1352
1384
  static void generate_method_decl(struct generator * g, struct name * q) {
1353
- g->V[0] = q;
1354
- w(g, "~MFunction ~W0 : Boolean;");
1385
+ w(g, "~MFunction ");
1386
+ write_varname(g, q);
1387
+ w(g, " : Boolean;");
1355
1388
  if (q->type == t_external) {
1356
- w(g, " Override;");
1389
+ if (SIZE(q->s) == 4 && memcmp(q->s, "stem", 4) == 0) {
1390
+ w(g, " Override;");
1391
+ }
1357
1392
  }
1358
1393
  w(g, "~N");
1359
1394
  }
@@ -1369,7 +1404,7 @@ static void generate_method_decls(struct generator * g) {
1369
1404
  }
1370
1405
  w(g, "~-");
1371
1406
 
1372
- int first = true;
1407
+ bool first = true;
1373
1408
  for (struct name * q = g->analyser->names; q; q = q->next) {
1374
1409
  if (q->type == t_routine) {
1375
1410
  if (first) {
@@ -1383,9 +1418,9 @@ static void generate_method_decls(struct generator * g) {
1383
1418
  }
1384
1419
 
1385
1420
  static void generate_member_decls(struct generator * g) {
1386
- int first = true;
1421
+ bool first = true;
1387
1422
  for (struct name * q = g->analyser->names; q; q = q->next) {
1388
- g->V[0] = q;
1423
+ if (q->local_to) continue;
1389
1424
  switch (q->type) {
1390
1425
  case t_string:
1391
1426
  case t_integer:
@@ -1396,13 +1431,19 @@ static void generate_member_decls(struct generator * g) {
1396
1431
  }
1397
1432
  switch (q->type) {
1398
1433
  case t_string:
1399
- w(g, "~M~W0 : AnsiString;~N");
1434
+ write_margin(g);
1435
+ write_varname(g, q);
1436
+ w(g, " : AnsiString;~N");
1400
1437
  break;
1401
1438
  case t_integer:
1402
- w(g, "~M~W0 : Integer;~N");
1439
+ write_margin(g);
1440
+ write_varname(g, q);
1441
+ w(g, " : Integer;~N");
1403
1442
  break;
1404
1443
  case t_boolean:
1405
- w(g, "~M~W0 : Boolean;~N");
1444
+ write_margin(g);
1445
+ write_varname(g, q);
1446
+ w(g, " : Boolean;~N");
1406
1447
  break;
1407
1448
  }
1408
1449
  }
@@ -1439,8 +1480,9 @@ static void generate_among_table(struct generator * g, struct among * x) {
1439
1480
  g->I[1] = i;
1440
1481
 
1441
1482
  /* Write among's string. */
1442
- g->L[0] = v[i].b;
1443
- w(g, "~Ma_~I0[~I1].Str := ~L0;~N");
1483
+ w(g, "~Ma_~I0[~I1].Str := ");
1484
+ write_literal_string(g, v[i].b);
1485
+ w(g, ";~N");
1444
1486
 
1445
1487
  /* Write among's index & result. */
1446
1488
  g->I[2] = v[i].i;
@@ -1453,8 +1495,9 @@ static void generate_among_table(struct generator * g, struct among * x) {
1453
1495
  if (v[i].function == NULL) {
1454
1496
  w(g, "nil;~N~N");
1455
1497
  } else {
1456
- g->V[0] = v[i].function;
1457
- w(g, "Self.~W0;~N~N");
1498
+ w(g, "Self.");
1499
+ write_varname(g, v[i].function);
1500
+ w(g, ";~N~N");
1458
1501
  }
1459
1502
  }
1460
1503
  w(g, "~-");
@@ -1473,19 +1516,17 @@ static void generate_constructor(struct generator * g) {
1473
1516
  }
1474
1517
 
1475
1518
  static void generate_methods(struct generator * g) {
1476
- struct node * p = g->analyser->program;
1477
- while (p != NULL) {
1519
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1478
1520
  generate(g, p);
1479
1521
  g->unreachable = false;
1480
- p = p->right;
1481
1522
  }
1482
1523
  }
1483
1524
 
1484
- static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1525
+ static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
1485
1526
 
1486
1527
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1487
1528
  int range = q->largest_ch - q->smallest_ch + 1;
1488
- int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1529
+ int size = (range + 7) / 8; /* assume 8 bits per symbol */
1489
1530
  symbol * b = q->b;
1490
1531
  symbol * map = create_b(size);
1491
1532
 
@@ -1493,9 +1534,10 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1493
1534
 
1494
1535
  for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1495
1536
 
1496
- g->V[0] = q->name;
1497
1537
  g->I[0] = size - 1;
1498
- w(g, "~N~MConst~+~N~M~W0 : Array [0..~I0] Of Char = (~N~+");
1538
+ w(g, "~N~MConst~+~N~M");
1539
+ write_varname(g, q->name);
1540
+ w(g, " : Array [0..~I0] Of Char = (~N~+");
1499
1541
  for (int i = 0; i < size; i++) {
1500
1542
  if (i != 0) w(g, ",~N");
1501
1543
  g->I[0] = map[i];
@@ -1508,8 +1550,7 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1508
1550
 
1509
1551
  static void generate_groupings(struct generator * g) {
1510
1552
  for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1511
- if (q->name->used)
1512
- generate_grouping_table(g, q);
1553
+ generate_grouping_table(g, q);
1513
1554
  }
1514
1555
  }
1515
1556