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