Libraryless. Click here for Pure Java version (13347L/95K/282K).
1 | !1006722 |
2 | |
3 | static bool autoQuine = true; |
4 | static int maxQuineLength = 80; |
5 | |
6 | static L<S> functionsToAlwaysInclude = ll("_registerThread"); |
7 | |
8 | !include #1001496 // Matches |
9 | !include #1000882 // EGDiff |
10 | !include #1000883 // BlockDiffer |
11 | !include #1001065 // DialoGIO |
12 | !include #1004045 // IndexedList2 |
13 | //include #1001296 // MultiMap |
14 | !include #1000988 // MultiSet |
15 | !include #1004543 // DynamicObject |
16 | !include #1005575 // CompilerBot |
17 | |
18 | !include #1002662 // isTrue |
19 | |
20 | static int varCount; |
21 | static new Map<S, S> snippetCache; |
22 | static bool useIndexedList = true, opt_javaTok = true; |
23 | |
24 | static new HashSet<Long> included; |
25 | static new HashSet<S> definitions; |
26 | static new HashSet<S> shouldNotIncludeFunction, shouldNotIncludeClass; |
27 | |
28 | p { |
29 | if (useIndexedList) findCodeTokens_debug = true; |
30 | javaTok_opt = opt_javaTok; |
31 | findCodeTokens_indexed = findCodeTokens_unindexed = 0; |
32 | findCodeTokens_bails = findCodeTokens_nonbails = 0; |
33 | javaTok_n = javaTok_elements = 0; |
34 | S in = loadMainJava(); |
35 | |
36 | print("759 STARTING " + identityHashCode(main.class)); |
37 | included.clear(); |
38 | shouldNotIncludeFunction.clear(); |
39 | shouldNotIncludeClass.clear(); |
40 | varCount = 0; |
41 | |
42 | //L ts = findTranslators(toLines(join(tok))); |
43 | //print("Translators in source at start: " + structure(ts)); |
44 | |
45 | // "duplicate" statement |
46 | |
47 | L<S> lines = toLines(in); |
48 | call(getJavaX(), "findTranslators", lines); |
49 | in = fromLines(lines); |
50 | new Matches m; |
51 | if (match("duplicate *", in, m)) { |
52 | // actual copying - unused |
53 | // tok = jtok(loadSnippet(m.get(0))); |
54 | |
55 | // reference by include() |
56 | in = "m { p { callMain(include(" + quote(m.get(0)) + ")); } }"; |
57 | } |
58 | |
59 | L<S> tok = jtok(in); |
60 | |
61 | // add m { } |
62 | |
63 | if (!hasCodeTokens(tok, "m", "{") && !hasCodeTokens(tok, "main", "{") && !hasCodeTokens(tok, "class", "main")) { |
64 | //tok = jtok(moveImportsUp("m {\n" + in + "\n}")); |
65 | replaceTokens_reTok(tok, 1, 2, "m {\n" + tok.get(1)); |
66 | replaceTokens_reTok(tok, l(tok)-2, l(tok)-1, tok.get(l(tok)-2) + "}"); |
67 | tok_moveImportsUp(tok); |
68 | } |
69 | |
70 | // standard translate |
71 | |
72 | //ts = findTranslators(toLines(join(tok))); |
73 | //print("Translators in source: " + structure(ts)); |
74 | tok = jtok(defaultTranslate(join(tok))); |
75 | |
76 | //print("end of default translate"); |
77 | //print(join(tok)); |
78 | |
79 | //tok_autoCloseBrackets(tok); |
80 | tok = processIncludes(tok); // before standard functions |
81 | processConceptsDot(tok); |
82 | tok = processIncludes(tok); |
83 | tok = localStuff1(tok); |
84 | |
85 | int safety = 0; |
86 | boolean same; |
87 | do { |
88 | S before = join(tok); |
89 | |
90 | // shortened method declarations BEFORE standardFunctions |
91 | jreplace(tok, "svoid", "static void"); |
92 | jreplace(tok, "void <id> {", "$1 $2() {"); |
93 | jreplace(tok, "String <id> {", "$1 $2() {"); |
94 | jreplace(tok, "Object <id> {", "$1 $2() {"); |
95 | jreplace(tok, "List <id> {", "$1 $2() {"); |
96 | |
97 | tok_definitions(tok); |
98 | tok_ifndef(tok); |
99 | tok_ifdef(tok); |
100 | tok = standardFunctions(tok); |
101 | tok = stdstuff(tok); // standard functions and all the keywords |
102 | S diff; |
103 | long startTime = now(); |
104 | //diff = unidiff(before, join(tok)); |
105 | //print("unidiff: " + (now()-startTime) + " ms"); |
106 | //same = eq(diff, ""); |
107 | same = eq(before, join(tok)); // << could be sped up |
108 | if (!same) { |
109 | print("Not same " + safety + "."); |
110 | //print(indent(2, diff)); |
111 | } |
112 | if (safety++ >= 10) { |
113 | //print(unidiff(before, join(tok))); |
114 | print("----"); |
115 | print(join(tok)); |
116 | print("----"); |
117 | fail("safety 10 error!"); |
118 | } |
119 | } while (!same); |
120 | |
121 | // POST-PROCESSING after stdstuff loop |
122 | |
123 | for (S clazz : ll("Pair", "Either")) { |
124 | jreplace(tok, clazz + "< <id> >", clazz + "<$3, $3>"); |
125 | jreplace(tok, clazz + "< <id><<id>> >", clazz + "<$3<$5>, $3<$5>>"); |
126 | jreplace(tok, clazz + "< <id><<id>,<id>> >", clazz + "<$3<$5,$7>, $3<$5,$7>>"); |
127 | } |
128 | |
129 | quicknew2(tok); |
130 | //tok = jtok(quicknew(join(tok))); |
131 | tok = extendClasses(tok); |
132 | libs(tok); |
133 | sourceCodeLine(tok); |
134 | throwFail(tok); |
135 | innerClassesVar(tok); |
136 | tok_ifclass(tok); |
137 | |
138 | // Stuff that depends on the list of inner classes (haveClasses) |
139 | HashSet<S> haveClasses = haveClasses(tok); |
140 | expandClassReferences(tok, haveClasses); |
141 | slashCasts(tok, haveClasses); |
142 | newWithoutNew(tok, haveClasses); |
143 | |
144 | tok = autoImports(tok); // faster to do it at the end |
145 | |
146 | /*if (useIndexedList) |
147 | print("Indexed/unindexed lookups: " + findCodeTokens_indexed + "/" + findCodeTokens_unindexed + ", lists made: " + IndexedList2.instances); |
148 | print("findCodeToken bails: " + findCodeTokens_bails + "/" + findCodeTokens_nonbails); |
149 | print("javaToks: " + javaTok_n + "/" + javaTok_elements);*/ |
150 | |
151 | if (tok.contains("package")) |
152 | splitJavaFiles(tok); |
153 | else |
154 | saveMainJava(tok); |
155 | } |
156 | |
157 | static L<S> localStuff1(L<S> tok) { |
158 | int safety = 0, i; |
159 | boolean same; |
160 | do { |
161 | S before = join(tok); |
162 | |
163 | earlyStuff(tok); |
164 | |
165 | replaceKeywordBlock(tok, |
166 | "swing", |
167 | "{ swing(r {", |
168 | "}); }"); |
169 | |
170 | jreplace(tok, "synced <id>", "synchronized $2"); |
171 | |
172 | replaceKeywordBlock(tok, "answer", |
173 | "static S answer(S s) {\nfinal new Matches m;\n", |
174 | "\nret null;\n}"); |
175 | |
176 | replaceKeywordBlock(tok, "static-pcall", |
177 | "static { pcall {", |
178 | "}}"); |
179 | |
180 | replaceKeywordBlock(tok, "loading", |
181 | "{ JWindow _loading_window = showLoadingAnimation(); try { /* loading try */ ", |
182 | "/* loading try */ } finally { disposeWindow(_loading_window); }\n /* loading end */ } /* after loading */ \n"); |
183 | |
184 | replaceKeywordBlock(tok, "html", |
185 | "static O html(S uri, fMap<S, S> params) ctex " + "{\n", "}"); |
186 | |
187 | // "static sync" => static synchronized |
188 | jreplace(tok, "static sync", "static synchronized"); |
189 | |
190 | // "sclass" => static class |
191 | jreplace(tok, "sclass", "static class"); |
192 | |
193 | // "asclass" => abstract static class |
194 | jreplace(tok, "asclass", "abstract static class"); |
195 | |
196 | // "sinterface" => static interface |
197 | jreplace(tok, "sinterface", "static interface"); |
198 | |
199 | // "ssynchronized" => static synchronized |
200 | jreplace(tok, "ssynchronized", "static synchronized"); |
201 | |
202 | jreplace(tok, "ssvoid", "static synchronized void"); |
203 | jreplace(tok, "sbool", "static bool"); |
204 | jreplace(tok, "sint", "static int"); |
205 | jreplace(tok, "snew", "static new"); |
206 | jreplace(tok, "sv <id>", "static void $2"); |
207 | jreplace(tok, "pvoid", "public void"); |
208 | |
209 | // "sS" => static S |
210 | jreplace(tok, "sS", "static S"); |
211 | |
212 | // "sO" => static O |
213 | jreplace(tok, "sO", "static O"); |
214 | |
215 | // "sL" => static L |
216 | jreplace(tok, "sL", "static L"); |
217 | |
218 | // "toString {" => "public S toString() {" |
219 | jreplace(tok, "toString {", "public S toString() {"); |
220 | |
221 | jreplace(tok, "Int", "Integer"); |
222 | jreplace(tok, "Bool", "Boolean"); |
223 | jreplace(tok, "BigInt", "BigInteger"); |
224 | jreplace(tok, "Char", "Character"); |
225 | |
226 | // I REALLY wanted to avoid this, but eh... |
227 | jreplace(tok, "SS", "Map<S, S>"); |
228 | |
229 | // "on fail {" => "catch (Throwable _e) { ... rethrow(_e); }" |
230 | replaceKeywordBlock(tok, "on fail", |
231 | "catch (Throwable _e) {", |
232 | "\nthrow rethrow(_e); }"); |
233 | |
234 | // "catch {" => "catch (Throwable _e) {" |
235 | jreplace(tok, "catch {", "catch (Throwable _e) {"); |
236 | |
237 | // "catch X e {" => "catch (X e) {" |
238 | jreplace(tok, "catch <id> <id> {", "catch ($2 $3) {"); |
239 | |
240 | // "catch e {" => "catch (Throwable e) {" (if e is lowercase) |
241 | jreplace(tok, "catch <id> {", "catch (Throwable $2) {", new O() { |
242 | bool get(L<S> tok, int i) { |
243 | S word = tok.get(i+3); |
244 | ret startsWithLowerCaseOrUnderscore(word); |
245 | } |
246 | }); |
247 | |
248 | jreplace(tok, "+ +", "+", new O() { |
249 | bool get(L<S> tok, int i) { |
250 | //printStructure("++: ", subList(tok, i-1, i+6)); |
251 | if (empty(_get(tok, i+2))) ret false; // no space between the pluses |
252 | if (empty(_get(tok, i)) && eq("+", _get(tok, i-1))) ret false; // an actual "++" at the left |
253 | if (empty(_get(tok, i+4)) && eq("+", _get(tok, i+5))) ret false; // an actual "++" at the right |
254 | //print("doing it"); |
255 | ret true; |
256 | } |
257 | }); |
258 | |
259 | // some crazy fancy syntax |
260 | jreplace(tok, "set <id>;", "$2 = true;"); |
261 | |
262 | // [stdEq] -> implementation of equals() and hashCode() |
263 | jreplace(tok, "[stdEq]", |
264 | "public bool equals(O o) { ret stdEq2(this, o); }\n" + |
265 | "public int hashCode() { ret stdHash2(this); }"); |
266 | |
267 | // [concepts] "concept.field!" for dereferencing references |
268 | |
269 | jreplace(tok, "<id>!", "$1.get()", func(L<S> tok, int i) { |
270 | if (tok.get(i+2).contains("\n")) false; // no line break between <id> and ! |
271 | if (nempty(tok.get(i+4))) true; // space after = ok |
272 | S t = _get(tok, i+5); |
273 | if (t == null) ret false; |
274 | if (isIdentifier(t) || eqOneOf(t, "=", "(")) false; |
275 | true; |
276 | }); |
277 | |
278 | // [concepts] "field := value" for defining fields e.g. in "uniq" |
279 | while ((i = jfind(tok, "<id> :=")) >= 0) { |
280 | tok.set(i, quote(tok.get(i))); |
281 | tok.set(i+2, ","); |
282 | tok.set(i+4, ""); |
283 | reTok(tok, i, i+5); |
284 | } |
285 | |
286 | // "quoted" := value |
287 | while ((i = jfind(tok, "<quoted> :=")) >= 0) { |
288 | tok.set(i, tok.get(i)); |
289 | tok.set(i+2, ","); |
290 | tok.set(i+4, ""); |
291 | reTok(tok, i, i+5); |
292 | } |
293 | |
294 | // more shortening |
295 | |
296 | jreplace(tok, "fS", "final S"); |
297 | jreplace(tok, "fO", "final O"); |
298 | jreplace(tok, "fL", "final L"); |
299 | jreplace(tok, "fMap", "final Map"); |
300 | jreplace(tok, "fRunnable", "final Runnable"); |
301 | jreplace(tok, "f int", "final int"); |
302 | |
303 | // "continue unless" |
304 | |
305 | while ((i = jfind(tok, "continue unless")) >= 0) { |
306 | int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); |
307 | replaceTokens(tok, i, i+4, "{ if (!("); |
308 | tok.set(j, ")) continue; }"); |
309 | reTok(tok, i, j+1); |
310 | } |
311 | |
312 | // "continue if" |
313 | |
314 | while ((i = jfind(tok, "continue if")) >= 0) { |
315 | int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); |
316 | replaceTokens(tok, i, i+4, "{ if ("); |
317 | tok.set(j, ") continue; }"); |
318 | reTok(tok, i, j+1); |
319 | } |
320 | |
321 | // "return if" |
322 | |
323 | while ((i = jfind(tok, "return if")) >= 0) { |
324 | int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); |
325 | replaceTokens(tok, i, i+4, "{ if ("); |
326 | tok.set(j, ") return; }"); |
327 | reTok(tok, i, j+1); |
328 | } |
329 | |
330 | // while not null () |
331 | |
332 | while ((i = jfind(tok, "while not null (")) >= 0) { |
333 | int closingBracket = findEndOfBracketPart(tok, i+6)-1; |
334 | replaceTokens(tok, i+2, i+6, "("); |
335 | tok.set(closingBracket, ") != null)"); |
336 | reTok(tok, i, closingBracket+1); |
337 | } |
338 | |
339 | // Replace $1 with m.unq(0) etc. - caveat: this blocks identifiers $1, $2, ... |
340 | for (i = 1; i < l(tok); i += 2) { |
341 | S s = tok.get(i); |
342 | if (s.startsWith("$")) { |
343 | s = substring(s, 1); |
344 | if (isInteger(s)) { |
345 | tok.set(i, "m.unq(" + (parseInt(s)-1) + ")"); |
346 | reTok(tok, i); |
347 | } |
348 | } |
349 | } |
350 | |
351 | // instanceof trickery |
352 | |
353 | jreplace(tok, "is a <id>", "instanceof $3"); |
354 | jreplace(tok, "!<id> instanceof <id>.<id>", "!($2 instanceof $4.$6)"); |
355 | jreplace(tok, "!<id> instanceof <id>", "!($2 instanceof $4)"); |
356 | jreplace(tok, "<id> !instanceof <id>", "!($1 instanceof $4)"); |
357 | |
358 | // map funcname(...) => map(f funcname, ...) |
359 | |
360 | jreplace(tok, "map <id>(", "map(f $2,"); |
361 | |
362 | // func keyword for lambdas - now automatically quines toString() if enabled |
363 | |
364 | while ((i = jfind(tok, "func(")) >= 0) { |
365 | int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); |
366 | int idx = findCodeTokens(tok, argsTo, false, "{"); |
367 | int j = findEndOfBracketPart(tok, idx); |
368 | L<S> contents = subList(tok, idx+1, j-1); |
369 | |
370 | S returnType = null; |
371 | if (eq(tok.get(argsTo+2), "-") && eq(tok.get(argsTo+4), ">")) |
372 | returnType = join(subList(tok, argsTo+6, idx-1)); |
373 | |
374 | S toString = autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : ""; |
375 | |
376 | // TODO: infer argument types |
377 | /* if (nempty(returnType)) |
378 | replaceTokens(tok, i, j, "new F1<?, " + returnType + ">{ " + returnType + " get(" + join(subList(tok, argsFrom, argsTo-1)) + ") ctex { " + tok_addReturn(contents) + " }\n" +*/ |
379 | replaceTokens(tok, i, j, "new O { O get(" + join(subList(tok, argsFrom, argsTo-1)) + ") ctex { " + tok_addReturn(contents) + " }\n" + |
380 | + toString + "}"); |
381 | reTok(tok, i, j); |
382 | } |
383 | |
384 | while ((i = jfind(tok, "voidfunc(")) >= 0) { |
385 | int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); |
386 | int idx = findCodeTokens(tok, argsTo, false, "{"); |
387 | int j = findEndOfBracketPart(tok, idx); |
388 | L<S> contents = subList(tok, idx+1, j-1); |
389 | replaceTokens(tok, i, j, "new O { void get(" + join(subList(tok, argsFrom, argsTo-1)) + ") ct" + "ex { " + tok_addSemicolon(contents) + " }\n" + |
390 | (autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}"); |
391 | reTok(tok, i, j); |
392 | } |
393 | |
394 | for (S keyword : ll("f", "func")) { |
395 | while ((i = jfind(tok, keyword + " {")) >= 0) { |
396 | int idx = findCodeTokens(tok, i, false, "{"); |
397 | int j = findEndOfBracketPart(tok, idx+2); // XXX - not idx??? |
398 | L<S> contents = subList(tok, idx+1, j-1); |
399 | replaceTokens(tok, i, j, "new O { O get() ct" + "ex { " + tok_addReturn(contents) + " }\n" + |
400 | (autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}"); |
401 | reTok(tok, i, j); |
402 | } |
403 | |
404 | while ((i = jfind(tok, keyword + " ->")) >= 0) { |
405 | int idx = findCodeTokens(tok, i, false, "{"); |
406 | int j = findEndOfBracketPart(tok, idx); |
407 | S returnType = join(subList(tok, i+6, idx-1)); |
408 | L<S> contents = subList(tok, idx+1, j-1); |
409 | replaceTokens(tok, i, j, "new F0<" + returnType + ">() { " + returnType + " get() ctex { " + tok_addReturn(contents) + " }\n" + |
410 | (autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}"); |
411 | reTok(tok, i, j); |
412 | } |
413 | } |
414 | |
415 | // "ref -> bla" for dereferencing Concept.Ref or ThreadLocal or other |
416 | //jreplace(tok, "<id> ->", "$1.get()."); |
417 | jreplace(tok, "->", ".get().", func(L<S> tok, int i) { |
418 | empty(tok.get(i+2)) |
419 | && !(empty(_get(tok, i)) && eq(_get(tok, i-1), "-")) // i-->0 |
420 | }); |
421 | |
422 | // shortened subconcept declaration (before star constructors!) |
423 | shortenedSubconcepts(tok); |
424 | |
425 | // "case" as a variable name ( => _case) |
426 | |
427 | caseAsVariableName(tok); |
428 | |
429 | // "do" as a function name ( => dO) |
430 | |
431 | tok_doAsMethodName(tok); |
432 | |
433 | // "continue" as a function name ( => _continue) |
434 | continueAsFunctionName(tok); |
435 | |
436 | // Do this BEFORE awt replacement! ("p-awt" contains "awt" token) |
437 | if (hasCodeTokens(tok, "p", "-")) { |
438 | jreplace(tok, "p-pretty {", "p-noconsole {"); |
439 | replaceKeywordBlock(tok, "p-awt-noconsole", "p-awt {", "\nhideConsole(); }"); |
440 | replaceKeywordBlock(tok, "p-substance-noconsole", "p-substance {", "\nhideConsole(); }"); |
441 | replaceKeywordBlock(tok, "p-nimbus-noconsole", "p-nimbus {", "\nhideConsole(); }"); |
442 | replaceKeywordBlock(tok, "p-subst-noconsole", "p-subst {", "\nhideConsole(); }"); |
443 | replaceKeywordBlock(tok, "p-noconsole", "p-subst {", "\nhideConsole(); }"); |
444 | replaceKeywordBlock(tok, "p-subst", "p-substance-thread {", "}"); |
445 | replaceKeywordBlock(tok, "p-substance-thread", "p { substance();", "}"); |
446 | replaceKeywordBlock(tok, "p-magellan-thread", "p { magellan();", "}"); |
447 | replaceKeywordBlock(tok, "p-substance", "p-awt { substance();", "}"); |
448 | replaceKeywordBlock(tok, "p-nimbus", "p-awt { nimbus();", "}"); |
449 | jreplace(tok, "p-type {", "p-typewriter {"); |
450 | jreplace(tok, "p-tt {", "p-typewriter {"); |
451 | replaceKeywordBlock(tok, "p-awt", "p { swing {", "}}"); |
452 | replaceKeywordBlock(tok, "p-typewriter", "p { typeWriterConsole();", "}"); |
453 | replaceKeywordBlock(tok, "p-lowprio", "p { lowPriorityThread(r " + "{", "}); }"); |
454 | tok_p_repeatWithSleep(tok); |
455 | } |
456 | |
457 | replaceKeywordBlock(tok, |
458 | "awt", |
459 | "swingLater(r {", |
460 | "});"); |
461 | |
462 | unswing(tok); |
463 | lockBlocks(tok); |
464 | |
465 | // crazy stuff |
466 | |
467 | jreplace (tok, "for <id> over <id>:", "for (int $2 = 0; $2 < l($4); $2++)"); |
468 | jreplace (tok, "for <id>, <id> <id> over <id>: {", "for (int $2 = 0; $2 < l($7); $2++) { $4 $5 = $7.get($2);"); |
469 | jreplace (tok, "for <id> to <id>:", "for (int $2 = 0; $2 < $4; $2++)"); |
470 | jreplace (tok, "for <id> to <int>:", "for (int $2 = 0; $2 < $4; $2++)"); |
471 | |
472 | same = eq(before, join(tok)); // << could be sped up |
473 | if (!same) |
474 | print("local not same " + safety + "."); |
475 | if (safety++ >= 10) { |
476 | print("----"); |
477 | print(join(tok)); |
478 | print("----"); |
479 | fail("safety 10 error!"); |
480 | } |
481 | } while (!same); |
482 | |
483 | ret tok; |
484 | } |
485 | |
486 | static L<S> reTok_include(L<S> tok, int i, int j) { |
487 | ret reTok_modify(tok, i, j, f localStuff1); |
488 | } |
489 | |
490 | static L<S> includeInMainLoaded_reTok(L<S> tok, int i, int j) { |
491 | ret reTok_include(tok, i, j); |
492 | } |
493 | |
494 | static L<S> stdstuff(L<S> tok) { |
495 | //if (++level >= 10) fail("woot? 10"); |
496 | |
497 | print("stdstuff!"); |
498 | int i; |
499 | |
500 | if (jfind(tok, "!<int>") >= 0) { |
501 | L<S> lines = toLines(join(tok)); |
502 | L ts = findTranslators(lines); |
503 | tok = jtok(fromLines(lines)); |
504 | print("DROPPING TRANSLATORS: " + structure(ts)); |
505 | } |
506 | |
507 | tok = quickmain(tok); |
508 | tok = processIncludes(tok); |
509 | processConceptsDot(tok); |
510 | tok = processIncludes(tok); |
511 | tok = multilineStrings(tok); |
512 | tok_singleQuoteIdentifiersToStringConstants(tok); |
513 | inStringEvals(tok); |
514 | listComprehensions(tok); |
515 | doubleFor_simple(tok); |
516 | forPing(tok); |
517 | directSnippetRefs(tok); |
518 | quicknu(tok); |
519 | //tok_juxtaposeCalls(tok); |
520 | |
521 | conceptDeclarations(tok); |
522 | |
523 | // * constructors |
524 | if (hasCodeTokens(tok, "\\*", "(")) |
525 | tok = expandStarConstructors(tok); |
526 | |
527 | // STANDARD CLASSES & INTERFACES |
528 | |
529 | S sc = cacheGet("#1003674"); |
530 | new L<S> lclasses; |
531 | for (S line : toLinesFullTrim(sc)) { |
532 | line = javaDropComments(line).trim(); |
533 | int idx = line.indexOf('/'); |
534 | lclasses.addAll(ll(line.substring(0, idx), line.substring(idx+1))); |
535 | } |
536 | |
537 | final Set<S> haveClasses = addStandardClasses(tok, toStringArray(lclasses)); |
538 | |
539 | if (tok.contains("Triple") && !haveClasses.contains("Triple")) |
540 | jreplace(tok, "Triple", "T3"); |
541 | |
542 | // "x << X" or "x >> X" => "x instanceof X" |
543 | for (S op : ll("<<", ">>")) |
544 | jreplace(tok, "<id> " + op + " <id>", "$1 instanceof $4", func(L<S> tok, int i) { |
545 | haveClasses.contains(tok.get(i+7)) |
546 | }); |
547 | |
548 | expandVarCopies(tok); |
549 | |
550 | // concept-related stuff |
551 | |
552 | // auto-import concepts |
553 | bool _a = tok_hasClassRef2(tok, /*"extends",*/ "Concept") || tok_hasClassRef2(tok, "Concepts"), _b = !haveClasses.contains("Concept"); |
554 | //print("auto-import: " + _a + ", " + _b); |
555 | if (_a && _b) { |
556 | print("Auto-including concepts."); |
557 | if (shouldNotIncludeClass.contains("Concepts")) { |
558 | print(join(tok)); |
559 | fail("Unwanted concepts import"); |
560 | } |
561 | printStruct(haveClasses); |
562 | tok = includeInMainLoaded(tok, "concepts."); |
563 | reTok(tok, l(tok)-1, l(tok)); |
564 | //processConceptsDot(tok); |
565 | } |
566 | |
567 | jreplace(tok, "for (<id> <id>)", "for ($3 $4 : list($3))"); |
568 | jreplace(tok, "for (final <id> <id>)", "for (final $4 $5 : list($4))"); |
569 | |
570 | // the infamous missing functions (usually caused by class Matches) |
571 | // maybe not needed anymore? |
572 | if (!hasCodeTokens(tok, "String", "unquote") && containsToken(tok, "unquote")) { |
573 | print("Adding unquote"); |
574 | tok = includeInMain(tok, "#1001735"); |
575 | } |
576 | |
577 | if (!hasCodeTokens(tok, "String", "formatSnippetID") && containsToken(tok, "formatSnippetID")) { |
578 | print("Adding formatSnippetID"); |
579 | tok = includeInMain(tok, "#1000709"); |
580 | } |
581 | |
582 | tok = expandShortTypes(tok); |
583 | |
584 | if (containsToken(tok, "cast")) { |
585 | S s = join(tok); |
586 | s = s.replaceAll("(\\w+<[\\w\\s,\\[\\]]+>|\\w+|\\w+\\[\\]|\\w+\\[\\]\\[\\])\\s+(\\w+)\\s*=\\s*cast(\\W[^;]*);", "$1 $2 = ($1) ($3);"); |
587 | tok = jtok(s); |
588 | } |
589 | |
590 | replaceKeywordBlock(tok, "r-thread", "runnableThread(r " + "{", "})"); |
591 | rNamedThread(tok); |
592 | |
593 | // runnable and r - now also with automatic toString if enabled |
594 | for (S keyword : ll("runnable", "r")) |
595 | while ((i = jfind(tok, keyword + " {")) >= 0) { |
596 | int idx = findCodeTokens(tok, i, false, "{"); |
597 | int j = findEndOfBracketPart(tok, idx); |
598 | L<S> contents = subList(tok, idx+1, j-1); |
599 | //print("r contents: " + structure(contents)); |
600 | replaceTokens(tok, i, j+1, "new Runnable() { public void run() { try { " + tok_addSemicolon(contents) + |
601 | "\n} catch (Exception __e) { throw rethrow(__e); } }" + |
602 | (autoQuine ? " public S toString() { return " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + |
603 | "}"); |
604 | reTok(tok, i, j+1); |
605 | } |
606 | |
607 | replaceKeywordBlock(tok, |
608 | "expectException", |
609 | "{ bool __ok = false; try {", |
610 | "} catch { __ok = true; } assertTrue(\"expected exception\", __ok); }"); |
611 | |
612 | while ((i = tok.indexOf("tex")) >= 0) { |
613 | tok.set(i, "throws Exception"); |
614 | tok = jtok(tok); |
615 | } |
616 | |
617 | // shorter & smarter whiles |
618 | |
619 | jreplace(tok, "while true", "while (true)"); |
620 | jreplace(tok, "while licensed", "while (licensed())"); |
621 | jreplace(tok, "repeat {", "while (licensed()) {"); |
622 | tok_repeatWithSleep(tok); |
623 | |
624 | // null; => return null; etc. |
625 | |
626 | O cond = func(L<S> tok, int i) { |
627 | tok_tokenBeforeLonelyReturnValue(_get(tok, i-1)) |
628 | }; |
629 | jreplace(tok, "null;", "return null;", cond); |
630 | jreplace(tok, "false;", "return false;", cond); |
631 | jreplace(tok, "true;", "return true;", cond); |
632 | jreplace(tok, "this;", "return this;", cond); |
633 | |
634 | // "myFunction;" instead of "myFunction();" - quite rough |
635 | cond = new O() { |
636 | bool get(L<S> tok, int i) { |
637 | S word = tok.get(i+3); |
638 | //print("single word: " + word); |
639 | ret !litlist("break", "continue", "return", "else").contains(word); |
640 | } |
641 | }; |
642 | for (S pre : litlist("}", ";")) |
643 | jreplace(tok, pre + " <id>;", "$1 $2();", cond); |
644 | |
645 | // shorter match syntax for answer methods |
646 | |
647 | jreplace(tok, "if <quoted> || <quoted>", |
648 | "if (matchOneOf(s, m, $2, $5))"); |
649 | // "bla..." |
650 | jreplace(tok, "if <quoted>", "if (matchStartX($2, s, m))", |
651 | new O() { bool get(L<S> tok, int i) { |
652 | ret unquote(tok.get(i+3)).endsWith("..."); |
653 | }}); |
654 | |
655 | // "bla * bla | blubb * blubb" |
656 | jreplace_dyn(tok, "if <quoted>", func(L<S> tok, int cIdx) { |
657 | S s = unquote(tok.get(cIdx+2)); |
658 | //print("multimatch: " + quote(s)); |
659 | new L<S> l; |
660 | for (S pat : splitAtJavaToken(s, "|")) { |
661 | //print("multimatch part: " + quote(pat)); |
662 | if (javaTok(pat).contains("*")) |
663 | l.add("match(" + quote(trim(pat)) + ", s, m)"); |
664 | else |
665 | l.add("match(" + quote(trim(pat)) + ", s)"); |
666 | } |
667 | ret "if (" + join(" || ", l) + ")"; |
668 | }, func(L<S> tok, int i) { |
669 | javaTokC(unquote(tok.get(i+3))).contains("|") |
670 | }); |
671 | |
672 | // "bla * bla" |
673 | jreplace(tok, "if <quoted>", "if (match($2, s))", |
674 | new O() { bool get(L<S> tok, int i) { |
675 | ret !javaTokC(unquote(tok.get(i+3))).contains("*"); |
676 | }}); |
677 | // "bla" |
678 | jreplace(tok, "if <quoted>", "if (match($2, s, m))"); |
679 | jreplace(tok, "if match <quoted>", "if (match($3, s, m))"); |
680 | |
681 | // extra commas ("litlist(1, 2,)") |
682 | |
683 | jreplace(tok, ",)", ")"); |
684 | |
685 | // additional translations (if necessary) |
686 | |
687 | replaceKeywordBlock(tok, |
688 | "pcall", |
689 | "try {", |
690 | "} catch (Throwable __e) { printStackTrace2(__e); }"); |
691 | |
692 | replaceKeywordBlock(tok, |
693 | "pcall-short", |
694 | "try {", |
695 | "} catch (Throwable __e) { print(exceptionToStringShort(__e)); }"); |
696 | |
697 | replaceKeywordBlock(tok, |
698 | "pcall-silent", |
699 | "try {", |
700 | "} catch (Throwable __e) { silentException(__e); }"); |
701 | |
702 | replaceKeywordBlock(tok, |
703 | "pcall-messagebox", |
704 | "try {", |
705 | "} catch __e { messageBox(__e); }"); |
706 | |
707 | replaceKeywordBlock(tok, |
708 | "pcall-infobox", |
709 | "try {", |
710 | "} catch __e { infoBox(__e); }"); |
711 | |
712 | tok = dialogHandler(tok); |
713 | |
714 | replaceKeywordBlock(tok, "exceptionToUser", |
715 | "try {", |
716 | "} catch (Throwable __e) { ret exceptionToUser(__e); }"); |
717 | |
718 | if (hasCodeTokens(tok, "twice", "{")) |
719 | replaceKeywordBlock(tok, "twice", |
720 | "for (int __twice = 0; __twice < 2; __twice++) {", |
721 | "}"); |
722 | |
723 | while ((i = findCodeTokens(tok, "repeat", "*", "{")) >= 0) { |
724 | S v = makeVar("repeat"); |
725 | tok.set(i, "for (int " + v + " = 0; " + v + " < " + tok.get(i+2) + "; " + v + "++)"); |
726 | tok.set(i+2, ""); |
727 | tok = jtok(tok); |
728 | } |
729 | |
730 | replaceKeywordBlockDyn(tok, |
731 | "time", |
732 | new O() { S[] get() { |
733 | S var = makeVar("startTime"); |
734 | ret new S[] { |
735 | "{ long " + var + " = sysNow(); try { ", |
736 | "} finally { " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); } }"}; |
737 | }}); |
738 | |
739 | // version without { } |
740 | replaceKeywordBlockDyn(tok, |
741 | "time2", |
742 | new O() { S[] get() { |
743 | S var = makeVar("startTime"); |
744 | ret new S[] { |
745 | "long " + var + " = sysNow(); ", |
746 | " " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); "}; |
747 | }}); |
748 | |
749 | // time "bla" { |
750 | replaceKeywordPlusQuotedBlock(tok, |
751 | "time", |
752 | func(L<S> tok, int i) { |
753 | S var = makeVar("startTime"); |
754 | ret new S[] { |
755 | "long " + var + " = sysNow(); ", |
756 | " done2(" + tok.get(i+2) + ", " + var + "); "}; |
757 | }); |
758 | |
759 | if (hasCodeTokens(tok, "assertFail", "{")) { |
760 | S var = makeVar("oops"); |
761 | |
762 | replaceKeywordBlock(tok, |
763 | "assertFail", |
764 | "boolean " + var + " = false; try {", |
765 | "\n" + var + " = true; } catch (Exception e) { /* ok */ } assertFalse(" + var + ");"); |
766 | } |
767 | |
768 | replaceKeywordBlock(tok, |
769 | "yo", |
770 | "try {", |
771 | "} catch (Exception " + makeVar("e") + ") { ret false; }"); |
772 | |
773 | replaceKeywordBlock(tok, |
774 | "awtIfNecessary", |
775 | "swingNowOrLater(r " + "{", |
776 | "});"); |
777 | |
778 | ctex(tok); |
779 | |
780 | replaceKeywordBlock(tok, |
781 | "actionListener", |
782 | "new java.awt.event.ActionListener() { " + |
783 | "public void actionPerformed(java.awt.event.ActionEvent _evt) {", |
784 | "}}"); |
785 | |
786 | namedThreads(tok); |
787 | threads(tok); |
788 | |
789 | // try answer |
790 | while ((i = findCodeTokens(tok, "try", "answer")) >= 0) { |
791 | int j = findEndOfStatement(tok, i); |
792 | S v = makeVar("a"); |
793 | tok.set(i, "{ S " + v); |
794 | tok.set(i+2, "="); |
795 | tok.set(j-1, "; if (!empty(" + v + ")) ret " + v + "; }"); |
796 | tok = jtok(tok); |
797 | } |
798 | |
799 | // return optional (return if not null) |
800 | while ((i = jfind(tok, "return optional <id> =")) >= 0) { |
801 | int j = findEndOfStatement(tok, i); |
802 | S v = tok.get(i+4); |
803 | clearTokens(tok, i+2, i+4); |
804 | tok.set(i, "{"); |
805 | tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); |
806 | tok = jtok(tok); |
807 | } |
808 | |
809 | functionReferences(tok); |
810 | |
811 | tok_moveImportsUp(tok); |
812 | /*S moved = moveImportsUp2(join(tok)); |
813 | if (moved != null) tok = jtok(moved);*/ |
814 | |
815 | ret tok; |
816 | } // end of stdStuff! |
817 | |
818 | static L<S> multilineStrings(L<S> tok) { |
819 | for (int i = 1; i < tok.size(); i += 2) { |
820 | S t = tok.get(i); |
821 | if (isQuoted(t)) |
822 | if (t.startsWith("[") || t.contains("\r") || t.contains("\n")) |
823 | tok.set(i, quote(unquote(t))); |
824 | } |
825 | ret tok; |
826 | } |
827 | |
828 | static void inStringEvals(L<S> tok) { |
829 | bool change = false; |
830 | for (int i = 1; i < tok.size(); i += 2) { |
831 | S t = tok.get(i); |
832 | if (!isQuoted(t)) continue; |
833 | if (t.contains("\\*") && !t.contains("\\\\")) { // << rough |
834 | tok.set(i, inStringEval(t)); |
835 | change = true; |
836 | } |
837 | } |
838 | if (change) reTok(tok); |
839 | } |
840 | |
841 | static S inStringEval(S t) { |
842 | t = dropPrefix("\"", dropSuffix("\"", t)); |
843 | new L<S> l; |
844 | int idx; |
845 | while ((idx = t.indexOf("\\*")) >= 0) { |
846 | int j = indexOf(t, idx, "*/"); |
847 | if (j < 0) break; |
848 | if (idx > 0) |
849 | l.add("\"" + substring(t, 0, idx) + "\""); |
850 | l.add("(" + trim(substring(t, idx+2, j)) + ")"); |
851 | t = substring(t, j+2); |
852 | } |
853 | if (nempty(t)) |
854 | l.add("\"" + t + "\""); |
855 | ret "(" + join(" + ", l) + ")"; |
856 | } |
857 | |
858 | static L<S> quickmain(L<S> tok) { |
859 | bool change = false; |
860 | |
861 | int i = findCodeTokens(tok, "main", "{"); |
862 | if (i < 0) i = findCodeTokens(tok, "m", "{"); |
863 | if (i >= 0 && !(i-2 > 0 && tok.get(i-2).equals("class"))) { |
864 | tok.set(i, "class main"); |
865 | change = true; |
866 | } |
867 | |
868 | i = findCodeTokens(tok, "psvm", "{"); |
869 | if (i < 0) i = findCodeTokens(tok, "p", "{"); |
870 | if (i >= 0) { |
871 | int idx = i+2; |
872 | int j = findEndOfBracketPart(tok, idx); |
873 | L<S> contents = subList(tok, idx+1, j-1); |
874 | tok.set(i, "public static void main(final String[] args) throws Exception"); |
875 | replaceTokens(tok, idx+1, j-1, tok_addSemicolon(contents)); |
876 | change = true; |
877 | } |
878 | |
879 | ret change ? jtok(tok) : tok; |
880 | } |
881 | |
882 | static S makeVar(S name) { |
883 | ret "_" + name + "_" + varCount++; |
884 | } |
885 | |
886 | static S makeVar() { ret makeVar(""); } |
887 | |
888 | /*static L<S> standardFunctions(L<S> tok) { |
889 | ret rtq(tok, "#1002474"); |
890 | }*/ |
891 | |
892 | static L<S> rtq(L<S> tok, S id) { |
893 | ret runTranslatorQuick(tok, id); |
894 | } |
895 | |
896 | static L<S> expandShortTypes(L<S> tok) { |
897 | // replace <int> with <Integer> |
898 | for (int i = 1; i+4 < tok.size(); i += 2) |
899 | if (tok.get(i).equals("<") |
900 | && litlist(">", ",").contains(tok.get(i+4))) { |
901 | String type = tok.get(i+2); |
902 | if (type.equals("int")) type = "Integer"; |
903 | else if (type.equals("long")) type = "Long"; |
904 | tok.set(i+2, type); |
905 | } |
906 | |
907 | // O = Object, S = String, ret = return |
908 | for (int i = 1; i < tok.size(); i += 2) { |
909 | String t = tok.get(i); |
910 | if (t.equals("O")) t = "Object"; |
911 | if (t.equals("S")) t = "String"; |
912 | else if (t.equals("L")) t = "List"; |
913 | //else if (t.equals("F")) t = "Function"; |
914 | else if (t.equals("ret")) t = "return"; |
915 | 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 |
916 | tok.set(i, t); |
917 | } |
918 | |
919 | jreplace(tok, "LL< <id> >", "L<L<$3>>"); |
920 | |
921 | ret tok; |
922 | } |
923 | |
924 | static L<S> autoImports(L<S> tok) { |
925 | S s = join(tok); |
926 | List<String> imports = findImports(s); |
927 | new StringBuilder buf; |
928 | for (String c : standardImports) |
929 | if (!(imports.contains(c))) |
930 | buf.append("import " + c + ";\n"); |
931 | if (buf.length() == 0) ret tok; |
932 | ret jtok(buf+s); |
933 | } |
934 | |
935 | static String[] standardImports = { |
936 | "java.util.*", |
937 | "java.util.zip.*", |
938 | "java.util.List", |
939 | "java.util.regex.*", |
940 | "java.util.concurrent.*", |
941 | "java.util.concurrent.atomic.*", |
942 | "java.util.concurrent.locks.*", |
943 | "javax.swing.*", |
944 | "javax.swing.event.*", |
945 | "javax.swing.text.*", |
946 | "javax.swing.table.*", |
947 | "java.io.*", |
948 | "java.net.*", |
949 | "java.lang.reflect.*", |
950 | "java.lang.ref.*", |
951 | "java.lang.management.*", |
952 | "java.security.*", |
953 | "java.security.spec.*", |
954 | "java.awt.*", |
955 | "java.awt.event.*", |
956 | "java.awt.image.*", |
957 | "javax.imageio.*", |
958 | "java.math.*" |
959 | }; |
960 | |
961 | static L<S> expandStarConstructors(L<S> tok) { |
962 | mainLoop: for (int i = 3; i+6 < tok.size(); i += 2) { |
963 | String t = tok.get(i), l = tok.get(i-2); |
964 | if (!t.equals("*")) |
965 | continue; |
966 | if (!tok.get(i+2).equals("(")) |
967 | continue; |
968 | if (!eqOneOf(l, "}", "public", "private", "protected", ";", "{", "endif") && neq(get(tok, i-4), "ifclass")) // is this correct...?? |
969 | continue; |
970 | |
971 | // ok, it seems like a constructor declaration. |
972 | // Now find class name by going backwards. |
973 | |
974 | int j = i, level = 1; |
975 | while (j > 0 && level > 0) { |
976 | t = tok.get(j); |
977 | if (t.equals("}")) ++level; |
978 | if (t.equals("{")) --level; |
979 | j -= 2; |
980 | } |
981 | |
982 | while (j > 0) { |
983 | t = tok.get(j); |
984 | if (t.equals("class")) { |
985 | String className = tok.get(j+2); |
986 | tok.set(i, className); // exchange constructor name! |
987 | |
988 | // now for the parameters. |
989 | // Syntax: *(Learner *learner) { |
990 | // We will surely add type inference here in time... :) |
991 | |
992 | j = i+2; |
993 | while (!tok.get(j).equals("{")) |
994 | j += 2; |
995 | int block = j+1; |
996 | for (int k = i+2; k < block-1; k += 2) |
997 | if (tok.get(k).equals("*")) { |
998 | tok.remove(k); |
999 | tok.remove(k); |
1000 | block -= 2; |
1001 | String name = tok.get(k); |
1002 | tok.addAll(block, Arrays.asList(new String[] { |
1003 | "\n ", "this", "", ".", "", name, " ", "=", " ", name, "", ";" })); |
1004 | } |
1005 | |
1006 | continue mainLoop; |
1007 | } |
1008 | j -= 2; |
1009 | } |
1010 | } |
1011 | ret tok; |
1012 | } |
1013 | |
1014 | static L<S> processIncludes(L<S> tok) { |
1015 | int safety = 0; |
1016 | while (hasCodeTokens(tok, "!", "include") && ++safety < 100) |
1017 | tok = processIncludesSingle(tok); |
1018 | |
1019 | //tok_autoCloseBrackets(tok); |
1020 | ret tok; |
1021 | } |
1022 | |
1023 | static L<S> processIncludesSingle(L<S> tok) { |
1024 | int i; |
1025 | while ((i = jfind(tok, "!include #<int>")) >= 0) { |
1026 | S id = tok.get(i+6); |
1027 | included.add(parseLong(id)); |
1028 | replaceTokens(tok, i, i+8, "\n" + loadSnippet(id) + "\n"); |
1029 | reTok_include(tok, i, i+8); |
1030 | } |
1031 | while ((i = jfind(tok, "!include once #<int>")) >= 0) { |
1032 | S id = tok.get(i+8); |
1033 | bool isNew = included.add(parseLong(id)); |
1034 | replaceTokens(tok, i, i+10, |
1035 | isNew ? "\n" + loadSnippet(id) + "\n" : ""); |
1036 | reTok_include(tok, i, i+10); |
1037 | } |
1038 | ret tok; |
1039 | } |
1040 | |
1041 | static void ctex(L<S> tok) { |
1042 | replaceKeywordBlock(tok, "ctex", |
1043 | "{ try {", |
1044 | "} catch (Exception __e) { throw rethrow(__e); } }"); |
1045 | replaceKeywordBlock(tok, "null on exception", |
1046 | "{ try {", |
1047 | "} catch (Throwable __e) { return null; } }"); |
1048 | replaceKeywordBlock(tok, "false on exception", |
1049 | "{ try {", |
1050 | "} catch (Throwable __e) { return false; } }"); |
1051 | } |
1052 | |
1053 | static L<S> dialogHandler(L<S> tok) { |
1054 | ret replaceKeywordBlock(tok, |
1055 | "dialogHandler", |
1056 | "new DialogHandler() {\n" + |
1057 | "public void run(final DialogIO io) {", |
1058 | "}}"); |
1059 | } |
1060 | |
1061 | static void quicknew2(L<S> tok) { |
1062 | jreplace(tok, "new <id> <id>;", "$2 $3 = new $2;"); |
1063 | jreplace(tok, "new <id><<id>> <id>;", "$2<$4> $6 = new $2;"); |
1064 | jreplace(tok, "new <id><<id>> <id>, <id>;", "$2<$4> $6 = new $2, $8 = new $2;"); |
1065 | jreplace(tok, "new <id><<id>,<id>> <id>;", "$2<$4,$6> $8 = new $2;"); |
1066 | jreplace(tok, "new <id><<id><<id>>> <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 = new $2;"); |
1067 | jreplace(tok, "new <id>< <id><<id>,<id>> > <id>;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;"); |
1068 | |
1069 | // [abandoned, confusing, looks like a function definition] with arguments - new A a(...); => A a = new A(...); |
1070 | //jreplace(tok, "new <id> <id>(", "$2 $3 = new $2("); |
1071 | |
1072 | jreplace(tok, "for args " + "{", "for (int i = 0; i < args.length; i++) { final String arg = args[i];"); |
1073 | |
1074 | // Constructor calls without parentheses |
1075 | // So you can say something like: predictors.add(new P1); |
1076 | |
1077 | jreplace1(tok, "new <id>", "new $2()", func(L<S> tok, int i) { |
1078 | eqOneOf(_get(tok, i+5), "{", ",", ")", ";", ":") |
1079 | }); |
1080 | |
1081 | jreplace(tok, "new List(", "new ArrayList("); |
1082 | jreplace(tok, "new Map(", "new HashMap("); |
1083 | jreplace(tok, "new Set(", "new HashSet("); |
1084 | jreplace(tok, "\\*<id>[<id>] <id>;", "$2[] $6 = new $2[$4];"); |
1085 | |
1086 | // X x = new(...) => X x = new X(...) |
1087 | // X x = new => X x = new |
1088 | jreplace(tok, "<id> <id> = new", "$1 $2 = new $1", func(L<S> tok, int i) { |
1089 | eqOneOf(_get(tok, i+9), "(", ";", ",", ")") |
1090 | }); |
1091 | jreplace(tok, "<id> <id> = new \\*", "$1 $2 = new $1"); |
1092 | jreplace(tok, "\\* <id> = new <id>", "$5 $2 = new $5"); |
1093 | jreplace(tok, "<id><<id>> <id> = new", "$1 $2 $3 $4 $5 = new $1", func(L<S> tok, int i) { |
1094 | eqOneOf(_get(tok, i+9+3*2), "(", ";", ",", ")") |
1095 | }); |
1096 | jreplace(tok, "<id><<id>,<id>> <id> = new", "$1 $2 $3 $4 $5 $6 $7 = new $1", func(L<S> tok, int i) { |
1097 | eqOneOf(_get(tok, i+9+5*2), "(", ";", ",", ")") |
1098 | }); |
1099 | } |
1100 | |
1101 | static L<S> extendClasses(L<S> tok) { |
1102 | int i; |
1103 | while ((i = jfind(tok, "extend <id> {")) >= 0) { |
1104 | S className = tok.get(i+2); |
1105 | int idx = findCodeTokens(tok, i, false, "{"); |
1106 | int j = findEndOfBracketPart(tok, idx+2); |
1107 | S content = join(subList(tok, idx+1, j-1)); |
1108 | L<S> c = findInnerClassOfMain(tok, className); |
1109 | //print("Extending class " + className + " ==> " + join(c)); |
1110 | clearTokens(tok.subList(i, j+1)); |
1111 | if (c == null) { |
1112 | print("Warning: Can't extend class " + className + ", not found"); |
1113 | continue; |
1114 | } |
1115 | int startOfClass = indexOfSubList(tok, c); // magicIndexOfSubList is broken |
1116 | int endOfClass = startOfClass + l(c)-1; |
1117 | //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass))); |
1118 | while (neq(tok.get(endOfClass), "}")) --endOfClass; |
1119 | //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass))); |
1120 | tok.set(endOfClass, content + "\n" + tok.get(endOfClass)); |
1121 | reTok(tok); // changed in 2 places, let's retok it all |
1122 | } |
1123 | ret tok; |
1124 | } |
1125 | |
1126 | static void listComprehensions(L<S> tok) { |
1127 | int i; |
1128 | for (S op : ll(":", "in")) |
1129 | while ((i = jfind(tok, "[<id> <id> " + op)) >= 0) { |
1130 | Map<Integer, Integer> bracketMap = getBracketMap(tok); // XXX - optimize |
1131 | S type = tok.get(i+2), id = tok.get(i+4); |
1132 | int j = scanOverExpression(tok, bracketMap, i+8, "|"); |
1133 | S exp = join(tok.subList(i+8, j)); |
1134 | j += 2; |
1135 | int k = scanOverExpression(tok, bracketMap, j, "]"); |
1136 | S where = join(tok.subList(j, k)); |
1137 | ++k; |
1138 | |
1139 | S code = "filter(" + exp + ", func(" + type + " " + id + ") { " + where + " })"; |
1140 | replaceTokens(tok, i, k, code); |
1141 | reTok(tok, i, k); |
1142 | } |
1143 | } |
1144 | |
1145 | /* complicated version - TODO */ |
1146 | // for (S key, S value : map) |
1147 | /*static void doubleFor(L<S> tok) { |
1148 | int i; |
1149 | while ((i = jfind(tok, "for (<id> <id>, <id> <id> :")) >= 0) { |
1150 | int iComma = indexOf(tok, ",", i); |
1151 | S valType = tok.get(iComma+2); |
1152 | S valName = tok.get(iComma+4); |
1153 | int expStart = indexOf(tok, ":", i)+2; |
1154 | int expEnd = findEndOfBracketPart(expStart-2); |
1155 | assertEquals(")", tok.get(expEnd)); |
1156 | assertEquals("{", tok.get(expEnd+2)); |
1157 | replaceTokens(tok, iComma, expStart, ": keys("); |
1158 | tok.set(expEnd, "))"); |
1159 | tok.set(expEnd+2, "{ " + valType + " " + valName + " = " + |
1160 | S type = tok.get(i+2), id = tok.get(i+4); |
1161 | int j = scanOverExpression(tok, bracketMap, i+8, "|"); |
1162 | S exp = join(tok.subList(i+8, j)); |
1163 | j += 2; |
1164 | int k = scanOverExpression(tok, bracketMap, j, "]"); |
1165 | S where = join(tok.subList(j, k)); |
1166 | ++k; |
1167 | |
1168 | S code = "filter(" + exp + ", func(" + type + " " + id + ") { " + where + " })"; |
1169 | replaceTokens(tok, i, k, code); |
1170 | reTok(tok, i, k); |
1171 | } |
1172 | }*/ |
1173 | |
1174 | static void doubleFor_simple(L<S> tok) { |
1175 | jreplace(tok, "for (<id> <id>, <id> <id> : <id>) {", |
1176 | "for ($3 $4 : keys($9)) { $6 $7 = $9.get($4);"); |
1177 | jreplace(tok, "for (<id> <id>, <id> : <id>) {", |
1178 | "for ($3 $4 : keys($8)) { $3 $6 = $8.get($4);"); |
1179 | } |
1180 | |
1181 | static void forPing(L<S> tok) { |
1182 | int i, safety = 0; |
1183 | while ((i = jfind(tok, "for ping (")) >= 0) { |
1184 | if (++safety >= 10) fail("safety"); |
1185 | int bracketEnd = findEndOfBracketPart(tok, i+4)-1; |
1186 | if (neq("{", tok.get(bracketEnd+2))) |
1187 | fail("Please use { with 'for ping' : " + joinSubList(tok, i+4, bracketEnd+3)); |
1188 | tokSet(tok, bracketEnd+2, "{ ping();"); |
1189 | tokSet(tok, i+2, ""); |
1190 | } |
1191 | } |
1192 | |
1193 | // lib 123 => !123 |
1194 | static void libs(L<S> tok) { |
1195 | new TreeSet<S> libs; |
1196 | int i; |
1197 | while ((i = jfind(tok, "lib <int>")) >= 0) { |
1198 | S id = tok.get(i+2); |
1199 | print("lib " + id); |
1200 | if (!libs.contains(id)) { |
1201 | libs.add(id); |
1202 | tok.set(i, "!"); |
1203 | tok.set(i+1, ""); |
1204 | } else { |
1205 | print("...ignoring (duplicate)"); |
1206 | clearAllTokens(tok, i, i+3); |
1207 | reTok(tok, i, i+3); |
1208 | } |
1209 | } |
1210 | } |
1211 | |
1212 | // sourceCodeLine() => 1234 |
1213 | static void sourceCodeLine(L<S> tok) { |
1214 | int i ; |
1215 | while ((i = jfind(tok, "sourceCodeLine()")) >= 0) { |
1216 | replaceTokens(tok, i, i+5, str(countChar(join(subList(tok, 0, i)), '\n')+1)); |
1217 | reTok(tok, i, i+5); |
1218 | } |
1219 | } |
1220 | |
1221 | // done before any other processing |
1222 | static void earlyStuff(L<S> tok) { |
1223 | int i; |
1224 | |
1225 | tok_autosemi(tok); |
1226 | tok_autoCloseBrackets(tok); |
1227 | jreplace(tok, "°", "()"); |
1228 | |
1229 | // Note: this makes the word "quine" a special operator |
1230 | // (unusable as a function name) |
1231 | |
1232 | while ((i = jfind(tok, "quine(")) >= 0) { |
1233 | int idx = findCodeTokens(tok, i, false, "("); |
1234 | int j = findEndOfBracketPart(tok, idx+2); |
1235 | tok.set(i, "new Quine"); |
1236 | tok.set(idx, "(" + quote(join(subList(tok, idx+1, j-1))) + ", "); |
1237 | reTok(tok, i, idx+1); |
1238 | } |
1239 | } |
1240 | |
1241 | static void throwFail(L<S> tok) { |
1242 | bool anyChange = false; |
1243 | for (int i = 1; i+2 < l(tok); i += 2) |
1244 | if (eq(get(tok, i+2), "fail") && !eqOneOf(get(tok, i), "throw", "RuntimeException", "return")) { |
1245 | tok.set(i+2, "throw fail"); |
1246 | anyChange = true; |
1247 | } |
1248 | if (anyChange) |
1249 | reTok(tok); |
1250 | } |
1251 | |
1252 | static void namedThreads(L<S> tok) { |
1253 | for (int i = 0; i < 100; i++) { |
1254 | int idx = findCodeTokens(tok, "thread", "<quoted>", "{"); |
1255 | if (idx < 0) idx = findCodeTokens(tok, "thread", "<id>", "{"); |
1256 | if (idx < 0) |
1257 | break; |
1258 | int j = findEndOfBracketPart(tok, idx+4); |
1259 | S tName = tok.get(idx+2); |
1260 | |
1261 | S var = "_t_" + i; |
1262 | S pre = "{ Thread " + var + " = new Thread(" + tName + ") {\n" + |
1263 | "public void run() { pcall {\n"; |
1264 | S post = "} }\n};\n" + |
1265 | "startThread(" + var + "); }"; |
1266 | |
1267 | tok.set(idx, pre); |
1268 | tok.set(idx+2, ""); |
1269 | tok.set(idx+4, ""); |
1270 | tok.set(j-1, post); |
1271 | //print(join(subList(tok, idx, j))); |
1272 | reTok(tok, idx, j); |
1273 | } |
1274 | } |
1275 | |
1276 | static void rNamedThread(L<S> tok) { |
1277 | for (int i = 0; i < 100; i++) { |
1278 | int idx = findCodeTokens(tok, "r", "-", "thread", "<quoted>", "{"); |
1279 | if (idx < 0) idx = findCodeTokens(tok, "r", "-", "thread", "<id>", "{"); |
1280 | if (idx < 0) |
1281 | break; |
1282 | int j = findEndOfBracketPart(tok, idx+8); |
1283 | S tName = tok.get(idx+6); |
1284 | |
1285 | S pre = "r { thread " + tName + " {"; |
1286 | S post = "}}"; |
1287 | |
1288 | replaceTokens(tok, idx, idx+9, pre); |
1289 | tok.set(j-1, post); |
1290 | reTok(tok, idx, j); |
1291 | } |
1292 | } |
1293 | |
1294 | static void threads(L<S> tok) { |
1295 | for (bool daemon : litlist(false, true)) |
1296 | for (int i = 0; i < 100; i++) { |
1297 | int idx = findCodeTokens(tok, daemon ? "daemon" : "thread", "{"); |
1298 | if (idx < 0) |
1299 | break; |
1300 | int j = findEndOfBracketPart(tok, idx+2); |
1301 | |
1302 | S var = "_t_" + i; |
1303 | S pre = "{ Thread " + var + " = new Thread() {\n" + |
1304 | "public void run() { pcall\n"; |
1305 | S post = "} }\n};\n" + |
1306 | (daemon ? var + ".setDaemon(true);\n" : "") + |
1307 | "startThread(" + var + "); }"; |
1308 | |
1309 | tok.set(idx, pre); |
1310 | tok.set(j-1, post); |
1311 | reTok(tok, idx, j); |
1312 | } |
1313 | } |
1314 | |
1315 | static Map<S, S> sf; |
1316 | static Bool _761ok; |
1317 | |
1318 | static L<S> standardFunctions(L<S> tok) { |
1319 | if (sf == null) { |
1320 | S _761 = cacheGet("#761"); |
1321 | if (_761ok == null) |
1322 | _761ok = isBracketHygienic(_761); |
1323 | assertTrue("Whoa! #761 truncated?", _761ok); |
1324 | L<S> standardFunctions = concatLists( |
1325 | (L) loadVariableDefinition(_761, "standardFunctions"), |
1326 | (L) loadVariableDefinition(cacheGet("#1006654"), "standardFunctions")); |
1327 | |
1328 | sf = new HashMap(); |
1329 | for (String x : standardFunctions) { |
1330 | String[] f = x.split("/"); |
1331 | sf.put(f[1], f[0]); |
1332 | } |
1333 | } |
1334 | |
1335 | for (int i = 0; ; i++) { |
1336 | Set<String> defd = new HashSet(findFunctions(tok)); |
1337 | |
1338 | int j; |
1339 | while ((j = jfind(tok, "should not include function *.")) >= 0) { |
1340 | S fname = tok.get(j+8); |
1341 | shouldNotIncludeFunction.add(fname); |
1342 | clearAllTokens(tok.subList(j, j+12)); |
1343 | } |
1344 | |
1345 | // changes tok |
1346 | Set<String> invocations = findFunctionInvocations(tok, sf); |
1347 | invocations.addAll(functionsToAlwaysInclude); |
1348 | |
1349 | //print("Functions invoked: " + structure(invocations)); |
1350 | List<String> needed = diff(invocations, defd); |
1351 | if (needed.isEmpty()) |
1352 | break; |
1353 | print("Adding functions: " + join(" " , needed)); |
1354 | |
1355 | Collection<S> bad = setIntersection(new HashSet(needed), shouldNotIncludeFunction); |
1356 | if (nempty(bad)) { |
1357 | S msg = "INCLUDING BAD FUNCTIONS: " + sfu(bad); |
1358 | print(msg); |
1359 | print(join(tok)); |
1360 | fail(msg); |
1361 | } |
1362 | |
1363 | new L<S> added; |
1364 | new StringBuilder buf; |
1365 | new L<S> preload; |
1366 | |
1367 | for (S x : needed) |
1368 | if (sf.containsKey(x)) |
1369 | preload.add(sf.get(x)); |
1370 | cachePreload(preload); |
1371 | |
1372 | for (String x : cloneList(needed)) { |
1373 | if (defd.contains(x)) continue; |
1374 | |
1375 | String id = sf.get(x); |
1376 | if (id == null) { |
1377 | print("Standard function " + x + " not found."); |
1378 | needed.remove(x); |
1379 | continue; |
1380 | } |
1381 | //print("Adding function: " + x + " (" + id + ")"); |
1382 | |
1383 | S function = cacheGet(id); |
1384 | if (("\n" + function).contains("\n!")) print("Warning: " + id + " contains translators."); |
1385 | |
1386 | buf.append(function).append("\n"); |
1387 | added.add(x); |
1388 | defd.addAll(findFunctionDefs(javaTok(function))); |
1389 | } |
1390 | tok = includeInMainLoaded(tok, str(buf)); |
1391 | // defd = new HashSet(findFunctions(tok)); |
1392 | //print("Functions added: " + structure(added)); |
1393 | |
1394 | for (String x : needed) |
1395 | if (!defd.contains(x)) { |
1396 | print(join(tok)); |
1397 | fail("Function not defined properly: " + x); |
1398 | } |
1399 | //print("Iteration " + (i+2)); |
1400 | |
1401 | tok_definitions(tok); |
1402 | tok_ifndef(tok); |
1403 | tok_ifdef(tok); |
1404 | |
1405 | if (i >= 1000) fail("Too many iterations"); |
1406 | } |
1407 | |
1408 | ret tok; |
1409 | } |
1410 | |
1411 | static L<S> findFunctions(L<S> tok) { |
1412 | //ret findFunctionDefinitions(join(findMainClass(tok))); |
1413 | ret findFunctionDefs(findMainClass(tok)); |
1414 | } |
1415 | |
1416 | static S cacheGet(S snippetID) { |
1417 | snippetID = formatSnippetID(snippetID); |
1418 | S text = snippetCache.get(snippetID); |
1419 | if (text == null) |
1420 | snippetCache.put(snippetID, text = loadSnippet(snippetID)); |
1421 | ret text; |
1422 | } |
1423 | |
1424 | static void cachePreload(L<S> ids) { |
1425 | new L<S> needed; |
1426 | for (S id : ids) |
1427 | if (!snippetCache.containsKey(formatSnippetID(id))) |
1428 | needed.add(formatSnippetID(id)); |
1429 | if (l(needed) > 1) { |
1430 | L<S> texts = loadSnippets(needed); |
1431 | for (int i = 0; i < l(needed); i++) |
1432 | if (texts.get(i) != null) |
1433 | snippetCache.put(needed.get(i), texts.get(i)); |
1434 | } |
1435 | } |
1436 | |
1437 | static L<S> jtok(L<S> tok) { |
1438 | ret jtok(join(tok)); |
1439 | } |
1440 | |
1441 | static L<S> jtok(S s) { |
1442 | L<S> l = javaTok(s); |
1443 | ret useIndexedList ? new IndexedList2(l) : l; |
1444 | } |
1445 | |
1446 | static HashSet<S> haveClasses(L<S> tok) { |
1447 | new HashSet<S> have; |
1448 | for (L<S> c : innerClassesOfMain(tok)) |
1449 | have.add(getClassDeclarationName(c)); |
1450 | have.addAll(tok_importedClassNames(tok)); |
1451 | have.add("String"); |
1452 | ret have; |
1453 | } |
1454 | |
1455 | // works on Java level (no "sclass" etc) |
1456 | // returns list of classes we have (useful for other processing) |
1457 | static Set<S> addStandardClasses(L<S> tok, S... data) { |
1458 | HashSet<S> have = haveClasses(tok); |
1459 | |
1460 | int j; |
1461 | while ((j = jfind(tok, "should not include class *.")) >= 0) { |
1462 | S cname = tok.get(j+8); |
1463 | shouldNotIncludeClass.add(cname); |
1464 | clearAllTokens(tok.subList(j, j+12)); |
1465 | } |
1466 | |
1467 | //L<S> idx = IndexedList2.ensureIndexed(tok); |
1468 | Set<S> idx = tokenIndexWithoutIfclass(tok); |
1469 | for (int i = 0; i+1 < l(data); i++) { |
1470 | S className = data[i], snippetID = data[i+1]; |
1471 | if (idx.contains(className) |
1472 | && !have.contains(className)) { |
1473 | |
1474 | if (shouldNotIncludeClass.contains(className)) { |
1475 | S msg = "INCLUDING BAD CLASS: " + className; |
1476 | print(msg); |
1477 | print(join(tok)); |
1478 | fail(msg); |
1479 | } |
1480 | |
1481 | print("Adding class " + className + " / " + snippetID); |
1482 | snippetID = formatSnippetID(snippetID); |
1483 | S text = cacheGet(snippetID); |
1484 | includeInMainLoaded(tok, text); |
1485 | L<S> ct = javaTok(text); |
1486 | shortenedSubconcepts(ct); |
1487 | conceptDeclarations(ct); |
1488 | jreplace(ct, "sclass", "static class"); |
1489 | jreplace(ct, "sinterface", "static interface"); |
1490 | //tok_autoCloseBrackets(ct); |
1491 | for (L<S> c : allClasses(ct)) |
1492 | have.add(getClassDeclarationName(c)); |
1493 | if (!have.contains(className)) |
1494 | fail("Wrongly defined class: " + className + " / " + snippetID); |
1495 | } |
1496 | } |
1497 | |
1498 | ret have; |
1499 | } |
1500 | |
1501 | static Set<S> expandableClassNames = lithashset("BigInteger"); |
1502 | |
1503 | // magically append ".class" to class name references |
1504 | static void expandClassReferences(L<S> tok, Set<S> classNames) { |
1505 | bool change = false; |
1506 | for (int i = 3; i+2 < l(tok); i += 2) { |
1507 | S t = tok.get(i); |
1508 | if (classNames.contains(t) || expandableClassNames.contains(t)) { |
1509 | S s = tok.get(i-2); t = tok.get(i+2); |
1510 | if (eqOneOf(s, "instanceof", "new", ".", "<", ">", "implements", "throws", "extends", "/", "nu")) continue; |
1511 | if (isIdentifier(s) || isInteger(s)) continue; |
1512 | if (eq(s, ",") && isIdentifier(get(tok, i-4)) && eqGet(tok, i-6, "<")) continue; // e.g. T3<S, S, S> |
1513 | if (eq(s, ",") && eqOneOf(_get(tok, i-6), "implements", "throws")) continue; |
1514 | // TODO: longer lists |
1515 | |
1516 | // check for cast |
1517 | if (eq(s, "(") && eq(t, ")") && i >= 5) { |
1518 | if (!eqOneOf(get(tok, i+4), "{", ";")) { |
1519 | S x = tok.get(i-4); |
1520 | if (!isIdentifier(x)) continue; |
1521 | if (eqOneOf(x, "ret", "return")) continue; |
1522 | } |
1523 | } |
1524 | if (eqOneOf(t, ",", ")", ";", ":")) { |
1525 | tok.set(i, tok.get(i) + ".class"); |
1526 | change = true; |
1527 | } |
1528 | } |
1529 | } |
1530 | if (change) reTok(tok); |
1531 | } |
1532 | |
1533 | // "<id>/<ClassName>" => "((ClassName) <id>)" |
1534 | static void slashCasts(L<S> tok, final Set<S> classNames) { |
1535 | jreplace(tok, "<id>/<id>", "(($3) $1)", new O() { |
1536 | O get(L<S> tok, int i) { |
1537 | ret classNames.contains(tok.get(i+5)); |
1538 | } |
1539 | }); |
1540 | } |
1541 | |
1542 | // experimental - "<ClassName>(...)" => "new <ClassName>(...)" |
1543 | // doesn't work at beginning of statement as we can't easily |
1544 | // distinguish it from a constructor declaration. |
1545 | static void newWithoutNew(L<S> tok, final Set<S> classNames) { |
1546 | jreplace(tok, "<id>(", "new $1(", func(L<S> tok, int i) { |
1547 | if (!classNames.contains(tok.get(i+1))) false; |
1548 | bool ok = neqOneOf(_get(tok, i-1), "new", ";", "}", "{", "public", "protected", "private", "."); |
1549 | //print("newWithoutNew: checking " + struct(subList(tok, i-1, i+2)) + " => " + ok); |
1550 | ret ok; |
1551 | }); |
1552 | } |
1553 | |
1554 | // +var => "var", +var |
1555 | static void expandVarCopies(L<S> tok) { |
1556 | bool change = false; |
1557 | for (int i = 3; i+2 < l(tok); i += 2) { |
1558 | if (!eq(tok.get(i), "+")) continue; |
1559 | if (!eqOneOf(tok.get(i-2), "(", ",", "{")) continue; |
1560 | S s = tok.get(i+2); |
1561 | if (!isIdentifier(s)) continue; |
1562 | tok.set(i, quote(s) + ", "); |
1563 | change = true; |
1564 | } |
1565 | if (change) reTok(tok); |
1566 | } |
1567 | |
1568 | static void processConceptsDot(L<S> tok) { |
1569 | bool change; |
1570 | do { |
1571 | change = false; |
1572 | for (int i : jfindAll(tok, "concepts.")) |
1573 | if (contains(get(tok, i+3), "\n")) { |
1574 | replaceTokens(tok, i, i+3, "!" + "include #1004863 // Dynamic Concepts"); |
1575 | reTok(tok, i, i+3); |
1576 | change = true; |
1577 | break; |
1578 | } |
1579 | } while (change); |
1580 | } |
1581 | |
1582 | static void addFieldOrder(L<S> tok, int i) { |
1583 | int idx = findCodeTokens(tok, i, false, "{"); |
1584 | if (idx < 0) ret; |
1585 | int j = findEndOfBracketPart(tok, idx); |
1586 | L<S> vars = allVarNames(subList(tok, idx+1, j-1)); |
1587 | print("addFieldOrder " + struct(vars)); |
1588 | if (!vars.contains("_fieldOrder") |
1589 | && !isSortedList(vars)) { |
1590 | print("Adding field order"); |
1591 | tok.set(idx+2, "static String _fieldOrder = " + quote(join(" ", vars)) + ";\n " + tok.get(idx+2)); |
1592 | // reTok has to be done by caller |
1593 | } |
1594 | } |
1595 | |
1596 | static void caseAsVariableName(L<S> tok) { |
1597 | if (!tok.contains("case")) ret; |
1598 | for (int i = 1; i+2 < l(tok); i += 2) { |
1599 | S t = tok.get(i+2); |
1600 | if (tok.get(i).equals("case") |
1601 | && !(t.startsWith("'") || isInteger(t) || isIdentifier(t))) |
1602 | tok.set(i, "_case"); |
1603 | } |
1604 | } |
1605 | |
1606 | static void continueAsFunctionName(L<S> tok) { |
1607 | jreplace(tok, "continue(", "_continue("); |
1608 | } |
1609 | |
1610 | // f bla => "bla" - and "please include function bla." |
1611 | static void functionReferences(L<S> tok) { |
1612 | int i; |
1613 | S keyword = "f"; |
1614 | while ((i = jfind(tok, keyword + " <id>", new O() { |
1615 | O get(L<S> tok, int i) { |
1616 | ret !eq(tok.get(i+3), "instanceof"); |
1617 | } |
1618 | })) >= 0) { |
1619 | S f = tok.get(i+2); |
1620 | clearTokens(tok, i, i+2); |
1621 | tok.set(i+2, quote(f)); |
1622 | reTok(tok, i, i+2); |
1623 | tok.set(l(tok)-1, last(tok) + "\nplease include function " + f + "."); |
1624 | reTok(tok, l(tok)-1, l(tok)); |
1625 | } |
1626 | } |
1627 | |
1628 | // # 123 => "#123" |
1629 | static void directSnippetRefs(L<S> tok) { |
1630 | int i; |
1631 | while ((i = jfind(tok, "#<int>", new O() { |
1632 | bool get(L<S> tok, int i) { |
1633 | ret neq(_get(tok, i-1), "include"); |
1634 | } |
1635 | })) >= 0) { |
1636 | S id = tok.get(i+2); |
1637 | clearTokens(tok, i+1, i+3); |
1638 | tok.set(i, quote("#" + id)); |
1639 | reTok(tok, i, i+3); |
1640 | } |
1641 | } |
1642 | |
1643 | static void quicknu(L<S> tok) { |
1644 | jreplace(tok, "nu <id>(", "nu($2.class, "); |
1645 | jreplace(tok, "nu <id>", "new $2"); |
1646 | } |
1647 | |
1648 | // fill variable innerClasses_list |
1649 | static void innerClassesVar(L<S> tok) { |
1650 | if (!tok.contains("myInnerClasses_list")) ret; |
1651 | |
1652 | L<S> have = classDeclarationNames(innerClassesOfMain(tok)); |
1653 | int i = jfind(tok, ">myInnerClasses_list;"); |
1654 | if (i < 0) ret; |
1655 | tok.set(i+4, "=litlist(\n" + joinQuoted(", ", have) + ");"); |
1656 | reTok(tok, i+4, i+5); |
1657 | } |
1658 | |
1659 | // process ifclass x ... endif blocks |
1660 | static void tok_ifclass(L<S> tok) { |
1661 | if (!tok.contains("ifclass")) ret; |
1662 | |
1663 | L<S> have = classDeclarationNames(innerClassesOfMain(tok)); |
1664 | int i; |
1665 | while ((i = rjfind(tok, "ifclass <id>")) >= 0) { |
1666 | int j = jfind(tok, i+4, "endif"); |
1667 | if (j < 0) j = l(tok)-1; |
1668 | bool has = have.contains(tok.get(i+2)); |
1669 | clearTokens(tok, i, i+3); |
1670 | clearTokens(tok, j, j+1); |
1671 | if (!has) clearTokens(tok, i+3, j); |
1672 | reTok(tok, i, j+1); |
1673 | } |
1674 | } |
1675 | |
1676 | // set flag *. |
1677 | static void tok_definitions(L<S> tok) { |
1678 | int i; |
1679 | while ((i = jfind(tok, "set flag <id>.")) >= 0) { |
1680 | String fname = tok.get(i+4); |
1681 | definitions.add(fname); |
1682 | clearAllTokens(tok.subList(i, i+8)); |
1683 | } |
1684 | } |
1685 | |
1686 | // process ifndef x ... endifndef blocks |
1687 | static void tok_ifndef(L<S> tok) { |
1688 | if (!tok.contains("ifndef")) ret; |
1689 | |
1690 | int i; |
1691 | while ((i = rjfind(tok, "ifndef <id>")) >= 0) { |
1692 | int j = jfind(tok, i+4, "endifndef"); |
1693 | if (j < 0) j = l(tok)-1; |
1694 | S fname = tok.get(i+2); |
1695 | bool has = !definitions.contains(fname); |
1696 | print("ifndef " + fname + " => " + has); |
1697 | clearTokens(tok, i, i+3); |
1698 | clearTokens(tok, j, j+1); |
1699 | if (!has) clearTokens(tok, i+3, j); |
1700 | reTok(tok, i, j+1); |
1701 | } |
1702 | } |
1703 | |
1704 | // process ifdef x ... endifdef blocks |
1705 | static void tok_ifdef(L<S> tok) { |
1706 | if (!tok.contains("ifdef")) ret; |
1707 | |
1708 | int i; |
1709 | while ((i = rjfind(tok, "ifdef <id>")) >= 0) { |
1710 | int j = jfind(tok, i+4, "endifdef"); |
1711 | if (j < 0) j = l(tok)-1; |
1712 | S fname = tok.get(i+2); |
1713 | bool has = definitions.contains(fname); |
1714 | print("ifdef " + fname + " => " + has); |
1715 | clearTokens(tok, i, i+3); |
1716 | clearTokens(tok, j, j+1); |
1717 | if (!has) clearTokens(tok, i+3, j); |
1718 | reTok(tok, i, j+1); |
1719 | } |
1720 | } |
1721 | |
1722 | svoid conceptDeclarations(L<S> tok) { |
1723 | for (S kw : ll("concept", "sconcept")) { |
1724 | O cond = new O() { |
1725 | O get(L<S> tok, int i) { |
1726 | addFieldOrder(tok, i+1); |
1727 | ret true; |
1728 | } |
1729 | }; |
1730 | bool re = false; |
1731 | if (jreplace(tok, kw + " <id> {", "static class $2 extends Concept {", cond)) re = true; |
1732 | if (jreplace(tok, kw + " <id> implements", "static class $2 extends Concept implements", cond)) re = true; |
1733 | if (jreplace(tok, kw + " <id>", "static class $2", cond)) re = true; |
1734 | if (re) reTok(tok); |
1735 | } |
1736 | } |
1737 | |
1738 | svoid shortenedSubconcepts(L<S> tok) { |
1739 | jreplace(tok, "<id> > <id> {", "concept $3 extends $1 {", new O() { O get(L<S> tok, int i) { |
1740 | bool b = (i == 0 || tok.get(i).contains("\n")) || eq(_get(tok, i-1), "abstract"); // only at beginning of line or after "abstract" |
1741 | //print("subconcept " + b + ": " + structure(subList(tok, i-1, i+5))); |
1742 | ret b; |
1743 | }}); |
1744 | } |
1745 | |
1746 | // -slightly experimental |
1747 | // -do calculation in another thread, then return to AWT thread |
1748 | // -must be placed in a block |
1749 | // -transforms rest of block |
1750 | svoid unswing(L<S> tok) { |
1751 | int i; |
1752 | while ((i = jfind(tok, "unswing {")) >= 0) { |
1753 | int idx = i+2; |
1754 | int closingBracket = findEndOfBracketPart(tok, idx)-1; |
1755 | int endOfOuterBlock = findEndOfBracketPart(tok, closingBracket)-1; |
1756 | tok.set(i, "thread"); |
1757 | tok.set(closingBracket, " awt {"); |
1758 | tok.set(endOfOuterBlock, "}}}"); |
1759 | reTok(tok, closingBracket-1, endOfOuterBlock+1); |
1760 | } |
1761 | } |
1762 | |
1763 | // -slightly experimental |
1764 | // -Syntax: lock theLock; |
1765 | // -lock a lock, unlock at end of current block with finally |
1766 | svoid lockBlocks(L<S> tok) { |
1767 | int i; |
1768 | while ((i = jfind(tok, "lock <id>", func(L<S> tok, int i) { neq(tok.get(i+3), "instanceof") })) >= 0) { |
1769 | int semicolon = findEndOfStatement(tok, i)-1; |
1770 | S var = makeVar("lock"); |
1771 | int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1; |
1772 | replaceTokens(tok, i, semicolon+1, |
1773 | "Lock " + var + " = " + joinSubList(tok, i+2, semicolon-1) + "; lock(" + var + "); try {"); |
1774 | tok.set(endOfOuterBlock, "} finally { " + var + ".unlock(); } }"); |
1775 | reTok(tok, i, endOfOuterBlock+1); |
1776 | } |
1777 | } |
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: | #1010087 |
Snippet name: | Speeding up "Super-Edgy" JavaX Translator (Extension of #7) 2 |
Eternal ID of this version: | #1010087/6 |
Text MD5: | af00501583b5113ff05629bf1727db27 |
Transpilation MD5: | 8ab7b47758cdbb74dba6bc142ea79705 |
Author: | stefan |
Category: | javax |
Type: | JavaX translator |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-09-02 09:23:56 |
Source code size: | 57308 bytes / 1777 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 432 / 547 |
Version history: | 5 change(s) |
Referenced in: | [show references] |