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

1784
LINES

< > BotCompany Repo | #1010084 // Speeding up "Super-Edgy" JavaX Translator (Extension of #7)

JavaX translator [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (13351L/95K/281K).

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

Author comment

Began life as a copy of #759

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1010084
Snippet name: Speeding up "Super-Edgy" JavaX Translator (Extension of #7)
Eternal ID of this version: #1010084/7
Text MD5: 15dee8b399a6f2002fcc6960171b8864
Transpilation MD5: 0ecfbb85e0ff4588bb890ea58a8d9a5f
Author: stefan
Category: javax
Type: JavaX translator
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-09-02 03:43:40
Source code size: 58019 bytes / 1784 lines
Pitched / IR pitched: No / No
Views / Downloads: 347 / 426
Version history: 6 change(s)
Referenced in: [show references]