mittens 0.3.0 → 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 (174) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +2 -1
  4. data/README.md +2 -2
  5. data/Rakefile +12 -5
  6. data/ext/mittens/extconf.rb +3 -1
  7. data/lib/mittens/version.rb +1 -1
  8. data/vendor/snowball/.github/workflows/ci.yml +144 -17
  9. data/vendor/snowball/.github/workflows/coverage.yml +117 -0
  10. data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
  11. data/vendor/snowball/.gitignore +33 -7
  12. data/vendor/snowball/CONTRIBUTING.rst +7 -0
  13. data/vendor/snowball/COPYING +1 -1
  14. data/vendor/snowball/GNUmakefile +736 -298
  15. data/vendor/snowball/NEWS +1394 -7
  16. data/vendor/snowball/README.rst +8 -8
  17. data/vendor/snowball/ada/generate/generate.adb +5 -5
  18. data/vendor/snowball/ada/src/stemmer.adb +177 -188
  19. data/vendor/snowball/ada/src/stemmer.ads +86 -89
  20. data/vendor/snowball/ada/src/stemwords.adb +21 -5
  21. data/vendor/snowball/algorithms/czech.sbl +255 -0
  22. data/vendor/snowball/algorithms/danish.sbl +22 -10
  23. data/vendor/snowball/algorithms/english.sbl +7 -4
  24. data/vendor/snowball/algorithms/esperanto.sbl +6 -7
  25. data/vendor/snowball/algorithms/estonian.sbl +9 -4
  26. data/vendor/snowball/algorithms/finnish.sbl +33 -21
  27. data/vendor/snowball/algorithms/german.sbl +5 -0
  28. data/vendor/snowball/algorithms/indonesian.sbl +115 -96
  29. data/vendor/snowball/algorithms/italian.sbl +26 -1
  30. data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
  31. data/vendor/snowball/algorithms/norwegian.sbl +17 -6
  32. data/vendor/snowball/algorithms/persian.sbl +387 -0
  33. data/vendor/snowball/algorithms/polish.sbl +177 -0
  34. data/vendor/snowball/algorithms/sesotho.sbl +115 -0
  35. data/vendor/snowball/algorithms/turkish.sbl +4 -4
  36. data/vendor/snowball/compiler/analyser.c +2002 -711
  37. data/vendor/snowball/compiler/driver.c +460 -298
  38. data/vendor/snowball/compiler/generator.c +439 -1965
  39. data/vendor/snowball/compiler/generator_ada.c +605 -430
  40. data/vendor/snowball/compiler/generator_c.c +2227 -0
  41. data/vendor/snowball/compiler/generator_csharp.c +365 -274
  42. data/vendor/snowball/compiler/generator_dart.c +1476 -0
  43. data/vendor/snowball/compiler/generator_go.c +348 -270
  44. data/vendor/snowball/compiler/generator_java.c +330 -233
  45. data/vendor/snowball/compiler/generator_js.c +534 -385
  46. data/vendor/snowball/compiler/generator_pascal.c +361 -320
  47. data/vendor/snowball/compiler/generator_php.c +1445 -0
  48. data/vendor/snowball/compiler/generator_python.c +399 -299
  49. data/vendor/snowball/compiler/generator_rust.c +370 -261
  50. data/vendor/snowball/compiler/generator_zig.c +1474 -0
  51. data/vendor/snowball/compiler/header.h +153 -86
  52. data/vendor/snowball/compiler/space.c +121 -63
  53. data/vendor/snowball/compiler/tokeniser.c +286 -182
  54. data/vendor/snowball/compiler/tokens.h +71 -0
  55. data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
  56. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
  57. data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
  58. data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
  59. data/vendor/snowball/cxx/.gitignore +4 -0
  60. data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
  61. data/vendor/snowball/cxx/stemmer.h +12 -0
  62. data/vendor/snowball/cxx/stemwords.cxx +176 -0
  63. data/vendor/snowball/cxx/utilities.cxx +2 -0
  64. data/vendor/snowball/dart/.gitignore +4 -0
  65. data/vendor/snowball/dart/analysis_options.yaml +1 -0
  66. data/vendor/snowball/dart/example/test_app.dart +65 -0
  67. data/vendor/snowball/dart/generate_algorithms.pl +21 -0
  68. data/vendor/snowball/dart/lib/snowball.dart +18 -0
  69. data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
  70. data/vendor/snowball/dart/pubspec.yaml +17 -0
  71. data/vendor/snowball/doc/libstemmer_dart_README +37 -0
  72. data/vendor/snowball/doc/libstemmer_js_README +2 -2
  73. data/vendor/snowball/doc/libstemmer_php_README +38 -0
  74. data/vendor/snowball/doc/libstemmer_python_README +3 -3
  75. data/vendor/snowball/examples/stemwords.c +18 -3
  76. data/vendor/snowball/go/README.md +12 -4
  77. data/vendor/snowball/go/env.go +12 -14
  78. data/vendor/snowball/go/stemwords/main.go +2 -1
  79. data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
  80. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
  81. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
  82. data/vendor/snowball/javascript/base-stemmer.js +219 -252
  83. data/vendor/snowball/javascript/stemwords.js +86 -58
  84. data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
  85. data/vendor/snowball/libstemmer/modules.txt +4 -0
  86. data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
  87. data/vendor/snowball/php/base-stemmer.php +453 -0
  88. data/vendor/snowball/php/stemwords.php +25 -0
  89. data/vendor/snowball/python/create_init.py +16 -21
  90. data/vendor/snowball/python/pyproject.toml +3 -0
  91. data/vendor/snowball/python/setup.py +5 -7
  92. data/vendor/snowball/python/snowballstemmer/among.py +1 -2
  93. data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
  94. data/vendor/snowball/python/stemwords.py +72 -63
  95. data/vendor/snowball/runtime/api.c +11 -42
  96. data/vendor/snowball/runtime/api.h +11 -9
  97. data/vendor/snowball/runtime/snowball_runtime.h +110 -0
  98. data/vendor/snowball/runtime/utilities.c +282 -106
  99. data/vendor/snowball/rust/src/main.rs +2 -2
  100. data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
  101. data/vendor/snowball/tests/compilertest +62 -0
  102. data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
  103. data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
  104. data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
  105. data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
  106. data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
  107. data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
  108. data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
  109. data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
  110. data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
  111. data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
  112. data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
  113. data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
  114. data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
  115. data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
  116. data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
  117. data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
  118. data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
  119. data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
  120. data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
  121. data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
  122. data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
  123. data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
  124. data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
  125. data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
  126. data/vendor/snowball/tests/runtime/among.sbl +19 -0
  127. data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
  128. data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
  129. data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
  130. data/vendor/snowball/tests/runtime/externals.sbl +22 -0
  131. data/vendor/snowball/tests/runtime/hop.sbl +12 -0
  132. data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
  133. data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
  134. data/vendor/snowball/tests/runtime/naming.sbl +20 -0
  135. data/vendor/snowball/tests/runtime/not.sbl +30 -0
  136. data/vendor/snowball/tests/runtime/or.sbl +17 -0
  137. data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
  138. data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
  139. data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
  140. data/vendor/snowball/tests/runtime/slice.sbl +27 -0
  141. data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
  142. data/vendor/snowball/tests/runtime/strings.sbl +66 -0
  143. data/vendor/snowball/tests/runtime/test.sbl +19 -0
  144. data/vendor/snowball/tests/stemtest.c +41 -1
  145. data/vendor/snowball/tests/syntax/canon.sbl +32 -0
  146. data/vendor/snowball/tests/syntax/canon.stderr +0 -0
  147. data/vendor/snowball/tests/syntax/canon.syntax +57 -0
  148. data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
  149. data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
  150. data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
  151. data/vendor/snowball/tests/syntax/inline.sbl +144 -0
  152. data/vendor/snowball/tests/syntax/inline.stderr +0 -0
  153. data/vendor/snowball/tests/syntax/inline.syntax +121 -0
  154. data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
  155. data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
  156. data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
  157. data/vendor/snowball/tests/syntax/loops.sbl +14 -0
  158. data/vendor/snowball/tests/syntax/loops.stderr +9 -0
  159. data/vendor/snowball/tests/syntax/loops.syntax +29 -0
  160. data/vendor/snowball/tests/syntax/noops.sbl +76 -0
  161. data/vendor/snowball/tests/syntax/noops.stderr +27 -0
  162. data/vendor/snowball/tests/syntax/noops.syntax +135 -0
  163. data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
  164. data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
  165. data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
  166. data/vendor/snowball/tests/syntax/unused.sbl +18 -0
  167. data/vendor/snowball/tests/syntax/unused.stderr +7 -0
  168. data/vendor/snowball/tests/syntax/unused.syntax +3 -0
  169. data/vendor/snowball/zig/env.zig +599 -0
  170. data/vendor/snowball/zig/generate_algorithms.pl +19 -0
  171. data/vendor/snowball/zig/stemwords.zig +123 -0
  172. metadata +102 -4
  173. data/vendor/snowball/compiler/syswords.h +0 -86
  174. data/vendor/snowball/runtime/header.h +0 -62
@@ -1,68 +1,67 @@
1
1
  #include <assert.h>
2
+ #include <stdio.h> /* for fprintf etc */
2
3
  #include <stdlib.h> /* for exit */
3
4
  #include <string.h> /* for strlen */
4
- #include <stdio.h> /* for fprintf etc */
5
5
  #include "header.h"
6
6
 
7
- /* prototypes */
7
+ /* prototype functions for recursive use: */
8
8
 
9
9
  static void generate(struct generator * g, struct node * p);
10
10
  static void w(struct generator * g, const char * s);
11
11
  static void writef(struct generator * g, const char * s, struct node * p);
12
12
 
13
- static int new_label(struct generator * g) {
14
- return g->next_label++;
15
- }
13
+ /* Write routines for items from the syntax tree */
16
14
 
17
- static struct str * vars_newname(struct generator * g) {
18
- struct str * output;
19
- g->var_number++;
20
- output = str_new();
21
- str_append_string(output, "v_");
22
- str_append_int(output, g->var_number);
23
- return output;
15
+ static void write_relop(struct generator * g, int relop) {
16
+ // Relational operators are the same as C.
17
+ write_c_relop(g, relop);
24
18
  }
25
19
 
26
- /* Write routines for items from the syntax tree */
27
-
28
20
  static void write_varname(struct generator * g, struct name * p) {
29
- int ch = "SBIrxg"[p->type];
30
- if (p->type != t_external) {
31
- write_char(g, ch);
21
+ if (p->type == t_external) {
22
+ if (g->options->externals_prefix) {
23
+ write_string(g, g->options->externals_prefix);
24
+ }
25
+ } else {
26
+ // We use the same naming scheme for both global and local variables.
27
+ write_char(g, "SBIrxg"[p->type]);
32
28
  write_char(g, '_');
33
29
  }
34
30
  write_s(g, p->s);
35
31
  }
36
32
 
33
+ /* Reference to variable, e.g. when assigning to or using in an expression. */
37
34
  static void write_varref(struct generator * g, struct name * p) {
38
- /* In java, references look just the same */
35
+ /* In Java, references look just the same */
39
36
  write_varname(g, p);
40
37
  }
41
38
 
42
39
  static void write_literal_string(struct generator * g, symbol * p) {
43
- write_string(g, "\"");
40
+ write_char(g, '"');
44
41
  for (int i = 0; i < SIZE(p); i++) {
45
42
  int ch = p[i];
46
43
  if (32 <= ch && ch < 127) {
47
- if (ch == '\"' || ch == '\\') write_string(g, "\\");
44
+ if (ch == '\"' || ch == '\\') write_char(g, '\\');
48
45
  write_char(g, ch);
46
+ } else if (ch < 128) {
47
+ // Escape as octal.
48
+ write_char(g, '\\');
49
+ write_char(g, '0' + ((ch >> 6) & 0x03));
50
+ write_char(g, '0' + ((ch >> 3) & 0x07));
51
+ write_char(g, '0' + (ch & 0x07));
49
52
  } else {
50
53
  write_string(g, "\\u");
51
54
  write_hex4(g, ch);
52
55
  }
53
56
  }
54
- write_string(g, "\"");
55
- }
56
-
57
- static void write_margin(struct generator * g) {
58
- for (int i = 0; i < g->margin; i++) write_string(g, " ");
57
+ write_char(g, '"');
59
58
  }
60
59
 
61
60
  static void write_comment(struct generator * g, struct node * p) {
62
61
  if (!g->options->comments) return;
63
62
  write_margin(g);
64
63
  write_string(g, "// ");
65
- write_comment_content(g, p);
64
+ write_comment_content(g, p, NULL);
66
65
  write_newline(g);
67
66
  }
68
67
 
@@ -115,8 +114,9 @@ static void wgotol(struct generator * g, int n) {
115
114
  write_margin(g);
116
115
  write_string(g, "break lab");
117
116
  write_int(g, n);
118
- write_string(g, ";");
117
+ write_char(g, ';');
119
118
  write_newline(g);
119
+ g->unreachable = true;
120
120
  }
121
121
 
122
122
  static void write_failure(struct generator * g) {
@@ -129,15 +129,14 @@ static void write_failure(struct generator * g) {
129
129
  switch (g->failure_label) {
130
130
  case x_return:
131
131
  write_string(g, "return false;");
132
- g->unreachable = true;
133
132
  break;
134
133
  default:
135
134
  write_string(g, "break lab");
136
135
  write_int(g, g->failure_label);
137
- write_string(g, ";");
138
- g->unreachable = true;
136
+ write_char(g, ';');
139
137
  }
140
138
  write_newline(g);
139
+ g->unreachable = true;
141
140
  }
142
141
 
143
142
  static void write_failure_if(struct generator * g, const char * s, struct node * p) {
@@ -161,7 +160,6 @@ static void write_check_limit(struct generator * g, struct node * p) {
161
160
 
162
161
  /* Formatted write. */
163
162
  static void writef(struct generator * g, const char * input, struct node * p) {
164
- (void)p;
165
163
  int i = 0;
166
164
 
167
165
  while (input[i]) {
@@ -207,26 +205,17 @@ static void writef(struct generator * g, const char * input, struct node * p) {
207
205
  continue;
208
206
  }
209
207
  case 'V':
210
- case 'W': {
211
- int j = input[i++] - '0';
212
- if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
213
- goto invalid_escape2;
214
- if (ch == 'V')
215
- write_varref(g, g->V[j]);
216
- else
217
- write_varname(g, g->V[j]);
208
+ write_varref(g, p->name);
218
209
  continue;
219
- }
220
- case 'L': {
221
- int j = input[i++] - '0';
222
- if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
223
- goto invalid_escape2;
224
- write_literal_string(g, g->L[j]);
210
+ case 'W':
211
+ write_varname(g, p->name);
212
+ continue;
213
+ case 'L':
214
+ write_literal_string(g, p->literalstring);
225
215
  continue;
226
- }
227
216
  case '+': g->margin++; continue;
228
217
  case '-': g->margin--; continue;
229
- case 'n': write_string(g, g->options->name); continue;
218
+ case 'n': write_s(g, g->options->name); continue;
230
219
  default:
231
220
  printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
232
221
  ch, input);
@@ -247,39 +236,53 @@ static void generate_AE(struct generator * g, struct node * p) {
247
236
  const char * s;
248
237
  switch (p->type) {
249
238
  case c_name:
250
- write_varref(g, p->name); break;
239
+ write_varref(g, p->name);
240
+ break;
251
241
  case c_number:
252
- write_int(g, p->number); break;
242
+ write_int(g, p->number);
243
+ break;
253
244
  case c_maxint:
254
- write_string(g, "Integer.MAX_VALUE"); break;
245
+ write_string(g, "Integer.MAX_VALUE");
246
+ break;
255
247
  case c_minint:
256
- write_string(g, "Integer.MIN_VALUE"); break;
248
+ write_string(g, "Integer.MIN_VALUE");
249
+ break;
257
250
  case c_neg:
258
- write_char(g, '-'); generate_AE(g, p->right); break;
251
+ write_char(g, '-');
252
+ generate_AE(g, p->right);
253
+ break;
259
254
  case c_multiply:
260
- s = " * "; goto label0;
261
- case c_plus:
262
- s = " + "; goto label0;
263
- case c_minus:
264
- s = " - "; goto label0;
255
+ s = " * ";
256
+ goto label0;
265
257
  case c_divide:
266
258
  s = " / ";
259
+ goto label0;
260
+ case c_plus:
261
+ s = " + ";
262
+ goto label0;
263
+ case c_minus:
264
+ s = " - ";
267
265
  label0:
268
- write_char(g, '('); generate_AE(g, p->left);
269
- write_string(g, s); generate_AE(g, p->right); write_char(g, ')'); break;
266
+ write_char(g, '(');
267
+ generate_AE(g, p->left);
268
+ write_string(g, s);
269
+ generate_AE(g, p->right);
270
+ write_char(g, ')');
271
+ break;
270
272
  case c_cursor:
271
- w(g, "cursor"); break;
273
+ w(g, "cursor");
274
+ break;
272
275
  case c_limit:
273
- w(g, p->mode == m_forward ? "limit" : "limit_backward"); break;
274
- case c_lenof: /* Same as sizeof() for Java. */
275
- case c_sizeof:
276
- g->V[0] = p->name;
277
- w(g, "~V0.length()");
276
+ w(g, p->mode == m_forward ? "limit" : "limit_backward");
278
277
  break;
279
278
  case c_len: /* Same as size() for Java. */
280
279
  case c_size:
281
280
  w(g, "length");
282
281
  break;
282
+ case c_lenof: /* Same as sizeof() for Java. */
283
+ case c_sizeof:
284
+ writef(g, "L~V", p);
285
+ break;
283
286
  }
284
287
  }
285
288
 
@@ -294,13 +297,15 @@ static void generate_bra(struct generator * g, struct node * p) {
294
297
 
295
298
  static void generate_and(struct generator * g, struct node * p) {
296
299
  struct str * savevar = NULL;
297
- if (K_needed(g, p->left)) {
300
+ if (K_needed_for_and(p->left)) {
298
301
  savevar = vars_newname(g);
299
302
  }
300
303
 
301
304
  write_comment(g, p);
302
305
 
303
- if (savevar) write_savecursor(g, p, savevar);
306
+ if (savevar) {
307
+ write_savecursor(g, p, savevar);
308
+ }
304
309
 
305
310
  p = p->left;
306
311
  while (p) {
@@ -317,7 +322,7 @@ static void generate_and(struct generator * g, struct node * p) {
317
322
 
318
323
  static void generate_or(struct generator * g, struct node * p) {
319
324
  struct str * savevar = NULL;
320
- if (K_needed(g, p->left)) {
325
+ if (K_needed_for_or(p->left)) {
321
326
  savevar = vars_newname(g);
322
327
  }
323
328
 
@@ -325,12 +330,14 @@ static void generate_or(struct generator * g, struct node * p) {
325
330
  struct str * a1 = str_copy(g->failure_str);
326
331
 
327
332
  int out_lab = new_label(g);
328
- int end_unreachable = true;
333
+ bool end_unreachable = true;
329
334
 
330
335
  write_comment(g, p);
331
336
  wsetlab_begin(g, out_lab);
332
337
 
333
- if (savevar) write_savecursor(g, p, savevar);
338
+ if (savevar && K_needed_node_on_f(p)) {
339
+ write_savecursor(g, p, savevar);
340
+ }
334
341
 
335
342
  p = p->left;
336
343
  str_clear(g->failure_str);
@@ -342,7 +349,8 @@ static void generate_or(struct generator * g, struct node * p) {
342
349
  exit(1);
343
350
  }
344
351
  while (p->right != NULL) {
345
- g->failure_label = new_label(g);
352
+ int label = new_label(g);
353
+ g->failure_label = label;
346
354
  wsetlab_begin(g, g->failure_label);
347
355
  generate(g, p);
348
356
  if (!g->unreachable) {
@@ -351,7 +359,9 @@ static void generate_or(struct generator * g, struct node * p) {
351
359
  }
352
360
  wsetlab_end(g);
353
361
  g->unreachable = false;
354
- if (savevar) write_restorecursor(g, p, savevar);
362
+ if (savevar) {
363
+ write_restorecursor(g, p, savevar);
364
+ }
355
365
  p = p->right;
356
366
  }
357
367
 
@@ -378,10 +388,9 @@ static void generate_backwards(struct generator * g, struct node * p) {
378
388
  w(g, "~Mcursor = limit_backward;~N");
379
389
  }
380
390
 
381
-
382
391
  static void generate_not(struct generator * g, struct node * p) {
383
392
  struct str * savevar = NULL;
384
- if (K_needed(g, p->left)) {
393
+ if (K_needed_node_on_f(p->left)) {
385
394
  savevar = vars_newname(g);
386
395
  }
387
396
 
@@ -394,7 +403,8 @@ static void generate_not(struct generator * g, struct node * p) {
394
403
  write_savecursor(g, p, savevar);
395
404
  }
396
405
 
397
- g->failure_label = new_label(g);
406
+ int label = new_label(g);
407
+ g->failure_label = label;
398
408
  str_clear(g->failure_str);
399
409
 
400
410
  wsetlab_begin(g, g->failure_label);
@@ -417,14 +427,14 @@ static void generate_not(struct generator * g, struct node * p) {
417
427
  }
418
428
  }
419
429
 
420
-
421
430
  static void generate_try(struct generator * g, struct node * p) {
422
431
  struct str * savevar = NULL;
423
- if (K_needed(g, p->left)) {
432
+ if (K_needed(p->left)) {
424
433
  savevar = vars_newname(g);
425
434
  }
426
435
 
427
- g->failure_label = new_label(g);
436
+ int label = new_label(g);
437
+ g->failure_label = label;
428
438
  str_clear(g->failure_str);
429
439
 
430
440
  write_comment(g, p);
@@ -445,14 +455,12 @@ static void generate_try(struct generator * g, struct node * p) {
445
455
 
446
456
  static void generate_set(struct generator * g, struct node * p) {
447
457
  write_comment(g, p);
448
- g->V[0] = p->name;
449
- writef(g, "~M~V0 = true;~N", p);
458
+ writef(g, "~M~V = true;~N", p);
450
459
  }
451
460
 
452
461
  static void generate_unset(struct generator * g, struct node * p) {
453
462
  write_comment(g, p);
454
- g->V[0] = p->name;
455
- writef(g, "~M~V0 = false;~N", p);
463
+ writef(g, "~M~V = false;~N", p);
456
464
  }
457
465
 
458
466
  static void generate_fail(struct generator * g, struct node * p) {
@@ -462,10 +470,9 @@ static void generate_fail(struct generator * g, struct node * p) {
462
470
  }
463
471
 
464
472
  /* generate_test() also implements 'reverse' */
465
-
466
473
  static void generate_test(struct generator * g, struct node * p) {
467
474
  struct str * savevar = NULL;
468
- if (K_needed(g, p->left)) {
475
+ if (K_needed(p->left)) {
469
476
  savevar = vars_newname(g);
470
477
  }
471
478
 
@@ -487,20 +494,22 @@ static void generate_test(struct generator * g, struct node * p) {
487
494
 
488
495
  static void generate_do(struct generator * g, struct node * p) {
489
496
  struct str * savevar = NULL;
490
- if (K_needed(g, p->left)) {
497
+ if (K_needed(p->left)) {
491
498
  savevar = vars_newname(g);
492
499
  }
493
500
 
494
501
  write_comment(g, p);
495
- if (savevar) write_savecursor(g, p, savevar);
502
+ if (savevar) {
503
+ write_savecursor(g, p, savevar);
504
+ }
496
505
 
497
506
  if (p->left->type == c_call) {
498
507
  /* Optimise do <call> */
499
508
  write_comment(g, p->left);
500
- g->V[0] = p->left->name;
501
- w(g, "~M~V0();~N");
509
+ writef(g, "~M~V();~N", p->left);
502
510
  } else {
503
- g->failure_label = new_label(g);
511
+ int label = new_label(g);
512
+ g->failure_label = label;
504
513
  str_clear(g->failure_str);
505
514
 
506
515
  wsetlab_begin(g, g->failure_label);
@@ -527,10 +536,9 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
527
536
  struct grouping * q = p->name->grouping;
528
537
  g->S[0] = p->mode == m_forward ? "" : "_b";
529
538
  g->S[1] = complement ? "in" : "out";
530
- g->V[0] = p->name;
531
539
  g->I[0] = q->smallest_ch;
532
540
  g->I[1] = q->largest_ch;
533
- write_failure_if(g, "!go_~S1_grouping~S0(~V0, ~I0, ~I1)", p);
541
+ write_failure_if(g, "!go_~S1_grouping~S0(~V, ~I0, ~I1)", p);
534
542
  if (!is_goto) {
535
543
  if (p->mode == m_forward)
536
544
  w(g, "~Mcursor++;~N");
@@ -539,26 +547,27 @@ static void generate_GO_grouping(struct generator * g, struct node * p, int is_g
539
547
  }
540
548
  }
541
549
 
542
- static void generate_GO(struct generator * g, struct node * p, int style) {
550
+ static void generate_GO(struct generator * g, struct node * p, int is_goto) {
543
551
  write_comment(g, p);
544
552
 
545
553
  int a0 = g->failure_label;
546
554
  struct str * a1 = str_copy(g->failure_str);
547
555
 
548
- int end_unreachable = false;
556
+ bool end_unreachable = false;
549
557
 
550
558
  int golab = new_label(g);
551
559
  g->I[0] = golab;
552
- w(g, "~Mgolab~I0: while(true)~N");
560
+ w(g, "~Mgolab~I0: while (true)~N");
553
561
  w(g, "~{");
554
562
 
555
563
  struct str * savevar = NULL;
556
- if (style == 1 || repeat_restore(g, p->left)) {
564
+ if (is_goto || repeat_restore(p->left)) {
557
565
  savevar = vars_newname(g);
558
566
  write_savecursor(g, p, savevar);
559
567
  }
560
568
 
561
- g->failure_label = new_label(g);
569
+ int label = new_label(g);
570
+ g->failure_label = label;
562
571
  str_clear(g->failure_str);
563
572
  wsetlab_begin(g, g->failure_label);
564
573
  generate(g, p->left);
@@ -569,7 +578,7 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
569
578
  end_unreachable = true;
570
579
  } else {
571
580
  /* include for goto; omit for gopast */
572
- if (style == 1) write_restorecursor(g, p, savevar);
581
+ if (is_goto) write_restorecursor(g, p, savevar);
573
582
  g->I[0] = golab;
574
583
  w(g, "~Mbreak golab~I0;~N");
575
584
  }
@@ -591,8 +600,8 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
591
600
  }
592
601
 
593
602
  static void generate_loop(struct generator * g, struct node * p) {
594
- struct str * loopvar = vars_newname(g);
595
603
  write_comment(g, p);
604
+ struct str * loopvar = vars_newname(g);
596
605
  g->B[0] = str_data(loopvar);
597
606
  w(g, "~Mfor (int ~B0 = ");
598
607
  generate_AE(g, p->AE);
@@ -608,15 +617,16 @@ static void generate_loop(struct generator * g, struct node * p) {
608
617
  }
609
618
 
610
619
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
611
- writef(g, "~Mwhile(true)~N~{", p);
620
+ writef(g, "~Mwhile (true)~N~{", p);
612
621
 
613
622
  struct str * savevar = NULL;
614
- if (repeat_restore(g, p->left)) {
623
+ if (repeat_restore(p->left)) {
615
624
  savevar = vars_newname(g);
616
625
  write_savecursor(g, p, savevar);
617
626
  }
618
627
 
619
- g->failure_label = new_label(g);
628
+ int label = new_label(g);
629
+ g->failure_label = label;
620
630
  str_clear(g->failure_str);
621
631
  wsetlab_begin(g, g->failure_label);
622
632
  generate(g, p->left);
@@ -647,10 +657,10 @@ static void generate_repeat(struct generator * g, struct node * p) {
647
657
  }
648
658
 
649
659
  static void generate_atleast(struct generator * g, struct node * p) {
650
- struct str * loopvar = vars_newname(g);
651
-
652
660
  write_comment(g, p);
661
+
653
662
  w(g, "~{");
663
+ struct str * loopvar = vars_newname(g);
654
664
  g->B[0] = str_data(loopvar);
655
665
  w(g, "~Mint ~B0 = ");
656
666
  generate_AE(g, p->AE);
@@ -671,12 +681,6 @@ static void generate_atleast(struct generator * g, struct node * p) {
671
681
  str_delete(loopvar);
672
682
  }
673
683
 
674
- static void generate_setmark(struct generator * g, struct node * p) {
675
- write_comment(g, p);
676
- g->V[0] = p->name;
677
- writef(g, "~M~V0 = cursor;~N", p);
678
- }
679
-
680
684
  static void generate_tomark(struct generator * g, struct node * p) {
681
685
  write_comment(g, p);
682
686
  g->S[0] = p->mode == m_forward ? ">" : "<";
@@ -689,15 +693,6 @@ static void generate_tomark(struct generator * g, struct node * p) {
689
693
  w(g, "~Mcursor = "); generate_AE(g, p->AE); writef(g, ";~N", p);
690
694
  }
691
695
 
692
- static void generate_atmark(struct generator * g, struct node * p) {
693
- write_comment(g, p);
694
- w(g, "~Mif (cursor != "); generate_AE(g, p->AE); writef(g, ")~N", p);
695
- write_block_start(g);
696
- write_failure(g);
697
- write_block_end(g);
698
- g->unreachable = false;
699
- }
700
-
701
696
  static void generate_hop(struct generator * g, struct node * p) {
702
697
  write_comment(g, p);
703
698
  g->S[0] = p->mode == m_forward ? "+" : "-";
@@ -721,24 +716,12 @@ static void generate_hop(struct generator * g, struct node * p) {
721
716
  writef(g, "~}", p);
722
717
  }
723
718
 
724
- static void generate_delete(struct generator * g, struct node * p) {
725
- write_comment(g, p);
726
- writef(g, "~Mslice_del();~N", p);
727
- }
728
-
729
719
  static void generate_tolimit(struct generator * g, struct node * p) {
730
720
  write_comment(g, p);
731
721
  g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
732
722
  writef(g, "~Mcursor = ~S0;~N", p);
733
723
  }
734
724
 
735
- static void generate_atlimit(struct generator * g, struct node * p) {
736
- write_comment(g, p);
737
- g->S[0] = p->mode == m_forward ? "limit" : "limit_backward";
738
- g->S[1] = p->mode == m_forward ? "<" : ">";
739
- write_failure_if(g, "cursor ~S1 ~S0", p);
740
- }
741
-
742
725
  static void generate_leftslice(struct generator * g, struct node * p) {
743
726
  write_comment(g, p);
744
727
  g->S[0] = p->mode == m_forward ? "bra" : "ket";
@@ -753,14 +736,25 @@ static void generate_rightslice(struct generator * g, struct node * p) {
753
736
 
754
737
  static void generate_assignto(struct generator * g, struct node * p) {
755
738
  write_comment(g, p);
756
- g->V[0] = p->name;
757
- writef(g, "~Massign_to(~V0);~N", p);
739
+ writef(g, "~Mif (~V.length < limit) {~N~+", p);
740
+ writef(g, "~M~V = Arrays.copyOf(current, limit);~N~-", p);
741
+ writef(g, "~M} else {~N~+", p);
742
+ writef(g, "~MSystem.arraycopy(current, 0, ~V, 0, limit);~N~-", p);
743
+ writef(g, "~M}~N", p);
744
+ writef(g, "~ML~V = limit;~N", p);
745
+ g->java_import_arrays = true;
758
746
  }
759
747
 
760
748
  static void generate_sliceto(struct generator * g, struct node * p) {
761
749
  write_comment(g, p);
762
- g->V[0] = p->name;
763
- writef(g, "~Mslice_to(~V0);~N", p);
750
+ writef(g, "~Mslice_check();~N", p);
751
+ writef(g, "~Mif (~V.length < ket - bra) {~N~+", p);
752
+ writef(g, "~M~V = Arrays.copyOfRange(current, bra, ket);~N~-", p);
753
+ writef(g, "~M} else {~N~+", p);
754
+ writef(g, "~MSystem.arraycopy(current, bra, ~V, 0, ket - bra);~N~-", p);
755
+ writef(g, "~M}~N", p);
756
+ writef(g, "~ML~V = ket - bra;~N", p);
757
+ g->java_import_arrays = true;
764
758
  }
765
759
 
766
760
  static void generate_address(struct generator * g, struct node * p) {
@@ -768,13 +762,18 @@ static void generate_address(struct generator * g, struct node * p) {
768
762
  if (b != NULL) {
769
763
  write_literal_string(g, b);
770
764
  } else {
765
+ write_string(g, "new CharArraySequence(");
771
766
  write_varref(g, p->name);
767
+ write_string(g, ", L");
768
+ write_varref(g, p->name);
769
+ write_string(g, ")");
770
+ g->java_import_chararraysequence = true;
772
771
  }
773
772
  }
774
773
 
775
774
  static void generate_insert(struct generator * g, struct node * p, int style) {
776
- int keep_c = style == c_attach;
777
775
  write_comment(g, p);
776
+ int keep_c = style == c_attach;
778
777
  if (p->mode == m_backward) keep_c = !keep_c;
779
778
  if (keep_c) w(g, "~{~Mint c = cursor;~N");
780
779
  writef(g, "~Minsert(cursor, cursor, ", p);
@@ -783,11 +782,12 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
783
782
  if (keep_c) w(g, "~Mcursor = c;~N~}");
784
783
  }
785
784
 
786
- static void generate_assignfrom(struct generator * g, struct node * p) {
787
- int keep_c = p->mode == m_forward; /* like 'attach' */
788
-
785
+ static void generate_stringassign(struct generator * g, struct node * p) {
789
786
  write_comment(g, p);
790
- if (keep_c) writef(g, "~{~Mint c = cursor;~N", p);
787
+ int keep_c = p->mode == m_forward; /* like 'attach' */
788
+ if (keep_c) {
789
+ writef(g, "~{~Mint c = cursor;~N", p);
790
+ }
791
791
  if (p->mode == m_forward) {
792
792
  writef(g, "~Minsert(cursor, limit, ", p);
793
793
  } else {
@@ -795,19 +795,26 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
795
795
  }
796
796
  generate_address(g, p);
797
797
  writef(g, ");~N", p);
798
- if (keep_c) w(g, "~Mcursor = c;~N~}");
798
+ if (keep_c) {
799
+ w(g, "~Mcursor = c;~N~}");
800
+ }
799
801
  }
800
802
 
801
803
  static void generate_slicefrom(struct generator * g, struct node * p) {
802
804
  write_comment(g, p);
805
+ if (p->literalstring && SIZE(p->literalstring) == 0) {
806
+ w(g, "~Mslice_del();~N");
807
+ return;
808
+ }
803
809
  w(g, "~Mslice_from(");
804
810
  generate_address(g, p);
805
- writef(g, ");~N", p);
811
+ w(g, ");~N");
806
812
  }
807
813
 
808
814
  static void generate_setlimit(struct generator * g, struct node * p) {
809
- struct str * varname = vars_newname(g);
810
815
  write_comment(g, p);
816
+ struct str * varname = vars_newname(g);
817
+
811
818
  if (p->left && p->left->type == c_tomark) {
812
819
  /* Special case for:
813
820
  *
@@ -819,6 +826,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
819
826
  */
820
827
  struct node * q = p->left;
821
828
  write_comment(g, q);
829
+
822
830
  g->S[0] = q->mode == m_forward ? ">" : "<";
823
831
  w(g, "~Mif (cursor ~S0 "); generate_AE(g, q->AE); w(g, ")~N");
824
832
  write_block_start(g);
@@ -828,14 +836,17 @@ static void generate_setlimit(struct generator * g, struct node * p) {
828
836
 
829
837
  g->B[0] = str_data(varname);
830
838
  if (p->mode == m_forward) {
831
- w(g, "~Mint ~B0 = limit - cursor;~N");
839
+ w(g, "~Mint ~B0 = limit;~N");
832
840
  w(g, "~Mlimit = ");
841
+ generate_AE(g, q->AE);
842
+ w(g, ";~N");
843
+ w(g, "~M~B0 -= limit;~N");
833
844
  } else {
834
845
  w(g, "~Mint ~B0 = limit_backward;~N");
835
846
  w(g, "~Mlimit_backward = ");
847
+ generate_AE(g, q->AE);
848
+ w(g, ";~N");
836
849
  }
837
- generate_AE(g, q->AE);
838
- writef(g, ";~N", q);
839
850
 
840
851
  if (p->mode == m_forward) {
841
852
  str_assign(g->failure_str, "limit += ");
@@ -893,34 +904,62 @@ static void generate_setlimit(struct generator * g, struct node * p) {
893
904
  static void generate_dollar(struct generator * g, struct node * p) {
894
905
  write_comment(g, p);
895
906
 
907
+ int a0 = g->failure_label;
908
+ struct str * a1 = str_copy(g->failure_str);
909
+ int label = new_label(g);
910
+ g->failure_label = label;
911
+ str_clear(g->failure_str);
912
+
896
913
  struct str * savevar = vars_newname(g);
897
914
  g->B[0] = str_data(savevar);
898
915
  writef(g, "~{~N"
899
916
  "~MSnowballProgram ~B0 = new SnowballProgram(this);~N", p);
900
917
 
901
- ++g->copy_from_count;
902
- str_assign(g->failure_str, "copy_from(");
903
- str_append(g->failure_str, savevar);
904
- str_append_string(g->failure_str, ");");
905
- g->V[0] = p->name;
906
- writef(g, "~Mcurrent = ~V0;~N"
918
+ writef(g, "~Mcurrent = ~V;~N"
907
919
  "~Mcursor = 0;~N"
908
- "~Mlimit = current.length();~N", p);
920
+ "~Mlength = L~V;~N"
921
+ "~Mlimit = length;~N", p);
922
+ if (p->left->possible_signals == -1) {
923
+ /* Assume failure. */
924
+ w(g, "~Mboolean ~B0_f = true;~N");
925
+ }
926
+
927
+ wsetlab_begin(g, g->failure_label);
928
+
909
929
  generate(g, p->left);
910
- if (!g->unreachable) {
911
- write_margin(g);
912
- write_str(g, g->failure_str);
913
- write_newline(g);
930
+
931
+ if (!g->unreachable && p->left->possible_signals == -1) {
932
+ /* Mark success. */
933
+ g->B[0] = str_data(savevar);
934
+ w(g, "~M~B0_f = false;~N");
935
+ }
936
+
937
+ wsetlab_end(g);
938
+
939
+ g->failure_label = a0;
940
+ str_delete(g->failure_str);
941
+ g->failure_str = a1;
942
+
943
+ g->B[0] = str_data(savevar);
944
+ writef(g, "~ML~W = length;~N"
945
+ "~Mcopy_from(~B0);~N", p);
946
+ ++g->copy_from_count;
947
+
948
+ if (p->left->possible_signals == 0) {
949
+ // p->left always signals f.
950
+ write_failure(g);
951
+ } else if (p->left->possible_signals == -1) {
952
+ write_failure_if(g, "~B0_f", p);
914
953
  }
915
954
  w(g, "~}");
955
+
916
956
  str_delete(savevar);
917
957
  }
918
958
 
919
959
  static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
920
960
  write_comment(g, p);
921
- g->V[0] = p->name;
922
961
  g->S[0] = s;
923
- w(g, "~M~V0 ~S0 ");
962
+ writef(g, "~M~V ~S0 ", p);
924
963
  generate_AE(g, p->AE);
925
964
  w(g, ";~N");
926
965
  }
@@ -928,7 +967,7 @@ static void generate_integer_assign(struct generator * g, struct node * p, const
928
967
  static void generate_integer_test(struct generator * g, struct node * p) {
929
968
  write_comment(g, p);
930
969
  int relop = p->type;
931
- int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
970
+ int optimise_to_return = tailcallable(g, p);
932
971
  if (optimise_to_return) {
933
972
  w(g, "~Mreturn ");
934
973
  p->right = NULL;
@@ -938,8 +977,7 @@ static void generate_integer_test(struct generator * g, struct node * p) {
938
977
  relop ^= 1;
939
978
  }
940
979
  generate_AE(g, p->left);
941
- // Relational operators are the same as C.
942
- write_c_relop(g, relop);
980
+ write_relop(g, relop);
943
981
  generate_AE(g, p->AE);
944
982
  if (optimise_to_return) {
945
983
  w(g, ";~N");
@@ -953,24 +991,30 @@ static void generate_integer_test(struct generator * g, struct node * p) {
953
991
  }
954
992
 
955
993
  static void generate_call(struct generator * g, struct node * p) {
956
- int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
994
+ int signals = p->name->definition->possible_signals;
957
995
  write_comment(g, p);
958
- g->V[0] = p->name;
959
- if (g->failure_label == x_return &&
960
- (signals == 0 || (p->right && p->right->type == c_functionend))) {
961
- /* Always fails or tail call. */
962
- writef(g, "~Mreturn ~V0();~N", p);
996
+ if (tailcallable(g, p)) {
997
+ /* Tail call. */
998
+ writef(g, "~Mreturn ~V();~N", p);
999
+ p->right = NULL;
1000
+ g->unreachable = true;
1001
+ return;
1002
+ }
1003
+ if (just_return_on_fail(g) && signals == 0) {
1004
+ /* Always fails. */
1005
+ writef(g, "~Mreturn ~V();~N", p);
1006
+ g->unreachable = true;
963
1007
  return;
964
1008
  }
965
1009
  if (signals == 1) {
966
1010
  /* Always succeeds. */
967
- writef(g, "~M~V0();~N", p);
1011
+ writef(g, "~M~V();~N", p);
968
1012
  } else if (signals == 0) {
969
1013
  /* Always fails. */
970
- writef(g, "~M~V0();~N", p);
1014
+ writef(g, "~M~V();~N", p);
971
1015
  write_failure(g);
972
1016
  } else {
973
- write_failure_if(g, "!~V0()", p);
1017
+ write_failure_if(g, "!~V()", p);
974
1018
  }
975
1019
  }
976
1020
 
@@ -980,30 +1024,41 @@ static void generate_grouping(struct generator * g, struct node * p, int complem
980
1024
  struct grouping * q = p->name->grouping;
981
1025
  g->S[0] = p->mode == m_forward ? "" : "_b";
982
1026
  g->S[1] = complement ? "out" : "in";
983
- g->V[0] = p->name;
984
1027
  g->I[0] = q->smallest_ch;
985
1028
  g->I[1] = q->largest_ch;
986
- write_failure_if(g, "!(~S1_grouping~S0(~V0, ~I0, ~I1))", p);
1029
+ if (tailcallable(g, p)) {
1030
+ writef(g, "~Mreturn ~S1_grouping~S0(~V, ~I0, ~I1);~N", p);
1031
+ p->right = NULL;
1032
+ } else {
1033
+ write_failure_if(g, "!(~S1_grouping~S0(~V, ~I0, ~I1))", p);
1034
+ }
987
1035
  }
988
1036
 
989
1037
  static void generate_namedstring(struct generator * g, struct node * p) {
990
1038
  write_comment(g, p);
991
1039
  g->S[0] = p->mode == m_forward ? "" : "_b";
992
- g->V[0] = p->name;
993
- write_failure_if(g, "!(eq_s~S0(~V0))", p);
1040
+ if (tailcallable(g, p)) {
1041
+ writef(g, "~Mreturn eq_s~S0(new CharArraySequence(~V, L~V));~N", p);
1042
+ p->right = NULL;
1043
+ } else {
1044
+ write_failure_if(g, "!(eq_s~S0(new CharArraySequence(~V, L~V)))", p);
1045
+ }
1046
+ g->java_import_chararraysequence = true;
994
1047
  }
995
1048
 
996
1049
  static void generate_literalstring(struct generator * g, struct node * p) {
997
- symbol * b = p->literalstring;
998
1050
  write_comment(g, p);
999
1051
  g->S[0] = p->mode == m_forward ? "" : "_b";
1000
- g->L[0] = b;
1001
- write_failure_if(g, "!(eq_s~S0(~L0))", p);
1052
+ if (tailcallable(g, p)) {
1053
+ writef(g, "~Mreturn eq_s~S0(~L);~N", p);
1054
+ p->right = NULL;
1055
+ } else {
1056
+ write_failure_if(g, "!(eq_s~S0(~L))", p);
1057
+ }
1002
1058
  }
1003
1059
 
1004
1060
  static void generate_define(struct generator * g, struct node * p) {
1005
1061
  struct name * q = p->name;
1006
- if (q->type == t_routine && !q->used) return;
1007
1062
 
1008
1063
  write_newline(g);
1009
1064
  write_comment(g, p);
@@ -1011,38 +1066,54 @@ static void generate_define(struct generator * g, struct node * p) {
1011
1066
  if (q->type == t_routine) {
1012
1067
  g->S[0] = "private";
1013
1068
  } else {
1014
- w(g, "~M@Override~N");
1069
+ if (SIZE(q->s) == 4 && memcmp(q->s, "stem", 4) == 0) {
1070
+ w(g, "~M@Override~N");
1071
+ }
1015
1072
  g->S[0] = "public";
1016
1073
  }
1017
- g->V[0] = q;
1018
- w(g, "~M~S0 boolean ~V0() {~+~N");
1019
-
1020
- /* Save output. */
1021
- struct str * saved_output = g->outbuf;
1022
- g->outbuf = str_new();
1074
+ writef(g, "~M~S0 boolean ~V() {~+~N", p);
1023
1075
 
1024
1076
  g->next_label = 0;
1025
1077
  g->var_number = 0;
1026
1078
 
1027
- if (p->amongvar_needed) w(g, "~Mint among_var;~N");
1079
+ if (q->amongvar_needed) {
1080
+ w(g, "~Mint among_var;~N");
1081
+ }
1082
+
1083
+ /* Declare localised variables. */
1084
+ for (struct name * name = g->analyser->names; name; name = name->next) {
1085
+ if (name->local_to == q) {
1086
+ switch (name->type) {
1087
+ case t_string:
1088
+ assert(0);
1089
+ break;
1090
+ case t_integer:
1091
+ w(g, "~Mint ");
1092
+ write_varname(g, name);
1093
+ w(g, ";~N");
1094
+ break;
1095
+ case t_boolean:
1096
+ w(g, "~Mboolean ");
1097
+ write_varname(g, name);
1098
+ w(g, ";~N");
1099
+ break;
1100
+ }
1101
+ }
1102
+ }
1103
+
1028
1104
  str_clear(g->failure_str);
1029
1105
  g->failure_label = x_return;
1030
1106
  g->unreachable = false;
1031
- int signals = check_possible_signals_list(g, p->left, c_define, 0);
1032
1107
 
1033
1108
  /* Generate function body. */
1034
1109
  generate(g, p->left);
1035
1110
  if (p->left->right) {
1036
1111
  assert(p->left->right->type == c_functionend);
1037
- if (signals) {
1112
+ if (p->left->possible_signals) {
1038
1113
  generate(g, p->left->right);
1039
1114
  }
1040
1115
  }
1041
1116
  w(g, "~}");
1042
-
1043
- str_append(saved_output, g->outbuf);
1044
- str_delete(g->outbuf);
1045
- g->outbuf = saved_output;
1046
1117
  }
1047
1118
 
1048
1119
  static void generate_functionend(struct generator * g, struct node * p) {
@@ -1065,6 +1136,10 @@ static void generate_substring(struct generator * g, struct node * p) {
1065
1136
  }
1066
1137
  } else if (x->always_matches) {
1067
1138
  writef(g, "~Mfind_among~S0(a_~I0);~N", p);
1139
+ } else if (x->command_count == 0 && tailcallable(g, p)) {
1140
+ writef(g, "~Mreturn find_among~S0(a_~I0) != 0;~N", p);
1141
+ x->node->right = NULL;
1142
+ g->unreachable = true;
1068
1143
  } else {
1069
1144
  write_failure_if(g, "find_among~S0(a_~I0) == 0", p);
1070
1145
  }
@@ -1096,10 +1171,24 @@ static void generate_among(struct generator * g, struct node * p) {
1096
1171
  }
1097
1172
  }
1098
1173
 
1099
- static void generate_booltest(struct generator * g, struct node * p) {
1174
+ static void generate_booltest(struct generator * g, struct node * p, int inverted) {
1100
1175
  write_comment(g, p);
1101
- g->V[0] = p->name;
1102
- write_failure_if(g, "!(~V0)", p);
1176
+ if (tailcallable(g, p)) {
1177
+ // Optimise at end of function.
1178
+ if (inverted) {
1179
+ writef(g, "~Mreturn !~V;~N", p);
1180
+ } else {
1181
+ writef(g, "~Mreturn ~V;~N", p);
1182
+ }
1183
+ p->right = NULL;
1184
+ g->unreachable = true;
1185
+ return;
1186
+ }
1187
+ if (inverted) {
1188
+ write_failure_if(g, "~V", p);
1189
+ } else {
1190
+ write_failure_if(g, "!~V", p);
1191
+ }
1103
1192
  }
1104
1193
 
1105
1194
  static void generate_false(struct generator * g, struct node * p) {
@@ -1144,25 +1233,21 @@ static void generate(struct generator * g, struct node * p) {
1144
1233
  case c_repeat: generate_repeat(g, p); break;
1145
1234
  case c_loop: generate_loop(g, p); break;
1146
1235
  case c_atleast: generate_atleast(g, p); break;
1147
- case c_setmark: generate_setmark(g, p); break;
1148
1236
  case c_tomark: generate_tomark(g, p); break;
1149
- case c_atmark: generate_atmark(g, p); break;
1150
1237
  case c_hop: generate_hop(g, p); break;
1151
- case c_delete: generate_delete(g, p); break;
1152
1238
  case c_next: generate_next(g, p); break;
1153
1239
  case c_tolimit: generate_tolimit(g, p); break;
1154
- case c_atlimit: generate_atlimit(g, p); break;
1155
1240
  case c_leftslice: generate_leftslice(g, p); break;
1156
1241
  case c_rightslice: generate_rightslice(g, p); break;
1157
1242
  case c_assignto: generate_assignto(g, p); break;
1158
1243
  case c_sliceto: generate_sliceto(g, p); break;
1159
- case c_assign: generate_assignfrom(g, p); break;
1244
+ case c_stringassign: generate_stringassign(g, p); break;
1160
1245
  case c_insert:
1161
1246
  case c_attach: generate_insert(g, p, p->type); break;
1162
1247
  case c_slicefrom: generate_slicefrom(g, p); break;
1163
1248
  case c_setlimit: generate_setlimit(g, p); break;
1164
1249
  case c_dollar: generate_dollar(g, p); break;
1165
- case c_mathassign: generate_integer_assign(g, p, "="); break;
1250
+ case c_assign: generate_integer_assign(g, p, "="); break;
1166
1251
  case c_plusassign: generate_integer_assign(g, p, "+="); break;
1167
1252
  case c_minusassign: generate_integer_assign(g, p, "-="); break;
1168
1253
  case c_multiplyassign:generate_integer_assign(g, p, "*="); break;
@@ -1182,7 +1267,8 @@ static void generate(struct generator * g, struct node * p) {
1182
1267
  case c_literalstring: generate_literalstring(g, p); break;
1183
1268
  case c_among: generate_among(g, p); break;
1184
1269
  case c_substring: generate_substring(g, p); break;
1185
- case c_booltest: generate_booltest(g, p); break;
1270
+ case c_booltest: generate_booltest(g, p, false); break;
1271
+ case c_not_booltest: generate_booltest(g, p, true); break;
1186
1272
  case c_false: generate_false(g, p); break;
1187
1273
  case c_true: break;
1188
1274
  case c_debug: generate_debug(g, p); break;
@@ -1198,15 +1284,23 @@ static void generate(struct generator * g, struct node * p) {
1198
1284
 
1199
1285
  static void generate_class_begin(struct generator * g) {
1200
1286
  w(g, "package ");
1201
- w(g, g->options->package);
1287
+ write_string(g, g->options->package);
1202
1288
  w(g, ";~N~N");
1203
1289
 
1204
- if (g->analyser->among_count > 0) {
1290
+ if (g->java_import_arrays) {
1291
+ w(g, "import java.util.Arrays;~N~N");
1292
+ }
1293
+
1294
+ if (g->analyser->amongs) {
1205
1295
  w(g, "import ");
1206
- w(g, g->options->among_class);
1296
+ write_string(g, g->options->among_class);
1207
1297
  w(g, ";~N~N");
1208
1298
  }
1209
1299
 
1300
+ if (g->java_import_chararraysequence) {
1301
+ w(g, "import org.tartarus.snowball.CharArraySequence;~N~N");
1302
+ }
1303
+
1210
1304
  if (g->copy_from_count > 0) {
1211
1305
  w(g, "import org.tartarus.snowball.SnowballProgram;~N~N");
1212
1306
  }
@@ -1222,10 +1316,8 @@ static void generate_class_begin(struct generator * g) {
1222
1316
  "@SuppressWarnings(\"unused\")~N"
1223
1317
  "public class ~n extends ");
1224
1318
 
1225
- w(g, g->options->parent_class_name);
1226
- w(g, " {~+~N"
1227
- "~N"
1228
- "~Mprivate static final long serialVersionUID = 1L;~N");
1319
+ write_string(g, g->options->parent_class_name);
1320
+ w(g, " {~+~N");
1229
1321
  if (g->analyser->among_with_function_count > 0) {
1230
1322
  w(g, "~Mprivate static final java.lang.invoke.MethodHandles.Lookup methodObject = java.lang.invoke.MethodHandles.lookup();~N");
1231
1323
  }
@@ -1242,13 +1334,13 @@ static void generate_equals(struct generator * g) {
1242
1334
  "~M@Override~N"
1243
1335
  "~Mpublic boolean equals( Object o ) {~N"
1244
1336
  "~+~Mreturn o instanceof ");
1245
- w(g, g->options->name);
1337
+ write_s(g, g->options->name);
1246
1338
  w(g, ";~N~-~M}~N"
1247
1339
  "~N"
1248
1340
  "~M@Override~N"
1249
1341
  "~Mpublic int hashCode() {~N"
1250
1342
  "~+~Mreturn ");
1251
- w(g, g->options->name);
1343
+ write_s(g, g->options->name);
1252
1344
  w(g, ".class.getName().hashCode();~N"
1253
1345
  "~-~M}~N");
1254
1346
  }
@@ -1259,23 +1351,23 @@ static void generate_among_table(struct generator * g, struct among * x) {
1259
1351
  struct amongvec * v = x->b;
1260
1352
 
1261
1353
  g->I[0] = x->number;
1262
-
1263
1354
  w(g, "~Mprivate final static Among[] a_~I0 = {~N~+");
1264
1355
  for (int i = 0; i < x->literalstring_count; i++) {
1356
+ if (i) w(g, ",~N");
1265
1357
  g->I[0] = v[i].i;
1266
1358
  g->I[1] = v[i].result;
1267
- g->L[0] = v[i].b;
1268
- g->S[0] = i < x->literalstring_count - 1 ? "," : "";
1269
1359
 
1270
- w(g, "~Mnew Among(~L0, ~I0, ~I1");
1360
+ w(g, "~Mnew Among(");
1361
+ write_literal_string(g, v[i].b);
1362
+ w(g, ", ~I0, ~I1");
1271
1363
  if (v[i].function != NULL) {
1272
1364
  w(g, ", \"");
1273
1365
  write_varname(g, v[i].function);
1274
1366
  w(g, "\", methodObject");
1275
1367
  }
1276
- w(g, ")~S0~N");
1368
+ w(g, ")");
1277
1369
  }
1278
- w(g, "~-~M};~N~N");
1370
+ w(g, "~N~-~M};~N~N");
1279
1371
  }
1280
1372
 
1281
1373
  static void generate_amongs(struct generator * g) {
@@ -1284,11 +1376,11 @@ static void generate_amongs(struct generator * g) {
1284
1376
  }
1285
1377
  }
1286
1378
 
1287
- static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1379
+ static void set_bit(symbol * b, int i) { b[i >> 3] |= 1 << (i & 7); }
1288
1380
 
1289
1381
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1290
1382
  int range = q->largest_ch - q->smallest_ch + 1;
1291
- int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1383
+ int size = (range + 7) / 8; /* assume 8 bits per symbol */
1292
1384
  symbol * b = q->b;
1293
1385
  symbol * map = create_b(size);
1294
1386
 
@@ -1296,11 +1388,12 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1296
1388
 
1297
1389
  for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1298
1390
 
1299
- g->V[0] = q->name;
1300
- w(g, "~Mprivate static final char[] ~V0 = {");
1391
+ w(g, "~Mprivate static final char[] ");
1392
+ write_varname(g, q->name);
1393
+ write_string(g, " = {");
1301
1394
  for (int i = 0; i < size; i++) {
1395
+ if (i) w(g, ", ");
1302
1396
  write_int(g, map[i]);
1303
- if (i < size - 1) w(g, ", ");
1304
1397
  }
1305
1398
  w(g, " };~N~N");
1306
1399
 
@@ -1309,31 +1402,35 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1309
1402
 
1310
1403
  static void generate_groupings(struct generator * g) {
1311
1404
  for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1312
- if (q->name->used)
1313
- generate_grouping_table(g, q);
1405
+ generate_grouping_table(g, q);
1314
1406
  }
1315
1407
  }
1316
1408
 
1317
1409
  static void generate_members(struct generator * g) {
1318
- int wrote_members = false;
1410
+ bool wrote_members = false;
1319
1411
 
1320
1412
  for (struct name * q = g->analyser->names; q; q = q->next) {
1321
- g->V[0] = q;
1413
+ if (q->local_to) continue;
1322
1414
  switch (q->type) {
1323
1415
  case t_string:
1324
- w(g, "~Mprivate ");
1325
- w(g, g->options->string_class);
1326
- w(g, " ~W0 = new ");
1327
- w(g, g->options->string_class);
1328
- w(g, "();~N");
1416
+ w(g, "~Mprivate char[] ");
1417
+ write_varname(g, q);
1418
+ w(g, " = new char[8];~N");
1419
+ w(g, "~Mprivate int L");
1420
+ write_varname(g, q);
1421
+ w(g, " = 0;~N");
1329
1422
  wrote_members = true;
1330
1423
  break;
1331
1424
  case t_integer:
1332
- w(g, "~Mprivate int ~W0;~N");
1425
+ w(g, "~Mprivate int ");
1426
+ write_varname(g, q);
1427
+ w(g, ";~N");
1333
1428
  wrote_members = true;
1334
1429
  break;
1335
1430
  case t_boolean:
1336
- w(g, "~Mprivate boolean ~W0;~N");
1431
+ w(g, "~Mprivate boolean ");
1432
+ write_varname(g, q);
1433
+ w(g, ";~N");
1337
1434
  wrote_members = true;
1338
1435
  break;
1339
1436
  }