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