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

2837
LINES

< > BotCompany Repo | #1026023 // #759 backup with reTok_multi in tok_conditionals (seems slower?)

JavaX source code (desktop) - run with: x30.jar

Download Jar.

1  
!1006722
2  
3  
// new JavaParser includes
4  
!include once #1025814
5  
!include once #1025813
6  
7  
!include once #1025802 // optimized findCodeTokens
8  
9  
set flag AllowMetaCode.
10  
11  
//set flag tok_forUnnull_debug.
12  
13  
// ifdef in cached includes? => i think cached includes still contain the ifdefs, so it's fine. tok_ifdef is not called within localStuff1
14  
15  
set flag noAI.
16  
set flag isQuoted_dirty. // should be OK, we're dealing with tokens
17  
18  
static bool autoQuine = true;
19  
static int maxQuineLength = 80;
20  
sbool assumeTriple = true;
21  
sbool quickInstanceOfEnabled; // interferes with things
22  
23  
// _registerThread usually costs nothing because we need
24  
// the registerWeakHashMap mechanism anyway for ping().
25  
// Anyway - no forced functions for now :)
26  
static L<S> functionsToAlwaysInclude = ll(
27  
  //"_registerThread",
28  
  //"asRuntimeException"
29  
);
30  
31  
// classes with two type parameters that can written with just one
32  
// e.g. Pair<S> => Pair<S, S>
33  
static Set<S> pairClasses = lithashset("Pair", "Either", "Map", "AbstractMap", "HashMap", "TreeMap", "LinkedHashMap", "MultiMap", "CompactHashMap", "WrappedMap", "F1", "IF1", "AllOnAll", "AllOnAllWithUpdates");
34  
35  
sS transpilingSnippetID;
36  
//static new AtomicInteger varCount;
37  
static new ThreadLocal<AtomicInteger> varCountByThread;
38  
static Map<S, S> snippetCache = syncMap();
39  
sbool useIndexedList2 = false, useTokenIndexedList = true;
40  
sbool opt_javaTok = true;
41  
static bool cacheStdFunctions = true, cacheStdClasses = true;
42  
static new HashMap<Long, CachedInclude> cachedIncludes;
43  
static ExecutorService executor;
44  
static L lclasses;
45  
static long startTime, lastPrint;
46  
47  
// These variables have to be cleared manually for each transpilation
48  
49  
static new HashSet<Long> included;
50  
static Set<S> definitions = ciSet();
51  
static new HashMap<S> rewrites;
52  
static new HashSet<S> shouldNotIncludeFunction;
53  
static new HashSet<S> shouldNotIncludeClass;
54  
static new HashSet<S> doNotIncludeFunction;
55  
static new HashSet<S> addedFunctions;
56  
static new HashSet<S> addedClasses;
57  
static new HashSet<S> hardFunctionReferences;
58  
static new HashSet<S> mapLikeFunctions;
59  
static new HashSet<S> lambdaMapLikeFunctions;
60  
static new HashSet<S> mapMethodLikeFunctions;
61  
static new HashSet<S> nuLikeFunctions;
62  
static SS extraStandardFunctions;
63  
sbool quickmainDone1, quickmainDone2;
64  
static new TreeSet<S> libs;
65  
sS mainBaseClass, mainPackage, mainClassName;
66  
sbool localStuffOnly; // for transpiling a fragment
67  
sbool asInclude; // for transpiling an include (auto-close scopes)
68  
sbool allowMetaCode = false; // run any embedded meta code
69  
static LS metaPostBlocks, metaTransformers;
70  
sbool dontPrintSource;
71  
sbool dontLoadCachedIncludesFromVM; // for benchmarking
72  
73  
sclass CachedInclude {
74  
  S javax;
75  
  Future<S> java;
76  
  S realJava;
77  
  long snippetID;
78  
  
79  
  *() {}
80  
  *(long *snippetID) {}
81  
  
82  
  S java() {
83  
    ret realJava != null ? realJava : getFuture(java);
84  
  }
85  
  
86  
  Future<S> javaFuture() {
87  
    ret realJava != null ? nowFuture(realJava) : java;
88  
  }
89  
  
90  
  void clean {
91  
    if (java != null) {
92  
      realJava = getFuture(java);
93  
      java = null;
94  
    }
95  
  }
96  
}
97  
98  
p {
99  
  startTime = lastPrint = sysNow();
100  
  pcall {
101  
    if (!dontLoadCachedIncludesFromVM)
102  
      vmKeepWithProgramMD5_get('cachedIncludes);
103  
  }
104  
  executor = Executors.newFixedThreadPool(numberOfCores());
105  
  transpilingSnippetID = or(getThreadLocal((ThreadLocal<S>) getOpt(javax(), 'transpilingSnippetID)), transpilingSnippetID);
106  
  print(+transpilingSnippetID);
107  
  set transpileRaw_dontCopyFromCreator;
108  
  
109  
  fO oldPrint = or(print_byThread()!, f print_raw);
110  
  temp tempInterceptPrint(new F1<S, Bool>() {
111  
    Bool get(S s) {
112  
      long now = sysNow();
113  
      long time = now-lastPrint; // -startTime;
114  
      lastPrint = now;
115  
      callF(oldPrint, "[" + formatInt(time/1000, 2) + ":" + formatInt(time % 1000, 3) + "] " + s);
116  
      false;
117  
    }
118  
  });
119  
  
120  
  try {
121  
    _main();
122  
  } finally {
123  
    interceptPrintInThisThread(oldPrint);
124  
    if (executor != null) executor.shutdown();
125  
    executor = null;
126  
    localStuffOnly = false;
127  
    asInclude = false;
128  
  }
129  
}
130  
131  
svoid _main() ctex {
132  
  if (sameSnippetID(programID(), defaultJavaXTranslatorID())) setDefaultJavaXTranslatorID(#7);
133  
  
134  
  //reTok_modify_check = true;
135  
  //if (useIndexedList) findCodeTokens_debug = true;
136  
  javaTok_opt = opt_javaTok;
137  
  //findCodeTokens_indexed = findCodeTokens_unindexed = 0;
138  
  findCodeTokens_bails = findCodeTokens_nonbails = 0;
139  
  javaTok_n = javaTok_elements = 0;
140  
  S in = loadMainJava();
141  
  
142  
  print("759 STARTING " + identityHashCode(main.class));
143  
  included.clear();
144  
  definitions.clear();
145  
  rewrites.clear();
146  
  definitions.add("SymbolAsString");
147  
  shouldNotIncludeFunction.clear();
148  
  shouldNotIncludeClass.clear();
149  
  doNotIncludeFunction.clear();
150  
  addedFunctions.clear();
151  
  addedClasses.clear();
152  
  hardFunctionReferences.clear();
153  
  mapLikeFunctions = cloneHashSet(tok_mapLikeFunctions());
154  
  lambdaMapLikeFunctions = new HashSet;
155  
  mapMethodLikeFunctions = cloneHashSet(tok_mapMethodLikeFunctions());
156  
  nuLikeFunctions.clear();
157  
  extraStandardFunctions = new HashMap;
158  
  libs.clear();
159  
  mainBaseClass = mainPackage = mainClassName = null;
160  
  varCountByThread.set(null);
161  
  quickmainDone1 = quickmainDone2 = false;
162  
  metaPostBlocks = new L;
163  
  metaTransformers = new L;
164  
  dontPrintSource = false;
165  
  
166  
  //L ts = findTranslators(toLines(join(tok)));
167  
  //print("Translators in source at start: " + structure(ts));
168  
  
169  
  L<S> tok = jtok(in);
170  
  
171  
  try {
172  
    tok_definitions(tok);
173  
    
174  
    // add m { }
175  
    
176  
    if (!localStuffOnly && !hasCodeTokens(tok, "m", "{") && !hasCodeTokens(tok, "main", "{") && !hasCodeTokens(tok, "class", "main")) {
177  
      //tok = jtok(moveImportsUp("m {\n" + in + "\n}"));
178  
      if (l(tok) == 1) tok = singlePlusList(first(tok), dropFirst(javaTok("m {}")));
179  
      else {
180  
        replaceTokens_reTok(tok, 1, 2, "m {\n\n" + unnull(get(tok, 1)));
181  
        replaceTokens_reTok(tok, l(tok)-2, l(tok)-1, unnull(get(tok, l(tok)-2)) + "}");
182  
      }
183  
      tok_moveImportsUp(tok);
184  
    }
185  
    
186  
    // standard translate
187  
    
188  
    //ts = findTranslators(toLines(join(tok)));
189  
    //print("Translators in source: " + structure(ts));
190  
    
191  
    if (tok_hasTranslators(tok))
192  
      tok = jtok(defaultTranslate(join(tok)));
193  
    
194  
    //print("end of default translate");
195  
    //print(join(tok));
196  
  
197  
    //tok_autoCloseBrackets(tok);    
198  
    
199  
    tok_metaTransformNow(tok);
200  
    
201  
    tok_processEarlyIncludes(tok);
202  
      
203  
    tok_earlyGeneralStuff(tok);
204  
    
205  
    tok = tok_processIncludes(tok); // before standard functions
206  
    if (processConceptsDot(tok))
207  
      tok = tok_processIncludes(tok);
208  
    tok = localStuff1(tok);
209  
    
210  
   if (!localStuffOnly) {
211  
    int safety = 0;
212  
    boolean same;
213  
    do { // BIG LOOP
214  
      LS before = cloneList(tok);
215  
      
216  
      // do the non-local stuff (flags and rewrites, things that correlate across includes like tok_selfType)
217  
      tok_selfType(tok);
218  
      tok_mainClassNameAndPackage(tok);
219  
      tok_definitions(tok);
220  
      tok_ifndef(tok);
221  
      tok_ifdef(tok);
222  
      defineMapLikes(tok);
223  
      defineLambdaMapLikes(tok);
224  
      if (tok_applyMapLikeFunctions(tok, mapLikeFunctions))
225  
        functionReferences(tok);
226  
      if (tok_applyLambdaMapLikeFunctions(tok, lambdaMapLikeFunctions))
227  
        lambdaReferences(tok);
228  
      defineMapMethodLikes(tok);
229  
      tok_applyMapMethodLikeFunctions(tok, mapMethodLikeFunctions);
230  
      defineNuLikes(tok);
231  
      tok_applyNuLikeFunctions(tok, nuLikeFunctions);
232  
      tok_dropExtraCommas(tok); // from e.g. tok_applyMapMethodLikeFunctions
233  
      tok_delegateTo(tok);
234  
      tok_replaceWith(tok);
235  
      tok_findRewrites(tok);
236  
      tok_processRewrites(tok);
237  
      
238  
      // main bla(...) => mainClassName.bla(...)
239  
      jreplace(tok, "main <id>(", or(mainClassName, "main") + ".$2(");
240  
      
241  
      try {
242  
        if (safety == 0) tok = quickmain(tok);
243  
      } catch e {
244  
        printSources(tok);
245  
        rethrow(e);
246  
      }
247  
      tok_collectMetaPostBlocks(tok, metaPostBlocks);
248  
      tok_collectTransformers(tok, metaTransformers);
249  
      tok_metaTransformNow(tok);
250  
      
251  
      // Hack to allow DynModule to reimplement _registerThread
252  
      /*if (tok.contains("DynModule") && !addedClasses.contains("DynModule"))
253  
        addStandardClasses_v2(tok);*/
254  
      
255  
      defineExtraSF(tok);
256  
      tok = standardFunctions(tok);
257  
      tok = stdstuff(tok); // all the keywords, standard
258  
      S diff;
259  
      long startTime = now();
260  
      //diff = unidiff(before, join(tok));
261  
      //print("unidiff: " + (now()-startTime) + " ms");
262  
      //same = eq(diff, "");
263  
      same = eq(tok, before);
264  
      if (!same) {
265  
        print("Not same " + safety + ".");
266  
        //print(indent(2, diff));
267  
      }
268  
      if (safety++ >= 10) {
269  
        //print(unidiff(before, join(tok)));
270  
        printSources(tok);
271  
        fail("safety 10 error!");
272  
      }
273  
    } while (!same); // END OF BIG LOOP
274  
    
275  
    print("Post.");
276  
    
277  
    if (mainBaseClass != null) {
278  
      jreplace1(tok, "class main", "class main extends " + mainBaseClass);
279  
      mainBaseClass = null;
280  
    }
281  
    
282  
    print('moveImportsUp); tok_moveImportsUp(tok);
283  
    
284  
    print('Indexing); tok = indexTokenList(tok);
285  
    
286  
    // POST-PROCESSING after stdstuff loop
287  
    
288  
    if (transpilingSnippetID != null)
289  
      jreplace_dyn(tok, "class whatever", 
290  
        func(L<S> tok, int cIndex) -> S {
291  
          pcall { ret "class " + stringToLegalIdentifier(getSnippetTitle(transpilingSnippetID)); }
292  
          ret "class Whatever";
293  
        });
294  
    
295  
    //print("Type<A, A>"); // Type<A> to Type<A, A>
296  
    
297  
    print('extendClasses); tok = extendClasses(tok);
298  
    print('libs); libs(tok);
299  
    print('sourceCodeLine); sourceCodeLine(tok);
300  
    
301  
    tok_overridableFunctionDefs(tok, null);
302  
    
303  
    // escaping for lambdas
304  
    //jreplace(tok, "-=>", "->");
305  
  
306  
    // Stuff that depends on the list of inner classes (haveClasses)
307  
    HashSet<S> haveClasses = haveClasses_actual(tok);
308  
    print('innerClassesVar); innerClassesVar(tok, haveClasses);
309  
    fillVar_transpilationDate(tok);
310  
    haveClasses_addImported(tok, haveClasses);
311  
    print('ifclass); tok_ifclass(tok, haveClasses);
312  
    print('slashCasts); slashCasts(tok, haveClasses);
313  
    print('newWithoutNew); newWithoutNew(tok, haveClasses);
314  
    
315  
    if (!assumeTriple) {
316  
      print('Triple);
317  
      if (tok.contains("Triple") && !haveClasses.contains("Triple")) {
318  
        jreplace(tok, "Triple", "T3");
319  
        haveClasses.remove("Triple");
320  
        haveClasses.add("T3");
321  
        slashCasts(tok, lithashset("T3"));
322  
        tok_quickInstanceOf(tok, lithashset("T3"));
323  
      }
324  
      expandTriple(tok);
325  
    }
326  
    
327  
    if (hasDef("SymbolAsString"))
328  
      jreplace(tok, "Symbol", "String");
329  
  
330  
    print('classReferences); expandClassReferences_lazy(tok, haveClasses);
331  
    
332  
    if (metaCodeAllowed()) runMetaPostBlocks(tok);
333  
334  
    // Error-checking
335  
    print("Error-checking"); 
336  
    Set<S> functions = new HashSet(findFunctions(tok));
337  
    for (S f : hardFunctionReferences)
338  
      if (!functions.contains(f))
339  
        fail("Function " + f + " requested, but not supplied");
340  
  
341  
    print('autoImports); tok = autoImports(tok); // faster to do it at the end
342  
    
343  
    print("definitions=" + sfu(definitions));
344  
    if (containsOneOfIC(definitions, "allpublic", "reparse", "PublicExceptTopClass")) {
345  
      // Fire up the Java parser & pretty printer!
346  
      print(containsIC(definitions, "allpublic")? "Making all public." : "Reparsing.");
347  
      //try {
348  
        S src = join(tok);
349  
        try {
350  
          if (containsIC(definitions, "PublicExceptTopClass"))
351  
            src = javaParser_makeAllPublic(src, notTopLevelClassDecl := true);
352  
          else if (containsIC(definitions, "keepComments"))
353  
            src = javaParser_makeAllPublic_keepComments(src);
354  
          else if (containsIC(definitions, "allpublic"))
355  
            src = javaParser_makeAllPublic(src);
356  
          else
357  
            src = javaParser_reparse_keepComments(src);
358  
        } catch e {
359  
          extractAndPrintJavaParseError(src, e);
360  
          File f = javaxCachesDir("error-source.java");
361  
          saveTextFileVerbose(f, src);
362  
          dontPrintSource = true;
363  
          throw e;
364  
        }
365  
        tok = jtok(src);
366  
      /*} catch e {
367  
        S src = join(tok);
368  
        if (!dontPrintSource)
369  
          print(src);
370  
        print(f2s(saveProgramTextFile("error.java", src)));
371  
        throw rethrow(e);
372  
      }*/
373  
    }
374  
    
375  
    // Do this after JavaParser (because it doesn't like package after class)
376  
    
377  
    if (mainPackage != null) {
378  
      print('mainPackage);
379  
      tokPrepend(tok, 1, "package " + mainPackage + ";\n");
380  
      reTok(tok, 1, 2);
381  
    }
382  
    
383  
    if (mainClassName != null) {
384  
      print('mainClassName);
385  
      jreplace(tok, "class main", "class " + mainClassName);
386  
      jreplace(tok, "main.class", mainClassName + ".class");
387  
      //tokPrepend(tok, 1, "class main {}\n"); // so main.class is generated and compiler sanity checks succeed. we can later skip it in the JavaXClassLoader
388  
    }
389  
    
390  
    if (nempty(libs)) {
391  
      print("Adding libs: " + libs);
392  
      tok.add(concatMap_strings(func(S s) -> S { "\n!" + s }, libs));
393  
    }
394  
   } // if (!localStuffOnly)
395  
  } catch e {
396  
    S src = join(tok);
397  
    if (!dontPrintSource)
398  
      print(src);
399  
    print(f2s(saveProgramTextFile("error.java", src)));
400  
    throw rethrow(e);
401  
  }
402  
  
403  
  /*if (useIndexedList)
404  
    print("Indexed/unindexed lookups: " + findCodeTokens_indexed + "/" + findCodeTokens_unindexed + ", lists made: " + IndexedList2.instances);
405  
  print("findCodeToken bails: " + findCodeTokens_bails + "/" + findCodeTokens_nonbails);
406  
  print("javaToks: " + javaTok_n + "/" + javaTok_elements);*/
407  
  
408  
  print("Saving.");
409  
  
410  
  // for dexcompile.php
411  
  if (mainClassName != null)
412  
    tokPrepend(tok, 0, "//FILENAME: " 
413  
      + (mainPackage != null ? mainPackage.replace(".", "/") + "/" : "") + mainClassName + ".java\n");
414  
    
415  
  if (mainJava != null)
416  
    mainJava = join(tok);
417  
  else if (tok.contains("package"))
418  
    splitJavaFiles(tok);
419  
  else
420  
    saveMainJava(tok);
421  
}
422  
423  
static L<S> localStuff1(L<S> tok) {
424  
  int safety = 0, i;
425  
  boolean same;
426  
  tok = indexTokenList(tok);
427  
  
428  
  tok_scopes(tok, autoCloseScopes := true);
429  
    
430  
  do {
431  
    LS before = cloneList(tok);
432  
    
433  
    //print("localStuff loop " + safety);
434  
    
435  
    earlyStuff(tok);
436  
    
437  
    // EARLY local stuff goes here
438  
    
439  
    tok_earlyGeneralStuff(tok);
440  
    
441  
    conceptDeclarations(tok);
442  
    tok_recordDecls(tok);
443  
  
444  
    tok = multilineStrings(tok);
445  
    tok_singleQuoteIdentifiersToStringConstants(tok);
446  
    inStringEvals(tok);
447  
    tok_listComprehensions(tok);
448  
    
449  
    tok_for_single(tok);
450  
    
451  
    tok_for_unpair(tok); // Do this...
452  
    tok_doubleFor_v2(tok); // ...before this
453  
    
454  
    tok_forUnnull(tok);
455  
    tok_ifCast(tok);
456  
    forPing(tok);
457  
    tok_directSnippetRefs(tok);
458  
    quicknu(tok);
459  
    //tok_juxtaposeCalls(tok);
460  
    
461  
    jreplace(tok, "LLS", "L<LS>");
462  
    jreplace(tok, "LS", "L<S>");
463  
    jreplace(tok, "ES", "Ext<S>");
464  
    jreplace(tok, "ExtS", "Ext<S>");
465  
    
466  
    jreplace(tok, "dispose <id>;", "{ cleanUp($2); $2 = null; }");
467  
  
468  
    jreplace(tok, "do ping {", "do { ping();");
469  
    
470  
    replaceKeywordBlock(tok,
471  
      "swing",
472  
      "{ swing(r {",
473  
      "}); }");
474  
      
475  
    replaceKeywordBlock(tok,
476  
      "androidUI",
477  
      "{ androidUI(r {",
478  
      "}); }");
479  
      
480  
    replaceKeywordBlock(tok,
481  
      "withDBLock",
482  
      "{ withDBLock(r {",
483  
      "}); }");
484  
      
485  
    replaceKeywordBlock(tok, "afterwards", "temp tempAfterwards(r {", "});");
486  
      
487  
    for (S keyword : ll("tokcondition", "tokCondition"))
488  
      replaceKeywordBlock(tok,
489  
        keyword,
490  
        "new TokCondition { bool get(final L<S> tok, final int i) {",
491  
        "}}");
492  
      
493  
    jreplace(tok, "synced <id>", "synchronized $2");
494  
    jreplace(tok, "sync <id>", "synchronized $2");
495  
    
496  
    replaceKeywordBlock(tok, "answer",
497  
      "static S answer(S s) {\nfinal new Matches m;\n",
498  
      "\nret null;\n}");
499  
      
500  
    replaceKeywordBlock(tok, "static-pcall",
501  
      "static { pcall {",
502  
      "}}");
503  
      
504  
    replaceKeywordBlock(tok, "loading",
505  
      "{ temp tempShowLoadingAnimation(); ",
506  
      "}");
507  
  
508  
    replaceKeywordPlusQuotedBlock(tok, "loading",
509  
      new O { S[] get(L<S> tok, int i) {
510  
        S text = tok.get(i+2);
511  
        ret new S[] {
512  
          "{ temp tempShowLoadingAnimation(" + text + "); ",
513  
          "}" };
514  
      }});
515  
      
516  
    while ((i = jfind(tok, "visualize as")) >= 0) {
517  
      int j = tok_findEndOfStatement(tok, i); // expression, rather
518  
      tok.set(i+2, "{ ret");
519  
      tok.set(j-1, "; }");
520  
      reTok(tok, i, j);
521  
    }
522  
      
523  
    jreplace(tok, "visualize {", "public JComponent visualize() {", tokCondition_beginningOfMethodDeclaration());
524  
  
525  
    jreplace(tok, "visualize2 {", "JComponent visualize2() {", tokCondition_beginningOfMethodDeclaration());
526  
    
527  
    replaceKeywordBlock(tok, "start-thread-printDone", "start-thread {", "printDone(); }");
528  
529  
    replaceKeywordBlock(tok, "start-thread", [[start { thread "Start" { temp enter(); pcall {]], "}}}");
530  
    
531  
    jreplace(tok, "start {", "void start() { super.start();", tokCondition_beginningOfMethodDeclaration());
532  
    
533  
    // run { ... } => public void run() { ... }
534  
    jreplace(tok, "run {", "public void run() {", tokcondition {
535  
      ret neqGet(tok, i-1, "void");
536  
    });
537  
538  
    replaceKeywordBlock(tok, "html",
539  
      "static O html(S uri, fMap<S, S> params) ctex " + "{\n", "}");
540  
    
541  
    replaceKeywordBlock(tok, "afterVisualize",
542  
      "visualize { JComponent _c = super.visualize();",
543  
      "ret _c; }");
544  
    
545  
    replaceKeywordBlock(tok, "enhanceFrame",
546  
      "void enhanceFrame(Container f) { super.enhanceFrame(f);",
547  
      "}");
548  
    
549  
    if (assumeTriple) {
550  
      jreplace(tok, "Triple", "T3");
551  
      expandTriple(tok);
552  
    }
553  
    
554  
    tok_shortFinals(tok);
555  
    
556  
    tok_moduleClassDecls(tok);
557  
558  
    jreplace(tok, "static sync", "static synchronized");
559  
    jreplace(tok, "sclass", "static class");
560  
    jreplace(tok, "srecord", "static record");
561  
    jreplace(tok, "record noeq", "noeq record");
562  
    jreplace(tok, "asclass", "abstract static class");
563  
    jreplace(tok, "sinterface", "static interface");
564  
    jreplace(tok, "ssynchronized", "static synchronized");
565  
  
566  
    jreplace(tok, "ssvoid", "static synchronized void");
567  
    jreplace(tok, "sbool", "static bool");
568  
    jreplace(tok, "fbool", "final bool");
569  
    jreplace(tok, "sint", "static int");
570  
    jreplace(tok, "snew", "static new");
571  
    jreplace(tok, "sv <id>", "static void $2");
572  
    jreplace(tok, "pvoid", "public void");
573  
  
574  
    // "sS" => static S
575  
    jreplace(tok, "sS", "static S");
576  
  
577  
    // "sO" => static O
578  
    jreplace(tok, "sO", "static O");
579  
  
580  
    // "sL" => static L
581  
    jreplace(tok, "sL", "static L");
582  
  
583  
    // "toString {" => "public S toString() {"
584  
    jreplace(tok, "toString {", "public S toString() {");
585  
    
586  
    jreplace(tok, "Int", "Integer");
587  
    jreplace(tok, "Bool", "Boolean");
588  
    jreplace(tok, "BigInt", "BigInteger");
589  
    jreplace(tok, "Char", "Character");
590  
    
591  
    jreplace(tok, "Sym", "Symbol");
592  
    jreplace(tok, "SymSym", "SymbolSymbol");
593  
    
594  
    jreplace(tok, "SS", "Map<S>");
595  
    jreplace(tok, "SymbolSymbol", "Map<Symbol>");
596  
    
597  
    jreplace(tok, "PairS", "Pair<S>");
598  
    jreplace(tok, "LPairS", "L<Pair<S>>");
599  
    
600  
    jreplace(tok, "T3S", "T3<S>");
601  
    jreplace(tok, "F1S", "F1<S>");
602  
    
603  
    jreplace(tok, "ItIt", "IterableIterator");
604  
    jreplace(tok, "CloseableItIt", "CloseableIterableIterator");
605  
606  
    jreplace(tok, "class <id> > <id> {", "class $2 extends $4 {");
607  
    jreplace(tok, "class <id> > <id><<id>> {", "class $2 extends $4  $5 $6 $7 {");
608  
    
609  
    jreplace(tok, "ISegmenter", "IF1<BufferedImage, L<Rect>>");
610  
    
611  
    // IPred<A> => IF1<A, Bool>
612  
    jreplace(tok, "IPred<<id>>", "IF1<$3, Bool>");
613  
    
614  
    // "on fail {" => "catch (Throwable _e) { ... rethrow(_e); }"
615  
    replaceKeywordBlock(tok, "on fail",
616  
      "catch (Throwable _e) {",
617  
      "\nthrow rethrow(_e); }");
618  
  
619  
    // "catch {" => "catch (Throwable _e) {"
620  
    jreplace(tok, "catch {", "catch (Throwable _e) {");
621  
  
622  
    // "catch print e {" => "catch e { _handleException(e); "
623  
    jreplace(tok, "catch print <id> {", "catch $3 { _handleException($3);");
624  
  
625  
    // "catch print short e {" => "catch e { printExceptionShort(e); "
626  
    jreplace(tok, "catch print short <id> {", "catch $4 { printExceptionShort($4);");
627  
    
628  
    // "catch X e {" => "catch (X e) {"
629  
    jreplace(tok, "catch <id> <id> {", "catch ($2 $3) {");
630  
  
631  
    // "catch e {" => "catch (Throwable e) {" (if e is lowercase)
632  
    jreplace(tok, "catch <id> {", "catch (Throwable $2) {", tokcondition {
633  
      S word = tok.get(i+3);
634  
      ret startsWithLowerCaseOrUnderscore(word);
635  
    });
636  
    
637  
    jreplace(tok, "+ +", "+", tokcondition {
638  
      //printStructure("++: ", subList(tok, i-1, i+6));
639  
      if (empty(_get(tok, i+2))) ret false; // no space between the pluses
640  
      if (empty(_get(tok, i)) && eq("+", _get(tok, i-1))) ret false;  // an actual "++" at the left
641  
      if (empty(_get(tok, i+4)) && eq("+", _get(tok, i+5))) ret false;  // an actual "++" at the right
642  
      //print("doing it");
643  
      ret true;
644  
    });
645  
  
646  
    // some crazy fancy syntax
647  
    jreplace(tok, "set <id>;", "$2 = true;");
648  
    
649  
    // single underscore (not allowed in Java anymore) to double underscore
650  
    jreplace(tok, "_", "__");
651  
    
652  
    // [stdEq] -> implementation of equals() and hashCode()
653  
    jreplace(tok, "[stdEq]",
654  
      "public bool equals(O o) { ret stdEq2(this, o); }\n" +
655  
      "public int hashCode() { ret stdHash2(this); }");
656  
    
657  
    // [stdToString] -> toString { ret stdToString(this); }
658  
    jreplace(tok, "[stdToString]",
659  
      "toString { ret stdToString(this); }");
660  
    
661  
    // [concepts] "concept.field!" for dereferencing references
662  
    
663  
    jreplace(tok, "*!", "$1.get()", tokcondition {
664  
      S l = tok.get(i+1);
665  
      if (!(isIdentifier(l) || eq(l, ")"))) false;
666  
      if (tok.get(i+2).contains("\n")) false; // no line break between <id> and !
667  
      if (nempty(tok.get(i+4))) true; // space after = ok
668  
      S t = _get(tok, i+5);
669  
      if (t == null) ret false;
670  
      if (isIdentifier(t) || eqOneOf(t, "=", "(")) false;
671  
      true;
672  
    });
673  
    
674  
    jreplace(tok, "for (<id> <id>)", "for ($3 $4 : list($3))");
675  
    jreplace(tok, "for (final <id> <id>)", "for (final $4 $5 : list($4))");
676  
677  
    // "continue unless", "break unless"
678  
    
679  
    for (S phrase : ll("continue unless", "break unless"))
680  
      while ((i = jfind(tok, phrase)) >= 0) {
681  
        S keyword = tok.get(i);
682  
        int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
683  
        replaceTokens(tok, i, i+4, "{ if (!(");
684  
        tok.set(j, ")) " + keyword + "; }");
685  
        reTok(tok, i, j+1);
686  
      }
687  
    
688  
    // S s = bla(), return if null; => S s = bla(); if (s == null) return;
689  
    // same with continue, break
690  
    while ((i = jfind(tok, ", <id> if null;", tokCondition {
691  
      ret eqOneOf(tok.get(i+3), "return", "continue", "break");
692  
    })) >= 0) {
693  
      S cmd = tok.get(i+2);
694  
      int j = tok_findBeginningOfStatement(tok, i);
695  
      print("Found statement " + j + "/" + i + " - " + joinSubList(tok, j-1, i+5*2-1));
696  
      S var = getVarDeclarationName(subList(tok, j-1, i));
697  
      replaceTokens_reTok(tok, i, i+5*2-1, "; if (" + var + " == null) " + cmd + ";");
698  
    }
699  
    
700  
    // "continue if", "break if"
701  
    
702  
    for (S phrase : ll("continue if", "break if"))
703  
      while ((i = jfind(tok, phrase)) >= 0) {
704  
        S keyword = tok.get(i);
705  
        int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
706  
        replaceTokens(tok, i, i+4, "{ if (");
707  
        tok.set(j, ") " + keyword + "; }");
708  
        reTok(tok, i, j+1);
709  
      }
710  
    
711  
    // "return if"
712  
    
713  
    while ((i = jfind(tok, "return if")) >= 0) {
714  
      int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
715  
      replaceTokens(tok, i, i+4, "{ if (");
716  
      tok.set(j, ") return; }");
717  
      reTok(tok, i, j+1);
718  
    }
719  
    
720  
    // "return unless"
721  
    
722  
    while ((i = jfind(tok, "return unless")) >= 0) {
723  
      int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
724  
      replaceTokens(tok, i, i+4, "{ if (!(");
725  
      tok.set(j, ")) return; }");
726  
      reTok(tok, i, j+1);
727  
    }
728  
    
729  
    // "return <id> if"
730  
    
731  
    while ((i = jfind(tok, "return <id> if")) >= 0) {
732  
      int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
733  
      tok.set(j, ") return " + tok.get(i+2) + "; }");
734  
      replaceTokens(tok, i, i+6, "{ if (");
735  
      reTok(tok, i, j+1);
736  
    }
737  
    
738  
    // "return with <statement>" / "continue with <statement>" / "break with <statement>"
739  
    
740  
    while ((i = jfind(tok, "<id> with", tokcondition { ret eqOneOf(tok.get(i+1), "return", "continue", "break"); })) >= 0) {
741  
      int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";");
742  
      tok.set(j, "; " + tok.get(i) + "; }");
743  
      replaceTokens(tok, i, i+3, "{");
744  
      reTok(tok, i, j+1);
745  
    }
746  
    
747  
    // return "bla" with <statement>
748  
    
749  
    while ((i = jfindOneOf(tok,
750  
      "return <quoted> with", "return <id> with")) >= 0) {
751  
      S result = tok.get(i+2);
752  
      int j = scanOverExpression(tok, getBracketMap(tok), i+6, ";");
753  
      replaceTokens(tok, i, i+5, "{");
754  
      tok.set(j, "; return " + result + "; }");
755  
      reTok(tok, i, j+1);
756  
    }
757  
    
758  
    tok_debugStatements(tok);
759  
760  
    // while not null (...) / if not null (...)
761  
    
762  
    while ((i = jfind_check not(tok, "<id> not null (", tokcondition {
763  
      ret eqOneOf(_get(tok, i+1), "if", "while");
764  
    })) >= 0) {
765  
      int closingBracket = findEndOfBracketPart(tok, i+6)-1;
766  
      replaceTokens(tok, i+2, i+6, "(");
767  
      tok.set(closingBracket, ") != null)");
768  
      reTok(tok, i, closingBracket+1);
769  
    }
770  
    
771  
    // while null (...) / if null (...)
772  
    
773  
    while ((i = jfind_check null(tok, "<id> null (", tokcondition {
774  
      ret eqOneOf(_get(tok, i+1), "if", "while");
775  
    })) >= 0) {
776  
      int closingBracket = findEndOfBracketPart(tok, i+4)-1;
777  
      replaceTokens(tok, i+2, i+4, "(");
778  
      tok.set(closingBracket, ") == null)");
779  
      reTok(tok, i, closingBracket+1);
780  
    }
781  
    
782  
    // Replace $1 with m.unq(0) etc. - caveat: this blocks identifiers $1, $2, ...
783  
    for (i = 1; i < l(tok); i += 2) {
784  
      S s = tok.get(i);
785  
      if (s.startsWith("$")) {
786  
        s = substring(s, 1);
787  
        if (isInteger(s)) {
788  
          tok.set(i, "m.unq(" + (parseInt(s)-1) + ")");
789  
          reTok(tok, i);
790  
        }
791  
      }
792  
    }
793  
  
794  
    // instanceof trickery
795  
    
796  
    jreplace(tok, "is a <id>", "instanceof $3");
797  
    jreplace(tok, "!<id> instanceof <id>.<id>", "!($2 instanceof $4.$6)");
798  
    jreplace(tok, "!<id> instanceof <id>", "!($2 instanceof $4)");
799  
    jreplace(tok, "<id> !instanceof <id>", "!($1 instanceof $4)");
800  
    
801  
    // map func1 func2 func3(...) => mapFGH(f func1, f func2, f func3, ...)
802  
    jreplace(tok, "map <id> <id> <id>(", "mapFGH(f $2, f $3, f $4,");
803  
804  
    // map func1 func2(...) => mapFG(f func1, f func2, ...)
805  
    jreplace(tok, "map <id> <id>(", "mapFG(f $2, f $3,");
806  
807  
    // "ref->bla" for dereferencing Concept.Ref or ThreadLocal or other
808  
    // For lambdas, use SPACES on the left or right of the arrow!
809  
    //jreplace(tok, "<id> ->", "$1.get().");
810  
    jreplace(tok, "->", ".get().", tokcondition {
811  
      ret empty(tok.get(i)) // no space on left of arrow
812  
        && empty(tok.get(i+2)) // no space inside of arrow
813  
        && empty(tok.get(i+4)) // no space on right of arrow
814  
        && !eq(_get(tok, i-1), "-"); // i-->0;
815  
    });
816  
    
817  
    // shortened subconcept declaration (before star constructors!)
818  
    shortenedSubconcepts(tok);
819  
    
820  
    // "case" as a variable name ( => _case)
821  
    
822  
    caseAsVariableName(tok);
823  
    
824  
    // "do" as a function name ( => dO)
825  
    
826  
    tok_doAsMethodName(tok);
827  
    
828  
    // "continue" as a function name ( => _continue)
829  
    continueAsFunctionName(tok);
830  
    
831  
    tok_extend(tok);
832  
    
833  
    jreplace(tok, "pn {", "p-noconsole {");
834  
      
835  
    // Do these BEFORE awt replacement! ("p-awt" contains "awt" token)
836  
    replaceKeywordBlock(tok, "r-awt", "r { awt {", "}}");
837  
    if (hasCodeTokens(tok, "p", "-")) tok_p_old(tok);
838  
839  
    replaceKeywordBlock(tok, "awt-messagebox", "awt { pcall-messagebox {", "}}");
840  
    replaceKeywordBlock(tok, "awt", "swingLater(r {", "});");
841  
  
842  
    jreplace(tok, "p-android {", "set flag Android. p {");
843  
      
844  
    unswing(tok);
845  
    lockBlocks(tok);
846  
    tempBlocks(tok);
847  
    tok_switchTo(tok);
848  
    
849  
    // trim x;
850  
    
851  
    jreplace(tok, "trim <id>;", "$2 = trim($2);");
852  
  
853  
    // iterate with index
854  
  
855  
    jreplace (tok, "for <id> over <id>:", "for (int $2 = 0; $2 < l($4); $2++)");
856  
    jreplace (tok, "for <id> backwards over <id>:", "for (int $2 = l($5)-1; $2 >= 0; $2--)");
857  
    jreplace (tok, "for <id>, <id> <id> over <id>: {", "for (int $2 = 0; $2 < l($7); $2++) { $4 $5 = $7.get($2);");
858  
    jreplace (tok, "for <id>, <id> <id> backwards over <id>: {", "for (int $2 = l($8)-1; $2 >= 0; $2--) { $4 $5 = $8.get($2);");
859  
    jreplace (tok, "for <id> to <id>:", "for (int $2 = 0; $2 < $4; $2++)");
860  
    jreplace (tok, "for <id> to <int>:", "for (int $2 = 0; $2 < $4; $2++)");
861  
    
862  
    tok = expandShortTypes(tok);
863  
      
864  
    tok_equalsCast(tok);
865  
    tok_equalsOptCast(tok);
866  
867  
    replaceKeywordBlock(tok, "r-thread-messagebox", "r-thread { pcall-messagebox {", "}}");
868  
    
869  
    replaceKeywordBlock(tok, "thread-messagebox", "thread { pcall-messagebox {", "}}");
870  
    
871  
    jreplace(tok, "rThread {", "r-thread {");
872  
    jreplace(tok, "rThreadEnter {", "r-thread { temp enter(); ");
873  
  
874  
    replaceKeywordBlock(tok, "r-thread", "runnableThread(r {", "})");
875  
    rNamedThread(tok);
876  
    
877  
    // only works in the scope of a DynModule
878  
    jreplace(tok, "rEnter {", "r { temp enter(); ");
879  
  
880  
    replaceKeywordBlock(tok, "r-pcall", "r { pcall {", "}}");
881  
  
882  
    replaceKeywordBlock(tok, "r-messagebox", "r { pcall-messagebox {", "}}");
883  
    
884  
    jreplace(tok, "r <id> + r <id>", "r { $2(); $5(); }");
885  
    
886  
    // runnable and r - now also with automatic toString if enabled
887  
    for (S keyword : ll("runnable", "r")) {
888  
      while ((i = jfind(tok, keyword + " {")) >= 0) {
889  
        int idx = findCodeTokens(tok, i, false, "{");
890  
        int j = findEndOfBracketPart(tok, idx);
891  
        L<S> contents = subList(tok, idx+1, j-1);
892  
        replaceTokens(tok, i, j+1, "new Runnable {"
893  
          + "  public void run() ctex { " + tok_addSemicolon(contents) + "\n}"
894  
          + (autoQuine ? tok_autoQuineFunc(contents) : "")
895  
          + "}");
896  
        reTok(tok, i, j+1);
897  
      }
898  
      
899  
      while ((i = jfind(tok, keyword + " <quoted> {")) >= 0) {
900  
        int idx = findCodeTokens(tok, i, false, "{");
901  
        int j = findEndOfBracketPart(tok, idx);
902  
        L<S> contents = subList(tok, idx+1, j-1);
903  
        replaceTokens(tok, i, j+1, "new Runnable {"
904  
          + "  public void run() ctex { " + tok_addSemicolon(contents) + "\n}"
905  
          + "  toString { ret " + tok.get(i+2) + "; }"
906  
          + (autoQuine ? tok_autoQuineFunc(contents, '_shortenedSourceCode) : "")
907  
          + "}");
908  
        reTok(tok, i, j+1);
909  
      }
910  
    }
911  
    
912  
    replaceKeywordBlock(tok,
913  
      "expectException",
914  
      "{ bool __ok = false; try {",
915  
      "} catch { __ok = true; } assertTrue(\"expected exception\", __ok); }");
916  
      
917  
    while ((i = tok.indexOf("tex")) >= 0) {
918  
      tok.set(i, "throws Exception");
919  
      tok = jtok(tok);
920  
    }
921  
    
922  
    // shorter & smarter whiles
923  
    
924  
    jreplace(tok, "while true", "while (true)");
925  
    jreplace(tok, "while licensed", "while (licensed())");
926  
    jreplace(tok, "repeat {", "while (licensed()) {");
927  
    tok_repeatWithSleep(tok);
928  
    
929  
    // null; => return null; etc.
930  
  
931  
    O cond = tokcondition {
932  
      ret tok_tokenBeforeLonelyReturnValue(tok, i-1);
933  
    };
934  
    jreplace(tok, "null;", "return null;", cond);
935  
    jreplace(tok, "false;", "return false;", cond);
936  
    jreplace(tok, "true;", "return true;", cond);
937  
    jreplace(tok, "this;", "return this;", cond);
938  
    
939  
    // ok <cmd> => ret "OK" with <cmd>
940  
    jreplace(tok, "ok <id>", "return \"OK\" with $2");
941  
    replaceKeywordBlock(tok, "ok", "{", " return \"OK\"; }");
942  
  
943  
    // "myFunction;" instead of "myFunction();" - quite rough
944  
    // (isolated identifier as function call)
945  
    cond = new TokCondition {
946  
      bool get(L<S> tok, int i) {
947  
        S word = tok.get(i+3);
948  
        //print("single word: " + word);
949  
        ret !eqOneOf(word, "break", "continue", "return", "else", "endifdef", "endif");
950  
      }
951  
    };
952  
    for (S pre : litlist("}", ";"))
953  
      jreplace(tok, pre + " <id>;", "$1 $2();", cond);
954  
  
955  
    // shorter match syntax for answer methods
956  
    
957  
    jreplace(tok, "if <quoted> || <quoted>",
958  
      "if (matchOneOf(s, m, $2, $5))");
959  
      
960  
    // "bla * bla | blubb * blubb"
961  
    jreplace_dyn(tok, "if <quoted>", func(L<S> tok, int cIdx) -> S {
962  
      S s = unquote(tok.get(cIdx+2));
963  
      //print("multimatch: " + quote(s));
964  
      new L<S> l;
965  
      for (S pat : splitAtJavaToken(s, "|")) {
966  
        //print("multimatch part: " + quote(pat));
967  
        if (pat.contains("..."))
968  
          l.add("matchX(" + quote(trim(pat)) + ", s, m)");
969  
        else if (javaTok(pat).contains("*"))
970  
          l.add("match(" + quote(trim(pat)) + ", s, m)");
971  
        else
972  
          l.add("match(" + quote(trim(pat)) + ", s)");
973  
      }
974  
      ret "if (" + join(" || ", l) + ")";
975  
    }, tokcondition {
976  
      ret javaTokC(unquote(tok.get(i+3))).contains("|");
977  
    });
978  
    
979  
    // "...bla..."
980  
    jreplace(tok, "if <quoted>", "if (find3plusRestsX($2, s, m))",
981  
      tokcondition {
982  
        ret startsAndEndsWith(unquote(tok.get(i+3)), "...");
983  
      });
984  
      
985  
    // "bla..."
986  
    jreplace(tok, "if <quoted>", "if (matchStartX($2, s, m))",
987  
      tokcondition {
988  
        ret unquote(tok.get(i+3)).endsWith("...");
989  
      });
990  
      
991  
    // "bla"
992  
    jreplace(tok, "if <quoted>", "if (match($2, s))",
993  
      tokcondition {
994  
        ret !javaTokC(unquote(tok.get(i+3))).contains("*");
995  
      });
996  
    // "bla * bla"
997  
    jreplace(tok, "if <quoted>", "if (match($2, s, m))");
998  
    jreplace(tok, "if match <quoted>", "if (match($3, s, m))");
999  
    
1000  
    jreplace(tok, "if <id> eq <quoted>", "if (eq($2, $4))");
1001  
  
1002  
    tok_dropExtraCommas(tok);
1003  
    
1004  
    // additional translations (if necessary)
1005  
    
1006  
    jreplace(tok, "pcall ping {", "pcall { ping();");
1007  
    
1008  
    replaceKeywordBlock(tok, ") pcall",
1009  
      ") { pcall {",
1010  
      "}}");
1011  
    
1012  
    replaceKeywordBlock(tok,
1013  
      "pcall",
1014  
      "try {",
1015  
      "} catch (Throwable __e) { _handleException(__e); }");
1016  
  
1017  
    replaceKeywordBlock(tok,
1018  
      "pcall-short",
1019  
      "try {",
1020  
      "} catch (Throwable __e) { print(exceptionToStringShort(__e)); }");
1021  
  
1022  
    replaceKeywordBlock(tok,
1023  
      "pcall-silent",
1024  
      "try {",
1025  
      "} catch (Throwable __e) { silentException(__e); }");
1026  
  
1027  
    replaceKeywordBlock(tok,
1028  
      "pcall-messagebox",
1029  
      "try {",
1030  
      "} catch __e { messageBox(__e); }");
1031  
  
1032  
    replaceKeywordBlock(tok,
1033  
      "pcall-infobox",
1034  
      "try {",
1035  
      "} catch __e { infoBox(__e); }");
1036  
  
1037  
    tok = dialogHandler(tok);
1038  
    
1039  
    replaceKeywordBlock(tok, "exceptionToUser",
1040  
      "try {",
1041  
      "} catch (Throwable __e) { ret exceptionToUser(__e); }"); 
1042  
  
1043  
    if (hasCodeTokens(tok, "twice", "{"))
1044  
      replaceKeywordBlock(tok, "twice",
1045  
        "for (int __twice = 0; __twice < 2; __twice++) {",
1046  
        "}"); 
1047  
  
1048  
    while ((i = findCodeTokens(tok, "bench", "*", "{")) >= 0) {
1049  
      int j = findEndOfBracketPart(tok, i+4)-1;
1050  
      S time = makeVar("time");
1051  
      S v = makeVar("bench");
1052  
      S n = tok.get(i+2);
1053  
      tok.set(i, "{ long " + time + " = sysNow(); for (int " + v + " = 0; " + v + " < " + n + "; " + v + "++)");
1054  
      tok.set(i+2, "");
1055  
      tok.set(j, "} printBenchResult(sysNow()-" + time + ", " + n + "); }");
1056  
      reTok(tok, i, j+1);
1057  
    }
1058  
  
1059  
    replaceKeywordBlockDyn(tok,
1060  
      "time",
1061  
      new O { S[] get() {
1062  
        S var = makeVar("startTime");
1063  
        ret new S[] {
1064  
          "{ long " + var + " = sysNow(); try { ",
1065  
          "} finally { " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); } }"};
1066  
      }});
1067  
    
1068  
    // version without { }
1069  
    replaceKeywordBlockDyn(tok,
1070  
      "time2",
1071  
      new O { S[] get() {
1072  
        S var = makeVar("startTime");
1073  
        ret new S[] {
1074  
          "long " + var + " = sysNow(); ",
1075  
          " " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); "};
1076  
      }});
1077  
    
1078  
    // time "bla" {
1079  
    // time msg {
1080  
    replaceKeywordPlusQuotedOrIDBlock(tok,
1081  
      "time",
1082  
      new O { S[] get(L<S> tok, int i) {
1083  
        S var = makeVar("startTime");
1084  
        ret new S[] {
1085  
          "long " + var + " = sysNow(); ",
1086  
          " done2_always(" + tok.get(i+2) + ", " + var + "); "};
1087  
      }});
1088  
    
1089  
    if (hasCodeTokens(tok, "assertFail", "{")) {
1090  
      S var = makeVar("oops");
1091  
      
1092  
      replaceKeywordBlock(tok,
1093  
        "assertFail",
1094  
        "boolean " + var + " = false; try {",
1095  
        "\n" + var + " = true; } catch (Exception e) { /* ok */ } assertFalse(" + var + ");"); 
1096  
    }
1097  
    
1098  
    replaceKeywordBlock(tok,
1099  
      "yo",
1100  
      "try {",
1101  
      "} catch (Exception " + makeVar("e") + ") { ret false; }",
1102  
      tokcondition {
1103  
        ret neqOneOf(_get(tok, i-1), "svoid", "void");
1104  
      });
1105  
  
1106  
    replaceKeywordBlock(tok,
1107  
      "awtIfNecessary",
1108  
      "swingNowOrLater(r " + "{",
1109  
      "});");
1110  
      
1111  
    ctex(tok);
1112  
      
1113  
    replaceKeywordBlock(tok,
1114  
      "actionListener",
1115  
      "new java.awt.event.ActionListener() { " +
1116  
        "public void actionPerformed(java.awt.event.ActionEvent _evt) { pcall-messagebox {",
1117  
      "}}}");
1118  
      
1119  
    for (S keyword : ll("autocloseable", "autoCloseable"))
1120  
      /*replaceKeywordBlock(tok,
1121  
        keyword,
1122  
        "new AutoCloseable() { public void close() throws Exception {",
1123  
        "}}");*/
1124  
        replaceKeywordBlock_dyn2_legacy(tok, keyword, new O {
1125  
          S[] get(LS tok, int iOpening, int iClosing) {
1126  
            LS contents = subList(tok, iOpening+1, iClosing);
1127  
            ret new S[] {
1128  
              "new AutoCloseable() { toString { ret " + quote(shorten(maxQuineLength, trimJoin(contents))) + "; } public void close() throws Exception {",
1129  
              "}}"
1130  
            };
1131  
          }
1132  
        });
1133  
      
1134  
    // try answer (string, test with nempty)
1135  
    while ((i = findCodeTokens(tok, "try", "answer")) >= 0) {
1136  
      int j = findEndOfStatement(tok, i);
1137  
      S v = makeVar();
1138  
      bool needCurly = !eqGet(tok, i-2, "{");
1139  
      tok.set(i, (needCurly ? "{" : "") + " S " + v);
1140  
      tok.set(i+2, "=");
1141  
      tok.set(j-1, "; if (!empty(" + v + ")) ret " + v + "; " + (needCurly ? "}" : ""));
1142  
      reTok(tok, i, j);
1143  
    }
1144  
  
1145  
    // try bool[ean] (try answer with Bool type)
1146  
    while ((i = findCodeTokens(tok, "try", "boolean")) >= 0) {
1147  
      int j = findEndOfStatement(tok, i);
1148  
      S v = makeVar();
1149  
      tok.set(i, "{ Bool " + v);
1150  
      tok.set(i+2, "=");
1151  
      tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
1152  
      reTok(tok, i, j);
1153  
    }
1154  
    
1155  
    // <statement>, print "..."; => { <statement>; print("..."); }
1156  
    while ((i = jfind(tok, ", print <quoted>;")) >= 0) {
1157  
      int j = tok_findBeginningOfStatement(tok, i);
1158  
      replaceTokens_reTok(tok, i, i+4*2-1, "; print(" + tok.get(i+4) + "); }");
1159  
      tokPrepend_reTok(tok, j, "{ ");
1160  
    }
1161  
    
1162  
    // return if null <expression> => if (<expression> == null) return;
1163  
    while ((i = jfind(tok, "return if null")) >= 0) {
1164  
      int j = findEndOfStatement(tok, i);
1165  
      clearTokens(tok, i, i+2);
1166  
      tok.set(i+4, "((");
1167  
      tok.set(j-1, ") == null) ret;");
1168  
      reTok(tok, i, j);
1169  
    }
1170  
    
1171  
    // return optional (return if not null)
1172  
    while ((i = jfind_check optional(tok, "return optional <id> =")) >= 0) {
1173  
      int j = findEndOfStatement(tok, i);
1174  
      S v = tok.get(i+4);
1175  
      clearTokens(tok, i+2, i+4);
1176  
      tok.set(i, "{");
1177  
      tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
1178  
      reTok(tok, i, j);
1179  
    }
1180  
    
1181  
    // try object (return if not null)
1182  
    while ((i = jfind_check object(tok, "try object")) >= 0) {
1183  
      int j = findEndOfStatement(tok, i);
1184  
      clearTokens(tok, i, i+3);
1185  
      bool isDecl = isIdentifier(get(tok, i+4)) && isIdentifier(get(tok, i+6)) && eqGet(tok, i+8, "=");
1186  
      if (isDecl) {
1187  
        S v = get(tok, i+6);
1188  
        tok.set(i, "{");
1189  
        tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
1190  
      } else {
1191  
        S v = makeVar();
1192  
        tok.set(i, "{ O " + v + "=");
1193  
        tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
1194  
      }
1195  
      reTok(tok, i, j);
1196  
    }
1197  
    
1198  
    // try Int i = ...; (return if not null, shorter version of "try object")
1199  
    while ((i = jfind(tok, "try <id> <id> =")) >= 0) {
1200  
      int j = findEndOfStatement(tok, i);
1201  
      S type = tok.get(i+2), v = tok.get(i+4);
1202  
      tok.set(i, "{");
1203  
      tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }");
1204  
      reTok(tok, i, j);
1205  
    }
1206  
    
1207  
    // debug print ...; => if (debug) print(...);
1208  
    while ((i = jfind(tok, "debug print")) >= 0) {
1209  
      int j = findEndOfStatement(tok, i);
1210  
      replaceTokens(tok, i, i+4, "if (debug) print(");
1211  
      tok.set(j-1, ");");
1212  
      reTok(tok, i, j);
1213  
    }
1214  
    
1215  
    functionReferences(tok);
1216  
    tok_expandLPair(tok);
1217  
    tok_expandPairL(tok);
1218  
    tok_expandLT3(tok);
1219  
    quicknew2(tok);
1220  
    
1221  
    // X x = nu(+...)  =>  X x = nu X(+...)
1222  
    jreplace(tok, "<id> <id> = nu(+", "$1 $2 = nu $1(+");
1223  
    // X x = nu(a := ...)  =>  X x = nu X(a := ...)
1224  
    jreplace(tok, "<id> <id> = nu(<id> :=", "$1 $2 = nu $1($6 :=");
1225  
    
1226  
    tok_expandVarCopies(tok); // AFTER the lines just above
1227  
    tok_replaceColonEqualsSyntax(tok); // ditto
1228  
1229  
    tok_unpair(tok);
1230  
    tok_cachedFunctions(tok);
1231  
    tok_simplyCachedFunctions(tok);
1232  
    tok_timedCachedFunctions(tok);
1233  
    
1234  
    tok_optPar(tok);
1235  
    
1236  
    throwFailEtc(tok);
1237  
    tok_typeAA(tok, pairClasses);
1238  
1239  
    // do this after expanding sclass etc.
1240  
    tok = tok_expandStarConstructors(tok);
1241  
    
1242  
    tok_kiloConstants(tok);
1243  
    //tok_colonMessages(tok);
1244  
    
1245  
    while ((i = jfind(tok, "shit:")) >= 0) {
1246  
      int j = tok_findEndOfStatement(tok, i);
1247  
      tok.set(i+2, "(");
1248  
      tok.set(j-1, ");");
1249  
      reTok(tok, i, j);
1250  
    }
1251  
      
1252  
    jreplace("shit(", "ret with print(");
1253  
    
1254  
    tok_virtualTypes(tok);
1255  
    tok_autoLongConstants(tok);
1256  
    
1257  
    // common misordering of type arguments
1258  
    jreplace("boolean <A>", "<A> boolean");
1259  
    
1260  
    tok_unimplementedMethods(tok);
1261  
    tok_switchableFields(tok);
1262  
    tok_autoDisposeFields(tok);
1263  
    tok_shortVisualize(tok);
1264  
    tok_whileGreaterThan(tok);
1265  
    tok_ifThenEnd(tok);
1266  
    
1267  
    tok_autoInitVars(tok);
1268  
    
1269  
    tok_fixBadTypeParameterOrder(tok);
1270  
    
1271  
    // shortened method declarations BEFORE standardFunctions
1272  
    jreplace(tok, "svoid", "static void");
1273  
    jreplace(tok, "void <id> {", "$1 $2() {");
1274  
    jreplace(tok, "void <id> thread {", "$1 $2() thread {");
1275  
    jreplace(tok, "String <id> {", "$1 $2() {");
1276  
    jreplace(tok, "Object <id> {", "$1 $2() {");
1277  
    jreplace(tok, "List <id> {", "$1 $2() {");
1278  
1279  
    namedThreads(tok);
1280  
    threads(tok);
1281  
    
1282  
    //tok_maxEquals(tok);
1283  
    
1284  
    tok_questionDot(tok);
1285  
    
1286  
    tok_embeddedFunctions(tok);
1287  
    
1288  
    jreplace("<id>[] <id> = new[", "$1[] $4 = new $1[");
1289  
    
1290  
    jreplace("<id> ifNull =", "if ($1 == null) $1 =");
1291  
    
1292  
    jreplace("class <id> extends <id><.<id>>", "class $2 extends $4<$2.$7>");
1293  
    
1294  
    tok_once(tok); // must come before next line so you can combine them
1295  
    tok_ifRecordMatch(tok);
1296  
    
1297  
    jreplace(tok, "<id> ||=", "$1 = $1 ||");
1298  
    
1299  
    // magicValue followed by a numerical constant
1300  
    jreplace("magicValue", "", (_tok, _i) -> {
1301  
      S t = _get(_tok, _i+3);
1302  
      ret eqOneOf(t, ".", "-") || isInteger(t);
1303  
    });
1304  
    
1305  
    lambdaReferences(tok);
1306  
    
1307  
    // end of local stuff
1308  
    
1309  
    tok_processMetaBlocks(tok, metaCodeAllowed());
1310  
    if (metaCodeAllowed()) runMetaTransformers(tok);
1311  
1312  
    same = eq(tok, before);
1313  
    /*if (!same)
1314  
      print("local not same " + safety + " (" + l(tok) + " tokens)");*/
1315  
    if (safety++ >= 10) {
1316  
      printSources(tok);
1317  
      fail("safety 10 error!");
1318  
    }
1319  
  } while (!same);
1320  
  
1321  
  ret tok;
1322  
}
1323  
1324  
static L<S> reTok_include(L<S> tok, int i, int j) {
1325  
  ret reTok_modify(tok, i, j, f localStuff1);
1326  
}
1327  
1328  
static L<S> includeInMainLoaded_reTok(L<S> tok, int i, int j) {
1329  
  ret reTok_include(tok, i, j);
1330  
}
1331  
1332  
static L<S> stdstuff(L<S> tok) {
1333  
  //if (++level >= 10) fail("woot? 10");
1334  
  
1335  
  print("stdstuff!");
1336  
  int i;
1337  
  
1338  
  new L<S> ts;
1339  
  tok_findTranslators(tok, ts);
1340  
  if (nempty(ts))
1341  
    print("DROPPING TRANSLATORS: " + structure(ts));
1342  
1343  
  print('quickmain); tok = quickmain(tok);
1344  
  print('includes); tok = tok_processIncludes(tok);
1345  
  print('conceptsDot); if (processConceptsDot(tok))
1346  
    tok = tok_processIncludes(tok);
1347  
  
1348  
  //print('starConstructors); tok = tok_expandStarConstructors(tok);
1349  
    
1350  
  // drop Java 8 annotations since we're compiling for Java 7
1351  
  jreplace(tok, "@Nullable", "");
1352  
1353  
  // STANDARD CLASSES & INTERFACES
1354  
  
1355  
  print("standard classes");
1356  
  final Set<S> haveClasses = addStandardClasses_v2(tok);
1357  
  
1358  
  tok_quickInstanceOf(tok, haveClasses);
1359  
1360  
  // concept-related stuff
1361  
  
1362  
  // auto-import concepts
1363  
  bool _a = tok_hasClassRef2(tok, /*"extends",*/ "Concept") || tok_hasClassRef2(tok, "Concepts"), _b = !haveClasses.contains("Concept");
1364  
  //print("auto-import: " + _a + ", " + _b);
1365  
  if (_a && _b) {
1366  
    print("Auto-including concepts.");
1367  
    if (shouldNotIncludeClass.contains("Concepts")) {
1368  
      print(join(tok));
1369  
      fail("Unwanted concepts import");
1370  
    }
1371  
    printStruct(haveClasses);
1372  
    tok = includeInMainLoaded(tok, "concepts.");
1373  
    reTok(tok, l(tok)-1, l(tok));
1374  
    //processConceptsDot(tok);
1375  
  }
1376  
  
1377  
  ret tok;
1378  
} // end of stdStuff!
1379  
1380  
static L<S> multilineStrings(L<S> tok) {
1381  
  for (int i = 1; i < tok.size(); i += 2) {
1382  
    S t = tok.get(i);
1383  
    if (isQuoted(t))
1384  
      if (t.startsWith("[") || t.contains("\r") || t.contains("\n"))
1385  
        tok.set(i, quote(unquote(t)));
1386  
  }
1387  
  ret tok;
1388  
}
1389  
1390  
static void inStringEvals(L<S> tok) {
1391  
  bool change = false;
1392  
  for (int i = 1; i < tok.size(); i += 2) {
1393  
    S t = tok.get(i);
1394  
    if (!isQuoted(t)) continue;
1395  
    if (t.contains("\\*") && !t.contains("\\\\")) { // << rough
1396  
      tok.set(i, inStringEval(t));
1397  
      change = true;
1398  
    }
1399  
  }
1400  
  if (change) reTok(tok);
1401  
}
1402  
1403  
static S inStringEval(S t) {
1404  
  t = dropPrefix("\"", dropSuffix("\"", t));
1405  
  new L<S> l;
1406  
  int idx;
1407  
  while ((idx = t.indexOf("\\*")) >= 0) {
1408  
    int j = indexOf(t, idx, "*/");
1409  
    if (j < 0) break;
1410  
    if (idx > 0)
1411  
      l.add("\"" + substring(t, 0, idx) + "\"");
1412  
    l.add("(" + trim(substring(t, idx+2, j)) + ")");
1413  
    t = substring(t, j+2);
1414  
  }
1415  
  if (nempty(t))
1416  
    l.add("\"" + t + "\"");
1417  
  ret "(" + join(" + ", l) + ")";
1418  
}
1419  
1420  
static L<S> quickmain(L<S> tok) {
1421  
  if (quickmainDone1 && quickmainDone2) ret tok;
1422  
1423  
  int i = findCodeTokens(tok, "main", "{");
1424  
  if (i < 0) i = findCodeTokens(tok, "m", "{");
1425  
  if (i >= 0 && !(i-2 > 0 && tok.get(i-2).equals("class"))) {
1426  
    tokSet_reTok(tok, i, "class main");
1427  
    quickmainDone1 = true;
1428  
  }
1429  
    
1430  
  i = findCodeTokens(tok, "psvm", "{");
1431  
  if (i < 0) i = findCodeTokens(tok, "p", "{");
1432  
  if (i >= 0) {
1433  
    int idx = i+2;
1434  
    int j = findEndOfBracketPart(tok, idx)-1;
1435  
    L<S> contents = subList(tok, idx+1, j);
1436  
    //print("contents: " + sfu(contents));
1437  
    tok.set(i, "public static void main(final String[] args) throws Exception");
1438  
    replaceTokens(tok, idx+1, j, tok_addSemicolon(contents));
1439  
    reTok(tok, i, j);
1440  
    quickmainDone2 = true;
1441  
  }
1442  
    
1443  
  ret tok;
1444  
}
1445  
1446  
sS makeVar(S name) {
1447  
  AtomicInteger counter = varCountByThread!;
1448  
  if (counter == null)
1449  
    varCountByThread.set(counter = new AtomicInteger);
1450  
  ret "_" + name + "_" + getAndInc(counter);
1451  
}
1452  
1453  
static S makeVar() { ret makeVar(""); }
1454  
1455  
static L<S> rtq(L<S> tok, S id) {
1456  
  ret runTranslatorQuick(tok, id);
1457  
}
1458  
1459  
static L<S> expandShortTypes(L<S> tok) {
1460  
  // replace <int> with <Integer>
1461  
  for (int i = 1; i+4 < tok.size(); i += 2)
1462  
    if (tok.get(i).equals("<")
1463  
      && litlist(">", ",").contains(tok.get(i+4))) {
1464  
      String type = tok.get(i+2);
1465  
      if (type.equals("int")) type = "Integer";
1466  
      else if (type.equals("long")) type = "Long";
1467  
      tok.set(i+2, type);
1468  
    }
1469  
    
1470  
  jreplace(tok, "O", "Object");
1471  
  jreplace(tok, "S", "String");
1472  
  jreplace(tok, "L", "List");
1473  
  jreplace(tok, "Cl", "Collection");
1474  
  
1475  
  jreplace(tok, "ret", "return", tokCondition {
1476  
    ret neqGetOneOf(tok, i+3, "=", ")", ".");
1477  
  });
1478  
  
1479  
  // bool -> boolean if it's not a function name
1480  
  jreplace(tok, "bool", "boolean", tokCondition {
1481  
    ret neqGetOneOf(tok, i+3, "(", null);
1482  
  });
1483  
  
1484  
  jreplace(tok, "AtomicBool", "AtomicBoolean");
1485  
  jreplace(tok, "AtomicInt", "AtomicInteger");
1486  
1487  
  jreplace(tok, "LL< <id> >", "L<L<$3>>");
1488  
  jreplace(tok, "LL<?>", "L<L<?>>");
1489  
  jreplace(tok, "LL", "L<L>");
1490  
  
1491  
  jreplace(tok, "Clusters< <id> >", "Map<$3, Collection<$3>>");
1492  
  
1493  
  ret tok;
1494  
}
1495  
1496  
static L<S> autoImports(L<S> tok) {
1497  
  HashSet<S> imports = new HashSet(tok_findImports(tok));
1498  
  new StringBuilder buf;
1499  
  for (S c : standardImports)
1500  
    if (!(imports.contains(c)))
1501  
      buf.append("import " + c + ";\n");
1502  
  if (buf.length() == 0) ret tok;
1503  
  tok.set(0, buf+tok.get(0));
1504  
  ret reTok(tok, 0, 1);
1505  
}
1506  
1507  
static String[] standardImports = {
1508  
  "java.util.*",
1509  
  "java.util.zip.*",
1510  
  "java.util.List",
1511  
  "java.util.regex.*",
1512  
  "java.util.concurrent.*",
1513  
  "java.util.concurrent.atomic.*",
1514  
  "java.util.concurrent.locks.*",
1515  
  "javax.swing.*",
1516  
  "javax.swing.event.*",
1517  
  "javax.swing.text.*",
1518  
  "javax.swing.table.*",
1519  
  "java.io.*",
1520  
  "java.net.*",
1521  
  "java.lang.reflect.*",
1522  
  "java.lang.ref.*",
1523  
  "java.lang.management.*",
1524  
  "java.security.*",
1525  
  "java.security.spec.*",
1526  
  "java.awt.*",
1527  
  "java.awt.event.*",
1528  
  "java.awt.image.*",
1529  
  "javax.imageio.*",
1530  
  "java.math.*"
1531  
};
1532  
1533  
static L<S> tok_processIncludes(L<S> tok) {
1534  
  int safety = 0;
1535  
  while (hasCodeTokens(tok, "!", "include") && ++safety < 100)
1536  
    tok = tok_processIncludesSingle(tok);
1537  
  
1538  
  //tok_autoCloseBrackets(tok);
1539  
  ret tok;
1540  
}
1541  
1542  
svoid tok_processEarlyIncludes(L<S> tok) {
1543  
  int i;
1544  
  while ((i = jfind_check include(tok, "!include early #<int>")) >= 0) {
1545  
    S id = tok.get(i+8);
1546  
    included.add(parseLong(id));
1547  
    replaceTokens_reTok(tok, i, i+10, "\n" + cacheGet(id) + "\n");
1548  
  }
1549  
}
1550  
1551  
static L<S> tok_processIncludesSingle(L<S> tok) {
1552  
  int i;
1553  
  while ((i = jfind_check include(tok, "!include #<int>")) >= 0) {
1554  
    S id = tok.get(i+6);
1555  
    included.add(parseLong(id));
1556  
    replaceTokens(tok, i, i+8, "\n" + cacheGet(id) + "\n");
1557  
    reTok_include(tok, i, i+8);
1558  
  }
1559  
  while ((i = jfind_check include(tok, "!include once #<int>")) >= 0) {
1560  
    S id = tok.get(i+8);
1561  
    bool isNew = included.add(parseLong(id));
1562  
    replaceTokens(tok, i, i+10, 
1563  
      isNew ? "\n" + cacheGet(id) + "\n" : "");
1564  
    reTok_include(tok, i, i+10);
1565  
  }
1566  
  ret tok;
1567  
}
1568  
1569  
static void ctex(L<S> tok) {
1570  
  replaceKeywordBlock(tok, "ctex",
1571  
    "{ try {",
1572  
    "} catch (Exception __e) { throw rethrow(__e); } }");
1573  
  for (S keyword : ll("null on exception", "null on error"))
1574  
    replaceKeywordBlock(tok, keyword,
1575  
      "{ try {",
1576  
      "} catch (Throwable __e) { return null; } }");
1577  
  replaceKeywordBlock(tok, "false on exception",
1578  
    "{ try {",
1579  
    "} catch (Throwable __e) { return false; } }");
1580  
}
1581  
  
1582  
static L<S> dialogHandler(L<S> tok) {
1583  
  ret replaceKeywordBlock(tok,
1584  
    "dialogHandler",
1585  
    "new DialogHandler() {\n" +
1586  
      "public void run(final DialogIO io) {",
1587  
    "}}");
1588  
}
1589  
1590  
static void quicknew2(L<S> tok) {
1591  
  tok_quicknew(tok);
1592  
1593  
  /*jreplace(tok, "new <id> <id>;", "$2 $3 = new $2;");
1594  
  jreplace(tok, "new <id><<id>> <id>;", "$2<$4> $6 = new $2;");
1595  
  jreplace(tok, "new <id>.<id> <id>;", "$2.$4 $5 = new $2.$4();");
1596  
  jreplace(tok, "new <id><<id>> <id>, <id>;", "$2<$4> $6 = new $2, $8 = new $2;");
1597  
  jreplace(tok, "new <id><<id>,<id>> <id>;", "$2<$4,$6> $8 = new $2;");
1598  
  jreplace(tok, "new <id><<id><<id>>> <id>;", "$2<$4<$6>> $9 = new $2;");
1599  
  jreplace(tok, "new <id><<id>[]> <id>;", "$2 $3 $4 $5 $6 $7 $8 = new $2;");
1600  
  jreplace(tok, "new <id>< <id><<id>>, <id>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;");
1601  
  jreplace(tok, "new <id>< <id><<id>,<id>> > <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;");
1602  
  jreplace(tok, "new <id>< <id>, <id><<id>> > <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;");
1603  
  jreplace(tok, "new <id>< <id><<id>,<id>,<id>> > <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;");
1604  
  jreplace(tok, "new <id>< <id><<id>,<id>>, <id>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;");
1605  
  jreplace(tok, "new <id>< <id>, <id><<id>,<id>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;");
1606  
  jreplace(tok, "new <id>< <id>< <id>, <id><<id>,<id>>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 = new $2;");
1607  
  jreplace(tok, "new <id>< <id>< <id>.<id>, <id><<id>,<id>>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 = new $2;");
1608  
  jreplace(tok, "new <id>< <id>< <id><<id>>, <id><<id>>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 = new $2;");*/
1609  
  
1610  
  // [abandoned, confusing, looks like a function definition] with arguments - new A a(...); => A a = new A(...);
1611  
  //jreplace(tok, "new <id> <id>(", "$2 $3 = new $2(");
1612  
1613  
  jreplace(tok, "for args " + "{", "for (int i = 0; i < args.length; i++) { final String arg = args[i];");
1614  
  
1615  
  // Constructor calls without parentheses
1616  
  // So you can say something like: predictors.add(new P1);
1617  
  
1618  
  jreplace1(tok, "new <id>", "new $2()", tokcondition {
1619  
    ret eqOneOf(_get(tok, i+5), "{", ",", ")", ";", ":");
1620  
  });
1621  
  
1622  
  jreplace1(tok, "new <id> < <id> >", "new $2<$4>()", tokcondition {
1623  
    ret eqOneOf(_get(tok, i+11), "{", ",", ")", ";", ":");
1624  
  });
1625  
  
1626  
  jreplace(tok, "new List(", "new ArrayList(");
1627  
  jreplace(tok, "new Map(", "new HashMap(");
1628  
  jreplace(tok, "new Set(", "new HashSet(");
1629  
  jreplace(tok, "new (Hash)Set", "new HashSet"); // rough
1630  
  jreplace(tok, "new (Tree)Set", "new TreeSet");
1631  
  jreplace(tok, "new (Hash)Map", "new HashMap");
1632  
  jreplace(tok, "new (Tree)Map", "new TreeMap");
1633  
  jreplace(tok, "\\*<id>[<id>] <id>;", "$2[] $6 = new $2[$4];");
1634  
  
1635  
  // X x = new(...)  =>  X x = new X(...)
1636  
  // X x = new {...} =>  X x = new X {...}
1637  
  // X x = new       =>  X x = new
1638  
  jreplace(tok, "<id> <id> = new", "$1 $2 = new $1", tokcondition {
1639  
    ret eqOneOf(_get(tok, i+9), "(", ";", ",", ")", "{");
1640  
  });
1641  
  jreplace(tok, "<id> <id> = new \\*", "$1 $2 = new $1");
1642  
  jreplace(tok, "\\* <id> = new <id>", "$5 $2 = new $5");
1643  
  
1644  
  // TODO: use backward type scanning
1645  
  
1646  
  jreplace(tok, "<id><<id>> <id> = new", "$1 $2 $3 $4 $5 = new $1", tokcondition {
1647  
    ret eqOneOf(_get(tok, i+9+3*2), "(", ";", ",", ")");
1648  
  });
1649  
  jreplace(tok, "<id><<id>,<id>> <id> = new", "$1 $2 $3 $4 $5 $6 $7 = new $1", tokcondition {
1650  
    ret eqOneOf(_get(tok, i+9+5*2), "(", ";", ",", ")");
1651  
  });
1652  
  jreplace(tok, "<id><<id><<id>>> <id> = new", "$1 $2 $3 $4 $5 $6 $7 $8 = new $1", tokcondition {
1653  
    ret eqOneOf(_get(tok, i+9+6*2), "(", ";", ",", ")");
1654  
  });
1655  
}
1656  
1657  
static L<S> extendClasses(L<S> tok) {
1658  
  int i;
1659  
  while ((i = jfind(tok, "extend <id> {")) >= 0) {
1660  
    S className = tok.get(i+2);
1661  
    int idx = findCodeTokens(tok, i, false, "{");
1662  
    int j = findEndOfBracketPart(tok, idx+2);
1663  
    S content = joinSubList(tok, idx+1, j-1);
1664  
    L<S> c = findInnerClassOfMain(tok, className);
1665  
    print("Extending class " + className);
1666  
    clearTokens(tok.subList(i, j+1));
1667  
    if (c == null) {
1668  
      print("Warning: Can't extend class " + className + ", not found");
1669  
      continue;
1670  
    }
1671  
    int startOfClass = indexOfSubList(tok, c); // magicIndexOfSubList is broken
1672  
    int endOfClass = startOfClass + l(c)-1;
1673  
    //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass)));
1674  
    while (neq(tok.get(endOfClass), "}")) --endOfClass;
1675  
    //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass)));
1676  
    tok.set(endOfClass, content + "\n" + tok.get(endOfClass));
1677  
    
1678  
    doubleReTok(tok, i, j+1, endOfClass, endOfClass+1);
1679  
  }
1680  
  ret tok;
1681  
}
1682  
1683  
// for ping / while ping
1684  
static void forPing(L<S> tok) {
1685  
  int i;
1686  
  for (S keyword : ll("for", "fOr", "while"))
1687  
    while ((i = jfind(tok, keyword + " ping (")) >= 0) {
1688  
      int bracketEnd = findEndOfBracketPart(tok, i+4)-1;
1689  
      int iStatement = bracketEnd+2;
1690  
      int iEnd = findEndOfStatement(tok, iStatement);
1691  
      tok.set(i+2, "");
1692  
      
1693  
      // turn into block
1694  
      if (!eq(get(tok, iStatement), "{")) {
1695  
        tok.set(iStatement, "{ " + tok.get(iStatement));
1696  
        tok.set(iEnd-1, tok.get(iEnd-1) + " }");
1697  
      }
1698  
        
1699  
      // add ping
1700  
      tok.set(iStatement, "{ ping(); " + dropPrefixTrim("{", tok.get(iStatement)));
1701  
      reTok(tok, i+2, iEnd);
1702  
    }
1703  
}
1704  
1705  
// lib 123 => !123
1706  
static void libs(L<S> tok) {
1707  
  int i;
1708  
  while ((i = jfind(tok, "lib <int>")) >= 0) {
1709  
    S id = tok.get(i+2);
1710  
    print("lib " + id);
1711  
    if (!libs.contains(id)) {
1712  
      libs.add(id);
1713  
      clearAllTokens(tok, i, i+3);
1714  
      /*tok.set(i, "!");
1715  
      tok.set(i+1, "");*/
1716  
    } else {
1717  
      print("...ignoring (duplicate)");
1718  
      clearAllTokens(tok, i, i+3);
1719  
      reTok(tok, i, i+3);
1720  
    }
1721  
  }
1722  
  print("libs found: " + libs);
1723  
}
1724  
1725  
// sourceCodeLine() => 1234
1726  
static void sourceCodeLine(L<S> tok) {
1727  
  int i ;
1728  
  while ((i = jfind(tok, "sourceCodeLine()")) >= 0) {
1729  
    replaceTokens(tok, i, i+5, str(countChar(joinSubList(tok, 0, i), '\n')+1));
1730  
    reTok(tok, i, i+5);
1731  
  }
1732  
}
1733  
1734  
// done before any other processing
1735  
static void earlyStuff(L<S> tok) {
1736  
  int i;
1737  
  
1738  
  tok_scopes(tok, autoCloseScopes := asInclude);
1739  
  tok_autosemi(tok);
1740  
  tok_autoCloseBrackets(tok);
1741  
  jreplace(tok, "°", "()");
1742  
  
1743  
  // Note: this makes the word "quine" a special operator
1744  
  // (unusable as a function name)
1745  
  
1746  
  while ((i = jfind(tok, "quine(")) >= 0) {
1747  
    int idx = findCodeTokens(tok, i, false, "(");
1748  
    int j = findEndOfBracketPart(tok, idx+2);
1749  
    tok.set(i, "new Quine");
1750  
    tok.set(idx, "(" + quote(joinSubList(tok, idx+1, j-1)) + ", ");
1751  
    reTok(tok, i, idx+1);
1752  
  }
1753  
  
1754  
  jreplace_check after(tok, "void <id> after super {", "void $2 { super.$2();");
1755  
  
1756  
  // do this before func & voidfunc because otherwise they swallow it
1757  
  jreplace(tok, "enter {", "{ temp enter();");
1758  
  
1759  
  // func keyword for lambdas - now automatically quines toString() if enabled
1760  
  
1761  
  // do func & voidfunc early to preserve original code as toString
1762  
  
1763  
  while ((i = jfind(tok, "func(")) >= 0) {
1764  
    int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")");
1765  
    int idx = findCodeTokens(tok, argsTo, false, "{");
1766  
    int j = findEndOfBracketPart(tok, idx);
1767  
    L<S> contents = subList(tok, idx+1, j-1);
1768  
    
1769  
    S returnType = "O";
1770  
    if (eq(tok.get(argsTo+2), "-") && eq(tok.get(argsTo+4), ">"))
1771  
      returnType = tok_toNonPrimitiveTypes(joinSubList(tok, argsTo+6, idx-1));
1772  
      
1773  
    S toString = autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trimJoin(contents))) + "; }" : "";
1774  
    
1775  
    L<S> args = cloneSubList(tok, argsFrom-1, argsTo);
1776  
    tok_shortFinals(args);
1777  
    tok_toNonPrimitiveTypes(args);
1778  
    
1779  
    L<S> types = tok_typesOfParams(args);
1780  
    O type = "O";
1781  
    if (l(types) <= 3)
1782  
      type = "F" + l(types) + "<" + joinWithComma(types) + ", " + returnType + ">";
1783  
    S body = tok_addReturn(contents);
1784  
    
1785  
    replaceTokens_reTok(tok, i, j,
1786  
      "new " + type + "() { "
1787  
        + returnType + " get(" + trimJoin(args) + ") ctex { "
1788  
          + body
1789  
        + " }\n" +
1790  
       + toString + "}");
1791  
  }
1792  
  
1793  
  while ((i = jfind(tok, "voidfunc(")) >= 0) {
1794  
    int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")");
1795  
    int idx = findCodeTokens(tok, argsTo, false, "{");
1796  
    int j = findEndOfBracketPart(tok, idx);
1797  
    L<S> contents = subList(tok, idx+1, j-1);
1798  
    
1799  
    L<S> args = cloneSubList(tok, argsFrom-1, argsTo);
1800  
    tok_shortFinals(args);
1801  
    tok_toNonPrimitiveTypes(args);
1802  
    
1803  
    L<S> types = tok_typesOfParams(args);
1804  
    O type = "O";
1805  
    if (l(types) <= 4)
1806  
      type = "VF" + l(types) + "<" + joinWithComma(types) + ">";
1807  
1808  
    replaceTokens(tok, i, j, "new " + type + "() { public void get(" + trimJoin(args) + ") ctex { " + tok_addSemicolon(contents) + " }\n" +
1809  
    (autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}");
1810  
    reTok(tok, i, j);
1811  
  }
1812  
  
1813  
  jreplace(tok, "func {", "func -> O {");
1814  
  jreplace(tok, "f {", "f -> O {");
1815  
  
1816  
  // swing -> S { ... } => swing(func -> S { ... })
1817  
  while ((i = jfind(tok, "swing ->")) >= 0) {
1818  
    int bracket = findCodeTokens(tok, i, false, "{");
1819  
    int j = findEndOfBracketPart(tok, bracket);
1820  
    tok.set(i, "swing(func");
1821  
    tok.set(j-1, "})");
1822  
    reTok(tok, i, j);
1823  
  }
1824  
  
1825  
  tok_qFunctions(tok);
1826  
  
1827  
  for (S keyword : ll(/*"f",*/ "func")) {
1828  
    while ((i = jfind(tok, keyword + " ->", tokcondition {
1829  
      ret isIdentifier(_get(tok, i+7)); // avoid lambda declaration like: f -> { ... }
1830  
    })) >= 0) {
1831  
      // I think there is a bug here for something like func -> x { new x { } }
1832  
      int idx = findCodeTokens(tok, i, false, "{");
1833  
      int j = findEndOfBracketPart(tok, idx);
1834  
      S returnType = tok_toNonPrimitiveTypes(joinSubList(tok, i+6, idx-1));
1835  
      L<S> contents = subList(tok, idx+1, j-1);
1836  
      replaceTokens(tok, i, j, "new F0<" + returnType + ">() { " + returnType + " get() ctex { " + tok_addReturn(contents) + " }\n" +
1837  
      (autoQuine ? "  public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}");
1838  
      reTok(tok, i, j);
1839  
    }
1840  
  }
1841  
    
1842  
  while ((i = jfind(tok, "time repeat * {")) >= 0) {
1843  
    int j = findEndOfBlock(tok, i+6)-1;
1844  
    tok.set(i, "time {");
1845  
    tok.set(j, "}}");
1846  
    reTok(tok, i, j+1);
1847  
  }
1848  
1849  
  // do this before "m {" stuff because "repeat m" [doesn't seem to work yet though)
1850  
  while ((i = findCodeTokens(tok, "repeat", "*", "{")) >= 0) {
1851  
    S v = makeVar("repeat");
1852  
    tok.set(i, "for (int " + v + " = 0; " + v + " < " + tok.get(i+2) + "; " + v + "++)");
1853  
    tok.set(i+2, "");
1854  
    reTok(tok, i, i+3);
1855  
  }
1856  
}
1857  
1858  
static void throwFailEtc(L<S> tok) {
1859  
  bool anyChange = false;
1860  
  for (int i = 1; i+4 < l(tok); i += 2)
1861  
    if (eqOneOf(get(tok, i+2), "fail", "todo")
1862  
      && eq(get(tok, i+4), "(")
1863  
      && !eqOneOf(get(tok, i), "throw", "RuntimeException", "return", "f", "function")) {
1864  
      tok.set(i+2, "throw " + tok.get(i+2));
1865  
      anyChange = true;
1866  
    }
1867  
  if (anyChange)
1868  
    reTok(tok);
1869  
}
1870  
1871  
static void namedThreads(L<S> tok) {
1872  
  for (int i = 0; i < 100; i++) {
1873  
    int idx = findCodeTokens(tok, "thread", "<quoted>", "{");
1874  
    if (idx < 0) idx = findCodeTokens(tok, "thread", "<id>", "{");
1875  
    if (idx < 0)
1876  
      break;
1877  
    int j = findEndOfBracketPart(tok, idx+4);
1878  
    S tName = tok.get(idx+2);
1879  
    
1880  
    S pre = "startThread(" + tName + ", r { ";
1881  
    S post = "})";
1882  
    if (!tok_tokenLeftOfExpression(tok, idx-2)) post += ";";
1883  
1884  
    tok.set(idx, pre);
1885  
    tok.set(idx+2, "");
1886  
    tok.set(idx+4, "");
1887  
    tok.set(j-1, post);
1888  
    //print(join(subList(tok, idx, j)));
1889  
    reTok(tok, idx, j);
1890  
  }
1891  
}
1892  
1893  
static void rNamedThread(L<S> tok) {
1894  
  for (int i = 0; i < 100; i++) {
1895  
    int idx = findCodeTokens(tok, "r", "-", "thread", "<quoted>", "{");
1896  
    if (idx < 0) idx = findCodeTokens(tok, "r", "-", "thread", "<id>", "{");
1897  
    if (idx < 0)
1898  
      break;
1899  
    int j = findEndOfBracketPart(tok, idx+8);
1900  
    S tName = tok.get(idx+6);
1901  
    
1902  
    S pre = "r { thread " + tName + " {";
1903  
    S post = "}}";
1904  
1905  
    replaceTokens(tok, idx, idx+9, pre);
1906  
    tok.set(j-1, post);
1907  
    reTok(tok, idx, j);
1908  
  }
1909  
}
1910  
1911  
static void threads(L<S> tok) {
1912  
  replaceKeywordBlock(tok, "daemon", "startDaemonThread(r {", "});");
1913  
  //replaceKeywordBlock(tok, "thread", "startThread(r {", "});");
1914  
  
1915  
  // now enclose in { } to allow using like "void bla() thread { ... }" - if it's not used as an expression
1916  
  
1917  
  replaceKeywordBlock_dyn2_legacy(tok, "thread", new O { // don't use func here, it can't be transpiled
1918  
    S[] get (LS tok, int iOpening, int iClosing) {
1919  
      // is the thread clause used as an expression?
1920  
      bool isExpression = tok_tokenLeftOfExpression(tok, iOpening-4);
1921  
      ret new S[] {
1922  
        (isExpression ? "" : "{ ") + "startThread(r {",
1923  
        "})" +
1924  
        (isExpression ? "" : "; }")
1925  
      };
1926  
    }
1927  
  });
1928  
}
1929  
1930  
static SS sf; // standard standard functions (haha)
1931  
static Bool _761ok;
1932  
1933  
static L<S> standardFunctions(L<S> tok) {
1934  
  if (sf == null) {
1935  
    S _761 = cacheGet("#761");
1936  
    if (_761ok == null)
1937  
      _761ok = isBracketHygienic(_761);
1938  
    assertTrue("Whoa! #761 truncated?", _761ok);
1939  
    L<S> standardFunctions = concatLists(
1940  
      (L) loadVariableDefinition(_761, "standardFunctions"),
1941  
      (L) loadVariableDefinition(cacheGet("#1006654"), "standardFunctions"));
1942  
1943  
    sf = new HashMap;
1944  
    for (S x : standardFunctions) {
1945  
      S[] f = x.split("/");
1946  
      sf.put(f[1], f[0]);
1947  
    }
1948  
  }
1949  
  
1950  
  SS sfMap = combinedMap(extraStandardFunctions, sf);
1951  
    
1952  
  for (int i = 0; ; i++) {
1953  
    Set<S> defd = new HashSet(findFunctions(tok));
1954  
    
1955  
    int j;
1956  
    while ((j = jfind(tok, "should not include function *.")) >= 0) {
1957  
      S fname = tok.get(j+8);
1958  
      shouldNotIncludeFunction.add(fname);
1959  
      clearAllTokens(tok.subList(j, j+12));
1960  
    }
1961  
1962  
    while ((j = jfind(tok, "do not include function *.")) >= 0) {
1963  
      S fname = tok.get(j+8);
1964  
      doNotIncludeFunction.add(fname);
1965  
      clearAllTokens(tok.subList(j, j+12));
1966  
    }
1967  
    
1968  
    doNotIncludeFunction.addAll(tok_importedStaticFunctionNames(tok));
1969  
    
1970  
    // changes tok
1971  
    Set<String> invocations = findFunctionInvocations(tok, sfMap, hardFunctionReferences, defd, true);
1972  
    /*if (invocations.contains("str"))
1973  
      print("==STR==" + join(tok) + "==STR==");*/
1974  
    if (!cic(definitions, "leanMode"))
1975  
      invocations.addAll(functionsToAlwaysInclude);
1976  
1977  
    //print("Functions invoked: " + structure(invocations));
1978  
    List<String> needed = diff(invocations, defd);
1979  
    for (S f : doNotIncludeFunction) needed.remove(f);
1980  
    if (needed.isEmpty())
1981  
      break;
1982  
    print("Adding functions: " + join(" " , needed));
1983  
    
1984  
    HashSet neededSet = new HashSet(needed);
1985  
    Collection<S> bad = setIntersection(neededSet, shouldNotIncludeFunction);
1986  
    if (nempty(bad)) {
1987  
      S msg = "INCLUDING BAD FUNCTIONS: " + sfu(bad);
1988  
      print(msg);
1989  
      print(join(tok));
1990  
      fail(msg);
1991  
    }
1992  
      
1993  
    new L<S> added;
1994  
    new L<Future<S>> parts;
1995  
    new L<S> preload;
1996  
    
1997  
    for (S x : needed)
1998  
      if (sfMap.containsKey(x))
1999  
        preload.add(sfMap.get(x));
2000  
    print("Preloading: " + preload);
2001  
    cachePreload(preload);
2002  
    
2003  
    for (String x : cloneList(needed)) {
2004  
      if (defd.contains(x)) continue;
2005  
      
2006  
      String id = sfMap.get(x);
2007  
      if (id == null) {
2008  
        print("Standard function " + x + " not found.");
2009  
        needed.remove(x);
2010  
        continue;
2011  
      }
2012  
      //print("Adding function: " + x + " (" + id + ")");
2013  
       
2014  
      S function = cacheGet(id);
2015  
      //if (("\n" + function).contains("\n!")) print("Warning: " + id + " contains translators.");
2016  
      
2017  
      if (cacheStdFunctions) {
2018  
        long _id = psI(id);
2019  
        CachedInclude ci = cachedIncludes.get(_id);
2020  
        if (ci == null) {
2021  
          cachedIncludes.put(_id, ci = new CachedInclude(_id));
2022  
          //println("Caching include " + _id + ", l=" + l(cachedIncludes));
2023  
        }
2024  
        function += "\n";
2025  
        fS _function = function;
2026  
        if (neq(ci.javax, function)) {
2027  
          print("Compiling function: " + x);
2028  
          ci.javax = function;
2029  
          ci.java = executor.submit(new Callable<S>() {
2030  
            public S call() {
2031  
              // We assume that variables made with makeVar() will always be local to some block
2032  
              varCountByThread.set(null);
2033  
              ret join(localStuff1(jtok(_function)));
2034  
            }
2035  
          });
2036  
          ci.realJava = null;
2037  
        }
2038  
        parts.add(ci.javaFuture());
2039  
      } else
2040  
        parts.add(nowFuture(function + "\n"));
2041  
        
2042  
      added.add(x);
2043  
      Collection<S> newFunctions = new HashSet(findFunctionDefs(javaTok(function)));
2044  
      defd.addAll(newFunctions);
2045  
      for (S f : newFunctions)
2046  
        if (!addedFunctions.add(f)) {
2047  
          printSources(tok);
2048  
          fail("Trying to add function " + f + " again - main class syntax broken!");
2049  
        }
2050  
    }
2051  
    
2052  
    S text = join(getAllFutures(parts));
2053  
    tok = includeInMainLoaded(tok, text);
2054  
      
2055  
    // defd = new HashSet(findFunctions(tok));
2056  
    //print("Functions added: " + joinWithSpace(added));
2057  
    
2058  
    for (String x : needed)
2059  
      if (!defd.contains(x)) {
2060  
        print(join(tok));
2061  
        fail("Function not defined properly: " + x);
2062  
      }
2063  
    //print("Iteration " + (i+2));
2064  
    
2065  
    print('definitions); tok_definitions(tok);
2066  
    print('ifndef); tok_ifndef(tok);
2067  
    print('ifdef); tok_ifdef(tok);
2068  
    
2069  
    if (i >= 1000) fail("Too many iterations");
2070  
  }
2071  
  
2072  
  ret tok;
2073  
}
2074  
2075  
static L<S> findFunctions(L<S> tok) {
2076  
  //ret findFunctionDefinitions(join(findMainClass(tok)));
2077  
  ret findFunctionDefs(findMainClass(tok));
2078  
}
2079  
2080  
static S cacheGet(S snippetID) {
2081  
  snippetID = formatSnippetID(snippetID);
2082  
  S text = snippetCache.get(snippetID);
2083  
  if (text == null) {
2084  
    text = loadSnippet(snippetID);
2085  
    // very early processing/checks for includes
2086  
    
2087  
    if (hasUnclosedStringLiterals(text))
2088  
      fail("Unclosed string literals in " + snippetID);
2089  
      
2090  
    if (regexpContains("\\bscope\\b", text)) {
2091  
      LS tok = javaTok(text);
2092  
      tok_scopes(tok, autoCloseScopes := true);
2093  
      text = join(tok);
2094  
    }
2095  
    
2096  
    snippetCache.put(snippetID, text);
2097  
  }
2098  
  ret text;
2099  
}
2100  
2101  
static void cachePreload(Collection<S> ids) {
2102  
  new L<S> needed;
2103  
  for (S id : ids)
2104  
    if (!snippetCache.containsKey(formatSnippetID(id)))
2105  
      needed.add(formatSnippetID(id));
2106  
  if (l(needed) > 1) {
2107  
    L<S> texts = loadSnippets(needed);
2108  
    for (int i = 0; i < l(needed); i++)
2109  
      if (texts.get(i) != null)
2110  
        snippetCache.put(needed.get(i), texts.get(i));
2111  
  }
2112  
}
2113  
2114  
static L<S> jtok(L<S> tok) {
2115  
  ret jtok(join(tok));
2116  
}
2117  
2118  
static L<S> jtok(S s) {
2119  
  ret indexTokenList(javaTok(s));
2120  
}
2121  
2122  
static HashSet<S> haveClasses_actual(L<S> tok) {
2123  
  new HashSet<S> have;
2124  
  for (L<S> c : innerClassesOfMain(tok))
2125  
    have.add(getClassDeclarationName(c));
2126  
  ret have;
2127  
}
2128  
2129  
static HashSet<S> haveClasses_addImported(L<S> tok, HashSet<S> have) {
2130  
  have.addAll(tok_importedClassNames(tok));
2131  
  have.addAll(usualJavaClassNames()); // for S => S.class
2132  
  ret have;
2133  
}
2134  
2135  
// works on Java level (no "sclass" etc)
2136  
// returns list of classes we have (useful for other processing)
2137  
static Set<S> addStandardClasses_v2(L<S> tok) {
2138  
  if (lclasses == null) {
2139  
    S sc = cacheGet("#1003674");   
2140  
    lclasses = new L;
2141  
    for (S line : tlft_j(sc)) {
2142  
      int idx = line.indexOf('/');
2143  
      lclasses.addAll(ll(line.substring(0, idx), line.substring(idx+1)));
2144  
    }
2145  
  }
2146  
  L<S> definitions = lclasses;
2147  
2148  
  for (int safety = 0; safety < 10; safety++) {
2149  
    HashSet<S> have = haveClasses_actual(tok);
2150  
    have.addAll(tok_importedClassNames(tok));
2151  
2152  
    int j;
2153  
    while ((j = jfind(tok, "should not include class *.")) >= 0) {
2154  
      S cname = tok.get(j+8);
2155  
      shouldNotIncludeClass.add(cname);
2156  
      clearAllTokens(tok.subList(j, j+12));
2157  
    }
2158  
    
2159  
    new SS need;
2160  
    new Set<S> snippets;
2161  
    Set<S> idx = tokenIndexWithoutIfclass_forStdClasses(tok);
2162  
    
2163  
    while ((j = jfind(tok, "please include class *.")) >= 0) {
2164  
      S cname = tok.get(j+6);
2165  
      idx.add(cname);
2166  
      clearAllTokens(tok.subList(j, j+10));
2167  
    }
2168  
2169  
    for (int i = 0; i+1 < l(definitions); i += 2) {
2170  
      S className = definitions.get(i);
2171  
      S snippetID = fsI(definitions.get(i+1));
2172  
      if (idx.contains(className) && !have.contains(className) && snippets.add(snippetID))
2173  
        need.put(className, snippetID);
2174  
    }
2175  
    if (hasDef("SymbolAsString")) {
2176  
      print("Have SymbolAsString.");
2177  
      if (need.containsKey("Symbol")) {
2178  
        print("Have Symbol.");
2179  
        need.remove("Symbol");
2180  
      }
2181  
    } else
2182  
      print("No SymbolAsString.");
2183  
      
2184  
    if (empty(need)) ret have;
2185  
  
2186  
    for (S className : keys(need))
2187  
      if (shouldNotIncludeClass.contains(className)) {
2188  
        S msg = "INCLUDING BAD CLASS: " + className;
2189  
        print(msg);
2190  
        print(join(tok));
2191  
        fail(msg);
2192  
      }
2193  
      
2194  
    cachePreload(values(need));
2195  
    
2196  
    new LPair<S, CachedInclude> parts; // class name, Java code
2197  
    
2198  
    print("Adding classes: " + joinWithSpace(keys(need)));
2199  
    for (S className : keys(need)) {
2200  
      if (have.contains(className)) continue; // intermittent add
2201  
      S snippetID = need.get(className);
2202  
      //print("Adding class " + className + " / " + snippetID);
2203  
      snippetID = fsI(snippetID);
2204  
      S text = cacheGet(snippetID);
2205  
      
2206  
      assertTrue(cacheStdClasses);
2207  
      long _id = psI(snippetID);
2208  
      CachedInclude ci = cachedIncludes.get(_id);
2209  
      if (ci == null) cachedIncludes.put(_id, ci = new CachedInclude(_id));
2210  
      if (neq(ci.javax, text)) {
2211  
        print("Compiling class: " + className);
2212  
        ci.javax = text;
2213  
        ci.java = executor.submit(new Callable<S>() {
2214  
          public S call() {
2215  
            // We assume that variables made with makeVar() will always be local to some block
2216  
            varCountByThread.set(null);
2217  
            ret join(localStuff1(jtok(text)));
2218  
          }
2219  
        });
2220  
        ci.realJava = null;
2221  
      }
2222  
      parts.add(pair(className, ci));
2223  
    }
2224  
    
2225  
    new StringBuilder buf;
2226  
    for (Pair<S, CachedInclude> p : parts) {
2227  
      S className = p.a;
2228  
      LS ct = javaTok(p.b.java());
2229  
      for (LS c : allClasses(ct)) {
2230  
        S name = getClassDeclarationName(c);
2231  
        have.add(name);
2232  
      }
2233  
      if (!have.contains(className))
2234  
        fail("Wrongly defined class: " + className + " / " + p.b.snippetID);
2235  
      if (!addedClasses.add(className)) {
2236  
        printSources(tok);
2237  
        fail("Trying to add class " + className + " again - main class syntax broken!");
2238  
      }
2239  
      buf.append(p.b.java());
2240  
    } // for part
2241  
    
2242  
    tok = includeInMainLoaded(tok, str(buf));
2243  
  }
2244  
  fail("safety 10");
2245  
}
2246  
2247  
static Set<S> expandableClassNames = lithashset("BigInteger");
2248  
2249  
// no reTok - leaves tok dirty
2250  
// magically append ".class" to class name references
2251  
static bool expandClassReferences_lazy(L<S> tok, Set<S> classNames) {
2252  
  bool change = false;
2253  
  for (int i = 3; i+2 < l(tok); i += 2) {
2254  
    S t = tok.get(i);
2255  
    
2256  
    // skip implements/extends/throws lists
2257  
    if (eqOneOf(t, "implements", "extends", "throws")) {
2258  
      i = tok_endOfImplementsList(tok, i);
2259  
      continue;
2260  
    }
2261  
    
2262  
    if (classNames.contains(t) || expandableClassNames.contains(t)) {
2263  
      S s = tok.get(i-2); t = tok.get(i+2);
2264  
      // TODO: This whole logic ain't very good
2265  
      // (Hard to distinguish between "Int.class" as an argument
2266  
      // and "Int" as a type parameter.)
2267  
      if (eqOneOf(s, "instanceof", "new", ".", "<", ">", "/", "nu")) continue;
2268  
      if (isIdentifier(s) || isInteger(s)) continue;
2269  
      if (eq(t, ",") && isIdentifier(get(tok, i+4)) && eqGet(tok, i+6, ">")) continue; // e.g. T3<L<S>, S, S>
2270  
      if (eq(s, ",") && isIdentifier(get(tok, i-4)) && eqGet(tok, i-6, "<")) continue; // e.g. T3<S, S, S>
2271  
      if (eq(s, ",") && eqOneOf(_get(tok, i-6), "implements", "throws")) continue;
2272  
      
2273  
      // check for cast
2274  
      if (eq(s, "(") && eq(t, ")") && i >= 5) {
2275  
        if (!eqOneOf(get(tok, i+4), "{", ";")) {
2276  
          S x = tok.get(i-4);
2277  
          if (!isIdentifier(x)) continue;
2278  
          if (eqOneOf(x, "ret", "return")) continue;
2279  
        }
2280  
      }
2281  
      if (eqOneOf(t, ",", ")", ";", ":")) {
2282  
        tok.set(i, tok.get(i) + ".class");
2283  
        change = true;
2284  
      }
2285  
    }
2286  
  }
2287  
  ret change;
2288  
}
2289  
2290  
static void expandClassReferences(L<S> tok, Set<S> classNames) {
2291  
  if (expandClassReferences_lazy(tok, classNames))
2292  
    reTok(tok);
2293  
}
2294  
2295  
// "<id>/<ClassName>" => "((ClassName) <id>)"
2296  
static void slashCasts(L<S> tok, final Set<S> classNames) {
2297  
  /*jreplace(tok, "<id>/<id>", "(($3) $1)", tokcondition {
2298  
    ret classNames.contains(tok.get(i+5));
2299  
  });*/
2300  
  int n = l(tok)-4;
2301  
  for (int i = 1; i < n; i += 2)
2302  
    if (tok.get(i+2).equals("/") && isIdentifier(tok.get(i))
2303  
      && classNames.contains(tok.get(i+4)))
2304  
      replaceTokens_reTok(tok, i, i+5, "((" + tok.get(i+4) + ") " + tok.get(i) + ")");
2305  
}
2306  
2307  
// "<ClassName>(...)" => "new <ClassName>(...)"
2308  
// doesn't work at beginning of statement as we can't easily
2309  
// distinguish it from a constructor declaration.
2310  
static void newWithoutNew(L<S> tok, final Set<S> classNames) {
2311  
  TokCondition cond = newWithoutNew_condition(classNames);
2312  
  jreplace(tok, "<id>(", "new $1(", cond);
2313  
  // just one case with type arg for now
2314  
  jreplace(tok, "<id><<id>>(", "new $1<$3>(", cond);
2315  
}
2316  
2317  
static TokCondition newWithoutNew_condition(final Set<S> classNames) {
2318  
  ret tokcondition {
2319  
    if (!classNames.contains(tok.get(i+1))) false;
2320  
    S prev = _get(tok, i-1);
2321  
    bool ok = eq(prev, ">") ? eqGet(tok, i-3, "-")
2322  
      : neqOneOf(prev, "new", ";", "}", "{", "public", "protected", "private", ".");
2323  
    //print("newWithoutNew: checking " + struct(subList(tok, i-1, i+2)) + " => " + ok);
2324  
    ret ok;
2325  
  };
2326  
}
2327  
2328  
static bool processConceptsDot(L<S> tok) {
2329  
  bool anyChange = false, change;
2330  
  do {
2331  
    change = false;
2332  
    for (int i : jfindAll(tok, "concepts."))
2333  
      if (contains(get(tok, i+3), "\n")) {
2334  
        replaceTokens(tok, i, i+3, "!" + "include once #1004863 // Dynamic Concepts");
2335  
        reTok(tok, i, i+3);
2336  
        change = anyChange = true;
2337  
        break;
2338  
      }
2339  
  } while (change);
2340  
  ret anyChange;
2341  
}
2342  
2343  
static void caseAsVariableName(L<S> tok) {
2344  
  if (!tok.contains("case")) ret;
2345  
  for (int i = 1; i+2 < l(tok); i += 2) {
2346  
    S t = tok.get(i+2);
2347  
    if (tok.get(i).equals("case")
2348  
      && !(t.startsWith("'") || isInteger(t) || isIdentifier(t)))
2349  
      tok.set(i, "_case");
2350  
  }
2351  
}
2352  
2353  
static void continueAsFunctionName(L<S> tok) {
2354  
  jreplace(tok, "continue(", "_continue(");
2355  
}
2356  
2357  
// f bla => "bla" - and "please include function bla."
2358  
static void functionReferences(L<S> tok) {
2359  
  int i;
2360  
  
2361  
  jreplace_dyn(tok, "f-thread <id>", func(L<S> tok, int cIdx) {
2362  
    "dynamicCallableMC_thread(" + quote(tok.get(cIdx+6)) + ")"
2363  
  });
2364  
  
2365  
  S keyword = "f";
2366  
  while ((i = jfind(tok, keyword + " <id>", tokcondition {
2367  
    ret !eq(tok.get(i+3), "instanceof");
2368  
  })) >= 0) {
2369  
    S f = tok.get(i+2);
2370  
    clearTokens(tok, i, i+2);
2371  
    tok.set(i+2, quote(f));
2372  
    reTok(tok, i, i+2);
2373  
    tok.set(l(tok)-1, last(tok) + "\nplease include function " + f + ".");
2374  
    reTok(tok, l(tok)-1, l(tok));
2375  
  }
2376  
  
2377  
  // r|rThread|rEnter|rThreadEnter fname => r|rThread|... { fname() }
2378  
  while ((i = jfindOneOf_cond(tok, tokcondition {
2379  
    ret !eq(tok.get(i+3), "instanceof");
2380  
  }, "r <id>", "rThread <id>", "rEnter <id>", "rThreadEnter <id>")) >= 0) {
2381  
    S f = tok.get(i+2);
2382  
    replaceTokens(tok, i, i+3, tok.get(i) + " { " + f + "(); }");
2383  
    reTok(tok, i, i+3);
2384  
  }
2385  
  
2386  
  // dm_q fname => r_dm_q(r fname)
2387  
  jreplace(tok, "dm_q <id>", "r_dm_q(r $2)");
2388  
  
2389  
  // vf<S> fname => voidfunc(S s) { fname(s) }
2390  
  jreplace(tok, "vf<<id>> <id>", "voidfunc($3 a) { $5(a) }");
2391  
  
2392  
  // vf<L<S>> fname => voidfunc(L<S> a) { fname(a) }
2393  
  jreplace(tok, "vf<<id><<id>>> <id>", "voidfunc($3<$5> a) { $8(a) }");
2394  
  
2395  
  // construct<S> Entry => func(S s) -> Entry { new Entry(s) }
2396  
  jreplace(tok, "construct<<id>> <id>", "func($3 a) -> $5 { new $5(a) }");
2397  
  
2398  
  // f<S> fname => func -> S { fname() }
2399  
  jreplace(tok, "f<<id>> <id>", "func -> $3 { $5() }");
2400  
  
2401  
  // f<S, S> fname => func(S x) -> S { fname(x) }
2402  
  jreplace(tok, "f<<id>, <id>> <id>", "func($3 x) -> $5 { $7(x) }");
2403  
  
2404  
  // f<S, L<S>> fname => func(S x) -> L<S> { fname(x) }
2405  
  jreplace(tok, "f<<id>, <id><<id>>> <id>", "func($3 x) -> $5 $6 $7 $8 { $10(x) }");
2406  
  
2407  
  // f<S, L<S>, S> fname => func(S x, L<S> y) -> S { fname(x, y) }
2408  
  jreplace(tok, "f<<id>, <id><<id>>, <id>> <id>", "func($3 x, $5 $6 $7 $8 y) -> $10 { $12(x, y) }");
2409  
  
2410  
  // if1 fname => a -> fname(a)
2411  
  jreplace_dyn(tok, "if1 <id>", func(LS tok, int i) -> S {
2412  
    S var = makeVar();
2413  
    ret var + " -> " + tok.get(i+2) + "(" + var + ")";
2414  
  });
2415  
}
2416  
2417  
static void quicknu(L<S> tok) {
2418  
  jreplace(tok, "nu <id>(", "nu($2.class, "); // not needed anymore
2419  
  jreplace(tok, "nu <id>", "new $2");
2420  
}
2421  
2422  
// fill variable innerClasses_list
2423  
static void innerClassesVar(L<S> tok, Set<S> have) {
2424  
  int i = jfind_check myInnerClasses_list(tok, ">myInnerClasses_list;");
2425  
  if (i < 0) ret;
2426  
  tok.set(i+4, "=litlist(\n" + joinQuoted(", ", have) + ");");
2427  
  reTok(tok, i+4, i+5);
2428  
}
2429  
2430  
// fill variable innerClasses_list
2431  
static void fillVar_transpilationDate(L<S> tok) {
2432  
  int i = jfind_check myTranspilationDate_value(tok, "long myTranspilationDate_value;");
2433  
  if (i < 0) ret;
2434  
  tok.set(i+4, " = " + now() + "L;");
2435  
  reTok(tok, i+4, i+5);
2436  
}
2437  
2438  
sbool ifclass_reTokImmediately = false;
2439  
2440  
// process ifclass x ... endif blocks
2441  
static void tok_ifclass(LS tok, Set<S> have) {
2442  
  tok_conditionals(tok, "ifclass", "endif", id -> contains(have, id), ifclass_reTokImmediately);
2443  
}
2444  
2445  
svoid tok_conditionals(LS tok, S keyword, S keywordEnd, IPred<S> pred, bool reTokImmediately) {
2446  
  L<IntRange> reToks = reTokImmediately ? null : new L;
2447  
  if (tok instanceof IContentsIndexedList) {
2448  
    int[] l = tok/IContentsIndexedList.indicesOf(keyword);
2449  
    for (int j = l(l)-1; j >= 0; j--) {
2450  
      int i = l[j];
2451  
      if (isIdentifier(get(tok, i+2)))
2452  
        processConditional(tok, i, keyword, keywordEnd, pred, reToks);
2453  
    }
2454  
  } else {
2455  
    if (!tok.contains(keyword)) ret;
2456  
    int i = l(tok);
2457  
    while ((i = rjfind(tok, 1, i-1, keyword + " <id>")) >= 0)
2458  
      processConditional(tok, i, keyword, keywordEnd, pred, reToks);
2459  
  }
2460  
  if (reToks != null) reTok_multi(tok, reToks);
2461  
}
2462  
2463  
svoid processConditional(LS tok, int i, S keyword, S keywordEnd, IPred<S> pred, L<IntRange> reToks) {
2464  
  int j = jfind(tok, i+4, keywordEnd);
2465  
  if (j < 0) j = l(tok)-1;
2466  
  S name = tok.get(i+2);
2467  
  bool has = pred.get(name);
2468  
  //print(keyword + " " + name + " => " + has);
2469  
  if (has) {
2470  
    clearTokens_addToReToksOrReTok(tok, j, j+1, reToks);
2471  
    clearTokens_addToReToksOrReTok(tok, i, i+3, reToks);
2472  
  } else
2473  
    clearTokens_addToReToksOrReTok(tok, i, j+1, reToks); // safer than before
2474  
}
2475  
2476  
// set flag *.
2477  
static void tok_definitions(L<S> tok) {
2478  
  int i;
2479  
  while ((i = jfind_check flag(tok, "set flag <id>.")) >= 0) {
2480  
    S fname = tok.get(i+4);
2481  
    print("Setting flag " + fname);
2482  
    definitions.add(fname);
2483  
    clearAllTokens(tok.subList(i, i+8));
2484  
  }
2485  
  
2486  
  while ((i = jfind_check flag(tok, "unset flag <id>.")) >= 0) {
2487  
    S fname = tok.get(i+4);
2488  
    print("Unsetting flag " + fname);
2489  
    definitions.remove(fname);
2490  
    clearAllTokens(tok.subList(i, i+8));
2491  
  }
2492  
}
2493  
2494  
static void tok_findRewrites(L<S> tok) {
2495  
  int i;
2496  
  while ((i = jfind(tok, "rewrite <id> =")) >= 0) {
2497  
    S token = tok.get(i+2);
2498  
    int repStart = i+6;
2499  
    int repEnd = smartIndexOf(tok, repStart, ".");
2500  
    S replacement = joinSubList(tok, repStart, repEnd-1);
2501  
    clearTokens(tok, i, repEnd+1);
2502  
    rewrites.put(token, replacement);
2503  
    print("Have rewrite: " + token + " => " + replacement);
2504  
  }
2505  
}
2506  
2507  
static void tok_processRewrites(L<S> tok) {
2508  
  for (S token : keys(rewrites))
2509  
    jreplace(tok, token, rewrites.get(token));
2510  
}
2511  
2512  
// extend *. (set base class of main class)
2513  
static void tok_extend(L<S> tok) {
2514  
  int i;
2515  
  while ((i = jfind(tok, "extend <id>.")) >= 0) {
2516  
    mainBaseClass = tok.get(i+2);
2517  
    clearAllTokens(tok, i, i+7);
2518  
  }
2519  
}
2520  
2521  
// process ifndef x ... endifndef blocks
2522  
static void tok_ifndef(LS tok) {
2523  
  tok_conditionals(tok, "ifndef", "endifndef", id -> !definitions.contains(id), true);
2524  
}
2525  
  
2526  
svoid tok_ifndef_old(L<S> tok) {
2527  
  if (!tok.contains("ifndef")) ret;
2528  
  
2529  
  int i;
2530  
  while ((i = rjfind(tok, "ifndef <id>")) >= 0) {
2531  
    int j = jfind(tok, i+4, "endifndef");
2532  
    if (j < 0) j = l(tok)-1;
2533  
    S fname = tok.get(i+2);
2534  
    bool has = !definitions.contains(fname);
2535  
    //print("ifndef " + fname + " => " + has);
2536  
    clearTokens(tok, i, i+3);
2537  
    clearTokens(tok, j, j+1);
2538  
    if (!has) clearTokens(tok, i+3, j);
2539  
    reTok(tok, i, j+1);
2540  
  }
2541  
}
2542  
2543  
// process ifdef x ... endifdef blocks
2544  
static void tok_ifdef(LS tok) {
2545  
  tok_conditionals(tok, "ifdef", "endifdef", id -> definitions.contains(id), true);
2546  
}
2547  
  
2548  
svoid tok_ifdef_old(LS tok) {
2549  
  if (!tok.contains("ifdef")) ret;
2550  
  
2551  
  int i;
2552  
  while ((i = rjfind(tok, "ifdef <id>")) >= 0) {
2553  
    int j = jfind(tok, i+4, "endifdef");
2554  
    if (j < 0) j = l(tok)-1;
2555  
    S fname = tok.get(i+2);
2556  
    bool has = definitions.contains(fname);
2557  
    //print("ifdef " + fname + " => " + has);
2558  
    clearTokens(tok, i, i+3);
2559  
    clearTokens(tok, j, j+1);
2560  
    if (!has) clearTokens(tok, i+3, j);
2561  
    reTok(tok, i, j+1);
2562  
  }
2563  
}
2564  
2565  
svoid conceptDeclarations(L<S> tok) {
2566  
  for (S kw : ll("concept", "sconcept")) {
2567  
    O cond = tokcondition { tok_addFieldOrder(tok, i+1); true; };
2568  
    bool re = false;
2569  
    if (jreplace(tok, kw + " <id> {", "static class $2 extends Concept {", cond)) re = true;
2570  
    if (jreplace(tok, kw + " <id> implements", "static class $2 extends Concept implements", cond)) re = true;
2571  
    if (jreplace(tok, kw + " <id>", "static class $2", cond)) re = true;
2572  
    if (re) reTok(tok);
2573  
  }
2574  
}
2575  
2576  
svoid shortenedSubconcepts(L<S> tok) {
2577  
  jreplace(tok, "<id> > <id> {", "concept $3 extends $1 {", tokcondition {
2578  
    bool b = (i == 0 || tok.get(i).contains("\n")) || eq(_get(tok, i-1), "abstract"); // only at beginning of line or after "abstract"
2579  
    //print("subconcept " + b + ": " + structure(subList(tok, i-1, i+5)));
2580  
    ret b;
2581  
  });
2582  
}
2583  
2584  
// -slightly experimental
2585  
// -do calculation in another thread, then return to AWT thread
2586  
// -must be placed in a block
2587  
// -transforms rest of block 
2588  
svoid unswing(L<S> tok) {
2589  
  int i;
2590  
  while ((i = jfind(tok, "unswing {")) >= 0) {
2591  
    int idx = i+2;
2592  
    int closingBracket = findEndOfBracketPart(tok, idx)-1;
2593  
    int endOfOuterBlock = findEndOfBracketPart(tok, closingBracket)-1;
2594  
    tok.set(i, "thread");
2595  
    tok.set(closingBracket, " awt {");
2596  
    tok.set(endOfOuterBlock, "}}}");
2597  
    reTok(tok, closingBracket-1, endOfOuterBlock+1);
2598  
  }
2599  
}
2600  
2601  
// -Syntax: lock theLock;
2602  
// -lock a lock, unlock at end of current block with finally
2603  
svoid lockBlocks(L<S> tok) {
2604  
  int i;
2605  
  while ((i = jfind(tok, "lock <id>", tokcondition { ret neq(tok.get(i+3), "instanceof"); })) >= 0) {
2606  
    int semicolon = findEndOfStatement(tok, i)-1;
2607  
    S var = makeVar();
2608  
    int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1;
2609  
    replaceTokens(tok, i, semicolon+1,
2610  
      "Lock " + var + " = " + joinSubList(tok, i+2, semicolon-1) + "; lock(" + var + "); try {");
2611  
    tok.set(endOfOuterBlock, "} finally { unlock(" + var + "); } }");
2612  
    reTok(tok, i, endOfOuterBlock+1);
2613  
  }
2614  
}
2615  
2616  
// -Syntax: temp Bla bla = bla();
2617  
// -expands to try(Bla bla = bla()) { ... } with rest of block inside
2618  
svoid tempBlocks(L<S> tok) {
2619  
  int i;
2620  
  while ((i = jfind(tok, "temp <id>")) >= 0) {
2621  
    int semicolon = findEndOfStatement(tok, i)-1;
2622  
    int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1;
2623  
    L<S> sub = subList(tok, i-1, semicolon);
2624  
    int eq = subList(sub, 0, smartIndexOfOneOf(sub, "{", "(")).indexOf("=");
2625  
    S var;
2626  
    if (eq >= 0)
2627  
      var = sub.get(eq-2);
2628  
    else {
2629  
      // no var name, e.g. temp newThoughtSpace();
2630  
      var = makeVar();
2631  
      tok.set(i+2, "AutoCloseable " + var + " = " + tok.get(i+2));
2632  
    }
2633  
      
2634  
    //tok.set(i, "try (");
2635  
    //tok.set(semicolon, ") {";
2636  
    //tok.set(endOfOuterBlock, "}}");
2637  
    
2638  
    tok.set(i, "");
2639  
    tok.set(semicolon, "; try {");
2640  
    tok.set(endOfOuterBlock, "} finally { _close(" + var + "); }}");
2641  
    
2642  
    reTok(tok, i, endOfOuterBlock+1);
2643  
  }
2644  
}
2645  
2646  
svoid forgetCachedIncludes {
2647  
  cachedIncludes.clear();
2648  
}
2649  
2650  
// TODO: when to do this / merge contents if there are multiple transpilers?
2651  
svoid cleanMeUp {
2652  
  for (CachedInclude ci : values(cachedIncludes))
2653  
    ci.clean();
2654  
  vmKeepWithProgramMD5_save('cachedIncludes);
2655  
}
2656  
2657  
svoid printSources(L<S> tok) {
2658  
  print("----");
2659  
  print(join(tok));
2660  
  print("----");
2661  
}
2662  
2663  
svoid tok_quickInstanceOf(L<S> tok, final Set<S> haveClasses) {
2664  
  if (!quickInstanceOfEnabled) ret;
2665  
  // "x << X" or "x >> X" => "x instanceof X"
2666  
  for (S op : ll("<<", ">>"))
2667  
    jreplace(tok, "<id> " + op + " <id>", "$1 instanceof $4", tokcondition {
2668  
      ret haveClasses.contains(tok.get(i+7))
2669  
        && !eqOneOf(tok.get(i-1), "<", "extends", "implements");
2670  
    });
2671  
}
2672  
2673  
sbool hasDef(S s) {
2674  
  ret definitions.contains(s);
2675  
}
2676  
2677  
svoid expandTriple(L<S> tok) {
2678  
  jreplace(tok, "T3< <id> >", "T3<$3, $3, $3>");
2679  
  jreplace(tok, "T3< <id><<id>> >", "T3<$3<$5>, $3<$5>, $3<$5>>");
2680  
}
2681  
2682  
svoid tok_shortFinals(L<S> tok) {
2683  
  jreplace(tok, "fS", "final S");
2684  
  jreplace(tok, "fO", "final O");
2685  
  jreplace(tok, "fL", "final L");
2686  
  jreplace(tok, "fMap", "final Map");
2687  
  jreplace(tok, "fRunnable", "final Runnable");
2688  
  jreplace(tok, "f int", "final int");
2689  
}
2690  
2691  
svoid tok_mainClassNameAndPackage(LS tok) {
2692  
  int i;
2693  
  if ((i = jfind(tok, "mainClassName <id>")) >= 0) {
2694  
    mainClassName = tok.get(i+2);
2695  
    if (eqGet(tok, i+4, ".") && isIdentifier(get(tok, i+6))) {
2696  
      mainPackage = mainClassName;
2697  
      mainClassName = tok.get(i+6);
2698  
      clearTokensAndReTok(tok, i, i+7);
2699  
    } else
2700  
      clearTokensAndReTok(tok, i, i+3);
2701  
  }
2702  
  
2703  
  if ((i = jfind(tok, "mainPackage <id>")) >= 0) {
2704  
    mainPackage = tok.get(i+2);
2705  
    clearTokens(tok, i, i+3);
2706  
    reTok(tok, i, i+3);
2707  
  }
2708  
}
2709  
2710  
svoid defineMapLikes(LS tok) {
2711  
  int i;
2712  
  while ((i = jfind(tok, "mapLike <id>")) >= 0) {
2713  
    mapLikeFunctions.add(tok.get(i+2));
2714  
    clearTokens_reTok(tok, i, i+2);
2715  
  }
2716  
}
2717  
2718  
svoid defineLambdaMapLikes(LS tok) {
2719  
  int i;
2720  
  while ((i = jfind(tok, "lambdaMapLike <id>")) >= 0) {
2721  
    lambdaMapLikeFunctions.add(tok.get(i+2));
2722  
    clearTokens_reTok(tok, i, i+2);
2723  
  }
2724  
}
2725  
2726  
svoid defineMapMethodLikes(LS tok) {
2727  
  int i;
2728  
  while ((i = jfind(tok, "mapMethodLike <id>")) >= 0) {
2729  
    mapMethodLikeFunctions.add(tok.get(i+2));
2730  
    clearTokens_reTok(tok, i, i+2);
2731  
  }
2732  
}
2733  
2734  
// functions that work like "nu" syntactically (accept a class as "super-first" parameter [left of the bracket])
2735  
svoid defineNuLikes(LS tok) {
2736  
  int i;
2737  
  while ((i = jfind(tok, "nuLike <id>")) >= 0) {
2738  
    nuLikeFunctions.add(tok.get(i+2));
2739  
    clearTokens_reTok(tok, i, i+2);
2740  
  }
2741  
}
2742  
2743  
svoid defineExtraSF(LS tok) {
2744  
  int i;
2745  
  IntRange reTok = null;
2746  
  while ((i = jfind(tok, "function <id> is in *.")) >= 0) {
2747  
    extraStandardFunctions.put(tok.get(i+2), fsI(unquote(tok.get(i+8))));
2748  
    clearTokens(tok, i, i+12);
2749  
    reTok = combineIntRanges(reTok, intRange(i, i+12));
2750  
  }
2751  
  reTok(tok, reTok);
2752  
}
2753  
2754  
sbool tok_applyMapLikeFunctions(LS tok, final Set<S> mapLikeFunctions) {
2755  
  // map funcname(...) => map(f funcname, ...)
2756  
  // filter funcname(...) => filter(f funcname, ...)
2757  
  // ...
2758  
  ret jreplace(tok, "<id> <id>(", "$1(f $2,", func(L<S> tok, int i) -> bool {
2759  
    contains(mapLikeFunctions, tok.get(i+1))
2760  
  });
2761  
}
2762  
2763  
sbool tok_applyLambdaMapLikeFunctions(LS tok, final Set<S> lambdaMapLikeFunctions) {
2764  
  // mapNonNulls funcname(...) => mapNonNulls(lambda1 funcname, ...)
2765  
  // mapKeysAndValues funcname(...) => mapKeysAndValues(lambda1 funcname, ...)
2766  
  // ...
2767  
  ret jreplace(tok, "<id> <id>(", "$1(lambda1 $2,", func(L<S> tok, int i) -> bool {
2768  
    contains(lambdaMapLikeFunctions, tok.get(i+1))
2769  
  });
2770  
}
2771  
2772  
sbool tok_applyMapMethodLikeFunctions(LS tok, final Set<S> mapMethodLikeFunctions) {
2773  
  // mapMethod funcname(...) => mapMethod('funcname, ...)
2774  
  // collect funcname(...) => collect('funcname, ...)
2775  
  // ...
2776  
  ret jreplace_dyn(tok, "<id> <id>(",
2777  
    func(L<S> tok, int cIdx) -> S { tok.get(cIdx) + "(" + quote(tok.get(cIdx+2)) + "," },
2778  
    func(L<S> tok, int i) -> bool {
2779  
      contains(mapMethodLikeFunctions, tok.get(i+1))
2780  
    });
2781  
}
2782  
2783  
svoid runMetaPostBlocks(LS tok) {
2784  
  for ping (S code : unnull(metaPostBlocks))
2785  
    call(hotwireCached(standardFunctionSnippet(assertIdentifier(code))), code, tok);
2786  
    //callF(codeToFunctionOnArbitraryType(code, "LS", L, "tok"), tok);
2787  
}
2788  
2789  
svoid runMetaTransformers(LS tok) {
2790  
  for ping (S code : unnull(metaTransformers))
2791  
    tok_runMetaTransformer(tok, code);
2792  
}
2793  
2794  
sbool tok_applyNuLikeFunctions(LS tok, final Set<S> nuLikeFunctions) {
2795  
  // nu ClassName(...) => nu(ClassName, ...)
2796  
  // ...
2797  
  ret jreplace_dyn(tok, "<id> <id>(",
2798  
    func(L<S> tok, int cIdx) -> S { tok.get(cIdx) + "(" + tok.get(cIdx+2) + ".class," },
2799  
    func(L<S> tok, int i) -> bool {
2800  
      contains(nuLikeFunctions, tok.get(i+1))
2801  
    });
2802  
}
2803  
2804  
sbool metaCodeAllowed() {
2805  
  ret allowMetaCode || containsIC(definitions, "allowMetaCode");
2806  
}
2807  
2808  
static LS indexTokenList(LS tok) {
2809  
  if (useIndexedList2) ret indexedList2(tok);
2810  
  if (useTokenIndexedList) ret tokenIndexedList3(tok);
2811  
  ret tok;
2812  
}
2813  
2814  
svoid tok_earlyGeneralStuff(LS tok) {
2815  
  tok_standardBot1(tok);
2816  
  tok_processSimplified(tok);
2817  
  tok_compactModules(tok);
2818  
}
2819  
2820  
svoid lambdaReferences(LS tok) {
2821  
  // lambda1 myFunction => var123 -> myFunction(var123)
2822  
  jreplace_dyn(tok, "lambda1 <id>", func(L<S> tok, int cIdx) {
2823  
    S var = makeVar();
2824  
    ret var + " -> " + tok.get(cIdx+2) + "(" + var + ")";
2825  
  });
2826  
}
2827  
2828  
svoid clearSnippetCache {
2829  
  snippetCache.clear();
2830  
  sf = null;
2831  
  lclasses = null;
2832  
}
2833  
2834  
svoid mediumRefresh {
2835  
  clearSnippetCache();
2836  
  print("Medium-refreshed transpiler " + mc());
2837  
}

Author comment

Began life as a copy of #759

download  show line numbers  debug dex  old transpilations   

Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1026023
Snippet name: #759 backup with reTok_multi in tok_conditionals (seems slower?)
Eternal ID of this version: #1026023/1
Text MD5: 70646b208142bb7d8b5e29324ffeb10c
Author: stefan
Category: javax
Type: JavaX source code (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-11-08 01:05:45
Source code size: 94791 bytes / 2837 lines
Pitched / IR pitched: No / No
Views / Downloads: 143 / 271
Referenced in: [show references]