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