Libraryless. Click here for Pure Java version (4779L/36K/89K).
1 | !747 |
2 | |
3 | m { |
4 | !include #1001496 // Matches |
5 | !include #1000882 // EGDiff |
6 | !include #1000883 // BlockDiffer |
7 | !include #1001065 // DialoGIO |
8 | |
9 | !include #1002662 // isTrue |
10 | |
11 | !include #1003674 // Standard Classes List |
12 | |
13 | static int varCount; |
14 | |
15 | static new Map<S, S> snippetCache; |
16 | |
17 | p { |
18 | print("759 STARTING " + identityHashCode(main.class)); |
19 | varCount = 0; |
20 | L<S> tok = tokMainJava(); |
21 | |
22 | L ts = findTranslators(toLines(join(tok))); |
23 | print("Translators in source at start: " + structure(ts)); |
24 | |
25 | // "duplicate" statement |
26 | |
27 | L<S> lines = toLines(join(tok)); |
28 | call(getJavaX(), "findTranslators", lines); |
29 | new Matches m; |
30 | if (match("duplicate *", fromLines(lines), m)) { |
31 | // actual copying - unused |
32 | // tok = javaTok(loadSnippet(m.get(0))); |
33 | |
34 | // reference by include() |
35 | tok = javaTok("m { p { callMain(include(" + quote(m.get(0)) + ")); } }"); |
36 | } |
37 | |
38 | // add m { } |
39 | |
40 | if (!hasCodeTokens(tok, "m", "{") && !hasCodeTokens(tok, "main", "{") && !hasCodeTokens(tok, "class", "main")) |
41 | tok = javaTok(moveImportsUp("m {\n" + join(tok) + "\n}")); |
42 | |
43 | // standard translate |
44 | |
45 | ts = findTranslators(toLines(join(tok))); |
46 | print("Translators in source: " + structure(ts)); |
47 | tok = javaTok(defaultTranslate(join(tok))); |
48 | |
49 | print("end of default translate"); |
50 | //print(join(tok)); |
51 | |
52 | tok = processIncludes(tok); // before standard functions |
53 | earlyStuff(tok); |
54 | |
55 | int safety = 0; |
56 | boolean same; |
57 | do { |
58 | S before = join(tok); |
59 | tok = standardFunctions(tok); |
60 | tok = stdstuff(tok); // standard functions and all the keywords |
61 | S diff; |
62 | long startTime = now(); |
63 | diff = unidiff(before, join(tok)); |
64 | print("unidiff: " + (now()-startTime) + " ms"); |
65 | same = eq(diff, ""); |
66 | if (!same) { |
67 | print("Not same " + safety + "."); |
68 | //print(indent(2, diff)); |
69 | } |
70 | if (safety++ >= 10) fail("safety 10 error!"); |
71 | } while (!same); |
72 | |
73 | // POST-PROCESSING after stdstuff loop |
74 | |
75 | tok = javaTok(quicknew(join(tok))); |
76 | tok = extendClasses(tok); |
77 | libs(tok); |
78 | sourceCodeLine(tok); |
79 | throwFail(tok); |
80 | tok = autoImports(tok); // faster to do it at the end |
81 | |
82 | |
83 | saveMainJava(tok); |
84 | } |
85 | |
86 | // now also for interfaces |
87 | static L<S> loadClass(L<S> tok, S className, S snippetID) { |
88 | if (containsToken(tok, className) |
89 | && !hasCodeTokens(tok, "class", className) && !hasCodeTokens(tok, "interface", className) |
90 | && !tok_importsClassNamed(tok, className)) { |
91 | snippetID = formatSnippetID(snippetID); |
92 | S text = cacheGet(snippetID); |
93 | tok = includeInMainLoaded(tok, text); |
94 | } |
95 | ret tok; |
96 | } |
97 | |
98 | static L<S> stdstuff(L<S> tok) { |
99 | //if (++level >= 10) fail("woot? 10"); |
100 | |
101 | print("stdstuff!"); |
102 | L<S> lines = toLines(join(tok)); |
103 | L ts = findTranslators(lines); |
104 | tok = javaTok(fromLines(lines)); |
105 | if (nempty(ts)) { |
106 | //print("Warning: Contains translators."); |
107 | print("DROPPING TRANSLATORS: " + structure(ts)); |
108 | } |
109 | |
110 | tok = quickmain(tok); |
111 | tok = processIncludes(tok); |
112 | earlyStuff(tok); |
113 | tok = multilineStrings(tok); |
114 | listComprehensions(tok); |
115 | |
116 | tok = replaceKeywordBlock(tok, "answer", |
117 | "static S answer(S s) {\nnew Matches m;\n", |
118 | "\nret null;\n}"); |
119 | |
120 | tok = replaceKeywordBlock(tok, "loading", |
121 | "{ JWindow _loading_window = showLoadingAnimation(); try {", |
122 | "} finally { disposeWindow(_loading_window); }}"); |
123 | |
124 | tok = replaceKeywordBlock(tok, "html", |
125 | "static O html(S uri, fMap<S, S> params) {\n", "}"); |
126 | |
127 | // "static sync" => static synchronized |
128 | jreplace(tok, "static sync", "static synchronized"); |
129 | |
130 | // "sclass" => static class |
131 | jreplace(tok, "sclass", "static class"); |
132 | |
133 | // "asclass" => abstract static class |
134 | jreplace(tok, "asclass", "abstract static class"); |
135 | |
136 | // "sinterface" => static interface |
137 | jreplace(tok, "sinterface", "static interface"); |
138 | |
139 | // "ssynchronized" => static synchronized |
140 | jreplace(tok, "ssynchronized", "static synchronized"); |
141 | |
142 | jreplace(tok, "ssvoid", "static synchronized void"); |
143 | jreplace(tok, "svoid", "static void"); |
144 | jreplace(tok, "sbool", "static bool"); |
145 | jreplace(tok, "sint", "static int"); |
146 | jreplace(tok, "snew", "static new"); |
147 | jreplace(tok, "sv <id>", "static void $2"); |
148 | jreplace(tok, "pvoid", "public void"); |
149 | |
150 | // "sS" => static S |
151 | jreplace(tok, "sS", "static S"); |
152 | |
153 | // "sO" => static O |
154 | jreplace(tok, "sO", "static O"); |
155 | |
156 | // "sL" => static L |
157 | jreplace(tok, "sL", "static L"); |
158 | |
159 | // "toString {" => "public S toString() {" |
160 | jreplace(tok, "toString {", "public S toString() {"); |
161 | |
162 | jreplace(tok, "Int", "Integer"); |
163 | jreplace(tok, "Bool", "Boolean"); |
164 | |
165 | // "catch {" => "catch (Throwable _e) {" |
166 | jreplace(tok, "catch {", "catch (Throwable _e) {"); |
167 | |
168 | // "catch X e {" => "catch (X e) {" |
169 | jreplace(tok, "catch <id> <id> {", "catch ($2 $3) {"); |
170 | |
171 | // "catch e {" => "catch (Throwable e) {" (if e is lowercase) |
172 | jreplace(tok, "catch <id> {", "catch (Throwable $2) {", new O() { |
173 | bool check(L<S> tok, int i) { |
174 | S word = tok.get(i+3); |
175 | ret startsWithLowerCase(word); |
176 | } |
177 | }); |
178 | |
179 | // some crazy fancy syntax |
180 | jreplace(tok, "set <id>;", "$2 = true;"); |
181 | |
182 | jreplace(tok, "fS", "final S"); |
183 | jreplace(tok, "fO", "final O"); |
184 | jreplace(tok, "fL", "final L"); |
185 | jreplace(tok, "fMap", "final Map"); |
186 | jreplace(tok, "fRunnable", "final Runnable"); |
187 | jreplace(tok, "f int", "final int"); |
188 | |
189 | jreplace(tok, "new <id> {", "new $2() {"); |
190 | |
191 | // shortened method declarations - hopefully that works |
192 | |
193 | jreplace(tok, "void <id> {", "$1 $2() {"); |
194 | jreplace(tok, "String <id> {", "$1 $2() {"); |
195 | jreplace(tok, "Object <id> {", "$1 $2() {"); |
196 | jreplace(tok, "List <id> {", "$1 $2() {"); |
197 | |
198 | // "is a X" => instanceof X |
199 | |
200 | jreplace(tok, "is a <id>", "instanceof $3"); |
201 | |
202 | // func keyword for lambdas - now automatically quines toString() |
203 | |
204 | int i; |
205 | while ((i = jfind(tok, "func(")) >= 0) { |
206 | int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); |
207 | int idx = findCodeTokens(tok, argsTo, false, "{"); |
208 | int j = findEndOfBracketPart(tok, idx+2); |
209 | L<S> contents = subList(tok, idx+1, j-1); |
210 | replaceTokens(tok, i, j, "new O { O get(" + join(subList(tok, argsFrom, argsTo-1)) + ") { " + tok_addReturn(contents) + " }\n" + |
211 | " public S toString() { ret " + quote(trim(join(contents))) + "; }}"); |
212 | reTok(tok); |
213 | } |
214 | |
215 | while ((i = jfind(tok, "voidfunc(")) >= 0) { |
216 | int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); |
217 | int idx = findCodeTokens(tok, argsTo, false, "{"); |
218 | int j = findEndOfBracketPart(tok, idx+2); |
219 | L<S> contents = subList(tok, idx+1, j-1); |
220 | replaceTokens(tok, i, j, "new O { void get(" + join(subList(tok, argsFrom, argsTo-1)) + ") { " + join(contents) + " }\n" + |
221 | " public S toString() { ret " + quote(trim(join(contents))) + "; }}"); |
222 | reTok(tok); |
223 | } |
224 | |
225 | while ((i = jfind(tok, "func {")) >= 0) { |
226 | int idx = findCodeTokens(tok, i, false, "{"); |
227 | int j = findEndOfBracketPart(tok, idx+2); |
228 | L<S> contents = subList(tok, idx+1, j-1); |
229 | replaceTokens(tok, i, j, "new O { O get() { " + tok_addReturn(contents) + " }\n" + |
230 | " public S toString() { ret " + quote(trim(join(contents))) + "; }}"); |
231 | reTok(tok); |
232 | } |
233 | /*tok = replaceKeywordBlock(tok, "func", |
234 | "new O { O get() { ret", |
235 | ";}}");*/ |
236 | |
237 | // * constructors |
238 | if (hasCodeTokens(tok, "\\*", "(")) |
239 | tok = expandStarConstructors(tok); |
240 | |
241 | // Do this BEFORE awt replacement! ("p-awt" contains "awt" token) |
242 | tok = replaceKeywordBlock(tok, "p-substance", "p-awt { substance();", "}"); |
243 | tok = replaceKeywordBlock(tok, "p-awt", "p { awt {", "}}"); |
244 | |
245 | tok = replaceKeywordBlock(tok, |
246 | "awt", |
247 | "swingLater(r {", |
248 | "});"); |
249 | |
250 | // crazy stuff |
251 | |
252 | jreplace (tok, "for <id> over <id>:", "for (int $2 = 0; $2 < l($4); $2++)"); |
253 | |
254 | // STANDARD CLASSES & INTERFACES |
255 | |
256 | for (S line : toLinesFullTrim(standardClasses)) { |
257 | int idx = line.indexOf('/'); |
258 | tok = loadClass(tok, line.substring(0, idx), line.substring(idx+1)); |
259 | } |
260 | |
261 | tok = loadClass(tok, "Quine", "#1003601"); |
262 | tok = loadClass(tok, "Var", "#1003550"); |
263 | tok = loadClass(tok, "TableFinder", "#1000850"); |
264 | tok = loadClass(tok, "Snippet", "#1003519"); |
265 | tok = loadClass(tok, "GermanDateAdapter", "#1003510"); |
266 | tok = loadClass(tok, "BF", "#1003489"); |
267 | tok = loadClass(tok, "BotChat", "#1003499"); |
268 | tok = loadClass(tok, "StrictTreeMap", "#1003482"); |
269 | tok = loadClass(tok, "E", "#1003474"); |
270 | tok = loadClass(tok, "Dialog", "#1003356"); |
271 | tok = loadClass(tok, "OccTree2", "#1003407"); |
272 | tok = loadClass(tok, "OccTree", "#1003331"); |
273 | tok = loadClass(tok, "EGDiff", "#1000882"); |
274 | tok = loadClass(tok, "BlockDiffer", "#1000883"); |
275 | tok = loadClass(tok, "Q", "#1000934"); |
276 | tok = loadClass(tok, "F", "#1003033"); |
277 | tok = loadClass(tok, "LoadEnv", "#1002955"); |
278 | tok = loadClass(tok, "CIString", "#1002873"); |
279 | tok = loadClass(tok, "PersistentCIMap", "#1002872"); |
280 | tok = loadClass(tok, "EvalTransform", "#1002867"); |
281 | tok = loadClass(tok, "Prolog", "#1002884"); // Yay! |
282 | tok = loadClass(tok, "IEngine", "#1002809"); |
283 | tok = loadClass(tok, "Native", "#1002774"); |
284 | tok = loadClass(tok, "ProgramScan", "#1000804"); |
285 | tok = loadClass(tok, "SNLMatches", "#1002748"); |
286 | tok = loadClass(tok, "SNLInfo", "#1002744"); |
287 | tok = loadClass(tok, "Lisp", "#1002696"); |
288 | tok = loadClass(tok, "Explain", "#1002529"); |
289 | tok = loadClass(tok, "NanoHTTPD", "#1001651"); |
290 | tok = loadClass(tok, "Source", "#1002461"); |
291 | tok = loadClass(tok, "ShowBigText", "#1001425"); |
292 | tok = loadClass(tok, "DialogIO", "#1001065"); |
293 | tok = loadClass(tok, "Matches", "#1001496"); |
294 | tok = loadClass(tok, "MultiMap", "#1001296"); |
295 | tok = loadClass(tok, "MultiSet", "#1000988"); |
296 | tok = loadClass(tok, "MultiHashSet", "#1003597"); |
297 | tok = loadClass(tok, "PersistentLog", "#1001972"); |
298 | tok = loadClass(tok, "PersistentMap", "#1002063"); |
299 | tok = loadClass(tok, "PersistentTreeMap", "#1003529"); |
300 | tok = loadClass(tok, "Rat", "#1002052"); |
301 | tok = loadClass(tok, "DiskTextMap", "#1002087"); |
302 | |
303 | // image classes (now static) |
304 | |
305 | tok = loadClass(tok, "ImageSurface", "#1002470"); |
306 | tok = loadClass(tok, "RGB", "#1002470"); |
307 | tok = loadClass(tok, "RGBImage", "#1002470"); |
308 | |
309 | // the infamous missing functions (usually caused by class Matches) |
310 | if (!hasCodeTokens(tok, "String", "unquote") && containsToken(tok, "unquote")) { |
311 | print("Adding unquote"); |
312 | tok = includeInMain(tok, "#1001735"); |
313 | } |
314 | |
315 | if (!hasCodeTokens(tok, "String", "formatSnippetID") && containsToken(tok, "formatSnippetID")) { |
316 | print("Adding formatSnippetID"); |
317 | tok = includeInMain(tok, "#1000709"); |
318 | } |
319 | |
320 | tok = expandShortTypes(tok); |
321 | |
322 | if (containsToken(tok, "cast")) { |
323 | S s = join(tok); |
324 | s = s.replaceAll("(\\w+<[\\w\\s,\\[\\]]+>|\\w+|\\w+\\[\\]|\\w+\\[\\]\\[\\])\\s+(\\w+)\\s*=\\s*cast(\\W[^;]*);", "$1 $2 = ($1) ($3);"); |
325 | tok = javaTok(s); |
326 | } |
327 | |
328 | for (S keyword : ll("runnable", "r")) |
329 | tok = replaceKeywordBlock(tok, |
330 | keyword, |
331 | "new Runnable() { public void run() { try {", |
332 | "} catch (Exception __e) { throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e); }}}"); |
333 | |
334 | tok = replaceKeywordBlock(tok, |
335 | "expectException", |
336 | "{ bool __ok = false; try {", |
337 | "} catch { __ok = true; } assertTrue(\"expected exception\", __ok); }"); |
338 | |
339 | while ((i = tok.indexOf("tex")) >= 0) { |
340 | tok.set(i, "throws Exception"); |
341 | tok = javaTok(tok); |
342 | } |
343 | |
344 | while ((i = findCodeTokens(tok, "while", "true")) >= 0) { |
345 | tok.set(i+2, "(true)"); |
346 | tok = javaTok(tok); |
347 | } |
348 | |
349 | // "null;" instead of "return null;" |
350 | jreplace(tok, "{ null;", "$1 return null;"); |
351 | jreplace(tok, "} null;", "$1 return null;"); |
352 | jreplace(tok, "; null;", "$1 return null;"); |
353 | jreplace(tok, ") null;", "$1 return null;"); |
354 | |
355 | // "false;" instead of "return false;" |
356 | jreplace(tok, "} false;", "} return false;"); |
357 | jreplace(tok, "; false;", "; return false;"); |
358 | jreplace(tok, ") false;", ") return false;"); |
359 | |
360 | // "true;" instead of "return true;" |
361 | jreplace(tok, "} true;", "} return true;"); |
362 | jreplace(tok, "; true;", "; return true;"); |
363 | jreplace(tok, ") true;", ") return true;"); |
364 | |
365 | // "myFunction;" instead of "myFunction();" - quite rough |
366 | O cond = new O() { |
367 | bool check(L<S> tok, int i) { |
368 | S word = tok.get(i+3); |
369 | //print("single word: " + word); |
370 | ret !litlist("break", "continue", "return").contains(word); |
371 | } |
372 | }; |
373 | for (S pre : litlist("}", ";")) |
374 | jreplace(tok, pre + " <id>;", "$1 $2();", cond); |
375 | |
376 | // shorter match syntax for answer methods |
377 | |
378 | jreplace(tok, "if <quoted>", "if (match($2, s, m))"); |
379 | jreplace(tok, "if match <quoted>", "if (match($3, s, m))"); |
380 | |
381 | // extra commas ("litlist(1, 2,)") |
382 | |
383 | jreplace(tok, ",)", ")"); |
384 | |
385 | // additional translations (if necessary) |
386 | |
387 | if (hasCodeTokens(tok, "pcall", "{")) |
388 | tok = replaceKeywordBlock(tok, |
389 | "pcall", |
390 | "try {", |
391 | "} catch (Throwable __e) { printStackTrace(__e); }"); |
392 | |
393 | tok = dialogHandler(tok); |
394 | |
395 | tok = replaceKeywordBlock(tok, "exceptionToUser", |
396 | "try {", |
397 | "} catch (Throwable __e) { ret exceptionToUser(__e); }"); |
398 | |
399 | if (hasCodeTokens(tok, "twice", "{")) |
400 | tok = replaceKeywordBlock(tok, "twice", |
401 | "for (int __twice = 0; __twice < 2; __twice++) {", |
402 | "}"); |
403 | |
404 | while ((i = findCodeTokens(tok, "repeat", "*", "{")) >= 0) { |
405 | S v = makeVar("repeat"); |
406 | tok.set(i, "for (int " + v + " = 0; " + v + " < " + tok.get(i+2) + "; " + v + "++)"); |
407 | tok.set(i+2, ""); |
408 | tok = javaTok(tok); |
409 | } |
410 | |
411 | tok = replaceKeywordBlockDyn(tok, |
412 | "time", |
413 | new O() { S[] get() { |
414 | S var = makeVar("startTime"); |
415 | ret new S[] { |
416 | "{ long " + var + " = now(); try { ", |
417 | "} finally { " + var + " = now()-" + var + "; saveTiming(" + var + "); } }"}; |
418 | }}); |
419 | |
420 | if (hasCodeTokens(tok, "assertFail", "{")) { |
421 | S var = makeVar("oops"); |
422 | |
423 | tok = replaceKeywordBlock(tok, |
424 | "assertFail", |
425 | "boolean " + var + " = false; try {", |
426 | "\n" + var + " = true; } catch (Exception e) { /* ok */ } assertFalse(" + var + ");"); |
427 | } |
428 | |
429 | tok = replaceKeywordBlock(tok, |
430 | "yo", |
431 | "try {", |
432 | "} catch (Exception " + makeVar("e") + ") { ret false; }"); |
433 | |
434 | tok = replaceKeywordBlock(tok, |
435 | "awtIfNecessary", |
436 | "swingNowOrLater(r {", |
437 | "});"); |
438 | |
439 | if (hasCodeTokens(tok, "ctex")) |
440 | tok = ctex(tok); |
441 | |
442 | tok = replaceKeywordBlock(tok, |
443 | "actionListener", |
444 | "new java.awt.event.ActionListener() { " + |
445 | "public void actionPerformed(java.awt.event.ActionEvent _evt) {", |
446 | "}}"); |
447 | |
448 | namedThreads(tok); |
449 | threads(tok); |
450 | |
451 | // try answer |
452 | while ((i = findCodeTokens(tok, "try", "answer")) >= 0) { |
453 | int j = findEndOfStatement(tok, i); |
454 | S v = makeVar("a"); |
455 | tok.set(i, "S " + v); |
456 | tok.set(i+2, "="); |
457 | tok.set(j-1, "; if (!empty(" + v + ")) ret " + v + ";"); |
458 | tok = javaTok(tok); |
459 | } |
460 | |
461 | tok = javaTok(moveImportsUp(join(tok))); |
462 | |
463 | ret tok; |
464 | } |
465 | |
466 | static L<S> multilineStrings(L<S> tok) { |
467 | for (int i = 1; i < tok.size(); i += 2) { |
468 | S t = tok.get(i); |
469 | if (t.startsWith("[") && isQuoted (t)) |
470 | tok.set(i, quote(unquote(t))); |
471 | } |
472 | ret tok; |
473 | } |
474 | |
475 | static L<S> quickmain(L<S> tok) { |
476 | int i = findCodeTokens(tok, "main", "{"); |
477 | if (i < 0) i = findCodeTokens(tok, "m", "{"); |
478 | if (i >= 0 && !(i-2 > 0 && tok.get(i-2).equals("class"))) |
479 | tok.set(i, "public class main"); |
480 | |
481 | i = findCodeTokens(tok, "psvm", "{"); |
482 | if (i < 0) i = findCodeTokens(tok, "p", "{"); |
483 | if (i >= 0) |
484 | tok.set(i, "public static void main(String[] args) throws Exception"); |
485 | |
486 | ret javaTok(tok); |
487 | } |
488 | |
489 | static S makeVar(S name) { |
490 | ret "_" + name + "_" + varCount++; |
491 | } |
492 | |
493 | static S makeVar() { ret makeVar(""); } |
494 | |
495 | /*static L<S> standardFunctions(L<S> tok) { |
496 | ret rtq(tok, "#1002474"); |
497 | }*/ |
498 | |
499 | static L<S> rtq(L<S> tok, S id) { |
500 | ret runTranslatorQuick(tok, id); |
501 | } |
502 | |
503 | static L<S> expandShortTypes(L<S> tok) { |
504 | // replace <int> with <Integer> |
505 | for (int i = 1; i+4 < tok.size(); i += 2) |
506 | if (tok.get(i).equals("<") |
507 | && litlist(">", ",").contains(tok.get(i+4))) { |
508 | String type = tok.get(i+2); |
509 | if (type.equals("int")) type = "Integer"; |
510 | else if (type.equals("long")) type = "Long"; |
511 | tok.set(i+2, type); |
512 | } |
513 | |
514 | // O = Object, S = String, ret = return |
515 | for (int i = 1; i < tok.size(); i += 2) { |
516 | String t = tok.get(i); |
517 | if (t.equals("O")) t = "Object"; |
518 | if (t.equals("S")) t = "String"; |
519 | else if (t.equals("L")) t = "List"; |
520 | else if (t.equals("F")) t = "Function"; |
521 | else if (t.equals("ret")) t = "return"; |
522 | 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 |
523 | tok.set(i, t); |
524 | } |
525 | |
526 | ret tok; |
527 | } |
528 | |
529 | static L<S> autoImports(L<S> tok) { |
530 | S s = join(tok); |
531 | List<String> imports = findImports(s); |
532 | new StringBuilder buf; |
533 | for (String c : standardImportClasses) |
534 | if (!(imports.contains(c))) |
535 | buf.append("import " + c + ";\n"); |
536 | if (buf.length() == 0) ret tok; |
537 | ret javaTok(buf+s); |
538 | } |
539 | |
540 | static String[] standardImportClasses = { |
541 | "java.util.*", |
542 | "java.util.zip.*", |
543 | "java.util.List", |
544 | "java.util.regex.*", |
545 | "java.util.concurrent.*", |
546 | "java.util.concurrent.atomic.*", |
547 | "javax.swing.*", |
548 | "javax.swing.event.*", |
549 | "javax.swing.text.*", |
550 | "javax.swing.table.*", |
551 | "java.io.*", |
552 | "java.net.*", |
553 | "java.lang.reflect.*", |
554 | "java.lang.ref.*", |
555 | "java.lang.management.*", |
556 | "java.security.*", |
557 | "java.security.spec.*", |
558 | "java.awt.*", |
559 | "java.awt.event.*", |
560 | "java.awt.image.*", |
561 | "javax.imageio.*", |
562 | "java.math.*" |
563 | }; |
564 | |
565 | static L<S> expandStarConstructors(L<S> tok) { |
566 | mainLoop: for (int i = 3; i+6 < tok.size(); i += 2) { |
567 | String t = tok.get(i), l = tok.get(i-2); |
568 | if (!t.equals("*")) |
569 | continue; |
570 | if (!tok.get(i+2).equals("(")) |
571 | continue; |
572 | if (!eqOneOf(l, "}", "public", "private", "protected", ";", "{")) // is this correct...?? |
573 | continue; |
574 | |
575 | // ok, it seems like a constructor declaration. |
576 | // Now find class name by going backwards. |
577 | |
578 | int j = i, level = 1; |
579 | while (j > 0 && level > 0) { |
580 | t = tok.get(j); |
581 | if (t.equals("}")) ++level; |
582 | if (t.equals("{")) --level; |
583 | j -= 2; |
584 | } |
585 | |
586 | while (j > 0) { |
587 | t = tok.get(j); |
588 | if (t.equals("class")) { |
589 | String className = tok.get(j+2); |
590 | tok.set(i, className); // exchange constructor name! |
591 | |
592 | // now for the parameters. |
593 | // Syntax: *(Learner *learner) { |
594 | // We will surely add type inference here in time... :) |
595 | |
596 | j = i+2; |
597 | while (!tok.get(j).equals("{")) |
598 | j += 2; |
599 | int block = j+1; |
600 | for (int k = i+2; k < block-1; k += 2) |
601 | if (tok.get(k).equals("*")) { |
602 | tok.remove(k); |
603 | tok.remove(k); |
604 | block -= 2; |
605 | String name = tok.get(k); |
606 | tok.addAll(block, Arrays.asList(new String[] { |
607 | "\n ", "this", "", ".", "", name, " ", "=", " ", name, "", ";" })); |
608 | } |
609 | |
610 | continue mainLoop; |
611 | } |
612 | j -= 2; |
613 | } |
614 | } |
615 | ret tok; |
616 | } |
617 | |
618 | static L<S> processIncludes(L<S> tok) { |
619 | int safety = 0; |
620 | while (hasCodeTokens(tok, "!", "include") && ++safety < 100) |
621 | tok = processIncludesSingle(tok); |
622 | ret tok; |
623 | } |
624 | |
625 | static L<S> processIncludesSingle(L<S> tok) { |
626 | S s = join(tok); |
627 | Matcher m = Pattern.compile("\n\\s*!include (#\\d+)").matcher(s); |
628 | StringBuffer buf = new StringBuffer(); |
629 | while (m.find()) { |
630 | String includedSrc = loadSnippet(m.group(1)); |
631 | m.appendReplacement(buf, m.quoteReplacement("\n" + includedSrc)); |
632 | } |
633 | m.appendTail(buf); |
634 | ret javaTok(str(buf)); |
635 | } |
636 | |
637 | static L<S> ctex(L<S> tok) { |
638 | S s = join(tok); |
639 | Pattern regex = Pattern.compile("\\s+(no\\s+exceptions|ctex|null on exception)\\s*\\{"); |
640 | |
641 | for (int i = 0; i < 100; i++) { |
642 | Matcher matcher = regex.matcher(s); |
643 | if (!matcher.find()) |
644 | break; |
645 | String kind = matcher.group(1); |
646 | |
647 | System.out.println("Iteration " + (i+1)); |
648 | int start = matcher.start(), end = matcher.end(); |
649 | int endOfBlock = ctex_findEndOfBlock(s, end); |
650 | |
651 | String catchBlock, catchWhat; |
652 | if (kind.startsWith("null")) { |
653 | catchBlock = "return null;"; |
654 | catchWhat = "Throwable"; |
655 | } else { |
656 | catchBlock = "throw __e instanceof RuntimeException ? (RuntimeException) __e : new RuntimeException(__e);"; |
657 | catchWhat = "Throwable"; |
658 | } |
659 | |
660 | String tryBlock = " { try {\n " + |
661 | s.substring(end, endOfBlock) + "\n} catch (" + catchWhat + " __e) { " + catchBlock + " }"; |
662 | s = s.substring(0, start) + tryBlock + s.substring(endOfBlock); |
663 | } |
664 | ret javaTok(s); |
665 | } |
666 | |
667 | // start is the index AFTER the opening bracket |
668 | // returns index OF closing bracket |
669 | static int ctex_findEndOfBlock(String s, int start) { |
670 | int level = 1; |
671 | for (int i = start; i < s.length(); i++) { |
672 | if (s.charAt(i) == '{') ++level; |
673 | else if (s.charAt(i) == '}') --level; |
674 | if (level == 0) |
675 | return i; |
676 | } |
677 | return s.length(); |
678 | } |
679 | |
680 | static L<S> dialogHandler(L<S> tok) { |
681 | ret replaceKeywordBlock(tok, |
682 | "dialogHandler", |
683 | "new DialogHandler() {\n" + |
684 | "public void run(final DialogIO io) {", |
685 | "}}"); |
686 | } |
687 | |
688 | /*static S defaultTrans(S s) { |
689 | findTranslators... |
690 | }*/ |
691 | |
692 | static S quicknew(S s) { |
693 | // TODO: switch to tokenizing! |
694 | s = s.replaceAll("new\\s+(\\w+)\\s+(\\w+);", "$1 $2 = new $1();"); |
695 | s = s.replaceAll("new\\s+L<([\\w\\[\\]<>,\\s]+)>\\s+(\\w+);", "List<$1> $2 = new ArrayList<$1>();"); |
696 | s = s.replaceAll("new\\s+List<([\\w\\[\\]<>,\\s]+)>\\s+(\\w+);", "List<$1> $2 = new ArrayList<$1>();"); |
697 | s = s.replaceAll("new\\s+\\(Hash\\)Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new HashSet<$1>();"); |
698 | s = s.replaceAll("new\\s+\\(Tree\\)Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new TreeSet<$1>();"); |
699 | s = s.replaceAll("new\\s+Set<(\\w+)>\\s+(\\w+);", "Set<$1> $2 = new TreeSet<$1>();"); // TreeSet now default - pay attention to explicitly say HashSet if you need it. |
700 | s = s.replaceAll("new\\s+\\(Hash\\)Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new HashMap<$1>();"); |
701 | s = s.replaceAll("new\\s+\\(Tree\\)Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();"); |
702 | |
703 | // TreeMap when string as key |
704 | s = s.replaceAll("new\\s+Map<(S,[\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();"); |
705 | s = s.replaceAll("new\\s+Map<(String,[\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new TreeMap<$1>();"); |
706 | |
707 | // HashMap is default for everything else |
708 | s = s.replaceAll("new\\s+Map<([\\w\\s,]+)>\\s+(\\w+);", "Map<$1> $2 = new HashMap<$1>();"); |
709 | |
710 | s = s.replaceAll("new\\s+(\\w+<[\\w\\s,]+>)\\s+(\\w+);", "$1 $2 = new $1();"); |
711 | |
712 | // Constructor calls without parantheses |
713 | // So you can say something like: predictors.add(new P1); |
714 | |
715 | s = s.replaceAll("new\\s+(\\w+)\\s*([,\\);])", "new $1()$2"); |
716 | |
717 | // replace "new List" with "new ArrayList" |
718 | s = s.replaceAll("new\\s+List\\s*\\(", "new ArrayList("); |
719 | |
720 | // for args |
721 | |
722 | s = s.replace("for args {", "for (int i = 0; i < args.length; i++) { final String arg = args[i];"); |
723 | ret s; |
724 | } |
725 | |
726 | static L<S> extendClasses(L<S> tok) { |
727 | int i; |
728 | while ((i = jfind(tok, "extend <id> {")) >= 0) { |
729 | S className = tok.get(i+2); |
730 | int idx = findCodeTokens(tok, i, false, "{"); |
731 | int j = findEndOfBracketPart(tok, idx+2); |
732 | S content = join(subList(tok, idx+1, j-1)); |
733 | L<S> c = findInnerClassOfMain(tok, className); |
734 | clearTokens(tok.subList(i, j+1)); |
735 | if (c == null) { |
736 | print("Warning: Can't extend class " + className + ", not found"); |
737 | continue; |
738 | } |
739 | int endOfClass = magicIndexOfSubList(tok, c) + l(c)-1; |
740 | while (neq(tok.get(endOfClass), "}")) --endOfClass; |
741 | tok.set(endOfClass, content + "\n" + tok.get(endOfClass)); |
742 | reTok(tok); |
743 | } |
744 | ret tok; |
745 | } |
746 | |
747 | static void listComprehensions(L<S> tok) { |
748 | int i; |
749 | while ((i = jfind(tok, "[<id> <id> in")) >= 0) { |
750 | Map<Integer, Integer> bracketMap = getBracketMap(tok); |
751 | S type = tok.get(i+2), id = tok.get(i+4); |
752 | int j = scanOverExpression(tok, bracketMap, i+8, "|"); |
753 | S exp = join(tok.subList(i+8, j)); |
754 | j += 2; |
755 | int k = scanOverExpression(tok, bracketMap, j, "]"); |
756 | S where = join(tok.subList(j, k)); |
757 | ++k; |
758 | |
759 | S code = "filter(" + exp + ", func(" + type + " " + id + ") { " + where + " })"; |
760 | replaceTokens(tok, i, k, code); |
761 | reTok(tok); |
762 | } |
763 | } |
764 | |
765 | // lib 123 => !123 |
766 | static void libs(L<S> tok) { |
767 | new Set<S> libs; |
768 | int i; |
769 | while ((i = jfind(tok, "lib <int>")) >= 0) { |
770 | S id = tok.get(i+2); |
771 | print("lib " + id); |
772 | if (!libs.contains(id)) { |
773 | libs.add(id); |
774 | tok.set(i, "!"); |
775 | tok.set(i+1, ""); |
776 | } else { |
777 | print("...ignoring (duplicate)"); |
778 | clearAllTokens(tok, i, i+3); |
779 | reTok(tok); |
780 | } |
781 | } |
782 | } |
783 | |
784 | // sourceCodeLine() => 1234 |
785 | static void sourceCodeLine(L<S> tok) { |
786 | int i ; |
787 | while ((i = jfind(tok, "sourceCodeLine()")) >= 0) { |
788 | replaceTokens(tok, i, i+5, str(countChar(join(subList(tok, 0, i)), '\n')+1)); |
789 | reTok(tok); |
790 | } |
791 | } |
792 | |
793 | // done before any other processing |
794 | static void earlyStuff(L<S> tok) { |
795 | int i; |
796 | |
797 | // Note: this makes the word "quine" a special operator |
798 | // (unusable as a function name) |
799 | |
800 | while ((i = jfind(tok, "quine(")) >= 0) { |
801 | int idx = findCodeTokens(tok, i, false, "("); |
802 | int j = findEndOfBracketPart(tok, idx+2); |
803 | tok.set(i, "new Quine"); |
804 | tok.set(idx, "(" + quote(join(subList(tok, idx+1, j-1))) + ", "); |
805 | reTok(tok); |
806 | } |
807 | } |
808 | |
809 | static void throwFail(L<S> tok) { |
810 | bool anyChange = false; |
811 | for (int i = 1; i+2 < l(tok); i += 2) |
812 | if (eq(get(tok, i+2), "fail") && !eqOneOf(get(tok, i), "throw", "RuntimeException", "return")) { |
813 | tok.set(i+2, "throw fail"); |
814 | anyChange = true; |
815 | } |
816 | if (anyChange) |
817 | reTok(tok); |
818 | } |
819 | |
820 | static void namedThreads(L<S> tok) { |
821 | bool change = false; |
822 | for (int i = 0; i < 100; i++) { |
823 | int idx = findCodeTokens(tok, "thread", "*", "{"); |
824 | if (idx < 0) |
825 | break; |
826 | int j = findEndOfBracketPart(tok, idx+4); |
827 | S tName = tok.get(idx+2); |
828 | |
829 | S var = "_t_" + i; |
830 | S pre = "{ Thread " + var + " = new Thread(" + tName + ") {\n" + |
831 | "public void run() {\n" + |
832 | "try"; |
833 | S post = "} catch (Exception _e) {\n" + |
834 | " throw _e instanceof RuntimeException ? (RuntimeException) _e : new RuntimeException(_e); } }\n};\n" + |
835 | var + ".start(); }"; |
836 | |
837 | tok.set(idx, pre); |
838 | tok.set(idx+2, ""); |
839 | tok.set(j-1, post); |
840 | change = true; |
841 | } |
842 | if (change) reTok(tok); |
843 | } |
844 | |
845 | static void threads(L<S> tok) { |
846 | bool change = false; |
847 | for (bool daemon : litlist(false, true)) |
848 | for (int i = 0; i < 100; i++) { |
849 | int idx = findCodeTokens(tok, daemon ? "daemon" : "thread", "{"); |
850 | if (idx < 0) |
851 | break; |
852 | int j = findEndOfBracketPart(tok, idx+2); |
853 | |
854 | S var = "_t_" + i; |
855 | S pre = "{ Thread " + var + " = new Thread() {\n" + |
856 | "public void run() {\n" + |
857 | "try"; |
858 | S post = "} catch (Exception _e) {\n" + |
859 | " throw _e instanceof RuntimeException ? (RuntimeException) _e : new RuntimeException(_e); } }\n};\n" + |
860 | (daemon ? var + ".setDaemon(true);\n" : "") + |
861 | var + ".start(); }"; |
862 | |
863 | tok.set(idx, pre); |
864 | tok.set(j-1, post); |
865 | change = true; |
866 | } |
867 | if (change) reTok(tok); |
868 | } |
869 | |
870 | static Map<S, S> sf; |
871 | |
872 | static L<S> standardFunctions(L<S> tok) { |
873 | if (sf == null) { |
874 | L<S> standardFunctions = (L) loadVariableDefinition( |
875 | loadSnippet("#761"), "standardFunctions"); |
876 | |
877 | sf = new HashMap(); |
878 | for (String x : standardFunctions) { |
879 | String[] f = x.split("/"); |
880 | sf.put(f[1], f[0]); |
881 | } |
882 | } |
883 | |
884 | for (int i = 0; ; i++) { |
885 | Set<String> defd = new HashSet(findFunctions(tok)); |
886 | |
887 | // changes tok |
888 | Set<String> invocations = findFunctionInvocations(tok, sf); |
889 | |
890 | print("Functions invoked: " + structure(invocations)); |
891 | List<String> needed = diff(invocations, defd); |
892 | print("Functions needed: " + structure(needed)); |
893 | if (needed.isEmpty()) |
894 | break; |
895 | |
896 | new L<S> added; |
897 | new StringBuilder buf; |
898 | for (String x : needed) { |
899 | if (defd.contains(x)) continue; |
900 | |
901 | String id = sf.get(x); |
902 | //print("Adding function: " + x + " (" + id + ")"); |
903 | |
904 | S function = cacheGet(id); |
905 | if (("\n" + function).contains("\n!")) print("Warning: " + id + " contains translators."); |
906 | |
907 | buf.append(function).append("\n"); |
908 | added.add(x); |
909 | defd.addAll(findFunctionDefinitions(function)); |
910 | } |
911 | tok = includeInMainLoaded(tok, str(buf)); |
912 | defd = new HashSet(findFunctions(tok)); |
913 | print("Functions added: " + structure(added)); |
914 | |
915 | for (String x : needed) |
916 | if (!defd.contains(x)) |
917 | fail("Function not defined properly: " + x); |
918 | print("Iteration " + (i+2)); |
919 | if (i >= 1000) fail("Too many iterations"); |
920 | } |
921 | |
922 | ret tok; |
923 | } |
924 | |
925 | static L<S> findFunctions(L<S> tok) { |
926 | ret findFunctionDefinitions(join(findMainClass(tok))); |
927 | } |
928 | |
929 | static S cacheGet(S snippetID) { |
930 | S text = snippetCache.get(snippetID); |
931 | if (text == null) |
932 | snippetCache.put(snippetID, text = loadSnippet(snippetID)); |
933 | ret text; |
934 | } |
935 | } |
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: | #1003872 |
Snippet name: | Integrating #759 in One Program |
Eternal ID of this version: | #1003872/1 |
Text MD5: | b31d7b406b562489a7bf6ec862436151 |
Transpilation MD5: | dc467e80e2e11ea0aac911973e2671a0 |
Author: | stefan |
Category: | |
Type: | JavaX translator |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-07-29 15:30:29 |
Source code size: | 31277 bytes / 935 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 614 / 850 |
Referenced in: | [show references] |