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: | 702 / 781 |
| Version history: | 4 change(s) |
| Referenced in: | [show references] |