Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

1440
LINES

< > BotCompany Repo | #1007595 // "Super-Edgy" JavaX Translator (Extension of #752) [dev., broken]

JavaX translator

1  
!1006722
2  
3  
// experimental
4  
sbool stdstuffOnFunctions = false;
5  
6  
sbool verify_includes = true;
7  
8  
static bool autoQuine = true;
9  
static int maxQuineLength = 80;
10  
11  
!include #1001496 // Matches
12  
!include #1000882 // EGDiff
13  
!include #1000883 // BlockDiffer
14  
!include #1001065 // DialoGIO
15  
!include #1004045 // IndexedList2
16  
//include #1001296 // MultiMap
17  
!include #1000988 // MultiSet
18  
!include #1004543 // DynamicObject
19  
!include #1005575 // CompilerBot
20  
21  
!include #1002662 // isTrue
22  
23  
static int varCount;
24  
static new Map<S, S> snippetCache;
25  
static bool useIndexedList = true, opt_javaTok = true;
26  
27  
p {
28  
  setOpt(mc(), "includeInMainLoaded_safe", true);
29  
  if (useIndexedList) findCodeTokens_debug = true;
30  
  javaTok_opt = opt_javaTok;
31  
  findCodeTokens_indexed = findCodeTokens_unindexed = 0;
32  
  findCodeTokens_bails = findCodeTokens_nonbails = 0;
33  
  javaTok_n = javaTok_elements = 0;
34  
  S in = loadMainJava();
35  
  
36  
  print("759 STARTING " + identityHashCode(main.class));
37  
  varCount = 0;
38  
  
39  
  //L ts = findTranslators(toLines(join(tok)));
40  
  //print("Translators in source at start: " + structure(ts));
41  
  
42  
  // "duplicate" statement
43  
  
44  
  L<S> lines = toLines(in);
45  
  call(getJavaX(), "findTranslators", lines);
46  
  in = fromLines(lines);
47  
  new Matches m;
48  
  if (match("duplicate *", in, m)) {
49  
    // actual copying - unused
50  
    // tok = jtok(loadSnippet(m.get(0)));
51  
    
52  
    // reference by include()
53  
    in = "m { p { callMain(include(" + quote(m.get(0)) + ")); } }";
54  
  }
55  
  
56  
  L<S> tok = jtok(in);
57  
58  
  // add m { }
59  
  
60  
  if (!hasCodeTokens(tok, "m", "{") && !hasCodeTokens(tok, "main", "{") && !hasCodeTokens(tok, "class", "main"))
61  
    tok = jtok(moveImportsUp("m {\n" + in + "\n}"));
62  
  
63  
  // standard translate
64  
  
65  
  //ts = findTranslators(toLines(join(tok)));
66  
  //print("Translators in source: " + structure(ts));
67  
  tok = jtok(defaultTranslate(join(tok)));
68  
  
69  
  //print("end of default translate");
70  
  //print(join(tok));
71  
72  
  tok_autoCloseBrackets(tok);    
73  
  tok = processIncludes(tok); // before standard functions
74  
  processConceptsDot(tok);
75  
  tok = processIncludes(tok);
76  
  earlyStuff(tok);
77  
  
78  
  int safety = 0;
79  
  boolean same;
80  
  do {
81  
    S before = join(tok);
82  
    
83  
    // shortened method declarations BEFORE standardFunctions
84  
    jreplace(tok, "svoid", "static void");
85  
    jreplace(tok, "void <id> {", "$1 $2() {");
86  
    jreplace(tok, "String <id> {", "$1 $2() {");
87  
    jreplace(tok, "Object <id> {", "$1 $2() {");
88  
    jreplace(tok, "List <id> {", "$1 $2() {");
89  
    
90  
    standardFunctions(tok);
91  
    stdstuff(tok, true); // JavaX keywords, special syntax etc.
92  
    S diff;
93  
    long startTime = now();
94  
    //diff = unidiff(before, join(tok));
95  
    //print("unidiff: " + (now()-startTime) + " ms");
96  
    //same = eq(diff, "");
97  
    same = eq(before, join(tok)); // << could be sped up
98  
    if (!same) {
99  
      print("Not same " + safety + ".");
100  
      //print(indent(2, diff));
101  
    }
102  
    if (safety++ >= 10) {
103  
      //print(unidiff(before, join(tok)));
104  
      print("----");
105  
      print(join(tok));
106  
      print("----");
107  
      fail("safety 10 error!");
108  
    }
109  
  } while (!same);
110  
  
111  
  // POST-PROCESSING after stdstuff loop
112  
  
113  
  quicknew2(tok);
114  
  //tok = jtok(quicknew(join(tok)));
115  
  tok = extendClasses(tok);
116  
  libs(tok);
117  
  sourceCodeLine(tok);
118  
  throwFail(tok);
119  
  innerClassesVar(tok);
120  
  tok_ifclass(tok);
121  
  tok = autoImports(tok); // faster to do it at the end
122  
123  
  if (useIndexedList)
124  
    print("Indexed/unindexed lookups: " + findCodeTokens_indexed + "/" + findCodeTokens_unindexed + ", lists made: " + IndexedList2.instances);
125  
  print("findCodeToken bails: " + findCodeTokens_bails + "/" + findCodeTokens_nonbails);
126  
  print("javaToks: " + javaTok_n + "/" + javaTok_elements);
127  
  
128  
  if (tok.contains("package"))
129  
    splitJavaFiles(tok);
130  
  else
131  
    saveMainJava(tok);
132  
}
133  
134  
static S stdstuff(S s) { ret join(stdstuff(jtok(s), false)); }
135  
136  
static L<S> stdstuff(L<S> tok, bool globalStuff) {
137  
  //if (++level >= 10) fail("woot? 10");
138  
  
139  
  print("stdstuff!");
140  
  int i;
141  
  
142  
  if (jfind(tok, "!<int>") >= 0) {
143  
    L<S> lines = toLines(join(tok));
144  
    L ts = findTranslators(lines);
145  
    tok = jtok(fromLines(lines));
146  
    print("DROPPING TRANSLATORS: " + structure(ts));
147  
  }
148  
149  
  tok = quickmain(tok);
150  
  tok = processIncludes(tok);
151  
  processConceptsDot(tok);
152  
  tok = processIncludes(tok);
153  
  earlyStuff(tok);
154  
  tok = multilineStrings(tok);
155  
  inStringEvals(tok);
156  
  listComprehensions(tok);
157  
  directSnippetRefs(tok);
158  
  quicknu(tok);
159  
  
160  
  jreplace(tok, "synced <id>", "synchronized $2");
161  
  
162  
  replaceKeywordBlock(tok, "answer",
163  
    "static S answer(S s) {\nfinal new Matches m;\n",
164  
    "\nret null;\n}");
165  
    
166  
  replaceKeywordBlock(tok, "loading",
167  
    "{ JWindow _loading_window = showLoadingAnimation(); try { /* loading try */ ",
168  
    "/* loading try */ } finally { disposeWindow(_loading_window); }\n /* loading end */ } /* after loading */ \n");
169  
170  
  replaceKeywordBlock(tok, "html",
171  
    "static O html(S uri, fMap<S, S> params) ctex " + "{\n", "}");
172  
  
173  
  // "static sync" => static synchronized
174  
  jreplace(tok, "static sync", "static synchronized");
175  
176  
  // "sclass" => static class
177  
  jreplace(tok, "sclass", "static class");
178  
179  
  // "asclass" => abstract static class
180  
  jreplace(tok, "asclass", "abstract static class");
181  
182  
  // "sinterface" => static interface
183  
  jreplace(tok, "sinterface", "static interface");
184  
185  
  // "ssynchronized" => static synchronized
186  
  jreplace(tok, "ssynchronized", "static synchronized");
187  
188  
  jreplace(tok, "ssvoid", "static synchronized void");
189  
  jreplace(tok, "sbool", "static bool");
190  
  jreplace(tok, "sint", "static int");
191  
  jreplace(tok, "snew", "static new");
192  
  jreplace(tok, "sv <id>", "static void $2");
193  
  jreplace(tok, "pvoid", "public void");
194  
195  
  // "sS" => static S
196  
  jreplace(tok, "sS", "static S");
197  
198  
  // "sO" => static O
199  
  jreplace(tok, "sO", "static O");
200  
201  
  // "sL" => static L
202  
  jreplace(tok, "sL", "static L");
203  
204  
  // "toString {" => "public S toString() {"
205  
  jreplace(tok, "toString {", "public S toString() {");
206  
  
207  
  jreplace(tok, "Int", "Integer");
208  
  jreplace(tok, "Bool", "Boolean");
209  
  jreplace(tok, "Char", "Character");
210  
  
211  
  // I REALLY wanted to avoid this, but eh...
212  
  jreplace(tok, "SS", "Map<S, S>");
213  
214  
  // "on fail {" => "catch (Throwable _e) { ... rethrow(_e); }"
215  
  replaceKeywordBlock(tok, "on fail",
216  
    "catch (Throwable _e) {",
217  
    "\nthrow rethrow(_e); }");
218  
219  
  // "catch {" => "catch (Throwable _e) {"
220  
  jreplace(tok, "catch {", "catch (Throwable _e) {");
221  
222  
  // "catch X e {" => "catch (X e) {"
223  
  jreplace(tok, "catch <id> <id> {", "catch ($2 $3) {");
224  
225  
  // "catch e {" => "catch (Throwable e) {" (if e is lowercase)
226  
  jreplace(tok, "catch <id> {", "catch (Throwable $2) {", new O() {
227  
    bool get(L<S> tok, int i) {
228  
      S word = tok.get(i+3);
229  
      ret startsWithLowerCaseOrUnderscore(word);
230  
    }
231  
  });
232  
  
233  
  jreplace(tok, "+ +", "+", new O() {
234  
    bool get(L<S> tok, int i) {
235  
      //printStructure("++: ", subList(tok, i-1, i+6));
236  
      if (empty(_get(tok, i+2))) ret false; // no space between the pluses
237  
      if (empty(_get(tok, i)) && eq("+", _get(tok, i-1))) ret false;  // an actual "++" at the left
238  
      if (empty(_get(tok, i+4)) && eq("+", _get(tok, i+5))) ret false;  // an actual "++" at the right
239  
      //print("doing it");
240  
      ret true;
241  
    }
242  
  });
243  
244  
  // some crazy fancy syntax
245  
  jreplace(tok, "set <id>;", "$2 = true;");
246  
  
247  
  // [stdEq] -> implementation of equals()
248  
  jreplace(tok, "[stdEq]",
249  
    "public bool equals(O o) { ret stdEq2(this, o); }\n" +
250  
    "public int hashCode() { ret stdHash2(this); }");
251  
  
252  
  // [concepts] "concept.field -> bla" for dereferencing references
253  
  jreplace(tok, "<id> ->", "$1.get().");
254  
  
255  
  // [concepts] "concept.field!" for dereferencing references
256  
  
257  
  jreplace(tok, "<id>!", "$1.get()", new O() { bool get(L<S> tok, int i) {
258  
    if (tok.get(i+2).contains("\n")) ret false; // no line break between <id> and !
259  
    S t = _get(tok, i+5);
260  
    if (t == null) ret false;
261  
    if (isIdentifier(t) || eqOneOf(t, "=", "(")) ret false;
262  
    ret true;
263  
  }});
264  
  
265  
  // [concepts] "field := value" for defining fields e.g. in "uniq"
266  
  while ((i = jfind(tok, "<id> :=")) >= 0) {
267  
    tok.set(i, quote(tok.get(i)));
268  
    tok.set(i+2, ",");
269  
    tok.set(i+4, "");
270  
    reTok(tok, i, i+5);
271  
  }
272  
  
273  
  // "quoted" := value
274  
  while ((i = jfind(tok, "<quoted> :=")) >= 0) {
275  
    tok.set(i, tok.get(i));
276  
    tok.set(i+2, ",");
277  
    tok.set(i+4, "");
278  
    reTok(tok, i, i+5);
279  
  }
280  
  
281  
  // more shortening
282  
283  
  jreplace(tok, "fS", "final S");
284  
  jreplace(tok, "fO", "final O");
285  
  jreplace(tok, "fL", "final L");
286  
  jreplace(tok, "fMap", "final Map");
287  
  jreplace(tok, "fRunnable", "final Runnable");
288  
  jreplace(tok, "f int", "final int");
289  
  
290  
  // "continue unless"
291  
  
292  
  while ((i = jfind(tok, "continue unless")) >= 0) {
293  
    int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
294  
    replaceTokens(tok, i, i+4, "{ if (!(");
295  
    tok.set(j, ")) continue; }");
296  
    reTok(tok, i, j+1);
297  
  }
298  
  
299  
  // "continue if"
300  
  
301  
  while ((i = jfind(tok, "continue if")) >= 0) {
302  
    int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
303  
    replaceTokens(tok, i, i+4, "{ if (");
304  
    tok.set(j, ") continue; }");
305  
    reTok(tok, i, j+1);
306  
  }
307  
  
308  
  // "return if"
309  
  
310  
  while ((i = jfind(tok, "return if")) >= 0) {
311  
    int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
312  
    replaceTokens(tok, i, i+4, "{ if (");
313  
    tok.set(j, ") return; }");
314  
    reTok(tok, i, j+1);
315  
  }
316  
  
317  
  // while not null ()
318  
  
319  
  while ((i = jfind(tok, "while not null (")) >= 0) {
320  
    int closingBracket = findEndOfBracketPart(tok, i+6)-1;
321  
    replaceTokens(tok, i+2, i+6, "(");
322  
    tok.set(closingBracket, ") != null)");
323  
    reTok(tok, i, closingBracket+1);
324  
  }
325  
  
326  
  // Replace $1 with m.unq(0) etc. - caveat: this blocks identifiers $1, $2, ...
327  
  for (i = 1; i < l(tok); i += 2) {
328  
    S s = tok.get(i);
329  
    if (s.startsWith("$")) {
330  
      s = substring(s, 1);
331  
      if (isInteger(s)) {
332  
        tok.set(i, "m.unq(" + (parseInt(s)-1) + ")");
333  
        reTok(tok, i);
334  
      }
335  
    }
336  
  }
337  
338  
  // instanceof trickery
339  
  
340  
  jreplace(tok, "is a <id>", "instanceof $3");
341  
  jreplace(tok, "!<id> instanceof <id>.<id>", "!($2 instanceof $4.$6)");
342  
  jreplace(tok, "!<id> instanceof <id>", "!($2 instanceof $4)");
343  
  jreplace(tok, "<id> !instanceof <id>", "!($1 instanceof $4)");
344  
  
345  
  // func keyword for lambdas - now automatically quines toString() if enabled
346  
  
347  
  while ((i = jfind(tok, "func(")) >= 0) {
348  
    int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")");
349  
    int idx = findCodeTokens(tok, argsTo, false, "{");
350  
    int j = findEndOfBracketPart(tok, idx);
351  
    L<S> contents = subList(tok, idx+1, j-1);
352  
    replaceTokens(tok, i, j, "new O { O get(" + join(subList(tok, argsFrom, argsTo-1)) + ") ct" + "ex { " + tok_addReturn(contents) + " }\n" +
353  
    (autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}");
354  
    reTok(tok, i, j);
355  
  }
356  
  
357  
  while ((i = jfind(tok, "voidfunc(")) >= 0) {
358  
    int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")");
359  
    int idx = findCodeTokens(tok, argsTo, false, "{");
360  
    int j = findEndOfBracketPart(tok, idx);
361  
    L<S> contents = subList(tok, idx+1, j-1);
362  
    replaceTokens(tok, i, j, "new O { void get(" + join(subList(tok, argsFrom, argsTo-1)) + ") ct" + "ex { " + tok_addSemicolon(contents) + " }\n" +
363  
    (autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}");
364  
    reTok(tok, i, j);
365  
  }
366  
  
367  
  while ((i = jfind(tok, "func {")) >= 0) {
368  
    int idx = findCodeTokens(tok, i, false, "{");
369  
    int j = findEndOfBracketPart(tok, idx+2);
370  
    L<S> contents = subList(tok, idx+1, j-1);
371  
    replaceTokens(tok, i, j, "new O { O get() ct" + "ex { " + tok_addReturn(contents) + " }\n" +
372  
    (autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}");
373  
    reTok(tok, i, j);
374  
  }
375  
  /*replaceKeywordBlock(tok, "func",
376  
    "new O { O get() { ret",
377  
    ";}}");*/
378  
  
379  
  // shortened subconcept declaration (before star constructors!)
380  
  
381  
  jreplace(tok, "<id> > <id> {", "concept $3 extends $1 {", new O() { O get(L<S> tok, int i) {
382  
    //print("subconcept: " + quote(tok.get(i)));
383  
    ret tok.get(i).contains("\n"); // only at beginning of line
384  
  }});
385  
  
386  
  // "case" as a variable name ( => _case)
387  
  
388  
  caseAsVariableName(tok);
389  
  
390  
  // "continue" as a function name ( => _continue)
391  
  continueAsFunctionName(tok);
392  
  
393  
  // Do this BEFORE awt replacement! ("p-awt" contains "awt" token)
394  
  if (hasCodeTokens(tok, "p", "-")) {
395  
    jreplace(tok, "p-pretty {", "p-noconsole {");
396  
    replaceKeywordBlock(tok, "p-awt-noconsole", "p-awt {", "\nhideConsole(); }");
397  
    replaceKeywordBlock(tok, "p-substance-noconsole", "p-substance {", "\nhideConsole(); }");
398  
    replaceKeywordBlock(tok, "p-noconsole", "p-subst {", "\nhideConsole(); }");
399  
    replaceKeywordBlock(tok, "p-subst", "p-substance-thread {", "}");
400  
    replaceKeywordBlock(tok, "p-substance-thread", "p { substance();", "}");
401  
    replaceKeywordBlock(tok, "p-substance", "p-awt { substance();", "}");
402  
    jreplace(tok, "p-type {", "p-typewriter {");
403  
    jreplace(tok, "p-tt {", "p-typewriter {");
404  
    replaceKeywordBlock(tok, "p-awt", "p { swing {", "}}");
405  
    replaceKeywordBlock(tok, "p-typewriter", "p { typeWriterConsole();", "}");
406  
    replaceKeywordBlock(tok, "p-lowprio", "p { lowPriorityThread(r " + "{", "}); }");
407  
    tok_p_repeatWithSleep(tok);
408  
  }
409  
410  
  replaceKeywordBlock(tok,
411  
    "awt",
412  
    "swingLater(r " + "{", // for #711
413  
    "});");
414  
415  
  replaceKeywordBlock(tok,
416  
    "swing",
417  
    "{ swingAndWait(r " + "{", // for #711
418  
    "}); }");
419  
420  
  // crazy stuff
421  
422  
  jreplace (tok, "for <id> over <id>:", "for (int $2 = 0; $2 < l($4); $2++)");
423  
  jreplace (tok, "for <id> to <id>:", "for (int $2 = 0; $2 < $4; $2++)");
424  
  jreplace (tok, "for <id> to <int>:", "for (int $2 = 0; $2 < $4; $2++)");
425  
  
426  
  conceptDeclarations(tok);
427  
  
428  
  // * constructors
429  
  if (hasCodeTokens(tok, "\\*", "("))
430  
    tok = expandStarConstructors(tok);
431  
    
432  
  // STANDARD CLASSES & INTERFACES
433  
434  
  S sc = cacheGet("#1003674");   
435  
  new L<S> lclasses;
436  
  for (S line : toLinesFullTrim(sc)) {
437  
    line = javaDropComments(line).trim();
438  
    int idx = line.indexOf('/');
439  
    lclasses.addAll(ll(line.substring(0, idx), line.substring(idx+1)));
440  
  }
441  
  
442  
  final Set<S> haveClasses = globalStuff
443  
    ? addStandardClasses(tok, toStringArray(lclasses))
444  
    : null;
445  
  if (globalStuff) haveClasses.add("String");
446  
  
447  
  // Stuff that depends on the list of inner classes (haveClasses)
448  
  if (globalStuff) {
449  
    expandClassReferences(tok, haveClasses);
450  
    slashCasts(tok, haveClasses);
451  
  
452  
    // "x << X" => "x instanceof X"
453  
    jreplace(tok, "<id> << <id>", "$1 instanceof $4", new O() {
454  
      O get(L<S> tok, int i) {
455  
        ret haveClasses.contains(tok.get(i+7));
456  
      }
457  
    });
458  
  }
459  
460  
  tok_expandVarCopies(tok);
461  
  
462  
  // concept-related stuff
463  
  
464  
  // auto-import concepts
465  
  if (globalStuff) {
466  
    bool _a = hasCodeTokens(tok, /*"extends",*/ "Concept") || hasCodeTokens(tok, "Concepts"), _b = !haveClasses.contains("Concept");
467  
    print("auto-import: " + _a + ", " + _b);
468  
    if (_a && _b) {
469  
      printStruct(haveClasses);
470  
      tok = includeInMainLoaded(tok, "concepts.");
471  
      reTok(tok, l(tok)-1, l(tok));
472  
      //processConceptsDot(tok);
473  
    }
474  
  }
475  
  
476  
  jreplace(tok, "for (<id> <id>)", "for ($3 $4 : list($3))");
477  
478  
  // the infamous missing functions (usually caused by class Matches)
479  
  // maybe not needed anymore?
480  
  /*if (!hasCodeTokens(tok, "String", "unquote") && containsToken(tok, "unquote")) {
481  
    print("Adding unquote");
482  
    tok = includeInMain(tok, "#1001735");
483  
  }
484  
    
485  
  if (!hasCodeTokens(tok, "String", "formatSnippetID") && containsToken(tok, "formatSnippetID")) {
486  
    print("Adding formatSnippetID");
487  
    tok = includeInMain(tok, "#1000709");
488  
  }*/
489  
  
490  
  tok = expandShortTypes(tok);
491  
    
492  
  if (containsToken(tok, "cast")) {
493  
    S s = join(tok);
494  
    s = s.replaceAll("(\\w+<[\\w\\s,\\[\\]]+>|\\w+|\\w+\\[\\]|\\w+\\[\\]\\[\\])\\s+(\\w+)\\s*=\\s*cast(\\W[^;]*);", "$1 $2 = ($1) ($3);");
495  
    tok = jtok(s);
496  
  }
497  
  
498  
  replaceKeywordBlock(tok, "r-thread", "runnableThread(r " + "{", "})");
499  
  rNamedThread(tok);
500  
  
501  
  // runnable and r - now also with automatic toString if enabled
502  
  for (S keyword : ll("runnable", "r"))
503  
    while ((i = jfind(tok, keyword + " {")) >= 0) {
504  
      int idx = findCodeTokens(tok, i, false, "{");
505  
      int j = findEndOfBracketPart(tok, idx);
506  
      L<S> contents = subList(tok, idx+1, j-1);
507  
      //print("r contents: " + structure(contents));
508  
      replaceTokens(tok, i, j+1, "new Runnable() { public void run() { try { " + tok_addSemicolon(contents) + 
509  
        "\n} catch (Exception __e) { throw rethrow(__e); } }" +
510  
    (autoQuine ? "  public S toString() { return " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") +
511  
        "}");
512  
      reTok(tok, i, j+1);
513  
    }
514  
  
515  
  replaceKeywordBlock(tok,
516  
    "expectException",
517  
    "{ bool __ok = false; try {",
518  
    "} catch { __ok = true; } assertTrue(\"expected exception\", __ok); }");
519  
    
520  
  while ((i = tok.indexOf("tex")) >= 0) {
521  
    tok.set(i, "throws Exception");
522  
    tok = jtok(tok);
523  
  }
524  
  
525  
  // shorter & smarter whiles
526  
  
527  
  jreplace(tok, "while true", "while (true)");
528  
  jreplace(tok, "while licensed", "while (licensed())");
529  
  jreplace(tok, "repeat {", "while (licensed()) {");
530  
  tok_repeatWithSleep(tok);
531  
  
532  
  // null; => return null; etc.
533  
534  
  O cond = new O() {
535  
    bool get(L<S> tok, int i) {
536  
      S t = _get(tok, i-1);
537  
      ret l(t) == 1 && "{};)".contains(t) || eq(t, "else");
538  
    }
539  
  };
540  
  jreplace(tok, "null;", "return null;", cond);
541  
  jreplace(tok, "false;", "return false;", cond);
542  
  jreplace(tok, "true;", "return true;", cond);
543  
  jreplace(tok, "this;", "return this;", cond);
544  
545  
  // "myFunction;" instead of "myFunction();" - quite rough
546  
  cond = new O() {
547  
    bool get(L<S> tok, int i) {
548  
      S word = tok.get(i+3);
549  
      //print("single word: " + word);
550  
      ret !litlist("break", "continue", "return").contains(word);
551  
    }
552  
  };
553  
  for (S pre : litlist("}", ";"))
554  
    jreplace(tok, pre + " <id>;", "$1 $2();", cond);
555  
556  
  // shorter match syntax for answer methods
557  
  
558  
  jreplace(tok, "if <quoted> || <quoted>",
559  
    "if (matchOneOf(s, m, $2, $5))");
560  
  jreplace(tok, "if <quoted>", "if (matchStartX($2, s, m))",
561  
    new O() { bool get(L<S> tok, int i) {
562  
      ret unquote(tok.get(i+3)).endsWith("...");
563  
    }});
564  
  jreplace(tok, "if <quoted>", "if (match($2, s))",
565  
    new O() { bool get(L<S> tok, int i) {
566  
      ret !javaTokC(unquote(tok.get(i+3))).contains("*");
567  
    }});
568  
  jreplace(tok, "if <quoted>", "if (match($2, s, m))");
569  
  jreplace(tok, "if match <quoted>", "if (match($3, s, m))");
570  
571  
  // extra commas ("litlist(1, 2,)")
572  
  
573  
  jreplace(tok, ",)", ")");
574  
  
575  
  // additional translations (if necessary)
576  
  
577  
  replaceKeywordBlock(tok,
578  
    "pcall",
579  
    "try {",
580  
    "} catch (Throwable __e) { printStackTrace(__e); }");
581  
582  
  replaceKeywordBlock(tok,
583  
    "pcall-short",
584  
    "try {",
585  
    "} catch (Throwable __e) { print(exceptionToStringShort(__e)); }");
586  
587  
  replaceKeywordBlock(tok,
588  
    "pcall-messagebox",
589  
    "try {",
590  
    "} catch __e { messageBox(__e); }");
591  
592  
  tok = dialogHandler(tok);
593  
  
594  
  replaceKeywordBlock(tok, "exceptionToUser",
595  
    "try {",
596  
    "} catch (Throwable __e) { ret exceptionToUser(__e); }"); 
597  
598  
  if (hasCodeTokens(tok, "twice", "{"))
599  
    replaceKeywordBlock(tok, "twice",
600  
      "for (int __twice = 0; __twice < 2; __twice++) {",
601  
      "}"); 
602  
603  
  while ((i = findCodeTokens(tok, "repeat", "*", "{")) >= 0) {
604  
    S v = makeVar("repeat");
605  
    tok.set(i, "for (int " + v + " = 0; " + v + " < " + tok.get(i+2) + "; " + v + "++)");
606  
    tok.set(i+2, "");
607  
    tok = jtok(tok);
608  
  }
609  
610  
  replaceKeywordBlockDyn(tok,
611  
    "time",
612  
    new O() { S[] get() {
613  
      S var = makeVar("startTime");
614  
      ret new S[] {
615  
        "{ long " + var + " = sysNow(); try { ",
616  
        "} finally { " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); } }"};
617  
    }});
618  
  
619  
  replaceKeywordBlockDyn(tok,
620  
    "time2",
621  
    new O() { S[] get() {
622  
      S var = makeVar("startTime");
623  
      ret new S[] {
624  
        "long " + var + " = sysNow(); ",
625  
        " " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); "};
626  
    }});
627  
  
628  
  if (hasCodeTokens(tok, "assertFail", "{")) {
629  
    S var = makeVar("oops");
630  
    
631  
    replaceKeywordBlock(tok,
632  
      "assertFail",
633  
      "boolean " + var + " = false; try {",
634  
      "\n" + var + " = true; } catch (Exception e) { /* ok */ } assertFalse(" + var + ");"); 
635  
  }
636  
  
637  
  replaceKeywordBlock(tok,
638  
    "yo",
639  
    "try {",
640  
    "} catch (Exception " + makeVar("e") + ") { ret false; }");
641  
642  
  replaceKeywordBlock(tok,
643  
    "awtIfNecessary",
644  
    "swingNowOrLater(r " + "{",
645  
    "});");
646  
    
647  
  ctex(tok);
648  
    
649  
  replaceKeywordBlock(tok,
650  
    "actionListener",
651  
    "new java.awt.event.ActionListener() { " +
652  
      "public void actionPerformed(java.awt.event.ActionEvent _evt) {",
653  
    "}}");
654  
    
655  
  namedThreads(tok);
656  
  threads(tok);
657  
658  
  // try answer
659  
  while ((i = findCodeTokens(tok, "try", "answer")) >= 0) {
660  
    int j = findEndOfStatement(tok, i);
661  
    S v = makeVar("a");
662  
    tok.set(i, "{ S " + v);
663  
    tok.set(i+2, "=");
664  
    tok.set(j-1, "; if (!empty(" + v + ")) ret " + v + "; }");
665  
    tok = jtok(tok);
666  
  }
667  
668  
  // return optional (return if not null)
669  
  while ((i = jfind(tok, "return optional <id> =")) >= 0) {
670  
    int j = findEndOfStatement(tok, i);
671  
    S v = tok.get(i+4);
672  
    clearTokens(tok, i+2, i+4);
673  
    tok.set(i, "{");
674  
    tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
675  
    tok = jtok(tok);
676  
  }
677  
  
678  
  functionReferences(tok);
679  
680  
  // TODO: optimize
681  
  S moved = moveImportsUp2(join(tok));
682  
  if (moved != null)
683  
    tok = jtok(moved);
684  
    
685  
  ret tok;
686  
} // end of stdStuff!
687  
688  
static L<S> multilineStrings(L<S> tok) {
689  
  for (int i = 1; i < tok.size(); i += 2) {
690  
    S t = tok.get(i);
691  
    if (isQuoted(t))
692  
      if (t.startsWith("[") || t.contains("\r") || t.contains("\n"))
693  
        tok.set(i, quote(unquote(t)));
694  
  }
695  
  ret tok;
696  
}
697  
698  
static void inStringEvals(L<S> tok) {
699  
  bool change = false;
700  
  for (int i = 1; i < tok.size(); i += 2) {
701  
    S t = tok.get(i);
702  
    if (!isQuoted(t)) continue;
703  
    if (t.contains("\\*") && !t.contains("\\\\")) { // << rough
704  
      tok.set(i, inStringEval(t));
705  
      change = true;
706  
    }
707  
  }
708  
  if (change) reTok(tok);
709  
}
710  
711  
static S inStringEval(S t) {
712  
  t = dropPrefix("\"", dropSuffix("\"", t));
713  
  new L<S> l;
714  
  int idx;
715  
  while ((idx = t.indexOf("\\*")) >= 0) {
716  
    int j = indexOf(t, idx, "*/");
717  
    if (j < 0) break;
718  
    if (idx > 0)
719  
      l.add("\"" + substring(t, 0, idx) + "\"");
720  
    l.add("(" + trim(substring(t, idx+2, j)) + ")");
721  
    t = substring(t, j+2);
722  
  }
723  
  if (nempty(t))
724  
    l.add("\"" + t + "\"");
725  
  ret "(" + join(" + ", l) + ")";
726  
}
727  
728  
static L<S> quickmain(L<S> tok) {
729  
  bool change = false;
730  
  
731  
  int i = findCodeTokens(tok, "main", "{");
732  
  if (i < 0) i = findCodeTokens(tok, "m", "{");
733  
  if (i >= 0 && !(i-2 > 0 && tok.get(i-2).equals("class"))) {
734  
    tok.set(i, "public class main");
735  
    change = true;
736  
  }
737  
    
738  
  i = findCodeTokens(tok, "psvm", "{");
739  
  if (i < 0) i = findCodeTokens(tok, "p", "{");
740  
  if (i >= 0) {
741  
    int idx = i+2;
742  
    int j = findEndOfBracketPart(tok, idx);
743  
    L<S> contents = subList(tok, idx+1, j-1);
744  
    tok.set(i, "public static void main(final String[] args) throws Exception");
745  
    replaceTokens(tok, idx+1, j-1, tok_addSemicolon(contents));
746  
    change = true;
747  
  }
748  
    
749  
  ret change ? jtok(tok) : tok;
750  
}
751  
752  
static S makeVar(S name) {
753  
  ret "_" + name + "_" + varCount++;
754  
}
755  
756  
static S makeVar() { ret makeVar(""); }
757  
758  
/*static L<S> standardFunctions(L<S> tok) {
759  
  ret rtq(tok, "#1002474");
760  
}*/
761  
762  
static L<S> rtq(L<S> tok, S id) {
763  
  ret runTranslatorQuick(tok, id);
764  
}
765  
766  
static L<S> expandShortTypes(L<S> tok) {
767  
  // replace <int> with <Integer>
768  
  for (int i = 1; i+4 < tok.size(); i += 2)
769  
    if (tok.get(i).equals("<")
770  
      && litlist(">", ",").contains(tok.get(i+4))) {
771  
      String type = tok.get(i+2);
772  
      if (type.equals("int")) type = "Integer";
773  
      else if (type.equals("long")) type = "Long";
774  
      tok.set(i+2, type);
775  
    }
776  
    
777  
  // O = Object, S = String, ret = return
778  
  for (int i = 1; i < tok.size(); i += 2) {
779  
    String t = tok.get(i);
780  
    if (t.equals("O")) t = "Object";
781  
    if (t.equals("S")) t = "String";
782  
    else if (t.equals("L")) t = "List";
783  
    //else if (t.equals("F")) t = "Function";
784  
    else if (t.equals("ret")) t = "return";
785  
    else if (t.equals("bool") && i+2 < tok.size() && neq(tok.get(i+2), "(")) t = "boolean"; // bool -> boolean if it's not a function name
786  
    tok.set(i, t);
787  
  }
788  
  
789  
  ret tok;
790  
}
791  
792  
static L<S> autoImports(L<S> tok) {
793  
  S s = join(tok);
794  
  List<String> imports = findImports(s);
795  
  new StringBuilder buf;
796  
  for (String c : standardImports)
797  
    if (!(imports.contains(c)))
798  
      buf.append("import " + c + ";\n");
799  
  if (buf.length() == 0) ret tok;
800  
  ret jtok(buf+s);
801  
}
802  
803  
static String[] standardImports = {
804  
  "java.util.*",
805  
  "java.util.zip.*",
806  
  "java.util.List",
807  
  "java.util.regex.*",
808  
  "java.util.concurrent.*",
809  
  "java.util.concurrent.atomic.*",
810  
  "java.util.concurrent.locks.*",
811  
  "javax.swing.*",
812  
  "javax.swing.event.*",
813  
  "javax.swing.text.*",
814  
  "javax.swing.table.*",
815  
  "java.io.*",
816  
  "java.net.*",
817  
  "java.lang.reflect.*",
818  
  "java.lang.ref.*",
819  
  "java.lang.management.*",
820  
  "java.security.*",
821  
  "java.security.spec.*",
822  
  "java.awt.*",
823  
  "java.awt.event.*",
824  
  "java.awt.image.*",
825  
  "javax.imageio.*",
826  
  "java.math.*"
827  
};
828  
829  
static L<S> expandStarConstructors(L<S> tok) {
830  
  mainLoop: for (int i = 3; i+6 < tok.size(); i += 2) {
831  
    String t = tok.get(i), l = tok.get(i-2);
832  
    if (!t.equals("*"))
833  
      continue;
834  
    if (!tok.get(i+2).equals("("))
835  
      continue;
836  
    if (!eqOneOf(l, "}", "public", "private", "protected", ";", "{", "endif") && neq(get(tok, i-4), "ifclass")) // is this correct...??
837  
      continue;
838  
      
839  
    // ok, it seems like a constructor declaration.
840  
    // Now find class name by going backwards.
841  
    
842  
    int j = i, level = 1;
843  
    while (j > 0 && level > 0) {
844  
      t = tok.get(j);
845  
      if (t.equals("}")) ++level;
846  
      if (t.equals("{")) --level;
847  
      j -= 2;
848  
    }
849  
    
850  
    while (j > 0) {
851  
      t = tok.get(j);
852  
      if (t.equals("class")) {
853  
        String className = tok.get(j+2);
854  
        tok.set(i, className); // exchange constructor name!
855  
        
856  
        // now for the parameters.
857  
        // Syntax: *(Learner *learner) {
858  
        // We will surely add type inference here in time... :)
859  
        
860  
        j = i+2;
861  
        while (!tok.get(j).equals("{"))
862  
          j += 2;
863  
        int block = j+1;
864  
        for (int k = i+2; k < block-1; k += 2)
865  
          if (tok.get(k).equals("*")) {
866  
            tok.remove(k);
867  
            tok.remove(k);
868  
            block -= 2;
869  
            String name = tok.get(k);
870  
            tok.addAll(block, Arrays.asList(new String[] {
871  
              "\n  ", "this", "", ".", "", name, " ", "=", " ", name, "", ";" }));
872  
          }
873  
        
874  
        continue mainLoop;
875  
      }
876  
      j -= 2;
877  
    }
878  
  }
879  
  ret tok;
880  
}
881  
882  
static L<S> processIncludes(L<S> tok) {
883  
  int safety = 0;
884  
  while (hasCodeTokens(tok, "!", "include") && ++safety < 100)
885  
    tok = processIncludesSingle_2(tok);
886  
  
887  
  tok_autoCloseBrackets(tok);
888  
  ret tok;
889  
}
890  
891  
static L<S> processIncludesSingle(L<S> tok) {
892  
  S s = join(tok);
893  
  Matcher m = Pattern.compile("\n\\s*!include (#\\d+)").matcher(s);
894  
  if (!m.find()) ret tok;
895  
  StringBuffer buf = new StringBuffer();
896  
  do {
897  
    String includedSrc = loadSnippet(m.group(1));
898  
    m.appendReplacement(buf, m.quoteReplacement("\n" + includedSrc));
899  
  } while (m.find());
900  
  m.appendTail(buf);
901  
  ret jtok(str(buf));
902  
}
903  
904  
static L<S> processIncludesSingle_2(L<S> tok) {
905  
  int i;
906  
  while ((i = jfind(tok, "!include #<int>")) >= 0) {
907  
    S id = tok.get(i+6);
908  
    String includedSrc = loadSnippet(id);
909  
    clearTokens(tok, i, i+8);
910  
    tok.set(i, "\n" + includedSrc + "\n");
911  
    reTok(tok, i, i+8);
912  
  }
913  
  ret tok;
914  
}
915  
916  
static void ctex(L<S> tok) {
917  
  replaceKeywordBlock(tok, "ctex",
918  
    "{ try {",
919  
    "} catch (Exception __e) { throw rethrow(__e); } }");
920  
  replaceKeywordBlock(tok, "null on exception",
921  
    "{ try {",
922  
    "} catch (Throwable __e) { return null; } }");
923  
  replaceKeywordBlock(tok, "false on exception",
924  
    "{ try {",
925  
    "} catch (Throwable __e) { return false; } }");
926  
}
927  
  
928  
static L<S> dialogHandler(L<S> tok) {
929  
  ret replaceKeywordBlock(tok,
930  
    "dialogHandler",
931  
    "new DialogHandler() {\n" +
932  
      "public void run(final DialogIO io) {",
933  
    "}}");
934  
}
935  
936  
static void quicknew2(L<S> tok) {
937  
  jreplace(tok, "new <id> <id>;", "$2 $3 = new $2;");
938  
  jreplace(tok, "new <id><<id>> <id>;", "$2<$4> $6 = new $2;");
939  
  jreplace(tok, "new <id><<id>,<id>> <id>;", "$2<$4,$6> $8 = new $2;");
940  
  jreplace(tok, "new <id><<id><<id>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 = new $2;");
941  
  
942  
  jreplace(tok, "for args " + "{", "for (int i = 0; i < args.length; i++) { final String arg = args[i];");
943  
  
944  
  // Constructor calls without parentheses
945  
  // So you can say something like: predictors.add(new P1);
946  
  
947  
  jreplace1(tok, "new <id>", "new $2()", new O() {
948  
    bool get(L<S> tok, int i) {
949  
      ret eqOneOf(_get(tok, i+5), "{", ",", ")", ";", ":");
950  
    }
951  
  });
952  
  
953  
  jreplace(tok, "new " + "List(", "new ArrayList(");
954  
  jreplace(tok, "new " + "Map(", "new HashMap(");
955  
  jreplace(tok, "\\*<id>[<id>] <id>;", "$2[] $6 = new $2[$4];");
956  
}
957  
958  
// OLD
959  
static S quicknew(S s) {
960  
  s = s.replaceAll("new\\s+L<([\\w\\[\\]<>,\\s]+)>\\s+(\\w+);", "List<$1> $2 = new ArrayList<$1>();");
961  
  s = s.replaceAll("new\\s+List<([\\w\\[\\]<>,\\s]+)>\\s+(\\w+);", "List<$1> $2 = new ArrayList<$1>();");
962  
  s = s.replaceAll("new\\s+\\(Hash\\)Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new HashSet<$1>();");
963  
  s = s.replaceAll("new\\s+\\(Tree\\)Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new TreeSet<$1>();");
964  
  s = s.replaceAll("new\\s+Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new TreeSet<$1>();"); // TreeSet now default - pay attention to explicitly say HashSet if you need it.
965  
  s = s.replaceAll("new\\s+\\(Hash\\)Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new HashMap<$1>();");
966  
  s = s.replaceAll("new\\s+\\(Tree\\)Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();");
967  
  
968  
  // TreeMap when string as key
969  
  s = s.replaceAll("new\\s+Map<(S,[\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();");
970  
  s = s.replaceAll("new\\s+Map<(String,[\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();");
971  
  
972  
  // HashMap is default for everything else
973  
  s = s.replaceAll("new\\s+Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new HashMap<$1>();");
974  
  
975  
  s = s.replaceAll("new\\s+(\\w+<[\\w\\s,]+>)\\s+(\\w+);", "$1 $2 = new $1();");
976  
  
977  
  ret s;
978  
}
979  
980  
static L<S> extendClasses(L<S> tok) {
981  
  int i;
982  
  while ((i = jfind(tok, "extend <id> {")) >= 0) {
983  
    S className = tok.get(i+2);
984  
    int idx = findCodeTokens(tok, i, false, "{");
985  
    int j = findEndOfBracketPart(tok, idx+2);
986  
    S content = join(subList(tok, idx+1, j-1));
987  
    L<S> c = findInnerClassOfMain(tok, className);
988  
    print("Extending class " + className + " ==> " + join(c));
989  
    clearTokens(tok.subList(i, j+1));
990  
    if (c == null) {
991  
      print("Warning: Can't extend class " + className + ", not found");
992  
      continue;
993  
    }
994  
    int startOfClass = indexOfSubList(tok, c); // magicIndexOfSubList is broken
995  
    int endOfClass = startOfClass + l(c)-1;
996  
    print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass)));
997  
    while (neq(tok.get(endOfClass), "}")) --endOfClass;
998  
    print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass)));
999  
    tok.set(endOfClass, content + "\n" + tok.get(endOfClass));
1000  
    reTok(tok); // changed in 2 places, let's retok it all
1001  
  }
1002  
  ret tok;
1003  
}
1004  
1005  
static void listComprehensions(L<S> tok) {
1006  
  int i;
1007  
  for (S op : ll(":", "in"))
1008  
    while ((i = jfind(tok, "[<id> <id> " + op)) >= 0) {
1009  
      Map<Integer, Integer> bracketMap = getBracketMap(tok);
1010  
      S type = tok.get(i+2), id = tok.get(i+4);
1011  
      int j = scanOverExpression(tok, bracketMap, i+8, "|");
1012  
      S exp = join(tok.subList(i+8, j));
1013  
      j += 2;
1014  
      int k = scanOverExpression(tok, bracketMap, j, "]");
1015  
      S where = join(tok.subList(j, k));
1016  
      ++k;
1017  
      
1018  
      S code = "filter(" + exp + ", func(" + type + " " + id + ") { " + where + " })";
1019  
      replaceTokens(tok, i, k, code);
1020  
      reTok(tok, i, k);
1021  
    }
1022  
}
1023  
1024  
// lib 123 => !123
1025  
static void libs(L<S> tok) {
1026  
  new TreeSet<S> libs;
1027  
  int i;
1028  
  while ((i = jfind(tok, "lib <int>")) >= 0) {
1029  
    S id = tok.get(i+2);
1030  
    print("lib " + id);
1031  
    if (!libs.contains(id)) {
1032  
      libs.add(id);
1033  
      tok.set(i, "!");
1034  
      tok.set(i+1, "");
1035  
    } else {
1036  
      print("...ignoring (duplicate)");
1037  
      clearAllTokens(tok, i, i+3);
1038  
      reTok(tok, i, i+3);
1039  
    }
1040  
  }
1041  
}
1042  
1043  
// sourceCodeLine() => 1234
1044  
static void sourceCodeLine(L<S> tok) {
1045  
  int i ;
1046  
  while ((i = jfind(tok, "sourceCodeLine()")) >= 0) {
1047  
    replaceTokens(tok, i, i+5, str(countChar(join(subList(tok, 0, i)), '\n')+1));
1048  
    reTok(tok, i, i+5);
1049  
  }
1050  
}
1051  
1052  
// done before any other processing
1053  
static void earlyStuff(L<S> tok) {
1054  
  int i;
1055  
  
1056  
  // Note: this makes the word "quine" a special operator
1057  
  // (unusable as a function name)
1058  
  
1059  
  while ((i = jfind(tok, "quine(")) >= 0) {
1060  
    int idx = findCodeTokens(tok, i, false, "(");
1061  
    int j = findEndOfBracketPart(tok, idx+2);
1062  
    tok.set(i, "new Quine");
1063  
    tok.set(idx, "(" + quote(join(subList(tok, idx+1, j-1))) + ", ");
1064  
    reTok(tok, i, idx+1);
1065  
  }
1066  
}
1067  
1068  
static void throwFail(L<S> tok) {
1069  
  bool anyChange = false;
1070  
  for (int i = 1; i+2 < l(tok); i += 2)
1071  
    if (eq(get(tok, i+2), "fail") && !eqOneOf(get(tok, i), "throw", "RuntimeException", "return")) {
1072  
      tok.set(i+2, "throw fail");
1073  
      anyChange = true;
1074  
    }
1075  
  if (anyChange)
1076  
    reTok(tok);
1077  
}
1078  
1079  
static void namedThreads(L<S> tok) {
1080  
  for (int i = 0; i < 100; i++) {
1081  
    int idx = findCodeTokens(tok, "thread", "<quoted>", "{");
1082  
    if (idx < 0) idx = findCodeTokens(tok, "thread", "<id>", "{");
1083  
    if (idx < 0)
1084  
      break;
1085  
    int j = findEndOfBracketPart(tok, idx+4);
1086  
    S tName = tok.get(idx+2);
1087  
    
1088  
    S var = "_t_" + i;
1089  
    S pre = "{ /*nt*/ Thread " + var + " = new Thread(" + tName + ") {\n" +
1090  
      "public void run() { /* in run */ pcall { /* in thread */ \n";
1091  
    S post = "/* in thread */ } /* in run */ }\n};\n" +
1092  
      var + ".start(); }";
1093  
1094  
    tok.set(idx, pre);
1095  
    tok.set(idx+2, "");
1096  
    tok.set(idx+4, "");
1097  
    tok.set(j-1, post);
1098  
    //print(join(subList(tok, idx, j)));
1099  
    reTok(tok, idx, j);
1100  
  }
1101  
}
1102  
1103  
static void rNamedThread(L<S> tok) {
1104  
  for (int i = 0; i < 100; i++) {
1105  
    int idx = findCodeTokens(tok, "r", "-", "thread", "<quoted>", "{");
1106  
    if (idx < 0) idx = findCodeTokens(tok, "r", "-", "thread", "<id>", "{");
1107  
    if (idx < 0)
1108  
      break;
1109  
    int j = findEndOfBracketPart(tok, idx+8);
1110  
    S tName = tok.get(idx+6);
1111  
    
1112  
    S pre = "r { thread " + tName + " {";
1113  
    S post = "}}";
1114  
1115  
    replaceTokens(tok, idx, idx+9, pre);
1116  
    tok.set(j-1, post);
1117  
    reTok(tok, idx, j);
1118  
  }
1119  
}
1120  
1121  
static void threads(L<S> tok) {
1122  
  for (bool daemon : litlist(false, true))
1123  
    for (int i = 0; i < 100; i++) {
1124  
      int idx = findCodeTokens(tok, daemon ? "daemon" : "thread", "{");
1125  
      if (idx < 0)
1126  
        break;
1127  
      int j = findEndOfBracketPart(tok, idx+2);
1128  
1129  
      S var = "_t_" + i;
1130  
      S pre = "{ Thread " + var + " = new Thread() {\n" +
1131  
        "public void run() { pcall\n";
1132  
      S post = "} }\n};\n" +
1133  
        (daemon ? var + ".setDaemon(true);\n" : "") +
1134  
        var + ".start(); }";
1135  
1136  
      tok.set(idx, pre);
1137  
      tok.set(j-1, post);
1138  
      reTok(tok, idx, j);
1139  
    }
1140  
}
1141  
1142  
static Map<S, S> sf;
1143  
1144  
static L<S> standardFunctions(L<S> tok) {
1145  
  if (sf == null) {
1146  
    L<S> standardFunctions = concatLists(
1147  
      (L) loadVariableDefinition(cacheGet("#761"), "standardFunctions"),
1148  
      (L) loadVariableDefinition(cacheGet("#1006654"), "standardFunctions"));
1149  
1150  
    sf = new HashMap();
1151  
    for (String x : standardFunctions) {
1152  
      String[] f = x.split("/");
1153  
      sf.put(f[1], f[0]);
1154  
    }
1155  
  }
1156  
  
1157  
  for (int i = 0; ; i++) {
1158  
    Set<String> defd = new HashSet(findFunctions(tok));
1159  
1160  
    // changes tok
1161  
    Set<String> invocations = findFunctionInvocations(tok, sf);
1162  
1163  
    //print("Functions invoked: " + structure(invocations));
1164  
    List<String> needed = diff(invocations, defd);
1165  
    if (needed.isEmpty())
1166  
      break;
1167  
    print("Adding functions: " + join(" " , needed));
1168  
      
1169  
    new L<S> added;
1170  
    new StringBuilder buf;
1171  
    new L<S> preload;
1172  
    
1173  
    for (S x : needed)
1174  
      if (sf.containsKey(x))
1175  
        preload.add(sf.get(x));
1176  
    cachePreload(preload);
1177  
    
1178  
    for (String x : cloneList(needed)) {
1179  
      if (defd.contains(x)) continue;
1180  
      
1181  
      String id = sf.get(x);
1182  
      if (id == null) {
1183  
        print("Standard function " + x + " not found.");
1184  
        needed.remove(x);
1185  
        continue;
1186  
      }
1187  
      //print("Adding function: " + x + " (" + id + ")");
1188  
       
1189  
      S function = cacheGet(id);
1190  
      if (("\n" + function).contains("\n!")) print("Warning: " + id + " contains translators.");
1191  
      
1192  
      buf.append(function).append("\n");
1193  
      added.add(x);
1194  
      defd.addAll(findFunctionDefs(javaTok(function)));
1195  
    }
1196  
    S s = str(buf);
1197  
    if (stdstuffOnFunctions) s = stdstuff(s);
1198  
    tok = includeInMainLoaded(tok, s);
1199  
    if (verify_includes) assertTrue("main class", findMainClass(tok) != null);
1200  
    // defd = new HashSet(findFunctions(tok));
1201  
    //print("Functions added: " + structure(added));
1202  
    
1203  
    for (String x : needed)
1204  
      if (!defd.contains(x)) {
1205  
        print(join(tok));
1206  
        fail("Function not defined properly: " + x);
1207  
      }
1208  
    //print("Iteration " + (i+2));
1209  
    if (i >= 1000) fail("Too many iterations");
1210  
  }
1211  
  
1212  
  ret tok;
1213  
}
1214  
1215  
static L<S> findFunctions(L<S> tok) {
1216  
  //ret findFunctionDefinitions(join(findMainClass(tok)));
1217  
  ret findFunctionDefs(findMainClass(tok));
1218  
}
1219  
1220  
static S cacheGet(S snippetID) {
1221  
  snippetID = formatSnippetID(snippetID);
1222  
  S text = snippetCache.get(snippetID);
1223  
  if (text == null)
1224  
    snippetCache.put(snippetID, text = loadSnippet(snippetID));
1225  
  ret text;
1226  
}
1227  
1228  
static void cachePreload(L<S> ids) {
1229  
  new L<S> needed;
1230  
  for (S id : ids)
1231  
    if (!snippetCache.containsKey(formatSnippetID(id)))
1232  
      needed.add(formatSnippetID(id));
1233  
  if (l(needed) > 1) {
1234  
    L<S> texts = loadSnippets(needed);
1235  
    for (int i = 0; i < l(needed); i++)
1236  
      if (texts.get(i) != null)
1237  
        snippetCache.put(needed.get(i), texts.get(i));
1238  
  }
1239  
}
1240  
1241  
static L<S> jtok(L<S> tok) {
1242  
  ret jtok(join(tok));
1243  
}
1244  
1245  
static L<S> jtok(S s) {
1246  
  L<S> l = javaTok(s);
1247  
  ret useIndexedList ? new IndexedList2(l) : l;
1248  
}
1249  
1250  
// works on Java level (no "sclass" etc)
1251  
// returns list of classes we have (useful for other processing)
1252  
static Set<S> addStandardClasses(L<S> tok, S... data) {
1253  
  new HashSet<S> have;
1254  
  for (L<S> c : innerClassesOfMain(tok))
1255  
    have.add(getClassDeclarationName(c));
1256  
  have.addAll(tok_importedClassNames(tok));
1257  
  
1258  
  //L<S> idx = IndexedList2.ensureIndexed(tok);
1259  
  Set<S> idx = tokenIndexWithoutIfclass(tok);
1260  
  for (int i = 0; i+1 < l(data); i++) {
1261  
    S className = data[i], snippetID = data[i+1];
1262  
    if (idx.contains(className)
1263  
      && !have.contains(className)) {
1264  
      print("Adding class " + className + " / " + snippetID);
1265  
      snippetID = formatSnippetID(snippetID);
1266  
      S text = cacheGet(snippetID);
1267  
      includeInMainLoaded(tok, text);
1268  
      L<S> ct = javaTok(text);
1269  
      jreplace (ct, "sclass", "static class");
1270  
      jreplace (ct, "sinterface", "static interface");
1271  
      tok_autoCloseBrackets(ct);
1272  
      for (L<S> c : allClasses(ct))
1273  
        have.add(getClassDeclarationName(c));
1274  
      if (!have.contains(className))
1275  
        fail("Wrongly defined class: " + className + " / " + snippetID);
1276  
    }
1277  
  }
1278  
  
1279  
  ret have;
1280  
}
1281  
1282  
// magically append ".class" to class name references
1283  
static void expandClassReferences(L<S> tok, Set<S> classNames) {
1284  
  bool change = false;
1285  
  for (int i = 3; i+2 < l(tok); i += 2)
1286  
    if (classNames.contains(tok.get(i))) {
1287  
      S s = tok.get(i-2), t = tok.get(i+2);
1288  
      if (eqOneOf(s, "instanceof", "new", ".", "<", "implements", "throws", "extends", "/", "nu")) continue;
1289  
      if (isIdentifier(s)) continue; // XXX?
1290  
      if (eq(s, ",") && eqOneOf(_get(tok, i-6), "implements", "throws")) continue;
1291  
      // TODO: longer lists
1292  
      
1293  
      // check for cast
1294  
      if (eq(s, "(") && eq(t, ")") && i >= 5) {
1295  
        if (!eqOneOf(get(tok, i+4), "{", ";")) {
1296  
          S x = tok.get(i-4);
1297  
          if (!isIdentifier(x)) continue;
1298  
          if (eqOneOf(x, "ret", "return")) continue;
1299  
        }
1300  
      }
1301  
      if (eqOneOf(t, ",", ")", ";", ":")) {
1302  
        tok.set(i, tok.get(i) + ".class");
1303  
        change = true;
1304  
      }
1305  
    }
1306  
  if (change) reTok(tok);
1307  
}
1308  
1309  
// "<id>/<ClassName>" => "((ClassName) <id>)"
1310  
static void slashCasts(L<S> tok, final Set<S> classNames) {
1311  
  jreplace(tok, "<id>/<id>", "(($3) $1)", new O() {
1312  
    O get(L<S> tok, int i) {
1313  
      ret classNames.contains(tok.get(i+5));
1314  
    }
1315  
  });
1316  
}
1317  
1318  
static void processConceptsDot(L<S> tok) {
1319  
  bool change;
1320  
  do {
1321  
    change = false;
1322  
    for (int i : jfindAll(tok, "concepts."))
1323  
      if (contains(get(tok, i+3), "\n")) {
1324  
        replaceTokens(tok, i, i+3, "!" + "include #1004863 // Dynamic Concepts");
1325  
        reTok(tok, i, i+3);
1326  
        change = true;
1327  
        break;
1328  
      }
1329  
  } while (change);
1330  
}
1331  
1332  
static void addFieldOrder(L<S> tok, int i) {
1333  
  int idx = findCodeTokens(tok, i, false, "{");
1334  
  if (idx < 0) ret;
1335  
  int j = findEndOfBracketPart(tok, idx);
1336  
  L<S> vars = allVarNames(subList(tok, idx+1, j-1));
1337  
  print("addFieldOrder " + struct(vars));
1338  
  if (!vars.contains("_fieldOrder")
1339  
    && !isSortedList(vars)) {
1340  
    print("Adding field order");
1341  
    tok.set(idx+2, "static String _fieldOrder = " + quote(join(" ", vars)) + ";\n  " + tok.get(idx+2));
1342  
    // reTok has to be done by caller
1343  
  }
1344  
}
1345  
1346  
static void caseAsVariableName(L<S> tok) {
1347  
  if (!tok.contains("case")) ret;
1348  
  for (int i = 1; i+2 < l(tok); i += 2) {
1349  
    S t = tok.get(i+2);
1350  
    if (tok.get(i).equals("case")
1351  
      && !(t.startsWith("'") || isInteger(t) || isIdentifier(t)))
1352  
      tok.set(i, "_case");
1353  
  }
1354  
}
1355  
1356  
static void continueAsFunctionName(L<S> tok) {
1357  
  jreplace(tok, "continue(", "_continue(");
1358  
}
1359  
1360  
// func bla => "bla" - and "please include function bla."
1361  
static void functionReferences(L<S> tok) {
1362  
  int i;
1363  
  for (S keyword : ll("f", "func"))
1364  
    while ((i = jfind(tok, keyword + " <id>", new O() {
1365  
      O get(L<S> tok, int i) {
1366  
        ret !eq(tok.get(i+3), "instanceof");
1367  
      }
1368  
    })) >= 0) {
1369  
      S f = tok.get(i+2);
1370  
      clearTokens(tok, i, i+2);
1371  
      tok.set(i+2, quote(f));
1372  
      reTok(tok, i, i+2);
1373  
      tok.set(l(tok)-1, last(tok) + "\nplease include function " + f + ".");
1374  
      reTok(tok, l(tok)-1, l(tok));
1375  
    }
1376  
}
1377  
1378  
// # 123 => "#123"
1379  
static void directSnippetRefs(L<S> tok) {
1380  
  int i;
1381  
  while ((i = jfind(tok, "#<int>", new O() {
1382  
    bool get(L<S> tok, int i) {
1383  
      ret neq(_get(tok, i-1), "include");
1384  
    }
1385  
  })) >= 0) {
1386  
    S id = tok.get(i+2);
1387  
    clearTokens(tok, i+1, i+3);
1388  
    tok.set(i, quote("#" + id));
1389  
    reTok(tok, i, i+3);
1390  
  }
1391  
}
1392  
1393  
static void quicknu(L<S> tok) {
1394  
  jreplace(tok, "nu <id>(", "nu($2.class, ");
1395  
  jreplace(tok, "nu <id>", "new $2");
1396  
}
1397  
1398  
// fill variable innerClasses_list
1399  
static void innerClassesVar(L<S> tok) {
1400  
  if (!tok.contains("myInnerClasses_list")) ret;
1401  
  
1402  
  L<S> have = classDeclarationNames(innerClassesOfMain(tok));
1403  
  int i = jfind(tok, ">myInnerClasses_list;");
1404  
  if (i < 0) ret;
1405  
  tok.set(i+4, "=litlist(\n" + joinQuoted(", ", have) + ");");
1406  
  reTok(tok, i+4, i+5);
1407  
}
1408  
1409  
// process ifclass x ... endif blocks
1410  
static void tok_ifclass(L<S> tok) {
1411  
  if (!tok.contains("ifclass")) ret;
1412  
  
1413  
  L<S> have = classDeclarationNames(innerClassesOfMain(tok));
1414  
  int i;
1415  
  while ((i = rjfind(tok, "ifclass <id>")) >= 0) {
1416  
    int j = jfind(tok, i+4, "endif");
1417  
    if (j < 0) j = l(tok)-1;
1418  
    bool has = have.contains(tok.get(i+2));
1419  
    clearTokens(tok, i, i+3);
1420  
    clearTokens(tok, j, j+1);
1421  
    if (!has) clearTokens(tok, i+3, j);
1422  
    reTok(tok, i, j+1);
1423  
  }
1424  
}
1425  
1426  
svoid conceptDeclarations(L<S> tok) {
1427  
  for (S kw : ll("concept", "sconcept")) {
1428  
    O cond = new O() {
1429  
      O get(L<S> tok, int i) {
1430  
        addFieldOrder(tok, i+1);
1431  
        ret true;
1432  
      }
1433  
    };
1434  
    bool re = false;
1435  
    if (jreplace(tok, kw + " <id> {", "static class $2 extends Concept {", cond)) re = true;
1436  
    if (jreplace(tok, kw + " <id> implements", "static class $2 extends Concept implements", cond)) re = true;
1437  
    if (jreplace(tok, kw + " <id>", "static class $2", cond)) re = true;
1438  
    if (re) reTok(tok);
1439  
  }
1440  
}

Author comment

Began life as a copy of #759

download  show line numbers  debug dex  old transpilations   

Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1007595
Snippet name: "Super-Edgy" JavaX Translator (Extension of #752) [dev., broken]
Eternal ID of this version: #1007595/1
Text MD5: bb756d593c96c2cbfb8abbefa8c46dd9
Author: stefan
Category: javax
Type: JavaX translator
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-03-27 18:17:13
Source code size: 45565 bytes / 1440 lines
Pitched / IR pitched: No / No
Views / Downloads: 526 / 509
Referenced in: [show references]