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