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

3290
LINES

< > BotCompany Repo | #759 // "Leading Edge" JavaX Translator (Extension of #7)

JavaX source code (desktop) [tags: use-pretranspiled] - run with: x30.jar

Download Jar. Uses 1176K of libraries. Click here for Pure Java version (35141L/234K).

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

Author comment

Began life as a copy of #752

download  show line numbers  debug dex  old transpilations   

Travelled to 33 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, cysqohhbtkwd, ddnzoavkxhuk, etmzoiygucik, etryasgzbotu, gsoxhkmxfcgg, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, iveijnkanddl, jtubtzbbkimh, lpdgvwnxivlt, mowyntqkapby, mqqgnosmbjvj, nbgitpuheiab, omdjrrnzbjjv, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, teubizvjbppd, tslmcundralx, tvejysmllsmz, unoaxrwscvea, vdyxwxlmubrt, vouqrxazstgt, wnsclhtenguj, xprdwmaupziu, xrpafgyirdlv, zudvenktlakg

No comments. add comment

Snippet ID: #759
Snippet name: "Leading Edge" JavaX Translator (Extension of #7)
Eternal ID of this version: #759/1552
Text MD5: 05b3abe3069849c7674ba2c8ae99c3b4
Transpilation MD5: 1bd9f5c334a971f10a95c086b25bc07b
Author: stefan
Category: javax
Type: JavaX source code (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-07-08 00:53:15
Source code size: 109400 bytes / 3290 lines
Pitched / IR pitched: No / No
Views / Downloads: 8809 / 94745
Version history: 1551 change(s)
Referenced in: [show references]