!1011230 // JavaParser import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.EnumDeclaration; import com.github.javaparser.ast.stmt.LocalClassDeclarationStmt; import com.github.javaparser.printer.*; import com.github.javaparser.*; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.visitor.*; import com.github.javaparser.Problem; import javax.net.ssl.*; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.nio.file.Files; import java.nio.file.Path; import java.text.NumberFormat; import javax.imageio.metadata.*; import javax.imageio.stream.*; class main { static boolean autoQuine = true; static int maxQuineLength = 80; static boolean assumeTriple = true; static boolean quickInstanceOfEnabled = false; // interferes with things // _registerThread usually costs nothing because we need // the registerWeakHashMap mechanism anyway for ping(). // Anyway - no forced functions for now :) static List functionsToAlwaysInclude = ll( //"_registerThread", //"asRuntimeException" ); // classes with two type parameters that can written with just one // e.g. Pair => Pair static Set pairClasses = lithashset("Pair", "Either", "Map", "AbstractMap", "HashMap", "TreeMap", "LinkedHashMap", "MultiMap", "CompactHashMap", "WrappedMap", "F1", "IF1", "AllOnAll", "AllOnAllWithUpdates"); static class Matches { String[] m; Matches() {} Matches(String... m) { this.m = m;} String get(int i) { return i < m.length ? m[i] : null; } String unq(int i) { return unquote(get(i)); } String fsi(int i) { return formatSnippetID(unq(i)); } String fsi() { return fsi(0); } String tlc(int i) { return unq(i).toLowerCase(); } boolean bool(int i) { return "true".equals(unq(i)); } String rest() { return m[m.length-1]; } // for matchStart int psi(int i) { return Integer.parseInt(unq(i)); } public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; } public int hashCode() { return _hashCode(toList(m)); } public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); } } /** * A class to compare vectors of objects. The result of comparison * is a list of change objects which form an * edit script. The objects compared are traditionally lines * of text from two files. Comparison options such as "ignore * whitespace" are implemented by modifying the equals * and hashcode methods for the objects compared. *

* The basic algorithm is described in:
* "An O(ND) Difference Algorithm and its Variations", Eugene Myers, * Algorithmica Vol. 1 No. 2, 1986, p 251. *

* This class outputs different results from GNU diff 1.15 on some * inputs. Our results are actually better (smaller change list, smaller * total size of changes), but it would be nice to know why. Perhaps * there is a memory overwrite bug in GNU diff 1.15. * * @author Stuart D. Gathman, translated from GNU diff 1.15 * Copyright (C) 2000 Business Management Systems, Inc. *

* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *

* You should have received a copy of the * GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static class EGDiff { /** * Prepare to find differences between two arrays. Each element of * the arrays is translated to an "equivalence number" based on * the result of equals. The original Object arrays * are no longer needed for computing the differences. They will * be needed again later to print the results of the comparison as * an edit script, if desired. */ public EGDiff(Object[] a, Object[] b) { Hashtable h = new Hashtable(a.length + b.length); filevec[0] = new file_data(a, h); filevec[1] = new file_data(b, h); } /** * 1 more than the maximum equivalence value used for this or its * sibling file. */ private int equiv_max = 1; /** * When set to true, the comparison uses a heuristic to speed it up. * With this heuristic, for files with a constant small density * of changes, the algorithm is linear in the file size. */ public boolean heuristic = false; /** * When set to true, the algorithm returns a guarranteed minimal * set of changes. This makes things slower, sometimes much slower. */ public boolean no_discards = false; private int[] xvec, yvec; /* Vectors being compared. */ private int[] fdiag; /* Vector, indexed by diagonal, containing the X coordinate of the point furthest along the given diagonal in the forward search of the edit matrix. */ private int[] bdiag; /* Vector, indexed by diagonal, containing the X coordinate of the point furthest along the given diagonal in the backward search of the edit matrix. */ private int fdiagoff, bdiagoff; private final file_data[] filevec = new file_data[2]; private int cost; /** * Find the midpoint of the shortest edit script for a specified * portion of the two files. *

* We scan from the beginnings of the files, and simultaneously from the ends, * doing a breadth-first search through the space of edit-sequence. * When the two searches meet, we have found the midpoint of the shortest * edit sequence. *

* The value returned is the number of the diagonal on which the midpoint lies. * The diagonal number equals the number of inserted lines minus the number * of deleted lines (counting only lines before the midpoint). * The edit cost is stored into COST; this is the total number of * lines inserted or deleted (counting only lines before the midpoint). *

* This function assumes that the first lines of the specified portions * of the two files do not match, and likewise that the last lines do not * match. The caller must trim matching lines from the beginning and end * of the portions it is going to specify. *

* Note that if we return the "wrong" diagonal value, or if * the value of bdiag at that diagonal is "wrong", * the worst this can do is cause suboptimal diff output. * It cannot cause incorrect diff output. */ private int diag(int xoff, int xlim, int yoff, int ylim) { final int[] fd = fdiag; // Give the compiler a chance. final int[] bd = bdiag; // Additional help for the compiler. final int[] xv = xvec; // Still more help for the compiler. final int[] yv = yvec; // And more and more . . . final int dmin = xoff - ylim; // Minimum valid diagonal. final int dmax = xlim - yoff; // Maximum valid diagonal. final int fmid = xoff - yoff; // Center diagonal of top-down search. final int bmid = xlim - ylim; // Center diagonal of bottom-up search. int fmin = fmid, fmax = fmid; // Limits of top-down search. int bmin = bmid, bmax = bmid; // Limits of bottom-up search. /* True if southeast corner is on an odd diagonal with respect to the northwest. */ final boolean odd = (fmid - bmid & 1) != 0; fd[fdiagoff + fmid] = xoff; bd[bdiagoff + bmid] = xlim; for (int c = 1; ; ++c) { int d; /* Active diagonal. */ boolean big_snake = false; /* Extend the top-down search by an edit step in each diagonal. */ if (fmin > dmin) fd[fdiagoff + --fmin - 1] = -1; else ++fmin; if (fmax < dmax) fd[fdiagoff + ++fmax + 1] = -1; else --fmax; for (d = fmax; d >= fmin; d -= 2) { int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1]; if (tlo >= thi) x = tlo + 1; else x = thi; oldx = x; y = x - d; while (x < xlim && y < ylim && xv[x] == yv[y]) { ++x; ++y; } if (x - oldx > 20) big_snake = true; fd[fdiagoff + d] = x; if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) { cost = 2 * c - 1; return d; } } /* Similar extend the bottom-up search. */ if (bmin > dmin) bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE; else ++bmin; if (bmax < dmax) bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE; else --bmax; for (d = bmax; d >= bmin; d -= 2) { int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1]; if (tlo < thi) x = tlo; else x = thi - 1; oldx = x; y = x - d; while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) { --x; --y; } if (oldx - x > 20) big_snake = true; bd[bdiagoff + d] = x; if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) { cost = 2 * c; return d; } } /* Heuristic: check occasionally for a diagonal that has made lots of progress compared with the edit distance. If we have any such, find the one that has made the most progress and return it as if it had succeeded. With this heuristic, for files with a constant small density of changes, the algorithm is linear in the file size. */ if (c > 200 && big_snake && heuristic) { int best = 0; int bestpos = -1; for (d = fmax; d >= fmin; d -= 2) { int dd = d - fmid; if ((fd[fdiagoff + d] - xoff) * 2 - dd > 12 * (c + (dd > 0 ? dd : -dd))) { if (fd[fdiagoff + d] * 2 - dd > best && fd[fdiagoff + d] - xoff > 20 && fd[fdiagoff + d] - d - yoff > 20) { int k; int x = fd[fdiagoff + d]; /* We have a good enough best diagonal; now insist that it end with a significant snake. */ for (k = 1; k <= 20; k++) if (xvec[x - k] != yvec[x - d - k]) break; if (k == 21) { best = fd[fdiagoff + d] * 2 - dd; bestpos = d; } } } } if (best > 0) { cost = 2 * c - 1; return bestpos; } best = 0; for (d = bmax; d >= bmin; d -= 2) { int dd = d - bmid; if ((xlim - bd[bdiagoff + d]) * 2 + dd > 12 * (c + (dd > 0 ? dd : -dd))) { if ((xlim - bd[bdiagoff + d]) * 2 + dd > best && xlim - bd[bdiagoff + d] > 20 && ylim - (bd[bdiagoff + d] - d) > 20) { /* We have a good enough best diagonal; now insist that it end with a significant snake. */ int k; int x = bd[bdiagoff + d]; for (k = 0; k < 20; k++) if (xvec[x + k] != yvec[x - d + k]) break; if (k == 20) { best = (xlim - bd[bdiagoff + d]) * 2 + dd; bestpos = d; } } } } if (best > 0) { cost = 2 * c - 1; return bestpos; } } } } /** * Compare in detail contiguous subsequences of the two files * which are known, as a whole, to match each other. *

* The results are recorded in the vectors filevec[N].changed_flag, by * storing a 1 in the element for each line that is an insertion or deletion. *

* The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. *

* Note that XLIM, YLIM are exclusive bounds. * All line numbers are origin-0 and discarded lines are not counted. */ private void compareseq(int xoff, int xlim, int yoff, int ylim) { /* Slide down the bottom initial diagonal. */ while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) { ++xoff; ++yoff; } /* Slide up the top initial diagonal. */ while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) { --xlim; --ylim; } /* Handle simple cases. */ if (xoff == xlim) while (yoff < ylim) filevec[1].changed_flag[1 + filevec[1].realindexes[yoff++]] = true; else if (yoff == ylim) while (xoff < xlim) filevec[0].changed_flag[1 + filevec[0].realindexes[xoff++]] = true; else { /* Find a point of correspondence in the middle of the files. */ int d = diag(xoff, xlim, yoff, ylim); int c = cost; int b = bdiag[bdiagoff + d]; if (c == 1) { /* This should be impossible, because it implies that one of the two subsequences is empty, and that case was handled above without calling `diag'. Let's verify that this is true. */ throw new IllegalArgumentException("Empty subsequence"); } else { /* Use that point to split this problem into two subproblems. */ compareseq(xoff, b, yoff, b - d); /* This used to use f instead of b, but that is incorrect! It is not necessarily the case that diagonal d has a snake from b to f. */ compareseq(b, xlim, b - d, ylim); } } } /** * Discard lines from one file that have no matches in the other file. */ private void discard_confusing_lines() { filevec[0].discard_confusing_lines(filevec[1]); filevec[1].discard_confusing_lines(filevec[0]); } private boolean inhibit = false; /** * Adjust inserts/deletes of blank lines to join changes * as much as possible. */ private void shift_boundaries() { if (inhibit) return; filevec[0].shift_boundaries(filevec[1]); filevec[1].shift_boundaries(filevec[0]); } public interface ScriptBuilder { /** * Scan the tables of which lines are inserted and deleted, * producing an edit script. * * @param changed0 true for lines in first file which do not match 2nd * @param len0 number of lines in first file * @param changed1 true for lines in 2nd file which do not match 1st * @param len1 number of lines in 2nd file * @return a linked list of changes - or null */ public change build_script(boolean[] changed0, int len0, boolean[] changed1, int len1); } /** * Scan the tables of which lines are inserted and deleted, * producing an edit script in reverse order. */ static class ReverseScript implements ScriptBuilder { public change build_script(final boolean[] changed0, int len0, final boolean[] changed1, int len1) { change script = null; int i0 = 0, i1 = 0; while (i0 < len0 || i1 < len1) { if (changed0[1 + i0] || changed1[1 + i1]) { int line0 = i0, line1 = i1; /* Find # lines changed here in each file. */ while (changed0[1 + i0]) ++i0; while (changed1[1 + i1]) ++i1; /* Record this change. */ script = new change(line0, line1, i0 - line0, i1 - line1, script); } /* We have reached lines in the two files that match each other. */ i0++; i1++; } return script; } } static class ForwardScript implements ScriptBuilder { /** * Scan the tables of which lines are inserted and deleted, * producing an edit script in forward order. */ public change build_script(final boolean[] changed0, int len0, final boolean[] changed1, int len1) { change script = null; int i0 = len0, i1 = len1; while (i0 >= 0 || i1 >= 0) { if (changed0[i0] || changed1[i1]) { int line0 = i0, line1 = i1; /* Find # lines changed here in each file. */ while (changed0[i0]) --i0; while (changed1[i1]) --i1; /* Record this change. */ script = new change(i0, i1, line0 - i0, line1 - i1, script); } /* We have reached lines in the two files that match each other. */ i0--; i1--; } return script; } } /** * Standard ScriptBuilders. */ public final static ScriptBuilder forwardScript = new ForwardScript(), reverseScript = new ReverseScript(); /* Report the differences of two files. DEPTH is the current directory depth. */ public final change diff_2(final boolean reverse) { return diff(reverse ? reverseScript : forwardScript); } /** * Get the results of comparison as an edit script. The script * is described by a list of changes. The standard ScriptBuilder * implementations provide for forward and reverse edit scripts. * Alternate implementations could, for instance, list common elements * instead of differences. * * @param bld an object to build the script from change flags * @return the head of a list of changes */ public change diff(final ScriptBuilder bld) { /* Some lines are obviously insertions or deletions because they don't match anything. Detect them now, and avoid even thinking about them in the main comparison algorithm. */ discard_confusing_lines(); /* Now do the main comparison algorithm, considering just the undiscarded lines. */ xvec = filevec[0].undiscarded; yvec = filevec[1].undiscarded; int diags = filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3; fdiag = new int[diags]; fdiagoff = filevec[1].nondiscarded_lines + 1; bdiag = new int[diags]; bdiagoff = filevec[1].nondiscarded_lines + 1; compareseq(0, filevec[0].nondiscarded_lines, 0, filevec[1].nondiscarded_lines); fdiag = null; bdiag = null; /* Modify the results slightly to make them prettier in cases where that can validly be done. */ shift_boundaries(); /* Get the results of comparison in the form of a chain of `struct change's -- an edit script. */ return bld.build_script(filevec[0].changed_flag, filevec[0].buffered_lines, filevec[1].changed_flag, filevec[1].buffered_lines); } /** * The result of comparison is an "edit script": a chain of change objects. * Each change represents one place where some lines are deleted * and some are inserted. *

* LINE0 and LINE1 are the first affected lines in the two files (origin 0). * DELETED is the number of lines deleted here from file 0. * INSERTED is the number of lines inserted here in file 1. *

* If DELETED is 0 then LINE0 is the number of the line before * which the insertion was done; vice versa for INSERTED and LINE1. */ public static class change { /** * Previous or next edit command. */ public change link; /** * # lines of file 1 changed here. */ public final int inserted; /** * # lines of file 0 changed here. */ public final int deleted; /** * Line number of 1st deleted line. */ public final int line0; /** * Line number of 1st inserted line. */ public final int line1; /** * Cons an additional entry onto the front of an edit script OLD. * LINE0 and LINE1 are the first affected lines in the two files (origin 0). * DELETED is the number of lines deleted here from file 0. * INSERTED is the number of lines inserted here in file 1. *

* If DELETED is 0 then LINE0 is the number of the line before * which the insertion was done; vice versa for INSERTED and LINE1. */ public change(int line0, int line1, int deleted, int inserted, change old) { this.line0 = line0; this.line1 = line1; this.inserted = inserted; this.deleted = deleted; this.link = old; //System.err.println(line0+","+line1+","+inserted+","+deleted); } } /** * Data on one input file being compared. */ class file_data { /** * Allocate changed array for the results of comparison. */ void clear() { /* Allocate a flag for each line of each file, saying whether that line is an insertion or deletion. Allocate an extra element, always zero, at each end of each vector. */ changed_flag = new boolean[buffered_lines + 2]; } /** * Return equiv_count[I] as the number of lines in this file * that fall in equivalence class I. * * @return the array of equivalence class counts. */ int[] equivCount() { int[] equiv_count = new int[equiv_max]; for (int i = 0; i < buffered_lines; ++i) ++equiv_count[equivs[i]]; return equiv_count; } /** * Discard lines that have no matches in another file. *

* A line which is discarded will not be considered by the actual * comparison algorithm; it will be as if that line were not in the file. * The file's `realindexes' table maps virtual line numbers * (which don't count the discarded lines) into real line numbers; * this is how the actual comparison algorithm produces results * that are comprehensible when the discarded lines are counted. *

* When we discard a line, we also mark it as a deletion or insertion * so that it will be printed in the output. * * @param f the other file */ void discard_confusing_lines(file_data f) { clear(); /* Set up table of which lines are going to be discarded. */ final byte[] discarded = discardable(f.equivCount()); /* Don't really discard the provisional lines except when they occur in a run of discardables, with nonprovisionals at the beginning and end. */ filterDiscards(discarded); /* Actually discard the lines. */ discard(discarded); } /** * Mark to be discarded each line that matches no line of another file. * If a line matches many lines, mark it as provisionally discardable. * * @param counts The count of each equivalence number for the other file. * @return 0=nondiscardable, 1=discardable or 2=provisionally discardable * for each line */ private byte[] discardable(final int[] counts) { final int end = buffered_lines; final byte[] discards = new byte[end]; final int[] equivs = this.equivs; int many = 5; int tem = end / 64; /* Multiply MANY by approximate square root of number of lines. That is the threshold for provisionally discardable lines. */ while ((tem = tem >> 2) > 0) many *= 2; for (int i = 0; i < end; i++) { int nmatch; if (equivs[i] == 0) continue; nmatch = counts[equivs[i]]; if (nmatch == 0) discards[i] = 1; else if (nmatch > many) discards[i] = 2; } return discards; } /** * Don't really discard the provisional lines except when they occur * in a run of discardables, with nonprovisionals at the beginning * and end. */ private void filterDiscards(final byte[] discards) { final int end = buffered_lines; for (int i = 0; i < end; i++) { /* Cancel provisional discards not in middle of run of discards. */ if (discards[i] == 2) discards[i] = 0; else if (discards[i] != 0) { /* We have found a nonprovisional discard. */ int j; int length; int provisional = 0; /* Find end of this run of discardable lines. Count how many are provisionally discardable. */ for (j = i; j < end; j++) { if (discards[j] == 0) break; if (discards[j] == 2) ++provisional; } /* Cancel provisional discards at end, and shrink the run. */ while (j > i && discards[j - 1] == 2) { discards[--j] = 0; --provisional; } /* Now we have the length of a run of discardable lines whose first and last are not provisional. */ length = j - i; /* If 1/4 of the lines in the run are provisional, cancel discarding of all provisional lines in the run. */ if (provisional * 4 > length) { while (j > i) if (discards[--j] == 2) discards[j] = 0; } else { int consec; int minimum = 1; int tem = length / 4; /* MINIMUM is approximate square root of LENGTH/4. A subrun of two or more provisionals can stand when LENGTH is at least 16. A subrun of 4 or more can stand when LENGTH >= 64. */ while ((tem = tem >> 2) > 0) minimum *= 2; minimum++; /* Cancel any subrun of MINIMUM or more provisionals within the larger run. */ for (j = 0, consec = 0; j < length; j++) if (discards[i + j] != 2) consec = 0; else if (minimum == ++consec) /* Back up to start of subrun, to cancel it all. */ j -= consec; else if (minimum < consec) discards[i + j] = 0; /* Scan from beginning of run until we find 3 or more nonprovisionals in a row or until the first nonprovisional at least 8 lines in. Until that point, cancel any provisionals. */ for (j = 0, consec = 0; j < length; j++) { if (j >= 8 && discards[i + j] == 1) break; if (discards[i + j] == 2) { consec = 0; discards[i + j] = 0; } else if (discards[i + j] == 0) consec = 0; else consec++; if (consec == 3) break; } /* I advances to the last line of the run. */ i += length - 1; /* Same thing, from end. */ for (j = 0, consec = 0; j < length; j++) { if (j >= 8 && discards[i - j] == 1) break; if (discards[i - j] == 2) { consec = 0; discards[i - j] = 0; } else if (discards[i - j] == 0) consec = 0; else consec++; if (consec == 3) break; } } } } } /** * Actually discard the lines. * * @param discards flags lines to be discarded */ private void discard(final byte[] discards) { final int end = buffered_lines; int j = 0; for (int i = 0; i < end; ++i) if (no_discards || discards[i] == 0) { undiscarded[j] = equivs[i]; realindexes[j++] = i; } else changed_flag[1 + i] = true; nondiscarded_lines = j; } file_data(Object[] data, Hashtable h) { buffered_lines = data.length; equivs = new int[buffered_lines]; undiscarded = new int[buffered_lines]; realindexes = new int[buffered_lines]; for (int i = 0; i < data.length; ++i) { Integer ir = (Integer) h.get(data[i]); if (ir == null) h.put(data[i], new Integer(equivs[i] = equiv_max++)); else equivs[i] = ir.intValue(); } } /** * Adjust inserts/deletes of blank lines to join changes * as much as possible. *

* We do something when a run of changed lines include a blank * line at one end and have an excluded blank line at the other. * We are free to choose which blank line is included. * `compareseq' always chooses the one at the beginning, * but usually it is cleaner to consider the following blank line * to be the "change". The only exception is if the preceding blank line * would join this change to other changes. * * @param f the file being compared against */ void shift_boundaries(file_data f) { final boolean[] changed = changed_flag; final boolean[] other_changed = f.changed_flag; int i = 0; int j = 0; int i_end = buffered_lines; int preceding = -1; int other_preceding = -1; for (; ;) { int start, end, other_start; /* Scan forwards to find beginning of another run of changes. Also keep track of the corresponding point in the other file. */ while (i < i_end && !changed[1 + i]) { while (other_changed[1 + j++]) /* Non-corresponding lines in the other file will count as the preceding batch of changes. */ other_preceding = j; i++; } if (i == i_end) break; start = i; other_start = j; for (; ;) { /* Now find the end of this run of changes. */ while (i < i_end && changed[1 + i]) i++; end = i; /* If the first changed line matches the following unchanged one, and this run does not follow right after a previous run, and there are no lines deleted from the other file here, then classify the first changed line as unchanged and the following line as changed in its place. */ /* You might ask, how could this run follow right after another? Only because the previous run was shifted here. */ if (end != i_end && equivs[start] == equivs[end] && !other_changed[1 + j] && end != i_end && !((preceding >= 0 && start == preceding) || (other_preceding >= 0 && other_start == other_preceding))) { changed[1 + end] = true; changed[1 + start++] = false; ++i; /* Since one line-that-matches is now before this run instead of after, we must advance in the other file to keep in synch. */ ++j; } else break; } preceding = i; other_preceding = j; } } /** * Number of elements (lines) in this file. */ final int buffered_lines; /** * Vector, indexed by line number, containing an equivalence code for * each line. It is this vector that is actually compared with that * of another file to generate differences. */ private final int[] equivs; /** * Vector, like the previous one except that * the elements for discarded lines have been squeezed out. */ final int[] undiscarded; /** * Vector mapping virtual line numbers (not counting discarded lines) * to real ones (counting those lines). Both are origin-0. */ final int[] realindexes; /** * Total number of nondiscarded lines. */ int nondiscarded_lines; /** * Array, indexed by real origin-1 line number, * containing true for a line that is an insertion or a deletion. * The results of comparison are stored here. */ boolean[] changed_flag; } } static class BlockDiff { public CopyBlock asCopyBlock() { return null; } public NewBlock asNewBlock () { return null; } } static class CopyBlock extends BlockDiff { int firstLine, lines; CopyBlock(int firstLine, int lines) { this.firstLine = firstLine; this.lines = lines; } public CopyBlock asCopyBlock() { return this; } public int getFirstLine() { return firstLine; } public int getLines() { return lines; } } static class NewBlock extends BlockDiff { int originalStart; List contents; NewBlock(int originalStart, List contents) { this.originalStart = originalStart; this.contents = contents; } public NewBlock asNewBlock () { return this; } public int getOriginalStart() { return originalStart; } public List getContents() { return contents; } } static class ExplodedLine { int type; String left, right; int leftIndex, rightIndex; ExplodedLine(int type, String left, String right, int leftIndex, int rightIndex) { this.type = type; this.left = left; this.right = right; this.leftIndex = leftIndex; this.rightIndex = rightIndex; } public int getType() { return type; } public String getLeft() { return left; } public String getRight() { return right; } public int getLeftIndex() { return leftIndex; } public int getRightIndex() { return rightIndex; } } static class BlockDiffer { public static final int IDENTICAL = 0; public static final int DIFFERENT = 1; public static final int LEFT_ONLY = 2; public static final int RIGHT_ONLY = 3; private static void printChange(EGDiff.change change) { if (change != null) { System.out.println("line0="+change.line0+", line1="+change.line1 +", inserted="+change.inserted+", deleted="+change.deleted); printChange(change.link); } } /** Generates the text content of a Unified-format context diff between 2 files * (NB the 'files-changed' header must be added separately). */ public static List generateUniDiff(List fileA, List fileB, int contextSize) { EGDiff diff = new EGDiff(fileA.toArray(), fileB.toArray()); EGDiff.change change = diff.diff_2(false); if (change != null) { int inserted, deleted; List hunkLines = new ArrayList(); int cumulExtraLinesBwrtA = 0; // Each hunk is generated with a header do { int line0 = change.line0, line1 = change.line1; int changeStart = ((line1 < line0) ? line1 : line0); int contextStart = ((changeStart > contextSize) ? changeStart - contextSize : 0); int headerPosn = hunkLines.size(); // Provide the first lines of context for (int i = contextStart; i < changeStart; i++) //System.out.println(" " + fileA.get(i)); hunkLines.add(" " + fileA.get(i)); boolean hunkFinish = false; // Step through each change giving the change lines and following context do { inserted = change.inserted; deleted = change.deleted; line0 = change.line0; line1 = change.line1; if (line1 < line0) // An insert comes earlier while (inserted-- > 0) hunkLines.add("+" + fileB.get(line1++)); while (deleted-- > 0) hunkLines.add("-" + fileA.get(line0++)); while (inserted-- > 0) hunkLines.add("+" + fileB.get(line1++)); // Lines following are trailing context, identical in fileA and fileB // The next change may overlap the context, so check and if so, form one hunk EGDiff.change nextChange = change.link; int nextChangeStart = fileA.size(); if (nextChange != null) nextChangeStart = ((nextChange.line1 < nextChange.line0) ? nextChange.line1 : nextChange.line0); if (nextChangeStart - line0 > contextSize * 2) { // A separate hunk nextChangeStart = line0 + contextSize; hunkFinish = true; } if (nextChangeStart > fileA.size()) nextChangeStart = fileA.size(); // Limit to file size while (line0 < nextChangeStart) { hunkLines.add(" " + fileA.get(line0++)); line1++; // Keep in sync with trailing context } change = change.link; } while (!hunkFinish && change != null); int hunkStartB = contextStart + cumulExtraLinesBwrtA; int hunkTotA = line0 - contextStart; int hunkTotB = line1 - hunkStartB; hunkLines.add(headerPosn, "@@ -" + (contextStart + 1) + ',' + hunkTotA + " +" + (hunkStartB + 1) + ',' + hunkTotB + " @@"); cumulExtraLinesBwrtA += hunkTotB - hunkTotA; } while (change != null); return hunkLines; } return null; } /* For testing: private static void printUniDiff(List fileA, List fileB, int contextSize) { List uniDiff = generateUniDiff(fileA, fileB, contextSize); if (uniDiff != null) for (int j = 0; j < uniDiff.size(); j++) System.out.println(uniDiff.get(j)); } */ public static List diffLines(List lines, List reference) { List diffs = new ArrayList(); EGDiff diff = new EGDiff(reference.toArray(), lines.toArray()); EGDiff.change change = diff.diff_2(false); //printChange(change); //printUniDiff(reference, lines, 3); int l0 = 0, l1 = 0; while (change != null) { if (change.line0 > l0 && change.line1 > l1) diffs.add(new CopyBlock(l0, change.line0-l0)); if (change.inserted != 0) diffs.add(new NewBlock(change.line1, lines.subList(change.line1, change.line1+change.inserted))); l0 = change.line0 + change.deleted; l1 = change.line1 + change.inserted; change = change.link; } if (l0 < reference.size()) diffs.add(new CopyBlock(l0, reference.size()-l0)); return diffs; } /** fills files with empty lines to align matching blocks * * @param file1 first file * @param file2 second file * @return an array with two lists */ public static List explode(List file1, List file2) { List lines = new ArrayList(); List diffs = BlockDiffer.diffLines(file2, file1); int lastLineCopied = 0, rightOnlyStart = -1, rightPosition = 0; for (int i = 0; i < diffs.size(); i++) { BlockDiff diff = diffs.get(i); if (diff instanceof CopyBlock) { CopyBlock copyBlock = (CopyBlock) diff; if (lastLineCopied < copyBlock.getFirstLine()) { if (rightOnlyStart >= 0) { int overlap = Math.min(lines.size()-rightOnlyStart, copyBlock.getFirstLine()-lastLineCopied); //lines.subList(rightOnlyStart, rightOnlyStart+overlap).clear(); convertRightOnlyToDifferent(lines, rightOnlyStart, overlap, file1, lastLineCopied); lastLineCopied += overlap; } addBlock(lines, LEFT_ONLY, file1, lastLineCopied, copyBlock.getFirstLine(), lastLineCopied, -1); } addBlock(lines, IDENTICAL, file1, copyBlock.getFirstLine(), copyBlock.getFirstLine()+copyBlock.getLines(), copyBlock.getFirstLine(), rightPosition); rightPosition += copyBlock.getLines(); lastLineCopied = copyBlock.getFirstLine()+copyBlock.getLines(); rightOnlyStart = -1; } else if (diff instanceof NewBlock) { NewBlock newBlock = (NewBlock) diff; /*if (nextDiff instanceof BlockDiffer.CopyBlock) { BlockDiffer.CopyBlock copyBlock = (BlockDiffer.CopyBlock) nextDiff; copyBlock.getFirstLine()-lastLineCopied*/ rightOnlyStart = lines.size(); addBlock(lines, RIGHT_ONLY, newBlock.getContents(), 0, newBlock.getContents().size(), -1, rightPosition); rightPosition += newBlock.getContents().size(); } } if (rightOnlyStart >= 0) { int overlap = Math.min(lines.size()-rightOnlyStart, file1.size()-lastLineCopied); //lines.subList(rightOnlyStart, rightOnlyStart+overlap).clear(); convertRightOnlyToDifferent(lines, rightOnlyStart, overlap, file1, lastLineCopied); lastLineCopied += overlap; } addBlock(lines, LEFT_ONLY, file1, lastLineCopied, file1.size(), lastLineCopied, -1); return lines; } private static void convertRightOnlyToDifferent(List lines, int start, int numLines, List leftLines, int leftStart) { for (int i = 0; i < numLines; i++) { ExplodedLine line = lines.get(start+i); lines.set(start+i, new ExplodedLine(DIFFERENT, leftLines.get(i+leftStart), line.getRight(), i+leftStart, line.getRightIndex())); } } private static void addBlock(List lines, int type, List srcLines, int start, int end, int leftStart, int rightStart) { for (int i = start; i < end; i++) lines.add(new ExplodedLine(type, type == RIGHT_ONLY ? "" : srcLines.get(i), type == LEFT_ONLY ? "" : srcLines.get(i), type == RIGHT_ONLY ? -1 : i - start + leftStart, type == LEFT_ONLY ? -1 : i - start + rightStart)); } public static List condense(List lines) { List result = new ArrayList(); for (Iterator i = lines.iterator(); i.hasNext();) { ExplodedLine line = i.next(); if (line.getType() == IDENTICAL) { if (result.isEmpty() || result.get(result.size()-1).getType() != IDENTICAL) result.add(new ExplodedLine(IDENTICAL, "[...]", "[...]", -1, -1)); } else result.add(line); } return result; } } static abstract class DialogIO implements AutoCloseable { String line; boolean eos, loud, noClose; Lock lock = lock(); abstract String readLineImpl(); abstract boolean isStillConnected(); abstract void sendLine(String line); abstract boolean isLocalConnection(); abstract Socket getSocket(); int getPort() { Socket s = getSocket(); return s == null ? 0 : s.getPort(); } boolean helloRead = false; int shortenOutputTo = 500; String readLineNoBlock() { String l = line; line = null; return l; } boolean waitForLine() { try { ping(); if (line != null) return true; //print("Readline"); line = readLineImpl(); //print("Readline done: " + line); if (line == null) eos = true; return line != null; } catch (Exception __e) { throw rethrow(__e); } } String readLine() { waitForLine(); helloRead = true; return readLineNoBlock(); } String ask(String s, Object... args) { if (loud) return askLoudly(s, args); if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); sendLine(s); return readLine(); } String askLoudly(String s, Object... args) { if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); print("> " + shorten(s, shortenOutputTo)); sendLine(s); String answer = readLine(); print("< " + shorten(answer, shortenOutputTo)); return answer; } void pushback(String l) { if (line != null) throw fail(); line = l; helloRead = false; } } static abstract class DialogHandler { abstract void run(DialogIO io); } static class CompilerBot { static boolean verbose = false; static File compileSnippet(String snippetID) { return compileSnippet(snippetID, ""); } static Pair compileSnippet2(String snippetID) { return compileSnippet2(snippetID, ""); } // returns jar path static File compileSnippet(String snippetID, String javaTarget) { return compileSnippet2(snippetID, javaTarget).a; } // returns jar path, Java source static Pair compileSnippet2(String snippetID, String javaTarget) { String transpiledSrc = getServerTranspiled2(snippetID); int i = transpiledSrc.indexOf('\n'); String libs = transpiledSrc.substring(0, Math.max(0, i)); if (verbose) print("Compiling snippet: " + snippetID + ". Libs: " + libs); transpiledSrc = transpiledSrc.substring(i+1); return pair(compile(transpiledSrc, libs, javaTarget, snippetID), transpiledSrc); } static File compile(String src) { return compile(src, ""); } static File compile(String src, String libs) { return compile(src, libs, null); } static File compile(String src, String dehlibs, String javaTarget) { return compile(src, dehlibs, javaTarget, null); } static File compile(String src, String dehlibs, String javaTarget, String progID) { if (verbose) print("Compiling " + l(src) + " chars"); // Note: This is different from the calculation in x30 // (might lead to programs being compiled twice) String md5 = md5(dehlibs + "\n" + src + "\n" + fsIOpt(progID)); File jar = getJarFile(md5); if (jar == null || jar.length() <= 22) { // have to compile print("Have to compile: " + progID + " / " + md5); List mainClass = findMainClass(javaTok(src)); boolean canRename = mainClass != null && useDummyMainClasses() && isSnippetID(progID) && !tok_classHasModifier(mainClass, "public"); if (verbose) print("useRenaming: " + useDummyMainClasses() + ", canRename: " + canRename + ", progID: " + progID); javaCompileToJar_optionalRename(src, dehlibs, jar, canRename ? progID : null, progID); } else { if (verbose) print("Getting classes from cache (" + jar.getAbsolutePath() + ", " + jar.length() + " bytes)"); touchFile(jar); // so we can find the unused ones easier } return jar; } // look in non-virtual JavaX-Caches first (important for packaged programs) static File getJarFile(String md5) { assertTrue(isMD5(md5)); String sub = "JavaX-Caches/#1002203/" + md5 + ".jar"; File f = actualUserDir(sub); return fileExists(f) ? f : userDir(sub); } } static boolean isTrue(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o == null) return false; if (o instanceof ThreadLocal) return isTrue(((ThreadLocal) o).get()); throw fail(getClassName(o)); } static String unquote(String s) { if (s == null) return null; if (s.startsWith("[")) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i+1, s.length()-i-1); } } if ((s.startsWith("\"") || s.startsWith("\'")) && s.length() > 1) { int l = s.endsWith(substring(s, 0, 1)) ? s.length()-1 : s.length(); StringBuilder sb = new StringBuilder(l-1); for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch (nextChar) { case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\"': ch = '\"'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt( "" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: ch = nextChar; // added by Stefan } i++; } sb.append(ch); } return sb.toString(); } return s; // not quoted - return original } static String transpilingSnippetID; static AtomicInteger varCount = new AtomicInteger(); static Map snippetCache = new HashMap(); static boolean useIndexedList = true, opt_javaTok = true; static boolean cacheStdFunctions = true, cacheStdClasses = true; static HashMap cachedIncludes = new HashMap(); static ExecutorService executor; static List lclasses; static long startTime, lastPrint; // These variables have to be cleared manually for each transpilation static HashSet included = new HashSet(); static Set definitions = ciSet(); static HashMap rewrites = new HashMap(); static HashSet shouldNotIncludeFunction = new HashSet(), shouldNotIncludeClass = new HashSet(); static HashSet doNotIncludeFunction = new HashSet(); static HashSet addedFunctions = new HashSet(); static HashSet addedClasses = new HashSet(); static HashSet hardFunctionReferences = new HashSet(); static HashSet mapLikeFunctions = new HashSet(); static HashSet mapMethodLikeFunctions = new HashSet(); static HashSet nuLikeFunctions = new HashSet(); static Map extraStandardFunctions; static boolean quickmainDone1, quickmainDone2; static TreeSet libs = new TreeSet(); static String mainBaseClass, mainPackage, mainClassName; static boolean localStuffOnly = false; // for transpiling a fragment static boolean asInclude = false; // for transpiling an include (auto-close scopes) static boolean allowMetaCode = false; // run any embedded meta code static List metaPostBlocks, metaTransformers; static boolean dontPrintSource = false; static class CachedInclude { String javax; Future java; String realJava; String java() { return realJava != null ? realJava : getFuture(java); } Future javaFuture() { return realJava != null ? nowFuture(realJava) : java; } void clean() { if (java != null) { realJava = getFuture(java); java = null; } } } public static void main(final String[] args) throws Exception { startTime = lastPrint = sysNow(); try { vmKeepWithProgramMD5_get("cachedIncludes"); } catch (Throwable __e) { _handleException(__e); } executor = Executors.newFixedThreadPool(numberOfCores()); transpilingSnippetID = or(getThreadLocal((ThreadLocal) getOpt(javax(), "transpilingSnippetID")), transpilingSnippetID); print("transpilingSnippetID", transpilingSnippetID); transpileRaw_dontCopyFromCreator = true; final Object oldPrint = or(print_byThread().get(), "print_raw"); AutoCloseable __11 = tempInterceptPrint(new F1() { Boolean get(String s) { long now = sysNow(); long time = now-lastPrint; // -startTime; lastPrint = now; callF(oldPrint, "[" + formatInt(time/1000, 2) + ":" + formatInt(time % 1000, 3) + "] " + s); return false; } }); try { try { _main(); } finally { interceptPrintInThisThread(oldPrint); if (executor != null) executor.shutdown(); executor = null; localStuffOnly = false; asInclude = false; } } finally { _close(__11); }} static void _main() { try { if (sameSnippetID(programID(), defaultJavaXTranslatorID())) setDefaultJavaXTranslatorID("#7"); //reTok_modify_check = true; //if (useIndexedList) findCodeTokens_debug = true; javaTok_opt = opt_javaTok; //findCodeTokens_indexed = findCodeTokens_unindexed = 0; findCodeTokens_bails = findCodeTokens_nonbails = 0; javaTok_n = javaTok_elements = 0; String in = loadMainJava(); print("759 STARTING " + identityHashCode(main.class)); included.clear(); definitions.clear(); rewrites.clear(); definitions.add("SymbolAsString"); shouldNotIncludeFunction.clear(); shouldNotIncludeClass.clear(); doNotIncludeFunction.clear(); addedFunctions.clear(); addedClasses.clear(); hardFunctionReferences.clear(); mapLikeFunctions = cloneHashSet(tok_mapLikeFunctions()); mapMethodLikeFunctions = cloneHashSet(tok_mapMethodLikeFunctions()); nuLikeFunctions.clear(); extraStandardFunctions = new HashMap(); libs.clear(); mainBaseClass = mainPackage = mainClassName = null; varCount.set(0); quickmainDone1 = quickmainDone2 = false; metaPostBlocks = new ArrayList(); metaTransformers = new ArrayList(); dontPrintSource = false; //L ts = findTranslators(toLines(join(tok))); //print("Translators in source at start: " + structure(ts)); // "duplicate" statement - unused /*L lines = toLines(in); call(getJavaX(), "findTranslators", lines); in = fromLines(lines); new Matches m; if (match("duplicate *", in, m)) { // actual copying - unused // tok = jtok(loadSnippet(m.get(0))); // reference by include() in = "m { p { callMain(include(" + quote(m.get(0)) + ")); } }"; }*/ List tok = jtok(in); try { tok_definitions(tok); // add m { } if (!localStuffOnly && !hasCodeTokens(tok, "m", "{") && !hasCodeTokens(tok, "main", "{") && !hasCodeTokens(tok, "class", "main")) { //tok = jtok(moveImportsUp("m {\n" + in + "\n}")); if (l(tok) == 1) tok = singlePlusList(first(tok), dropFirst(javaTok("m {}"))); else { replaceTokens_reTok(tok, 1, 2, "m {\n\n" + unnull(get(tok, 1))); replaceTokens_reTok(tok, l(tok)-2, l(tok)-1, unnull(get(tok, l(tok)-2)) + "}"); } tok_moveImportsUp(tok); } // standard translate //ts = findTranslators(toLines(join(tok))); //print("Translators in source: " + structure(ts)); if (tok_hasTranslators(tok)) tok = jtok(defaultTranslate(join(tok))); //print("end of default translate"); //print(join(tok)); //tok_autoCloseBrackets(tok); tok_metaTransformNow(tok); tok_compactModules(tok); tok = tok_processIncludes(tok); // before standard functions if (processConceptsDot(tok)) tok = tok_processIncludes(tok); tok = localStuff1(tok); if (!localStuffOnly) { int safety = 0; boolean same = false; do { // BIG LOOP String before = join(tok); // do the non-local stuff (flags and rewrites, things that correlate across includes like tok_selfType) tok_selfType(tok); tok_mainClassNameAndPackage(tok); tok_definitions(tok); tok_ifndef(tok); tok_ifdef(tok); defineMapLikes(tok); if (tok_applyMapLikeFunctions(tok, mapLikeFunctions)) functionReferences(tok); defineMapMethodLikes(tok); tok_applyMapMethodLikeFunctions(tok, mapMethodLikeFunctions); defineNuLikes(tok); tok_applyNuLikeFunctions(tok, nuLikeFunctions); tok_dropExtraCommas(tok); // from e.g. tok_applyMapMethodLikeFunctions tok_delegateTo(tok); tok_replaceWith(tok); tok_findRewrites(tok); tok_processRewrites(tok); // main bla(...) => mainClassName.bla(...) jreplace(tok, "main (", or(mainClassName, "main") + ".$2("); try { if (safety == 0) tok = quickmain(tok); } catch (Throwable e) { printSources(tok); rethrow(e); } tok_collectMetaPostBlocks(tok, metaPostBlocks); tok_collectTransformers(tok, metaTransformers); tok_metaTransformNow(tok); // Hack to allow DynModule to reimplement _registerThread /*if (tok.contains("DynModule") && !addedClasses.contains("DynModule")) addStandardClasses_v2(tok);*/ defineExtraSF(tok); tok = standardFunctions(tok); tok = stdstuff(tok); // all the keywords, standard String diff; long startTime = now(); //diff = unidiff(before, join(tok)); //print("unidiff: " + (now()-startTime) + " ms"); //same = eq(diff, ""); same = tok_sameTest(tok, before); if (!same) { print("Not same " + safety + "."); //print(indent(2, diff)); } if (safety++ >= 10) { //print(unidiff(before, join(tok))); printSources(tok); throw fail("safety 10 error!"); } } while (!same); // END OF BIG LOOP print("Post."); if (mainBaseClass != null) { jreplace1(tok, "class main", "class main extends " + mainBaseClass); mainBaseClass = null; } print("moveImportsUp"); tok_moveImportsUp(tok); print("Indexing"); tok = indexedList2(tok); // POST-PROCESSING after stdstuff loop if (transpilingSnippetID != null) jreplace_dyn(tok, "class whatever", new F2, Integer, String>() { String get(List tok, Integer cIndex) { try { try { return "class " + stringToLegalIdentifier(getSnippetTitle(transpilingSnippetID)); } catch (Throwable __e) { _handleException(__e); } return "class Whatever"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcall { ret \"class \" + stringToLegalIdentifier(getSnippetTitle(transpilingSni..."; }}); //print("Type"); // Type to Type print("extendClasses"); tok = extendClasses(tok); print("libs"); libs(tok); print("sourceCodeLine"); sourceCodeLine(tok); tok_overridableFunctionDefs(tok, null); // escaping for lambdas //jreplace(tok, "-=>", "->"); // Stuff that depends on the list of inner classes (haveClasses) HashSet haveClasses = haveClasses_actual(tok); print("innerClassesVar"); innerClassesVar(tok, haveClasses); fillVar_transpilationDate(tok); haveClasses_addImported(tok, haveClasses); print("ifclass"); tok_ifclass(tok, haveClasses); print("slashCasts"); slashCasts(tok, haveClasses); print("newWithoutNew"); newWithoutNew(tok, haveClasses); if (!assumeTriple) { print("Triple"); if (tok.contains("Triple") && !haveClasses.contains("Triple")) { jreplace(tok, "Triple", "T3"); haveClasses.remove("Triple"); haveClasses.add("T3"); slashCasts(tok, lithashset("T3")); tok_quickInstanceOf(tok, lithashset("T3")); } expandTriple(tok); } if (hasDef("SymbolAsString")) jreplace(tok, "Symbol", "String"); print("classReferences"); expandClassReferences_lazy(tok, haveClasses); if (metaCodeAllowed()) runMetaPostBlocks(tok); // Error-checking print("Error-checking"); Set functions = new HashSet(findFunctions(tok)); for (String f : hardFunctionReferences) if (!functions.contains(f)) throw fail("Function " + f + " requested, but not supplied"); print("autoImports"); tok = autoImports(tok); // faster to do it at the end print("definitions=" + sfu(definitions)); if (containsOneOfIC(definitions, "allpublic", "reparse", "PublicExceptTopClass")) { // Fire up the Java parser & pretty printer! print(containsIC(definitions, "allpublic")? "Making all public." : "Reparsing."); //try { String src = join(tok); try { if (containsIC(definitions, "PublicExceptTopClass")) src = javaParser_makeAllPublic(src, "notTopLevelClassDecl" , true); else if (containsIC(definitions, "keepComments")) src = javaParser_makeAllPublic_keepComments(src); else if (containsIC(definitions, "allpublic")) src = javaParser_makeAllPublic(src); else src = javaParser_reparse_keepComments(src); } catch (Throwable e) { extractAndPrintJavaParseError(src, e); File f = javaxCachesDir("error-source.java"); saveTextFileVerbose(f, src); dontPrintSource = true; throw e; } tok = jtok(src); /*} catch e { S src = join(tok); if (!dontPrintSource) print(src); print(f2s(saveProgramTextFile("error.java", src))); throw rethrow(e); }*/ } // Do this after JavaParser (because it doesn't like package after class) if (mainPackage != null) { print("mainPackage"); tokPrepend(tok, 1, "package " + mainPackage + ";\n"); reTok(tok, 1, 2); } if (mainClassName != null) { print("mainClassName"); jreplace(tok, "class main", "class " + mainClassName); jreplace(tok, "main.class", mainClassName + ".class"); //tokPrepend(tok, 1, "class main {}\n"); // so main.class is generated and compiler sanity checks succeed. we can later skip it in the JavaXClassLoader } if (nempty(libs)) { print("Adding libs: " + libs); tok.add(concatMap_strings(new F1() { String get(String s) { try { return "\n!" + s; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "\"\\n!\" + s"; }}, libs)); } } // if (!localStuffOnly) } catch (Throwable e) { String src = join(tok); if (!dontPrintSource) print(src); print(f2s(saveProgramTextFile("error.java", src))); throw rethrow(e); } /*if (useIndexedList) print("Indexed/unindexed lookups: " + findCodeTokens_indexed + "/" + findCodeTokens_unindexed + ", lists made: " + IndexedList2.instances); print("findCodeToken bails: " + findCodeTokens_bails + "/" + findCodeTokens_nonbails); print("javaToks: " + javaTok_n + "/" + javaTok_elements);*/ print("Saving."); // for dexcompile.php if (mainClassName != null) tokPrepend(tok, 0, "//FILENAME: " + (mainPackage != null ? mainPackage.replace(".", "/") + "/" : "") + mainClassName + ".java\n"); if (mainJava != null) mainJava = join(tok); else if (tok.contains("package")) splitJavaFiles(tok); else saveMainJava(tok); } catch (Exception __e) { throw rethrow(__e); } } static List localStuff1(List tok) { int safety = 0, i; boolean same = false; tok = indexedList2(tok); tok_scopes(tok, "autoCloseScopes" , true); do { String before = join(tok); earlyStuff(tok); conceptDeclarations(tok); tok_recordDecls(tok); tok = multilineStrings(tok); tok_singleQuoteIdentifiersToStringConstants(tok); inStringEvals(tok); tok_listComprehensions(tok); tok_for_single(tok); tok_for_unpair(tok); // Do this... tok_doubleFor_v2(tok); // ...before this tok_forUnnull(tok); tok_ifCast(tok); forPing(tok); tok_directSnippetRefs(tok); quicknu(tok); //tok_juxtaposeCalls(tok); jreplace(tok, "LLS", "L"); jreplace(tok, "LS", "L"); jreplace(tok, "ES", "Ext"); jreplace(tok, "ExtS", "Ext"); jreplace(tok, "dispose ;", "{ cleanUp($2); $2 = null; }"); jreplace(tok, "do ping {", "do { ping();"); replaceKeywordBlock(tok, "swing", "{ swing(r {", "}); }"); replaceKeywordBlock(tok, "androidUI", "{ androidUI(r {", "}); }"); replaceKeywordBlock(tok, "withDBLock", "{ withDBLock(r {", "}); }"); replaceKeywordBlock(tok, "afterwards", "temp tempAfterwards(r {", "});"); for (String keyword : ll("tokcondition", "tokCondition")) replaceKeywordBlock(tok, keyword, "new TokCondition { bool get(final L tok, final int i) {", "}}"); jreplace(tok, "synced ", "synchronized $2"); jreplace(tok, "sync ", "synchronized $2"); replaceKeywordBlock(tok, "answer", "static S answer(S s) {\nfinal new Matches m;\n", "\nret null;\n}"); replaceKeywordBlock(tok, "static-pcall", "static { pcall {", "}}"); replaceKeywordBlock(tok, "loading", "{ temp tempShowLoadingAnimation(); ", "}"); replaceKeywordPlusQuotedBlock(tok, "loading", new Object() { String[] get(List tok, int i) { String text = tok.get(i+2); return new String[] { "{ temp tempShowLoadingAnimation(" + text + "); ", "}" }; }}); while ((i = jfind(tok, "visualize as")) >= 0) { int j = tok_findEndOfStatement(tok, i); // expression, rather tok.set(i+2, "{ ret"); tok.set(j-1, "; }"); reTok(tok, i, j); } jreplace(tok, "visualize {", "public JComponent visualize() {", tokCondition_beginningOfMethodDeclaration()); jreplace(tok, "visualize2 {", "JComponent visualize2() {", tokCondition_beginningOfMethodDeclaration()); replaceKeywordBlock(tok, "start-thread-printDone", "start-thread {", "printDone(); }"); replaceKeywordBlock(tok, "start-thread", "start { thread \"Start\" { temp enter(); ", "}}"); jreplace(tok, "start {", "void start() { super.start();", tokCondition_beginningOfMethodDeclaration()); // run { ... } => public void run() { ... } jreplace(tok, "run {", "public void run() {", new TokCondition() { boolean get(final List tok, final int i) { return neqGet(tok, i-1, "void"); }}); replaceKeywordBlock(tok, "html", "static O html(S uri, fMap params) ctex " + "{\n", "}"); replaceKeywordBlock(tok, "afterVisualize", "visualize { JComponent _c = super.visualize();", "ret _c; }"); replaceKeywordBlock(tok, "enhanceFrame", "void enhanceFrame(Container f) { super.enhanceFrame(f);", "}"); if (assumeTriple) { jreplace(tok, "Triple", "T3"); expandTriple(tok); } tok_shortFinals(tok); tok_moduleClassDecls(tok); jreplace(tok, "static sync", "static synchronized"); jreplace(tok, "sclass", "static class"); jreplace(tok, "srecord", "static record"); jreplace(tok, "record noeq", "noeq record"); jreplace(tok, "asclass", "abstract static class"); jreplace(tok, "sinterface", "static interface"); jreplace(tok, "ssynchronized", "static synchronized"); jreplace(tok, "ssvoid", "static synchronized void"); jreplace(tok, "sbool", "static bool"); jreplace(tok, "fbool", "final bool"); jreplace(tok, "sint", "static int"); jreplace(tok, "snew", "static new"); jreplace(tok, "sv ", "static void $2"); jreplace(tok, "pvoid", "public void"); // "sS" => static S jreplace(tok, "sS", "static S"); // "sO" => static O jreplace(tok, "sO", "static O"); // "sL" => static L jreplace(tok, "sL", "static L"); // "toString {" => "public S toString() {" jreplace(tok, "toString {", "public S toString() {"); jreplace(tok, "Int", "Integer"); jreplace(tok, "Bool", "Boolean"); jreplace(tok, "BigInt", "BigInteger"); jreplace(tok, "Char", "Character"); jreplace(tok, "Sym", "Symbol"); jreplace(tok, "SymSym", "SymbolSymbol"); jreplace(tok, "SS", "Map"); jreplace(tok, "SymbolSymbol", "Map"); jreplace(tok, "PairS", "Pair"); jreplace(tok, "LPairS", "L>"); jreplace(tok, "T3S", "T3"); jreplace(tok, "F1S", "F1"); jreplace(tok, "ItIt", "IterableIterator"); jreplace(tok, "CloseableItIt", "CloseableIterableIterator"); jreplace(tok, "class > {", "class $2 extends $4 {"); jreplace(tok, "class > <> {", "class $2 extends $4 $5 $6 $7 {"); jreplace(tok, "ISegmenter", "IF1>"); // "on fail {" => "catch (Throwable _e) { ... rethrow(_e); }" replaceKeywordBlock(tok, "on fail", "catch (Throwable _e) {", "\nthrow rethrow(_e); }"); // "catch {" => "catch (Throwable _e) {" jreplace(tok, "catch {", "catch (Throwable _e) {"); // "catch print e {" => "catch e { _handleException(e); " jreplace(tok, "catch print {", "catch $3 { _handleException($3);"); // "catch print short e {" => "catch e { printExceptionShort(e); " jreplace(tok, "catch print short {", "catch $4 { printExceptionShort($4);"); // "catch X e {" => "catch (X e) {" jreplace(tok, "catch {", "catch ($2 $3) {"); // "catch e {" => "catch (Throwable e) {" (if e is lowercase) jreplace(tok, "catch {", "catch (Throwable $2) {", new TokCondition() { boolean get(final List tok, final int i) { String word = tok.get(i+3); return startsWithLowerCaseOrUnderscore(word); }}); jreplace(tok, "+ +", "+", new TokCondition() { boolean get(final List tok, final int i) { //printStructure("++: ", subList(tok, i-1, i+6)); if (empty(_get(tok, i+2))) return false; // no space between the pluses if (empty(_get(tok, i)) && eq("+", _get(tok, i-1))) return false; // an actual "++" at the left if (empty(_get(tok, i+4)) && eq("+", _get(tok, i+5))) return false; // an actual "++" at the right //print("doing it"); return true; }}); // some crazy fancy syntax jreplace(tok, "set ;", "$2 = true;"); // single underscore (not allowed in Java anymore) to double underscore jreplace(tok, "_", "__"); // [stdEq] -> implementation of equals() and hashCode() jreplace(tok, "[stdEq]", "public bool equals(O o) { ret stdEq2(this, o); }\n" + "public int hashCode() { ret stdHash2(this); }"); // [concepts] "concept.field!" for dereferencing references jreplace(tok, "*!", "$1.get()", new TokCondition() { boolean get(final List tok, final int i) { String l = tok.get(i+1); if (!(isIdentifier(l) || eq(l, ")"))) return false; if (tok.get(i+2).contains("\n")) return false; // no line break between and ! if (nempty(tok.get(i+4))) return true; // space after = ok String t = _get(tok, i+5); if (t == null) return false; if (isIdentifier(t) || eqOneOf(t, "=", "(")) return false; return true; }}); jreplace(tok, "for ( )", "for ($3 $4 : list($3))"); jreplace(tok, "for (final )", "for (final $4 $5 : list($4))"); // "continue unless", "break unless" for (String phrase : ll("continue unless", "break unless")) while ((i = jfind(tok, phrase)) >= 0) { String keyword = tok.get(i); int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); replaceTokens(tok, i, i+4, "{ if (!("); tok.set(j, ")) " + keyword + "; }"); reTok(tok, i, j+1); } // "continue if", "break if" for (String phrase : ll("continue if", "break if")) while ((i = jfind(tok, phrase)) >= 0) { String keyword = tok.get(i); int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); replaceTokens(tok, i, i+4, "{ if ("); tok.set(j, ") " + keyword + "; }"); reTok(tok, i, j+1); } // "return if" while ((i = jfind(tok, "return if")) >= 0) { int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); replaceTokens(tok, i, i+4, "{ if ("); tok.set(j, ") return; }"); reTok(tok, i, j+1); } // "return unless" while ((i = jfind(tok, "return unless")) >= 0) { int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); replaceTokens(tok, i, i+4, "{ if (!("); tok.set(j, ")) return; }"); reTok(tok, i, j+1); } // "return if" while ((i = jfind(tok, "return if")) >= 0) { int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); tok.set(j, ") return " + tok.get(i+2) + "; }"); replaceTokens(tok, i, i+6, "{ if ("); reTok(tok, i, j+1); } // "return with " / "continue with " / "break with " while ((i = jfind(tok, " with", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(tok.get(i+1), "return", "continue", "break"); }})) >= 0) { int j = scanOverExpression(tok, getBracketMap(tok), i+4, ";"); tok.set(j, "; " + tok.get(i) + "; }"); replaceTokens(tok, i, i+3, "{"); reTok(tok, i, j+1); } // return "bla" with while ((i = jfindOneOf(tok, "return with", "return with")) >= 0) { String result = tok.get(i+2); int j = scanOverExpression(tok, getBracketMap(tok), i+6, ";"); replaceTokens(tok, i, i+5, "{"); tok.set(j, "; return " + result + "; }"); reTok(tok, i, j+1); } tok_debugStatements(tok); // while not null (...) / if not null (...) while ((i = jfind_check("not",tok, " not null (", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+1), "if", "while"); }})) >= 0) { int closingBracket = findEndOfBracketPart(tok, i+6)-1; replaceTokens(tok, i+2, i+6, "("); tok.set(closingBracket, ") != null)"); reTok(tok, i, closingBracket+1); } // while null (...) / if null (...) while ((i = jfind_check("null",tok, " null (", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+1), "if", "while"); }})) >= 0) { int closingBracket = findEndOfBracketPart(tok, i+4)-1; replaceTokens(tok, i+2, i+4, "("); tok.set(closingBracket, ") == null)"); reTok(tok, i, closingBracket+1); } // Replace $1 with m.unq(0) etc. - caveat: this blocks identifiers $1, $2, ... for (i = 1; i < l(tok); i += 2) { String s = tok.get(i); if (s.startsWith("$")) { s = substring(s, 1); if (isInteger(s)) { tok.set(i, "m.unq(" + (parseInt(s)-1) + ")"); reTok(tok, i); } } } // instanceof trickery jreplace(tok, "is a ", "instanceof $3"); jreplace(tok, "! instanceof .", "!($2 instanceof $4.$6)"); jreplace(tok, "! instanceof ", "!($2 instanceof $4)"); jreplace(tok, " !instanceof ", "!($1 instanceof $4)"); // map func1 func2 func3(...) => mapFGH(f func1, f func2, f func3, ...) jreplace(tok, "map (", "mapFGH(f $2, f $3, f $4,"); // map func1 func2(...) => mapFG(f func1, f func2, ...) jreplace(tok, "map (", "mapFG(f $2, f $3,"); // "ref->bla" for dereferencing Concept.Ref or ThreadLocal or other // For lambdas, use SPACES on the left or right of the arrow! //jreplace(tok, " ->", "$1.get()."); jreplace(tok, "->", ".get().", new TokCondition() { boolean get(final List tok, final int i) { return empty(tok.get(i)) // no space on left of arrow && empty(tok.get(i+2)) // no space inside of arrow && empty(tok.get(i+4)) // no space on right of arrow && !eq(_get(tok, i-1), "-"); // i-->0; }}); // shortened subconcept declaration (before star constructors!) shortenedSubconcepts(tok); // "case" as a variable name ( => _case) caseAsVariableName(tok); // "do" as a function name ( => dO) tok_doAsMethodName(tok); // "continue" as a function name ( => _continue) continueAsFunctionName(tok); tok_extend(tok); jreplace(tok, "pn {", "p-noconsole {"); // Do these BEFORE awt replacement! ("p-awt" contains "awt" token) replaceKeywordBlock(tok, "r-awt", "r { awt {", "}}"); if (hasCodeTokens(tok, "p", "-")) tok_p_old(tok); replaceKeywordBlock(tok, "awt-messagebox", "awt { pcall-messagebox {", "}}"); replaceKeywordBlock(tok, "awt", "swingLater(r {", "});"); jreplace(tok, "p-android {", "set flag Android. p {"); unswing(tok); lockBlocks(tok); tempBlocks(tok); tok_switchTo(tok); // trim x; jreplace(tok, "trim ;", "$2 = trim($2);"); // iterate with index jreplace (tok, "for over :", "for (int $2 = 0; $2 < l($4); $2++)"); jreplace (tok, "for backwards over :", "for (int $2 = l($5)-1; $2 >= 0; $2--)"); jreplace (tok, "for , over : {", "for (int $2 = 0; $2 < l($7); $2++) { $4 $5 = $7.get($2);"); jreplace (tok, "for , backwards over : {", "for (int $2 = l($8)-1; $2 >= 0; $2--) { $4 $5 = $8.get($2);"); jreplace (tok, "for to :", "for (int $2 = 0; $2 < $4; $2++)"); jreplace (tok, "for to :", "for (int $2 = 0; $2 < $4; $2++)"); tok = expandShortTypes(tok); tok_equalsCast(tok); tok_equalsOptCast(tok); replaceKeywordBlock(tok, "r-thread-messagebox", "r-thread { pcall-messagebox {", "}}"); replaceKeywordBlock(tok, "thread-messagebox", "thread { pcall-messagebox {", "}}"); jreplace(tok, "rThread {", "r-thread {"); jreplace(tok, "rThreadEnter {", "r-thread { temp enter(); "); replaceKeywordBlock(tok, "r-thread", "runnableThread(r {", "})"); rNamedThread(tok); // only works in the scope of a DynModule jreplace(tok, "rEnter {", "r { temp enter(); "); replaceKeywordBlock(tok, "r-messagebox", "r { pcall-messagebox {", "}}"); jreplace(tok, "r + r ", "r { $2(); $5(); }"); // runnable and r - now also with automatic toString if enabled for (String keyword : ll("runnable", "r")) { while ((i = jfind(tok, keyword + " {")) >= 0) { int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); List contents = subList(tok, idx+1, j-1); replaceTokens(tok, i, j+1, "new Runnable {" + " public void run() ctex { " + tok_addSemicolon(contents) + "\n}" + (autoQuine ? tok_autoQuineFunc(contents) : "") + "}"); reTok(tok, i, j+1); } while ((i = jfind(tok, keyword + " {")) >= 0) { int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); List contents = subList(tok, idx+1, j-1); replaceTokens(tok, i, j+1, "new Runnable {" + " public void run() ctex { " + tok_addSemicolon(contents) + "\n}" + " toString { ret " + tok.get(i+2) + "; }" + (autoQuine ? tok_autoQuineFunc(contents, "_shortenedSourceCode") : "") + "}"); reTok(tok, i, j+1); } } replaceKeywordBlock(tok, "expectException", "{ bool __ok = false; try {", "} catch { __ok = true; } assertTrue(\"expected exception\", __ok); }"); while ((i = tok.indexOf("tex")) >= 0) { tok.set(i, "throws Exception"); tok = jtok(tok); } // shorter & smarter whiles jreplace(tok, "while true", "while (true)"); jreplace(tok, "while licensed", "while (licensed())"); jreplace(tok, "repeat {", "while (licensed()) {"); tok_repeatWithSleep(tok); // null; => return null; etc. Object cond = new TokCondition() { boolean get(final List tok, final int i) { return tok_tokenBeforeLonelyReturnValue(tok, i-1); }}; jreplace(tok, "null;", "return null;", cond); jreplace(tok, "false;", "return false;", cond); jreplace(tok, "true;", "return true;", cond); jreplace(tok, "this;", "return this;", cond); // ok => ret "OK" with jreplace(tok, "ok ", "return \"OK\" with $2"); replaceKeywordBlock(tok, "ok", "{", " return \"OK\"; }"); // "myFunction;" instead of "myFunction();" - quite rough // (isolated identifier as function call) cond = new TokCondition() { boolean get(List tok, int i) { String word = tok.get(i+3); //print("single word: " + word); return !eqOneOf(word, "break", "continue", "return", "else", "endifdef", "endif"); } }; for (String pre : litlist("}", ";")) jreplace(tok, pre + " ;", "$1 $2();", cond); // shorter match syntax for answer methods jreplace(tok, "if || ", "if (matchOneOf(s, m, $2, $5))"); // "bla * bla | blubb * blubb" jreplace_dyn(tok, "if ", new F2, Integer, String>() { String get(List tok, Integer cIdx) { try { String s = unquote(tok.get(cIdx+2)); //print("multimatch: " + quote(s)); List l = new ArrayList(); for (String pat : splitAtJavaToken(s, "|")) { //print("multimatch part: " + quote(pat)); if (pat.contains("...")) l.add("matchX(" + quote(trim(pat)) + ", s, m)"); else if (javaTok(pat).contains("*")) l.add("match(" + quote(trim(pat)) + ", s, m)"); else l.add("match(" + quote(trim(pat)) + ", s)"); } return "if (" + join(" || ", l) + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S s = unquote(tok.get(cIdx+2));\r\n //print(\"multimatch: \" + quote(s));\r\n ..."; }}, new TokCondition() { boolean get(final List tok, final int i) { return javaTokC(unquote(tok.get(i+3))).contains("|"); }}); // "...bla..." jreplace(tok, "if ", "if (find3plusRestsX($2, s, m))", new TokCondition() { boolean get(final List tok, final int i) { return startsAndEndsWith(unquote(tok.get(i+3)), "..."); }}); // "bla..." jreplace(tok, "if ", "if (matchStartX($2, s, m))", new TokCondition() { boolean get(final List tok, final int i) { return unquote(tok.get(i+3)).endsWith("..."); }}); // "bla" jreplace(tok, "if ", "if (match($2, s))", new TokCondition() { boolean get(final List tok, final int i) { return !javaTokC(unquote(tok.get(i+3))).contains("*"); }}); // "bla * bla" jreplace(tok, "if ", "if (match($2, s, m))"); jreplace(tok, "if match ", "if (match($3, s, m))"); jreplace(tok, "if eq ", "if (eq($2, $4))"); tok_dropExtraCommas(tok); // additional translations (if necessary) jreplace(tok, "pcall ping {", "pcall { ping();"); replaceKeywordBlock(tok, ") pcall", ") { pcall {", "}}"); replaceKeywordBlock(tok, "pcall", "try {", "} catch (Throwable __e) { _handleException(__e); }"); replaceKeywordBlock(tok, "pcall-short", "try {", "} catch (Throwable __e) { print(exceptionToStringShort(__e)); }"); replaceKeywordBlock(tok, "pcall-silent", "try {", "} catch (Throwable __e) { silentException(__e); }"); replaceKeywordBlock(tok, "pcall-messagebox", "try {", "} catch __e { messageBox(__e); }"); replaceKeywordBlock(tok, "pcall-infobox", "try {", "} catch __e { infoBox(__e); }"); tok = dialogHandler(tok); replaceKeywordBlock(tok, "exceptionToUser", "try {", "} catch (Throwable __e) { ret exceptionToUser(__e); }"); if (hasCodeTokens(tok, "twice", "{")) replaceKeywordBlock(tok, "twice", "for (int __twice = 0; __twice < 2; __twice++) {", "}"); while ((i = findCodeTokens(tok, "bench", "*", "{")) >= 0) { int j = findEndOfBracketPart(tok, i+4)-1; String time = makeVar("time"); String v = makeVar("bench"); String n = tok.get(i+2); tok.set(i, "{ long " + time + " = sysNow(); for (int " + v + " = 0; " + v + " < " + n + "; " + v + "++)"); tok.set(i+2, ""); tok.set(j, "} printBenchResult(sysNow()-" + time + ", " + n + "); }"); reTok(tok, i, j+1); } replaceKeywordBlockDyn(tok, "time", new Object() { String[] get() { String var = makeVar("startTime"); return new String[] { "{ long " + var + " = sysNow(); try { ", "} finally { " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); } }"}; }}); // version without { } replaceKeywordBlockDyn(tok, "time2", new Object() { String[] get() { String var = makeVar("startTime"); return new String[] { "long " + var + " = sysNow(); ", " " + var + " = sysNow()-" + var + "; saveTiming(" + var + "); "}; }}); // time "bla" { replaceKeywordPlusQuotedBlock(tok, "time", new Object() { String[] get(List tok, int i) { String var = makeVar("startTime"); return new String[] { "long " + var + " = sysNow(); ", " done2_always(" + tok.get(i+2) + ", " + var + "); "}; }}); if (hasCodeTokens(tok, "assertFail", "{")) { String var = makeVar("oops"); replaceKeywordBlock(tok, "assertFail", "boolean " + var + " = false; try {", "\n" + var + " = true; } catch (Exception e) { /* ok */ } assertFalse(" + var + ");"); } replaceKeywordBlock(tok, "yo", "try {", "} catch (Exception " + makeVar("e") + ") { ret false; }", new TokCondition() { boolean get(final List tok, final int i) { return neqOneOf(_get(tok, i-1), "svoid", "void"); }}); replaceKeywordBlock(tok, "awtIfNecessary", "swingNowOrLater(r " + "{", "});"); ctex(tok); replaceKeywordBlock(tok, "actionListener", "new java.awt.event.ActionListener() { " + "public void actionPerformed(java.awt.event.ActionEvent _evt) { pcall-messagebox {", "}}}"); for (String keyword : ll("autocloseable", "autoCloseable")) /*replaceKeywordBlock(tok, keyword, "new AutoCloseable() { public void close() throws Exception {", "}}");*/ replaceKeywordBlock_dyn2_legacy(tok, keyword, new Object() { String[] get(List tok, int iOpening, int iClosing) { List contents = subList(tok, iOpening+1, iClosing); return new String[] { "new AutoCloseable() { toString { ret " + quote(shorten(maxQuineLength, trimJoin(contents))) + "; } public void close() throws Exception {", "}}" }; } }); // try answer (string, test with nempty) while ((i = findCodeTokens(tok, "try", "answer")) >= 0) { int j = findEndOfStatement(tok, i); String v = makeVar(); boolean needCurly = !eqGet(tok, i-2, "{"); tok.set(i, (needCurly ? "{" : "") + " S " + v); tok.set(i+2, "="); tok.set(j-1, "; if (!empty(" + v + ")) ret " + v + "; " + (needCurly ? "}" : "")); reTok(tok, i, j); } // try bool[ean] (try answer with Bool type) while ((i = findCodeTokens(tok, "try", "boolean")) >= 0) { int j = findEndOfStatement(tok, i); String v = makeVar(); tok.set(i, "{ Bool " + v); tok.set(i+2, "="); tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); reTok(tok, i, j); } // S s = bla(), return if null; => S s = bla(); if (s == null) return; while ((i = jfind(tok, ", return if null;")) >= 0) { int j = tok_findBeginningOfStatement(tok, i); print("Found statement " + j + "/" + i + " - " + joinSubList(tok, j-1, i+5*2-1)); String var = getVarDeclarationName(subList(tok, j-1, i)); replaceTokens_reTok(tok, i, i+5*2-1, "; if (" + var + " == null) ret;"); } // , print "..."; => { ; print("..."); } while ((i = jfind(tok, ", print ;")) >= 0) { int j = tok_findBeginningOfStatement(tok, i); replaceTokens_reTok(tok, i, i+4*2-1, "; print(" + tok.get(i+4) + "); }"); tokPrepend_reTok(tok, j, "{ "); } // return if null => if ( == null) return; while ((i = jfind(tok, "return if null")) >= 0) { int j = findEndOfStatement(tok, i); clearTokens(tok, i, i+2); tok.set(i+4, "(("); tok.set(j-1, ") == null) ret;"); reTok(tok, i, j); } // return optional (return if not null) while ((i = jfind_check("optional",tok, "return optional =")) >= 0) { int j = findEndOfStatement(tok, i); String v = tok.get(i+4); clearTokens(tok, i+2, i+4); tok.set(i, "{"); tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); reTok(tok, i, j); } // try object (return if not null) while ((i = jfind_check("object",tok, "try object")) >= 0) { int j = findEndOfStatement(tok, i); clearTokens(tok, i, i+3); boolean isDecl = isIdentifier(get(tok, i+4)) && isIdentifier(get(tok, i+6)) && eqGet(tok, i+8, "="); if (isDecl) { String v = get(tok, i+6); tok.set(i, "{"); tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); } else { String v = makeVar(); tok.set(i, "{ O " + v + "="); tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); } reTok(tok, i, j); } // try Int i = ...; (return if not null, shorter version of "try object") while ((i = jfind(tok, "try =")) >= 0) { int j = findEndOfStatement(tok, i); String type = tok.get(i+2), v = tok.get(i+4); tok.set(i, "{"); tok.set(j-1, "; if (" + v + " != null) ret " + v + "; }"); reTok(tok, i, j); } // debug print ...; => if (debug) print(...); while ((i = jfind(tok, "debug print")) >= 0) { int j = findEndOfStatement(tok, i); replaceTokens(tok, i, i+4, "if (debug) print("); tok.set(j-1, ");"); reTok(tok, i, j); } functionReferences(tok); tok_expandLPair(tok); tok_expandPairL(tok); tok_expandLT3(tok); quicknew2(tok); // X x = nu(+...) => X x = nu X(+...) jreplace(tok, " = nu(+", "$1 $2 = nu $1(+"); // X x = nu(a := ...) => X x = nu X(a := ...) jreplace(tok, " = nu( :=", "$1 $2 = nu $1($6 :="); tok_expandVarCopies(tok); // AFTER the lines just above tok_replaceColonEqualsSyntax(tok); // ditto tok_unpair(tok); tok_cachedFunctions(tok); tok_simplyCachedFunctions(tok); tok_optPar(tok); throwFailEtc(tok); tok_typeAA(tok, pairClasses); // do this after expanding sclass etc. tok = tok_expandStarConstructors(tok); tok_kiloConstants(tok); //tok_colonMessages(tok); while ((i = jfind(tok, "shit:")) >= 0) { int j = tok_findEndOfStatement(tok, i); tok.set(i+2, "("); tok.set(j-1, ");"); reTok(tok, i, j); } jreplace(tok, "shit(", "ret with print("); tok_virtualTypes(tok); tok_autoLongConstants(tok); // common misordering of type arguments jreplace(tok, "boolean ", " boolean"); tok_unimplementedMethods(tok); tok_switchableFields(tok); tok_autoDisposeFields(tok); tok_shortVisualize(tok); tok_whileGreaterThan(tok); tok_ifThenEnd(tok); tok_autoInitVars(tok); tok_fixBadTypeParameterOrder(tok); // shortened method declarations BEFORE standardFunctions jreplace(tok, "svoid", "static void"); jreplace(tok, "void {", "$1 $2() {"); jreplace(tok, "void thread {", "$1 $2() thread {"); jreplace(tok, "String {", "$1 $2() {"); jreplace(tok, "Object {", "$1 $2() {"); jreplace(tok, "List {", "$1 $2() {"); namedThreads(tok); threads(tok); //tok_maxEquals(tok); tok_questionDot(tok); tok_embeddedFunctions(tok); jreplace(tok, "[] = new[", "$1[] $4 = new $1["); jreplace(tok, " ifNull =", "if ($1 == null) $1 ="); jreplace(tok, "class extends <.>", "class $2 extends $4<$2.$7>"); tok_once(tok); // must come before next line so you can combine them tok_ifRecordMatch(tok); jreplace(tok, " ||=", "$1 = $1 ||"); // magicValue followed by a numerical constant jreplace(tok, "magicValue", "", (_tok, _i) -> { String t = _get(_tok, _i+3); return eqOneOf(t, ".", "-") || isInteger(t); }); // end of local stuff tok_processMetaBlocks(tok, metaCodeAllowed()); if (metaCodeAllowed()) runMetaTransformers(tok); same = tok_sameTest(tok, before); /*if (!same) print("local not same " + safety + " (" + l(tok) + " tokens)");*/ if (safety++ >= 10) { printSources(tok); throw fail("safety 10 error!"); } } while (!same); return tok; } static List reTok_include(List tok, int i, int j) { return reTok_modify(tok, i, j, "localStuff1"); } static List includeInMainLoaded_reTok(List tok, int i, int j) { return reTok_include(tok, i, j); } static List stdstuff(List tok) { //if (++level >= 10) fail("woot? 10"); print("stdstuff!"); int i; List ts = new ArrayList(); tok_findTranslators(tok, ts); if (nempty(ts)) print("DROPPING TRANSLATORS: " + structure(ts)); print("quickmain"); tok = quickmain(tok); print("includes"); tok = tok_processIncludes(tok); print("conceptsDot"); if (processConceptsDot(tok)) tok = tok_processIncludes(tok); //print('starConstructors); tok = tok_expandStarConstructors(tok); // drop Java 8 annotations since we're compiling for Java 7 jreplace(tok, "@Nullable", ""); // STANDARD CLASSES & INTERFACES print("standard classes"); final Set haveClasses = addStandardClasses_v2(tok); tok_quickInstanceOf(tok, haveClasses); // concept-related stuff // auto-import concepts boolean _a = tok_hasClassRef2(tok, /*"extends",*/ "Concept") || tok_hasClassRef2(tok, "Concepts"), _b = !haveClasses.contains("Concept"); //print("auto-import: " + _a + ", " + _b); if (_a && _b) { print("Auto-including concepts."); if (shouldNotIncludeClass.contains("Concepts")) { print(join(tok)); throw fail("Unwanted concepts import"); } printStruct(haveClasses); tok = includeInMainLoaded(tok, "concepts."); reTok(tok, l(tok)-1, l(tok)); //processConceptsDot(tok); } return tok; } // end of stdStuff! static List multilineStrings(List tok) { for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (isQuoted(t)) if (t.startsWith("[") || t.contains("\r") || t.contains("\n")) tok.set(i, quote(unquote(t))); } return tok; } static void inStringEvals(List tok) { boolean change = false; for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (!isQuoted(t)) continue; if (t.contains("\\*") && !t.contains("\\\\")) { // << rough tok.set(i, inStringEval(t)); change = true; } } if (change) reTok(tok); } static String inStringEval(String t) { t = dropPrefix("\"", dropSuffix("\"", t)); List l = new ArrayList(); int idx; while ((idx = t.indexOf("\\*")) >= 0) { int j = indexOf(t, idx, "*/"); if (j < 0) break; if (idx > 0) l.add("\"" + substring(t, 0, idx) + "\""); l.add("(" + trim(substring(t, idx+2, j)) + ")"); t = substring(t, j+2); } if (nempty(t)) l.add("\"" + t + "\""); return "(" + join(" + ", l) + ")"; } static List quickmain(List tok) { if (quickmainDone1 && quickmainDone2) return tok; int i = findCodeTokens(tok, "main", "{"); if (i < 0) i = findCodeTokens(tok, "m", "{"); if (i >= 0 && !(i-2 > 0 && tok.get(i-2).equals("class"))) { tokSet_reTok(tok, i, "class main"); quickmainDone1 = true; } i = findCodeTokens(tok, "psvm", "{"); if (i < 0) i = findCodeTokens(tok, "p", "{"); if (i >= 0) { int idx = i+2; int j = findEndOfBracketPart(tok, idx)-1; List contents = subList(tok, idx+1, j); //print("contents: " + sfu(contents)); tok.set(i, "public static void main(final String[] args) throws Exception"); replaceTokens(tok, idx+1, j, tok_addSemicolon(contents)); reTok(tok, i, j); quickmainDone2 = true; } return tok; } // TODO: what about multiple threads / compiling standard functions? static String makeVar(String name) { return "_" + name + "_" + getAndInc(varCount); } static String makeVar() { return makeVar(""); } static List rtq(List tok, String id) { return runTranslatorQuick(tok, id); } static List expandShortTypes(List tok) { // replace with for (int i = 1; i+4 < tok.size(); i += 2) if (tok.get(i).equals("<") && litlist(">", ",").contains(tok.get(i+4))) { String type = tok.get(i+2); if (type.equals("int")) type = "Integer"; else if (type.equals("long")) type = "Long"; tok.set(i+2, type); } // O = Object, S = String, ret = return for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.equals("O")) t = "Object"; if (t.equals("S")) t = "String"; else if (t.equals("L")) t = "List"; else if (t.equals("Cl")) t = "Collection"; //else if (t.equals("F")) t = "Function"; else if (t.equals("ret") && neqOneOf(get(tok, i+2), "=", ")", ".")) t = "return"; 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 else if (t.equals("AtomicBool")) t = "AtomicBoolean"; tok.set(i, t); } jreplace(tok, "LL< >", "L>"); jreplace(tok, "LL", "L>"); jreplace(tok, "LL", "L"); jreplace(tok, "Clusters< >", "Map<$3, Collection<$3>>"); return tok; } static List autoImports(List tok) { HashSet imports = new HashSet(tok_findImports(tok)); StringBuilder buf = new StringBuilder(); for (String c : standardImports) if (!(imports.contains(c))) buf.append("import " + c + ";\n"); if (buf.length() == 0) return tok; tok.set(0, buf+tok.get(0)); return reTok(tok, 0, 1); } static String[] standardImports = { "java.util.*", "java.util.zip.*", "java.util.List", "java.util.regex.*", "java.util.concurrent.*", "java.util.concurrent.atomic.*", "java.util.concurrent.locks.*", "javax.swing.*", "javax.swing.event.*", "javax.swing.text.*", "javax.swing.table.*", "java.io.*", "java.net.*", "java.lang.reflect.*", "java.lang.ref.*", "java.lang.management.*", "java.security.*", "java.security.spec.*", "java.awt.*", "java.awt.event.*", "java.awt.image.*", "javax.imageio.*", "java.math.*" }; static List tok_processIncludes(List tok) { int safety = 0; while (hasCodeTokens(tok, "!", "include") && ++safety < 100) tok = tok_processIncludesSingle(tok); //tok_autoCloseBrackets(tok); return tok; } static List tok_processIncludesSingle(List tok) { int i; while ((i = jfind_check("include",tok, "!include #")) >= 0) { String id = tok.get(i+6); included.add(parseLong(id)); replaceTokens(tok, i, i+8, "\n" + cacheGet(id) + "\n"); reTok_include(tok, i, i+8); } while ((i = jfind_check("include",tok, "!include once #")) >= 0) { String id = tok.get(i+8); boolean isNew = included.add(parseLong(id)); replaceTokens(tok, i, i+10, isNew ? "\n" + cacheGet(id) + "\n" : ""); reTok_include(tok, i, i+10); } return tok; } static void ctex(List tok) { replaceKeywordBlock(tok, "ctex", "{ try {", "} catch (Exception __e) { throw rethrow(__e); } }"); for (String keyword : ll("null on exception", "null on error")) replaceKeywordBlock(tok, keyword, "{ try {", "} catch (Throwable __e) { return null; } }"); replaceKeywordBlock(tok, "false on exception", "{ try {", "} catch (Throwable __e) { return false; } }"); } static List dialogHandler(List tok) { return replaceKeywordBlock(tok, "dialogHandler", "new DialogHandler() {\n" + "public void run(final DialogIO io) {", "}}"); } static void quicknew2(List tok) { jreplace(tok, "new ;", "$2 $3 = new $2;"); jreplace(tok, "new <> ;", "$2<$4> $6 = new $2;"); jreplace(tok, "new . ;", "$2.$4 $5 = new $2.$4();"); jreplace(tok, "new <> , ;", "$2<$4> $6 = new $2, $8 = new $2;"); jreplace(tok, "new <,> ;", "$2<$4,$6> $8 = new $2;"); jreplace(tok, "new <<>> ;", "$2<$4<$6>> $9 = new $2;"); jreplace(tok, "new <[]> ;", "$2 $3 $4 $5 $6 $7 $8 = new $2;"); jreplace(tok, "new < <>, > ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;"); jreplace(tok, "new < <,> > ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;"); jreplace(tok, "new < , <> > ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 = new $2;"); jreplace(tok, "new < <,,> > ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;"); jreplace(tok, "new < <,>, > ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;"); jreplace(tok, "new < , <,>> ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 = new $2;"); jreplace(tok, "new < < , <,>>> ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 = new $2;"); jreplace(tok, "new < < ., <,>>> ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 = new $2;"); jreplace(tok, "new < < <>, <>>> ;", "$2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 = new $2;"); // [abandoned, confusing, looks like a function definition] with arguments - new A a(...); => A a = new A(...); //jreplace(tok, "new (", "$2 $3 = new $2("); jreplace(tok, "for args " + "{", "for (int i = 0; i < args.length; i++) { final String arg = args[i];"); // Constructor calls without parentheses // So you can say something like: predictors.add(new P1); jreplace1(tok, "new ", "new $2()", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+5), "{", ",", ")", ";", ":"); }}); jreplace1(tok, "new < >", "new $2<$4>()", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+11), "{", ",", ")", ";", ":"); }}); jreplace(tok, "new List(", "new ArrayList("); jreplace(tok, "new Map(", "new HashMap("); jreplace(tok, "new Set(", "new HashSet("); jreplace(tok, "new (Hash)Set", "new HashSet"); // rough jreplace(tok, "new (Tree)Set", "new TreeSet"); jreplace(tok, "new (Hash)Map", "new HashMap"); jreplace(tok, "new (Tree)Map", "new TreeMap"); jreplace(tok, "\\*[] ;", "$2[] $6 = new $2[$4];"); // X x = new(...) => X x = new X(...) // X x = new {...} => X x = new X {...} // X x = new => X x = new jreplace(tok, " = new", "$1 $2 = new $1", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+9), "(", ";", ",", ")", "{"); }}); jreplace(tok, " = new \\*", "$1 $2 = new $1"); jreplace(tok, "\\* = new ", "$5 $2 = new $5"); // TODO: use backward type scanning jreplace(tok, "<> = new", "$1 $2 $3 $4 $5 = new $1", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+9+3*2), "(", ";", ",", ")"); }}); jreplace(tok, "<,> = new", "$1 $2 $3 $4 $5 $6 $7 = new $1", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+9+5*2), "(", ";", ",", ")"); }}); jreplace(tok, "<<>> = new", "$1 $2 $3 $4 $5 $6 $7 $8 = new $1", new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i+9+6*2), "(", ";", ",", ")"); }}); } static List extendClasses(List tok) { int i; while ((i = jfind(tok, "extend {")) >= 0) { String className = tok.get(i+2); int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx+2); String content = join(subList(tok, idx+1, j-1)); List c = findInnerClassOfMain(tok, className); print("Extending class " + className); clearTokens(tok.subList(i, j+1)); if (c == null) { print("Warning: Can't extend class " + className + ", not found"); continue; } int startOfClass = indexOfSubList(tok, c); // magicIndexOfSubList is broken int endOfClass = startOfClass + l(c)-1; //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass))); while (neq(tok.get(endOfClass), "}")) --endOfClass; //print("Extending class " + className + " ==> " + join(subList(tok, startOfClass, endOfClass))); tok.set(endOfClass, content + "\n" + tok.get(endOfClass)); doubleReTok(tok, i, j+1, endOfClass, endOfClass+1); } return tok; } // for ping / while ping static void forPing(List tok) { int i; for (String keyword : ll("for", "fOr", "while")) while ((i = jfind(tok, keyword + " ping (")) >= 0) { int bracketEnd = findEndOfBracketPart(tok, i+4)-1; int iStatement = bracketEnd+2; int iEnd = findEndOfStatement(tok, iStatement); tok.set(i+2, ""); // turn into block if (!eq(get(tok, iStatement), "{")) { tok.set(iStatement, "{ " + tok.get(iStatement)); tok.set(iEnd-1, tok.get(iEnd-1) + " }"); } // add ping tok.set(iStatement, "{ ping(); " + dropPrefixTrim("{", tok.get(iStatement))); reTok(tok, i+2, iEnd); } } // lib 123 => !123 static void libs(List tok) { int i; while ((i = jfind(tok, "lib ")) >= 0) { String id = tok.get(i+2); print("lib " + id); if (!libs.contains(id)) { libs.add(id); clearAllTokens(tok, i, i+3); /*tok.set(i, "!"); tok.set(i+1, "");*/ } else { print("...ignoring (duplicate)"); clearAllTokens(tok, i, i+3); reTok(tok, i, i+3); } } print("libs found: " + libs); } // sourceCodeLine() => 1234 static void sourceCodeLine(List tok) { int i ; while ((i = jfind(tok, "sourceCodeLine()")) >= 0) { replaceTokens(tok, i, i+5, str(countChar(join(subList(tok, 0, i)), '\n')+1)); reTok(tok, i, i+5); } } // done before any other processing static void earlyStuff(List tok) { int i; tok_scopes(tok, "autoCloseScopes" , asInclude); tok_autosemi(tok); tok_autoCloseBrackets(tok); jreplace(tok, "°", "()"); // Note: this makes the word "quine" a special operator // (unusable as a function name) while ((i = jfind(tok, "quine(")) >= 0) { int idx = findCodeTokens(tok, i, false, "("); int j = findEndOfBracketPart(tok, idx+2); tok.set(i, "new Quine"); tok.set(idx, "(" + quote(join(subList(tok, idx+1, j-1))) + ", "); reTok(tok, i, idx+1); } // do this before func & voidfunc because otherwise they swallow it jreplace(tok, "enter {", "{ temp enter();"); // func keyword for lambdas - now automatically quines toString() if enabled // do func & voidfunc early to preserve original code as toString while ((i = jfind(tok, "func(")) >= 0) { int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); int idx = findCodeTokens(tok, argsTo, false, "{"); int j = findEndOfBracketPart(tok, idx); List contents = subList(tok, idx+1, j-1); String returnType = "O"; if (eq(tok.get(argsTo+2), "-") && eq(tok.get(argsTo+4), ">")) returnType = tok_toNonPrimitiveTypes(join(subList(tok, argsTo+6, idx-1))); String toString = autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trimJoin(contents))) + "; }" : ""; List args = cloneSubList(tok, argsFrom-1, argsTo); tok_shortFinals(args); tok_toNonPrimitiveTypes(args); List types = tok_typesOfParams(args); Object type = "O"; if (l(types) <= 3) type = "F" + l(types) + "<" + joinWithComma(types) + ", " + returnType + ">"; String body = tok_addReturn(contents); replaceTokens_reTok(tok, i, j, "new " + type + "() { " + returnType + " get(" + trimJoin(args) + ") ctex { " + body + " }\n" + toString + "}"); } while ((i = jfind(tok, "voidfunc(")) >= 0) { int argsFrom = i+4, argsTo = findCodeTokens(tok, i, false, ")"); int idx = findCodeTokens(tok, argsTo, false, "{"); int j = findEndOfBracketPart(tok, idx); List contents = subList(tok, idx+1, j-1); List args = cloneSubList(tok, argsFrom-1, argsTo); tok_shortFinals(args); tok_toNonPrimitiveTypes(args); List types = tok_typesOfParams(args); Object type = "O"; if (l(types) <= 4) type = "VF" + l(types) + "<" + joinWithComma(types) + ">"; replaceTokens(tok, i, j, "new " + type + "() { public void get(" + trimJoin(args) + ") ctex { " + tok_addSemicolon(contents) + " }\n" + (autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}"); reTok(tok, i, j); } jreplace(tok, "func {", "func -> O {"); jreplace(tok, "f {", "f -> O {"); // swing -> S { ... } => swing(func -> S { ... }) while ((i = jfind(tok, "swing ->")) >= 0) { int bracket = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, bracket); tok.set(i, "swing(func"); tok.set(j-1, "})"); reTok(tok, i, j); } tok_qFunctions(tok); for (String keyword : ll(/*"f",*/ "func")) { while ((i = jfind(tok, keyword + " ->", new TokCondition() { boolean get(final List tok, final int i) { return isIdentifier(_get(tok, i+7)); // avoid lambda declaration like: f -> { ... } }})) >= 0) { // I think there is a bug here for something like func -> x { new x { } } int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); String returnType = tok_toNonPrimitiveTypes(join(subList(tok, i+6, idx-1))); List contents = subList(tok, idx+1, j-1); replaceTokens(tok, i, j, "new F0<" + returnType + ">() { " + returnType + " get() ctex { " + tok_addReturn(contents) + " }\n" + (autoQuine ? " public S toString() { ret " + quote(shorten(maxQuineLength, trim(join(contents)))) + "; }" : "") + "}"); reTok(tok, i, j); } } while ((i = jfind(tok, "time repeat * {")) >= 0) { int j = findEndOfBlock(tok, i+6)-1; tok.set(i, "time {"); tok.set(j, "}}"); reTok(tok, i, j+1); } // do this before "m {" stuff because "repeat m" [doesn't seem to work yet though) while ((i = findCodeTokens(tok, "repeat", "*", "{")) >= 0) { String v = makeVar("repeat"); tok.set(i, "for (int " + v + " = 0; " + v + " < " + tok.get(i+2) + "; " + v + "++)"); tok.set(i+2, ""); reTok(tok, i, i+3); } } static void throwFailEtc(List tok) { boolean anyChange = false; for (int i = 1; i+4 < l(tok); i += 2) if (eqOneOf(get(tok, i+2), "fail", "todo") && eq(get(tok, i+4), "(") && !eqOneOf(get(tok, i), "throw", "RuntimeException", "return", "f", "function")) { tok.set(i+2, "throw " + tok.get(i+2)); anyChange = true; } if (anyChange) reTok(tok); } static void namedThreads(List tok) { for (int i = 0; i < 100; i++) { int idx = findCodeTokens(tok, "thread", "", "{"); if (idx < 0) idx = findCodeTokens(tok, "thread", "", "{"); if (idx < 0) break; int j = findEndOfBracketPart(tok, idx+4); String tName = tok.get(idx+2); String pre = "startThread(" + tName + ", r { "; String post = "})"; if (!tok_tokenLeftOfExpression(tok, idx-2)) post += ";"; tok.set(idx, pre); tok.set(idx+2, ""); tok.set(idx+4, ""); tok.set(j-1, post); //print(join(subList(tok, idx, j))); reTok(tok, idx, j); } } static void rNamedThread(List tok) { for (int i = 0; i < 100; i++) { int idx = findCodeTokens(tok, "r", "-", "thread", "", "{"); if (idx < 0) idx = findCodeTokens(tok, "r", "-", "thread", "", "{"); if (idx < 0) break; int j = findEndOfBracketPart(tok, idx+8); String tName = tok.get(idx+6); String pre = "r { thread " + tName + " {"; String post = "}}"; replaceTokens(tok, idx, idx+9, pre); tok.set(j-1, post); reTok(tok, idx, j); } } static void threads(List tok) { replaceKeywordBlock(tok, "daemon", "startDaemonThread(r {", "});"); //replaceKeywordBlock(tok, "thread", "startThread(r {", "});"); // now enclose in { } to allow using like "void bla() thread { ... }" - if it's not used as an expression replaceKeywordBlock_dyn2_legacy(tok, "thread", new Object() { // don't use func here, it can't be transpiled String[] get (List tok, int iOpening, int iClosing) { // is the thread clause used as an expression? boolean isExpression = tok_tokenLeftOfExpression(tok, iOpening-4); return new String[] { (isExpression ? "" : "{ ") + "startThread(r {", "})" + (isExpression ? "" : "; }") }; } }); } static Map sf; // standard standard functions (haha) static Boolean _761ok; static List standardFunctions(List tok) { if (sf == null) { String _761 = cacheGet("#761"); if (_761ok == null) _761ok = isBracketHygienic(_761); assertTrue("Whoa! #761 truncated?", _761ok); List standardFunctions = concatLists( (List) loadVariableDefinition(_761, "standardFunctions"), (List) loadVariableDefinition(cacheGet("#1006654"), "standardFunctions")); sf = new HashMap(); for (String x : standardFunctions) { String[] f = x.split("/"); sf.put(f[1], f[0]); } } Map sfMap = combinedMap(extraStandardFunctions, sf); for (int i = 0; ; i++) { Set defd = new HashSet(findFunctions(tok)); int j; while ((j = jfind(tok, "should not include function *.")) >= 0) { String fname = tok.get(j+8); shouldNotIncludeFunction.add(fname); clearAllTokens(tok.subList(j, j+12)); } while ((j = jfind(tok, "do not include function *.")) >= 0) { String fname = tok.get(j+8); doNotIncludeFunction.add(fname); clearAllTokens(tok.subList(j, j+12)); } doNotIncludeFunction.addAll(tok_importedStaticFunctionNames(tok)); // changes tok Set invocations = findFunctionInvocations(tok, sfMap, hardFunctionReferences, defd, true); /*if (invocations.contains("str")) print("==STR==" + join(tok) + "==STR==");*/ if (!cic(definitions, "leanMode")) invocations.addAll(functionsToAlwaysInclude); //print("Functions invoked: " + structure(invocations)); List needed = diff(invocations, defd); for (String f : doNotIncludeFunction) needed.remove(f); if (needed.isEmpty()) break; print("Adding functions: " + join(" " , needed)); HashSet neededSet = new HashSet(needed); Collection bad = setIntersection(neededSet, shouldNotIncludeFunction); if (nempty(bad)) { String msg = "INCLUDING BAD FUNCTIONS: " + sfu(bad); print(msg); print(join(tok)); throw fail(msg); } List added = new ArrayList(); List> parts = new ArrayList(); List preload = new ArrayList(); for (String x : needed) if (sfMap.containsKey(x)) preload.add(sfMap.get(x)); print("Preloading: " + preload); cachePreload(preload); for (String x : cloneList(needed)) { if (defd.contains(x)) continue; String id = sfMap.get(x); if (id == null) { print("Standard function " + x + " not found."); needed.remove(x); continue; } //print("Adding function: " + x + " (" + id + ")"); String function = cacheGet(id); //if (("\n" + function).contains("\n!")) print("Warning: " + id + " contains translators."); if (cacheStdFunctions) { long _id = psI(id); CachedInclude ci = cachedIncludes.get(_id); if (ci == null) { cachedIncludes.put(_id, ci = new CachedInclude()); //println("Caching include " + _id + ", l=" + l(cachedIncludes)); } function += "\n"; final String _function = function; if (neq(ci.javax, function)) { print("Compiling function: " + x); ci.javax = function; ci.java = executor.submit(new Callable() { public String call() { // XXX return join(localStuff1(jtok(_function))); } }); ci.realJava = null; } parts.add(ci.javaFuture()); } else parts.add(nowFuture(function + "\n")); added.add(x); Collection newFunctions = new HashSet(findFunctionDefs(javaTok(function))); defd.addAll(newFunctions); for (String f : newFunctions) if (!addedFunctions.add(f)) { printSources(tok); throw fail("Trying to add function " + f + " again - main class syntax broken!"); } } String text = join(getAllFutures(parts)); if (cacheStdFunctions) tok = includeInMainLoaded_stdReTok(tok, text); else tok = includeInMainLoaded(tok, text); // defd = new HashSet(findFunctions(tok)); //print("Functions added: " + joinWithSpace(added)); for (String x : needed) if (!defd.contains(x)) { print(join(tok)); throw fail("Function not defined properly: " + x); } //print("Iteration " + (i+2)); tok_definitions(tok); tok_ifndef(tok); tok_ifdef(tok); if (i >= 1000) throw fail("Too many iterations"); } return tok; } static List findFunctions(List tok) { //ret findFunctionDefinitions(join(findMainClass(tok))); return findFunctionDefs(findMainClass(tok)); } static String cacheGet(String snippetID) { snippetID = formatSnippetID(snippetID); String text = snippetCache.get(snippetID); if (text == null) { text = loadSnippet(snippetID); // very early processing/checks for includes if (hasUnclosedStringLiterals(text)) throw fail("Unclosed string literals in " + snippetID); if (regexpContains("\\bscope\\b", text)) { List tok = javaTok(text); tok_scopes(tok, "autoCloseScopes" , true); text = join(tok); } snippetCache.put(snippetID, text); } return text; } static void cachePreload(Collection ids) { List needed = new ArrayList(); for (String id : ids) if (!snippetCache.containsKey(formatSnippetID(id))) needed.add(formatSnippetID(id)); if (l(needed) > 1) { List texts = loadSnippets(needed); for (int i = 0; i < l(needed); i++) if (texts.get(i) != null) snippetCache.put(needed.get(i), texts.get(i)); } } static List jtok(List tok) { return jtok(join(tok)); } static List jtok(String s) { List l = javaTok(s); return useIndexedList ? new IndexedList2(l) : l; } static HashSet haveClasses_actual(List tok) { HashSet have = new HashSet(); for (List c : innerClassesOfMain(tok)) have.add(getClassDeclarationName(c)); return have; } static HashSet haveClasses_addImported(List tok, HashSet have) { have.addAll(tok_importedClassNames(tok)); have.addAll(usualJavaClassNames()); // for S => S.class return have; } // works on Java level (no "sclass" etc) // returns list of classes we have (useful for other processing) static Set addStandardClasses_v2(List tok) { if (lclasses == null) { String sc = cacheGet("#1003674"); lclasses = new ArrayList(); for (String line : tlft_j(sc)) { int idx = line.indexOf('/'); lclasses.addAll(ll(line.substring(0, idx), line.substring(idx+1))); } } List definitions = lclasses; for (int safety = 0; safety < 10; safety++) { HashSet have = haveClasses_actual(tok); have.addAll(tok_importedClassNames(tok)); int j; while ((j = jfind(tok, "should not include class *.")) >= 0) { String cname = tok.get(j+8); shouldNotIncludeClass.add(cname); clearAllTokens(tok.subList(j, j+12)); } Map need = new HashMap(); Set idx = tokenIndexWithoutIfclass_forStdClasses(tok); while ((j = jfind(tok, "please include class *.")) >= 0) { String cname = tok.get(j+6); idx.add(cname); clearAllTokens(tok.subList(j, j+10)); } for (int i = 0; i+1 < l(definitions); i += 2) { String className = definitions.get(i); if (idx.contains(className) && !have.contains(className)) need.put(className, definitions.get(i+1)); } if (hasDef("SymbolAsString")) { print("Have SymbolAsString."); if (need.containsKey("Symbol")) { print("Have Symbol."); need.remove("Symbol"); } } else print("No SymbolAsString."); if (empty(need)) return have; for (String className : keys(need)) if (shouldNotIncludeClass.contains(className)) { String msg = "INCLUDING BAD CLASS: " + className; print(msg); print(join(tok)); throw fail(msg); } cachePreload(values(need)); StringBuilder buf = new StringBuilder(); print("Adding classes: " + joinWithSpace(keys(need))); for (String className : keys(need)) { if (have.contains(className)) continue; // intermittent add String snippetID = need.get(className); //print("Adding class " + className + " / " + snippetID); snippetID = fsI(snippetID); String text = cacheGet(snippetID); assertTrue(cacheStdClasses); long _id = psI(snippetID); CachedInclude ci = cachedIncludes.get(_id); if (ci == null) cachedIncludes.put(_id, ci = new CachedInclude()); if (neq(ci.javax, text)) { print("Compiling class: " + className); ci.javax = text; ci.java = null; ci.realJava = join(localStuff1(jtok(text))); } buf.append(ci.java()); List ct = javaTok(ci.java()); for (List c : allClasses(ct)) { String name = getClassDeclarationName(c); have.add(name); } if (!have.contains(className)) throw fail("Wrongly defined class: " + className + " / " + snippetID); if (!addedClasses.add(className)) { printSources(tok); throw fail("Trying to add class " + className + " again - main class syntax broken!"); } } // for className tok = includeInMainLoaded_stdReTok(tok, str(buf)); } throw fail("safety 10"); } static Set expandableClassNames = lithashset("BigInteger"); // no reTok - leaves tok dirty // magically append ".class" to class name references static boolean expandClassReferences_lazy(List tok, Set classNames) { boolean change = false; for (int i = 3; i+2 < l(tok); i += 2) { String t = tok.get(i); // skip implements/extends/throws lists if (eqOneOf(t, "implements", "extends", "throws")) { i = tok_endOfImplementsList(tok, i); continue; } if (classNames.contains(t) || expandableClassNames.contains(t)) { String s = tok.get(i-2); t = tok.get(i+2); // TODO: This whole logic ain't very good // (Hard to distinguish between "Int.class" as an argument // and "Int" as a type parameter.) if (eqOneOf(s, "instanceof", "new", ".", "<", ">", "/", "nu")) continue; if (isIdentifier(s) || isInteger(s)) continue; if (eq(t, ",") && isIdentifier(get(tok, i+4)) && eqGet(tok, i+6, ">")) continue; // e.g. T3, S, S> if (eq(s, ",") && isIdentifier(get(tok, i-4)) && eqGet(tok, i-6, "<")) continue; // e.g. T3 if (eq(s, ",") && eqOneOf(_get(tok, i-6), "implements", "throws")) continue; // check for cast if (eq(s, "(") && eq(t, ")") && i >= 5) { if (!eqOneOf(get(tok, i+4), "{", ";")) { String x = tok.get(i-4); if (!isIdentifier(x)) continue; if (eqOneOf(x, "ret", "return")) continue; } } if (eqOneOf(t, ",", ")", ";", ":")) { tok.set(i, tok.get(i) + ".class"); change = true; } } } return change; } static void expandClassReferences(List tok, Set classNames) { if (expandClassReferences_lazy(tok, classNames)) reTok(tok); } // "/" => "((ClassName) )" static void slashCasts(List tok, final Set classNames) { /*jreplace(tok, "/", "(($3) $1)", tokcondition { ret classNames.contains(tok.get(i+5)); });*/ int n = l(tok)-4; for (int i = 1; i < n; i += 2) if (tok.get(i+2).equals("/") && isIdentifier(tok.get(i)) && classNames.contains(tok.get(i+4))) replaceTokens_reTok(tok, i, i+5, "((" + tok.get(i+4) + ") " + tok.get(i) + ")"); } // "(...)" => "new (...)" // doesn't work at beginning of statement as we can't easily // distinguish it from a constructor declaration. static void newWithoutNew(List tok, final Set classNames) { TokCondition cond = newWithoutNew_condition(classNames); jreplace(tok, "(", "new $1(", cond); // just one case with type arg for now jreplace(tok, "<>(", "new $1<$3>(", cond); } static TokCondition newWithoutNew_condition(final Set classNames) { return new TokCondition() { boolean get(final List tok, final int i) { if (!classNames.contains(tok.get(i+1))) return false; String prev = _get(tok, i-1); boolean ok = eq(prev, ">") ? eqGet(tok, i-3, "-") : neqOneOf(prev, "new", ";", "}", "{", "public", "protected", "private", "."); //print("newWithoutNew: checking " + struct(subList(tok, i-1, i+2)) + " => " + ok); return ok; }}; } static boolean processConceptsDot(List tok) { boolean anyChange = false, change; do { change = false; for (int i : jfindAll(tok, "concepts.")) if (contains(get(tok, i+3), "\n")) { replaceTokens(tok, i, i+3, "!" + "include once #1004863 // Dynamic Concepts"); reTok(tok, i, i+3); change = anyChange = true; break; } } while (change); return anyChange; } static void caseAsVariableName(List tok) { if (!tok.contains("case")) return; for (int i = 1; i+2 < l(tok); i += 2) { String t = tok.get(i+2); if (tok.get(i).equals("case") && !(t.startsWith("'") || isInteger(t) || isIdentifier(t))) tok.set(i, "_case"); } } static void continueAsFunctionName(List tok) { jreplace(tok, "continue(", "_continue("); } // f bla => "bla" - and "please include function bla." static void functionReferences(List tok) { int i; jreplace_dyn(tok, "f-thread ", new F2, Integer, Object>() { Object get(List tok, Integer cIdx) { try { return "dynamicCallableMC_thread(" + quote(tok.get(cIdx+6)) + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "\"dynamicCallableMC_thread(\" + quote(tok.get(cIdx+6)) + \")\""; }}); String keyword = "f"; while ((i = jfind(tok, keyword + " ", new TokCondition() { boolean get(final List tok, final int i) { return !eq(tok.get(i+3), "instanceof"); }})) >= 0) { String f = tok.get(i+2); clearTokens(tok, i, i+2); tok.set(i+2, quote(f)); reTok(tok, i, i+2); tok.set(l(tok)-1, last(tok) + "\nplease include function " + f + "."); reTok(tok, l(tok)-1, l(tok)); } // r|rThread|rEnter|rThreadEnter fname => r|rThread|... { fname() } while ((i = jfindOneOf_cond(tok, new TokCondition() { boolean get(final List tok, final int i) { return !eq(tok.get(i+3), "instanceof"); }}, "r ", "rThread ", "rEnter ", "rThreadEnter ")) >= 0) { String f = tok.get(i+2); replaceTokens(tok, i, i+3, tok.get(i) + " { " + f + "(); }"); reTok(tok, i, i+3); } // dm_q fname => r_dm_q(r fname) jreplace(tok, "dm_q ", "r_dm_q(r $2)"); // vf fname => voidfunc(S s) { fname(s) } jreplace(tok, "vf<> ", "voidfunc($3 a) { $5(a) }"); // vf> fname => voidfunc(L a) { fname(a) } jreplace(tok, "vf<<>> ", "voidfunc($3<$5> a) { $8(a) }"); // construct Entry => func(S s) -> Entry { new Entry(s) } jreplace(tok, "construct<> ", "func($3 a) -> $5 { new $5(a) }"); // f fname => func -> S { fname() } jreplace(tok, "f<> ", "func -> $3 { $5() }"); // f fname => func(S x) -> S { fname(x) } jreplace(tok, "f<, > ", "func($3 x) -> $5 { $7(x) }"); // f> fname => func(S x) -> L { fname(x) } jreplace(tok, "f<, <>> ", "func($3 x) -> $5 $6 $7 $8 { $10(x) }"); // f, S> fname => func(S x, L y) -> S { fname(x, y) } jreplace(tok, "f<, <>, > ", "func($3 x, $5 $6 $7 $8 y) -> $10 { $12(x, y) }"); // if1 fname => a -> fname(a) jreplace_dyn(tok, "if1 ", new F2, Integer, String>() { String get(List tok, Integer i) { try { String var = makeVar(); return var + " -> " + tok.get(i+2) + "(" + var + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S var = makeVar();\r\n ret var + \" -> \" + tok.get(i+2) + \"(\" + var + \")\";"; }}); } static void quicknu(List tok) { jreplace(tok, "nu (", "nu($2.class, "); // not needed anymore jreplace(tok, "nu ", "new $2"); } // fill variable innerClasses_list static void innerClassesVar(List tok, Set have) { int i = jfind_check("myInnerClasses_list",tok, ">myInnerClasses_list;"); if (i < 0) return; tok.set(i+4, "=litlist(\n" + joinQuoted(", ", have) + ");"); reTok(tok, i+4, i+5); } // fill variable innerClasses_list static void fillVar_transpilationDate(List tok) { int i = jfind_check("myTranspilationDate_value",tok, "long myTranspilationDate_value;"); if (i < 0) return; tok.set(i+4, " = " + now() + "L;"); reTok(tok, i+4, i+5); } // process ifclass x ... endif blocks static void tok_ifclass(List tok, Set have) { if (!tok.contains("ifclass")) return; int i; while ((i = rjfind(tok, "ifclass ")) >= 0) { int j = jfind(tok, i+4, "endif"); if (j < 0) j = l(tok)-1; String name = tok.get(i+2); boolean has = have.contains(name); //print("ifclass " + name + " => " + has); clearTokens(tok, i, i+3); clearTokens(tok, j, j+1); if (!has) clearTokens(tok, i+3, j); reTok(tok, i, j+1); } } // set flag *. static void tok_definitions(List tok) { int i; while ((i = jfind_check("flag",tok, "set flag .")) >= 0) { String fname = tok.get(i+4); print("Setting flag " + fname); definitions.add(fname); clearAllTokens(tok.subList(i, i+8)); } while ((i = jfind_check("flag",tok, "unset flag .")) >= 0) { String fname = tok.get(i+4); print("Unsetting flag " + fname); definitions.remove(fname); clearAllTokens(tok.subList(i, i+8)); } } static void tok_findRewrites(List tok) { int i; while ((i = jfind(tok, "rewrite =")) >= 0) { String token = tok.get(i+2); int repStart = i+6; int repEnd = smartIndexOf(tok, repStart, "."); String replacement = joinSubList(tok, repStart, repEnd-1); clearTokens(tok, i, repEnd+1); rewrites.put(token, replacement); print("Have rewrite: " + token + " => " + replacement); } } static void tok_processRewrites(List tok) { for (String token : keys(rewrites)) jreplace(tok, token, rewrites.get(token)); } // extend *. (set base class of main class) static void tok_extend(List tok) { int i; while ((i = jfind(tok, "extend .")) >= 0) { mainBaseClass = tok.get(i+2); clearAllTokens(tok, i, i+7); } } // process ifndef x ... endifndef blocks static void tok_ifndef(List tok) { if (!tok.contains("ifndef")) return; int i; while ((i = rjfind(tok, "ifndef ")) >= 0) { int j = jfind(tok, i+4, "endifndef"); if (j < 0) j = l(tok)-1; String fname = tok.get(i+2); boolean has = !definitions.contains(fname); //print("ifndef " + fname + " => " + has); clearTokens(tok, i, i+3); clearTokens(tok, j, j+1); if (!has) clearTokens(tok, i+3, j); reTok(tok, i, j+1); } } // process ifdef x ... endifdef blocks static void tok_ifdef(List tok) { if (!tok.contains("ifdef")) return; int i; while ((i = rjfind(tok, "ifdef ")) >= 0) { int j = jfind(tok, i+4, "endifdef"); if (j < 0) j = l(tok)-1; String fname = tok.get(i+2); boolean has = definitions.contains(fname); //print("ifdef " + fname + " => " + has); clearTokens(tok, i, i+3); clearTokens(tok, j, j+1); if (!has) clearTokens(tok, i+3, j); reTok(tok, i, j+1); } } static void conceptDeclarations(List tok) { for (String kw : ll("concept", "sconcept")) { Object cond = new TokCondition() { boolean get(final List tok, final int i) { tok_addFieldOrder(tok, i+1); return true; }}; boolean re = false; if (jreplace(tok, kw + " {", "static class $2 extends Concept {", cond)) re = true; if (jreplace(tok, kw + " implements", "static class $2 extends Concept implements", cond)) re = true; if (jreplace(tok, kw + " ", "static class $2", cond)) re = true; if (re) reTok(tok); } } static void shortenedSubconcepts(List tok) { jreplace(tok, " > {", "concept $3 extends $1 {", new TokCondition() { boolean get(final List tok, final int i) { boolean b = (i == 0 || tok.get(i).contains("\n")) || eq(_get(tok, i-1), "abstract"); // only at beginning of line or after "abstract" //print("subconcept " + b + ": " + structure(subList(tok, i-1, i+5))); return b; }}); } // -slightly experimental // -do calculation in another thread, then return to AWT thread // -must be placed in a block // -transforms rest of block static void unswing(List tok) { int i; while ((i = jfind(tok, "unswing {")) >= 0) { int idx = i+2; int closingBracket = findEndOfBracketPart(tok, idx)-1; int endOfOuterBlock = findEndOfBracketPart(tok, closingBracket)-1; tok.set(i, "thread"); tok.set(closingBracket, " awt {"); tok.set(endOfOuterBlock, "}}}"); reTok(tok, closingBracket-1, endOfOuterBlock+1); } } // -Syntax: lock theLock; // -lock a lock, unlock at end of current block with finally static void lockBlocks(List tok) { int i; while ((i = jfind(tok, "lock ", new TokCondition() { boolean get(final List tok, final int i) { return neq(tok.get(i+3), "instanceof"); }})) >= 0) { int semicolon = findEndOfStatement(tok, i)-1; String var = makeVar(); int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1; replaceTokens(tok, i, semicolon+1, "Lock " + var + " = " + joinSubList(tok, i+2, semicolon-1) + "; lock(" + var + "); try {"); tok.set(endOfOuterBlock, "} finally { unlock(" + var + "); } }"); reTok(tok, i, endOfOuterBlock+1); } } // -Syntax: temp Bla bla = bla(); // -expands to try(Bla bla = bla()) { ... } with rest of block inside static void tempBlocks(List tok) { int i; while ((i = jfind(tok, "temp ")) >= 0) { int semicolon = findEndOfStatement(tok, i)-1; int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1; List sub = subList(tok, i-1, semicolon); int eq = subList(sub, 0, smartIndexOfOneOf(sub, "{", "(")).indexOf("="); String var; if (eq >= 0) var = sub.get(eq-2); else { // no var name, e.g. temp newThoughtSpace(); var = makeVar(); tok.set(i+2, "AutoCloseable " + var + " = " + tok.get(i+2)); } //tok.set(i, "try ("); //tok.set(semicolon, ") {"; //tok.set(endOfOuterBlock, "}}"); tok.set(i, ""); tok.set(semicolon, "; try {"); tok.set(endOfOuterBlock, "} finally { _close(" + var + "); }}"); reTok(tok, i, endOfOuterBlock+1); } } static void cleanMeUp() { for (CachedInclude ci : values(cachedIncludes)) ci.clean(); vmKeepWithProgramMD5_save("cachedIncludes"); } static void printSources(List tok) { print("----"); print(join(tok)); print("----"); } static void tok_quickInstanceOf(List tok, final Set haveClasses) { if (!quickInstanceOfEnabled) return; // "x << X" or "x >> X" => "x instanceof X" for (String op : ll("<<", ">>")) jreplace(tok, " " + op + " ", "$1 instanceof $4", new TokCondition() { boolean get(final List tok, final int i) { return haveClasses.contains(tok.get(i+7)) && !eqOneOf(tok.get(i-1), "<", "extends", "implements"); }}); } static boolean hasDef(String s) { return definitions.contains(s); } static void expandTriple(List tok) { jreplace(tok, "T3< >", "T3<$3, $3, $3>"); jreplace(tok, "T3< <> >", "T3<$3<$5>, $3<$5>, $3<$5>>"); } static void tok_shortFinals(List tok) { jreplace(tok, "fS", "final S"); jreplace(tok, "fO", "final O"); jreplace(tok, "fL", "final L"); jreplace(tok, "fMap", "final Map"); jreplace(tok, "fRunnable", "final Runnable"); jreplace(tok, "f int", "final int"); } static void tok_mainClassNameAndPackage(List tok) { int i; if ((i = jfind(tok, "mainClassName ")) >= 0) { mainClassName = tok.get(i+2); if (eqGet(tok, i+4, ".") && isIdentifier(get(tok, i+6))) { mainPackage = mainClassName; mainClassName = tok.get(i+6); clearTokensAndReTok(tok, i, i+7); } else clearTokensAndReTok(tok, i, i+3); } if ((i = jfind(tok, "mainPackage ")) >= 0) { mainPackage = tok.get(i+2); clearTokens(tok, i, i+3); reTok(tok, i, i+3); } } static void defineMapLikes(List tok) { int i; while ((i = jfind(tok, "mapLike ")) >= 0) { mapLikeFunctions.add(tok.get(i+2)); clearTokens_reTok(tok, i, i+2); } } static void defineMapMethodLikes(List tok) { int i; while ((i = jfind(tok, "mapMethodLike ")) >= 0) { mapMethodLikeFunctions.add(tok.get(i+2)); clearTokens_reTok(tok, i, i+2); } } // functions that work like "nu" syntactically (accept a class as "super-first" parameter [left of the bracket]) static void defineNuLikes(List tok) { int i; while ((i = jfind(tok, "nuLike ")) >= 0) { nuLikeFunctions.add(tok.get(i+2)); clearTokens_reTok(tok, i, i+2); } } static void defineExtraSF(List tok) { int i; IntRange reTok = null; while ((i = jfind(tok, "function is in *.")) >= 0) { extraStandardFunctions.put(tok.get(i+2), fsI(unquote(tok.get(i+8)))); clearTokens(tok, i, i+12); reTok = combineIntRanges(reTok, intRange(i, i+12)); } reTok(tok, reTok); } static boolean tok_applyMapLikeFunctions(List tok, final Set mapLikeFunctions) { // map funcname(...) => map(f funcname, ...) // filter funcname(...) => filter(f funcname, ...) // ... return jreplace(tok, " (", "$1(f $2,", new F2, Integer, Boolean>() { Boolean get(List tok, Integer i) { try { return contains(mapLikeFunctions, tok.get(i+1)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "contains(mapLikeFunctions, tok.get(i+1))"; }}); } static boolean tok_applyMapMethodLikeFunctions(List tok, final Set mapMethodLikeFunctions) { // mapMethod funcname(...) => mapMethod('funcname, ...) // collect funcname(...) => collect('funcname, ...) // ... return jreplace_dyn(tok, " (", new F2, Integer, String>() { String get(List tok, Integer cIdx) { try { return tok.get(cIdx) + "(" + quote(tok.get(cIdx+2)) + ","; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tok.get(cIdx) + \"(\" + quote(tok.get(cIdx+2)) + \",\""; }}, new F2, Integer, Boolean>() { Boolean get(List tok, Integer i) { try { return contains(mapMethodLikeFunctions, tok.get(i+1)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "contains(mapMethodLikeFunctions, tok.get(i+1))"; }}); } static void runMetaPostBlocks(List tok) { for (String code : unnull(metaPostBlocks)) { ping(); call(hotwireCached(standardFunctionSnippet(assertIdentifier(code))), code, tok); } //callF(codeToFunctionOnArbitraryType(code, "LS", L, "tok"), tok); } static void runMetaTransformers(List tok) { for (String code : unnull(metaTransformers)) { ping(); tok_runMetaTransformer(tok, code); } } static boolean tok_applyNuLikeFunctions(List tok, final Set nuLikeFunctions) { // nu ClassName(...) => nu(ClassName, ...) // ... return jreplace_dyn(tok, " (", new F2, Integer, String>() { String get(List tok, Integer cIdx) { try { return tok.get(cIdx) + "(" + tok.get(cIdx+2) + ".class,"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tok.get(cIdx) + \"(\" + tok.get(cIdx+2) + \".class,\""; }}, new F2, Integer, Boolean>() { Boolean get(List tok, Integer i) { try { return contains(nuLikeFunctions, tok.get(i+1)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "contains(nuLikeFunctions, tok.get(i+1))"; }}); } static boolean metaCodeAllowed() { return allowMetaCode || containsIC(definitions, "allowMetaCode"); } static List ll(A... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (A x : a) l.add(x); return l; } static HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } // get purpose 1: access a list/array/map (safer version of x.get(y)) static A get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } // seems to conflict with other signatures /*static B get(Map map, A key) { ret map != null ? map.get(key) : null; }*/ static A get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } // default to false static boolean get(boolean[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : false; } // get purpose 2: access a field by reflection or a map static Object get(Object o, String field) { try { if (o == null) return null; if (o instanceof Class) return get((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); Field f = getOpt_findField(o.getClass(), field); if (f != null) { makeAccessible(f); return f.get(o); } if (o instanceof DynamicObject) return ((DynamicObject) o).fieldValues.get(field); } catch (Exception e) { throw asRuntimeException(e); } throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName()); } static Object get_raw(String field, Object o) { return get_raw(o, field); } static Object get_raw(Object o, String field) { try { if (o == null) return null; Field f = get_findField(o.getClass(), field); makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static Object get(Class c, String field) { try { Field f = get_findStaticField(c, field); makeAccessible(f); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static Field get_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field get_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static Object get(String field, Object o) { return get(o, field); } static String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static String formatSnippetID(long id) { return "#" + id; } static String fsi(String id) { return formatSnippetID(id); } static String joinWithComma(Collection c) { return join(", ", c); } static String joinWithComma(String... c) { return join(", ", c); } static String joinWithComma(Pair p) { return p == null ? "" : joinWithComma(str(p.a), str(p.b)); } static List quoteAll(Collection l) { List x = new ArrayList(); for (String s : l) x.add(quote(s)); return x; } static ArrayList asList(A[] a) { return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a)); } static ArrayList asList(int[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (int i : a) l.add(i); return l; } static ArrayList asList(float[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (float i : a) l.add(i); return l; } static ArrayList asList(Iterable s) { if (s instanceof ArrayList) return (ArrayList) s; ArrayList l = new ArrayList(); if (s != null) for (A a : s) l.add(a); return l; } static ArrayList asList(Producer p) { ArrayList l = new ArrayList(); A a; if (p != null) while ((a = p.next()) != null) l.add(a); return l; } static ArrayList asList(Enumeration e) { ArrayList l = new ArrayList(); if (e != null) while (e.hasMoreElements()) l.add(e.nextElement()); return l; } static int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static ArrayList toList(A[] a) { return asList(a); } static ArrayList toList(int[] a) { return asList(a); } static ArrayList toList(Set s) { return asList(s); } static ArrayList toList(Iterable s) { return asList(s); } static boolean arraysEqual(Object[] a, Object[] b) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) if (neq(a[i], b[i])) return false; return true; } static void change() { //mainConcepts.allChanged(); // safe version for now cause function is sometimes included unnecessarily (e.g. by EGDiff) callOpt(getOptMC("mainConcepts"), "allChanged"); } static List diff(Collection a, Collection b) { Set set = asSet(b); List l = new ArrayList(); for (String s : a) if (!set.contains(s)) l.add(s); return l; } static void clear(Collection c) { if (c != null) c.clear(); } static void lock(Lock lock) { try { ping(); if (lock == null) return; try { lock.lockInterruptibly(); } catch (InterruptedException e) { print("Locking interrupted! I probably deadlocked, oops."); printStackTrace(e); rethrow(e); } ping(); } catch (Exception __e) { throw rethrow(__e); } } static void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static ReentrantLock lock() { return fairLock(); } //sbool ping_actions_shareable = true; static volatile boolean ping_pauseAll = false; static int ping_sleep = 100; // poll pauseAll flag every 100 static volatile boolean ping_anyActions = false; static Map ping_actions = newWeakHashMap(); static ThreadLocal ping_isCleanUpThread = new ThreadLocal(); // always returns true static boolean ping() { if (ping_pauseAll || ping_anyActions ) ping_impl(true /* XXX */); //ifndef LeanMode ping_impl(); endifndef return true; } // returns true when it slept static boolean ping_impl(boolean okInCleanUp) { try { if (ping_pauseAll && !isAWTThread()) { do Thread.sleep(ping_sleep); while (ping_pauseAll); return true; } if (ping_anyActions) { // don't allow sharing ping_actions if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get())) failIfUnlicensed(); Object action = null; synchronized(ping_actions) { if (!ping_actions.isEmpty()) { action = ping_actions.get(currentThread()); if (action instanceof Runnable) ping_actions.remove(currentThread()); if (ping_actions.isEmpty()) ping_anyActions = false; } } if (action instanceof Runnable) ((Runnable) action).run(); else if (eq(action, "cancelled")) throw fail("Thread cancelled."); } return false; } catch (Exception __e) { throw rethrow(__e); } } static RuntimeException rethrow(Throwable t) { if (t instanceof Error) _handleError((Error) t); throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static RuntimeException rethrow(String msg, Throwable t) { throw new RuntimeException(msg, t); } static volatile boolean readLine_noReadLine = false; static String readLine_lastInput; static String readLine_prefix = "[] "; static String readLine() { if (readLine_noReadLine) return null; String s = readLineHidden(); if (s != null) { readLine_lastInput = s; print(readLine_prefix + s); } return s; } static String format3(String pat, Object... args) { if (args.length == 0) return pat; List tok = javaTokPlusPeriod(pat); int argidx = 0; for (int i = 1; i < tok.size(); i += 2) if (tok.get(i).equals("*")) tok.set(i, format3_formatArg(argidx < args.length ? args[argidx++] : "null")); return join(tok); } static String format3_formatArg(Object arg) { if (arg == null) return "null"; if (arg instanceof String) { String s = (String) arg; return isIdentifier(s) || isNonNegativeInteger(s) ? s : quote(s); } if (arg instanceof Integer || arg instanceof Long) return String.valueOf(arg); return quote(structure(arg)); } static volatile StringBuffer local_log = new StringBuffer(); // not redirected static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot // in bytes - will cut to half that static volatile int print_log_max = 1024*1024; static volatile int local_log_max = 100*1024; static boolean print_silent = false; // total mute if set static Object print_byThread_lock = new Object(); static volatile ThreadLocal print_byThread; // special handling by thread - prefers F1 static volatile Object print_allThreads; static volatile Object print_preprocess; static void print() { print(""); } static A print(String s, A o) { print((endsWithLetterOrDigit(s) ? s + ": " : s) + o); return o; } // slightly overblown signature to return original object... static A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = String.valueOf(o) + "\n"; print_noNewLine(s); return o; } static void print_noNewLine(String s) { Object f = getThreadLocal(print_byThread_dontCreate()); if (f == null) f = print_allThreads; if (f != null) // We do need the general callF machinery here as print_byThread is sometimes shared between modules if (isFalse( f instanceof F1 ? ((F1) f).get(s) : callF(f, s))) return; print_raw(s); } static void print_raw(String s) { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); } static void print_autoRotate() { } static int shorten_default = 100; static String shorten(String s) { return shorten(s, shorten_default); } static String shorten(String s, int max) { return shorten(s, max, "..."); } static String shorten(String s, int max, String shortener) { if (s == null) return ""; if (max < 0) return s; return s.length() <= max ? s : substring(s, 0, min(s.length(), max-l(shortener))) + shortener; } static String shorten(int max, String s) { return shorten(s, max); } static RuntimeException fail() { throw new RuntimeException("fail"); } static RuntimeException fail(Throwable e) { throw asRuntimeException(e); } static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); } static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); } static boolean getServerTranspiled2_allowLocalFallback = true, getServerTranspiled2_localFallbackVerbose = true; // to avoid checking server for transpilations too often when booting OS static Map getServerTranspiled2_tempCache; static String getServerTranspiled2(String id) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getTranspiled(id); id = fsIOpt(id); String transpiled = mapGet(getServerTranspiled2_tempCache, id); if (transpiled != null) return transpiled; if (getServerTranspiled2_tempCache != null) print("CACHE FAIL on " + id); transpiled = loadCachedTranspilation(id); String md5 = null; if (machineIsOffline() || isOfflineMode() || isLocalSnippet(id)) return transpiled; if (transpiled != null) md5 = md5(transpiled); String transpiledSrc; try { transpiledSrc = getServerTranspiled(formatSnippetID(id), md5); } catch (Throwable e) { if (!getServerTranspiled2_allowLocalFallback) rethrow(e); printExceptionShort(e); if (getServerTranspiled2_localFallbackVerbose) print("Fallback to local code"); return transpiled; } if (eq(transpiledSrc, "SAME")) { if (!isTrue(loadPage_silent.get())) print("SAME"); return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiled); } return mapPut_returnValue(getServerTranspiled2_tempCache, id, transpiledSrc); } static Pair pair(A a, B b) { return new Pair(a, b); } static Pair pair(A a) { return new Pair(a, a); } static int l(Object[] a) { return a == null ? 0 : a.length; } static int l(boolean[] a) { return a == null ? 0 : a.length; } static int l(byte[] a) { return a == null ? 0 : a.length; } static int l(short[] a) { return a == null ? 0 : a.length; } static int l(long[] a) { return a == null ? 0 : a.length; } static int l(int[] a) { return a == null ? 0 : a.length; } static int l(float[] a) { return a == null ? 0 : a.length; } static int l(double[] a) { return a == null ? 0 : a.length; } static int l(char[] a) { return a == null ? 0 : a.length; } static int l(Collection c) { return c == null ? 0 : c.size(); } static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible static int l(Map m) { return m == null ? 0 : m.size(); } static int l(CharSequence s) { return s == null ? 0 : s.length(); } static long l(File f) { return f == null ? 0 : f.length(); } static int l(Object o) { return o == null ? 0 : o instanceof String ? l((String) o) : o instanceof Map ? l((Map) o) : o instanceof Collection ? l((Collection) o) : o instanceof Object[] ? l((Object[]) o) : o instanceof boolean[] ? l((boolean[]) o) : o instanceof byte[] ? l((byte[]) o) : o instanceof char[] ? l((char[]) o) : o instanceof short[] ? l((short[]) o) : o instanceof int[] ? l((int[]) o) : o instanceof float[] ? l((float[]) o) : o instanceof double[] ? l((double[]) o) : o instanceof long[] ? l((long[]) o) : (Integer) call(o, "size"); } static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); } static int l(IntRange r) { return r == null ? 0 : r.length(); } static String md5(String text) { try { if (text == null) return "-"; return bytesToHex(md5_impl(toUtf8(text))); // maybe different than the way PHP does it... } catch (Exception __e) { throw rethrow(__e); } } static String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static String md5(File file) { return md5OfFile(file); } static String fsIOpt(String s) { return formatSnippetIDOpt(s); } // returns actual CNC static List findMainClass(List tok) { for (List c : reversedList(allClasses(tok))) { String name = getClassDeclarationName(c); if (eq(name, "main") || name.startsWith("x")) return c; } return findBlock("m {", tok); } // TODO: extended multi-line strings static int javaTok_n, javaTok_elements; static boolean javaTok_opt = false; static List javaTok(String s) { ++javaTok_n; ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i+2 < l && "'\\".indexOf(s.charAt(i+2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { // allow multi-line strings, but not for ' ++j; break; } else if (c2 == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static List javaTok(List tok) { return javaTokWithExisting(join(tok), tok); } static boolean useDummyMainClasses() { return true; //ret eq("1", trim(loadTextFile(getProgramFile(#1008755, "use-dummy-main-classes")))); } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } static boolean tok_classHasModifier(List classDecl, String modifier) { if (classDecl == null) return false; int i = classDecl.indexOf("class"); return subList(classDecl, 0, i).contains(modifier); } // before you use this, add a RAM disk cleaner static boolean javaCompileToJar_useRAMDisk = false; static File javaCompileToJar_optionalRename(String src, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, "", destJar, progIDForRename); } static synchronized File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename) { return javaCompileToJar_optionalRename(src, dehlibs, destJar, progIDForRename, null); } // returns path to jar static synchronized File javaCompileToJar_optionalRename(String src, String dehlibs, File destJar, String progIDForRename, String progID) { String javaTarget = null; // use default target //print("Compiling " + l(src) + " chars"); String dummyClass = "main"; if (progIDForRename != null) { dummyClass = dummyMainClassName(progIDForRename); src += "\nclass " + dummyClass + "{}"; } String md5 = md5(src); File jar = destJar; Class j = getJavaX(); if (javaTarget != null) setOpt(j, "javaTarget", javaTarget); //setOpt(j, "verbose", true); File srcDir = tempDir(); String className = "main"; String fileName = dummyClass + ".java"; List tok = javaTok(src); String packageName = tok_packageName(tok); if (packageName != null) fileName = packageName.replace(".", "/") + "/" + tok_firstClassName(tok) + ".java"; File mainJava = new File(srcDir, fileName); //print("main java: " + mainJava.getAbsolutePath()); saveTextFile(mainJava, src); File classesDir = javaCompileToJar_useRAMDisk ? tempDirPossiblyInRAMDisk() : tempDir(); //print("Compiling to " + f2s(classesDir)); try { List libraries = new ArrayList(); Matcher m = Pattern.compile("\\d+").matcher(dehlibs); while (m.find()) { String libID = m.group(); //print("libID=" + quote(libID)); assertTrue(isSnippetID(libID)); libraries.add(loadLibraryOrSrcLib(libID)); } libraries.add(pathToJavaxJar()); String compilerOutput; try { compilerOutput = (String) call(j, "compileJava", srcDir, libraries, classesDir); } catch (Throwable e) { compilerOutput = (String) get(getJavaX(), "javaCompilerOutput"); //fail("Compile Error. " + cleanJavaCompilerOutput(compilerOutput) + " " + e); compilerOutput = indentx("> ", cleanJavaCompilerOutput(compilerOutput)); if (!swic(e.getMessage(), "Java compiler returned errors.")) compilerOutput = appendWithNewLine(compilerOutput, str(e)); //printStackTrace(e); throw fail(compilerOutput, e); } compilerOutput = cleanJavaCompilerOutput("Annotation processing got disabled, since it requires a 1.6 compliant JVM"); if (nempty(compilerOutput)) { print("Compiler said: " + compilerOutput); //fail("Compile Error. " + compilerOutput); } // sanity test if (!anyFileWithExtensionInDir(classesDir, ".class")) throw fail("No classes generated"); // add sources to .jar saveTextFile(new File(classesDir, "main.java"), src); // add information about libraries to jar if (nempty(dehlibs)) saveTextFile(new File(classesDir, "libraries"), dehlibs); // add prog id to jar saveTextFile(new File(classesDir, "progID"), progID); //print("Zipping: " + classesDir.getAbsolutePath() + " to " + jar.getAbsolutePath()); dir2zip_recurse_verbose = false; int n = dir2zip_recurse(classesDir, jar); // cache on success only //print("Files zipped: " + n); return jar; } finally { if (isInRAMDisk(classesDir)) deleteDirectory(classesDir); } } // will create the file or update its last modified timestamp static void touchFile(File file) { try { closeRandomAccessFile(newRandomAccessFile(mkdirsForFile(file), "rw")); } catch (Exception __e) { throw rethrow(__e); } } static void assertTrue(Object o) { if (!(eq(o, true) /*|| isTrue(pcallF(o))*/)) throw fail(str(o)); } static boolean assertTrue(String msg, boolean b) { if (!b) throw fail(msg); return b; } static boolean assertTrue(boolean b) { if (!b) throw fail("oops"); return b; } static boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static File actualUserDir() { return new File(actualUserHome()); } static File actualUserDir(String path) { return new File(actualUserHome(), path); } static boolean fileExists(String path) { return path != null && new File(path).exists(); } static boolean fileExists(File f) { return f != null && f.exists(); } static File userDir() { return new File(userHome()); } static File userDir(String path) { return new File(userHome(), path); } static String getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } static String substring(String s, int x) { return substring(s, x, strL(s)); } static String substring(String s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; if (x >= s.length()) return ""; if (y < x) y = x; if (y > s.length()) y = s.length(); return s.substring(x, y); } static String substring(String s, IntRange r) { return r == null ? null : substring(s, r.start, r.end); } static TreeSet ciSet() { return caseInsensitiveSet(); } static A getFuture(Future f) { try { return f == null ? null : f.get(); } catch (Exception __e) { throw rethrow(__e); } } static NowFuture nowFuture(A a) { return new NowFuture(a); } static long sysNow() { ping(); return System.nanoTime()/1000000; } static void vmKeepWithProgramMD5_get(String varName) { String struct = (String) (callOpt(javax(), "vmKeep_get", programID(), md5OfMyJavaSource(), varName)); if (struct != null) setOpt(mc(), varName, unstructure(struct)); } static volatile PersistableThrowable _handleException_lastException; static List _handleException_onException = synchroList(ll("printStackTrace2")); static void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) return; for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { printStackTrace2(e3); // not using pcall here - it could lead to endless loops } } static volatile int numberOfCores_value; static int numberOfCores() { if (numberOfCores_value == 0) numberOfCores_value = Runtime.getRuntime().availableProcessors(); return numberOfCores_value; } static A or(A a, A b) { return a != null ? a : b; } // this syntax should be removed... static Object getThreadLocal(Object o, String name) { ThreadLocal t = (ThreadLocal) (getOpt(o, name)); return t != null ? t.get() : null; } static A getThreadLocal(ThreadLocal tl) { return tl == null ? null : tl.get(); } static A getThreadLocal(ThreadLocal tl, A defaultValue) { return or(getThreadLocal(tl), defaultValue); } static Object getOpt(Object o, String field) { return getOpt_cached(o, field); } static Object getOpt(String field, Object o) { return getOpt_cached(o, field); } static Object getOpt_raw(Object o, String field) { try { Field f = getOpt_findField(o.getClass(), field); if (f == null) return null; makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } // access of static fields is not yet optimized static Object getOpt(Class c, String field) { try { if (c == null) return null; Field f = getOpt_findStaticField(c, field); if (f == null) return null; makeAccessible(f); return f.get(null); } catch (Exception __e) { throw rethrow(__e); } } static Field getOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Class javax() { return getJavaX(); } static ThreadLocal print_byThread() { synchronized(print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } // f can return false to suppress regular printing // call print_raw within f to actually print something static AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static Map> callF_cache = newDangerousWeakHashMap(); static A callF(F0 f) { return f == null ? null : f.get(); } static B callF(F1 f, A a) { return f == null ? null : f.get(a); } static A callF(IF0 f) { return f == null ? null : f.get(); } static B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static C callF(F2 f, A a, B b) { return f == null ? null : f.get(a, b); } static C callF(IF2 f, A a, B b) { return f == null ? null : f.get(a, b); } static void callF(VF1 f, A a) { if (f != null) f.get(a); } static Object callF(Object f, Object... args) { try { if (f instanceof String) return callMC((String) f, args); if (f instanceof Runnable) { ((Runnable) f).run(); return null; } if (f == null) return null; Class c = f.getClass(); ArrayList methods; synchronized(callF_cache) { methods = callF_cache.get(c); if (methods == null) methods = callF_makeCache(c); } int n = l(methods); if (n == 0) { throw fail("No get method in " + getClassName(c)); } if (n == 1) return invokeMethod(methods.get(0), f, args); for (int i = 0; i < n; i++) { Method m = methods.get(i); if (call_checkArgs(m, args, false)) return invokeMethod(m, f, args); } throw fail("No matching get method in " + getClassName(c)); } catch (Exception __e) { throw rethrow(__e); } } // used internally static ArrayList callF_makeCache(Class c) { ArrayList l = new ArrayList(); Class _c = c; do { for (Method m : _c.getDeclaredMethods()) if (m.getName().equals("get")) { makeAccessible(m); l.add(m); } if (!l.isEmpty()) break; _c = _c.getSuperclass(); } while (_c != null); callF_cache.put(c, l); return l; } static String formatInt(int i, int digits) { return padLeft(str(i), '0', digits); } static String formatInt(long l, int digits) { return padLeft(str(l), '0', digits); } // f can return false to suppress regular printing // call print_raw within f to actually print something // f preferrably is F1 static Object interceptPrintInThisThread(Object f) { Object old = print_byThread().get(); print_byThread().set(f); return old; } static void _close(AutoCloseable c) { if (c != null) try { c.close(); } catch (Throwable e) { // Some classes stupidly throw an exception on double-closing if (c instanceof javax.imageio.stream.ImageOutputStream) return; else throw rethrow(e); } } static boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } static String programID() { return getProgramID(); } static String programID(Object o) { return getProgramID(o); } static String defaultJavaXTranslatorID_value = "#759"; static String defaultJavaXTranslatorID() { return defaultJavaXTranslatorID_value; } static void setDefaultJavaXTranslatorID(String snippetID) { defaultJavaXTranslatorID_value = snippetID; } static String mainJava; static String loadMainJava() throws IOException { if (mainJava != null) return mainJava; return loadTextFile("input/main.java", ""); } static int identityHashCode(Object o) { return System.identityHashCode(o); } static HashSet cloneHashSet(Collection set) { if (set == null) return new HashSet(); synchronized(collectionMutex(set)) { HashSet < A > s = new HashSet(l(set)); s.addAll(set); return s; } } static Set tok_mapLikeFunctions_set = asHashSet( splitAtSpace("map mapI mapLL filter concatMap pairMap antiFilter map_pcall mapPairB_pcall callFVerbose call_verbose map_pcall_notNull mapToCISet mapToHashSet mapVoid lazilyMap sortedByCalculatedField repF rcurry")); static Set tok_mapLikeFunctions() { return tok_mapLikeFunctions_set; } static Set tok_mapMethodLikeFunctions_set = asHashSet( splitAtSpace("mapMethod uniquifyByField indexByField collect")); static Set tok_mapMethodLikeFunctions() { return tok_mapMethodLikeFunctions_set; } static boolean hasCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, tokens) >= 0; } static List singlePlusList(A a, Collection l) { return itemPlusList(a, l); } static Object first(Object list) { return first((Iterable) list); } static A first(List list) { return empty(list) ? null : list.get(0); } static A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } static A first(IterableIterator i) { return first((Iterator) i); } static A first(Iterator i) { return i == null || !i.hasNext() ? null : i.next(); } static A first(Iterable i) { if (i == null) return null; Iterator it = i.iterator(); return it.hasNext() ? it.next() : null; } static Character first(String s) { return empty(s) ? null : s.charAt(0); } static A first(Pair p) { return p == null ? null : p.a; } static String[] dropFirst(int n, String[] a) { return drop(n, a); } static String[] dropFirst(String[] a) { return drop(1, a); } static Object[] dropFirst(Object[] a) { return drop(1, a); } static List dropFirst(List l) { return dropFirst(1, l); } static List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); } static List dropFirst(Iterable i) { return dropFirst(toList(i)); } static List dropFirst(int n, List l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static List dropFirst(List l, int n) { return dropFirst(n, l); } static String dropFirst(int n, String s) { return substring(s, n); } static String dropFirst(String s, int n) { return substring(s, n); } static String dropFirst(String s) { return substring(s, 1); } static void replaceTokens_reTok(List tok, int i, int j, String s) { replaceTokens(tok, i, j, s); reTok(tok, i, j); } static String unnull(String s) { return s == null ? "" : s; } static Collection unnull(Collection l) { return l == null ? emptyList() : l; } static List unnull(List l) { return l == null ? emptyList() : l; } static Map unnull(Map l) { return l == null ? emptyMap() : l; } static Iterable unnull(Iterable i) { return i == null ? emptyList() : i; } static A[] unnull(A[] a) { return a == null ? (A[]) new Object[0] : a; } static BitSet unnull(BitSet b) { return b == null ? new BitSet() : b; } //ifclass Symbol static Pair unnull(Pair p) { return p != null ? p : new Pair(null, null); } static List tok_moveImportsUp(List tok) { StringBuilder buf = new StringBuilder(); //print("tok_moveImportsUp n=" + l(tok)); //print("Source begins: " + quote(shorten(join(tok), 200))); // scan imports on top boolean change = false; int i; Set have = new HashSet(); for (i = 1; i < l(tok); i += 2) if (eq(tok.get(i), "import")) { int j = indexOf(tok, i+2, ";"); if (j < 0) break; String s = joinSubList(tok, i, j+1); have.add(s); i = j; } else break; //print("tok_moveImportsUp have " + l(have) + " after " + i); // scan imports in text for (; i < l(tok); i += 2) if (eq(tok.get(i), "import")) { int j = indexOf(tok, i+2, ";"); if (j < 0) continue; // huh? String s = joinSubList(tok, i, j+1); //print("Found import at " + i + ": " + s); if (!have.contains(s)) { buf.append(s).append("\n"); have.add(s); } replaceTokens/*_reTok*/(tok, i, j+1, ""); change = true; i -= 2; } if (nempty(buf)) { if (l(tok) == 1) addAll(tok, "", ""); tok.set(1, str(buf)+"\n"+tok.get(1)); change = true; //reTok(tok, 1, 2); } if (change) reTok(tok); return tok; } static boolean tok_hasTranslators(List tok) { int n = l(tok)-2; for (int i = 1; i < n; i += 2) if (tok.get(i).equals("!") && isInteger(tok.get(i+2))) return true; return false; } static String defaultTranslate(String text) { Class javax = getJavaX(); File x = makeTempDir(); saveTextFile(new File(x, "main.java"), text); List libraries_out = new ArrayList(); File y = (File) call(javax, "defaultTranslate", x, libraries_out); if (y == null) return null; return loadTextFile(new File(y, "main.java")); } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first(((Collection) strings))); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } static String join(Iterable strings) { return join("", strings); } static String join(Iterable strings, String glue) { return join(glue, strings); } public static String join(String[] strings) { return join("", strings); } static String join(String glue, Pair p) { return p == null ? "" : str(p.a) + glue + str(p.b); } static void tok_metaTransformNow(List tok) { int i = -1; while ((i = jfind(tok, i+1, "meta-transformNow {")) >= 0) { int iOpening = indexOf(tok, i, "{"); int iClosing = findEndOfBracketPart(tok, iOpening)-1; String code = joinSubList(tok, iOpening+2, iClosing-1); clearTokens_reTok(tok, i, iClosing+1); tok_runMetaTransformer(tok, code); } } static void tok_compactModules(List tok) { if (jreplace_multi(tok, ll("cmodule", "compact module"), "module")) { print("compact modules"); includeInMainLoaded(tok, "!include once #1020738\n"); } } static void tok_selfType(List tok) { int i; mainLoop: while ((i = jfind(tok, "selfType ")) >= 0) { // Now find class name by going backwards. int j = i, level = 1; while (j > 0 && level > 0) { String t = tok.get(j); if (t.equals("}")) ++level; if (t.equals("{")) --level; j -= 2; } // search for class name while (j > 0) { String t = tok.get(j); if (t.equals("class")) { String className = tok.get(j+2); tok.set(i, className); continue mainLoop; } j -= 2; } tok.set(i, "Object"); // avoid endless loop } } // extra commas - e.g. ll(1, 2,) => ll(1, 2) static void tok_dropExtraCommas(List tok) { jreplace(tok, ",)", ")"); } static void tok_delegateTo(List tok) { jreplace(tok, "delegate to .", "replace $2 with $4.$2."); jreplace(tok, "delegate to ().", "replace $2 with $4().$2."); // TODO: general expressions in "to" clause } static void tok_replaceWith(List tok) { int i; while ((i = jfind(tok, "replace with")) >= 0) { String token = tok.get(i+2); int repStart = i+6; int repEnd = repStart; // Find . with space or line break or EOF afterwards while (!(eqGet(tok, repEnd, ".") && (nempty(get(tok, repEnd+1)) || repEnd == l(tok)-2))) repEnd += 2; //int repEnd = smartIndexOf(tok, repStart, "."); String replacement = joinSubList(tok, repStart, repEnd-1); clearTokens(tok, i, repEnd+1); print("Replacing " + token + " with " + replacement + "."); int end = findEndOfBlock(tok, repEnd)-1; for (int j = repEnd+2; j < end; j += 2) if (eq(tok.get(j), token)) tok.set(j, replacement); reTok(tok, i, end); } } static String jreplace(String s, String in, String out) { return jreplace(s, in, out, null); } static String jreplace(String s, String in, String out, Object condition) { List tok = javaTok(s); return jreplace(tok, in, out, condition) ? join(tok) : s; } // leaves tok properly tokenized // returns true iff anything was replaced static boolean jreplace(List tok, String in, String out) { return jreplace(tok, in, out, false, true, null); } static boolean jreplace(List tok, String in, String out, Object condition) { return jreplace(tok, in, out, false, true, condition); } static boolean jreplace(List tok, String in, String out, IF2, Integer, Boolean> condition) { return jreplace(tok, in, out, (Object) condition); } static boolean jreplace(List tok, String in, String out, boolean ignoreCase, boolean reTok, Object condition) { String[] toks = javaTokForJFind_array(in); int lTokin = toks.length*2+1; boolean anyChange = false; int i = -1; for (int n = 0; n < 10000; n++) { // TODO: don't need this check anymore i = findCodeTokens(tok, i+1, ignoreCase, toks, condition); if (i < 0) return anyChange; List subList = tok.subList(i-1, i+lTokin-1); // N to N String expansion = jreplaceExpandRefs(out, subList); int end = i+lTokin-2; clearAllTokens(tok, i, end); // C to C tok.set(i, expansion); if (reTok) // would this ever be false?? reTok(tok, i, end); i = end; anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static boolean jreplace_debug = false; static void tok_collectMetaPostBlocks(List tok, List postProcessBlocks_out) { int i = -1; while ((i = jfind(tok, i+1, "meta-postProcess {")) >= 0) { int iOpening = indexOf(tok, i, "{"); int iClosing = findEndOfBracketPart(tok, iOpening)-1; add(postProcessBlocks_out, joinSubList(tok, iOpening+2, iClosing-1)); clearTokens_reTok(tok, i, iClosing+1); } } static void tok_collectTransformers(List tok, List out) { int i = -1; while ((i = jfind(tok, i+1, "meta-transform {")) >= 0) { int iOpening = indexOf(tok, i, "{"); int iClosing = findEndOfBracketPart(tok, iOpening)-1; add(out, joinSubList(tok, iOpening+2, iClosing-1)); clearTokens_reTok(tok, i, iClosing+1); } } static long now_virtualTime; static long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } static boolean tok_sameTest(List tok, String text) { int iTok = 0, iText = 0, nTok = l(tok), nText = l(text); while (iTok < nTok) { String t = tok.get(iTok++); int n = l(t); if (n == 0) continue; if (!t.regionMatches(0, text, iText, n)) return false; iText += n; } return iText == nText; } static String jreplace1(String s, String in, String out) { return jreplace1(s, in, out, null); } static String jreplace1(String s, String in, String out, Object condition) { List tok = javaTok(s); return jreplace1(tok, in, out, condition) ? join(tok) : s; } // leaves tok properly tokenized // returns true iff anything was replaced static boolean jreplace1(List tok, String in, String out) { return jreplace1(tok, in, out, false, true, null); } static boolean jreplace1(List tok, String in, String out, Object condition) { return jreplace1(tok, in, out, false, true, condition); } static boolean jreplace1(List tok, String in, String out, boolean ignoreCase, boolean reTok, Object condition) { List tokin = javaTok(in); jfind_preprocess(tokin); boolean anyChange = false; int i = 1; while ((i = findCodeTokens(tok, i, ignoreCase, toStringArray(codeTokensOnly(tokin)), condition)) >= 0) { List subList = tok.subList(i-1, i+l(tokin)-1); // N to N String expansion = jreplaceExpandRefs(out, subList); int end = i+l(tokin)-2; clearAllTokens(tok, i, end); // C to C tok.set(i, expansion); if (reTok) // would this ever be false?? reTok(tok, i, end); i = end; anyChange = true; } return anyChange; } static boolean jreplace1_debug = false; static IndexedList2 indexedList2(List l) { return l instanceof IndexedList2 ? ((IndexedList2) l) : new IndexedList2(l); } // out: func(L tok, int cIndex) -> S // condition: func(L tok, int nIndex) -> S [yeah it's inconsistent] static String jreplace_dyn(String s, String in, Object out) { return jreplace_dyn(s, in, out, null); } static String jreplace_dyn(String s, String in, Object out, Object condition) { List tok = javaTok(s); jreplace_dyn(tok, in, out, condition); return join(tok); } // leaves tok properly tokenized // returns true iff anything was replaced static boolean jreplace_dyn(List tok, String in, Object out) { return jreplace_dyn(tok, in, out, false, true, null); } static boolean jreplace_dyn(List tok, String in, Object out, Object condition) { return jreplace_dyn(tok, in, out, false, true, condition); } static boolean jreplace_dyn(List tok, String in, Object out, boolean ignoreCase, boolean reTok, Object condition) { List tokin = javaTok(in); jfind_preprocess(tokin); String[] toks = toStringArray(codeTokensOnly(tokin)); boolean anyChange = false; for (int n = 0; n < 10000; n++) { int i = findCodeTokens(tok, 1, ignoreCase, toks, condition); if (i < 0) return anyChange; String expansion = (String) (callF(out, tok, i)); int end = i+l(tokin)-2; clearAllTokens(tok, i, end); // C to C tok.set(i, expansion); if (reTok) // would this ever be false?? reTok(tok, i, end); anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static String stringToLegalIdentifier(String s) { StringBuilder buf = new StringBuilder(); s = dropTrailingSquareBracketStuff(s); for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (empty(buf) ? Character.isJavaIdentifierStart(c) : Character.isJavaIdentifierPart(c)) buf.append(c); } if (empty(buf)) throw fail("Can't convert to legal identifier: " + s); return str(buf); } static String getSnippetTitle(String id) { try { if (id == null) return null; if (!isSnippetID(id)) return "?"; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetTitle(id); if (isLocalSnippetID(id)) return localSnippetTitle(id); long parsedID = parseSnippetID(id); String url; if (isImageServerSnippet(parsedID)) url = imageServerURL() + "title/" + parsedID + muricaCredentialsQuery(); else if (isGeneralFileServerSnippet(parsedID)) url = "http://butter.botcompany.de:8080/files/name/" + parsedID; else url = tb_mainServer() + "/tb-int/getfield.php?id=" + parsedID + "&field=title" + standardCredentials_noCookies(); String title = trim(loadPageSilently(url)); if (title != null) try { saveTextFileIfChanged(snippetTitle_cacheFile(id), title); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return or(title, "?"); } catch (Exception __e) { throw rethrow(__e); } } static String getSnippetTitle(long id) { return getSnippetTitle(fsI(id)); } static void tok_overridableFunctionDefs(List tok, Set overriableFunctions_out) { int i; while ((i = jfind(tok, "static overridable ")) >= 0) { int bracket = indexOf(tok, "(", i); int codeStart = indexOf(tok, "{", bracket); String fName = assertIdentifier(tok.get(bracket-2)); String type = joinSubList(tok, i+4, bracket-3); String boxedType = tok_toNonPrimitiveTypes(type); String args = joinWithComma(map("tok_lastIdentifier",tok_parseArgsDeclList(subList(tok, i)))); String castIt = eq(type, "Object") ? "" : ("(" + (type) + ")"); replaceTokens(tok, i, bracket-1, ("static Object _override_" + (fName) + ";\n") + ("static " + (type) + " " + (fName))); tokAppend(tok, codeStart, (" if (_override_" + (fName) + " != null) return " + (castIt) + " callF(_override_" + (fName) + ", " + (args) + ");\n")); reTok(tok, i, codeStart+1); addToCollection(overriableFunctions_out, fName); } } static String sfu(Object o) { return structureForUser(o); } static boolean containsOneOfIC(Collection l, String... x) { Set set = asCISet(x); for (String a : unnull(l)) if (set.contains(a)) return true; return false; } static boolean containsIC(Collection l, String s) { return containsIgnoreCase(l, s); } static boolean containsIC(String[] l, String s) { return containsIgnoreCase(l, s); } static boolean containsIC(String s, char c) { return containsIgnoreCase(s, c); } static boolean containsIC(String a, String b) { return containsIgnoreCase(a, b); } static String javaParser_makeAllPublic(String src, Object... __) { CompilationUnit cu = javaParseCompilationUnit(src); PrettyPrinterConfiguration ppconf = new PrettyPrinterConfiguration(); ppconf.setIndent(" "); ppconf.setPrintComments(false); javaParser_makeAllPublic_Visitor visitor = new javaParser_makeAllPublic_Visitor(); visitor.notTopLevelClassDecl = boolOptPar("notTopLevelClassDecl",__); visitor.visit(cu, null); return cu.toString(ppconf); } static class javaParser_makeAllPublic_Visitor extends VoidVisitorAdapter { boolean notTopLevelClassDecl = false; // don't make top-level class declaration public void makePublic(Set modifiers) { modifiers.remove(com.github.javaparser.ast.Modifier.PRIVATE); modifiers.remove(com.github.javaparser.ast.Modifier.PROTECTED); modifiers.add(com.github.javaparser.ast.Modifier.PUBLIC); } public void visit(ClassOrInterfaceDeclaration n, Object arg) { Node parent = n.getParentNode().get(); if (!(parent instanceof LocalClassDeclarationStmt || parent instanceof CompilationUnit && neq(n.getName().asString(), "main"))) if (notTopLevelClassDecl) notTopLevelClassDecl = false; else makePublic(n.getModifiers()); super.visit(n, arg); } public void visit(FieldDeclaration n, Object arg) { makePublic(n.getModifiers()); super.visit(n, arg); } public void visit(ConstructorDeclaration n, Object arg) { Node parent = n.getParentNode().get(); if (!(parent instanceof EnumDeclaration)) makePublic(n.getModifiers()); super.visit(n, arg); } public void visit(MethodDeclaration n, Object arg) { EnumSet m = n.getModifiers(); //print("Method found: " + n.getName() + " with modifiers: " + m + ", position: " + n.getRange()->begin); if (m.contains(com.github.javaparser.ast.Modifier.PRIVATE) && !m.contains(com.github.javaparser.ast.Modifier.STATIC)) m.add(com.github.javaparser.ast.Modifier.FINAL); makePublic(m); super.visit(n, arg); } } static String javaParser_makeAllPublic_keepComments(String src) { //CompilationUnit cu = javaParseCompilationUnit(src); CompilationUnit cu = JavaParser.parse(src); PrettyPrinterConfiguration ppconf = new PrettyPrinterConfiguration(); ppconf.setIndent(" "); new javaParser_makeAllPublic_Visitor().visit(cu, null); return cu.toString(ppconf); } static String javaParser_reparse_keepComments(String src) { CompilationUnit cu = JavaParser.parse(src); PrettyPrinterConfiguration ppconf = new PrettyPrinterConfiguration(); ppconf.setIndent(" "); return cu.toString(ppconf); } static void extractAndPrintJavaParseError(String src, Throwable e) { print(); String msg = firstLine(innerMessage(e)); print(msg); int line = parseIntOpt(regexpFirstGroupIC("line (\\d+)", msg)); print(); if (line != 0) { List lines = lines(src); for (int i = max(1, line-5); i <= min(l(lines), line+5); i++) print((i == line ? "* " : " ") + "LINE " + i + ": " + lines.get(i-1)); } print(); } static File javaxCachesDir_dir; // can be set to work on different base dir static File javaxCachesDir() { return javaxCachesDir_dir != null ? javaxCachesDir_dir : new File(userHome(), "JavaX-Caches"); } static File javaxCachesDir(String sub) { return newFile(javaxCachesDir(), sub); } static void saveTextFileVerbose(File f, String text) { boolean exists = f.exists(); saveTextFile(f, text); print((exists ? "Created" : "Updated") + " file " + f2s(f) + " (" + f.length() + " bytes)"); } static void tokPrepend(List tok, int i, String s) { tok.set(i, s + tok.get(i)); } static List reTok(List tok) { replaceCollection(tok, javaTok(tok)); return tok; } static List reTok(List tok, int i) { return reTok(tok, i, i+1); } static List reTok(List tok, int i, int j) { // extend i to an "N" token // and j to "C" (so j-1 is an "N" token) i = max(i & ~1, 0); j = min(l(tok), j | 1); if (i >= j) return tok; List t = javaTok(joinSubList(tok, i, j)); replaceListPart(tok, i, j, t); // fallback to safety // reTok(tok); return tok; } static List reTok(List tok, IntRange r) { if (r != null) reTok(tok, r.start, r.end); return tok; } static boolean nempty(Collection c) { return !empty(c); } static boolean nempty(CharSequence s) { return !empty(s); } static boolean nempty(Object[] o) { return !empty(o); } static boolean nempty(byte[] o) { return !empty(o); } static boolean nempty(int[] o) { return !empty(o); } static boolean nempty(Map m) { return !empty(m); } static boolean nempty(Iterator i) { return i != null && i.hasNext(); } static boolean nempty(Object o) { return !empty(o); } static String concatMap_strings(Object f, Iterable l) { return join((List) map(f, l)); } static String concatMap_strings(Object f, Object[] l) { return join((List) map(f, l)); } static String concatMap_strings(Iterable l, Object f) { return concatMap_strings(f, l); } static String f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static String f2s(String s) { return f2s(newFile(s)); } static String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static File saveProgramTextFile(String name, String contents) { return saveTextFile(getProgramFile(name), contents); } static File saveProgramTextFile(String progID, String name, String contents) { return saveTextFile(getProgramFile(progID, name), contents); } static void splitJavaFiles(List tok) { try { splitJavaFiles(tok, newFile("output")); } catch (Exception __e) { throw rethrow(__e); } } static void splitJavaFiles(List tok, File outDir) { try { List indexes = jfindAll(tok, "package"); if (empty(indexes) || indexes.get(0) != 1) indexes.add(0, 1); for (int i = 0; i < l(indexes); i++) { int from = indexes.get(i); int to = i+1 < l(indexes) ? indexes.get(i+1) : l(tok); List subtok = cncSubList(tok, from, to); String src = join(subtok); //print(shorten(src, 80)); String pack = tok_packageName(subtok); print("Package: " + quote(pack)); List> classes = allClasses(subtok); /*for (L c : classes) { //print(" Class: " + shorten(join(c), 80)); print(" Class: " + quote(getClassDeclarationName(c))); }*/ if (empty(classes)) print("No classes?? " + quote(src)); else { String className = getNameOfPublicClass(subtok); if (className == null) className = getNameOfAnyClass(subtok); String fileName = addSlash(pack.replace('.', '/')) + className + ".java"; print("File name: " + fileName); saveTextFile(newFile(outDir, fileName), join(subtok)); } print(); } } catch (Exception __e) { throw rethrow(__e); } } static void saveMainJava(String s) throws IOException { if (mainJava != null) mainJava = s; else saveTextFile("output/main.java", s); } static void saveMainJava(List tok) throws IOException { saveMainJava(join(tok)); } // process scope x. ... end scope blocks static void tok_scopes(List tok, Object... __) { if (!tok.contains("scope")) return; boolean autoCloseScopes = boolPar("autoCloseScopes",__); int i; while ((i = rjfind(tok, "scope .")) >= 0) { String scopeName = tok.get(i+2); int j = jfind(tok, i+6, "end scope"); if (j < 0) if (autoCloseScopes) j = l(tok); else throw fail("Scope " + scopeName + " opened but not closed"); else clearTokens(tok, j, j+3); HashSet names = new HashSet(); HashSet functions = new HashSet(); clearTokens(tok, i, i+5); List subTok = subList(tok, i+5, j); // auto-make #lock variable if (jfind(subTok, "lock #lock") >= 0 && jfind(subTok, "Lock #lock") < 0) tok.set(i, "static Lock " + scopeName + "_lock = lock();\n"); // first pass (find # declarations) for (int k = i+6; k < j-2; k += 2) { String t = get(tok, k+2); if (eqGet(tok, k, "#") && isIdentifier(t)) { names.add(t); if (eqGetOneOf(tok, k+4, "(", "{", "<", "extends", "implements", ">")) // cover class declarations too functions.add(t); replaceTokens(tok, k, k+3, scopeName + "_" + t); } } // second pass (references to scoped variables) for (int k = i+6; k < j; k += 2) { String t = get(tok, k); if (isIdentifier(t)) { if (names.contains(t)) { if (eqGet(tok, k-2, ".")) {} else if (eqGet(tok, k+2, "(") && !functions.contains(t)) {} // avoid lock ... and map ... else if (eqOneOf(t, "lock", "map") && isIdentifier(get(tok, k+2))) {} else tok.set(k, scopeName + "_" + t); } else if (eq(t, "__scope")) tok.set(k, quote(scopeName)); } } reTok(tok, i, j+1); } } static boolean tok_recordDecls_autoWithToList = true; static void tok_recordDecls(List tok) { int i; boolean re = false; jreplace(tok, "record {", "record $2() {"); jreplace(tok, "record implements", "record $2() implements"); while ((i = jfind_any(tok, "record (", "record <")) >= 0) { int argsFrom = smartIndexOf(tok, i, "(")+2; int argsTo = findCodeTokens(tok, argsFrom, false, ")"); int idx = findCodeTokens(tok, argsTo, false, "{"); int j = findEndOfBracketPart(tok, idx); String name = tok.get(i+2); boolean noEq = eq(get(tok, i-2), "noeq"); if (noEq) tok.set(i-2, ""); boolean noToString = eq(get(tok, i-2), "noToString"); if (noToString) tok.set(i-2, ""); boolean withToList = eq(get(tok, i-2), "withToList"); if (withToList) tok.set(i-2, ""); withToList = withToList || tok_recordDecls_autoWithToList; StringBuilder buf = new StringBuilder(); List tArgs = subList(tok, argsFrom-1, argsTo); List> args = tok_typesAndNamesOfParams(tArgs, "typelessMeansObject" , true); List contents = subList(tok, idx+1, j); for (Pair p : args) buf.append("\n " + jreplace(p.a, "...", "[]") + " " + p.b + ";"); if (nempty(args)) buf.append("\n *() {}"); buf.append("\n *(" + joinWithComma(map(args, new F1, String>() { String get(Pair p) { try { return dropPrefix("new ", p.a) + " *" + p.b; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "dropPrefix(\"new \", p.a) + \" *\" + p.b"; }})) + ") {}"); if (!noToString && !(jfind(contents, "toString {") >= 0 || jfind(contents, "toString()") >= 0)) buf.append("\n toString { ret " + quote(name + "(") + " + " + join(" + \", \" + ", secondOfPairs(args)) + " + \")\"; }"); if (!noEq) { //buf.append("\n [stdEq]"); buf.append(tok_genEqualsAndHashCode(name, args)); } if (withToList) buf.append(tok_genRecordFieldsToList(args)); tok.set(idx, (!withToList ? "" : (contains(subList(tok, argsTo, idx), "implements") ? "," : "implements") + " IFieldsToList ") + "{" + buf); tok.set(i, "class"); clearTokens(tok, argsFrom-2, argsTo+1); reTok(tok, i, idx+1); tok_addFieldOrder(tok, i); re = true; } if (re) reTok(tok); } static void tok_singleQuoteIdentifiersToStringConstants(List tok) { for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (isSingleQuoteIdentifier(t)) tok.set(i, quote(substring(t, 1))); } } static void tok_listComprehensions(List tok) { if (!tok.contains("[")) return; for (int i = 1; i < l(tok); i += 2) { { if (!(eq(tok.get(i), "["))) continue; } int iOp = indexOfAny(tok, i+2, "?", ":", "in", "[", "]"); if (iOp < 0) return; if (!eqOneOf(tok.get(iOp), ":", "in")) continue; // not a list comprehension Map bracketMap = getBracketMap(tok); // XXX - optimize String type = joinSubList(tok, i+2, iOp-3), id = tok.get(iOp-2); int j = scanOverExpression(tok, bracketMap, iOp+2, "|"); String exp = join(tok.subList(iOp+2, j)); j += 2; int k = scanOverExpression(tok, bracketMap, j, "]"); String where = join(tok.subList(j, k)); ++k; String code = "filter(" + exp + ", func(" + type + " " + id + ") -> Bool { " + where + " })"; replaceTokens(tok, i, k, code); reTok(tok, i, k); } } static void tok_for_single(List tok) { int i = -1; while ((i = jfind(tok, i+1, "for single (")) >= 0) { int iColon = indexOf(tok, ":", i); int iClosing = findEndOfBracketPart(tok, iColon)-1; tok.set(iColon, ": singletonUnlessNull("); tok.set(iClosing, "))"); clearTokens(tok, i+2, i+4); reTok(tok, i, iClosing+1); } } static void tok_for_unpair(List tok) { jreplace(tok, "for (unpair , :", "for (unpair $4 $5, $4 $7 :"); jreplace(tok, "for ( , : unpair", "for (unpair $3 $4, $3 $6 :"); int i = -1; while ((i = jfind(tok, i+1, "for (unpair , :")) >= 0) { String type1 = tok.get(i+6), var1 = tok.get(i+8); String type2 = tok.get(i+12), var2 = tok.get(i+14); int iColon = indexOf(tok, ":", i); int iClosing = findEndOfBracketPart(tok, iColon)-1; if (!eqGet(tok, iClosing+2, "{")) throw fail("Use { with for unpair"); String pairVar = makeVar(); replaceTokens(tok, i+4, iColon-1, tok_toNonPrimitiveTypes("Pair<" + type1 + ", " + type2 + ">") + " " + pairVar); tok.set(iClosing+2, "{ " + type1 + " " + var1 + " = pairA(" + pairVar + "); " + type2 + " " + var2 + " = pairB(" + pairVar + "); "); reTok(tok, i, iClosing+3); } } static boolean tok_doubleFor_v2_debug = false; static void tok_doubleFor_v2(List tok) { for (int i : reversed(indexesOf(tok, "for"))) { if (neq(get(tok, i+2), "(")) continue; int argsFrom = i+4; // move loop label to proper place if (eqGet(tok, i-2, ":") && isIdentifier(get(tok, i-4))) i -= 4; int iColon = indexOfAny(tok, argsFrom, ":", ")"); if (neq(get(tok, iColon), ":")) continue; if (tok_doubleFor_v2_debug) print("have colon"); tok_typesAndNamesOfParams_keepModifiers.set(true); List> args = tok_typesAndNamesOfParams(subList(tok, argsFrom-1, iColon-1)); if (l(args) != 2) continue; // simple for or a three-argument for (out of this world!) // S a, b => S a, S b if (eq(second(args).a, "?")) second(args).a = first(args).a; if (tok_doubleFor_v2_debug) print("have 2 args: " + sfu(args)); int iClosing = tok_findEndOfForExpression(tok, iColon+2); if (iClosing < 0) continue; if (tok_doubleFor_v2_debug) print("have closing"); String exp = trimJoinSubList(tok, iColon+2, iClosing-1); if (tok_doubleFor_v2_debug) print("Expression: " + exp); int iCurly = iClosing+2; tok_statementToBlock(tok, iCurly); int iCurlyEnd = tok_findEndOfStatement(tok, iCurly)-1; if (iCurlyEnd < 0) continue; if (tok_doubleFor_v2_debug) print("have curly end"); // complicated expression? evaluate to variable first if (!isIdentifier(exp)) { String expVar = makeVar(); String mapType = tok_toNonPrimitiveTypes("Map<" + first(args).a + ", " + second(args).a + ">"); tokPrepend(tok, i, "{ final " + mapType + " " + expVar + " = " + exp + "; "); tokAppend(tok, iCurlyEnd, "}"); replaceTokens(tok, iColon+2, iClosing-1, expVar); exp = expVar; } tokAppend(tok, iColon, " keys("); tokPrepend(tok, iClosing, ")"); replaceTokens(tok, argsFrom, iColon-1, joinPairWithSpace(first(args))); tokAppend(tok, iCurly, " " + joinPairWithSpace(second(args)) + " = " + exp + ".get(" + first(args).b + "); "); reTok(tok, i, iCurlyEnd+1); } } static void tok_forUnnull(List tok) { jreplace(tok, "fOr (", "for unnull ("); int i = -1; while ((i = jfind(tok, i+1, "for unnull (")) >= 0) { int argsFrom = i+4; int iColon = indexOf(tok, i, ":"); int iClosing = tok_findEndOfForExpression(tok, iColon+2); clearTokens(tok, i+2, i+4); tokPrepend(tok, iColon+2, "unnull("); tokPrepend(tok, iClosing, ")"); reTok(tok, i+2, iClosing+1); } } static void tok_ifCast(List tok) { int i; while ((i = jfind_check("cast",tok, "if ( cast ")) >= 0) { int iClosing = indexOf(tok, i, ")"); String var = tok.get(i+4), type = joinSubList(tok, i+8, iClosing-1); int start = iClosing+2, end = findEndOfStatement(tok, start); tok.set(i+6, "instanceof"); // replace "var" with "((Type) var)" in enclosed block // unless it's another cast expression for (int j = start; j < end; j += 2) if (eq(tok.get(j), var) && neqGet(tok, j-2, ".") && neqGet(tok, j+2, "cast")) tok.set(j, "((" + type + ") " + var + ")"); reTok(tok, i+6, end); } } // # 123 => "#123" static void tok_directSnippetRefs(List tok) { int i = -1; while ((i = jfind(tok, i+1, "#", new TokCondition() { boolean get(final List tok, final int i) { return !eqOneOf(_get(tok, i-1), "include", "once"); }})) >= 0) { String id = tok.get(i+2); clearTokens(tok, i+1, i+3); tok.set(i, quote("#" + id)); reTok(tok, i, i+3); } } // keyword can comprise multiple tokens now (like "p-awt"} static List replaceKeywordBlock(List tok, String keyword, String beg, String end) { return replaceKeywordBlock(tok, keyword, beg, end, false, null); } static List replaceKeywordBlock(List tok, String keyword, String beg, String end, Object cond) { return replaceKeywordBlock(tok, keyword, beg, end, false, cond); } static List replaceKeywordBlock(List tok, String keyword, String beg, String end, boolean debug, Object cond) { for (int n = 0; n < 1000; n++) { int i = jfind(tok, keyword + " {", cond); if (i < 0) break; int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); if (debug) { print(toUpper(keyword) + " BEFORE\n" + join(subList(tok, i, j))); print(" THEN " + join(subList(tok, j, j+10))); } //assertEquals("}", tok.get(j-1)); tok.set(j-1, end); replaceTokens(tok, i, idx+1, beg); reTok(tok, i, j); if (debug) print(toUpper(keyword) + "\n" + join(subList(tok, i, j)) + "\n"); } return tok; } // finds " {" // func: tok, C token index of keyword -> S[] {beg, end} static List replaceKeywordPlusQuotedBlock(List tok, String keyword, Object func) { for (int i = 0; i < 1000; i++) { int idx = jfind(tok, keyword + " {"); if (idx < 0) break; int j = findEndOfBracketPart(tok, idx+4); String[] be = (String[]) callF(func, tok, idx); tok.set(idx, be[0]); clearTokens(tok, idx+1, idx+5); tok.set(j-1, be[1]); reTok(tok, idx, j); } return tok; } static int jfind(String s, String in) { return jfind(javaTok(s), in); } static int jfind(List tok, String in) { return jfind(tok, 1, in); } static int jfind(List tok, int startIdx, String in) { return jfind(tok, startIdx, in, null); } static int jfind(List tok, String in, Object condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, int startIdx, String in, Object condition) { //LS tokin = jfind_preprocess(javaTok(in)); return jfind(tok, startIdx, javaTokForJFind_array(in), condition); } // assumes you preprocessed tokin static int jfind(List tok, List tokin) { return jfind(tok, 1, tokin); } static int jfind(List tok, int startIdx, List tokin) { return jfind(tok, startIdx, tokin, null); } static int jfind(List tok, int startIdx, String[] tokinC, Object condition) { return findCodeTokens(tok, startIdx, false, tokinC, condition); } static int jfind(List tok, int startIdx, List tokin, Object condition) { return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition); } static List jfind_preprocess(List tok) { for (String type : litlist("quoted", "id", "int")) replaceSublist(tok, ll("<", "", type, "", ">"), ll("<" + type + ">")); replaceSublist(tok, ll("\\", "", "*"), ll("\\*")); return tok; } // Return value is index of semicolon/curly brace+1 static int tok_findEndOfStatement(List tok, int i) { // Is it a block? if (eq(get(tok, i), "{")) return findEndOfBlock(tok, i); // It's a regular statement. int j = i; while (j < l(tok) && neq(tok.get(j), ";")) if (eqOneOf(get(tok, j), "{", "(")) j = findEndOfBracketPart(tok, j)+1; else j += 2; return j+1; } static TokCondition tokCondition_beginningOfMethodDeclaration() { return new TokCondition() { boolean get(final List tok, final int i) { return eqOneOf(_get(tok, i-1), "}", ";", "{", null); }}; } static boolean neqGet(List l, int i, Object o) { return neq(get(l, i), o); } static void tok_moduleClassDecls(List tok) { jreplace(tok, "module {", "module $2 extends DynModule {"); int i = -1; while ((i = jfind(tok, i+1, "module ")) >= 0) { int j = findEndOfBlock(tok, indexOf(tok, "{", i))-1; String name = tok.get(i+2); tok.set(i, "sclass"); tokAppend(tok, j, "\nsbool _moduleClass_" + name + " = true;"); // just a marker to quickly find module classes reTok(tok, j, j+1); } } static boolean startsWithLowerCaseOrUnderscore(String s) { return nempty(s) && (s.startsWith("_") || Character.isLowerCase(s.charAt(0))); } static boolean empty(Collection c) { return c == null || c.isEmpty(); } static boolean empty(CharSequence s) { return s == null || s.length() == 0; } static boolean empty(Map map) { return map == null || map.isEmpty(); } static boolean empty(Object[] o) { return o == null || o.length == 0; } static boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); if (o instanceof Object[]) return empty((Object[]) o); if (o instanceof byte[]) return empty((byte[]) o); if (o == null) return true; throw fail("unknown type for 'empty': " + getType(o)); } static boolean empty(Iterator i) { return i == null || !i.hasNext(); } static boolean empty(float[] a) { return a == null || a.length == 0; } static boolean empty(int[] a) { return a == null || a.length == 0; } static boolean empty(long[] a) { return a == null || a.length == 0; } static boolean empty(byte[] a) { return a == null || a.length == 0; } static boolean empty(short[] a) { return a == null || a.length == 0; } static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); } static boolean empty(File f) { return getFileSize(f) == 0; } static A _get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static Object _get(Object o, String field) { return get(o, field); } static Object _get(String field, Object o) { return get(o, field); } static A _get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static boolean eq(Object a, Object b) { return a == b || (a == null ? b == null : b != null && a.equals(b)); } static boolean isIdentifier(String s) { return isJavaIdentifier(s); } static boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } // returns index of endToken static int scanOverExpression(List tok, Map bracketMap, int i, String endToken) { while (i < l(tok)) { if (eq(endToken, tok.get(i))) return i; Integer j = bracketMap.get(i); if (j != null) i = j+1; else i++; } return i; } // map: index of opening bracket -> index of closing bracket static Map getBracketMap(List tok) { return getBracketMap(tok, getBracketMap_opening, getBracketMap_closing); } static Map getBracketMap(List tok, Collection opening, Collection closing) { return getBracketMap(tok, opening, closing, 0, l(tok)); } static Map getBracketMap(List tok, Collection opening, Collection closing, int from, int to) { TreeMap map = new TreeMap(); List stack = new ArrayList(); for (int i = from|1; i < to; i+= 2) { if (opening.contains(tok.get(i))) stack.add(i); else if (closing.contains(tok.get(i))) { if (!empty(stack)) map.put(liftLast(stack), i); } } return map; } static Set getBracketMap_opening = lithashset("{", "("); static Set getBracketMap_closing = lithashset("}", ")"); static void replaceTokens(List tok, int i, int j, String s) { clearAllTokens(subList(tok, i, j)); tok.set(i, s); } static void replaceTokens(List tok, String s) { clearAllTokens(tok); tok.set(0, s); } static int jfindOneOf(List tok, String... patterns) { for (String in : patterns) { int i = jfind(tok, in); if (i >= 0) return i; } return -1; } // debug "bla" + blubb; => { if (debug) print("bla" + blubb); } static void tok_debugStatements(List tok) { int i = -1; while ((i = jfind(tok, i+1, "debug ")) >= 0) { int j = tok_findEndOfStatement(tok, i); // index of semicolon+1 replaceTokens(tok, i, i+2, "{ if (debug) print("); tok.set(j-1, "); }"); i = j; } } static int jfind_check(String checkToken, List tok, String in) { if (tok instanceof IndexedList2 && !tok.contains(checkToken)) return -1; return jfind(tok, in); } static int jfind_check(String checkToken, List tok, String in, Object condition) { if (tok instanceof IndexedList2 && !tok.contains(checkToken)) return -1; return jfind(tok, in, condition); } static Boolean not(Boolean b) { return b == null ? null : !b; } // i must point at the (possibly imaginary) opening bracket (any of the 2 types, not type parameters) // index returned is index of closing bracket + 1 static int findEndOfBracketPart(List cnc, int i) { int j = i+2, level = 1; while (j < cnc.size()) { if (eqOneOf(cnc.get(j), "{", "(")) ++level; else if (eqOneOf(cnc.get(j), "}", ")")) --level; if (level == 0) return j+1; ++j; } return cnc.size(); } static boolean isInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; if (s.charAt(0) == '-') if (++i >= n) return false; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static int parseInt(String s) { return empty(s) ? 0 : Integer.parseInt(s); } static int parseInt(char c) { return Integer.parseInt(str(c)); } static boolean tok_doAsMethodName_strict = false; // Strict mode: // Sometimes you have to make sure to omit the space after "do" // do(...) // as opposed to // do (bla+bla).something(); while ...; << very unusual anyway // Non-strict mode: // do (bla+bla).something(); while ...; // is not possible anymore (but who does this?) // You can use spaces however you like static void tok_doAsMethodName(List tok) { if (!tok.contains("do")) return; for (int i = 1; i+2 < l(tok); i += 2) { String next = tok.get(i+2), prev = get(tok, i-2); if (tok.get(i).equals("do") && eq(next, "(") && (!tok_doAsMethodName_strict || eq(prev, ".") || empty(tok.get(i+1)))) tok.set(i, "dO"); } } static void tok_p_old(List tok) { if (!containsSubList(tok, "p", "", "-")) return; replaceKeywordBlock(tok, "p-pcall", "p { pcall {", "}}"); jreplace(tok, "p-autorestart", "p-autoupdate"); jreplace(tok, "p-autoupdate {", "p { autoUpdate();"); jreplace(tok, "p-noconsole-autoupdate {", "p-noconsole { autoUpdate();"); jreplace(tok, "p-subst-autoupdate {", "p-subst { autoUpdate();"); jreplace(tok, "p-subst-autorestart {", "p-subst { autoUpdate();"); jreplace(tok, "p-pretty {", "p-noconsole {"); replaceKeywordBlock(tok, "p-awt-noconsole", "p-awt {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-hideconsole", "p {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-substance-noconsole", "p-substance {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-nimbus-noconsole", "p-nimbus {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-subst-noconsole", "p-subst {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-noconsole", "p-subst {", ";\nhideConsole(); }"); replaceKeywordBlock(tok, "p-subst", "p-substance-thread {", "}"); replaceKeywordBlock(tok, "p-substance-thread", "p { substance();", "}"); replaceKeywordBlock(tok, "p-magellan-thread", "p { magellan();", "}"); replaceKeywordBlock(tok, "p-substance", "p-awt { substance();", "}"); replaceKeywordBlock(tok, "p-nimbus", "p-awt { nimbus();", "}"); replaceKeywordBlock(tok, "p-center", "p { centerConsole(); ", "}"); replaceKeywordBlock(tok, "p-experiment-tt", "p-experiment { tt(); ", "}"); jreplace(tok, "p-exp", "p-experiment"); replaceKeywordBlock(tok, "p-experiment", "p { pExperiment(); ", "}"); jreplace(tok, "p-type {", "p-typewriter {"); jreplace(tok, "p-tt {", "p-typewriter {"); replaceKeywordBlock(tok, "p-awt", "p { swing {", "}}"); replaceKeywordBlock(tok, "p-typewriter", "p { typeWriterConsole();", "}"); replaceKeywordBlock(tok, "p-lowprio", "p { lowPriorityThread(r " + "{", "}); }"); tok_p_repeatWithSleep(tok); } // -Syntax: switch to q(); // -rest of block is executed in Queue q() static void tok_switchTo(List tok) { int i = -1; while ((i = jfind(tok, i+1, "switch to")) >= 0) { int semicolon = findEndOfStatement(tok, i)-1; int endOfOuterBlock = findEndOfBracketPart(tok, semicolon)-1; clearTokens(tok, i, i+4); tok.set(semicolon, ".add(r {"); tok.set(endOfOuterBlock, "}); }"); reTok(tok, i, endOfOuterBlock+1); } } static List tok_equalsCast(List tok) { if (!tok.contains("cast")) return tok; int iVar = -1; while ((iVar = jfind(tok, iVar+1, " = cast")) >= 0) { int iTypeStart = tok_scanTypeBackwards(tok, iVar-2); int iCast = iVar+4; int j = scanToEndOfInitializer2(tok, iCast); String type = joinSubList(tok, iTypeStart, iVar-1); clearTokens(tok, iCast, iCast+1); if (!tok_typeIsObject(type)) { boolean needBrackets = j > iCast+4; tokPrepend(tok, iCast+2, "(" + type + ") " + (needBrackets ? "(" : "")); if (needBrackets) tokPrepend(tok, j+1, ")"); } reTok(tok, iCast, j+2); } return tok; } // S s = opt cast ...; static List tok_equalsOptCast(List tok) { if (!tok.contains("cast")) return tok; int iVar = -1; while ((iVar = jfind(tok, iVar+1, " = opt cast")) >= 0) { int iTypeStart = tok_scanTypeBackwards(tok, iVar-2); int iCast = iVar+6; int j = scanToEndOfInitializer2(tok, iCast); String type = joinSubList(tok, iTypeStart, iVar-1); replaceTokens(tok, iCast-2, iCast+2, "optCast " + type + "("); tokPrepend(tok, j+1, ")"); reTok(tok, iCast-2, j+2); } return tok; } static int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static int findCodeTokens_bails, findCodeTokens_nonbails; static interface findCodeTokens_Matcher { boolean get(String token); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size()-tokens.length*2+2, nTokens = tokens.length; int i = startIdx | 1; // bail out early if first token not found (works great with IndexedList) String firstToken = tokens[0]; if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) { if (tok instanceof IndexedList2 && !tok.contains(firstToken)) { ++findCodeTokens_bails; return -1; } ++findCodeTokens_nonbails; // quickly scan for first token while (i < end && !firstToken.equals(tok.get(i))) i += 2; } findCodeTokens_Matcher[] matchers = new findCodeTokens_Matcher[nTokens]; for (int j = 0; j < nTokens; j++) { String p = tokens[j]; findCodeTokens_Matcher matcher; if (p.equals("*")) matcher = t -> true; else if (p.equals("")) matcher = t -> isQuoted(t); else if (p.equals("")) matcher = t -> isIdentifier(t); else if (p.equals("")) matcher = t -> isInteger(t); else if (p.equals("\\*")) matcher = t -> t.equals("*"); else if (ignoreCase) matcher = t -> eqic(p, t); else matcher = t -> t.equals(p); matchers[j] = matcher; } outer: for (; i < end; i += 2) { for (int j = 0; j < nTokens; j++) if (!matchers[j].get(tok.get(i+j*2))) continue outer; if (condition == null || checkTokCondition(condition, tok, i-1)) // pass N index return i; } return -1; } static List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static List subList(int startIndex, int endIndex, List l) { return subList(l, startIndex, endIndex); } static List subList(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = Math.max(0, startIndex); endIndex = Math.min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return l.subList(startIndex, endIndex); } static List subList(List l, IntRange r) { return subList(l, r.start, r.end); } static String tok_addSemicolon(List tok) { //assertOdd(l(tok)); String lastToken = get(tok, (l(tok)|1)-2); if (eqOneOf(lastToken, "}", ";")) return join(tok); return join(tok) + ";"; } static String tok_addSemicolon(String s) { return tok_addSemicolon(javaTok(s)); } static String tok_autoQuineFunc(List contents) { return tok_autoQuineFunc(contents, "toString"); } static String tok_autoQuineFunc(List contents, String funcName) { return " public S " + funcName + "() { ret " + quote(shorten(maxQuineLength, trimJoin(contents))) + "; }"; } static boolean tok_repeatWithSleep_verbose = false; static List tok_repeatWithSleep(List tok) { int i; while ((i = jfind(tok, "repeat with sleep * {")) >= 0) { String seconds = tok.get(i+6); // int or id int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); if (tok_repeatWithSleep_verbose) print("idx=" + idx + ", j=" + j); clearTokens(tok, i, idx+1); tok.set(i, "repeat { pcall {"); tok.set(j-1, "} sleepSeconds(" + seconds + "); }"); reTok(tok, j-1, j); reTok(tok, i, idx+1); } while ((i = jfind(tok, "repeat with ms sleep * {")) >= 0) { String ms = tok.get(i+8); // int or id int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); if (tok_repeatWithSleep_verbose) print("idx=" + idx + ", j=" + j); clearTokens(tok, i, idx+1); tok.set(i, "repeat { pcall {"); tok.set(j-1, "} sleep(" + ms + "); }"); reTok(tok, j-1, j); reTok(tok, i, idx+1); } return tok; } static boolean tok_tokenBeforeLonelyReturnValue(List tok, int i) { String t = get(tok, i); if (l(t) == 1 && "{};".contains(t) || eq(t, "else")) return true; if (!eq(t, ")")) return false; int level = 0; while (i > 0) { if (eq(tok.get(i), ")")) ++level; if (eq(tok.get(i), "(")) --level; if (level == 0) return eq(get(tok, i-2), "if"); i -= 2; } return false; } static ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } static List splitAtJavaToken(String s, String splitToken) { return splitByJavaToken(s, splitToken); } static String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s)*1.5+2)); quote_impl(s, out); return out.toString(); } static void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static String trim(String s) { return s == null ? null : s.trim(); } static String trim(StringBuilder buf) { return buf.toString().trim(); } static String trim(StringBuffer buf) { return buf.toString().trim(); } static List javaTokC(String s) { if (s == null) return null; int l = s.length(); ArrayList tok = new ArrayList(); int i = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) break; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } return tok; } static boolean startsAndEndsWith(String a, char c) { return startsWith(a, c) && endsWith(a, c) && l(a) >= 2; } static boolean startsAndEndsWith(String a, String b) { return startsWith(a, b) && endsWith(a, b) && l(a) >= l(b)*2; } // func returns S[] {beg, end} static List replaceKeywordBlockDyn(List tok, String keyword, Object func) { for (int i = 0; i < 1000; i++) { int idx = findCodeTokens(tok, keyword, "{"); if (idx < 0) break; int j = findEndOfBracketPart(tok, idx+2); String[] be = (String[]) callF(func); tok.set(idx, be[0]); tok.set(idx+1, " "); tok.set(idx+2, ""); tok.set(j-1, be[1]); reTok(tok, idx, j); } return tok; } static boolean neqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return false; return true; } // func : func(LS tok, int iOpening, int iClosing) -> S[] {beg, end} static List replaceKeywordBlock_dyn2_legacy(List tok, String keyword, Object func) { for (int i = 0; i < 1000; i++) { //int idx = findCodeTokens(tok, keyword, "{"); int idx = jfind(tok, keyword + " {"); if (idx < 0) break; int idx2 = findCodeTokens(tok, idx, false, "{"); int j = findEndOfBracketPart(tok, idx2); String[] be = (String[]) callF(func, tok, idx2, j-1); replaceTokens(tok, idx, idx2+2, be[0] + " "); tok.set(j-1, be[1]); reTok(tok, idx, j); } return tok; } static String trimJoin(List s) { return trim(join(s)); } // It's rough but should work if you don't make anonymous classes inside the statement or something... // Also won't work with "for" // Return value is index of semicolon/curly brace+1 static int findEndOfStatement(List tok, int i) { int j = i; // Is it a block? if (eq(get(tok, i), "{")) return findEndOfBlock(tok, i)+1; // It's a regular statement. int n = l(tok); String t; while (j < n && !";".equals(t = tok.get(j))) if ("{".equals(t)) j = findEndOfBlock(tok, j)+1; else j += 2; return j+1; } static boolean eqGet(List l, int i, Object o) { return eq(get(l, i), o); } static boolean eqGet(Map map, A key, Object o) { return eq(mapGet(map, key), o); } // Return value is C token static int tok_findBeginningOfStatement(List tok, int i) { i |= 1; int level = 0; while (i > 1) { String t = get(tok, i); if (eqOneOf(t, "{", "(")) { if (level-- < 0) break; } else if (eqOneOf(t, "}", ")")) level++; else if (level == 0 && eqGetOneOf(tok, i-2, "}", "{", ";")) break; i -= 2; } return i; } static String joinSubList(List l, int i, int j) { return join(subList(l, i, j)); } static String joinSubList(List l, int i) { return join(subList(l, i)); } static String joinSubList(List l, IntRange r) { return r == null ? null : joinSubList(l, r.start, r.end); } static String getVarDeclarationName(List tok) { int j = 1; List special = litlist("=", "{", ";"); while (j < tok.size() && !special.contains(tok.get(j))) j += 2; j -= 2; while (j > 1 && litlist("[", "]").contains(tok.get(j))) j -= 2; return tok.get(j); } static void tokPrepend_reTok(List tok, int i, String s) { tokPrepend(tok, i, s); reTok(tok, i, i+1); } static void clearTokens(List tok) { clearAllTokens(tok); } static void clearTokens(List tok, int i, int j) { clearAllTokens(tok, i, j); } static void clearTokens(List tok, IntRange r) { clearAllTokens(tok, r.start, r.end); } static void tok_expandLPair(List tok) { if (!tok.contains("LPair")) return; int n = l(tok)-6; for (int i = 1; i < n; i += 2) { { if (!(eq(tok.get(i), "LPair") && eq(tok.get(i+2), "<"))) continue; } int j = findEndOfTypeArgs(tok, i+2)-1; // j = index of > tok.set(i, "L>"); reTok(tok, i, j+1); n = l(tok)-6; } } static void tok_expandPairL(List tok) { if (!tok.contains("PairL")) return; int n = l(tok)-6; for (int i = 1; i < n; i += 2) { { if (!(eq(tok.get(i), "PairL") && eq(tok.get(i+2), "<"))) continue; } int j = findEndOfTypeArgs(tok, i+2)-1; // j = index of > tok.set(i, "Pair>"); reTok(tok, i, j+1); n = l(tok)-6; } } static void tok_expandLT3(List tok) { if (!tok.contains("LT3")) return; int n = l(tok)-6; for (int i = 1; i < n; i += 2) { { if (!(eq(tok.get(i), "LT3") && eq(tok.get(i+2), "<"))) continue; } int j = findEndOfTypeArgs(tok, i+2)-1; // j = index of > tok.set(i, "L>"); reTok(tok, i, j+1); n = l(tok)-6; } } // +var => "var", +var static void tok_expandVarCopies(List tok) { for (int i = 3; i+2 < l(tok); i += 2) { if (!eq(tok.get(i), "+")) continue; if (!eqOneOf(tok.get(i-2), "(", ",", "{")) continue; String s = tok.get(i+2); if (!isIdentifier(s)) continue; tok.set(i, quote(s) + ", "); reTok(tok, i, i+1); } } static void tok_replaceColonEqualsSyntax(List tok) { int i; // "field := value" for defining fields e.g. in "uniq" while ((i = jfind(tok, " :=")) >= 0) { tok.set(i, quote(tok.get(i))); tok.set(i+2, ","); tok.set(i+4, ""); reTok(tok, i, i+5); } // "quoted" := value while ((i = jfind(tok, " :=")) >= 0) { tok.set(i, tok.get(i)); tok.set(i+2, ","); tok.set(i+4, ""); reTok(tok, i, i+5); } } static void tok_unpair(List tok) { if (!tok.contains("unpair")) return; int i; jreplace(tok, " , = unpair", "$1 $2, $1 $4 = unpair"); while ((i = jfind(tok, " , = unpair")) >= 0) { int idx = indexOf(tok, "unpair", i); int j = findEndOfStatement(tok, idx); String type1 = tok.get(i), var1 = tok.get(i+2); String type2 = tok.get(i+6), var2 = tok.get(i+8); String v = makeVar(); tok.set(i+4, ";"); tok.set(idx-2, ";"); tok.set(idx, "Pair<" + tok_toNonPrimitiveTypes(type1) + "," + tok_toNonPrimitiveTypes(type2) + "> " + v + "="); tok.set(j-1, "; " + var1 + " = " + v + ".a; " + var2 + " = " + v + ".b;"); reTok(tok, i, j); } while ((i = jfind(tok, " , < , > = unpair")) >= 0 || (i = jfind(tok, " , <> = unpair")) >= 0) { print("unpair"); int idx = indexOf(tok, "unpair", i); int j = findEndOfStatement(tok, idx); String type1 = tok.get(i), var1 = tok.get(i+2); String type2 = joinSubList(tok, i+5, idx-5), var2 = tok.get(idx-4); String v = makeVar(); tok.set(i+4, ";"); tok.set(idx-2, ";"); tok.set(idx-1, ""); tok.set(idx, "Pair<" + type1 + "," + type2 + "> " + v + "="); tok.set(j-1, "; " + var1 + " = " + v + ".a; " + var2 + " = " + v + ".b;"); reTok(tok, i, j); } } static void tok_cachedFunctions(List tok) { try { if (!tok.contains("cached")) return; int i; while ((i = jfind(tok, "static cached ")) >= 0) { int bracket = indexOf(tok, "(", i); String fName = assertIdentifier(tok.get(bracket-2)); String type = joinSubList(tok, i+4, bracket-3); String boxedType = tok_toNonPrimitiveTypes(type); replaceTokens(tok, i, bracket-1, ("static Cache<" + (boxedType) + "> " + (fName) + "_cache = new Cache(f " + (fName) + "_load);\n") + ("static " + (type) + " " + (fName) + "() { ret " + (fName) + "_cache!; }\n\n") + ("static " + (boxedType) + " " + (fName) + "_load")); reTok(tok, i, bracket-3); } } catch (Throwable __e) { _handleException(__e); }} static void tok_simplyCachedFunctions(List tok) { try { if (!tok.contains("simplyCached")) return; int i = -1; while ((i = jfind(tok, i+1, "static simplyCached ")) >= 0) { int bracket = indexOf(tok, "(", i); String fName = assertIdentifier(tok.get(bracket-2)); String type = joinSubList(tok, i+4, bracket-3); String boxedType = tok_toNonPrimitiveTypes(type); replaceTokens(tok, i, bracket-1, ("static " + (boxedType) + " " + (fName) + "_cache;\n") + ("static " + (type) + " " + (fName) + "() { if (" + (fName) + "_cache == null) " + (fName) + "_cache = " + (fName) + "_load(); ret " + (fName) + "_cache; }\n\n") + ("static " + (boxedType) + " " + (fName) + "_load")); reTok(tok, i, bracket-3); } } catch (Throwable __e) { _handleException(__e); }} // "optPar int bla = 5;" => "int bla = optPar bla(_, 5);" static void tok_optPar(List tok) { if (!tok.contains("optPar")) return; int i; while ((i = jfindOneOf(tok, "optPar ", "optPar <")) >= 0) { int iSemicolon = tok_findEndOfStatement(tok, i)-1; int iEquals = indexOf_between(tok, "=", i, iSemicolon); clearTokens(tok, i, i+2); // drop optPar if (iEquals < 0) { // no initializer String var = tok.get(iSemicolon-2); String type = joinSubList(tok, i+2, iSemicolon-3); if (eqOneOf(type, "bool", "boolean")) tok.set(iSemicolon, " = boolPar " + var + "(_);"); else tok.set(iSemicolon, " = cast optPar " + var + "(_);"); } else { String var = tok.get(iEquals-2); tok.set(iEquals, "= optPar " + var + "(_, "); tok.set(iSemicolon, ");"); } reTok(tok, i, iSemicolon+1); } } static void tok_typeAA(List tok, Set pairClasses) { int n = l(tok)-6; boolean change = false; for (int i = 1; i < n; i += 2) { if (!eq(get(tok, i+2), "<")) continue; String t = tok.get(i); { if (!(contains(pairClasses, t) || eq(t, "Entry") && eqGet(tok, i-2, ".") && eqGet(tok, i-4, "Map"))) continue; } if (tok_isSingleTypeArg(tok, i+2)) { int j = findEndOfTypeArgs(tok, i+2)-1; String type = joinSubList(tok, i+4, j); replaceTokens_reTok(tok, i+4, j, type + ", " + type); change = true; } } } static List tok_expandStarConstructors(List tok) { mainLoop: for (int i = 3; i+6 < tok.size(); i += 2) { String t = tok.get(i), l = tok.get(i-2); if (!t.equals("*")) continue; if (!tok.get(i+2).equals("(")) continue; if (!eqOneOf(l, "}", "public", "private", "protected", ";", "{", "endif", ">") && neq(get(tok, i-4), "ifclass")) // is this correct...?? continue; // ok, it seems like a constructor declaration. // Now find class name by going backwards. int j = i, level = 1; while (j > 0 && level > 0) { t = tok.get(j); if (t.equals("}")) ++level; if (t.equals("{")) --level; j -= 2; } // search for class name while (j > 0) { t = tok.get(j); if (t.equals("class")) { String className = tok.get(j+2); tok.set(i, className); // exchange constructor name! // now for the parameters. // Syntax: *(Learner *learner) { // We will surely add type inference here in time... :) j = i+2; while (!tok.get(j).equals("{")) j += 2; // skip calling super/this constructor if (eqGetOneOf(tok, j+2, "super", "this")) j = tok_findEndOfStatement(tok, j+2)-1; int block = j+1; for (int k = i+2; k < block-1; k += 2) if (tok.get(k).equals("*")) { tok.remove(k); tok.remove(k); block -= 2; String name = tok.get(k); tok.addAll(block, Arrays.asList(new String[] { "\n ", "this", "", ".", "", name, " ", "=", " ", name, "", ";" })); } continue mainLoop; } j -= 2; } } return tok; } static void tok_kiloConstants(List tok) { if (!tok.contains("K")) return; jreplace(tok, " K", "($1*1024)"); } // references to objects in other realm (replace with Object) static void tok_virtualTypes(List tok) { int i = -1; while ((i = jfind(tok, i+1, "virtual ")) >= 0) { replaceTokens_reTok(tok, i, tok_findEndOfType(tok, i+2)-1, "Object"); } } static List tok_autoLongConstants(List tok) { int n = l(tok); for (int i = 1 ; i < n; i += 2) { String t = tok.get(i); if (isInteger(t) && !eq(get(tok, i+2), "L") && !eqOneOf(get(tok, i-2), "-" /* huh? */, "." /* float/double */) && !longIsInt(parseLong(t))) tokAppend(tok, i, "L"); } return tok; } // unimplemented S bla(); => S bla() { throw unimplemented(); } static void tok_unimplementedMethods(List tok) { int i = -1; while ((i = jfind(tok, i+1, "unimplemented")) >= 0) { String t = get(tok, i+2); { if (!(isIdentifier(t) || eq(t, "<"))) continue; } int j = tok_findEndOfStatement(tok, i); // abuse da function replaceTokens(tok, i, i+2, ""); tokReplace(tok, j-1, " { throw unimplemented(); }"); reTok(tok, i, j); } } static void tok_switchableFields(List tok) { int i = -1; while ((i = jfind(tok, i+1, "switchable ")) >= 0) { String var = getVarDeclarationName(subList(tok, i+1)); tokSet_withReTok(tok, i, "sbool _switchableField_" + var + " = true;"); } } static void tok_autoDisposeFields(List tok) { int i = -1; while ((i = jfind(tok, i+1, "autoDispose ")) >= 0) { String var = getVarDeclarationName(subList(tok, i+1)); tokSet_withReTok(tok, i, ""); tokPrepend_withReTok(tok, leftScanModifiers(tok, i), "void cleanMeUp_" + var + "() { dispose " + var +"; } "); } } // visual bla(super); => visualize { ret bla(super.visualize()); } static void tok_shortVisualize(List tok) { int i = -1; while ((i = jfind(tok, i+1, "visual ")) >= 0) { int j = tok_findEndOfStatement(tok, i); for (int k = i; k < j; k += 2) if (eqGet(tok, k, "super") && neqGet(tok, k+2, ".")) tokSet(tok, k, "super.visualize()"); tokSet(tok, j-1, "; }"); tokSet(tok, i, "visualize { ret"); reTok(tok, i, j); } } static void tok_whileGreaterThan(List tok) { int i = -1; while ((i = jfind(tok, "while >= (")) >= 0) { int iOpening = indexOf(tok, "(", i); int iClosing = findEndOfBracketPart(tok, iOpening)-1; tokSet_reTok(tok, iClosing, ") >= 0)"); replaceTokens_reTok(tok, i+2, iOpening+1, "(("); } } // if condition then code end static void tok_ifThenEnd(List tok) { int i = -1; while ((i = jfind(tok, i+1, "if ")) >= 0) { int iThen = indexOf(tok, i, "then"); if (iThen < 0) { print("No then for if"); continue; } int iEnd = tok_findTokenSkippingCurlyBrackets(tok, iThen, "end"); if (iEnd < 0) { print("No end for if"); continue; } tokSet(tok, iEnd, "}"); replaceTokens_reTok(tok, iThen-1, iThen+1, ") {"); replaceTokens_reTok(tok, i, i+2, "if ("); } } static void tok_autoInitVars(List tok) { jreplace(tok, "boolean ;", "boolean $2 = false;", new TokCondition() { boolean get(final List tok, final int i) { return !contains(tok_modifiersLeftOf(tok, i+1), "final"); }}); } static void tok_fixBadTypeParameterOrder(List tok) { // e.g. void bla() => void bla() jreplace(tok, "void <>", "<$3> void"); } static void tok_questionDot(List tok) { jreplace(tok, " ?.", "if ($1 != null) $1."); /*int i; while ((i = jfind(tok, " ?.")) { S var = tok.get(i); int j = findEndOfStatement(tok, i); int dot = indexOf(tok, i, "."); tok.set(i+2, ""); replaceTokens(tok, i, dot+1, "if (" + var + " != null) var."); }*/ } static void tok_embeddedFunctions(List tok) { int i; while ((i = jfind(tok, "embedded ")) >= 0) { int j = tok_findEndOfMethodDecl(tok, i); // points to N after function String functionName = tok_functionName(subList(tok, i)); String className = makeVar("C"), varName = makeVar(); // drop keyword, rewrite function to class, create object tok.set(i, "/* make final to optimize */ class " + className + " {"); tokAppend(tok, j-1, " } " + " final " + className + " " + varName + " = new " + className + "();"); // redirect calls to object int end = findEndOfBlock(tok, j)-1; for (j |= 1; j < end; j += 2) if (eq(tok.get(j), functionName) && eqGet(tok, j+2, "(")) tokPrepend(tok, j, varName + "."); reTok(tok, i, end); } } static void tok_once(List tok) { replaceKeywordBlock(tok, "once", "do {", "} while (false);"); } // Note: the variable names must match the record field names // as we still need a way to find the field names from here static void tok_ifRecordMatch(List tok) { int i; while ((i = jfind_check("is",tok, "if is (")) >= 0) { int iOpening = indexOf(tok, i, "("); int iClosing = indexOf(tok, iOpening+2, ")"); String var = tok.get(i+2), className = tok.get(i+6); String cast = "((" + className + ") " + var + ")"; int start = iClosing+2; tok_statementToBlock(tok, start); int end = findEndOfStatement(tok, start); StringBuilder statement = new StringBuilder(("if (" + (var) + " instanceof " + (className))); StringBuilder decls = new StringBuilder(); List> vars = tok_typesAndNamesOfParams(subList(tok, iOpening+1, iClosing)); for (Pair v : vars) { String type = v.a, name = v.b; String nonPrim = tok_toNonPrimitiveTypes(type); if (!tok_typeIsObject(type)) statement.append((" && " + (cast) + "." + (name) + " instanceof " + (nonPrim))); decls.append(("\n" + (type) + " " + (name) + " = cast " + (cast) + "." + (name) + ";")); } replaceTokens_reTok(tok, i, start+1, statement + ") {" + decls); } } static void tok_processMetaBlocks(List tok, boolean metaCodeAllowed) { for (int i = 0; i < 1000; i++) { int idx = findCodeTokens(tok, "meta", "{"); if (idx < 0) break; if (!metaCodeAllowed) throw fail("Meta code not allowed"); int j = findEndOfBracketPart(tok, idx+2); String code = joinSubList(tok, idx+4, j-2); print("Evaluating: " + code); String result = str(javaEval(code)); replaceTokens_reTok(tok, idx, j+1, result); } } static boolean reTok_modify_check = false; // f: func(L) -> L static List reTok_modify(List tok, int i, int j, Object f) { // extend i to an "N" token // and j to "C" (so j-1 is an "N" token) i = i & ~1; j = j | 1; List t = javaTok(join(subList(tok, i, j))); if (f != null) { t = (List) callF(f, t); if (reTok_modify_check) assertEquals("Improperly tokenized", javaTok(join(t)), t); } replaceListPart(tok, i, j, t); return tok; } // removes invocations from src static List tok_findTranslators(List tok, List libsOut) { int i; while ((i = jfind(tok, "!")) >= 0) { setAdd(libsOut, tok.get(i+2)); clearTokens(tok, i, i+3); reTok(tok, i, i+3); } return tok; } static boolean structure_showTiming, structure_checkTokenCount; static String structure(Object o) { return structure(o, new structure_Data()); } static String structure(Object o, structure_Data d) { StringWriter sw = new StringWriter(); d.out = new PrintWriter(sw); structure_go(o, d); String s = str(sw); if (structure_checkTokenCount) { print("token count=" + d.n); assertEquals("token count", l(javaTokC(s)), d.n); } return s; } static void structure_go(Object o, structure_Data d) { structure_1(o, d); while (nempty(d.stack)) popLast(d.stack).run(); } static void structureToPrintWriter(Object o, PrintWriter out) { structure_Data d = new structure_Data(); d.out = out; structure_go(o, d); } // leave to false, unless unstructure() breaks static boolean structure_allowShortening = false; // info on how to serialize objects of a certain class static class structure_ClassInfo { List fields; Method customSerializer; } static class structure_Data { PrintWriter out; int stringSizeLimit; int shareStringsLongerThan = 20; boolean noStringSharing = false; IdentityHashMap seen = new IdentityHashMap(); //new BitSet refd; HashMap strings = new HashMap(); HashSet concepts = new HashSet(); HashMap infoByClass = new HashMap(); HashMap persistenceInfo = new HashMap(); int n; // token count List stack = new ArrayList(); // append single token structure_Data append(String token) { out.print(token); ++n; return this; } structure_Data append(int i) { out.print(i); ++n; return this; } // append multiple tokens structure_Data append(String token, int tokCount) { out.print(token); n += tokCount; return this; } // extend last token structure_Data app(String token) { out.print(token); return this; } structure_Data app(int i) { out.print(i); return this; } } static void structure_1(final Object o, final structure_Data d) { try { if (o == null) { d.append("null"); return; } Class c = o.getClass(); boolean concept = false; structure_ClassInfo info = d.infoByClass.get(c); if (info == null) { d.infoByClass.put(c, info = new structure_ClassInfo()); info.customSerializer = findMethodNamed(c, "_serialize"); } List lFields = info.fields; if (lFields == null) { // these are never back-referenced (for readability) if (o instanceof Number) { PrintWriter out = d.out; if (o instanceof Integer) { int i = ((Integer) o).intValue(); out.print(i); d.n += i < 0 ? 2 : 1; return; } if (o instanceof Long) { long l = ((Long) o).longValue(); out.print(l); out.print("L"); d.n += l < 0 ? 2 : 1; return; } if (o instanceof Short) { short s = ((Short) o).shortValue(); d.append("sh "); out.print(s); d.n += s < 0 ? 2 : 1; return; } if (o instanceof Float) { d.append("fl ", 2); quoteToPrintWriter(str(o), out); return; } if (o instanceof Double) { d.append("d(", 3); quoteToPrintWriter(str(o), out); d.append(")"); return; } if (o instanceof BigInteger) { out.print("bigint("); out.print(o); out.print(")"); d.n += ((BigInteger) o).signum() < 0 ? 5 : 4; return; } } if (o instanceof Boolean) { d.append(((Boolean) o).booleanValue() ? "t" : "f"); return; } if (o instanceof Character) { d.append(quoteCharacter((Character) o)); return; } if (o instanceof File) { d.append("File ").append(quote(((File) o).getPath())); return; } // referencable objects follow Integer ref = d.seen.get(o); if (o instanceof String && ref == null) ref = d.strings.get((String) o); if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; } if (!(o instanceof String)) d.seen.put(o, d.n); // record token number else { String s = d.stringSizeLimit != 0 ? shorten((String) o, d.stringSizeLimit) : (String) o; if (!d.noStringSharing) { if (d.shareStringsLongerThan == Integer.MAX_VALUE) d.seen.put(o, d.n); if (l(s) >= d.shareStringsLongerThan) d.strings.put(s, d.n); } quoteToPrintWriter(s, d.out); d.n++; return; } if (o instanceof Set) { /*O set2 = unwrapSynchronizedSet(o); if (set2 != o) { d.append("sync"); o = set2; } TODO */ if (((Set) o) instanceof TreeSet) { d.append(isCISet_gen(((Set) o)) ? "ciset" : "treeset"); structure_1(new ArrayList(((Set) o)), d); return; } // assume it's a HashSet or LinkedHashSet d.append(((Set) o) instanceof LinkedHashSet ? "lhs" : "hashset"); structure_1(new ArrayList(((Set) o)), d); return; } String name = c.getName(); if (o instanceof Collection && !startsWith(name, "main$") /* && neq(name, "main$Concept$RefL") */) { // it's a list if (name.equals("java.util.Collections$SynchronizedList") || name.equals("java.util.Collections$SynchronizedRandomAccessList")) { d.append("sync "); { structure_1(unwrapSynchronizedList(((List) o)), d); return; } } else if (name.equals("java.util.LinkedList")) d.append("ll"); d.append("["); final int l = d.n; final Iterator it = ((Collection) o).iterator(); d.stack.add(new Runnable() { public void run() { try { if (!it.hasNext()) d.append("]"); else { d.stack.add(this); if (d.n != l) d.append(", "); structure_1(it.next(), d); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext())\r\n d.append(\"]\");\r\n else {\r\n d.sta..."; }}); return; } if (o instanceof Map && !startsWith(name, "main$")) { if (o instanceof LinkedHashMap) d.append("lhm"); else if (o instanceof HashMap) d.append("hm"); else if (o instanceof TreeMap) d.append(isCIMap_gen(((TreeMap) o)) ? "cimap" : "tm"); else if (name.equals("java.util.Collections$SynchronizedMap") || name.equals("java.util.Collections$SynchronizedSortedMap") || name.equals("java.util.Collections$SynchronizedNavigableMap")) { d.append("sync "); { structure_1(unwrapSynchronizedMap(((Map) o)), d); return; } } d.append("{"); final int l = d.n; final Iterator it = ((Map) o).entrySet().iterator(); d.stack.add(new Runnable() { boolean v = false; Map.Entry e; public void run() { if (v) { d.append("="); v = false; d.stack.add(this); structure_1(e.getValue(), d); } else { if (!it.hasNext()) d.append("}"); else { e = (Map.Entry) it.next(); v = true; d.stack.add(this); if (d.n != l) d.append(", "); structure_1(e.getKey(), d); } } } }); return; } if (c.isArray()) { if (o instanceof byte[]) { d.append("ba ").append(quote(bytesToHex((byte[]) o))); return; } final int n = Array.getLength(o); if (o instanceof boolean[]) { String hex = boolArrayToHex((boolean[]) o); int i = l(hex); while (i > 0 && hex.charAt(i-1) == '0' && hex.charAt(i-2) == '0') i -= 2; d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); return; } String atype = "array", sep = ", "; if (o instanceof int[]) { //ret "intarray " + quote(intArrayToHex((int[]) o)); atype = "intarray"; sep = " "; } d.append(atype).append("{"); d.stack.add(new Runnable() { int i; public void run() { if (i >= n) d.append("}"); else { d.stack.add(this); if (i > 0) d.append(", "); structure_1(Array.get(o, i++), d); } } }); return; } if (o instanceof Class) { d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); return; } if (o instanceof Throwable) { d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); return; } if (o instanceof BitSet) { BitSet bs = (BitSet) o; d.append("bitset{", 2); int l = d.n; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { if (d.n != l) d.append(", "); d.append(i); } d.append("}"); return; } // Need more cases? This should cover all library classes... if (name.startsWith("java.") || name.startsWith("javax.")) { d.append("j ").append(quote(str(o))); return; // Hm. this is not unstructure-able } /*if (name.equals("main$Lisp")) { fail("lisp not supported right now"); }*/ if (info.customSerializer != null) { // custom serialization (_serialize method) Object o2 = invokeMethod(info.customSerializer, o); d.append("cu "); String shortName = dropPrefix("main$", name); d.append(shortName); d.out.append(' '); structure_1(o2, d); return; } String dynName = shortDynamicClassName(o); if (concept && !d.concepts.contains(dynName)) { d.concepts.add(dynName); d.append("c "); } // serialize an object with fields. // first, collect all fields and values in fv. TreeSet fields = new TreeSet(new Comparator() { public int compare(Field a, Field b) { return stdcompare(a.getName(), b.getName()); } }); Class cc = c; while (cc != Object.class) { for (Field field : getDeclaredFields_cached(cc)) { String fieldName = field.getName(); if (fieldName.equals("_persistenceInfo")) d.persistenceInfo.put(c, field); if ((field.getModifiers() & (java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.TRANSIENT)) != 0) continue; fields.add(field); // put special cases here...? } cc = cc.getSuperclass(); } // TODO: S fieldOrder = getOpt(c, "_fieldOrder"); lFields = asList(fields); // Render this$1 first because unstructure needs it for constructor call. int n = l(lFields); for (int i = 0; i < n; i++) { Field f = lFields.get(i); if (f.getName().equals("this$1")) { lFields.remove(i); lFields.add(0, f); break; } } info.fields = lFields; } // << if (lFields == null) else { // ref handling for lFields != null Integer ref = d.seen.get(o); if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; } d.seen.put(o, d.n); // record token number } Field persistenceInfoField = (Field) (d.persistenceInfo.get(c)); Map persistenceInfo = persistenceInfoField == null ? null : (Map) persistenceInfoField.get(o); LinkedHashMap fv = new LinkedHashMap(); for (Field f : lFields) { Object value; try { value = f.get(o); } catch (Exception e) { value = "?"; } if (value != null && (persistenceInfo == null || !Boolean.FALSE.equals(persistenceInfo.get(f.getName())))) fv.put(f.getName(), value); } String name = c.getName(); String shortName = dropPrefix("main$", name); if (startsWithDigit(shortName)) shortName = name; // for anonymous classes // Now we have fields & values. Process fieldValues if it's a DynamicObject. // omit field "className" if equal to class's name if (concept && eq(fv.get("className"), shortName)) fv.remove("className"); if (o instanceof DynamicObject) { putAll(fv, (Map) fv.get("fieldValues")); fv.remove("fieldValues"); shortName = shortDynamicClassName(o); fv.remove("className"); } String singleField = fv.size() == 1 ? first(fv.keySet()) : null; d.append(shortName); d.n += countDots(shortName)*2; // correct token count final int l = d.n; final Iterator it = fv.entrySet().iterator(); d.stack.add(new Runnable() { public void run() { try { if (!it.hasNext()) { if (d.n != l) d.append(")"); } else { Map.Entry e = (Map.Entry) it.next(); d.append(d.n == l ? "(" : ", "); d.append((String) e.getKey()).append("="); d.stack.add(this); structure_1(e.getValue(), d); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext()) {\r\n if (d.n != l)\r\n d.append(\")\");\r\n } else..."; }}); } catch (Exception __e) { throw rethrow(__e); } } static boolean tok_hasClassRef2(List tok, String className) { int n = l(tok); int level = 0; for (int i = 1; i < n; i += 2) { String t = tok.get(i); if (eqOneOf(t, "ifclass", "ifndef")) ++level; else if (eqOneOf(t, "endif", "endifndef")) --level; else if (level <= 0 && eq(t, className)) return true; } return false; } static A printStruct(String prefix, A a) { printStructure(prefix, a); return a; } static A printStruct(A a) { printStructure(a); return a; } static boolean includeInMainLoaded_safe = false; static List includeInMainLoaded(List tok, String text) { List main = findMainClass(tok); if (main == null) { print(join(tok)); throw fail("no main class"); } int i = main.lastIndexOf("}"); main.set(i, "\n" + text + "\n}"); i += magicIndexOfSubList(tok, main); return includeInMainLoaded_safe ? includeInMainLoaded_reTok(tok, 0, l(tok)) : includeInMainLoaded_reTok(tok, i, i+1); } // supports the usual quotings (", variable length double brackets) except ' quoting static boolean isQuoted(String s) { if (isNormalQuoted_dirty(s)) return true; return isMultilineQuoted(s); } static String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static String dropSuffix(String suffix, String s) { return s.endsWith(suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static int indexOf(List l, A a, int startIndex) { if (l == null) return -1; int n = l(l); for (int i = startIndex; i < n; i++) if (eq(l.get(i), a)) return i; return -1; } static int indexOf(List l, int startIndex, A a) { return indexOf(l, a, startIndex); } static int indexOf(List l, A a) { if (l == null) return -1; return l.indexOf(a); } static int indexOf(String a, String b) { return a == null || b == null ? -1 : a.indexOf(b); } static int indexOf(String a, String b, int i) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, char b) { return a == null ? -1 : a.indexOf(b); } static int indexOf(String a, int i, char b) { return indexOf(a, b, i); } static int indexOf(String a, char b, int i) { return a == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, int i, String b) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(A[] x, A a) { int n = l(x); for (int i = 0; i < n; i++) if (eq(x[i], a)) return i; return -1; } static void tokSet_reTok(List tok, int i, String t) { tokSet_withReTok(tok, i, t); } static int getAndInc(AtomicInteger i) { return i.getAndIncrement(); } static Map runTranslatorQuick_cache = new HashMap(); static synchronized String runTranslatorQuick(String text, String translatorID) { translatorID = formatSnippetID(translatorID); Class c = runTranslatorQuick_cache.get(translatorID); print("runTranslatorQuick " + programID() + " " + identityHashCode(main.class) + " CACHE " + identityHashCode(runTranslatorQuick_cache) + " " + structure(runTranslatorQuick_cache.keySet()) + " " + (c != null ? "CACHED" : "LOAD") + ": " + translatorID); if (c == null) { //printStackTrace(); c = hotwire(translatorID); print("runTranslatorQuick " + programID() + " " + identityHashCode(main.class) + " CACHE " + identityHashCode(runTranslatorQuick_cache) + " " + structure(runTranslatorQuick_cache.keySet()) + " STORE: " + translatorID + " " + identityHashCode(c)); runTranslatorQuick_cache.put(translatorID, c); } set(c, "mainJava", text); callMain(c); return (String) get(c, "mainJava"); } static List runTranslatorQuick(List tok, String translatorID) { return javaTok(runTranslatorQuick(join(tok), translatorID)); } static boolean neq(Object a, Object b) { return !eq(a, b); } static List tok_findImports(List tok) { List imports = new ArrayList(); int n = l(tok); for (int i = 1; i < n; i += 2) if (eq(tok.get(i), "import")) { int j = indexOf(tok, ";", i+2); if (j < 0) break; imports.add(joinCodeTokens(subList(tok, i-1, j))); i = j; } return imports; } static Class include(String progID) { Class c = hotwire(progID); setOpt(c, "programID", getProgramID()); return c; } static long parseLong(String s) { if (empty(s)) return 0; return Long.parseLong(dropSuffix("L", s)); } static long parseLong(Object s) { return Long.parseLong((String) s); } static List findInnerClassOfMain(List tok, String className) { for (List c : innerClassesOfMain(tok)) { String name = getClassDeclarationName(c); if (eq(name, className)) return c; } return null; } static int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static int indexOfSubList(List x, List y, int i) { outer: for (; i+l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i+j), y.get(j))) continue outer; return i; } return -1; } static int indexOfSubList(List x, A[] y, int i) { outer: for (; i+l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i+j), y[j])) continue outer; return i; } return -1; } static void doubleReTok(List tok, int i1, int j1, int i2, int j2) { if (i1 > i2) { int i = i1, j = j1; i1 = i2; j1 = j2; i2 = i; j2 = j; } if (j1 > i2) { reTok(tok); return; } reTok(tok, i2, j2); reTok(tok, i1, j1); } static String dropPrefixTrim(String prefix, String s) { return trim(dropPrefix(prefix, s)); } static void clearAllTokens(List tok) { for (int i = 0; i < tok.size(); i++) tok.set(i, ""); } static void clearAllTokens(List tok, int i, int j) { for (; i < j; i++) tok.set(i, ""); } static String str(Object o) { return o == null ? "null" : o.toString(); } static String str(char[] c) { return new String(c); } static int countChar(String s, char c) { int n = 0, l = l(s), i = 0; while (true) { int j = s.indexOf(c, i); if (j < 0) break; ++n; i = j+1; } return n; } static void tok_autosemi(List tok) { int i; while ( (i = jfind(tok, "autosemi {")) >= 0 || (i = jfind(tok, "semiauto {")) >= 0) { int closing = findEndOfBlock(tok, i+2)-1; tok.set(i, ""); // remove autosemi keyword tok.set(i+1, ""); for (int j = i+5; j < closing; j += 2) if (containsNewLine(tok.get(j)) && neqOneOf(tok.get(j-1), "{", "}", ";")) tok.set(j-1, tok.get(j-1) + ";"); reTok(tok, i, closing); } } static String tok_autoCloseBrackets(String s) { return join(tok_autoCloseBrackets(javaTok(s))); } // modifies tok static List tok_autoCloseBrackets(List tok) { bigloop: for (int i = 1; i < l(tok); i += 2) { if (eq(tok.get(i), ";")) { int j, level = 0; for (j = i-2; j >= 0; j -= 2) { String t = tok.get(j); if (eqOneOf(t, ";", "{")) break; if (eq(t, "}")) break; // TODO: skip over until other end of bracket else if (eq(t, ")")) --level; else if (eq(t, "(")) { if (eq(get(tok, j-2), "for")) break; if (eq(get(tok, j-4), "for")) break; // for ping ++level; } } while (level-- > 0) { tok.add(i++, ")"); tok.add(i++, ""); } } } return tok; } static Map tok_toNonPrimitiveTypes_map = mapFromTokens("\r\n int Int\r\n byte Byte\r\n float Float\r\n short Short\r\n double Double\r\n long Long\r\n char Character\r\n bool Bool\r\n boolean Bool\r\n"); static String tok_toNonPrimitiveTypes(String s) { return join(tok_toNonPrimitiveTypes(javaTok(s))); } static List tok_toNonPrimitiveTypes(List tok) { for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); t = tok_toNonPrimitiveTypes_map.get(t); if (t != null && neq(get(tok, i+2), "[")) tok.set(i, t); } return tok; } static List cloneSubList(List l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static List cloneSubList(List l, int startIndex) { return newSubList(l, startIndex); } static List tok_typesOfParams(List tok) { try { List types = new ArrayList(); for (int i = 1; i < l(tok); ) { String t = tok.get(i); if (eqOneOf(t, "final")) t = get(tok, i += 2); assertTrue(isIdentifier(t)); i += 2; String type = t; if (eq(t, "virtual")) { type += " " + tok.get(i); i += 2; } while (eq(get(tok, i), ".") && isIdentifier(get(tok, i+2))) { type += "." + get(tok, i+2); i += 4; } // ... if (eqGet(tok, i, ".") && eqGet(tok, i+2, ".") && eqGet(tok, i+2, ".")) { type += "[]"; i += 6; } // just a parameter name, no type if (eqOneOf(get(tok, i), null, ",")) t = null; else { if (eq(tok.get(i), "<")) { int j = findEndOfTypeArgs(tok, i)-1; while (eq(get(tok, j), "[") && eq(get(tok, j+2), "]")) j += 4; type += trimJoinSubList(tok, i, j+1); String id = assertIdentifier(tok.get(j+2)); i = j+2; } while (eq(get(tok, i), "[") && eq(get(tok, i+2), "]")) { i += 4; type += "[]"; } String id = assertIdentifier(tok.get(i)); i += 2; while (eq(get(tok, i), "[") && eq(get(tok, i+2), "]")) { i += 4; type += "[]"; } if (i < l(tok)) { assertEquals(get(tok, i), ","); i += 2; } } types.add(type); } return types; } catch (Throwable e) { print("Bad parameter declaration: " + join(tok)); throw rethrow(e); } } static List tok_typesOfParams(String s) { return tok_typesOfParams(javaTok(s)); } // optionally convert expression to return statement static String tok_addReturn(List tok) { if (tok_shouldAddReturn(tok)) { tokPrepend(tok, 1, "ret "); tokAppend(tok, l(tok)-2, ";"); } return join(tok); } static String tok_addReturn(String s) { return tok_addReturn(javaTok(s)); } static void tok_qFunctions(List tok) { tok_qFunctions(tok, "q", "dm_q"); tok_qFunctions(tok, "runInQAndWait", "dm_runInQAndWait"); } static void tok_qFunctions(List tok, String keyword, String function) { int i; while ((i = jfind_check(keyword, tok, "void " + keyword + " {")) >= 0) { int bracket = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, bracket); clearTokens(tok, i+4, i+6); tok.set(bracket, "{ " + function + "(r {"); tok.set(j-1, "}); }"); reTok(tok, i+4, j); } while ((i = jfind_check(keyword, tok, ") " + keyword + " {")) >= 0) { int opening = findBeginningOfBracketPart(tok, i); String fname = assertIdentifier(get(tok, opening-2)); int bracket = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, bracket); clearTokens(tok, i+2, i+4); tok.set(bracket, "{ " + function + "(r {"); tok.set(j-1, "}); }"); reTok(tok, i+4, j); tok_makeArgumentsFinal(tok, opening, i); } } // i must point at the (possibly imaginary) opening bracket ("{") // index returned is index of closing bracket + 1 (or l(cnc)) static int findEndOfBlock(List cnc, int i) { int j = i+2, level = 1, n = cnc.size(); while (j < n) { String t = cnc.get(j); if ("{".equals(t)) ++level; else if ("}".equals(t)) --level; if (level == 0) return j+1; j += 2; } return n; } static boolean tok_tokenLeftOfExpression(List tok, int i) { return eqGetOneOf(tok, i, "(", "=", ",") || isIdentifier(get(tok, i)); } static boolean isBracketHygienic(String s) { return testBracketHygiene(s); } static boolean isBracketHygienic(String s, String op, String close, Var msg) { return testBracketHygiene(s, op, close, msg); } static boolean isBracketHygienic(String s, String op, String close) { return testBracketHygiene(s, op, close, null); } static List concatLists(Collection... lists) { List l = new ArrayList(); if (lists != null) for (Collection list : lists) if (list != null) l.addAll(list); return l; } static List concatLists(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Collection list : lists) if (list != null) l.addAll(list); return l; } static Object loadVariableDefinition(String varName) { return loadVariableDefinition(getProgramID(), varName); } // currently works with string lists ("= litlist(...)"), // strings, longs and ints. static Object loadVariableDefinition(String progIDOrSrc, String varName) { if (isSnippetID(progIDOrSrc)) progIDOrSrc = loadSnippet(progIDOrSrc); return loadVariableDefinition(progIDOrSrc, javaTok(progIDOrSrc), varName); } static Object loadVariableDefinition(String src, List tok, String varName) { int i = findCodeTokens(tok, varName, "="); if (i < 0) return null; i += 4; String t = tok.get(i); if (isQuoted(t)) return unquote(t); if (isLongConstant(t)) return parseLong(t); if (isInteger(t)) return parseInt(t); if (eqOneOf(t, "litlist", "ll") && eq(get(tok, i+2), "(")) { int opening = i+2; int closing = findEndOfBracketPart(tok, opening)-1; List l = new ArrayList(); for (i = opening+2; i < closing; i += 4) l.add(unquote(tok.get(i))); return l; } throw fail("Unknown variable type or no definition in source: " + shorten(src, 100) + "/" + varName); } static Map combinedMap(Map... maps) { return new CombinedMap(wrapAsList(maps)); } static > Map combinedMap(Collection maps) { return l(maps) == 1 ? first(maps) : new CombinedMap(maps); } static List tok_importedStaticFunctionNames(List tok) { List names = new ArrayList(); for (int i = 1; i < l(tok); i += 2) if (eq(tok.get(i), "import") && eq(get(tok, i+2), "static")) { int j = findEndOfStatement(tok, i); // index of ;+1 String s = get(tok, j-3); if (isIdentifier(s)) names.add(s); i = j-1; } return names; } static boolean findFunctionInvocations_debug = false; // these prefix tokens mark a non-invocation (TODO: expand) static Set findFunctionInvocations_pre = new HashSet(litlist(".", "void", "S", "String", "int", "bool", "boolean", "A", "Object", "O")); static Set findFunctionInvocations(String src, Map sf) { return findFunctionInvocations(javaTok(src), sf); } static Set findFunctionInvocations(List tok, Map sf) { return findFunctionInvocations(tok, sf, null); } // sf = set of functions to search for or null for any function static Set findFunctionInvocations(List tok, Map sf, Collection hardReferences) { return findFunctionInvocations(tok, sf, hardReferences, null); } static Set findFunctionInvocations(List tok, Map sf, Collection hardReferences, Set haveFunctions) { return findFunctionInvocations(tok, sf, hardReferences, haveFunctions, false); } static Set findFunctionInvocations(List tok, Map sf, Collection hardReferences, Set haveFunctions, boolean includePossiblyMapLikes) { LinkedHashSet l = new LinkedHashSet(); for (int i : jfindAll(tok, "please include functions")) { int j = i + 6; while (licensed()) { String fname = tok.get(j); assertIdentifier("in please include functions section", get(tok, j)); l.add(fname); add(hardReferences, fname); j += 2; if (eqGet(tok, j, ".")) break; if (!eqOneOf(get(tok, j), ",", "and")) throw fail("bad token 'please include functions' section: " + get(tok, j)); j += 2; } clearAllTokens(tok.subList(i, j+2)); } for (int i : jfindAll(tok, "please include function *.")) { String fname = tok.get(i+6); l.add(fname); add(hardReferences, fname); clearAllTokens(tok.subList(i, i+10)); } int i; boolean result = false; for (i = 1; i+2 < tok.size(); i += 2) { String f = tok.get(i); if (!isIdentifier(f)) continue; // main.bla() if ("main".equals(f) && eq(tok.get(i+2), ".") && eqGet(tok, i+4, "<")) { i = findEndOfTypeArgs(tok, i+4)+1; f = tok.get(i); if (!isIdentifier(f)) continue; } if (findFunctionInvocations_debug) print("Testing identifier " + f); // e.g. ... html_findLIs(LS [auto htmlTok] tok) { ... } if (eqGet(tok, i-4, "[") && eqGet(tok, i-2, "auto")) { // ok } else { if (!"(".equals(tok.get(i+2))) { if (!(includePossiblyMapLikes && eqGet(tok, i+4, "(") && isIdentifier(get(tok, i+2)))) continue; } } if (i == 1 || !findFunctionInvocations_pre.contains(tok.get(i-2)) || eq(get(tok, i-2), ".") && eq(get(tok, i-4), "main")) { boolean inSF = sf == null || sf.containsKey(f); if (findFunctionInvocations_debug) print("Possible invocation: " + f + ", inSF: " + inSF); if (inSF && !contains(haveFunctions, f) && l.add(f)) if (findFunctionInvocations_debug) print("Found reference to standard function " + f + ": " + lineAroundToken(tok, i)); } } return l; } static boolean cic(Collection l, String s) { return containsIgnoreCase(l, s); } static boolean cic(String[] l, String s) { return containsIgnoreCase(l, s); } static boolean cic(String s, char c) { return containsIgnoreCase(s, c); } static boolean cic(String a, String b) { return containsIgnoreCase(a, b); } static Set setIntersection(Set a, Collection b) { Set set = similarEmptySet(a); Set bSet = asSet(b); for (A x : a) if (bSet.contains(x)) set.add(x); return set; } static ArrayList cloneList(Iterable l) { return l instanceof Collection ? cloneList((Collection) l) : asList(l); } static ArrayList cloneList(Collection l) { if (l == null) return new ArrayList(); synchronized(collectionMutex(l)) { return new ArrayList(l); } } static long psI(String snippetID) { return parseSnippetID(snippetID); } static Set findFunctionDefs_keywords = new HashSet(splitAtSpace("static svoid ssvoid ssynchronized sbool sS sO sL")); static List findFunctionDefs(List tok) { int n = l(tok); List functions = new ArrayList(); for (int i = 1; i < n; i += 2) { String t = tok.get(i); if (findFunctionDefs_keywords.contains(t)) { int j = i+2; while (j < n && !eqOneOf(tok.get(j), ";", "=", "(", "{", "#")) j += 2; if (isIdentifier(tok.get(j-2)) && eqGet(tok, j, "(") || eqGet(tok, j, "{") && eq(t, "svoid")) functions.add(tok.get(j-2)); } } return functions; } static List getAllFutures(Collection> l) { List out = new ArrayList(l(l)); for (Future f : unnull(l)) out.add(getFuture(f)); return out; } static List includeInMainLoaded_stdReTok(List tok, String text) { List main = findMainClass(tok); if (main == null) { print(join(tok)); throw fail("no main class"); } int i = main.lastIndexOf("}"); main.set(i, "\n" + text + "\n}"); i += magicIndexOfSubList(tok, main); return reTok(tok, i, i+1); } static boolean preferCached = false; static boolean loadSnippet_debug = false; static ThreadLocal loadSnippet_silent = new ThreadLocal(); static int loadSnippet_timeout = 30000; static String loadSnippet(Snippet s) { return loadSnippet(s.id); } static String loadSnippet(String snippetID) { try { if (snippetID == null) return null; return loadSnippet(parseSnippetID(snippetID), preferCached); } catch (Exception __e) { throw rethrow(__e); } } static String loadSnippet(String snippetID, boolean preferCached) throws IOException { return loadSnippet(parseSnippetID(snippetID), preferCached); } public static String loadSnippet(long snippetID) { try { return loadSnippet(snippetID, preferCached); } catch (Exception __e) { throw rethrow(__e); } } public static String loadSnippet(long snippetID, boolean preferCached) throws IOException { String text; if (isLocalSnippetID(snippetID)) return loadLocalSnippet(snippetID); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadSnippet(fsI(snippetID)); // boss bot disabled for now for shorter transpilations /*text = getSnippetFromBossBot(snippetID); if (text != null) return text;*/ initSnippetCache(); text = DiskSnippetCache_get(snippetID); if (preferCached && text != null) return text; try { if (loadSnippet_debug && text != null) System.err.println("md5: " + md5(text)); String url = tb_mainServer() + "/getraw.php?id=" + snippetID + "&utf8=1"; if (nempty(text)) url += "&md5=" + md5(text); url += standardCredentials(); String text2 = loadSnippet_loadFromServer(url); boolean same = eq(text2, "==*#*=="); if (loadSnippet_debug) print("loadSnippet: same=" + same); if (!same) text = text2; } catch (RuntimeException e) { e.printStackTrace(); throw new IOException("Snippet #" + snippetID + " not found or not public"); } try { initSnippetCache(); DiskSnippetCache_put(snippetID, text); } catch (IOException e) { System.err.println("Minor warning: Couldn't save snippet to cache (" + DiskSnippetCache_getDir() + ")"); } return text; } static File DiskSnippetCache_dir; public static void initDiskSnippetCache(File dir) { DiskSnippetCache_dir = dir; dir.mkdirs(); } public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException { return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null); } private static File DiskSnippetCache_getFile(long snippetID) { return new File(DiskSnippetCache_dir, "" + snippetID); } public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException { saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet); } public static File DiskSnippetCache_getDir() { return DiskSnippetCache_dir; } public static void initSnippetCache() { if (DiskSnippetCache_dir == null) initDiskSnippetCache(getGlobalCache()); } static String loadSnippet_loadFromServer(String url) { Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_timeout); try { return isTrue(loadSnippet_silent.get()) ? loadPageSilently(url) : loadPage(url); } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } static boolean hasUnclosedStringLiterals(String s) { for (String t : javaTokC(s)) if (isUnproperlyQuoted(t)) return true; return false; } static boolean regexpContains(String pat, String s) { return regexpFinds(pat, s); } static boolean regexpContains(Pattern pat, String s) { return regexpFinds(pat, s); } static boolean loadSnippets_verbose = false; static List loadSnippets(String... ids) { return loadSnippets(asList(ids)); } static List loadSnippets(List ids) { try { List texts = new ArrayList(); StringBuilder buf = new StringBuilder(); Map cached = new HashMap(); initSnippetCache(); for (String id : ids) { long snippetID = psI(id); String text = DiskSnippetCache_get(snippetID); String md5 = text != null ? md5(text) : "."; if (loadSnippets_verbose) print(id + " => " + md5 + " - " + quote(shorten(text, 20))); mapPut(cached, snippetID, text); buf.append(snippetID).append(" ").append(md5).append(" "); } if (loadSnippets_verbose) print("loadSnippets post data: " + buf); Map map = jsonDecodeMap(doPost( "ids=" + urlencode(trim(str(buf))) + standardCredentials(), tb_mainServer() + "/get-multi2.php")); for (String id : ids) { long snippetID = psI(id); Object result = map.get(str(snippetID)); if (loadSnippets_verbose) print(id + " => " + className(result)); if (result instanceof String) { texts.add((String) result); DiskSnippetCache_put(snippetID, (String) result); } else texts.add(cached.get(snippetID)); } return texts; } catch (Exception __e) { throw rethrow(__e); } } static List> innerClassesOfMain(List tok) { return innerClasses(findMainClass(tok)); } static List> innerClassesOfMain(String src) { return innerClassesOfMain(javaTok(src)); } static String getClassDeclarationName(List tok) { if (tok != null) for (int i = 1; i+2 < tok.size(); i += 2) if (allClasses_keywords.contains(tok.get(i)) && isIdentifier(tok.get(i+2))) { if (eqGet(tok, i+2, "noeq")) i += 2; return tok.get(i+2); } return null; } static List tok_importedClassNames(List tok) { List names = new ArrayList(); int n = l(tok); for (int i = 1; i < n; i += 2) if (eq(tok.get(i), "import") /*&& neq(get(tok, i+2), "static")*/) { // static may be OK, e.g. import static x30_pkg.x30_util.VF1; int j = findEndOfStatement(tok, i); // index of ;+1 String s = get(tok, j-3); // This is to distinguish from imported functions; // yes it's rough. if (isIdentifier(s) && startsWithUpperCase(s)) names.add(s); i = j-1; } return names; } static Set usualJavaClassNames_set = asHashSet(javaTokC("\r\n String Object Map List Integer Long Collection File Component JComponent JButton\r\n JCheckBox Float JTextArea JTextComponent JFrame JPanel JInternalFrame\r\n Number\r\n")); static Set usualJavaClassNames() { return usualJavaClassNames_set; } static List tlft_j(String text) { return toLinesFullTrim_java(text); } static Set tokenIndexWithoutIfclass_forStdClasses(List tok) { HashSet set = new HashSet(); int n = l(tok); int level = 0; for (int i = 1; i < n; i += 2) { String t = tok.get(i); if (eqOneOf_twoNonNullStrings(t, "ifclass", "ifndef")) ++level; else if (eqOneOf_twoNonNullStrings(t, "endif", "endifndef")) --level; else if (level <= 0 && startsWithJavaIdentifierStart(t) && !eqOneOf_twoNonNullStrings(get(tok, i-2), ".", "virtual")) set.add(t); } return set; } static Set keys(Map map) { return map == null ? new HashSet() : map.keySet(); } static Set keys(Object map) { return keys((Map) map); } static Set keys(MultiSet ms) { return ms.keySet(); } static Collection values(Map map) { return map == null ? emptyList() : map.values(); } static String joinWithSpace(Collection c) { return join(" ", c); } static String joinWithSpace(String... c) { return join(" ", c); } static String fsI(String id) { return formatSnippetID(id); } static String fsI(long id) { return formatSnippetID(id); } static HashSet allClasses_keywords = lithashset("class", "interface", "enum", "sclass", "sinterface", "record", "srecord", "asclass"); // lists returned are actual CNC (N/C/N/.../C/N) - and connected to // original list // only returns the top level classes static List> allClasses(List tok) { List> l = new ArrayList(); int n = tok.size(); HashSet _allClasses_keywords = allClasses_keywords; for (int i = 1; i < n; i += 2) { String t = tok.get(i); if ("{".equals(t)) // skip functions i = findEndOfBlock(tok, i)-1; else if (_allClasses_keywords.contains(t) && (tok_isJavaxMetaCommandLeftOf(tok, i) || !eqGetOneOf(tok, i-2, ".", "include"))) { int j = i; while (j < n && !tok.get(j).equals("{")) j += 2; j = findEndOfBlock(tok, j)+1; i = leftScanModifiers(tok, i); l.add(tok.subList(i-1, Math.min(n, j))); i = j-2; } } return l; } static List> allClasses(String text) { return allClasses(javaTok(text)); } // i = index of "implements"/"extends" static int tok_endOfImplementsList(List tok, int i) { int level = 0; while (i < l(tok)) { String t = tok.get(i); if (eq(t, "<")) ++level; else if (eq(t, ">")) { if (level == 0) return i; else --level; } else if (eq(t, "{")) return i; i += 2; } return i; } static List jfindAll(List tok, String pat) { return jfindAll(tok, jfind_preprocess(javaTok(pat))); } // tokPat must be jfind_preprocess'd static List jfindAll(List tok, List tokPat) { String[] toks = toStringArray(codeTokensOnly(tokPat)); int i = -1; List l = new ArrayList(); while ((i = findCodeTokens(tok, i+1, false, toks)) >= 0) l.add(i); return l; } static boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static boolean contains(String s, char c) { return s != null && s.indexOf(c) >= 0; } static boolean contains(String s, String b) { return s != null && s.indexOf(b) >= 0; } static boolean contains(BitSet bs, int i) { return bs != null && bs.get(i); } static A last(List l) { return empty(l) ? null : l.get(l.size()-1); } static char last(String s) { return empty(s) ? '#' : s.charAt(l(s)-1); } static int last(int[] a) { return l(a) != 0 ? a[l(a)-1] : 0; } static A last(A[] a) { return l(a) != 0 ? a[l(a)-1] : null; } static A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static int jfindOneOf_cond(List tok, Object condition, String... patterns) { for (String in : patterns) { int i = jfind(tok, in, condition); if (i >= 0) return i; } return -1; } static String joinQuoted(String sep, Collection c) { List l = new ArrayList(); for (String s : c) l.add(quote(s)); return join(sep, l); } static int rjfind(List tok, String in) { return rjfind(tok, 1, in); } static int rjfind(List tok, int startIdx, String in) { return rjfind(tok, startIdx, in, null); } static int rjfind(List tok, String in, Object condition) { return rjfind(tok, 1, in, condition); } static int rjfind(List tok, int startIdx, String in, Object condition) { List tokin = javaTok(in); jfind_preprocess(tokin); return rjfind(tok, startIdx, tokin, condition); } // assumes you preprocessed tokin static int rjfind(List tok, List tokin) { return rjfind(tok, 1, tokin); } static int rjfind(List tok, int startIdx, List tokin) { return rjfind(tok, startIdx, tokin, null); } static int rjfind(List tok, int startIdx, List tokin, Object condition) { return rfindCodeTokens(tok, startIdx, false, toStringArray(codeTokensOnly(tokin)), condition); } // returns l(s) if not found static int smartIndexOf(String s, String sub, int i) { if (s == null) return 0; i = s.indexOf(sub, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, int i, char c) { return smartIndexOf(s, c, i); } static int smartIndexOf(String s, char c, int i) { if (s == null) return 0; i = s.indexOf(c, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, String sub) { return smartIndexOf(s, sub, 0); } static int smartIndexOf(String s, char c) { return smartIndexOf(s, c, 0); } static int smartIndexOf(List l, A sub) { return smartIndexOf(l, sub, 0); } static int smartIndexOf(List l, int start, A sub) { return smartIndexOf(l, sub, start); } static int smartIndexOf(List l, A sub, int start) { int i = indexOf(l, sub, start); return i < 0 ? l(l) : i; } static void tok_addFieldOrder(List tok, int i) { if (!contains(tok_modifiersLeftOf(tok, i), "static")) return; // no static fields allowed in non-static classes (for whatever reason) int idx = findCodeTokens(tok, i, false, "{"); if (idx < 0) return; int j = findEndOfBracketPart(tok, idx); List vars = allVarNames(subList(tok, idx+1, j-1)); //print("addFieldOrder " + struct(vars)); if (nempty(vars) && !vars.contains("_fieldOrder") && !isSortedList(vars)) { print("Adding field order"); tok.set(idx+2, "static String _fieldOrder = " + quote(join(" ", vars)) + ";\n " + tok.get(idx+2)); // reTok has to be done by caller } } static int smartIndexOfOneOf(List l, int i, A... x) { return smartIndexOfAny(l, i, x); } static int smartIndexOfOneOf(List l, A... x) { return smartIndexOfAny(l, x); } static void vmKeepWithProgramMD5_save(String varName) { if (vmExiting()) return; String struct = struct(getOpt(mc(), varName)); callOpt(javax(), "vmKeep_store", programID(), md5OfMyJavaSource(), varName, struct(getOpt(mc(), varName))); } static void clearTokensAndReTok(List tok, int i, int j) { clearTokens_reTok(tok, i, j); } static void clearTokens_reTok(List tok, int i, int j) { clearTokens(tok, i, j); reTok(tok, i, j); } static IntRange combineIntRanges(IntRange a, IntRange b) { if (a == null) return b; if (b == null) return a; return intRange(min(a.start, b.start), max(a.end, b.end)); } static IntRange intRange(int start, int end) { return new IntRange(start, end); } static Object call(Object o) { return callF(o); } // varargs assignment fixer for a single string array argument static Object call(Object o, String method, String[] arg) { return call(o, method, new Object[] {arg}); } static Object call(Object o, String method, Object... args) { //ret call_cached(o, method, args); return call_withVarargs(o, method, args); } static TreeMap hotwireCached_cache = new TreeMap(); static Lock hotwireCached_lock = lock(); static Class hotwireCached(String programID) { return hotwireCached(programID, true); } static Class hotwireCached(String programID, boolean runMain) { return hotwireCached(programID, runMain, false); } static Class hotwireCached(String programID, boolean runMain, boolean dependent) { Lock __554 = hotwireCached_lock; lock(__554); try { programID = formatSnippetID(programID); Class c = hotwireCached_cache.get(programID); if (c == null) { c = hotwire(programID); if (dependent) makeDependent(c); if (runMain) callMain(c); hotwireCached_cache.put(programID, c); } return c; } finally { unlock(__554); } } static String standardFunctionSnippet(String sfName) { return lookupStandardFunction(sfName); } static String assertIdentifier(String s) { return assertIsIdentifier(s); } static String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } static void tok_runMetaTransformer(List tok, String transformer) { print("META-TRANSFORM " + transformer); call(hotwireCached(standardFunctionSnippet(assertIdentifier(transformer))), transformer, tok); } static int loadPage_defaultTimeout = 60000; static ThreadLocal loadPage_charset = new ThreadLocal(); static boolean loadPage_allowGzip = true, loadPage_debug; static boolean loadPage_anonymous = false; // don't send computer ID static int loadPage_verboseness = 100000; static int loadPage_retries = 1; //60; // seconds static ThreadLocal loadPage_silent = new ThreadLocal(); static volatile int loadPage_forcedTimeout; // ms static ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); // ms static ThreadLocal>> loadPage_responseHeaders = new ThreadLocal(); static ThreadLocal> loadPage_extraHeaders = new ThreadLocal(); public static String loadPageSilently(String url) { try { return loadPageSilently(new URL(loadPage_preprocess(url))); } catch (Exception __e) { throw rethrow(__e); } } public static String loadPageSilently(URL url) { try { if (url.getProtocol().equals("https")) disableCertificateValidation(); if (!networkAllowanceTest(str(url))) throw fail("Not allowed: " + url); IOException e = null; for (int tries = 0; tries < loadPage_retries; tries++) try { URLConnection con = loadPage_openConnection(url); return loadPage(con, url); } catch (IOException _e) { e = _e; if (loadPageThroughProxy_enabled) { print("Trying proxy because of: " + e); try { return loadPageThroughProxy(str(url)); } catch (Throwable e2) { print(" " + exceptionToStringShort(e2)); } } else if (loadPage_debug) print(exceptionToStringShort(e)); if (tries < loadPage_retries-1) sleepSeconds(1); } throw e; } catch (Exception __e) { throw rethrow(__e); } } static String loadPage_preprocess(String url) { if (url.startsWith("tb/")) // don't think we use this anymore url = tb_mainServer() + "/" + url; if (url.indexOf("://") < 0) url = "http://" + url; return url; } static String loadPage(String url) { try { url = loadPage_preprocess(url); if (!isTrue(loadPage_silent.get())) printWithTime("Loading: " + hideCredentials(url)); return loadPageSilently(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static String loadPage(URL url) { return loadPage(url.toExternalForm()); } static String loadPage(URLConnection con, URL url) throws IOException { return loadPage(con, url, true); } static String loadPage(URLConnection con, URL url, boolean addHeaders) throws IOException { Map extraHeaders = getAndClearThreadLocal(loadPage_extraHeaders); if (addHeaders) try { if (!loadPage_anonymous) setHeaders(con); if (loadPage_allowGzip) con.setRequestProperty("Accept-Encoding", "gzip"); con.setRequestProperty("X-No-Cookies", "1"); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); } catch (Throwable e) {} // fails if within doPost vm_generalSubMap("URLConnection per thread").put(currentThread(), con); loadPage_responseHeaders.set(con.getHeaderFields()); InputStream in = null; try { in = urlConnection_getInputStream(con); //vm_generalSubMap("InputStream per thread").put(currentThread(), in); if (loadPage_debug) print("Put stream in map: " + currentThread()); String contentType = con.getContentType(); if (contentType == null) { //printStruct("Headers: ", con.getHeaderFields()); throw new IOException("Page could not be read: " + hideCredentials(url)); } //print("Content-Type: " + contentType); String charset = loadPage_charset == null ? null : loadPage_charset.get(); if (charset == null) charset = loadPage_guessCharset(contentType); if ("gzip".equals(con.getContentEncoding())) { if (loadPage_debug) print("loadPage: Using gzip."); in = newGZIPInputStream(in); } Reader r; try { r = new InputStreamReader(in, unquote(charset)); } catch (UnsupportedEncodingException e) { print(toHex(utf8(charset))); throw e; } boolean silent = isTrue(loadPage_silent.get()); StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; if (!silent && (n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { if (loadPage_debug) print("loadPage done"); //vm_generalSubMap("InputStream per thread").remove(currentThread()); vm_generalSubMap("URLConnection per thread").remove(currentThread()); if (in != null) in.close(); } } static String loadPage_guessCharset(String contentType) { Matcher m = regexpMatcher("text/[a-z]+;\\s*charset=([^\\s]+)\\s*", contentType); String match = m.matches() ? m.group(1) : null; if (loadPage_debug) print("loadPage: contentType=" + contentType + ", match: " + match); /* If Content-Type doesn't match this pre-conception, choose default and hope for the best. */ //return or(match, "ISO-8859-1"); return or(match, "UTF-8"); } static URLConnection loadPage_openConnection(URL url) { URLConnection con = openConnection(url); int timeout = toInt(loadPage_forcedTimeout_byThread.get()); if (timeout == 0) timeout = loadPage_forcedTimeout; if (timeout != 0) setURLConnectionTimeouts(con, loadPage_forcedTimeout); else setURLConnectionDefaultTimeouts(con, loadPage_defaultTimeout); return con; } static Throwable printStackTrace2(Throwable e) { // we go to system.out now - system.err is nonsense print(getStackTrace2(e)); return e; } static void printStackTrace2() { printStackTrace2(new Throwable()); } static void printStackTrace2(String msg) { printStackTrace2(new Throwable(msg)); } // JavaParser static CompilationUnit javaParseCompilationUnit(String java) { JavaParser.getStaticConfiguration().setAttributeComments(false); return JavaParser.parse(java); } static Field getOpt_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Field makeAccessible(Field f) { try { f.setAccessible(true); } catch (Throwable e) { // Note: The error reporting only works with Java VM option --illegal-access=deny vmBus_send("makeAccessible_error",e, f); } return f; } static Method makeAccessible(Method m) { try { m.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error",e, m); } return m; } static Constructor makeAccessible(Constructor c) { try { c.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error",e, c); } return c; } static RuntimeException asRuntimeException(Throwable t) { if (t instanceof Error) _handleError((Error) t); return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static ArrayList emptyList() { return new ArrayList(); //ret Collections.emptyList(); } static ArrayList emptyList(int capacity) { return new ArrayList(max(0, capacity)); } // Try to match capacity static ArrayList emptyList(Iterable l) { return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList(); } static ArrayList emptyList(Object[] l) { return emptyList(l(l)); } // get correct type at once static ArrayList emptyList(Class c) { return new ArrayList(); } static Object callOpt(Object o) { return callF(o); } static A callOpt(Object o, String method, Object... args) { return (A) callOpt_withVarargs(o, method, args); } static Object getOptMC(String field) { return getOpt(mc(), field); } static Set asSet(Object[] array) { HashSet set = new HashSet(); for (Object o : array) if (o != null) set.add(o); return set; } static Set asSet(String[] array) { TreeSet set = new TreeSet(); for (String o : array) if (o != null) set.add(o); return set; } static Set asSet(Iterable l) { if (l instanceof Set) return (Set) l; HashSet set = new HashSet(); for (A o : unnull(l)) if (o != null) set.add(o); return set; } static A printStackTrace(A e) { // we go to system.out now - system.err is nonsense print(getStackTrace(e)); return e; } static void printStackTrace() { printStackTrace(new Throwable()); } static void printStackTrace(String msg) { printStackTrace(new Throwable(msg)); } static void printStackTrace(String msg, Throwable e) { printStackTrace(new Throwable(msg, e)); } static void lockOrFail(Lock lock, long timeout) { try { ping(); if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) { String s = "Couldn't acquire lock after " + timeout + " ms."; if (lock instanceof ReentrantLock) { ReentrantLock l = (ReentrantLock) lock; s += " Hold count: " + l.getHoldCount() + ", owner: " + call(l, "getOwner"); } throw fail(s); } ping(); } catch (Exception __e) { throw rethrow(__e); } } static ReentrantLock fairLock() { return new ReentrantLock(true); } static Map newWeakHashMap() { return _registerWeakMap(synchroMap(new WeakHashMap())); } // TODO: test if android complains about this static boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static void failIfUnlicensed() { assertTrue("license off", licensed()); } static Thread currentThread() { return Thread.currentThread(); } static void _handleError(Error e) { call(javax(), "_handleError", e); } static String readLineHidden() { try { if (get(javax(), "readLine_reader") == null) set(javax(), "readLine_reader" , new BufferedReader(new InputStreamReader(System.in, "UTF-8"))); try { return ((BufferedReader) get(javax(), "readLine_reader")).readLine(); } finally { consoleClearInput(); } } catch (Exception __e) { throw rethrow(__e); } } // This is made for NL parsing. // It's javaTok extended with "..." token, "$n" and "#n" and // special quotes (which are converted to normal ones). static List javaTokPlusPeriod(String s) { List tok = new ArrayList(); if (s == null) return tok; int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j+2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); cc = s.substring(i, Math.min(i+2, l)); // scan for non-whitespace if (c == (char) 0x201C || c == (char) 0x201D) c = '"'; // normalize quotes if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { char _c = s.charAt(j); if (_c == (char) 0x201C || _c == (char) 0x201D) _c = '"'; // normalize quotes if (_c == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } if (j-1 >= i+1) { tok.add(opener + s.substring(i+1, j-1) + opener); i = j; continue; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); // for things like "this one's" else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (cc.equals("[=") && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else if (s.substring(j, Math.min(j+3, l)).equals("...")) j += 3; else if (c == '$' || c == '#') do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static boolean isNonNegativeInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1)); } static void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions ) ping_impl(true); } static ThreadLocal print_byThread_dontCreate() { return print_byThread; } static boolean isFalse(Object o) { return eq(false, o); } static String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i+1 < l && s.charAt(i+1) == '\n') ++i; } } return out.toString(); } static void print_append(Appendable buf, String s, int max) { try { synchronized(buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static int min(int a, int b) { return Math.min(a, b); } static long min(long a, long b) { return Math.min(a, b); } static float min(float a, float b) { return Math.min(a, b); } static float min(float a, float b, float c) { return min(min(a, b), c); } static double min(double a, double b) { return Math.min(a, b); } static double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static B mapGet(Map map, A a) { return map == null || a == null ? null : map.get(a); } static B mapGet(A a, Map map) { return map == null || a == null ? null : map.get(a); } static String loadCachedTranspilation(String id) { try { return loadTextFilePossiblyGZipped(getCachedTranspilationFile(id)); } catch (Throwable __e) { return null; } } static boolean machineIsOffline() { return isFalse(callF(vmGeneralMap_get("areWeOnline"))); } static boolean isOfflineMode() { return eq("1", trim(loadProgramTextFile("#1005806", "offline-mode"))); } static boolean isLocalSnippet(String snippetID) { return isLocalSnippetID(snippetID); } static boolean isLocalSnippet(long snippetID) { return isLocalSnippetID(snippetID); } static String getServerTranspiled(String snippetID) { return getServerTranspiled(snippetID, null); } static boolean getServerTranspiled_printStackTrace = false; // returns "SAME" if md5 matches static String getServerTranspiled(String snippetID, String expectedMD5) { try { if (getServerTranspiled_printStackTrace) printStackTrace(); long id = parseSnippetID(snippetID); /*S t = getTranspilationFromBossBot(id); if (t != null) return t;*/ String text = loadPage_utf8(tb_mainServer() + "/tb-int/get-transpiled.php?raw=1&withlibs=1&id=" + id + "&utf8=1" + (l(expectedMD5) > 1 ? "&md5=" + urlencode(expectedMD5) : "") + standardCredentials()); if (nempty(text) && neq(text, "SAME")) saveTranspiledCode(snippetID, text); return text; } catch (Exception __e) { throw rethrow(__e); } } static void printExceptionShort(Throwable e) { print(exceptionToStringShort(e)); } static B mapPut_returnValue(Map map, A key, B value) { mapPut(map, key, value); return value; } static int iteratorCount_int_close(Iterator i) { try { int n = 0; if (i != null) while (i.hasNext()) { i.next(); ++n; } if (i instanceof AutoCloseable) ((AutoCloseable) i).close(); return n; } catch (Exception __e) { throw rethrow(__e); } } public static String bytesToHex(byte[] bytes) { return bytesToHex(bytes, 0, bytes.length); } public static String bytesToHex(byte[] bytes, int ofs, int len) { StringBuilder stringBuilder = new StringBuilder(len*2); for (int i = 0; i < len; i++) { String s = "0" + Integer.toHexString(bytes[ofs+i]); stringBuilder.append(s.substring(s.length()-2, s.length())); } return stringBuilder.toString(); } static byte[] toUtf8(String s) { try { return s.getBytes("UTF-8"); } catch (Exception __e) { throw rethrow(__e); } } static boolean md5OfFile_verbose = false; static String md5OfFile(String path) { return md5OfFile(newFile(path)); } static String md5OfFile(File f) { try { if (!f.exists()) return "-"; if (md5OfFile_verbose) print("Getting MD5 of " + f); MessageDigest md5 = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(f); try { byte buf[] = new byte[65536]; int l; while (true) { l = in.read(buf); if (l <= 0) break; md5.update(buf, 0, l); } return bytesToHex(md5.digest()); } finally { _close(in); }} catch (Exception __e) { throw rethrow(__e); } } static String formatSnippetIDOpt(String s) { return isSnippetID(s) ? formatSnippetID(s) : s; } static List reversedList(Collection l) { List x = cloneList(l); Collections.reverse(x); return x; } static List findBlock(String pat, List tok) { List tokpat = javaTok(pat); int i = findCodeTokens(tok, toStringArray(codeTokensOnly(tokpat))); //print("index of block " + quote(pat) + ": " + i); if (i < 0) return null; int bracketIdx = i+tokpat.size()-3; assertEquals("{", tok.get(bracketIdx)); int endIdx = findEndOfBlock(tok, bracketIdx); return subList(tok, i-1, endIdx+1); // make it actual CNC } static String javaTok_substringN(String s, int i, int j) { if (i == j) return ""; if (j == i+1 && s.charAt(i) == ' ') return " "; return s.substring(i, j); } static String javaTok_substringC(String s, int i, int j) { return s.substring(i, j); } static List javaTokWithExisting(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i+2 < l && "'\\".indexOf(s.charAt(i+2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener /*|| s.charAt(j) == '\n'*/) { // allow multi-line strings ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else if (c == '[' && d == '[') { do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]")); j = Math.min(j+2, l); } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') { do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]")); j = Math.min(j+3, l); } else ++j; if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) { return t.length() == j-i && s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave } static String dummyMainClassName(String progID) { return "m" + psI(progID); } static Class __javax; static Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static Field setOpt_findField(Class c, String field) { HashMap map; synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map.get(field); } static void setOpt(Object o, String field, Object value) { try { if (o == null) return; Class c = o.getClass(); HashMap map; if (getOpt_cache == null) map = getOpt_makeCache(c); // in class init else synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) { setOpt((Class) o, field, value); return; } // It's probably a subclass of Map. Use raw method setOpt_raw(o, field, value); return; } Field f = map.get(field); if (f != null) { smartSet(f, o, value); return; } // possible improvement: skip setAccessible if (o instanceof DynamicObject) setDyn(((DynamicObject) o), field, value); } catch (Exception __e) { throw rethrow(__e); } } static void setOpt(Class c, String field, Object value) { if (c == null) return; try { Field f = setOpt_findStaticField(c, field); // TODO: optimize if (f != null) smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field setOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(f); return f; } _c = _c.getSuperclass(); } while (_c != null); return null; } static File tempDir() { return makeTempDir(); } static String tok_packageName(List tok) { int i = jfind(tok, "package"); if (i < 0) return ""; i += 2; int j = jfind(tok, i, ";"); if (j < 0) return ""; return join(codeTokensOnly(subList(tok, i-1, j))); } static String tok_firstClassName(List tok) { int i = jfind(tok, "class "); return i < 0 ? null : tok.get(i+2); } /** writes safely (to temp file, then rename) */ static File saveTextFile(String fileName, String contents) throws IOException { CriticalAction action = beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)"); try { File file = new File(fileName); mkdirsForFile(file); String tempFileName = fileName + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); vmBus_send("wroteFile", file); return file; } finally { action.done(); } } static File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static File tempDirPossiblyInRAMDisk() { File f = linux_fileInRamDisk(aGlobalID()); if (f != null) { f.mkdirs(); return f; } return makeTempDir(); } static boolean loadLibraryOrSrcLib_srcLibsEnabled = true; // to avoid checking src libs too often when booting OS static ThreadLocal> loadLibraryOrSrcLib_tempCache = new ThreadLocal(); static File loadLibraryOrSrcLib(String snippetID) { try { long id = parseSnippetID(snippetID); if (loadLibraryOrSrcLib_tempCache.get() != null) { File f = loadLibraryOrSrcLib_tempCache.get().get(id); if (f != null) return f; } boolean srcLib = loadLibraryOrSrcLib_srcLibsEnabled && isMarkedAsSrcLib(snippetID); if (srcLib) { File f = pairA(hotwire_compile(snippetID)); mapPut(loadLibraryOrSrcLib_tempCache.get(), id, f); } File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) != 0) return f; try { return loadDataSnippetToFile(snippetID); } catch (Throwable e) { if (loadLibraryOrSrcLib_srcLibsEnabled && nempty(loadSnippet(snippetID))) { markAsSrcLib(snippetID); return pairA(hotwire_compile(snippetID)); } throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static File pathToJavaxJar() { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.pathToJavaXJar(); int x = latestInstalledJavaX(); File xfile = new File(userHome(), ".javax/x" + Math.max(x, 30) + ".jar"); if (!xfile.isFile()) { print("Saving " + f2s(xfile)); String url = x30JarServerURL(); byte[] data = loadBinaryPage(url); if (data.length < 1000000) throw fail("Could not load " + url); saveBinaryFile(xfile.getPath(), data); } return xfile; } catch (Exception __e) { throw rethrow(__e); } } static String indentx(String s) { return indentx(indent_default, s); } static String indentx(int n, String s) { return dropSuffix(repeat(' ', n), indent(n, s)); } static String indentx(String indent, String s) { return dropSuffix(indent, indent(indent, s)); } static String cleanJavaCompilerOutput(String s) { return dropPrefixTrim("Annotation processing got disabled, since it requires a 1.6 compliant JVM", s); } static boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] {substring(a, l(b))}; return true; } static String appendWithNewLine(String a, String b) { if (empty(b)) return a; if (empty(a)) return b; return addSuffix(a, "\n") + b; } static boolean anyFileWithExtensionInDir(File dir, String ext) { return nempty(filesWithExtension(ext, findAllFiles_noDirs(dir))); } static boolean dir2zip_recurse_verbose = false; static int dir2zip_recurse(File inDir, File zip) { return dir2zip_recurse(inDir, zip, ""); } // TODO: the zero files case? static int dir2zip_recurse(File inDir, File zip, String outPrefix) { try { mkdirsForFile(zip); FileOutputStream fout = newFileOutputStream(zip); ZipOutputStream outZip = new ZipOutputStream(fout); try { return dir2zip_recurse(inDir, outZip, outPrefix, 0); } finally { outZip.close(); } } catch (Exception __e) { throw rethrow(__e); } } static int dir2zip_recurse(File inDir, ZipOutputStream outZip) { return dir2zip_recurse(inDir, outZip, "", 0); } static int dir2zip_recurse(File inDir, ZipOutputStream outZip, String outPrefix, int level) { try { if (++level >= 20) throw fail("woot? 20 levels in zip?"); List files = new ArrayList(); for (File f : listFiles(inDir)) files.add(f); int n = 0; sortFilesByName(files); for (File f : files) { if (f.isDirectory()) { print("dir2zip_recurse: Scanning " + f.getAbsolutePath()); n += dir2zip_recurse(f, outZip, outPrefix + f.getName() + "/", level); } else { if (dir2zip_recurse_verbose) print("Copying " + f.getName()); outZip.putNextEntry(new ZipEntry(outPrefix + f.getName())); InputStream fin = new FileInputStream(f); copyStream(fin, outZip); fin.close(); ++n; } } return n; } catch (Exception __e) { throw rethrow(__e); } } static boolean isInRAMDisk(File f) { return startsWith(f2s(f), "/dev/shm"); } static void deleteDirectory(File dir) { deleteDirectory(dir, false, false); } static void deleteDirectory(File dir, boolean verbose, boolean testRun) { deleteAllFilesInDirectory(dir, verbose, testRun); if (verbose) print((testRun ? "Would delete " : "Deleting ") + dir.getAbsolutePath()); if (!testRun) dir.delete(); } static void closeRandomAccessFile(RandomAccessFile f) { if (f != null) try { f.close(); callJavaX("dropIO", f); } catch (Throwable e) { printStackTrace(e); } } static RandomAccessFile newRandomAccessFile(File path, String mode) throws IOException { boolean forWrite = mode.indexOf('w') >= 0; if (forWrite) mkdirsForFile(path); RandomAccessFile f = new RandomAccessFile(path, mode); callJavaX("registerIO", f, path, forWrite); return f; } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { // is null if file is in current dir dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static boolean isLowerHexString(String s) { for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { // ok } else return false; } return true; } static String actualUserHome_value; static String actualUserHome() { if (actualUserHome_value == null) { if (isAndroid()) actualUserHome_value = "/storage/emulated/0/"; else actualUserHome_value = System.getProperty("user.home"); } return actualUserHome_value; } static File actualUserHome(String sub) { return newFile(new File(actualUserHome()), sub); } static String _userHome; static String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static File userHome(String path) { return new File(userDir(), path); } static int strL(String s) { return s == null ? 0 : s.length(); } static TreeSet caseInsensitiveSet() { return caseInsensitiveSet_treeSet(); } static TreeSet caseInsensitiveSet(Collection c) { return caseInsensitiveSet_treeSet(c); } static AutoInitVar < String > md5OfMyJavaSource_cache = new AutoInitVar(new F0() { String get() { try { return md5(myJavaSource()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret md5(myJavaSource());"; }}); static String md5OfMyJavaSource() { return md5OfMyJavaSource_cache.get(); } static Class mc() { return main.class; } static Object unstructure(String text) { return unstructure(text, false); } static Object unstructure(String text, final boolean allDynamic) { return unstructure(text, allDynamic, null); } static int structure_internStringsLongerThan = 50; static int unstructure_unquoteBufSize = 100; static int unstructure_tokrefs; // stats abstract static class unstructure_Receiver { abstract void set(Object o); } // classFinder: func(name) -> class (optional) static Object unstructure(String text, boolean allDynamic, Object classFinder) { if (text == null) return null; return unstructure_tok(javaTokC_noMLS_iterator(text), allDynamic, classFinder); } static Object unstructure_reader(BufferedReader reader) { return unstructure_tok(javaTokC_noMLS_onReader(reader), false, null); } static Object unstructure_tok(final Producer tok, final boolean allDynamic, final Object _classFinder) { final boolean debug = unstructure_debug; final class X { int i = -1; final Object classFinder = _classFinder != null ? _classFinder : _defaultClassFinder(); HashMap refs = new HashMap(); HashMap tokrefs = new HashMap(); HashSet concepts = new HashSet(); HashMap classesMap = new HashMap(); List stack = new ArrayList(); String curT; char[] unquoteBuf = new char[unstructure_unquoteBufSize]; String unquote(String s) { return unquoteUsingCharArray(s, unquoteBuf); } // look at current token String t() { return curT; } // get current token, move to next String tpp() { String t = curT; consume(); return t; } void parse(final unstructure_Receiver out) { String t = t(); int refID = 0; if (structure_isMarker(t, 0, l(t))) { refID = parseInt(t.substring(1)); consume(); } final int _refID = refID; // if (debug) print("parse: " + quote(t)); final int tokIndex = i; parse_inner(refID, tokIndex, new unstructure_Receiver() { void set(Object o) { if (_refID != 0) refs.put(_refID, o); if (o != null) tokrefs.put(tokIndex, o); out.set(o); } }); } void parse_inner(int refID, int tokIndex, final unstructure_Receiver out) { String t = t(); // if (debug) print("parse_inner: " + quote(t)); Class c = classesMap.get(t); if (c == null) { if (t.startsWith("\"")) { String s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan); out.set(s); return; } if (t.startsWith("'")) { out.set(unquoteCharacter(tpp())); return; } if (t.equals("bigint")) { out.set(parseBigInt()); return; } if (t.equals("d")) { out.set(parseDouble()); return; } if (t.equals("fl")) { out.set(parseFloat()); return; } if (t.equals("sh")) { consume(); t = tpp(); if (t.equals("-")) { t = tpp(); out.set((short) (-parseInt(t))); return; } out.set((short) parseInt(t)); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t)); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("false") || t.equals("f")) { consume(); out.set(false); return; } if (t.equals("true") || t.equals("t")) { consume(); out.set(true); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t)); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("File")) { consume(); File f = new File(unquote(tpp())); out.set(f); return; } if (t.startsWith("r") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = refs.get(ref); if (o == null) throw fail("unsatisfied back reference " + ref); out.set(o); return; } if (t.startsWith("t") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = tokrefs.get(ref); if (o == null) throw fail("unsatisfied token reference " + ref + " at " + tokIndex); out.set(o); return; } if (t.equals("hashset")) { parseHashSet(out); return; } if (t.equals("lhs")) { parseLinkedHashSet(out); return; } if (t.equals("treeset")) { parseTreeSet(out); return; } if (t.equals("ciset")) { parseCISet(out); return; } if (eqOneOf(t, "hashmap", "hm")) { consume(); parseMap(new HashMap(), out); return; } if (t.equals("lhm")) { consume(); parseMap(new LinkedHashMap(), out); return; } if (t.equals("tm")) { consume(); parseMap(new TreeMap(), out); return; } if (t.equals("cimap")) { consume(); parseMap(ciMap(), out); return; } if (t.equals("ll")) { consume(); { parseList(new LinkedList(), out); return; } } if (t.equals("syncLL")) { // legacy consume(); { parseList(synchroLinkedList(), out); return; } } if (t.equals("sync")) { consume(); { parse(new unstructure_Receiver() { void set(Object value) { if (value instanceof Map) { // Java 7 if (value instanceof NavigableMap) { out.set(Collections.synchronizedNavigableMap((NavigableMap) value)); return; } if (value instanceof SortedMap) { out.set(Collections.synchronizedSortedMap((SortedMap) value)); return; } { out.set(Collections.synchronizedMap((Map) value)); return; } } else { out.set(Collections.synchronizedList((List) value)); return; } } }); return; } } if (t.equals("{")) { parseMap(out); return; } if (t.equals("[")) { this.parseList(new ArrayList(), out); return; } if (t.equals("bitset")) { parseBitSet(out); return; } if (t.equals("array") || t.equals("intarray")) { parseArray(out); return; } if (t.equals("ba")) { consume(); String hex = unquote(tpp()); out.set(hexToBytes(hex)); return; } if (t.equals("boolarray")) { consume(); int n = parseInt(tpp()); String hex = unquote(tpp()); out.set(boolArrayFromBytes(hexToBytes(hex), n)); return; } if (t.equals("class")) { out.set(parseClass()); return; } if (t.equals("l")) { parseLisp(out); return; } if (t.equals("null")) { consume(); out.set(null); return; } if (eq(t, "c")) { consume(); t = t(); assertTrue(isJavaIdentifier(t)); concepts.add(t); } // custom deserialization (new static method method) if (eq(t, "cu")) { consume(); t = tpp(); assertTrue(isJavaIdentifier(t)); String fullClassName = "main$" + t; Class _c = classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName); if (_c == null) throw fail("Class not found: " + fullClassName); parse(new unstructure_Receiver() { void set(Object value) { out.set(call(_c, "_deserialize", value)); } }); return; } } if (eq(t, "j")) { consume("j"); out.set(parseJava()); return; } if (c == null && !isJavaIdentifier(t)) throw new RuntimeException("Unknown token " + (i+1) + ": " + t); // any other class name (or package name) consume(); String className, fullClassName; // Is it a package name? if (eq(t(), ".")) { consume(); className = fullClassName = t + "." + assertIdentifier(tpp()); } else { className = t; fullClassName = "main$" + t; } if (c == null) { // First, find class if (allDynamic) c = null; else c = classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName); if (c != null) classesMap.put(className, c); } // Check if it has an outer reference boolean hasBracket = eq(t(), "("); if (hasBracket) consume(); boolean hasOuter = hasBracket && eq(t(), "this$1"); DynamicObject dO = null; Object o = null; final String thingName = t; if (c != null) { o = hasOuter ? nuStubInnerObject(c, classFinder) : nuEmptyObject(c); if (o instanceof DynamicObject) dO = (DynamicObject) o; } else { if (concepts.contains(t) && (c = findClass("Concept")) != null) o = dO = (DynamicObject) nuEmptyObject(c); else dO = new DynamicObject(); dO.className = className; } // Save in references list early because contents of object // might link back to main object if (refID != 0) refs.put(refID, o != null ? o : dO); tokrefs.put(tokIndex, o != null ? o : dO); // NOW parse the fields! final LinkedHashMap fields = new LinkedHashMap(); // preserve order final Object _o = o; final DynamicObject _dO = dO; if (hasBracket) { stack.add(new Runnable() { public void run() { try { if (eq(t(), ",")) consume(); if (eq(t(), ")")) { consume(")"); objRead(_o, _dO, fields, hasOuter); out.set(_o != null ? _o : _dO); } else { final String key = unquote(tpp()); String t = tpp(); if (!eq(t, "=")) throw fail("= expected, got " + t + " after " + quote(key) + " in object " + thingName /*+ " " + sfu(fields)*/); stack.add(this); parse(new unstructure_Receiver() { void set(Object value) { fields.put(key, value); /*ifdef unstructure_debug print("Got field value " + value + ", next token: " + t()); endifdef*/ //if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef unstructure_debug\r\n print(\"in object values, token: \" + t())..."; }}); } else { objRead(o, dO, fields, hasOuter); out.set(o != null ? o : dO); } } void objRead(Object o, DynamicObject dO, Map fields, boolean hasOuter) { if (o != null) { if (dO != null) { setOptAllDyn(dO, fields); } else { setOptAll_pcall(o, fields); } if (hasOuter) fixOuterRefs(o); } else for (Map.Entry e : fields.entrySet()) setDynObjectValue(dO, intern(e.getKey()), e.getValue()); if (o != null) pcallOpt_noArgs(o, "_doneLoading"); } void parseSet(final Set set, final unstructure_Receiver out) { this.parseList(new ArrayList(), new unstructure_Receiver() { void set(Object o) { set.addAll((List) o); out.set(set); } }); } void parseLisp(final unstructure_Receiver out) { throw fail("class Lisp not included"); } void parseBitSet(final unstructure_Receiver out) { consume("bitset"); consume("{"); final BitSet bs = new BitSet(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(bs); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { bs.set((Integer) o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(bs);\r\n ..."; }}); } void parseList(final List list, final unstructure_Receiver out) { consume("["); stack.add(new Runnable() { public void run() { try { if (eq(t(), "]")) { consume(); out.set(list); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { //if (debug) print("List element type: " + getClassName(o)); list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"]\")) {\r\n consume();\r\n ifdef unstructure_debug\r..."; }}); } void parseArray(final unstructure_Receiver out) { final String type = tpp(); consume("{"); final List list = new ArrayList(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(type.equals("intarray") ? toIntArray(list) : list.toArray()); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(type.equals(\"..."; }}); } Object parseClass() { consume("class"); consume("("); String name = unquote(tpp()); consume(")"); Class c = allDynamic ? null : classFinder != null ? (Class) callF(classFinder, name) : findClass_fullName(name); if (c != null) return c; DynamicObject dO = new DynamicObject(); dO.className = "java.lang.Class"; name = dropPrefix("main$", name); dO.fieldValues.put("name", name); return dO; } Object parseBigInt() { consume("bigint"); consume("("); String val = tpp(); if (eq(val, "-")) val = "-" + tpp(); consume(")"); return new BigInteger(val); } Object parseDouble() { consume("d"); consume("("); String val = unquote(tpp()); consume(")"); return Double.parseDouble(val); } Object parseFloat() { consume("fl"); String val; if (eq(t(), "(")) { consume("("); val = unquote(tpp()); consume(")"); } else { val = unquote(tpp()); } return Float.parseFloat(val); } void parseHashSet(unstructure_Receiver out) { consume("hashset"); parseSet(new HashSet(), out); } void parseLinkedHashSet(unstructure_Receiver out) { consume("lhs"); parseSet(new LinkedHashSet(), out); } void parseTreeSet(unstructure_Receiver out) { consume("treeset"); parseSet(new TreeSet(), out); } void parseCISet(unstructure_Receiver out) { consume("ciset"); parseSet(ciSet(), out); } void parseMap(unstructure_Receiver out) { parseMap(new TreeMap(), out); } Object parseJava() { String j = unquote(tpp()); Matches m = new Matches(); if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m)) return nuObject("java.awt.Color", parseInt(m.unq(0)), parseInt(m.unq(1)), parseInt(m.unq(2))); else { warn("Unknown Java object: " + j); return null; } } void parseMap(final Map map, final unstructure_Receiver out) { consume("{"); stack.add(new Runnable() { boolean v = false; Object key; public void run() { if (v) { v = false; stack.add(this); if (!eq(tpp(), "=")) throw fail("= expected, got " + t() + " in map of size " + l(map)); parse(new unstructure_Receiver() { void set(Object value) { map.put(key, value); if (eq(t(), ",")) consume(); } }); } else { if (eq(t(), "}")) { consume("}"); out.set(map); } else { v = true; stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { key = o; } }); } } // if v else } // run() }); } /*void parseSub(unstructure_Receiver out) { int n = l(stack); parse(out); while (l(stack) > n) stack }*/ void consume() { curT = tok.next(); ++i; } void consume(String s) { if (!eq(t(), s)) { /*S prevToken = i-1 >= 0 ? tok.get(i-1) : ""; S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size()))); fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");*/ throw fail(quote(s) + " expected, got " + quote(t())); } consume(); } // outer wrapper function getting first token and unwinding the stack void parse_initial(unstructure_Receiver out) { consume(); // get first token parse(out); while (nempty(stack)) popLast(stack).run(); } } Boolean b = DynamicObject_loading.get(); DynamicObject_loading.set(true); try { final Var v = new Var(); X x = new X(); x.parse_initial(new unstructure_Receiver() { void set(Object o) { v.set(o); } }); unstructure_tokrefs = x.tokrefs.size(); return v.get(); } finally { DynamicObject_loading.set(b); } } static boolean unstructure_debug = false; static List synchroList() { return Collections.synchronizedList(new ArrayList()); } static List synchroList(List l) { return Collections.synchronizedList(l); } static PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static Throwable innerException(Throwable e) { return getInnerException(e); } //static final Map> getOpt_cache = newDangerousWeakHashMap(f getOpt_special_init); static class getOpt_Map extends WeakHashMap { getOpt_Map() { if (getOpt_special == null) getOpt_special = new HashMap(); clear(); } public void clear() { super.clear(); //print("getOpt clear"); put(Class.class, getOpt_special); put(String.class, getOpt_special); } } static final Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map())); //static final Map> getOpt_cache = _registerWeakMap(synchroMap(new getOpt_Map)); static HashMap getOpt_special; // just a marker /*static void getOpt_special_init(Map map) { map.put(Class.class, getOpt_special); map.put(S.class, getOpt_special); }*/ static Object getOpt_cached(Object o, String field) { try { if (o == null) return null; Class c = o.getClass(); HashMap map; synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) return getOpt((Class) o, field); /*if (o instanceof S) ret getOpt(getBot((S) o), field);*/ if (o instanceof Map) return ((Map) o).get(field); } Field f = map.get(field); if (f != null) return f.get(o); if (o instanceof DynamicObject) return mapGet2(((DynamicObject) o).fieldValues, field); return null; } catch (Exception __e) { throw rethrow(__e); } } // used internally - we are in synchronized block static HashMap getOpt_makeCache(Class c) { HashMap map; if (isSubtypeOf(c, Map.class)) map = getOpt_special; else { map = new HashMap(); if (!reflection_classesNotToScan().contains(c.getName())) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) { makeAccessible(f); String name = f.getName(); if (!map.containsKey(name)) map.put(name, f); } _c = _c.getSuperclass(); } while (_c != null); } } if (getOpt_cache != null) getOpt_cache.put(c, map); return map; } static AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) { if (tl == null) return null; final A prev = setThreadLocal(tl, a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); }}; } static Map newDangerousWeakHashMap() { return _registerDangerousWeakMap(synchroMap(new WeakHashMap())); } // initFunction: voidfunc(Map) - is called initially, and after clearing the map static Map newDangerousWeakHashMap(Object initFunction) { return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction); } static HashMap> callMC_cache = new HashMap(); static String callMC_key; static Method callMC_value; // varargs assignment fixer for a single string array argument static Object callMC(String method, String[] arg) { return callMC(method, new Object[] {arg}); } static Object callMC(String method, Object... args) { try { Method me; if (callMC_cache == null) callMC_cache = new HashMap(); // initializer time workaround synchronized(callMC_cache) { me = method == callMC_key ? callMC_value : null; } if (me != null) try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } List m; synchronized(callMC_cache) { m = callMC_cache.get(method); } if (m == null) { if (callMC_cache.isEmpty()) { callMC_makeCache(); m = callMC_cache.get(method); } if (m == null) throw fail("Method named " + method + " not found in main"); } int n = m.size(); if (n == 1) { me = m.get(0); synchronized(callMC_cache) { callMC_key = method; callMC_value = me; } try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } } for (int i = 0; i < n; i++) { me = m.get(i); if (call_checkArgs(me, args, false)) return invokeMethod(me, null, args); } throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main"); } catch (Exception __e) { throw rethrow(__e); } } static void callMC_makeCache() { synchronized(callMC_cache) { callMC_cache.clear(); Class _c = (Class) mc(), c = _c; while (c != null) { for (Method m : c.getDeclaredMethods()) if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(m); multiMapPut(callMC_cache, m.getName(), m); } c = c.getSuperclass(); } } } static Object invokeMethod(Method m, Object o, Object... args) { try { try { return m.invoke(o, args); } catch (InvocationTargetException e) { throw rethrow(getExceptionCause(e)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) print("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) { Object arg = args[i]; if (!(arg == null ? !types[i].isPrimitive() : isInstanceX(types[i], arg))) { if (debug) print("Bad parameter " + i + ": " + arg + " vs " + types[i]); return false; } } return true; } static String padLeft(String s, char c, int n) { return rep(c, n-l(s)) + s; } // default to space static String padLeft(String s, int n) { return padLeft(s, ' ', n); } static String programID; static String getProgramID() { return nempty(programID) ? formatSnippetIDOpt(programID) : "?"; } // TODO: ask JavaX instead static String getProgramID(Class c) { String id = (String) getOpt(c, "programID"); if (nempty(id)) return formatSnippetID(id); return "?"; } static String getProgramID(Object o) { return getProgramID(getMainClass(o)); } static String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static String loadTextFile(File f, String defaultContents) { try { checkFileNotTooBigToRead(f); if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static Object collectionMutex(List l) { return l; } static Object collectionMutex(Object o) { if (o instanceof List) return o; String c = className(o); if (eq(c, "java.util.TreeMap$KeySet")) c = className(o = getOpt(o, "m")); else if (eq(c, "java.util.HashMap$KeySet")) c = className(o = get_raw(o, "this$0")); if (eqOneOf(c, "java.util.TreeMap$AscendingSubMap", "java.util.TreeMap$DescendingSubMap")) c = className(o = get_raw(o, "m")); return o; } static HashSet asHashSet(Collection c) { synchronized(collectionMutex(c)) { return new HashSet(c); } } static HashSet asHashSet(A[] a) { return a == null ? null : new HashSet(Arrays.asList(a)); } static List splitAtSpace(String s) { return empty(s) ? emptyList() : asList(s.split("\\s+")); } static List itemPlusList(A a, Collection l) { return concatLists(ll(a), l); } static String[] drop(int n, String[] a) { n = Math.min(n, a.length); String[] b = new String[a.length-n]; System.arraycopy(a, n, b, 0, b.length); return b; } static Object[] drop(int n, Object[] a) { n = Math.min(n, a.length); Object[] b = new Object[a.length-n]; System.arraycopy(a, n, b, 0, b.length); return b; } static Map emptyMap() { return new HashMap(); } static void addAll(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) c.add(a); } static boolean addAll(Collection c, Collection b) { return c != null && b != null && c.addAll(b); } static boolean addAll(Collection c, B... b) { return c != null && c.addAll(Arrays.asList(b)); } static Map addAll(Map a, Map b) { if (a != null) a.putAll(b); return a; } static File makeTempDir() { return (File) call(getJavaX(), "TempDirMaker_make"); } static boolean jreplace_multi(List tok, List ins, String out) { boolean change = false; for (String in : ins) if (jreplace(tok, in, out)) change = true; return change; } // doesn't loop static String jreplace_multi(String s, String... replacements) { List tok = javaTok(s); boolean change = false; for (int i = 0; i < l(replacements); i += 2) if (jreplace(tok, replacements[i], replacements[i+1])) change = true; return change ? join(tok) : s; } static Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } // "$1" is first code token, "$2" second code token etc. static String jreplaceExpandRefs(String s, List tokref) { List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("$") && isInteger(t.substring(1))) { String x = tokref.get(-1+parseInt(t.substring(1))*2); tok.set(i, x); } else if (t.equals("\\")) { tok.set(i, ""); i += 2; } } return join(tok); } static void add(BitSet bs, int i) { bs.set(i); } static boolean add(Collection c, A a) { return c != null && c.add(a); } static void add(Container c, Component x) { addToContainer(c, x); } static String[] toStringArray(Collection c) { String[] a = new String[l(c)]; Iterator it = c.iterator(); for (int i = 0; i < l(a); i++) a[i] = it.next(); return a; } static String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof Collection) return toStringArray((Collection) o); else throw fail("Not a collection or array: " + getClassName(o)); } static List codeTokensOnly(List tok) { int n = tok.size(); List l = emptyList(n/2); for (int i = 1; i < n; i += 2) l.add(tok.get(i)); return l; } static String dropTrailingSquareBracketStuff(String s) { if (!endsWith(s, "]")) return s; return trimSubstring(s, 0, smartLastIndexOf(s, '[')); } static boolean isLocalSnippetID(String snippetID) { return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID)); } static boolean isLocalSnippetID(long snippetID) { return snippetID >= 1000 && snippetID <= 9999; } static String localSnippetTitle(String snippetID) { if (!isLocalSnippetID(snippetID)) return null; File f = localSnippetFile(snippetID); if (!f.exists()) return null; return or2(getFileInfoField(dropExtension(f), "Title"), "Unnamed"); } static boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static String imageServerURL() { return or2(trim(loadTextFile(javaxDataDir("image-server-url.txt"))), "http://botcompany.de/images/raw/"); } static String muricaCredentialsQuery() { return htmlQuery(muricaCredentials()); } static boolean isGeneralFileServerSnippet(long id) { return id >= 1400000 && id < 1500000; } static String tb_mainServer_default = "http://code.botcompany.de:8081"; static Object tb_mainServer_override; // func -> S static String tb_mainServer() { if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override); return trim(loadTextFile(tb_mainServer_file(), tb_mainServer_default)); } static File tb_mainServer_file() { return getProgramFile("#1001638", "mainserver.txt"); } static boolean tb_mainServer_isDefault() { return eq(tb_mainServer(), tb_mainServer_default); } static String standardCredentials_noCookies() { return standardCredentials() + "&noCookies=1"; } static boolean saveTextFileIfChanged(File f, String contents) { return saveTextFileIfDifferent(f, contents); } static File snippetTitle_cacheFile(String snippetID) { return javaxCachesDir("Snippet Titles/" + psI(snippetID)); } static String exceptionToStringShort(Throwable e) { lastException(e); e = getInnerException(e); String msg = hideCredentials(unnull(e.getMessage())); if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0) return baseClassName(e) + prependIfNempty(": ", msg); else return msg; } static List map(Iterable l, Object f) { return map(f, l); } static List map(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) x.add(callF(f, o)); return x; } static List map(Iterable l, F1 f) { return map(f, l); } static List map(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) x.add(callF(f, o)); return x; } static List map(IF1 f, Iterable l) { return map(l, f); } static List map(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) x.add(f.get(o)); return x; } static List map(IF1 f, A[] l) { return map(l, f); } static List map(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) x.add(f.get(o)); return x; } static List map(Object f, Object[] l) { return map(f, asList(l)); } static List map(Object[] l, Object f) { return map(f, l); } static List map(Object f, Map map) { return map(map, f); } // map: func(key, value) -> list element static List map(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static List map(Map map, IF2 f) { return map(map, (Object) f); } static String tok_lastIdentifier(String s) { return lastIdentifier(javaTokC(s)); } static List tok_parseArgsDeclList(List tok) { return tok_parseArgsList(tok, getBracketMapIncludingAngleBrackets(tok)); } static void tokAppend(List tok, int i, String s) { tok.set(i, tok.get(i)+s); } static boolean addToCollection(Collection c, A a) { return c != null && c.add(a); } static String structureForUser(Object o) { return beautifyStructure(struct_noStringSharing(o)); } static TreeSet asCISet(Iterable c) { return toCaseInsensitiveSet(c); } static TreeSet asCISet(String... x) { return toCaseInsensitiveSet(x); } static boolean containsIgnoreCase(Collection l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String[] l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String s, char c) { return indexOfIgnoreCase(s, String.valueOf(c)) >= 0; } static boolean containsIgnoreCase(String a, String b) { return indexOfIgnoreCase(a, b) >= 0; } static boolean boolOptPar(ThreadLocal tl) { return boolOptParam(tl); } // defaults to false static boolean boolOptPar(Object[] __, String name) { return boolOptParam(__, name); } static boolean boolOptPar(String name, Object[] __) { return boolOptParam(__, name); } static String firstLine(String text) { if (text == null) return null; int i = text.indexOf('\n'); return i >= 0 ? text.substring(0, i) : text; } static String innerMessage(Throwable e) { return getInnerMessage(e); } static int parseIntOpt(String s) { return isInteger(s) ? parseInt(s) : 0; } static String regexpFirstGroupIC(String pat, String s) { Matcher m = regexpIC(pat, s); if (m.find()) return m.group(1); else return null; } static String lines(Iterable lines) { return fromLines(lines); } static String lines(Object[] lines) { return fromLines(asList(lines)); } static List lines(String s) { return toLines(s); } static int max(int a, int b) { return Math.max(a, b); } static int max(int a, int b, int c) { return max(max(a, b), c); } static long max(int a, long b) { return Math.max((long) a, b); } static long max(long a, long b) { return Math.max(a, b); } static double max(int a, double b) { return Math.max((double) a, b); } static float max(float a, float b) { return Math.max(a, b); } static double max(double a, double b) { return Math.max(a, b); } static int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static float max(float[] c) { if (c.length == 0) return Float.MAX_VALUE; float x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static short max(short[] c) { short x = -0x8000; for (short d : c) if (d > x) x = d; return x; } static int max(int[] c) { int x = Integer.MIN_VALUE; for (int d : c) if (d > x) x = d; return x; } static File newFile(File base, String... names) { for (String name : names) base = new File(base, name); return base; } static File newFile(String name) { return name == null ? null : new File(name); } static File newFile(String base, String... names) { return newFile(newFile(base), names); } static void replaceCollection(Collection dest, Collection src) { dest.clear(); dest.addAll(src); } static void replaceListPart(List l, int i, int j, List l2) { int j2 = i+l(l2); if (j2 == j) { copyListPart(l2, 0, l, i, l(l2)); return; } l.subList(i, j).clear(); l.addAll(i, l2); } static File getProgramFile(String progID, String fileName) { if (new File(fileName).isAbsolute()) return new File(fileName); return new File(getProgramDir(progID), fileName); } static File getProgramFile(String fileName) { return getProgramFile(getProgramID(), fileName); } static List cncSubList(List tok, int from, int to) { from &= ~1; to |= 1; return subList(tok, from, to); } static String getNameOfPublicClass(List tok) { for (List c : allClasses(tok)) if (hasModifier(c, "public")) return getClassDeclarationName(c); return null; } static String getNameOfAnyClass(List tok) { return getClassDeclarationName(first(allClasses(tok))); } static String addSlash(String s) { return empty(s) || s.endsWith("/") ? s : s + "/"; } static boolean boolPar(ThreadLocal tl) { return boolOptParam(tl); } // defaults to false static boolean boolPar(Object[] __, String name) { return boolOptParam(__, name); } static boolean boolPar(String name, Object[] __) { return boolOptParam(__, name); } static boolean boolPar(String name, Map __) { return boolOptParam(name, __); } static boolean boolPar(String name, Object[] params, boolean defaultValue) { return optParam(params, name, defaultValue); } static boolean eqGetOneOf(List l, int i, A... options) { return eqOneOf(get(l, i), options); } static int jfind_any(String src, String... patterns) { return jfind_any(javaTok(src), patterns); } static int jfind_any(List tok, String... patterns) { int i = -1; for (String pat : patterns) i = minUnlessMinus1(i, jfind(tok, pat)); return i; } static ThreadLocal tok_typesAndNamesOfParams_keepModifiers = new ThreadLocal(); static List> tok_typesAndNamesOfParams(List tok, Object... __) { boolean keepModifiers = boolPar(tok_typesAndNamesOfParams_keepModifiers); try { List> out = new ArrayList(); for (int i = 1; i < l(tok); ) { String t = tok.get(i); String pre = ""; if (isIdentifier(t) && eqGetOneOf(tok, i+2, ",", null)) if (boolPar("typelessMeansObject",__)) { i += 4; { out.add(pair("Object", t)); continue; } } else throw fail("Parameter " + t + " has no type: " + join(tok)); if (eq(t, "final")) { if (keepModifiers) pre += "final "; t = get(tok, i += 2); } if (eq(t, "virtual")) { pre += "virtual "; t = get(tok, i += 2); } if (eq(t, "new")) { pre += "new "; t = get(tok, i += 2); } assertTrue(isIdentifier(t)); i += 2; String type = t, name = "?"; while (eq(get(tok, i), ".") && !eqGet(tok, i+2, ".")) { type += "." + assertIdentifier(get(tok, i+2)); i += 4; } // just a parameter name, no type if (eqOneOf(get(tok, i), null, ",")) { name = type; type = "?"; } else { if (eq(tok.get(i), "<")) { int j = findEndOfTypeArgs(tok, i)-1; while (eq(get(tok, j), "[") && eq(get(tok, j+2), "]")) j += 4; type += trimJoinSubList(tok, i, j+1); String id = assertIdentifier(tok.get(j+2)); i = j+2; } while (eq(get(tok, i), "[") && eq(get(tok, i+2), "]")) { i += 4; type += "[]"; } if (eqGet(tok, i, ".") && eqGet(tok, i+2, ".") && eqGet(tok, i+4, ".")) { type += "..."; i += 6; } name = assertIdentifier(tok.get(i)); i += 2; while (eq(get(tok, i), "[") && eq(get(tok, i+2), "]")) { i += 4; type += "[]"; } if (i < l(tok)) { assertEquals(get(tok, i), ","); i += 2; } } out.add(pair(pre + type, name)); } return out; } catch (Throwable e) { print("Bad parameter declaration: " + sfu(tok)); throw rethrow(e); } } static List secondOfPairs(Collection> l) { return map("secondOfPair", l); } static String tok_genEqualsAndHashCode(String className, List> fields) { StringBuilder buf = new StringBuilder("\n\npublic bool equals(O o) {\n"); if (empty(fields)) buf.append("ret o instanceof " + className + ";\n"); else buf.append("if (!o instanceof " + className + ") false;\r\n " + className + " x = cast o;\r\n ret " + join(" && ", map(fields, new F1, String>() { String get(Pair p) { try { // TODO: use == for primitive fields return "eq(" + p.b + ", x." + p.b + ")"; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "// TODO: use == for primitive fields\r\n \"eq(\" + p.b + \", x.\" + p.b + \")\""; }})) + ";\n"); buf.append("}\n"); buf.append("\r\n public int hashCode() {\r\n int h = " + hashCode(className) + ";\r\n " + concatMap_strings(fields, new F1, Object>() { Object get(Pair p) { try { return "h = boostHashCombine(h, _hashCode(" + p.b + "));\r\n "; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "\"h = boostHashCombine(h, _hashCode(\" + p.b + [[));\r\n ]]"; }}) + "ret h;\r\n }\r\n "); return str(buf); } static String tok_genRecordFieldsToList(List> fields) { return "public O[] _fieldsToList() { " + (empty(fields) ? "null;" : "ret new O[] {" + joinWithComma(pairsB(fields)) + "};") + " }\n"; } static boolean isSingleQuoteIdentifier(String s) { if (l(s) < 2 || s.charAt(0) != '\'' || !Character.isJavaIdentifierStart(s.charAt(1))) return false; for (int i = 2; i < l(s); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static int indexOfAny(List l, int i, A... x) { while (i < l(l)) if (eqOneOf(l.get(i), x)) return i; else ++i; return -1; } static int indexOfAny(List l, Collection x) { return indexOfAny(l, 0, x); } static int indexOfAny(List l, int i, Collection x) { if (nempty(x)) while (i < l(l)) if (x.contains(l.get(i))) return i; else ++i; return -1; } static int indexOfAny(String s, int i, String chars) { for (; i < l(s); i++) if (chars.indexOf(s.charAt(i)) >= 0) return i; return -1; } static int indexOfAny(String s, String chars) { return indexOfAny(s, 0, chars); } static List reversed(Collection l) { return reversedList(l); } static List reversed(A[] l) { return reversedList(asList(l)); } static String reversed(String s) { return reversedString(s); } static List indexesOf(List l, A a) { List x = new ArrayList(); for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) x.add(i); return x; } static A second(List l) { return get(l, 1); } static A second(Iterable l) { if (l == null) return null; Iterator it = iterator(l); if (!it.hasNext()) return null; it.next(); return it.hasNext() ? it.next() : null; } static A second(A[] bla) { return bla == null || bla.length <= 1 ? null : bla[1]; } static B second(Pair p) { return p == null ? null : p.b; } static A second(Producer p) { if (p == null) return null; if (p.next() == null) return null; return p.next(); } static char second(String s) { return charAt(s, 1); } // Return value is index of ")" static int tok_findEndOfForExpression(List tok, int i) { int level = 1; while (i < l(tok)) { String t = tok.get(i); if (eq(t, "(")) ++level; else if (eq(t, ")")) if (--level == 0) return i; i += 2; } return i; } static String trimJoinSubList(List l, int i, int j) { return trim(join(subList(l, i, j))); } static String trimJoinSubList(List l, int i) { return trim(join(subList(l, i))); } // i = beginning of statement or block static void tok_statementToBlock(List tok, int i) { if (neqGet(tok, i, "{")) { int iEnd = tok_findEndOfStatement(tok, i)-1; tokAppend_reTok(tok, iEnd, " }"); tokPrepend_reTok(tok, i, "{ "); } } static String joinPairWithSpace(Pair p) { return str(p.a) + " " + str(p.b); } static String toUpper(String s) { return s == null ? null : s.toUpperCase(); } static List toUpper(Collection s) { return allToUpper(s); } static String[] codeTokensAsStringArray(List tok) { int n = max(0, (l(tok)-1)/2); String[] out = new String[n]; for (int i = 0; i < n; i++) out[i] = tok.get(i*2+1); return out; } static List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; removeSubList(l, i, i+l(x)); l.addAll(i, y); i += l(y); } return l; } static List replaceSublist(List l, int fromIndex, int toIndex, List y) { // TODO: optimize more removeSubList(l, fromIndex, toIndex); l.addAll(fromIndex, y); return l; } static List replaceSublist(List l, IntRange r, List y) { return replaceSublist(l, r.start, r.end, y); } static String getType(Object o) { return getClassName(o); } static long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static long getFileSize(File f) { return f == null ? 0 : f.length(); } static boolean isJavaIdentifier(String s) { if (empty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static A liftLast(List l) { if (empty(l)) return null; int i = l(l)-1; A a = l.get(i); l.remove(i); return a; } static List liftLast(int n, List l) { int i = l(l)-n; List part = cloneSubList(l, i); removeSubList(l, i); return part; } static boolean containsSubList(List x, List y) { return indexOfSubList(x, y) >= 0; } static boolean containsSubList(List x, A... y) { return indexOfSubList(x, y, 0) >= 0; } static void tok_p_repeatWithSleep(List tok) { int i; while ((i = jfind(tok, "p-repeat with sleep * {")) >= 0) { String seconds = tok.get(i+6); // int or id int idx = findCodeTokens(tok, i, false, "{"); int j = findEndOfBracketPart(tok, idx); tok.set(i+2, " { "); tok.set(j-1, "} }"); reTok(tok, j-1); reTok(tok, i+2); } } // i = last C token of type // returns first C token of type static int tok_scanTypeBackwards(List tok, int i) { if (i < 0) return i; int level = 0; while (i > 0) { String t = tok.get(i); if (isIdentifier(t) && level == 0) { while (eqGet(tok, i-2, ".") && isIdentifier(get(tok, i-4))) i -= 4; return i; } if (eq(t, ">")) ++level; else if (eq(t, "<")) --level; i -= 2; } return i; } // returns index of trailing N token static int scanToEndOfInitializer2(List tok, int i) { int level = 0; while (i < l(tok)) { String t = tok.get(i); if (eqOneOf(t, "(", "{")) ++level; else if (level > 0 && eqOneOf(t, ")", "}")) --level; else if (level == 0 && eqOneOf(tok.get(i), ";", ",", ")", "}")) return i-1; i++; } return i; } static boolean tok_typeIsObject(String type) { return eqOneOf(type, "O", "Object"); } static boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static boolean eqic(char a, char b) { if (a == b) return true; char u1 = Character.toUpperCase(a); char u2 = Character.toUpperCase(b); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static boolean checkTokCondition(Object condition, List tok, int i) { if (condition instanceof TokCondition) return ((TokCondition) condition).get(tok, i); return checkCondition(condition, tok, i); } static List splitByJavaToken(String s, String splitToken) { List tok = javaTok(s); List l = new ArrayList(); int i = 1; while (i < l(tok)) { int j = smartIndexOf(tok, splitToken, i); l.add(join(subList(tok, i, j-1))); i = j+2; } return l; } static boolean startsWith(String a, String b) { return a != null && a.startsWith(b); } static boolean startsWith(String a, char c) { return nemptyString(a) && a.charAt(0) == c; } static boolean startsWith(String a, String b, Matches m) { if (!startsWith(a, b)) return false; m.m = new String[] {substring(a, strL(b))}; return true; } static boolean startsWith(List a, List b) { if (a == null || listL(b) > listL(a)) return false; for (int i = 0; i < listL(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static boolean endsWith(String a, String b) { return a != null && a.endsWith(b); } static boolean endsWith(String a, char c) { return nempty(a) && lastChar(a) == c; } static boolean endsWith(String a, String b, Matches m) { if (!endsWith(a, b)) return false; m.m = new String[] {dropLast(l(b), a)}; return true; } // i must point at the opening bracket ("<") // index returned is index of closing bracket + 1 static int findEndOfTypeArgs(List cnc, int i) { int j = i+2, level = 1; while (j < cnc.size()) { if (cnc.get(j).equals("<")) ++level; else if (cnc.get(j).equals(">")) --level; if (level == 0) return j+1; ++j; } return cnc.size(); } static int indexOf_between(List l, A a, int startIndex, int endIndex) { if (l == null) return -1; for (int i = startIndex; i < endIndex; i++) if (eq(l.get(i), a)) return i; return -1; } static boolean tok_isSingleTypeArg(List tok, int iOpeningBracket) { int j = tok_findEndOfTypeArg(tok, iOpeningBracket); return neqGet(tok, j, ","); } static int tok_findEndOfType(List tok) { return tok_findEndOfType(tok, 1); } // i = beginning of type (identifier) // index returned C index after type // TODO: packages/inner classes static int tok_findEndOfType(List tok, int i) { if (!eqGet(tok, i+2, "<")) return i+2; return findEndOfTypeArgs(tok, i+2)+1; } static boolean longIsInt(long l) { return l == (int) l; } static void tokReplace(List tok, int i, String t) { put(tok, i, t); } static void tokSet_withReTok(List tok, int i, String t) { put(tok, i, t); reTok(tok, i, i+1); } static void tokPrepend_withReTok(List tok, int i, String s) { tokPrepend_reTok(tok, i, s); } static int leftScanModifiers(List tok, int i) { List mod = getJavaModifiers(); while (i > 1 && mod.contains(tok.get(i-2))) i -= 2; return i; } static void tokSet(List tok, int idx, String token) { tok.set(idx, token); } static int tok_findTokenSkippingCurlyBrackets(List tok, int i, String t) { while (i < l(tok)) { if (eqGet(tok, i, t)) return i; if (eqGet(tok, i, "{")) i = findEndOfBracketPart(tok, i)+1; else i += 2; } return -1; } static Collection tok_modifiersLeftOf(List tok, int i) { int j = leftScanModifiers(tok, i); List modifiers = new ArrayList(); while (j < i) { modifiers.add(tok.get(j)); j += 2; } return modifiers; } // index returned is index of closing bracket or semicolon + 1 (or l(cnc)) static int tok_findEndOfMethodDecl(List tok, int i) { i = tok_findEndOfMethodHeader(tok, i); return findEndOfBlock(tok, i); } static String tok_functionName(List tok) { return get(tok, indexOfOneOf(tok, 0, "(", "{")-2); } static boolean is(String a, String b) { return false; } static Object javaEval(String code) { return evalJava(code); } static A assertEquals(Object x, A y) { return assertEquals(null, x, y); } static A assertEquals(String msg, Object x, A y) { if (assertVerbose()) return assertEqualsVerbose(msg, x, y); if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + y + " != " + x); return y; } static boolean setAdd(Collection c, A a) { if (c == null || c.contains(a)) return false; c.add(a); return true; } static A popLast(List l) { return liftLast(l); } static List popLast(int n, List l) { return liftLast(n, l); } // This is a bit rough... finds static and non-static methods. static Method findMethodNamed(Object obj, String method) { if (obj == null) return null; if (obj instanceof Class) return findMethodNamed((Class) obj, method); return findMethodNamed(obj.getClass(), method); } static Method findMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) { makeAccessible(m); return m; } c = c.getSuperclass(); } return null; } static void quoteToPrintWriter(String s, PrintWriter out) { if (s == null) { out.print("null"); return; } out.print('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') { out.print('\\'); out.print(c); } else if (c == '\r') out.print("\\r"); else if (c == '\n') out.print("\\n"); else if (c == '\0') out.print("\\0"); else out.print(c); } out.print('"'); } static String quoteCharacter(char c) { if (c == '\'') return "'\\''"; if (c == '\\') return "'\\\\'"; if (c == '\r') return "'\\r'"; if (c == '\n') return "'\\n'"; if (c == '\t') return "'\\t'"; return "'" + c + "'"; } static boolean isCISet_gen(Iterable l) { return l instanceof TreeSet && className(((TreeSet) l).comparator()).contains("CIComp"); } static List unwrapSynchronizedList(List l) { if (eqOneOf(className(l), "java.util.Collections$SynchronizedList", "java.util.Collections$SynchronizedRandomAccessList")) return (List) get_raw(l, "list"); return l; } static boolean isCIMap_gen(Map map) { return map instanceof TreeMap && className(((TreeMap) map).comparator()).contains("CIComp"); } static Map unwrapSynchronizedMap(Map map) { if (eqOneOf(className(map), "java.util.Collections$SynchronizedMap", "java.util.Collections$SynchronizedSortedMap", "java.util.Collections$SynchronizedNavigableMap")) return (Map) get_raw(map, "m"); return map; } static String boolArrayToHex(boolean[] a) { return bytesToHex(boolArrayToBytes(a)); } static Iterator emptyIterator() { return Collections.emptyIterator(); } static String shortDynamicClassName(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return ((DynamicObject) o).className; return shortClassName(o); } static int stdcompare(Number a, Number b) { return cmp(a, b); } static int stdcompare(String a, String b) { return cmp(a, b); } static int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static int stdcompare(Object a, Object b) { return cmp(a, b); } static Map getDeclaredFields_cache = newDangerousWeakHashMap(); static Field[] getDeclaredFields_cached(Class c) { Field[] fields; synchronized(getDeclaredFields_cache) { fields = getDeclaredFields_cache.get(c); if (fields == null) { getDeclaredFields_cache.put(c, fields = c.getDeclaredFields()); for (Field f : fields) makeAccessible(f); } } return fields; } static boolean startsWithDigit(String s) { return nempty(s) && isDigit(s.charAt(0)); } static Map putAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static int countDots(String s) { int n = l(s), count = 0; for (int i = 0; i < n; i++) if (s.charAt(i) == '.') ++count; return count; } static void printStructure(String prefix, Object o) { if (endsWithLetter(prefix)) prefix += ": "; print(prefix + structureForUser(o)); } static void printStructure(Object o) { print(structureForUser(o)); } static int lastIndexOf(String a, String b) { return a == null || b == null ? -1 : a.lastIndexOf(b); } static int lastIndexOf(String a, char b) { return a == null ? -1 : a.lastIndexOf(b); } static A set(A o, String field, Object value) { if (o == null) return null; if (o instanceof Class) set((Class) o, field, value); else try { Field f = set_findField(o.getClass(), field); makeAccessible(f); smartSet(f, o, value); } catch (Exception e) { throw new RuntimeException(e); } return o; } static void set(Class c, String field, Object value) { if (c == null) return; try { Field f = set_findStaticField(c, field); makeAccessible(f); smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field set_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field set_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } // Finds out the index of a sublist in the original list // Works with nested (grand-parent) sublists. // Does not work with lists not made with subList() (returns -1) static int magicIndexOfSubList(List list, List sublist) { if (sublist == list) return 0; Integer o2 = (Integer) (get(sublist, "offset")); if (o2 == null) return -1; Integer o1 = (Integer) (getOpt(list, "offset")); return o2-(o1 != null ? o1 : 0); } static boolean isNormalQuoted_dirty(String s) { return startsWith(s, "\"") && endsWith(s, "\"") && l(s) >= 2; } static boolean isMultilineQuoted(String s) { if (!startsWith(s, "[")) return false; int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; return i < s.length() && s.charAt(i) == '['; } static Class hotwire(String src) { assertFalse(_inCore()); Class j = getJavaX(); if (isAndroid()) { synchronized(j) { // hopefully this goes well... List libraries = new ArrayList(); File srcDir = (File) call(j, "transpileMain", src, libraries); if (srcDir == null) throw fail("transpileMain returned null (src=" + quote(src) + ")"); Object androidContext = get(j, "androidContext"); return (Class) call(j, "loadx2android", srcDir, src); } } else { Class c = (Class) (call(j, "hotwire", src)); hotwire_copyOver(c); return c; } } static A callMain(A c, String... args) { callOpt(c, "main", new Object[] {args}); return c; } static void callMain() { callMain(mc()); } static String joinCodeTokens(List tok) { StringBuilder buf = new StringBuilder(); int n = tok.size(); for (int i = 1; i < n; i += 2) buf.append(tok.get(i)); return buf.toString(); } static boolean containsNewLine(String s) { return contains(s, '\n'); // screw \r, nobody needs it } static HashMap mapFromTokens(String s) { List tok = javaTok(s); HashMap map = new HashMap(); for (int i = 1; i+2 < l(tok); i += 4) map.put(tok.get(i), tok.get(i+2)); return map; } static List newSubList(List l, int startIndex, int endIndex) { return cloneList(subList(l, startIndex, endIndex)); } static List newSubList(List l, int startIndex) { return cloneList(subList(l, startIndex)); } static boolean tok_shouldAddReturn(List tok) { String lastToken = get(tok, l(tok)-2); return !eqOneOf(lastToken, "}", ";"); } static boolean tok_shouldAddReturn(String s) { return tok_shouldAddReturn(javaTok(s)); } // i must point at the (possibly imaginary) closing bracket (any of the 2 types, not type parameters) // index returned is index of opening bracket static int findBeginningOfBracketPart(List cnc, int i) { int j = i-2, level = 1; while (j > 0) { if (eqOneOf(cnc.get(j), "}", ")")) ++level; else if (eqOneOf(cnc.get(j), "{", "(")) --level; if (level == 0) return j; j -= 2; } return -1; } // iOpening, iClosing = position of () brackets static List tok_makeArgumentsFinal(List tok, int iOpening, int iClosing) { Map bracketMap = getBracketMapIncludingAngleBrackets(tok, iOpening+2, iClosing); boolean change = false; int i = iOpening+2; while (i < iClosing) { if (neqGet(tok, i, "final")) { tokPrepend(tok, i, "final "); change = true; } while (i < iClosing && neqGet(tok, i, ",")) i = or(bracketMap.get(i), i)+2; i += 2; } if (change) reTok(tok, iOpening, iClosing); return tok; } // not including <> as they are ambiguous (< is also a comparison operator) static String testBracketHygiene_op = "([{"; static String testBracketHygiene_close = ")]}"; static boolean testBracketHygiene(String s) { return testBracketHygiene(s, testBracketHygiene_op, testBracketHygiene_close, null); } static boolean testBracketHygiene(String s, Var msg) { return testBracketHygiene(s, testBracketHygiene_op, testBracketHygiene_close, msg); } static boolean testBracketHygiene(String s, String op, String close, Var msg) { Pair p = testBracketHygiene2(s, op, close); if (p == null) { if (msg != null) msg.set("Hygiene OK!"); return true; } if (msg != null) msg.set(p.b); return false; } static boolean isLongConstant(String s) { if (!s.endsWith("L")) return false; s = s.substring(0, l(s)-1); return isInteger(s); } static List wrapAsList(A[] a) { return wrapArrayAsList(a); } static volatile boolean licensed_yes = true; static boolean licensed() { if (!licensed_yes) return false; ping_okInCleanUp(); return true; } static void licensed_off() { licensed_yes = false; } static String lineAroundToken(List tok, int tokenIndex) { int i = tokenIndex, j = tokenIndex; while (i > 1 && !containsNewLine(get(tok, i-1))) i -= 2; while (j+2 < l(tok) && !containsNewLine(get(tok, j+1))) j += 2; return afterLineBreak(get(tok, i-1)) + joinSubList(tok, i, j+1) + beforeLineBreak(get(tok, j+1)); } static Set similarEmptySet(Collection m) { if (m instanceof TreeSet) return new TreeSet(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashSet(); return new HashSet(); } static String loadLocalSnippet(String snippetID) { return loadLocalSnippet(psI(snippetID)); } static String loadLocalSnippet(long snippetID) { return loadTextFile(localSnippetFile(snippetID)); } static String standardCredentials() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass); return ""; } static File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } static boolean isUnproperlyQuoted(String s) { return startsWith(s, '"') && !isProperlyQuoted(s); } static boolean regexpFinds(String pat, String s) { return regexp(pat, s).find(); } static boolean regexpFinds(Pattern pat, String s) { return regexp(pat, s).find(); } static void mapPut(Map map, A key, B value) { if (map != null && key != null && value != null) map.put(key, value); } static Map jsonDecodeMap(String s) { Object o = jsonDecode(s); if (o instanceof List && empty((List) o)) return new HashMap(); if (o instanceof Map) return (Map) o; else throw fail("Not a JSON map: " + s); } static ThreadLocal doPost_silently = new ThreadLocal(); static ThreadLocal doPost_timeout = new ThreadLocal(); static ThreadLocal> doPost_extraHeaders = new ThreadLocal(); static String doPost(Map urlParameters, String url) { return doPost(makePostData(urlParameters), url); } static String doPost(String urlParameters, String url) { try { URL _url = new URL(url); ping(); return doPost(urlParameters, _url.openConnection(), _url); } catch (Exception __e) { throw rethrow(__e); } } static String doPost(String urlParameters, URLConnection conn, URL url) { try { boolean silently = isTrue(optParam(doPost_silently)); Long timeout = optParam(doPost_timeout); Map extraHeaders = optPar(doPost_extraHeaders); setHeaders(conn); for (String key : keys(extraHeaders)) conn.setRequestProperty(key, extraHeaders.get(key)); int l = lUtf8(urlParameters); if (!silently) print("Sending POST request: " + hideCredentials(url) + " (" + l + " bytes)"); // connect and do POST if (timeout != null) setURLConnectionTimeouts(conn, timeout); ((HttpURLConnection) conn).setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Length", str(l)); OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); writer.write(urlParameters); writer.flush(); String contents = loadPage_utf8(conn, url, false); writer.close(); return contents; } catch (Exception __e) { throw rethrow(__e); } } static String urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static String className(Object o) { return getClassName(o); } static List> innerClasses(List tok) { if (tok == null) return emptyList(); int i = 1; while (i < tok.size() && !tok.get(i).equals("{")) i += 2; return allClasses(tok.subList(i+1, tok.size())); } static boolean startsWithUpperCase(String s) { return nempty(s) && Character.isUpperCase(s.charAt(0)); } static List toLinesFullTrim_java(String text) { // TODO: shouldn't it be tlft(javaDropComments(text))? return tlft(joinLines(map("javaDropComments",tlft(text)))); } static boolean eqOneOf_twoNonNullStrings(String s, String a, String b) { return a.equals(s) || b.equals(s); } static boolean startsWithJavaIdentifierStart(String s) { return nempty(s) && Character.isJavaIdentifierStart(s.charAt(0)); } // i points at C token after suspected meta command static boolean tok_isJavaxMetaCommandLeftOf(List tok, int i) { int j = i-2*4-1; if (j >= 0 && jfind(subList(tok, j, i), "set flag .") == 1) return true; return false; } static int rfindCodeTokens(List tok, String... tokens) { return rfindCodeTokens(tok, 1, false, tokens); } static int rfindCodeTokens(List tok, boolean ignoreCase, String... tokens) { return rfindCodeTokens(tok, 1, ignoreCase, tokens); } static int rfindCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return rfindCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static List rfindCodeTokens_specials = litlist("*", "", "", "", "\\*"); static boolean rfindCodeTokens_debug = false; static int rfindCodeTokens_indexed, rfindCodeTokens_unindexed; static int rfindCodeTokens_bails, rfindCodeTokens_nonbails; static int rfindCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { if (rfindCodeTokens_debug) { if (eq(getClassName(tok), "main$IndexedList2")) rfindCodeTokens_indexed++; else rfindCodeTokens_unindexed++; } // bail out early if first token not found (works great with IndexedList) if (!rfindCodeTokens_specials.contains(tokens[0]) && !tok.contains(tokens[0] /*, startIdx << no signature in List for this, unfortunately */)) { ++rfindCodeTokens_bails; return -1; } ++rfindCodeTokens_nonbails; outer: for (int i = tok.size()-tokens.length*2; i >= startIdx; i -= 2) { for (int j = 0; j < tokens.length; j++) { String p = tokens[j], t = tok.get(i+j*2); boolean match = false; if (eq(p, "*")) match = true; else if (eq(p, "")) match = isQuoted(t); else if (eq(p, "")) match = isIdentifier(t); else if (eq(p, "")) match = isInteger(t); else if (eq(p, "\\*")) match = eq("*", t); else match = ignoreCase ? eqic(p, t) : eq(p, t); if (!match) continue outer; } if (condition == null || checkTokCondition(condition, tok, i-1)) // pass N index return i; } return -1; } static boolean allVarNames_debug = false; static List allVarNames(List tok) { boolean debug = allVarNames_debug; Map bracketMap = getBracketMap(tok); List varNames = new ArrayList(); for (int i = 3; i < tok.size(); i += 2) { String t = tok.get(i); if (eqOneOf(t, "=", ";", ",")) { String v = tok.get(i-2); if (isIdentifier(v)) varNames.add(v); if (eq(t, "=")) { i = scanToEndOfInitializer(tok, bracketMap, i)+1; assertTrue(odd(i)); } } else if (eq(t, "<")) { i = findEndOfTypeArgs(tok, i)+1; if (debug) print("Skipped type args: " + struct(subList(tok, i))); } else if (eqOneOf(t, "{", "(")) i = findEndOfBracketPart(tok, i)-1; // skip function/class bodies } return varNames; } static List allVarNames(String text) { return allVarNames(javaTok(text)); } static boolean isSortedList(List l) { for (int i = 0; i < l(l)-1; i++) if (cmp(l.get(i), l.get(i+1)) > 0) return false; return true; } static int smartIndexOfAny(List l, int i, A... x) { while (i < l(l)) if (eqOneOf(l.get(i), x)) return i; else ++i; return l(l); } static int smartIndexOfAny(List l, A... x) { return smartIndexOfAny(l, 0, x); } static boolean vmExiting() { return isTrue(getOpt(javax(), "killing")); } static String struct(Object o) { return structure(o); } static String struct(Object o, structure_Data data) { return structure(o, data); } static Object call_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findStaticMethod(method, args); if (me != null) return invokeMethod(me, null, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } { if (!(isStaticMethod(m))) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, null, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found in " + c); } } catch (Exception __e) { throw rethrow(__e); } } static Object makeDependent_postProcess; static void makeDependent(Object c) { if (c == null) return; assertTrue("Not a class", c instanceof Class); dependentClasses(); // cleans up the list hotwire_classes.add(new WeakReference(c)); Object local_log = getOpt(mc(), "local_log"); if (local_log != null) setOpt(c, "local_log", local_log); /*if (isTrue(getOpt(c, 'ping_actions_shareable))) setOpt(c, +ping_actions);*/ Object print_byThread = getOpt(mc(), "print_byThread"); if (print_byThread != null) setOpt(c, "print_byThread", print_byThread); callF(makeDependent_postProcess, c); } static void unlock(Lock lock, String msg) { if (lock == null) return; print("Unlocking: " + msg); lock.unlock(); } static void unlock(Lock lock) { if (lock == null) return; lock.unlock(); } static String lookupStandardFunction(String sfName) { return stdFunctions_cached().get(sfName); } static String assertIsIdentifier(String s) { if (!isIdentifier(s)) throw fail("Not an identifier: " + quote(s)); return s; } static String assertIsIdentifier(String msg, String s) { if (!isIdentifier(s)) throw fail(msg + " - Not an identifier: " + quote(s)); return s; } static B secondOfPair(Pair p) { return p == null ? null : p.b; } static volatile boolean disableCertificateValidation_attempted = false; static void disableCertificateValidation() { try { if (disableCertificateValidation_attempted) return; disableCertificateValidation_attempted = true; try { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} }}; // Ignore differences between given hostname and certificate hostname HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(hv); } catch (Throwable __e) { _handleException(__e); } } catch (Exception __e) { throw rethrow(__e); } } static boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } static final boolean loadPageThroughProxy_enabled = false; static String loadPageThroughProxy(String url) { return null; } static void sleepSeconds(double s) { if (s > 0) sleep(round(s*1000)); } static A printWithTime(A a) { return printWithTime("", a); } static A printWithTime(String s, A a) { print(hmsWithColons() + ": " + s, a); return a; } static String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key)=[^&\\s\"]*", "$1$2="); } static String hideCredentials(Object o) { return hideCredentials(str(o)); } static A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } static void setHeaders(URLConnection con) throws IOException { String computerID = getComputerID_quick(); if (computerID != null) try { con.setRequestProperty("X-ComputerID", computerID); con.setRequestProperty("X-OS", System.getProperty("os.name") + " " + System.getProperty("os.version")); } catch (Throwable e) { //printShortException(e); } } static Map vm_generalSubMap(Object name) { synchronized(get(javax(), "generalMap")) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static InputStream urlConnection_getInputStream(URLConnection con) throws IOException { UnknownHostException lastException = null; for (int _repeat_1085 = 0; _repeat_1085 < 2; _repeat_1085++) { try { if (con instanceof HttpURLConnection) if (((HttpURLConnection) con).getResponseCode() == 500) throw new IOException(joinNemptiesWithColonSpace("Server code 500", tryToReadErrorStreamFromURLConnection(((HttpURLConnection) con)))); return con.getInputStream(); } catch (UnknownHostException e) { lastException = e; print("Retrying because of: " + e); continue; } } throw lastException; } static GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static String toHex(byte[] bytes) { return bytesToHex(bytes); } static String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static byte[] utf8(String s) { return toUtf8(s); } static Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static URLConnection openConnection(String url) { try { return openConnection(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static URLConnection openConnection(URL url) { try { ping(); callOpt(javax(), "recordOpenURLConnection", str(url)); return url.openConnection(); } catch (Exception __e) { throw rethrow(__e); } } static int toInt(Object o) { if (o == null) return 0; if (o instanceof Number) return ((Number) o).intValue(); if (o instanceof String) return parseInt((String) o); throw fail("woot not int: " + getClassName(o)); } static int toInt(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static void vmBus_send(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); pcallFAll(vm_busListeners_live(), msg, arg); pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg); } static void vmBus_send(String msg) { vmBus_send(msg, (Object) null); } static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static Object callOpt_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me == null) { // TODO: varargs return null; } if ((me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } return null; } } catch (Exception __e) { throw rethrow(__e); } } static String getStackTrace(Throwable throwable) { lastException(throwable); return getStackTrace_noRecord(throwable); } static String getStackTrace_noRecord(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return hideCredentials(writer.toString()); } static String getStackTrace() { return getStackTrace_noRecord(new Throwable()); } static List _registerWeakMap_preList; static A _registerWeakMap(A map) { if (javax() == null) { // We're in class init if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList(); _registerWeakMap_preList.add(map); return map; } try { call(javax(), "_registerWeakMap", map); } catch (Throwable e) { printException(e); print("Upgrade JavaX!!"); } return map; } static void _onLoad_registerWeakMap() { assertNotNull(javax()); if (_registerWeakMap_preList == null) return; for (Object o : _registerWeakMap_preList) _registerWeakMap(o); _registerWeakMap_preList = null; } static Map synchroMap() { return synchroHashMap(); } static Map synchroMap(Map map) { return Collections.synchronizedMap(map); } static int isAndroid_flag; static boolean isAndroid() { if (isAndroid_flag == 0) isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1; return isAndroid_flag > 0; } static Boolean isHeadless_cache; static boolean isHeadless() { if (isHeadless_cache != null) return isHeadless_cache; if (isAndroid()) return isHeadless_cache = true; if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true; // Also check if AWT actually works. // If DISPLAY variable is set but no X server up, this will notice. try { SwingUtilities.isEventDispatchThread(); return isHeadless_cache = false; } catch (Throwable e) { return isHeadless_cache = true; } } static void consoleClearInput() { consoleSetInput(""); } static void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized(buf) { if (buf.length() <= max) return; try { int newLength = max/2; int ofs = buf.length()-newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized(buf) { if (buf.length() <= max) return; try { int newLength = max/2; int ofs = buf.length()-newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static A proxy(Class intrface, final Object target) { if (target == null) return null; if (isInstance(intrface, target)) return (A) target; return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { return call(target, method.getName(), unnull(args)); } }); } static A proxy(Object target, Class intrface) { return proxy(intrface, target); } static Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static String loadTextFilePossiblyGZipped(String fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(String fileName, String defaultContents) { File gz = new File(fileName + ".gz"); return gz.exists() ? loadGZTextFile(gz) : loadTextFile(fileName, defaultContents); } static String loadTextFilePossiblyGZipped(File fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(File fileName, String defaultContents) { return loadTextFilePossiblyGZipped(fileName.getPath(), defaultContents); } static File getCachedTranspilationFile(String id) { return newFile(getCodeProgramDir(id), "Transpilation"); } static Object vmGeneralMap_get(Object key) { return vm_generalMap_get(key); } static String loadProgramTextFile(String name) { return loadTextFile(getProgramFile(name)); } static String loadProgramTextFile(String progID, String name) { return loadTextFile(getProgramFile(progID, name)); } static String loadProgramTextFile(String progID, String name, String defaultText) { return loadTextFile(getProgramFile(progID, name), defaultText); } static String loadPage_utf8(URL url) { return loadPage_utf8(url.toString()); } static String loadPage_utf8(String url) { AutoCloseable __1139 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(url); } finally { _close(__1139); }} static String loadPage_utf8(URLConnection con, URL url, boolean addHeaders) throws IOException { AutoCloseable __1144 = tempSetTL(loadPage_charset, "UTF-8"); try { return loadPage(con, url, addHeaders); } finally { _close(__1144); }} static void saveTranspiledCode(String progID, String code) { File dir = getCodeProgramDir(progID); new File(dir, "Transpilation").delete(); saveGZTextFile(new File(dir, "Transpilation.gz"), code); } static void setOpt_raw(Object o, String field, Object value) { try { if (o == null) return; if (o instanceof Class) setOpt_raw((Class) o, field, value); else { Field f = setOpt_raw_findField(o.getClass(), field); if (f != null) { makeAccessible(f); smartSet(f, o, value); } } } catch (Exception __e) { throw rethrow(__e); } } static void setOpt_raw(Class c, String field, Object value) { try { if (c == null) return; Field f = setOpt_raw_findStaticField(c, field); if (f != null) { makeAccessible(f); smartSet(f, null, value); } } catch (Exception __e) { throw rethrow(__e); } } static Field setOpt_raw_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Field setOpt_raw_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static void smartSet(Field f, Object o, Object value) throws Exception { try { f.set(o, value); } catch (Exception e) { Class type = f.getType(); // take care of common case (long to int) if (type == int.class && value instanceof Long) value = ((Long) value).intValue(); if (type == LinkedHashMap.class && value instanceof Map) { f.set(o, asLinkedHashMap((Map) value)); return; } throw e; } } static A setDyn(A o, String key, Object value) { if (o == null) return o; setDynObjectValue(o, key, value); return o; } static List beginCriticalAction_inFlight = synchroList(); static class CriticalAction { String description; CriticalAction() {} CriticalAction(String description) { this.description = description;} void done() { beginCriticalAction_inFlight.remove(this); } } static CriticalAction beginCriticalAction(String description) { ping(); CriticalAction c = new CriticalAction(description); beginCriticalAction_inFlight.add(c); return c; } static void cleanMeUp_beginCriticalAction() { int n = 0; while (nempty(beginCriticalAction_inFlight)) { int m = l(beginCriticalAction_inFlight); if (m != n) { n = m; try { print("Waiting for " + n2(n, "critical actions") + ": " + join(", ", collect(beginCriticalAction_inFlight, "description"))); } catch (Throwable __e) { _handleException(__e); } } sleepInCleanUp(10); } } static File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static FileOutputStream newFileOutputStream(File path) throws IOException { return newFileOutputStream(path.getPath()); } static FileOutputStream newFileOutputStream(String path) throws IOException { return newFileOutputStream(path, false); } static FileOutputStream newFileOutputStream(File path, boolean append) throws IOException { return newFileOutputStream(path.getPath(), append); } static FileOutputStream newFileOutputStream(String path, boolean append) throws IOException { mkdirsForFile(path); FileOutputStream f = new FileOutputStream(path, append); _registerIO(f, path, true); return f; } static File linux_fileInRamDisk(String name) { if (!isLinux()) return null; File dir = newFile("/dev/shm"); if (dir.isDirectory()) return newFile(dir, name); return null; } static String aGlobalID() { return randomID(globalIDLength()); } static boolean isMarkedAsSrcLib(String snippetID) { if (snippetID == null) return false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return isJavaxCompilableSnippetType(rl.getSnippetType(snippetID)); return fileExists(javaxCodeDir("srclibs/" + psI(snippetID))); } static A pairA(Pair p) { return p == null ? null : p.a; } static Object hotwire_onCompile; // voidfunc(Pair) static boolean hotwire_serially = false; static Lock hotwire_overInternalBot_lock = lock(); static boolean hotwire_compileOnServer = false; static Class hotwire_overInternalBot(String progID) { return hotwire_overInternalBot(progID, "main"); } static Class hotwire_overInternalBot(String progID, String mainClass) { try { Pair p; try { p = hotwire_compile(progID); } catch (Throwable e) { throw rethrow("Error hotwiring " + progID, e); } File jar = p.a; assertTrue(jar.getAbsolutePath(), jar.isFile()); List files = hotwire_collectJars(jar); // make class loader JavaXClassLoader classLoader = hotwire_makeClassLoader(files); classLoader.progID = progID; return hotwire_finish(classLoader, progID, p.b, mainClass); } catch (Exception __e) { throw rethrow(__e); } } // returns pair(jar, transpiled src) static Pair hotwire_compile(String progID) { Pair p = hotwire_compileOnServer && !isLocalSnippetID(progID) ? compileSnippetThroughServer(progID) : CompilerBot.compileSnippet2(progID); Lock __1163 = hotwire_serially ? hotwire_overInternalBot_lock : null; lock(__1163); try { callF(hotwire_onCompile, p); return p; } finally { unlock(__1163); } } // If you change this, also change DiskSnippetCache_fileToLibID static File DiskSnippetCache_file(long snippetID) { return new File(getGlobalCache(), "data_" + snippetID + ".jar"); } // Data files are immutable, use centralized cache public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = DiskSnippetCache_file(snippetID); return file.exists() ? file : null; } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static long fileSize(String path) { return getFileSize(path); } static long fileSize(File f) { return getFileSize(f); } static File loadDataSnippetToFile(String snippetID) { try { snippetID = fsI(snippetID); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List urlsTried = new ArrayList(); List errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } // TODO: check if we hit the "LOADING" message if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { //printStackTrace(e); errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static void markAsSrcLib(String snippetID) { saveTextFile(javaxCodeDir("srclibs/" + psI(snippetID)), ""); } static int latestInstalledJavaX() { File[] files = new File(userHome(), ".javax").listFiles(); int v = 0; if (files != null) for (File f : files) { Matcher m = Pattern.compile("x(\\d\\d\\d?)\\.jar").matcher(f.getName()); if (m.matches()) v = Math.max(v, Integer.parseInt(m.group(1))); } return v; } static String x30JarServerURL() { return "http://botcompany.de:8081/x30.jar"; } static ThreadLocal>> loadBinaryPage_responseHeaders = new ThreadLocal(); static ThreadLocal> loadBinaryPage_extraHeaders = new ThreadLocal(); static byte[] loadBinaryPage(String url) { try { print("Loading " + url); return loadBinaryPage(loadPage_openConnection(new URL(url))); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage(URLConnection con) { try { Map extraHeaders = getAndClearThreadLocal(loadBinaryPage_extraHeaders); setHeaders(con); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); return loadBinaryPage_noHeaders(con); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage_noHeaders(URLConnection con) { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); loadBinaryPage_responseHeaders.set(con.getHeaderFields()); long len = 0; try { len = con.getContentLength/*Long*/(); } catch (Throwable e) { printStackTrace(e); } int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) println(" " + n + (len != 0 ? "/" + len : "") + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } /** writes safely (to temp file, then rename) */ public static byte[] saveBinaryFile(String fileName, byte[] contents) { try { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = newFileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); vmBus_send("wroteFile", file); return contents; } catch (Exception __e) { throw rethrow(__e); } } static byte[] saveBinaryFile(File fileName, byte[] contents) { return saveBinaryFile(fileName.getPath(), contents); } static String repeat(char c, int n) { n = Math.max(n, 0); char[] chars = new char[n]; for (int i = 0; i < n; i++) chars[i] = c; return new String(chars); } static List repeat(A a, int n) { n = Math.max(n, 0); List l = new ArrayList(n); for (int i = 0; i < n; i++) l.add(a); return l; } static List repeat(int n, A a) { return repeat(a, n); } static int indent_default = 2; static String indent(int indent) { return repeat(' ', indent); } static String indent(int indent, String s) { return indent(repeat(' ', indent), s); } static String indent(String indent, String s) { return indent + s.replace("\n", "\n" + indent); } static String indent(String s) { return indent(indent_default, s); } static List indent(String indent, List lines) { List l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } static String addSuffix(String s, String suffix) { return s == null || s.endsWith(suffix) ? s : s + suffix; } static List filesWithExtension(String ext, List files) { return filesEndingWith(files, addPrefixIfNotEmpty2(".", ext)); } static List findAllFiles_noDirs(List dirs) { return findAllFiles_noDirs(asObjectArray(dirs)); } // dirs are String's or File's static List findAllFiles_noDirs(Object... dirs) { List l = new ArrayList(); for (Object dir : dirs) { if (dir instanceof String && ((String) dir).endsWith("/.")) { // "/." means non-recurse for (File f : listFiles(dropSuffix("/.", (String) dir))) if (f.isFile()) l.add(f); } else findAllFiles_noDirs_impl(toFile(dir), l); } return l; } static void findAllFiles_noDirs_impl(File dir, List l) { for (File f : listFiles(dir)) { if (f.isDirectory()) findAllFiles_noDirs_impl(f, l); else l.add(f); } } static File[] listFiles(File dir) { File[] files = dir.listFiles(); return files == null ? new File[0] : files; } static File[] listFiles(String dir) { return listFiles(new File(dir)); } static List sortFilesByName(List l) { sort(l, new Comparator() { public int compare(File a, File b) { return stdcompare(a.getName(), b.getName()); } }); return l; } static void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static int deleteAllFilesInDirectory_minPathLength = 10; static void deleteAllFilesInDirectory(File dir) { deleteAllFilesInDirectory(dir, false, false); } static void deleteAllFilesInDirectory(File dir, boolean verbose, boolean testRun) { dir = getCanonicalFile(dir); assertTrue(f2s(dir), l(f2s(dir)) >= deleteAllFilesInDirectory_minPathLength); File[] files = dir.listFiles(); if (files == null) return; for (File f : files) { if (!isSymLink(f) && f.isDirectory()) // just delete the symlink, don't follow it deleteDirectory(f, verbose, testRun); else { if (verbose) print((testRun ? "Would delete " : "Deleting ") + f.getAbsolutePath()); if (!testRun) f.delete(); } } } static Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static TreeSet caseInsensitiveSet_treeSet() { return new TreeSet(caseInsensitiveComparator()); } static TreeSet caseInsensitiveSet_treeSet(Collection c) { return toCaseInsensitiveSet_treeSet(c); } static String myJavaSource_code; static String myJavaSource() { return myJavaSource_code; } static Producer javaTokC_noMLS_iterator(final String s) { return javaTokC_noMLS_iterator(s, 0); } static Producer javaTokC_noMLS_iterator(final String s, final int startIndex) { return new Producer() { final int l = s.length(); int i = startIndex; public String next() { if (i >= l) return null; int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) return null; c = s.charAt(i); d = i+1 >= l ? '\0' : s.charAt(i+1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't" else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L } else ++j; String t = quickSubstring(s, i, j); i = j; return t; } }; } static Producer javaTokC_noMLS_onReader(final BufferedReader r) { final class X implements Producer { StringBuilder buf = new StringBuilder(); // stores from "i" char c, d, e = 'x'; // just not '\0' X() { // fill c, d and e nc(); nc(); nc(); } // get next character(s) into c, d and e void nc() { try { c = d; d = e; if (e == '\0') return; int i = r.read(); e = i < 0 ? '\0' : i == '\0' ? '_' // shouldn't happen anymore : (char) i; } catch (Exception __e) { throw rethrow(__e); } } void ncSave() { if (c != '\0') { buf.append(c); nc(); } } public String next() { // scan for whitespace while (c != '\0') { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') nc(); else if (c == '/' && d == '*') { do nc(); while (c != '\0' && !(c == '*' && d == '/')); nc(); nc(); } else if (c == '/' && d == '/') { do nc(); while (c != '\0' && "\r\n".indexOf(c) < 0); } else break; } if (c == '\0') return null; // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ncSave(); while (c != '\0') { if (c == opener || c == '\n') { // end at \n to not propagate unclosed string literal errors ncSave(); break; } else if (c == '\\') { ncSave(); ncSave(); } else ncSave(); } } else if (Character.isJavaIdentifierStart(c)) do ncSave(); while (Character.isJavaIdentifierPart(c) || c == '\''); // for stuff like "don't" else if (Character.isDigit(c)) { do ncSave(); while (Character.isDigit(c)); if (c == 'L') ncSave(); // Long constants like 1L } else ncSave(); String t = buf.toString(); buf.setLength(0); return t; } } return new X(); } static Object _defaultClassFinder_value = defaultDefaultClassFinder(); static Object _defaultClassFinder() { return _defaultClassFinder_value; } static String unquoteUsingCharArray(String s, char[] buf) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i+1, s.length()-i-1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length()-1 : s.length(); if (l > buf.length) return unquote(s); // fallback int n = 0; for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } buf[n++] = (char) Integer.parseInt(code, 8); continue; } switch (nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt( "" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); char[] x = Character.toChars(code); int lx = x.length; for (int j = 0; j < lx; j++) buf[n++] = x[j]; i += 5; continue; default: ch = nextChar; // added by Stefan } i++; } buf[n++] = ch; } return new String(buf, 0, n); } } return s; // not quoted - return original } static boolean structure_isMarker(String s, int i, int j) { if (i >= j) return false; if (s.charAt(i) != 'm') return false; ++i; while (i < j) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static String internIfLongerThan(String s, int l) { return s == null ? null : l(s) >= l ? intern(s) : s; } static char unquoteCharacter(String s) { assertTrue(s.startsWith("'") && s.length() > 1); return unquote("\"" + s.substring(1, s.endsWith("'") ? s.length()-1 : s.length()) + "\"").charAt(0); } static double parseDouble(String s) { return Double.parseDouble(s); } static float parseFloat(String s) { return Float.parseFloat(s); } static TreeMap ciMap() { return caseInsensitiveMap(); } static List parseList(String s) { return (List) safeUnstructure(s); } static List synchroLinkedList() { return Collections.synchronizedList(new LinkedList()); } static byte[] hexToBytes(String s) { if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s))); int n = l(s) / 2; byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { int a = parseHexChar(s.charAt(i*2)); int b = parseHexChar(s.charAt(i*2+1)); if (a < 0 || b < 0) throw fail("Bad hex byte: " + quote(substring(s, i*2, i*2+2)) + " at " + i*2 + "/" + l(s)); bytes[i] = (byte) ((a << 4) | b); } return bytes; } static boolean[] boolArrayFromBytes(byte[] a, int n) { boolean[] b = new boolean[n]; int m = min(n, l(a)*8); for (int i = 0; i < m; i++) b[i] = (a[i/8] & 1 << (i & 7)) != 0; return b; } static HashMap findClass_fullName_cache = new HashMap(); // returns null on not found // this is the simple version that is not case-tolerant static Class findClass_fullName(String name) { synchronized(findClass_fullName_cache) { if (findClass_fullName_cache.containsKey(name)) return findClass_fullName_cache.get(name); Class c; try { c = Class.forName(name); } catch (ClassNotFoundException e) { c = null; } findClass_fullName_cache.put(name, c); return c; } } static A nuStubInnerObject(Class c) { return nuStubInnerObject(c, null); } static A nuStubInnerObject(Class c, Object classFinder) { try { Class outerType = getOuterClass(c, classFinder); Constructor m = c.getDeclaredConstructor(outerType); makeAccessible(m); return (A) m.newInstance(new Object[] {null}); } catch (Exception __e) { throw rethrow(__e); } } static Map nuEmptyObject_cache = newDangerousWeakHashMap(); static A nuEmptyObject(Class c) { try { Constructor ctr; synchronized(nuEmptyObject_cache) { ctr = nuEmptyObject_cache.get(c); if (ctr == null) { nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c)); makeAccessible(ctr); } } try { return (A) ctr.newInstance(); } catch (InstantiationException e) { if (empty(e.getMessage())) if ((c.getModifiers() & Modifier.ABSTRACT) != 0) throw fail("Can't instantiate abstract class " + className(c), e); else throw fail("Can't instantiate " + className(c), e); else throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuEmptyObject_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } static HashMap findClass_cache = new HashMap(); // currently finds only inner classes of class "main" // returns null on not found // this is the simple version that is not case-tolerant static Class findClass(String name) { synchronized(findClass_cache) { if (findClass_cache.containsKey(name)) return findClass_cache.get(name); if (!isJavaIdentifier(name)) return null; Class c; try { c = Class.forName("main$" + name); } catch (ClassNotFoundException e) { c = null; } findClass_cache.put(name, c); return c; } } static void setOptAllDyn(DynamicObject o, Map fields) { if (fields == null) return; HashMap fieldMap = instanceFieldsMap(o); for (Map.Entry e : fields.entrySet()) { String field = e.getKey(); Object val = e.getValue(); boolean has = fieldMap.containsKey(field); if (has) setOpt(o, field, val); else { o.fieldValues = syncMapPut2_createLinkedHashMap(o.fieldValues, intern(field), val); } } } static void setOptAll_pcall(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) try { setOpt(o, field, fields.get(field)); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } static void setOptAll_pcall(Object o, Object... values) { //values = expandParams(c.getClass(), values); warnIfOddCount(values); for (int i = 0; i+1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i+1]; try { setOpt(o, field, value); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } } static void fixOuterRefs(Object o) { try { if (o == null) return; Field[] l = thisDollarOneFields(o.getClass()); if (l.length <= 1) return; Object father = null; for (Field f : l) { father = f.get(o); if (father != null) break; } if (father == null) return; for (Field f : l) f.set(o, father); } catch (Exception __e) { throw rethrow(__e); } } static void setDynObjectValue(DynamicObject o, String field, Object value) { o.fieldValues = syncMapPut2_createLinkedHashMap(o.fieldValues, field, value); } static String intern(String s) { return fastIntern(s); } static void pcallOpt_noArgs(Object o, String method) { try { callOpt_noArgs(o, method); } catch (Throwable __e) { _handleException(__e); } } static int[] toIntArray(List l) { int[] a = new int[l(l)]; for (int i = 0; i < a.length; i++) a[i] = l.get(i); return a; } static boolean jmatch(String pat, String s) { return jmatch(pat, s, null); } static boolean jmatch(String pat, String s, Matches matches) { if (s == null) return false; return jmatch(pat, javaTok(s), matches); } static boolean jmatch(String pat, List toks) { return jmatch(pat, toks, null); } static boolean jmatch(String pat, List toks, Matches matches) { List tokpat = javaTok(pat); String[] m = match2(tokpat, toks); //print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static Object nuObject(String className, Object... args) { try { return nuObject(classForName(className), args); } catch (Exception __e) { throw rethrow(__e); } } // too ambiguous - maybe need to fix some callers /*static O nuObject(O realm, S className, O... args) { ret nuObject(_getClass(realm, className), args); }*/ static A nuObject(Class c, Object... args) { try { if (args.length == 0) return nuObjectWithoutArguments(c); // cached! Constructor m = nuObject_findConstructor(c, args); makeAccessible(m); return (A) m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : "")); } static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static boolean warn_on = true; static ThreadLocal> warn_warnings = new ThreadLocal(); static void warn(String s) { if (warn_on) print("Warning: " + s); } static void warn(String s, List warnings) { warn(s); if (warnings != null) warnings.add(s); addToCollection(warn_warnings.get(), s); } static Throwable getInnerException(Throwable e) { if (e == null) return null; while (e.getCause() != null) e = e.getCause(); return e; } static Throwable getInnerException(Runnable r) { return getInnerException(getException(r)); } static void put(Map map, A a, B b) { if (map != null) map.put(a, b); } static void put(List l, int i, A a) { if (l != null && i >= 0 && i < l(l)) l.set(i, a); } static List _registerDangerousWeakMap_preList; static A _registerDangerousWeakMap(A map) { return _registerDangerousWeakMap(map, null); } static A _registerDangerousWeakMap(A map, Object init) { callF(init, map); if (init instanceof String) { final String f = (String) init; init = new VF1() { public void get(Map map) { try { callMC(f, map) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callMC(f, map)"; }}; } if (javax() == null) { // We're in class init if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList(); _registerDangerousWeakMap_preList.add(pair(map, init)); return map; } call(javax(), "_registerDangerousWeakMap", map, init); return map; } static void _onLoad_registerDangerousWeakMap() { assertNotNull(javax()); if (_registerDangerousWeakMap_preList == null) return; for (Pair p : _registerDangerousWeakMap_preList) _registerDangerousWeakMap(p.a, p.b); _registerDangerousWeakMap_preList = null; } static B mapGet2(Map map, A a) { return map == null ? null : map.get(a); } static B mapGet2(A a, Map map) { return map == null ? null : map.get(a); } static boolean isSubtypeOf(Class a, Class b) { return b.isAssignableFrom(a); // << always hated that method, let's replace it! } static Set reflection_classesNotToScan_value = litset( "jdk.internal.loader.URLClassPath" ); static Set reflection_classesNotToScan() { return reflection_classesNotToScan_value; } static List classNames(Collection l) { return getClassNames(l); } static List classNames(Object[] l) { return getClassNames(Arrays.asList(l)); } static List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static void multiMapPut(Map> map, A a, B b) { List l = map.get(a); if (l == null) map.put(a, l = new ArrayList()); l.add(b); } static Throwable getExceptionCause(Throwable e) { Throwable c = e.getCause(); return c != null ? c : e; } static boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static String rep(int n, char c) { return repeat(c, n); } static String rep(char c, int n) { return repeat(c, n); } static List rep(A a, int n) { return repeat(a, n); } static List rep(int n, A a) { return repeat(n, a); } static Class getMainClass() { return mc(); } static Class getMainClass(Object o) { try { if (o == null) return null; if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o; return (o instanceof Class ? (Class) o : o.getClass()).getClassLoader().loadClass("main"); } catch (Exception __e) { throw rethrow(__e); } } static ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } static Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } static void addToContainer(final Container a, final Component b) { if (a != null && b != null) { swing(new Runnable() { public void run() { try { a.add(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.add(b);"; }}); } } static String trimSubstring(String s, int x) { return trim(substring(s, x)); } static String trimSubstring(String s, int x, int y) { return trim(substring(s, x, y)); } static String trimSubstring(String s, IntRange r) { return trim(substring(s, r)); } static int smartLastIndexOf(String s, char c) { if (s == null) return 0; int i = s.lastIndexOf(c); return i >= 0 ? i : l(s); } static File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static String or2(String a, String b) { return nempty(a) ? a : b; } static String or2(String a, String b, String c) { return or2(or2(a, b), c); } static String getFileInfoField(File f, String field) { return getOneLineFileInfoField(f, field); } static File dropExtension(File f) { return f == null ? null : fileInSameDir(f, dropExtension(f.getName())); } static String dropExtension(String s) { return takeFirst(s, smartLastIndexOf(s, '.')); } static File javaxDataDir_dir; // can be set to work on different base dir static File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static String htmlQuery(Map params) { return empty(params) ? "" : "?" + makePostData(params); } static String htmlQuery(Object... data) { return empty(data) ? "" : "?" + makePostData(data); } static Object[] muricaCredentials() { String pass = muricaPassword(); return nempty(pass) ? new Object[] {"_pass", pass } : new Object[0]; } static boolean saveTextFileIfDifferent(File f, String contents) { if (eq(loadTextFile(f), contents)) return false; { saveTextFile(f, contents); return true; } } // PersistableThrowable doesn't hold GC-disturbing class references in backtrace static volatile PersistableThrowable lastException_lastException; static PersistableThrowable lastException() { return lastException_lastException; } static void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static String baseClassName(String className) { return substring(className, className.lastIndexOf('.')+1); } static String baseClassName(Object o) { return baseClassName(getClassName(o)); } static String prependIfNempty(String prefix, String s) { return empty(s) ? s : prefix + s; } static String lastIdentifier(List l) { for (int i = l(l)-1; i >= 0; i--) { String t = l.get(i); if (isIdentifier(t)) return t; } return null; } static List tok_parseArgsList(String s) { return tok_parseArgsList(javaTok(s)); } static List tok_parseArgsList(List tok) { return tok_parseArgsList(tok, getBracketMap(tok)); } static List tok_parseArgsList(List tok, Map bracketMap) { int i = indexOfAny(tok, 0, "(", "{"); if (i < 0) return null; if (eq(get(tok, i), "{")) return ll(); // e.g. void bla { ... } int argStart = (i += 2); List args = new ArrayList(); while (i < l(tok)-2 && neq(get(tok, i), ")")) { Integer j = bracketMap.get(i); if (j != null) { i = j+2; continue; } if (eqGetOneOf(tok, i, ",")) { if (i > argStart) args.add(trimJoinSubList(tok, argStart, i)); argStart = i+2; } i += 2; } if (i > argStart) args.add(trimJoinSubList(tok, argStart, i)); return args; } static HashSet getBracketMapIncludingAngleBrackets_opening = lithashset("(", "{", "<"); static HashSet getBracketMapIncludingAngleBrackets_closing = lithashset(")", "}", ">"); static Map getBracketMapIncludingAngleBrackets(List tok) { return getBracketMap(tok, getBracketMapIncludingAngleBrackets_opening, getBracketMapIncludingAngleBrackets_closing); } static Map getBracketMapIncludingAngleBrackets(List tok, int from, int to) { return getBracketMap(tok, getBracketMapIncludingAngleBrackets_opening, getBracketMapIncludingAngleBrackets_closing, from, to); } static String beautifyStructure(String s) { List tok = javaTok(s); structure_addTokenMarkers(tok); jreplace(tok, "lhm", ""); return join(tok); } static String struct_noStringSharing(Object o) { structure_Data d = new structure_Data(); d.noStringSharing = true; return structure(o, d); } static TreeSet toCaseInsensitiveSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet(); addAll(set, c); return set; } static TreeSet toCaseInsensitiveSet(String... x) { TreeSet set = caseInsensitiveSet(); addAll(set, x); return set; } // works on lists and strings and null static int indexOfIgnoreCase(List a, String b) { return indexOfIgnoreCase(a, b, 0); } static int indexOfIgnoreCase(List a, String b, int i) { int n = a == null ? 0 : a.size(); for (; i < n; i++) if (eqic(a.get(i), b)) return i; return -1; } static int indexOfIgnoreCase(String a, String b) { return indexOfIgnoreCase_manual(a, b); /*Matcher m = Pattern.compile(b, Pattern.CASE_INSENSITIVE + Pattern.LITERAL).matcher(a); if (m.find()) return m.start(); else ret -1;*/ } static boolean boolOptParam(ThreadLocal tl) { return isTrue(optPar(tl)); } // defaults to false static boolean boolOptParam(Object[] __, String name) { return isTrue(optParam(__, name)); } static boolean boolOptParam(String name, Object[] __) { return boolOptParam(__, name); } static boolean boolOptParam(String name, Map __) { return isTrue(optPar(name, __)); } static String getInnerMessage(Throwable e) { if (e == null) return null; return getInnerException(e).getMessage(); } static Matcher regexpIC(Pattern pat, String s) { return pat.matcher(unnull(s)); } static Matcher regexpIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static Pattern regexpIC(String pat) { return compileRegexpIC(pat); } // usually L static String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static String fromLines(String... lines) { return fromLines(asList(lines)); } static IterableIterator toLines(File f) { return linesFromFile(f); } static List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i+1 < s.length() && s.charAt(i+1) == '\n') i += 2; else ++i; start = i; } return lines; } static int toLines_nextLineBreak(String s, int start) { for (int i = start; i < s.length(); i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2+i, a.get(i1+i)); } static File getProgramDir() { return programDir(); } static File getProgramDir(String snippetID) { return programDir(snippetID); } // scans a Java construct (class, method) and checks its modifiers static boolean hasModifier(List tok, String modifier) { for (int i = 1; i < tok.size() && getJavaModifiers().contains(tok.get(i)); i += 2) if (tok.get(i).equals(modifier)) return true; return false; } static A optParam(ThreadLocal tl, A defaultValue) { return optPar(tl, defaultValue); } static A optParam(ThreadLocal tl) { return optPar(tl); } static Object optParam(String name, Map params) { return mapGet(params, name); } // now also takes a map as single array entry static A optParam(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } if (!even(l(opt))) throw fail("Odd parameter length"); for (int i = 0; i < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i+1]; return defaultValue; } static Object optParam(Object[] opt, String name) { return optParam(opt, name, null); } static int minUnlessMinus1(int a, int b) { return a == -1 ? b : b == -1 ? a : min(a, b); } static int hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static List pairsB(Collection> l) { return secondOfPairs(l); } static String reversedString(String s) { return reverseString(s); } static Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } static char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } static void tokAppend_reTok(List tok, int i, String s) { tok.set(i, tok.get(i)+s); reTok(tok, i, i+1); } static List allToUpper(Collection l) { List x = new ArrayList(l(l)); if (l != null) for (String s : l) x.add(upper(s)); return x; } static void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static String asString(Object o) { return o == null ? null : o.toString(); } static boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } static boolean nemptyString(String s) { return s != null && s.length() > 0; } static int listL(Collection l) { return l == null ? 0 : l.size(); } static char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s)-1); } static String[] dropLast(String[] a, int n) { n = Math.min(n, a.length); String[] b = new String[a.length-n]; System.arraycopy(a, 0, b, 0, b.length); return b; } static List dropLast(List l) { return subList(l, 0, l(l)-1); } static List dropLast(int n, List l) { return subList(l, 0, l(l)-n); } static List dropLast(Iterable l) { return dropLast(asList(l)); } static String dropLast(String s) { return substring(s, 0, l(s)-1); } static String dropLast(String s, int n) { return substring(s, 0, l(s)-n); } static String dropLast(int n, String s) { return dropLast(s, n); } // i must point at the opening bracket ("<") // index returned is index of closing bracket or comma static int tok_findEndOfTypeArg(List cnc, int i) { int j = i+2, level = 1; while (j < cnc.size()) { String t = cnc.get(j); if (t.equals("<")) ++level; else if (t.equals(">")) --level; if (level == 0 || level == 1 && eq(t, ",")) return j; ++j; } return cnc.size(); } static List getJavaModifiers_list = litlist("static", "abstract", "public", "private", "protected", "final", "native", "volatile", "synchronized", "transient"); static List getJavaModifiers() { return getJavaModifiers_list; } // returns index of "{" or ";" static int tok_findEndOfMethodHeader(List tok, int i) { i |= 1; int level = 0; while (i < l(tok)) { String t = tok.get(i); if (eq(t, "(")) ++level; else if (eq(t, ")")) --level; else if (level == 0 && eqOneOf(t, "{", ";")) return i; i += 2; } return i; } static int indexOfOneOf(List l, int i, A... x) { return indexOfAny(l, i, x); } static int indexOfOneOf(List l, Collection x) { return indexOfAny(l, x); } static int indexOfOneOf(List l, int i, Collection x) { return indexOfAny(l, i, x); } static int indexOfOneOf(String s, int i, String chars) { return indexOfAny(s, i, chars); } static Object evalJava(String code) { return evalJava_main(evalJava_prep(code)); } static ThreadLocal assertVerbose_value = new ThreadLocal(); static void assertVerbose(boolean b) { assertVerbose_value.set(b); } static boolean assertVerbose() { return isTrue(assertVerbose_value.get()); } static A assertEqualsVerbose(Object x, A y) { assertEqualsVerbose((String) null, x, y); return y; } static A assertEqualsVerbose(String msg, Object x, A y) { if (!eq(x, y)) { throw fail((msg != null ? msg + ": " : "") + /*sfu*/(y) + " != " + /*sfu*/(x)); } else print("OK: " + /*sfu*/(x)); return y; } static byte[] boolArrayToBytes(boolean[] a) { byte[] b = new byte[(l(a)+7)/8]; for (int i = 0; i < l(a); i++) if (a[i]) b[i/8] |= 1 << (i & 7); return b; } static String shortClassName(Object o) { if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return shortenClassName(name); } static int cmp(Number a, Number b) { return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue()); } static int cmp(double a, double b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(Object a, Object b) { if (a == null) return b == null ? 0 : -1; if (b == null) return 1; return ((Comparable) a).compareTo(b); } static boolean isDigit(char c) { return Character.isDigit(c); } static boolean endsWithLetter(String s) { return nempty(s) && isLetter(last(s)); } static void assertFalse(Object o) { if (!(eq(o, false) /*|| isFalse(pcallF(o))*/)) throw fail(str(o)); } static boolean assertFalse(boolean b) { if (b) throw fail("oops"); return b; } static boolean assertFalse(String msg, boolean b) { if (b) throw fail(msg); return b; } static boolean _inCore() { return false; } static List hotwire_copyOver_after = synchroList(); static void hotwire_copyOver(Class c) { // TODO: make a mechanism for making such "inheritable" fields for (String field : ll("print_log", "print_silent", "androidContext", "_userHome")) setOptIfNotNull(c, field, getOpt(mc(), field)); setOptIfNotNull(c, "mainBot" , getMainBot()); setOpt(c, "creator_class" , new WeakReference(mc())); pcallFAll(hotwire_copyOver_after, c); } static Pair testBracketHygiene2(String s) { return testBracketHygiene2(s, testBracketHygiene_op, testBracketHygiene_close); } static Pair testBracketHygiene2(String s, String op, String close) { List tok = javaTok(s); Map map = new HashMap(); List stack = getBracketMap2(tok, map, op, close); for (int i = 1; i < l(tok); i += 2) if (isUnproperlyQuoted(tok.get(i))) { int lineNr = tokenIndexToUserLandLineNr(tok, i); return pair(tokenToCharIndex(tok, i), "Unclosed string literal at line " + lineNr); } for (int i : keys(map)) { int j = map.get(i); String a = tok.get(i), b = tok.get(j); int ai = op.indexOf(a), bi = close.indexOf(b); if (ai != bi) { int lineNr1 = tokenIndexToUserLandLineNr(tok, i); int lineNr2 = tokenIndexToUserLandLineNr(tok, j); return pair(tokenToCharIndex(tok, /*tossCoin() ?*/ i /*: j*/), "Bad hygiene - brackets don't match (" + quote(a) + " vs " + quote(b) + ") at lines " + lineNr1 + " and " + lineNr2); } } if (nempty(stack)) { int lineNr = tokenIndexToUserLandLineNr(tok, last(stack)); return pair(tokenIndexToCharIndex(tok, last(stack)), "Line " + lineNr + ": " + "Bad hygiene - " + n(l(stack), "bracket") + " not closed"); } if (map.containsKey(0)) { int lineNr = tokenIndexToUserLandLineNr(tok, map.get(0)); return pair(tokenToCharIndex(tok, map.get(0)), "Bad hygiene - bracket not opened (" + quote(tok.get(map.get(0))) + ") at line " + lineNr); } return null; } static List wrapArrayAsList(A[] a) { return a == null ? null : Arrays.asList(a); } static String afterLineBreak(String s) { return substring(s, lastIndexOf(s, '\n')+1); } static String beforeLineBreak(String s) { int i = smartIndexOf(s, '\n'); if (i > 0 && s.charAt(i-1) == '\r') --i; return substring(s, 0, i); } static String standardCredentialsUser() { return trim(loadTextFile( oneOfTheFiles( javaxSecretDir("tinybrain-username"), userDir(".tinybrain/username")))); } static String standardCredentialsPass() { return trim(loadTextFile( oneOfTheFiles( javaxSecretDir("tinybrain-userpass"), userDir(".tinybrain/userpass")))); } static boolean isProperlyQuoted(String s) { return s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"") && (!s.endsWith("\\\"") || s.endsWith("\\\\\"")) && !containsNewLine(s); } static Matcher regexp(String pat, String s) { return regexp(compileRegexp(pat), unnull(s)); } static Matcher regexp(Pattern pat, String s) { return pat.matcher(unnull(s)); } static Pattern regexp(String pat) { return compileRegexp(pat); } static boolean jsonDecode_useOrderedMaps = true; static Object jsonDecode(final String text) { final List tok = jsonTok(text); if (l(tok) == 1) return null; class Y { int i = 1; Object parse() { String t = tok.get(i); if (t.startsWith("\"")) { String s = unquote(tok.get(i)); i += 2; return s; } if (t.equals("{")) return parseMap(); if (t.equals("[")) return this.parseList(); // avoid loading standard function "parseList" if (t.equals("null")) { i += 2; return null; } if (t.equals("false")) { i += 2; return false; } if (t.equals("true")) { i += 2; return true; } boolean minus = false; if (t.equals("-")) { minus = true; i += 2; t = get(tok, i); } if (isInteger(t)) { i += 2; if (eq(get(tok, i), ".")) { String x = t + "." + get(tok, i+2); i += 4; double d = parseDouble(x); if (minus) d = -d; return d; } else { long l = parseLong(t); if (minus) l = -l; return l != (int) l ? new Long(l) : new Integer((int) l); } } throw new RuntimeException("Unknown token " + (i+1) + ": " + t + ": " + text); } Object parseList() { consume("["); List list = new ArrayList(); while (!tok.get(i).equals("]")) { list.add(parse()); if (tok.get(i).equals(",")) i += 2; } consume("]"); return list; } Object parseMap() { consume("{"); Map map = jsonDecode_useOrderedMaps ? new LinkedHashMap() : new TreeMap(); while (!tok.get(i).equals("}")) { String key = unquote(tok.get(i)); i += 2; consume(":"); Object value = parse(); map.put(key, value); if (tok.get(i).equals(",")) i += 2; } consume("}"); return map; } void consume(String s) { if (!tok.get(i).equals(s)) { String prevToken = i-2 >= 0 ? tok.get(i-2) : ""; String nextTokens = join(tok.subList(i, Math.min(i+4, tok.size()))); throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")"); } i += 2; } } return new Y().parse(); } static String makePostData(Map map) { StringBuilder buf = new StringBuilder(); for (Map.Entry e : map.entrySet()) { String key = (String) (e.getKey()); Object val = e.getValue(); if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/(value))); } } return str(buf); } static String makePostData(Object... params) { StringBuilder buf = new StringBuilder(); int n = l(params); for (int i = 0; i+1 < n; i += 2) { String key = (String) (params[i]); Object val = params[i+1]; if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/(value))); } } return str(buf); } static A optPar(ThreadLocal tl, A defaultValue) { A a = tl.get(); if (a != null) { tl.set(null); return a; } return defaultValue; } static A optPar(ThreadLocal tl) { return optPar(tl, null); } static Object optPar(Object[] params, String name) { return optParam(params, name); } static Object optPar(String name, Object[] params) { return optParam(params, name); } static Object optPar(String name, Map params) { return optParam(name, params); } static A optPar(Object[] params, String name, A defaultValue) { return optParam(params, name, defaultValue); } static A optPar(String name, Object[] params, A defaultValue) { return optParam(params, name, defaultValue); } static int lUtf8(String s) { return l(utf8(s)); } static List tlft(String s) { return toLinesFullTrim(s); } static List tlft(File f) { return toLinesFullTrim(f); } static String joinLines(List lines) { return fromLines(lines); } static String joinLines(String glue, String text) { return join(glue, toLines(text)); } static String javaDropComments(String s) { return javaDropAllComments(s); } // returns index of trailing N token static int scanToEndOfInitializer(List tok, Map bracketMap, int i) { while (i < l(tok)) { if (eqOneOf(tok.get(i), ";", ",", ")", "}")) return i-1; Integer j = bracketMap.get(i); if (j != null) i = j+1; else i++; } return i; } static boolean odd(int i) { return (i & 1) != 0; } static boolean odd(long i) { return (i & 1) != 0; } static boolean odd(BigInteger i) { return odd(toInt(i)); } static final Map callOpt_cache = newDangerousWeakHashMap(); static Object callOpt_cached(Object o, String methodName, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); // TODO: (super-rare) case where method exists static and non-static // with different args Method me = cache.findMethod(methodName, args); if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null) return null; return invokeMethod(me, o, args); } } catch (Exception __e) { throw rethrow(__e); } } static _MethodCache callOpt_getCache(Class c) { synchronized(callOpt_cache) { _MethodCache cache = callOpt_cache.get(c); if (cache == null) callOpt_cache.put(c, cache = new _MethodCache(c)); return cache; } } static boolean isStaticMethod(Method m) { return methodIsStatic(m); } static Object[] massageArgsForVarArgsCall(Method m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length-1, nArgs = args.length; if (nArgs < n) return null; for (int i = 0; i < n; i++) if (!argumentCompatibleWithType(args[i], types[i])) return null; Class varArgType = types[n].getComponentType(); for (int i = n; i < nArgs; i++) if (!argumentCompatibleWithType(args[i], varArgType)) return null; Object[] newArgs = new Object[n+1]; arraycopy(args, 0, newArgs, 0, n); Object[] varArgs = arrayOfType(varArgType, nArgs-n); arraycopy(args, n, varArgs, 0, nArgs-n); newArgs[n] = varArgs; return newArgs; } static List dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static Map stdFunctions_cached_map; // name -> snippet ID static Lock stdFunctions_cached_lock = lock(); static Map stdFunctions_cached() { Lock __1455 = stdFunctions_cached_lock; lock(__1455); try { if (stdFunctions_cached_map == null) stdFunctions_cached_map = stdFunctions_uncached(); return stdFunctions_cached_map; } finally { unlock(__1455); } } static synchronized void stdFunctions_clearCache() { stdFunctions_cached_map = null; } static List> hotwire_classes = synchroList(); static Class hotwireDependent(String src) { Class c = hotwire(src); makeDependent(c); return c; } static volatile Object isAllowed_function; // func(S, O[]) -> bool static volatile boolean isAllowed_all = true; static boolean isAllowed(String askingMethod, Object... args) { // check on VM level Object f = vm_generalMap_get("isAllowed_function"); if (f != null && !isTrue(callF(f, askingMethod, args))) return false; // check locally return isAllowed_all || isTrue(callF(isAllowed_function, askingMethod, args)); } static volatile boolean sleep_noSleep = false; static void sleep(long ms) { ping(); if (ms < 0) return; // allow spin locks if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static long round(double d) { return Math.round(d); } static String hmsWithColons() { return hmsWithColons(now()); } static String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } static boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static String hostNameFromURL(String url) { try { return new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static String getComputerID_quick() { return computerID(); } static Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static String joinNemptiesWithColonSpace(String... strings) { return joinNempties(": ", strings); } static String joinNemptiesWithColonSpace(Collection strings) { return joinNempties(": ", strings); } static String tryToReadErrorStreamFromURLConnection(URLConnection conn) { try { if (conn instanceof HttpURLConnection) return stream2string(((HttpURLConnection) conn).getErrorStream()); // TODO: ensure some max length return null; } catch (Throwable __e) { return null; } } static int gzInputStream_defaultBufferSize = 65536; static GZIPInputStream gzInputStream(File f) { try { return gzInputStream(new FileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(File f, int bufferSize) { try { return gzInputStream(new FileInputStream(f), bufferSize); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(InputStream in) { return gzInputStream(in, gzInputStream_defaultBufferSize); } static GZIPInputStream gzInputStream(InputStream in, int bufferSize) { try { return _registerIOWrap(new GZIPInputStream(in, gzInputStream_defaultBufferSize), in); } catch (Exception __e) { throw rethrow(__e); } } static Map compileRegexp_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexp(String pat) { java.util.regex.Pattern p = compileRegexp_cache.get(pat); if (p == null) { compileRegexp_cache.put(pat, p = java.util.regex.Pattern.compile(pat)); } return p; } static Throwable unwrapTrivialExceptionWraps(Throwable e) { if (e == null) return e; while (e.getClass() == RuntimeException.class && e.getCause() != null && eq(e.getMessage(), str(e.getCause()))) e = e.getCause(); return e; } static String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static Object vmBus_wrapArgs(Object... args) { return empty(args) ? null : l(args) == 1 ? args[0] : args; } static void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static Set vm_busListeners_live_cache; static Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache; } static Set vm_busListeners_live_load() { return vm_generalIdentityHashSet("busListeners"); } static Map vm_busListenersByMessage_live_cache; static Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache; } static Map vm_busListenersByMessage_live_load() { return vm_generalHashMap("busListenersByMessage"); } static A printException(A e) { printStackTrace(e); return e; } static A assertNotNull(A a) { assertTrue(a != null); return a; } static A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static Map synchroHashMap() { return Collections.synchronizedMap(new HashMap()); } static void consoleSetInput(final String text) { if (headless()) return; setTextAndSelectAll(consoleInputField(), text); focusConsole(); } static boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } static Map vm_generalMap_map; static Map vm_generalMap() { if (vm_generalMap_map == null) vm_generalMap_map = (Map) get(javax(), "generalMap"); return vm_generalMap_map; } static String loadGZTextFile(File file) { try { if (!file.isFile()) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream fis = new FileInputStream(file); GZIPInputStream gis = newGZIPInputStream(fis); try { byte[] buffer = new byte[1024]; int len; while((len = gis.read(buffer)) != -1){ baos.write(buffer, 0, len); } } finally { fis.close(); } baos.close(); return fromUtf8(baos.toByteArray()); // TODO: use a Reader } catch (Exception __e) { throw rethrow(__e); } } static File getCodeProgramDir() { return getCodeProgramDir(getProgramID()); } static File getCodeProgramDir(String snippetID) { return new File(javaxCodeDir(), formatSnippetID(snippetID)); } static File getCodeProgramDir(long snippetID) { return getCodeProgramDir(formatSnippetID(snippetID)); } static AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } static void saveGZTextFile(File file, String contents) { try { File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = file.getPath() + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(gos, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); gos.close(); fileOutputStream.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + file.getPath()); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); } catch (Exception __e) { throw rethrow(__e); } } static LinkedHashMap asLinkedHashMap(Map map) { if (map instanceof LinkedHashMap) return (LinkedHashMap) map; LinkedHashMap m = new LinkedHashMap(); if (map != null) synchronized(collectionMutex(map)) { m.putAll(map); } return m; } static String n2(long l) { return formatWithThousands(l); } static String n2(Collection l) { return n2(l(l)); } static String n2(double l, String singular) { return n2(l, singular, singular + "s"); } static String n2(double l, String singular, String plural) { if (fraction(l) == 0) return n2((long) l, singular, plural); else return l + " " + plural; } static String n2(long l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(long l, String singular) { return n_fancy2(l, singular, singular + "s"); } static String n2(Collection l, String singular) { return n2(l(l), singular); } static String n2(Collection l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(Map m, String singular, String plural) { return n_fancy2(m, singular, plural); } static String n2(Map m, String singular) { return n2(l(m), singular); } static String n2(Object[] a, String singular) { return n2(l(a), singular); } static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); } static String n2(MultiSet ms, String singular, String plural) { return n_fancy2(ms, singular, plural); } static List collect(Collection c, String field) { return collectField(c, field); } static List collect(String field, Collection c) { return collectField(c, field); } /*ifclass Concept static L collect(Class c, S field) { ret collect(list(c), field); } endif TODO: make translator ignore stuff in ifclass until resolved */ static void sleepInCleanUp(long ms) { try { if (ms < 0) return; Thread.sleep(ms); } catch (Exception __e) { throw rethrow(__e); } } static void _registerIO(Object object, String path, boolean opened) { } static Cache isLinux_cache = new Cache("isLinux_load"); static boolean isLinux() { return isLinux_cache.get(); } static Boolean isLinux_load() { return !isWindows() && !isMac() && !isAndroid(); } static int randomID_defaultLength = 12; static String randomID(int length) { return makeRandomID(length); } static String randomID(Random r, int length) { return makeRandomID(r, length); } static String randomID() { return randomID(randomID_defaultLength); } static String randomID(Random r) { return randomID(r, randomID_defaultLength); } static int globalIDLength() { return 16; } static boolean isJavaxCompilableSnippetType(int type) { return isJavaxCompilableSnippetTypeExceptInclude(type) || type == javaxIncludeSnippetType(); } static File javaxCodeDir_dir; // can be set to work on different base dir static File javaxCodeDir() { return javaxCodeDir_dir != null ? javaxCodeDir_dir : new File(userHome(), "JavaX-Code"); } static File javaxCodeDir(String sub) { return newFile(javaxCodeDir(), sub); } static List hotwire_collectJars(File jar) { List libIDs = hotwire_libraryIDsFromJar_deleteJarOnFail(jar); List files = ll(jar); // main program has to be first entry! (e.g. for hotwire_makeClassLoader_stickyAndSrcLibs) for (String libID : libIDs) files.add(loadLibraryOrSrcLib(libID)); return files; } static JavaXClassLoader hotwire_makeClassLoader(List files) { Collection toShare = hotwire_classesToShare(); return nempty(toShare) ? new JavaXClassLoaderWithParent2(null, files, myClassLoader(), cloneList(toShare)) : new JavaXClassLoader(null, files); } static Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource) { return hotwire_finish(classLoader, progID, javaSource, "main"); } static Class hotwire_finish(ClassLoader classLoader, String progID, String javaSource, String mainClass) { try { // load & return main class Class theClass = classLoader.loadClass(mainClass); Class j = getJavaX(); setOpt(theClass, "myJavaSource_code", javaSource); synchronized(j) { // hopefully this goes well... call(j, "setVars", theClass, progID); callOpt(j, "addInstance", progID, theClass); } hotwire_copyOver(theClass); vmBus_send("hotwireFinished",theClass, mc()); return theClass; } catch (Exception __e) { throw rethrow(__e); } } // returns (jar, transpiled src) static Pair compileSnippetThroughServer(String progID) { String transpiledSrc = getServerTranspiled2(progID); String md5 = md5(transpiledSrc + "\n" + progID); File jar = CompilerBot.getJarFile(md5); if (jar == null || jar.length() <= 22) { byte[] jarData = null; boolean dontLoad = false; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) { dontLoad = true; File jar2 = rl.getSnippetJar(progID, transpiledSrc); if (jar2 != null) return pair(jar2, transpiledSrc); } if (!dontLoad) { try { jarData = loadBinaryPage("http://www.botcompany.de/jar/" + psI(progID) + "?md5=" + md5(transpiledSrc)); } catch (Throwable __e) { _handleException(__e); }} if (!isJAR(jarData)) { if (jarData != null) { print(bytesToHex(takeFirstOfByteArray(8, jarData))); print("fallback to CompilerBot: " + fromUtf8(takeFirstOfByteArray(80, jarData))); } return CompilerBot.compileSnippet2(progID); } saveBinaryFile(jar, jarData); } return pair(jar, transpiledSrc); } static String dataSnippetLink(String snippetID) { long id = parseSnippetID(snippetID); if (id >= 1100000 && id < 1200000) return imageServerURL() + id; if (id >= 1400000 && id < 1500000) return "http://butter.botcompany.de:8080/files/" + id + "?_pass=" + muricaPassword(); if (id >= 1200000 && id < 1300000) { // Woody files, actually String pw = muricaPassword(); if (empty(pw)) throw fail("Please set 'murica password by running #1008829"); return "http://butter.botcompany.de:8080/1008823/raw/" + id + "?_pass=" + pw; // XXX, although it typically gets hidden when printing } else return "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id + "&contentType=application/binary"; } static A addAndReturn(Collection c, A a) { if (c != null) c.add(a); return a; } static void loadBinaryPageToFile(String url, File file) { try { print("Loading " + url); loadBinaryPageToFile(openConnection(new URL(url)), file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile(URLConnection con, File file) { try { setHeaders(con); loadBinaryPageToFile_noHeaders(con, file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile_noHeaders(URLConnection con, File file) { try { File ftemp = new File(f2s(file) + "_temp"); FileOutputStream buf = newFileOutputStream(mkdirsFor(ftemp)); try { InputStream inputStream = con.getInputStream(); long len = 0; try { len = con.getContentLength/*Long*/(); } catch (Throwable e) { printStackTrace(e); } String pat = " {*}" + (len != 0 ? "/" + len : "") + " bytes loaded."; copyStreamWithPrints(inputStream, buf, pat); inputStream.close(); buf.close(); file.delete(); renameFile_assertTrue(ftemp, file); } finally { if (buf != null) buf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static List allToString(Iterable c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static List allToString(Object[] c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static A println(A a) { return print(a); } static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) { return a != null && a.regionMatches(true, offsetA, b, offsetB, len); } static List filesEndingWith(File dir, String suffix) { return listFilesWithSuffix(dir, suffix); } static List filesEndingWith(List l, String suffix) { List out = new ArrayList(); for (File f : unnull(l)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) out.add(f); return out; } static String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static Object[] asObjectArray(Collection l) { return toObjectArray(l); } static File toFile(Object o) { if (o instanceof File) return (File) o; if (o instanceof String) return new File((String) o); throw fail("Not a file: " + o); } static void sort(T[] a, Comparator c) { Arrays.sort(a, c); } static void sort(T[] a) { Arrays.sort(a); } static void sort(int[] a) { if (a != null) Arrays.sort(a); } static void sort(List a, Comparator c) { Collections.sort(a, c); } static void sort(List a) { Collections.sort(a); } static File getCanonicalFile(File f) { try { return f == null ? null : f.getCanonicalFile(); } catch (Exception __e) { throw rethrow(__e); } } static boolean isSymLink(File f) { return f != null && Files.isSymbolicLink(toPath(f)); } static Comparator caseInsensitiveComparator() { return betterCIComparator(); } static TreeSet toCaseInsensitiveSet_treeSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, c); return set; } static TreeSet toCaseInsensitiveSet_treeSet(String... x) { TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, x); return set; } static String quickSubstring(String s, int i, int j) { if (i == j) return ""; return s.substring(i, j); } static Object defaultDefaultClassFinder() { return new F1() { Class get(String name) { try { Class c = findClass_fullName(name); if (c != null) return c; if (startsWith(name, "loadableUtils.utils$")) return findClass_fullName("main" + substring(name, 19)); return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Class c = findClass_fullName(name);\r\n if (c != null) ret c;\r\n if (start..."; }}; } static TreeMap caseInsensitiveMap() { return new TreeMap(caseInsensitiveComparator()); } static Object safeUnstructure(String s) { return unstructure(s, true); } static int parseHexChar(char c) { if (c >= '0' && c <= '9') return charDiff(c, '0'); if (c >= 'a' && c <= 'f') return charDiff(c, 'a')+10; if (c >= 'A' && c <= 'F') return charDiff(c, 'A')+10; return -1; } static Class getOuterClass(Class c) { return getOuterClass(c, null); } static Class getOuterClass(Class c, Object classFinder) { try { String s = c.getName(); int i = s.lastIndexOf('$'); String name = substring(s, 0, i); if (classFinder != null) return (Class) callF(classFinder, name); return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } static HashMap instanceFieldsMap(Object o) { Class c = o.getClass(); HashMap map; synchronized(getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map; } static LinkedHashMap syncMapPut2_createLinkedHashMap(LinkedHashMap map, A key, B value) { if (key != null) if (value != null) { if (map == null) map = new LinkedHashMap(); synchronized(collectionMutex(map)) { map.put(key, value); } } else synchronized(collectionMutex(map)) { map.remove(key); } return map; } static void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } static Map thisDollarOneFields_cache = newDangerousWeakHashMap(); static Field[] thisDollarOneFields(Class c) { synchronized(thisDollarOneFields_cache) { Field[] l = thisDollarOneFields_cache.get(c); if (l == null) thisDollarOneFields_cache.put(c, l = thisDollarOneFields_uncached(c)); return l; } } static Field[] thisDollarOneFields_uncached(Class c) { List fields = new ArrayList(); do { for (Field f : c.getDeclaredFields()) if (f.getName().equals("this$1")) fields.add(makeAccessible(f)); c = c.getSuperclass(); } while (c != null); return toArray(new Field[l(fields)], fields); } static Method fastIntern_method; static String fastIntern(String s) { try { if (s == null) return null; if (fastIntern_method == null) { fastIntern_method = findMethodNamed(javax(), "internPerProgram"); if (fastIntern_method == null) upgradeJavaXAndRestart(); } return (String) fastIntern_method.invoke(null, s); } catch (Exception __e) { throw rethrow(__e); } } static Map> callOpt_noArgs_cache = newDangerousWeakHashMap(); static Object callOpt_noArgs(Object o, String method) { try { if (o == null) return null; if (o instanceof Class) return callOpt(o, method); // not optimized Class c = o.getClass(); HashMap map; synchronized(callOpt_noArgs_cache) { map = callOpt_noArgs_cache.get(c); if (map == null) map = callOpt_noArgs_makeCache(c); } Method m = map.get(method); return m != null ? m.invoke(o) : null; } catch (Exception __e) { throw rethrow(__e); } } // used internally - we are in synchronized block static HashMap callOpt_noArgs_makeCache(Class c) { HashMap map = new HashMap(); Class _c = c; do { for (Method m : c.getDeclaredMethods()) if (m.getParameterTypes().length == 0 && !reflection_isForbiddenMethod(m)) { makeAccessible(m); String name = m.getName(); if (!map.containsKey(name)) map.put(name, m); } _c = _c.getSuperclass(); } while (_c != null); callOpt_noArgs_cache.put(c, map); return map; } // match2 matches multiple "*" (matches a single token) wildcards and zero or one "..." wildcards (matches multiple tokens) static String[] match2(List pat, List tok) { // standard case (no ...) int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); pat = new ArrayList(pat); // We're modifying it, so copy first pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); pat.add(i+1, ""); // doesn't matter } return match2_match(pat, tok); } static String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); if (eq(p, "*")) result.add(t); else if (!equalsIgnoreCase(unquote(p), unquote(t))) // bold change - match quoted and unquoted now return null; } return result.toArray(new String[result.size()]); } static Map classForName_cache = synchroHashMap(); static Class classForName(String name) { try { if (classForName_cache == null) return Class.forName(name); // in class init Class c = classForName_cache.get(name); if (c == null) classForName_cache.put(name, c = Class.forName(name)); return c; } catch (Exception __e) { throw rethrow(__e); } } static Map nuObjectWithoutArguments_cache = newDangerousWeakHashMap(); static Object nuObjectWithoutArguments(String className) { try { return nuObjectWithoutArguments(classForName(className)); } catch (Exception __e) { throw rethrow(__e); } } static A nuObjectWithoutArguments(Class c) { try { if (nuObjectWithoutArguments_cache == null) // in class init return (A) nuObjectWithoutArguments_findConstructor(c).newInstance(); Constructor m = nuObjectWithoutArguments_cache.get(c); if (m == null) nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c)); return (A) m.newInstance(); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObjectWithoutArguments_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } static HashSet litset(A... items) { return lithashset(items); } static List getClassNames(Collection l) { List out = new ArrayList(); if (l != null) for (Object o : l) out.add(o == null ? null : getClassName(o)); return out; } static Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; // could optimize this } } static Class _getClass(Object o) { return o == null ? null : o instanceof Class ? (Class) o : o.getClass(); } static Class _getClass(Object realm, String name) { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; // could optimize this } } static Object swing(Object f) { return swingAndWait(f); } static A swing(F0 f) { return (A) swingAndWait(f); } static A swing(IF0 f) { return (A) swingAndWait(f); } static File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } static String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } static List takeFirst(List l, int n) { return l(l) <= n ? l : newSubListOrSame(l, 0, n); } static List takeFirst(int n, List l) { return takeFirst(l, n); } static String takeFirst(int n, String s) { return substring(s, 0, n); } static String takeFirst(String s, int n) { return substring(s, 0, n); } static List takeFirst(int n, Iterable i) { List l = new ArrayList(); Iterator it = i.iterator(); for (int _repeat_1622 = 0; _repeat_1622 < n; _repeat_1622++) { if (it.hasNext()) l.add(it.next()); else break; } return l; } static volatile boolean muricaPassword_pretendNotAuthed = false; static String muricaPassword() { if (muricaPassword_pretendNotAuthed) return null; return trim(loadTextFile(muricaPasswordFile())); } static String structure_addTokenMarkers(String s) { return join(structure_addTokenMarkers(javaTok(s))); } static List structure_addTokenMarkers(List tok) { // find references TreeSet refs = new TreeSet(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("t") && isInteger(t.substring(1))) refs.add(parseInt(t.substring(1))); } if (empty(refs)) return tok; // add markers for (int i : refs) { int idx = i*2+1; if (idx >= l(tok)) continue; // broken structure String t = ""; if (endsWithLetterOrDigit(tok.get(idx-1))) t = " "; tok.set(idx, t + "m" + i + " " + tok.get(idx)); } return tok; } static boolean isCISet(Iterable l) { return l instanceof TreeSet && ((TreeSet) l).comparator() == caseInsensitiveComparator(); } static int indexOfIgnoreCase_manual(String a, String b) { int la = strL(a), lb = strL(b); if (la < lb) return -1; int n = la-lb; loop: for (int i = 0; i <= n; i++) { for (int j = 0; j < lb; j++) { char c1 = a.charAt(i+j), c2 = b.charAt(j); if (!eqic(c1, c2)) continue loop; } return i; } return -1; } static Map compileRegexpIC_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static CloseableIterableIterator linesFromFile(File f) { try { if (!f.exists()) return emptyCloseableIterableIterator(); if (ewic(f.getName(), ".gz")) return linesFromReader(utf8bufferedReader(newGZIPInputStream(f))); return linesFromReader(utf8bufferedReader(f)); } catch (Exception __e) { throw rethrow(__e); } } static CloseableIterableIterator linesFromFile(String path) { return linesFromFile(newFile(path)); } static File programDir_mine; // set this to relocate program's data static File programDir() { return programDir(getProgramID()); } static File programDir(String snippetID) { boolean me = sameSnippetID(snippetID, programID()); if (programDir_mine != null && me) return programDir_mine; File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID)); if (me) { String c = caseID(); if (nempty(c)) dir = newFile(dir, c); } return dir; } static File programDir(String snippetID, String subPath) { return new File(programDir(snippetID), subPath); } static boolean even(int i) { return (i & 1) == 0; } static boolean even(long i) { return (i & 1) == 0; } static String reverseString(String s) { return new StringBuilder(s).reverse().toString(); } static String upper(String s) { return s == null ? null : s.toUpperCase(); } static char upper(char c) { return Character.toUpperCase(c); } static Object evalJava_main(String main) { return callCalc(evalJava_prep2(main)); } static String evalJava_prep(String code) { return evalJava_prep(code, "calc"); } static String evalJava_prep(String code, String mainName) { return evalJava_prep(code, mainName, ""); } static ThreadLocal evalJava_prep_args = new ThreadLocal(); static ThreadLocal evalJava_prep_voidMagic = new ThreadLocal(); // set to false to avoid looking up standard function return types static String evalJava_prep(String code, String mainName, String preCode) { List tok = javaTok(trim(code)); if (!isFalse(evalJava_prep_voidMagic.get()) && tok_shouldAddReturn(tok) && eqGet(tok, 3, "(") && isIdentifier(get(tok, 1)) && isKnownVoidFunction(get(tok, 1))) tokAppend_reTok(tok, l(tok)-2, ";"); code = tok_addReturn(tok); String returnType = containsReturnWithArgument(code) ? "O" : "void"; String main = "static " + returnType + " " + mainName + "(" + unnull(evalJava_prep_args.get()) + ") throws Exception {\n" + preCode + code + "\n" + "}"; return main; } static String shortenClassName(String name) { if (name == null) return null; int i = lastIndexOf(name, "$"); if (i < 0) i = lastIndexOf(name, "."); return i < 0 ? name : substring(name, i+1); } static boolean isLetter(char c) { return Character.isLetter(c); } static void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static Object mainBot; static Object getMainBot() { return mainBot; } static List getBracketMap2(List tok, Map map, String openingBrackets, String closingBrackets) { map.clear(); List stack = new ArrayList(); for (int i = 1; i < l(tok); i+= 2) { String t = tok.get(i); if (l(t) == 1) if (openingBrackets.contains(t)) stack.add(i); else if (closingBrackets.contains(tok.get(i))) map.put(empty(stack) ? 0 : liftLast(stack), i); } return stack; } static int tokenIndexToUserLandLineNr(List tok, int tokenIndex) { return charIndexToUserLandLineNr(join(tok), tokenIndexToCharIndex(tok, tokenIndex)); } static int tokenToCharIndex(List tok, int tokenIndex) { if (tokenIndex < 0) return -1; int idx = 0; tokenIndex = min(tokenIndex, l(tok)); for (int i = 0; i < tokenIndex; i++) idx += l(tok.get(i)); return idx; } static int tokenIndexToCharIndex(List tok, int tokenIndex) { return tokenToCharIndex(tok, tokenIndex); } static String n(long l, String name) { return l + " " + trim(l == 1 ? singular(name) : getPlural(name)); } static String n(Collection l, String name) { return n(l(l), name); } static String n(Map m, String name) { return n(l(m), name); } static String n(Object[] a, String name) { return n(l(a), name); } static String n(MultiSet ms, String name) { return n(l(ms), name); } static File oneOfTheFiles(String... paths) { if (paths != null) for (String path : paths) if (fileExists(path)) return newFile(path); return null; } static File oneOfTheFiles(File... files) { if (files != null) for (File f : files) if (fileExists(f)) return f; return null; } static File javaxSecretDir_dir; // can be set to work on different base dir static File javaxSecretDir() { return javaxSecretDir_dir != null ? javaxSecretDir_dir : new File(userHome(), "JavaX-Secret"); } static File javaxSecretDir(String sub) { return newFile(javaxSecretDir(), sub); } static List jsonTok(String s) { List tok = new ArrayList(); int l = l(s); int i = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j+2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); // cc is not needed in rest of loop body // scan for non-whitespace (json strings, "null" identifier, numbers. everything else automatically becomes a one character token.) if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j+1 < l) j += 2; else ++j; } } else if (Character.isLetter(c)) do ++j; while (j < l && Character.isLetter(s.charAt(j))); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static List toLinesFullTrim(String s) { List l = new ArrayList(); for (String line : toLines(s)) if (nempty(line = trim(line))) l.add(line); return l; } static List toLinesFullTrim(File f) { List l = new ArrayList(); for (String line : linesFromFile(f)) if (nempty(line = trim(line))) l.add(line); return l; } static String javaDropAllComments(String s) { return join(javaDropAllComments(javaTok(s))); } static List javaDropAllComments(List tok) { for (int i = 0; i < l(tok); i += 2) tok.set(i, tok_javaDropCommentsFromWhitespace(tok.get(i))); return tok; } static boolean methodIsStatic(Method m) { return (m.getModifiers() & Modifier.STATIC) != 0; } static boolean argumentCompatibleWithType(Object arg, Class type) { return arg == null ? !type.isPrimitive() : isInstanceX(type, arg); } static void arraycopy(Object[] a, Object[] b) { if (a != null && b != null) arraycopy(a, 0, b, 0, min(a.length, b.length)); } static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { if (n != 0) System.arraycopy(src, srcPos, dest, destPos, n); } static A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } static List cleanUpAndGetWeakReferencesList(List> l) { if (l == null) return null; synchronized(l) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) { A a = l.get(i).get(); if (a == null) l.remove(i--); else out.add(a); } return out; } } static Map stdFunctions_uncached() { return stdFunctions_uncached(new HashMap()); } static Map stdFunctions_uncached(Map map) { parseStdFunctionsList(loadSnippetSilently("#1006654"), map); parseStdFunctionsList(loadSnippetSilently("#761"), map); return map; } static Object sleepQuietly_monitor = new Object(); static void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized(sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static boolean domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static String theAGIBlueDomain() { return "agi.blue"; } static String _computerID; static Lock computerID_lock = lock(); public static String computerID() { if (_computerID == null) { Lock __1700 = computerID_lock; lock(__1700); try { if (_computerID != null) return _computerID; File file = computerIDFile(); _computerID = loadTextFile(file.getPath()); if (_computerID == null) { // legacy load _computerID = loadTextFile(userDir(".tinybrain/computer-id")); if (_computerID == null) _computerID = makeRandomID(12, new SecureRandom()); saveTextFile(file, _computerID); } } finally { unlock(__1700); } } return _computerID; } static B mapPutOrRemove(Map map, A key, B value) { if (map != null && key != null) if (value != null) return map.put(key, value); else return map.remove(key); return null; } static String joinNempties(String sep, String... strings) { return joinStrings(sep, strings); } static String joinNempties(String sep, Collection strings) { return joinStrings(sep, strings); } static String stream2string(InputStream in) { return utf8streamToString(in); } static A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static Map syncMRUCache(int size) { return synchroMap(new MRUCache(size)); } static Object pcallF(Object f, Object... args) { return pcallFunction(f, args); } static A pcallF(F0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { return null; } } static B pcallF(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static void pcallF(VF1 f, A a) { try { if (f != null) f.get(a); } catch (Throwable __e) { _handleException(__e); } } static Set vm_generalIdentityHashSet(Object name) { synchronized(get(javax(), "generalMap")) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = syncIdentityHashSet()); return set; } } static Map vm_generalHashMap(Object name) { synchronized(get(javax(), "generalMap")) { Map m = (Map) (vm_generalMap_get(name)); if (m == null) vm_generalMap_put(name, m = syncHashMap()); return m; } } static boolean headless() { return isHeadless(); } static JTextField setTextAndSelectAll(final JTextField tf, final String text) { if (tf != null) { swing(new Runnable() { public void run() { try { tf.setText(text); tf.selectAll(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tf.setText(text);\r\n tf.selectAll();"; }}); } return tf; } static JTextField consoleInputField() { Object console = get(getJavaX(), "console"); return (JTextField) getOpt(console, "tfInput"); } static void focusConsole(String s) { setConsoleInput(s); focusConsole(); } static void focusConsole() { JComponent tf = consoleInputFieldOrComboBox(); if (tf != null) { //print("Focusing console"); tf.requestFocus(); } } static String fromUtf8(byte[] bytes) { try { return bytes == null ? null : new String(bytes, "UTF-8"); } catch (Exception __e) { throw rethrow(__e); } } static String formatWithThousands(long l) { return formatWithThousandsSeparator(l); } static double fraction(double d) { return d % 1; } static String n_fancy2(long l, String singular, String plural) { return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural); } static String n_fancy2(Collection l, String singular, String plural) { return n_fancy2(l(l), singular, plural); } static String n_fancy2(Map m, String singular, String plural) { return n_fancy2(l(m), singular, plural); } static String n_fancy2(Object[] a, String singular, String plural) { return n_fancy2(l(a), singular, plural); } static String n_fancy2(MultiSet ms, String singular, String plural) { return n_fancy2(l(ms), singular, plural); } static List collectField(Collection c, String field) { List l = new ArrayList(); if (c != null) for (Object a : c) l.add(getOpt(a, field)); return l; } static List collectField(String field, Collection c) { return collectField(c, field); } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } static boolean isMac() { return System.getProperty("os.name").toLowerCase().contains("mac"); } static String makeRandomID(int length) { return makeRandomID(length, defaultRandomGenerator()); } static String makeRandomID(int length, Random random) { char[] id = new char[length]; for (int i = 0; i < id.length; i++) id[i] = (char) ((int) 'a' + random.nextInt(26)); return new String(id); } static String makeRandomID(Random r, int length) { return makeRandomID(length, r); } static boolean isJavaxCompilableSnippetTypeExceptInclude(int type) { return isJavaxApplicationSnippetType(type) || isJavaxModuleSnippetType(type) || type == snippetType_dynModule(); } static int javaxIncludeSnippetType() { return 42; } static List hotwire_libraryIDsFromJar_deleteJarOnFail(File jar) { try { return hotwire_libraryIDsFromJar(jar); } catch (Throwable _e) { jar.delete(); throw rethrow(_e); } } static Set hotwire_classesToShare = synchroSet(); static Set hotwire_classesToShare() { return hotwire_classesToShare; } static ClassLoader myClassLoader() { return _getClass(mc()).getClassLoader(); } static byte[] isJAR_magic = bytesFromHex("504B0304"); static boolean isJAR(byte[] data) { return byteArrayStartsWith(data, isJAR_magic); } static boolean isJAR(File f) { return isJAR(loadBeginningOfBinaryFile(f, l(isJAR_magic))); } static byte[] takeFirstOfByteArray(byte[] b, int n) { return subByteArray(b, 0, n); } static byte[] takeFirstOfByteArray(int n, byte[] b) { return takeFirstOfByteArray(b, n); } public static File mkdirsFor(File file) { return mkdirsForFile(file); } static void copyStreamWithPrints(InputStream in, OutputStream out, String pat) { try { byte[] buf = new byte[65536]; int total = 0; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); if ((total+n)/100000 > total/100000) print(pat.replace("{*}", str(roundDownTo(total, 100000)))); total += n; } } catch (Exception __e) { throw rethrow(__e); } } static void renameFile_assertTrue(File a, File b) { try { if (!a.exists()) throw fail("Source file not found: " + f2s(a)); if (b.exists()) throw fail("Target file exists: " + f2s(b)); mkdirsForFile(b); if (!a.renameTo(b)) throw fail("Can't rename " + f2s(a) + " to " + f2s(b)); } catch (Exception __e) { throw rethrow(__e); } } static List listFilesWithSuffix(File dir, String suffix) { List l = new ArrayList(); for (File f : listFiles(dir)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) l.add(f); return l; } static boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la-lb, b, 0, lb); } static boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; m.m = new String[] { substring(a, 0, l(a)-l(b)) }; return true; } static String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static Object[] toObjectArray(Collection c) { List l = asList(c); return l.toArray(new Object[l.size()]); } static Path toPath(File f) { return f == null ? null : f.toPath(); } static betterCIComparator_C betterCIComparator_instance; static betterCIComparator_C betterCIComparator() { if (betterCIComparator_instance == null) betterCIComparator_instance = new betterCIComparator_C(); return betterCIComparator_instance; } static class betterCIComparator_C implements Comparator { public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { // No overflow because of numeric promotion return c1 - c2; } } } } return n1 - n2; } } static int charDiff(char a, char b) { return (int) a-(int) b; } static int charDiff(String a, char b) { return charDiff(stringToChar(a), b); } static Object[] toArray(Collection c) { return toObjectArray(c); } static A[] toArray(Collection c, Class type) { A[] a = arrayOfType(l(c), type); if (a.length == 0) return a; asList(c).toArray(a); return a; } // array must have correct length and will be filled static A[] toArray(A[] array, Collection c) { if (array == null || c == null) return null; asList(c).toArray(array); return array; } static void upgradeJavaXAndRestart() { run("#1001639"); restart(); sleep(); } static boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static boolean equalsIgnoreCase(String a, String b) { return eqic(a, b); } static boolean equalsIgnoreCase(char a, char b) { return eqic(a, b); } static Class getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static Class getClass(Object o) { return o instanceof Class ? (Class) o : o.getClass(); } static Class getClass(Object realm, String name) { try { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; } } catch (Exception __e) { throw rethrow(__e); } } static String classNameToVM(String name) { return name.replace(".", "$"); } static void swingAndWait(Runnable r) { try { if (isAWTThread()) r.run(); else EventQueue.invokeAndWait(addThreadInfoToRunnable(r)); } catch (Exception __e) { throw rethrow(__e); } } static Object swingAndWait(final Object f) { if (isAWTThread()) return callF(f); else { final Var result = new Var(); swingAndWait(new Runnable() { public void run() { try { result.set(callF(f)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; }}); return result.get(); } } static File associatedInfosFile(File f) { return replaceExtension(f, ".infos"); } static String firstStartingWithIC_drop(Collection l, final String prefix) { for (String s : unnull(l)) if (swic(s, prefix)) return substring(s, l(prefix)); return null; } static String firstStartingWithIC_drop(String prefix, Collection l) { return firstStartingWithIC_drop(l, prefix); } static File parentFile(File f) { return dirOfFile(f); } static List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static List newSubListOrSame(List l, IntRange r) { return newSubListOrSame(l, r.start, r.end); } static File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } static RuntimeException wrapPatternSyntaxException(PatternSyntaxException e) { if (e == null) return null; String pat = e.getPattern(); int i = e.getIndex(); return new RuntimeException("Regular expression error between " + multiLineQuoteWithSpaces(substring(pat, 0, i)) + " and " + multiLineQuoteWithSpaces(substring(pat, i)) + " - " + e.getMessage()); } static CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static CloseableIterableIterator linesFromReader(Reader r) { final BufferedReader br = bufferedReader(r); return iteratorFromFunction_f0_autoCloseable(new F0() { String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret readLineFromReaderWithClose(br);"; }}, _wrapIOCloseable(r)); } static BufferedReader utf8bufferedReader(InputStream in) { try { return bufferedReader(_registerIOWrap(new InputStreamReader(in, "UTF-8"), in)); } catch (Exception __e) { throw rethrow(__e); } } static BufferedReader utf8bufferedReader(File f) { try { return utf8bufferedReader(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static volatile String caseID_caseID; static String caseID() { return caseID_caseID; } static void caseID(String id) { caseID_caseID = id; } static Object callCalc(Object o, Object... args) { return call(o, "calc", args); } // flag is per thread, cache is per program (in-memory cache of JavaX source -> loaded Class) static ThreadLocal evalJava_prep2_useCacheInThread = new ThreadLocal(); static volatile boolean evalJava_prep2_useCache = false; // cached main classes, used only when you enable it static Map evalJava_prep2_cache = synchronizedMRUCache(100); static Object evalJava_prep2(String main) { boolean _useCache = evalJava_prep2_useCache || isTrue(evalJava_prep2_useCacheInThread.get()); if (_useCache) { Object obj = evalJava_prep2_cache.get(main); if (obj != null) return obj; } Object obj = veryQuickJava(main); if (_useCache) evalJava_prep2_cache.put(main, obj); makeDependent(obj); setOpt(obj, "getProgramName_cache", "User Code"); return obj; } static boolean isKnownVoidFunction(String name) { //ret mL_localCopy("Void Standard Functions").contains(name); return standardFunctionAlwaysReturnsVoid(name); } // We'd be really fancy if we filtered out return statements in // inner blocks. static boolean containsReturnWithArgument(List tok) { for (int i = 1; i+2 < l(tok); i += 2) if (eqOneOf(tok.get(i), "ret", "return") && neqOneOf(tok.get(i+2), ";", "if", "unless", "with")) return true; return false; } static boolean containsReturnWithArgument(String code) { return containsReturnWithArgument(javaTok(code)); } static int charIndexToUserLandLineNr(String text, int charIndex) { int i = 0, row = 1; charIndex = min(charIndex, l(text)); while (i < charIndex) { i = smartIndexOf(text, '\n', i)+1; if (charIndex < i) break; ++row; if (charIndex == i) break; } return row; } static Map singular_specials = litmap( "children", "child", "images", "image", "chess", "chess"); static Set singular_specials2 = litset("time", "machine", "line"); static String singular(String s) { if (s == null) return null; { String _a_1820 = singular_specials.get(s); if (!empty(_a_1820)) return _a_1820; } //try answer hippoSingulars().get(lower(s)); if (singular_specials2.contains(dropSuffix("s", afterLastSpace(s)))) return dropSuffix("s", s); if (s.endsWith("ness")) return s; if (s.endsWith("ges")) return dropSuffix("s", s); if (endsWith(s, "bases")) return dropLast(s); s = dropSuffix("es", s); s = dropSuffix("s", s); return s; } static List getPlural_specials = ll("sheep", "fish"); static String getPlural(String s) { if (containsIgnoreCase(getPlural_specials, s)) return s; if (ewic(s, "y")) return dropSuffixIgnoreCase("y", s) + "ies"; if (ewic(s, "ss")) return s + "es"; if (ewic(s, "s")) return s; return s + "s"; } static String tok_javaDropCommentsFromWhitespace(String s) { int l = l(s), j = 0; StringBuilder buf = new StringBuilder(); while (j < l) { char c = s.charAt(j); char d = j+1 >= l ? '\0' : s.charAt(j+1); if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/")); j = Math.min(j+2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else { buf.append(c); ++j; } } return str(buf); } static A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } // map contains function name -> snippet id static Map parseStdFunctionsList(String snippetSrc) { return parseStdFunctionsList(snippetSrc, new LinkedHashMap()); } static Map parseStdFunctionsList(String snippetSrc, Map map) { List tok = javaTok(snippetSrc); int i = findCodeTokens(tok, "standardFunctions", "=", "litlist", "("); int opening = i+6; int closing = indexOf(tok, ")", opening)-1; for (i = opening+2; i < closing; i += 4) { String[] f = unquote(tok.get(i)).split("/"); map.put(f[1], f[0]); } return map; } static String loadSnippetSilently(Snippet s) { return loadSnippetQuietly(s); } static String loadSnippetSilently(String snippetID) { return loadSnippetQuietly(snippetID); } static File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } static String joinStrings(String sep, String... strings) { return joinStrings(sep, Arrays.asList(strings)); } static String joinStrings(String sep, Collection strings) { StringBuilder buf = new StringBuilder(); for (String s : unnull(strings)) if (nempty(s)) { if (nempty(buf)) buf.append(sep); buf.append(s); } return str(buf); } static String utf8streamToString(InputStream in) { return readerToString(utf8bufferedReader(in)); } static Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { _handleException(__e); } return null; } static Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static Map syncHashMap() { return synchroHashMap(); } static void setConsoleInput(String text) { consoleSetInput(text); } static JComponent consoleInputFieldOrComboBox() { Object console = get(getJavaX(), "console"); JComboBox cb = (JComboBox) (getOpt(console, "cbInput")); if (cb != null) return cb; return (JTextField) getOpt(console, "tfInput"); } static String formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } static Random defaultRandomGenerator() { return ThreadLocalRandom.current(); } static boolean isJavaxApplicationSnippetType(int type) { return type == snippetType_javaxSource() || type == snippetType_JavaXDesktop(); } static boolean isJavaxModuleSnippetType(int type) { return type == snippetType_javaxModule() || type == snippetType_javaxDesktopModule(); } static int snippetType_dynModule() { return 57; } static List hotwire_libraryIDsFromJar(File jar) { String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); return regexpExtractAll("\\d+", dehlibs); } static Set synchroSet() { return synchroHashSet(); } static Set synchroSet(Set set) { return Collections.synchronizedSet(set); } static byte[] bytesFromHex(String s) { return hexToBytes(s); } static boolean byteArrayStartsWith(byte[] a, byte[] b) { if (a == null || b == null) return false; if (a.length < b.length) return false; for (int i = 0; i < b.length; i++) if (a[i] != b[i]) return false; return true; } static byte[] loadBeginningOfBinaryFile(File file, int maxBytes) { return loadBinaryFilePart(file, 0, maxBytes); } static byte[] subByteArray(byte[] b, int start) { return subByteArray(b, start, l(b)); } static byte[] subByteArray(byte[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new byte[0]; byte[] x = new byte[end-start]; System.arraycopy(b, start, x, 0, end-start); return x; } static int roundDownTo(int x, int n) { return x/n*n; } static long roundDownTo(long x, long n) { return x/n*n; } static char stringToChar(String s) { if (l(s) != 1) throw fail("bad stringToChar: " + s); return firstChar(s); } static Class run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static Runnable addThreadInfoToRunnable(final Object r) { final Object info = _threadInfo(); return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; }}; } static File replaceExtension(File f, String extOld, String extNew) { return newFile(replaceExtension(f2s(f), extOld, extNew)); } static File replaceExtension(File f, String extNew) { return replaceExtension(f, fileExtension(f), extNew); } static String replaceExtension(String s, String extOld, String extNew) { s = dropSuffixIC(addPrefixOptIfNempty(".", extOld), s); return s + addPrefixOptIfNempty(".", extNew); } static String replaceExtension(String name, String extNew) { return replaceExtension(name, fileExtension(name), extNew); } static File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } static BufferedReader bufferedReader(Reader r) { return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r), r); } static CloseableIterableIterator iteratorFromFunction_f0_autoCloseable(final F0 f, final AutoCloseable closeable) { class IFF2 extends CloseableIterableIterator { A a; boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } public void close() throws Exception { if (closeable != null) closeable.close(); } }; return new IFF2(); } static String readLineFromReaderWithClose(BufferedReader r) { try { String s = r.readLine(); if (s == null) r.close(); return s; } catch (Exception __e) { throw rethrow(__e); } } static AutoCloseable _wrapIOCloseable(final AutoCloseable c) { return c == null ? null : new AutoCloseable() { public String toString() { return "c.close();\r\n _registerIO(c, null, false);"; } public void close() throws Exception { c.close(); _registerIO(c, null, false); }}; } static FileInputStream newFileInputStream(File path) throws IOException { return newFileInputStream(path.getPath()); } static FileInputStream newFileInputStream(String path) throws IOException { FileInputStream f = new FileInputStream(path); _registerIO(f, path, true); return f; } // mainJava is a complete program, but without the !752/!759 at the top // returns link to main class static Class veryQuickJava(CharSequence mainJava) { return veryQuickJava3(str(mainJava)); // Latest version with internal compiler bot. } static boolean standardFunctionAlwaysReturnsVoid(String name) { return tok_staticFunctionAlwaysReturnsVoid(javaTok(textOfStandardFunction_cached(name)), name); } static HashMap litmap(Object... x) { HashMap map = new HashMap(); litmap_impl(map, x); return map; } static void litmap_impl(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length-1; i += 2) if (x[i+1] != null) map.put(x[i], x[i+1]); } static String afterLastSpace(String s) { return s == null ? null : substring(s, s.lastIndexOf(' ')+1); } static String dropSuffixIgnoreCase(String suffix, String s) { return ewic(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static String loadSnippetQuietly(Snippet s) { return loadSnippetQuietly(s.id); } static String loadSnippetQuietly(String snippetID) { loadSnippet_silent.set(true); try { return loadSnippet(snippetID); } finally { loadSnippet_silent.set(null); } } static String readerToString(Reader r) { try { try { StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; //if ((n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { r.close(); } } catch (Exception __e) { throw rethrow(__e); } } static Object callFunction(Object f, Object... args) { return callF(f, args); } static Set synchronizedSet() { return synchroHashSet(); } static Set synchronizedSet(Set set) { return Collections.synchronizedSet(set); } static Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } static int snippetType_javaxSource() { return 34; } static int snippetType_JavaXDesktop() { return 55; } static int snippetType_javaxModule() { return 54; } static int snippetType_javaxDesktopModule() { return 58; } static String loadTextFileFromZip(File inZip, String fileName) { return loadTextFileFromZipFile(inZip, fileName); } static List regexpExtractAll(String pat, String s) { if (s == null) return null; Matcher m = regexpMatcher(pat, s); List out = new ArrayList(); while (m.find()) out.add(m.group()); return out; } static Set synchroHashSet() { return Collections.synchronizedSet(new HashSet()); } static byte[] loadBinaryFilePart(File file, long start, long end) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); int n = toInt(min(raf.length(), end-start)); byte[] buffer = new byte[n]; try { raf.seek(start); raf.readFully(buffer, 0, n); return buffer; } finally { raf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static char firstChar(String s) { return s.charAt(0); } static List> _threadInfo_makers = synchroList(); static Object _threadInfo() { if (empty(_threadInfo_makers)) return null; HashMap map = new HashMap(); pcallFAll(_threadInfo_makers, map); return map; } static Runnable asRunnable(Object o) { return toRunnable(o); } static void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s)-l(suffix)) : s; } static String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } static boolean veryQuickJava_silent = true; static boolean veryQuickJava_useCompilerBot = true; // we always use it now static ThreadLocal veryQuickJava_transpiled = new ThreadLocal(); static Object veryQuickJava3_cacheFunction; // func(S, LS) -> Class // mainJava is a complete program, but without the !752/!759 at the top // returns link to main class static Class veryQuickJava3(String mainJava) { return veryQuickJava3(mainJava, emptyList()); } static Class veryQuickJava3(String mainJava, List libs) { Class c = (Class) (callF(veryQuickJava3_cacheFunction, mainJava, libs)); if (c != null) return c; transpileRaw_silent = veryQuickJava_silent; String src = transpileRaw(mainJava); // transpiled, with lib references if (veryQuickJava_transpiled.get() != null) veryQuickJava_transpiled.set(src); return veryQuickJava_finish(src, libs); } static boolean tok_staticFunctionAlwaysReturnsVoid(List tok, String name) { Set types = tok_returnTypesOfStaticFunction_uncleaned(tok, name); if (empty(types)) return false; for (String type : types) if (!containsOneOf(javaTokC(type), "void", "svoid")) return false; return true; } static String textOfStandardFunction_cached(String sfName) { return textOfStandardFunction(sfName); } static String loadTextFileFromZipFile(File inZip, String fileName) { try { if (!fileExists(inZip)) return null; try { ZipFile zip = new ZipFile(inZip); try { return loadTextFileFromZipFile(zip, fileName); } finally { _close(zip); }} catch (Throwable e) { throw fail(f2s(inZip), e); } } catch (Exception __e) { throw rethrow(__e); } } static String loadTextFileFromZipFile(ZipFile zip, String fileName) { try { ZipEntry entry = zip.getEntry(fileName); if (entry == null) return null; InputStream fin = zip.getInputStream(entry); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyStream(fin, baos); return fromUTF8(baos.toByteArray()); } finally { _close(fin); }} catch (Exception __e) { throw rethrow(__e); } } static Runnable toRunnable(final Object o) { if (o instanceof Runnable) return (Runnable) o; return new Runnable() { public void run() { try { callF(o) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; }}; } static List> _threadInheritInfo_retrievers = synchroList(); static void _threadInheritInfo(Object info) { if (info == null) return; pcallFAll(_threadInheritInfo_retrievers, (Map) info); } static boolean transpileRaw_silent = true; static boolean transpileRaw_useDiskCache = false; static Class transpileRaw_trans; static boolean transpileRaw_verySilent = false; static boolean transpileRaw_dontCopyFromCreator = false; static Lock transpileRaw_lock = lock(); static ThreadLocal transpileRaw_asInclude = new ThreadLocal(); static String transpileRaw(String mainJava) { return transpileRaw(mainJava, false, transpileRaw_useDiskCache); } static String transpileRaw(String mainJava, boolean fragment) { return transpileRaw(mainJava, fragment, transpileRaw_useDiskCache); } static String transpileRaw(String mainJava, boolean fragment, boolean useDiskCache) { mainJava = dropTranslators(mainJava); if (!transpileRaw_dontCopyFromCreator) transpileRaw_copyFromCreator(); Lock __1975 = transpileRaw_lock; lock(__1975); try { File cacheFile = null; if (useDiskCache) { cacheFile = new File(javaxCodeDir(), "Transpilations/" + uniqueFileNameUsingMD5_80_v2(mainJava) + ".java"); { String _a_1979 = loadTextFile(cacheFile); if (!empty(_a_1979)) return _a_1979; } } AutoCloseable __1977 = transpileRaw_verySilent ? null : tempLoadingAnim("Transpiling..."); try { transpileRaw_translator(); //setOpt(transpileRaw_trans, dontPrintSource := true); setOpt(transpileRaw_trans, "localStuffOnly" , fragment); setOpt(transpileRaw_trans, "asInclude" , isTrue(transpileRaw_asInclude.get())); set(transpileRaw_trans, "mainJava", mainJava); // TODO: setOpt(transpileRaw_trans, transpilingSnippetID := ); set(transpileRaw_trans, "print_byThread", print_byThread); if (!transpileRaw_verySilent) { print("Running translator " + getOpt(transpileRaw_trans, "programID")); if (!transpileRaw_silent) { print("Translator ID: " + systemHashCode(transpileRaw_trans) + ", print_byThread=" + getTL((ThreadLocal) getOpt(transpileRaw_trans, "print_byThread"))); call(transpileRaw_trans, "print", "test"); } } callMain(transpileRaw_trans); //print("Ran translator " + identityHashCode(transpileRaw_trans)); String main = (String) (get(transpileRaw_trans, "mainJava")); if (useDiskCache) { saveTextFile(new File(cacheFile.getPath() + "x"), mainJava); saveTextFile(cacheFile, main); } return main; } finally { _close(__1977); }} finally { unlock(__1975); } } static Class transpileRaw_translator() { if (transpileRaw_trans == null) { //print("Loading translator."); transpileRaw_trans = hotwireSharingLibraries_silently(defaultJavaXTranslatorID()); makeDependent(transpileRaw_trans); //print("Loaded translator: " + identityHashCode(transpileRaw_trans)); } setOpt(transpileRaw_trans, "print_silent", transpileRaw_silent); return transpileRaw_trans; } static void transpileRaw_copyFromCreator() { Lock __1976 = transpileRaw_lock; lock(__1976); try { if (transpileRaw_trans != null) return; Object c = creator(); if (c == null) return; Class trans = (Class) (getOpt(c, "transpileRaw_trans")); Lock lock = (Lock) (getOpt(c, "transpileRaw_lock")); if (trans != null && lock != null) { print("Using creator's transpiler: " + getProgramID(c) + " => " + programID()); transpileRaw_lock = lock; transpileRaw_trans = trans; } } finally { unlock(__1976); } } static void cleanMeUp_transpileRaw() { transpileRaw_trans = null; // release proactively (it's big) } static Class veryQuickJava_finish(String src, List libs) { libs = cloneList(libs); src = findTranslators2(src, libs); //print("Libs found: " + struct(libs)); String dehlibs = join(" ", libs); File bytecode = null; //try { bytecode = javaCompile_overInternalBot(src, dehlibs); /*} on fail { print("Was compiling: " + src + "\n"); }*/ return hotwireCore(concatLists(ll(bytecode), loadLibraries(libs))); } static Set tok_returnTypesOfStaticFunction_uncleaned(List tok, String functionName) { List> funcs = findFullFunctionDefs(tok, true); TreeSet out = new TreeSet(); for (List tokF : funcs) { int i = indexOfAny(tokF, 0, "(", "{"); if (i < 0) continue; String fname = get(tokF, i-2); if (!eq(fname, functionName)) continue; out.add(joinSubList(tokF, 1, i-3)); } return out; } static boolean containsOneOf(Collection l, A... x) { for (A a : unnull(l)) if (eqOneOf(a, x)) return true; return false; } static boolean containsOneOf(Collection l, Set set) { if (set == null) return false; for (A a : unnull(l)) if (set.contains(a)) return true; return false; } static boolean containsOneOf(String s, String... x) { for (String o : x) if (contains(s, o)) return true; return false; } static String textOfStandardFunction(String sfName) { return loadSnippet_cached(stdFunctions_cached().get(sfName)); } static String fromUTF8(byte[] bytes) { return fromUtf8(bytes); } static String dropTranslators(String src) { return findTranslators2(src, null); } // modifies original tok static List dropTranslators(List tok) { return findTranslators2(tok, null); } static String uniqueFileNameUsingMD5_80_v2(String fullName) { return uniqueFileNameUsingMD5_80_v2(fullName, md5(fullName)); } static String uniqueFileNameUsingMD5_80_v2(String fullName, String md5) { return takeFirst(80-33, fileNameEncode(fullName)) + " - " + md5; } static AutoCloseable tempLoadingAnim(String msg) { return tempDisposeWindow(loadingAnim(msg)); } static int systemHashCode(Object o) { return identityHashCode(o); } static Object getTL(Object o, String name) { return getThreadLocal(o, name); } static A getTL(ThreadLocal tl) { return getThreadLocal(tl); } static A getTL(ThreadLocal tl, A defaultValue) { return getThreadLocal(tl, defaultValue); } static Class hotwireSharingLibraries_silently(String progID) { AutoCloseable __1994 = temp_loadPage_silent(); try { return hotwireSharingLibraries(progID); } finally { _close(__1994); }} static WeakReference creator_class; static Object creator() { return creator_class == null ? null : creator_class.get(); } // probably better than findTranslators (uses tokens) // removes invocations from src static String findTranslators2(String src, List libsOut) { return join(findTranslators2(javaTok(src), libsOut)); } // modifies original tok static List findTranslators2(List tok, List libsOut) { int i; while ((i = jfind(tok, "!")) >= 0) { setAdd(libsOut, tok.get(i+2)); clearTokens(tok, i, i+3); } return tok; } static File javaCompile_overInternalBot(String src) { return javaCompile_overInternalBot(src, ""); } // returns path to jar static synchronized File javaCompile_overInternalBot(String src, String dehlibs) { return CompilerBot.compile(src, dehlibs); } static Class hotwireCore(List files) { try { // make class loader JavaXClassLoader classLoader = hotwire_makeClassLoader(files); // load & return main class Class theClass = classLoader.loadClass("main"); setOpt(theClass, "__javax", getJavaX()); if (getOpt(theClass, "programID") == null) setOpt(theClass, "programID", "#3999999"); if (!_inCore()) hotwire_copyOver(theClass); return theClass; } catch (Exception __e) { throw rethrow(__e); } } static List loadLibraries(List snippetIDs) { return map("loadLibrary", snippetIDs); } static Set findFullFunctionDefs_keywords = new HashSet(splitAtSpace("static svoid ssvoid ssynchronized sbool sS sO sL")); // returns actual CNC static List> findFullFunctionDefs(List tok, boolean topLevelOnly) { int n = l(tok); List> functions = new ArrayList(); for (int i = 1; i < n; i += 2) { String t = tok.get(i); if (topLevelOnly && eq(t, "{")) i = findEndOfBlock(tok, i)-1; else if (findFullFunctionDefs_keywords.contains(t)) { int j = i+2; while (j < n && !eqOneOf(tok.get(j), ";", "=", "(", "{")) j += 2; if ((eqGet(tok, j, "(") || eq(t, "svoid") && eqGet(tok, j, "{")) && isIdentifier(tok.get(j-2))) { int k = smartIndexOf(tok, "{", j); if (k < l(tok)) { k = findEndOfBlock(tok, k)+1; functions.add(subList(tok, i-1, k)); i = k-2; } } } } return functions; } static List> findFullFunctionDefs(String s, boolean topLevelOnly) { return findFullFunctionDefs(javaTok(s), topLevelOnly); } static String loadSnippet_cached(String id) { return loadSnippet_simpleCache(id); } static File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } static String fileNameEncode_safeChars = " ()[]#,!"; static String fileNameEncode(String s) { StringBuilder buf = new StringBuilder(); int n = l(s); for (int i = 0; i < n; i++) { char c = s.charAt(i); if (contains(fileNameEncode_safeChars, c)) buf.append(c); else buf.append(urlencode(str(c))); } return str(buf); } static AutoCloseable tempDisposeWindow(final Window w) { return new AutoCloseable() { public void close() { disposeWindow(w); } }; } static JWindow loadingAnim() { return showLoadingAnimation(); } static JWindow loadingAnim(String text) { return showLoadingAnimation(text); } static AutoCloseable temp_loadPage_silent() { return tempSetThreadLocal(loadPage_silent, true); } static Class hotwireSharingLibraries(String progID) { try { Pair p = CompilerBot.compileSnippet2(progID); File jar = p.a; assertTrue(f2s(jar), jar.isFile()); // collect files (program + libraries) List files = ll(jar); String dehlibs = unnull(loadTextFileFromZip(jar, "libraries")); List myLibraries = myLibraryFiles(); //print("My libraries: " + myLibraries); Matcher matcher = Pattern.compile("\\d+").matcher(dehlibs); while (matcher.find()) { String libID = matcher.group(); File lib = loadLibrary(libID); if (myLibraries.contains(lib)) { //print("Skipping lib " + lib); } else { //print("Adding lib " + lib); files.add(lib); } } // make class loader JavaXClassLoaderWithParent classLoader = new JavaXClassLoaderWithParent(progID, files, myClassLoader()); return hotwire_finish(classLoader, progID, p.b); } catch (Exception __e) { throw rethrow(__e); } } static ExpiringMap2 loadSnippet_simpleCache_map = new ExpiringMap2(10000); static Lock loadSnippet_simpleCache_lock = lock(); // timeout for loadPage static int loadSnippet_simpleCache_timeout = 60000; static String loadSnippet_simpleCache(String id) { if (id == null) return null; Lock __2022 = loadSnippet_simpleCache_lock; lock(__2022); try { id = fsI(id); // get from cache String src = loadSnippet_simpleCache_map.get(id); if (src != null) return src; // load & put in cache Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_simpleCache_timeout); try { src = loadSnippet(id); if (src != null) loadSnippet_simpleCache_map.put(id, src); return src; } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } finally { unlock(__2022); } } static File loadBinarySnippet(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); long id = parseSnippetID(snippetID); if (isImageServerSnippet(id)) return loadImageAsFile(snippetID); File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) == 0) f = loadDataSnippetToFile(snippetID); return f; } catch (Exception __e) { throw rethrow(__e); } } static void disposeWindow(final Window window) { if (window != null) { swing(new Runnable() { public void run() { try { window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); // call listeners myFrames_list.remove(window); window.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); //..."; }}); } } static void disposeWindow(final Component c) { disposeWindow(getWindow(c)); } static void disposeWindow(Object o) { if (o != null) disposeWindow(((Component) o)); } static void disposeWindow() { disposeWindow(heldInstance(Component.class)); } static JWindow showLoadingAnimation() { return showLoadingAnimation("Hold on user..."); } static JWindow showLoadingAnimation(String text) { try { return showAnimationInTopRightCorner("#1003543", text); } catch (Throwable __e) { return null; } } static List myLibraryFiles() { return (List) get(myClassLoader(), "files"); } static Map myFrames_list = weakHashMap(); static List myFrames() { return swing(new F0>() { List get() { try { return keysList(myFrames_list); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret keysList(myFrames_list);"; }}); } static File loadImageAsFile(String snippetIDOrURL) { try { if (isURL(snippetIDOrURL)) throw fail("not implemented"); if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL); String snippetID = "" + parseSnippetID(snippetIDOrURL); File file = imageSnippetCacheFile(snippetID); if (fileSize(file) > 0) return file; String imageURL = snippetImageURL_noHttps(snippetID); System.err.println("Loading image: " + imageURL); byte[] data = loadBinaryPage(imageURL); saveBinaryFile(file, data); return file; } catch (Exception __e) { throw rethrow(__e); } } static Window getWindow(Object o) { if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Window) return (Window) c; c = c.getParent(); } return null; } static A heldInstance(Class c) { List l = holdInstance_l.get(); for (int i = l(l)-1; i >= 0; i--) { Object o = l.get(i); if (isInstanceOf(o, c)) return (A) o; } throw fail("No instance of " + className(c) + " held"); } static boolean showAnimationInTopRightCorner_alwaysOnTop = true; static boolean showAnimationInTopRightCorner_on = true; // automatically switches to AWT thread for you // text is optional text below image static JWindow showAnimationInTopRightCorner(String imageID, String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(imageID), text); } static JWindow showAnimationInTopRightCorner(final Image image, final String text) { if (image == null || isHeadless() || !showAnimationInTopRightCorner_on) return null; return showAnimationInTopRightCorner(imageIcon(image), text); } static JWindow showAnimationInTopRightCorner(final ImageIcon imageIcon, final String text) { if (isHeadless() || !showAnimationInTopRightCorner_on) return null; return (JWindow) swingAndWait(new F0() { Object get() { try { JLabel label = new JLabel(imageIcon); if (nempty(text)) { label.setText(text); label.setVerticalTextPosition(SwingConstants.BOTTOM); label.setHorizontalTextPosition(SwingConstants.CENTER); } final JWindow window = showInTopRightCorner(label); onClick(label, new Runnable() { public void run() { try { window.dispose() ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispose()"; }}); if (showAnimationInTopRightCorner_alwaysOnTop) window.setAlwaysOnTop(true); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JLabel label = new JLabel(imageIcon);\r\n if (nempty(text)) {\r\n label.s..."; }}); } static JWindow showAnimationInTopRightCorner(final String imageID) { return showAnimationInTopRightCorner(imageID, ""); } static JWindow showAnimationInTopRightCorner(String imageID, double seconds) { return showAnimationInTopRightCorner(imageID, "", seconds); } static JWindow showAnimationInTopRightCorner(String imageID, String text, double seconds) { if (isHeadless()) return null; return disposeWindowAfter(iround(seconds*1000), showAnimationInTopRightCorner(imageID, text)); } static JWindow showAnimationInTopRightCorner(BufferedImage img, String text, double seconds) { return disposeWindowAfter(iround(seconds*1000), showAnimationInTopRightCorner(img, text)); } static boolean loadBufferedImage_useImageCache = true; static BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try { ping(); if (snippetIDOrURLOrFile == null) return null; if (isURL(snippetIDOrURLOrFile)) return imageIO_readURL(snippetIDOrURLOrFile); if (isAbsolutePath(snippetIDOrURLOrFile)) return loadBufferedImage(new File(snippetIDOrURLOrFile)); if (!isSnippetID(snippetIDOrURLOrFile)) throw fail("Not a URL or snippet ID or file: " + snippetIDOrURLOrFile); String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return loadBufferedImage(rl.loadLibrary(snippetID)); File dir = imageSnippetsCacheDir(); if (loadBufferedImage_useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return ImageIO.read(file); } catch (Throwable e) { e.printStackTrace(); // fall back to loading from sourceforge } } String imageURL = snippetImageURL_http(snippetID); print("Loading image: " + imageURL); BufferedImage image = imageIO_readURL(imageURL); if (loadBufferedImage_useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); //Log.info("Cached image."); } //Log.info("Loaded image."); return image; } catch (Exception __e) { throw rethrow(__e); } } static BufferedImage loadBufferedImage(File file) { try { return file.isFile() ? ImageIO.read(file) : null; } catch (Exception __e) { throw rethrow(__e); } } static ThreadLocal> holdInstance_l = new ThreadLocal(); static AutoCloseable holdInstance(Object o) { if (o == null) return null; listThreadLocalAdd(holdInstance_l, o); return new AutoCloseable() { public void close() { listThreadLocalPopLast(holdInstance_l); } }; } static Map weakHashMap() { return newWeakHashMap(); } static List keysList(Map map) { return cloneListSynchronizingOn(keys(map), map); } static List keysList(MultiSet ms) { return ms == null ? null : keysList(ms.map); } static boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static File imageSnippetCacheFile(String snippetID) { File dir = imageSnippetsCacheDir(); if (!loadBufferedImage_useImageCache) return null; return new File(dir, parseSnippetID(snippetID) + ".png"); } static String snippetImageURL_noHttps(String snippetID) { return snippetImageURL_noHttps(snippetID, "png"); } static String snippetImageURL_noHttps(String snippetID, String contentType) { return snippetImageURL(snippetID, contentType) .replace("https://www.botcompany.de:8443/", "http://www.botcompany.de:8080/") .replace("https://botcompany.de/", "http://botcompany.de/"); } static boolean isInstanceOf(Object o, Class type) { return type.isInstance(o); } static int imageIcon_cacheSize = 10; static boolean imageIcon_verbose = false; static Map imageIcon_cache; static Lock imageIcon_lock = lock(); static ThreadLocal imageIcon_fixGIF = new ThreadLocal(); // not going through BufferedImage preserves animations static ImageIcon imageIcon(String imageID) { try { if (imageID == null) return null; Lock __2062 = imageIcon_lock; lock(__2062); try { if (imageIcon_cache == null) imageIcon_cache = new MRUCache(imageIcon_cacheSize); imageID = fsI(imageID); ImageIcon ii = imageIcon_cache.get(imageID); if (ii == null) { if (imageIcon_verbose) print("Loading image icon: " + imageID); File f = loadBinarySnippet(imageID); Boolean b = imageIcon_fixGIF.get(); if (!isFalse(b)) ii = new ImageIcon(loadBufferedImageFixingGIFs(f)); else ii = new ImageIcon(f.toURI().toURL()); } else imageIcon_cache.remove(imageID); // move to front of cache on access imageIcon_cache.put(imageID, ii); return ii; } finally { unlock(__2062); } } catch (Exception __e) { throw rethrow(__e); } } // doesn't fix GIFs static ImageIcon imageIcon(File f) { try { return new ImageIcon(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } static ImageIcon imageIcon(Image img) { return new ImageIcon(img); } static JWindow showInTopRightCorner(Component c) { return swing(() -> { JWindow w = new JWindow(); w.add(c); w.pack(); moveToTopRightCorner(w); w.setVisible(true); return w; }); } static A onClick(final A c, final Object runnable) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { callF(runnable, e); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseListener(new MouseAdapter {\r\n public void mouseClicked(MouseEv..."; }}); } return c; } // re-interpreted for buttons static void onClick(JButton btn, final Object runnable) { onEnter(btn, runnable); } static A disposeWindowAfter(int delay, final A w) { if (w != null) swingLater(delay, new Runnable() { public void run() { try { w.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.dispose();"; }}); return w; } static A disposeWindowAfter(A w, double seconds) { return disposeWindowAfter(toMS_int(seconds), w); } static A disposeWindowAfter(double seconds, A w) { return disposeWindowAfter(w, seconds); } static int iround(double d) { return (int) Math.round(d); } static int iround(Number n) { return iround(toDouble(n)); } static BufferedImage imageIO_readURL(String url) { try { if (startsWith(url, "https:")) // Java is still buggy there :( disableCertificateValidation(); return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static boolean isAbsolutePath(String s) { return s != null && new File(s).isAbsolute(); } static boolean isAbsolutePath(File f) { return f != null && f.isAbsolute(); } static File imageSnippetsCacheDir() { return javaxCachesDir("Image-Snippets"); } static String snippetImageURL_http(String snippetID) { return snippetImageURL_http(snippetID, "png"); } static String snippetImageURL_http(String snippetID, String contentType) { return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080"); } static void listThreadLocalAdd(ThreadLocal> tl, A a) { List l = tl.get(); if (l == null) tl.set(l = new ArrayList()); l.add(a); } static A listThreadLocalPopLast(ThreadLocal> tl) { List l = tl.get(); if (l == null) return null; A a = popLast(l); if (empty(l)) tl.set(null); return a; } static ArrayList cloneListSynchronizingOn(Collection l, Object mutex) { if (l == null) return new ArrayList(); synchronized(mutex) { return new ArrayList(l); } } static String snippetImageURL(long snippetID) { return snippetImageURL(fsI(snippetID)); } static String snippetImageURL(String snippetID) { return snippetImageURL(snippetID, "png"); } static String snippetImageURL(String snippetID, String contentType) { if (isURL(snippetID)) return snippetID; long id = parseSnippetID(snippetID); String url; if (id == 1000010 || id == 1000012) url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + id; else if (isImageServerSnippet(id)) url = imageServerLink(id); else //url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id + "&contentType=image/" + contentType; url = "https://www.botcompany.de:8443/img/" + id; return url; } static boolean loadBufferedImageFixingGIFs_debug = false; static ThreadLocal> loadBufferedImageFixingGIFs_output = new ThreadLocal(); static Image loadBufferedImageFixingGIFs(File file) { try { if (!file.exists()) return null; // Load anything but GIF the normal way if (!isGIF(file)) return ImageIO.read(file); if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": checking gif"); // Get GIF reader ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); // Give it the stream to decode from reader.setInput(ImageIO.createImageInputStream(file)); int numImages = reader.getNumImages(true); // Get 'metaFormatName'. Need first frame for that. IIOMetadata imageMetaData = reader.getImageMetadata(0); String metaFormatName = imageMetaData.getNativeMetadataFormatName(); // Find out if GIF is bugged boolean foundBug = false; for (int i = 0; i < numImages && !foundBug; i++) { // Get metadata IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode)node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { foundBug = true; } break; } } } if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": " + f2s(file) + " foundBug=" + foundBug); // Load non-bugged GIF the normal way Image image; if (!foundBug) { image = Toolkit.getDefaultToolkit().createImage(f2s(file)); } else { // Prepare streams for image encoding ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); { ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream); try { // Get GIF writer that's compatible with reader ImageWriter writer = ImageIO.getImageWriter(reader); // Give it the stream to encode to writer.setOutput(ios); writer.prepareWriteSequence(null); for (int i = 0; i < numImages; i++) { // Get input image BufferedImage frameIn = reader.read(i); // Get input metadata IIOMetadataNode root = (IIOMetadataNode)reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode)node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { // Overwrite with a valid delay value ((IIOMetadataNode)node).setAttribute("delayTime", "10"); } break; } } // Create output metadata IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null); // Copy metadata to output metadata metadata.setFromTree(metadata.getNativeMetadataFormatName(), root); // Create output image IIOImage frameOut = new IIOImage(frameIn, null, metadata); // Encode output image writer.writeToSequence(frameOut, writer.getDefaultWriteParam()); } writer.endWriteSequence(); } finally { _close(ios); }} // Create image using encoded data byte[] data = baoStream.toByteArray(); setVar(loadBufferedImageFixingGIFs_output.get(), data); if (loadBufferedImageFixingGIFs_debug) print("Data size: " + l(data)); image = Toolkit.getDefaultToolkit().createImage(data); } return image; } catch (Exception __e) { throw rethrow(__e); } } static int moveToTopRightCorner_inset = 20; static A moveToTopRightCorner(A a) { return moveToTopRightCorner(moveToTopRightCorner_inset, moveToTopRightCorner_inset, a); } static A moveToTopRightCorner(int insetX, int insetY, A a) { Window w = getWindow(a); if (w != null) w.setLocation(getScreenSize().width-w.getWidth()-insetX, insetY); return a; } static JTextField onEnter(final JTextField tf, final Object action) { if (action == null || tf == null) return tf; tf.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { tf.selectAll(); callF(action); } catch (Throwable __e) { messageBox(__e); }}}); return tf; } static JButton onEnter(JButton btn, final Object action) { if (action == null || btn == null) return btn; btn.addActionListener(actionListener(action)); return btn; } static JList onEnter(JList list, Object action) { list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action))); return list; } static JComboBox onEnter(final JComboBox cb, final Object action) { { swing(new Runnable() { public void run() { try { if (cb.isEditable()) { JTextField text = (JTextField) cb.getEditor().getEditorComponent(); onEnter(text, action); } else { cb.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); cb.getActionMap().put("enter", abstractAction("", new Runnable() { public void run() { try { cb.hidePopup(); callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.hidePopup(); callF(action);"; }})); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (cb.isEditable()) {\r\n JTextField text = (JTextField) cb.getEditor().g..."; }}); } return cb; } static JTable onEnter(final JTable table, final Object action) { table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); table.getActionMap().put("Enter", new AbstractAction() { public void actionPerformed(ActionEvent e) { callF(action, table.getSelectedRow()); } }); return table; } /*static JTextArea onEnter(final JTextArea ta, fO action) { addKeyListener(ta, enterKeyListener(action)); ret ta; }*/ static JTextField onEnter(Object action, JTextField tf) { return onEnter(tf, action); } static void swingLater(long delay, final Object r) { javax.swing.Timer timer = new javax.swing.Timer(toInt(delay), actionListener(wrapAsActivity(r))); timer.setRepeats(false); timer.start(); } static void swingLater(Object r) { SwingUtilities.invokeLater(toRunnable(r)); } static int toMS_int(double seconds) { return toInt_checked((long) (seconds*1000)); } static double toDouble(Object o) { if (o instanceof Number) return ((Number) o).doubleValue(); if (o instanceof BigInteger) return ((BigInteger) o).doubleValue(); if (o == null) return 0.0; throw fail(o); } static String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static byte[] isGIF_magic = bytesFromHex("47494638"); // Actual signature is longer, but we're lazy static boolean isGIF(byte[] data) { return byteArrayStartsWith(data, isGIF_magic); } static boolean isGIF(File f) { return isGIF(loadBeginningOfBinaryFile(f, l(isGIF_magic))); } static void setVar(IVar v, A value) { if (v != null) v.set(value); } static Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } static void messageBox(final String msg) { if (headless()) print(msg); else { swing(new Runnable() { public void run() { try { JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JOptionPane.showMessageDialog(null, msg, \"JavaX\", JOptionPane.INFORMATION_MES..."; }}); } } static void messageBox(Throwable e) { //showConsole(); printStackTrace(e); messageBox(hideCredentials(innerException2(e))); } static ActionListener actionListener(final Object runnable) { return actionListener(runnable, null); } static ActionListener actionListener(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; final Object info = _threadInfo(); return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { _threadInheritInfo(info); AutoCloseable __2114 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__2114); }} catch (Throwable __e) { messageBox(__e); }}}; } static KeyListener enterKeyListener(final Object action) { return new KeyAdapter() { public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) pcallF(action); } }; } static Runnable rCallOnSelectedListItem(final JList list, final Object action) { return new Runnable() { public void run() { try { pcallF(action, getSelectedItem(list)) ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(action, getSelectedItem(list))"; }}; } static AbstractAction abstractAction(String name, final Object runnable) { return new AbstractAction(name) { public void actionPerformed(ActionEvent evt) { pcallF(runnable); } }; } static Runnable wrapAsActivity(Object r) { return toRunnable(r); } static int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static boolean possibleMD5(String s) { return isMD5(s); } static String getSelectedItem(JList l) { return (String) l.getSelectedValue(); } static String getSelectedItem(JComboBox cb) { return strOrNull(cb.getSelectedItem()); } static String strOrNull(Object o) { return o == null ? null : str(o); } // immutable, has strong refs final static class _MethodCache { final Class c; final HashMap> cache = new HashMap(); _MethodCache(Class c) { this.c = c; _init(); } void _init() { Class _c = c; while (_c != null) { for (Method m : _c.getDeclaredMethods()) if (!reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } // add default methods - this might lead to a duplication // because the overridden method is also added, but it's not // a problem except for minimal performance loss. for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if (m.isDefault() && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); } // Returns only matching methods Method findMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } Method findStaticMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } }static abstract class VF1 implements IVF1 { public abstract void get(A a); }static class NowFuture implements Future { T result; NowFuture() {} NowFuture(T result) { this.result = result;} public boolean cancel(final boolean b) { return false; } public boolean isCancelled() { return false; } public boolean isDone() { return true; } public T get() { return result; } public T get(long l, TimeUnit timeUnit) { return result; } }static class Var implements IVar { Var() {} Var(A v) { this.v = v;} A v; // you can access this directly if you use one thread public synchronized void set(A a) { if (v != a) { v = a; notifyAll(); } } public synchronized A get() { return v; } public synchronized boolean has() { return v != null; } public synchronized void clear() { v = null; } public String toString() { return str(get()); } }static final class IndexedList2 extends AbstractList { ArrayList l = new ArrayList(); MultiSet index = new MultiSet(false); // HashMap static boolean debug = false; static int instances; IndexedList2() { ++instances; } IndexedList2(List x) { this(); l.ensureCapacity(l(x)); addAll(x); } // required immutable list methods @Override public A get(int i) { return l.get(i); } @Override public int size() { return l.size(); } // required mutable list methods @Override public A set(int i, A a) { A prev = l.get(i); if (prev != a) { index.remove(prev); index.add(a); } l.set(i, a); return prev; } @Override public void add(int i, A a) { index.add(a); l.add(i, a); } @Override public A remove(int i) { A a = l.get(i); index.remove(a); l.remove(i); return a; } // speed up methods @Override protected void removeRange(int fromIndex, int toIndex) { for (int i = fromIndex; i < toIndex; i++) unindex(i); l.subList(fromIndex, toIndex).clear(); } @Override public int indexOf(Object a) { if (!contains(a)) return -1; return l.indexOf(a); } @Override public boolean contains(Object a) { boolean b = index.contains((A) a); if (debug) print("IndexedList2.contains " + a + " => " + b); return b; } @Override public void clear() { index.clear(); l.clear(); } @Override public boolean addAll(int i, Collection c) { index.addAll((Collection) c); return l.addAll(i, c); } // indexing methods void unindex(int i) { index.remove(l.get(i)); } void index(int i) { index.add(l.get(i)); } // static methods static IndexedList2 ensureIndexed(List l) { return l instanceof IndexedList2 ? (IndexedList2) l : new IndexedList2(l); } }static class AutoInitVar extends Var { Object make; boolean has = false; Lock lock = lock(); AutoInitVar() {} AutoInitVar(Object make) { this.make = make;} public A get() { if (has) return super.get(); Lock __2146 = lock; lock(__2146); try { if (has) return super.get(); set((A) pcallF(make)); make = null; has = true; return super.get(); } finally { unlock(__2146); } } }static abstract class TokCondition { abstract boolean get(List tok, int i); // i = N Index }static interface IResourceLoader { String loadSnippet(String snippetID); String getTranspiled(String snippetID); // with libs int getSnippetType(String snippetID); String getSnippetTitle(String snippetID); File loadLibrary(String snippetID); File pathToJavaXJar(); File getSnippetJar(String snippetID, String transpiledSrc); }static class CombinedMap extends AbstractMap { List < Map < A , B > > maps = new ArrayList(); CombinedMap() {} CombinedMap(Map... maps) { addAllNonNulls(this.maps, maps); } > CombinedMap(Collection maps) { addAllNonNulls(this.maps, maps); } public int size() { return lengthLevel2_maps(maps); } public Set> entrySet() { throw fail(); } public boolean containsKey(Object o) { for (Map map : maps) if (map.containsKey(o)) return true; return false; } @Override public B get(Object o) { for (Map map : maps) if (map.containsKey(o)) return map.get(o); return null; } } static class Pair implements Comparable> { A a; B b; Pair() {} Pair(A a, B b) { this.b = b; this.a = a;} public int hashCode() { return hashCodeFor(a) + 2*hashCodeFor(b); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Pair)) return false; Pair t = (Pair) o; return eq(a, t.a) && eq(b, t.b); } public String toString() { return "<" + a + ", " + b + ">"; } public int compareTo(Pair p) { if (p == null) return 1; int i = ((Comparable) a).compareTo(p.a); if (i != 0) return i; return ((Comparable) b).compareTo(p.b); } }static class JavaXClassLoader extends URLClassLoader { String progID; List files; Set triedToLoad = synchroSet(); Set loadedClasses = synchroSet(); boolean retired = false; Object retiredMarker; JavaXClassLoader(String progID, List files) { this(progID, files, getSystemClassLoader()); } JavaXClassLoader(String progID, List files, ClassLoader parent) { super(new URL[0], parent); this.progID = progID; this.files = files; { try { for (File f : files) addURL(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } fixACCInClassLoader(this); } protected Class findClass(String name) throws ClassNotFoundException { boolean triedBefore = !triedToLoad.add(name); try { Class c = super.findClass(name); loadedClasses.add(c); if (eq(name, "main")) callOpt(javax(), "registerAMainClass", c); return c; } catch (ClassNotFoundException e) { throw new ClassNotFoundException("Class " + name + " not found in " + joinWithComma(map("f2s", files)) + " (progID=" + progID + ")" + (triedBefore ? ", tried to load before" : ""), e); } } public String toString() { return "JavaXClassLoader[" + systemHashCodeHex(this) + "] - " + progID; } } static class JavaXClassLoaderWithParent extends JavaXClassLoader { ClassLoader virtualParent; JavaXClassLoaderWithParent(String progID, List files, ClassLoader virtualParent) { super(progID, files); this.virtualParent = virtualParent; } protected Class findClass(String name) throws ClassNotFoundException { if (virtualParent != null && !eq(name, "main") && !name.startsWith("main$")) { try { return virtualParent.loadClass(name); } catch (ClassNotFoundException e) {} } return super.findClass(name); } } final static class IntRange { int start, end; IntRange() {} IntRange(int start, int end) { this.end = end; this.start = start;} public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } int length() { return end-start; } static String _fieldOrder = "start end"; public String toString() { return "[" + start + ";" + end + "]"; } }static abstract class F0 { abstract A get(); }static abstract class F1 { abstract B get(A a); }// you still need to implement hasNext() and next() static abstract class IterableIterator implements Iterator, Iterable { public Iterator iterator() { return this; } public void remove() { unsupportedOperation(); } }static class Snippet { String id, title, md5, type, text; Snippet() {} Snippet(String id, String title) { this.title = title; this.id = id;} Snippet(String id, String title, String md5) { this.md5 = md5; this.title = title; this.id = id;} public String toString() { return id + " - " + title; } public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } }static abstract class F2 { abstract C get(A a, B b); }// elements are put to front when added (not when accessed) static class MRUCache extends LinkedHashMap { int maxSize = 10; MRUCache() {} MRUCache(int maxSize) { this.maxSize = maxSize;} protected boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } }static interface IF0 { A get(); }static abstract class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception {} }static class ExpiringMap2 extends AbstractMap { Map> byKey = new HashMap(); // key -> pair(expiry sys time, value) PriorityBlockingQueue < Pair < Long , A > > queue = new PriorityBlockingQueue(); // queue(pair(expiry sys time, key)) long standardExpiryTime; // ms boolean renewOnOverwrite = true, renewOnGet; Object onChange; // new RestartableCountdown countdown; // TODO ExpiringMap2() {} ExpiringMap2(long standardExpiryTime) { this.standardExpiryTime = standardExpiryTime;} ExpiringMap2(long standardExpiryTime, Object onChange) { this.onChange = onChange; this.standardExpiryTime = standardExpiryTime;} synchronized boolean clean() { boolean changes = false; Pair p; while ((p = queue.peek()) != null && sysTime() >= p.a) { p = queue.poll(); Pair v = byKey.get(p.b); if (v != null /*&& v.a == p.a*/) { byKey.remove(p.b); changes = true; change(); } } return changes; } void change() { callF(onChange); } synchronized public B put(A a, B b) { clean(); long timeout = sysTime()+standardExpiryTime; Pair p = byKey.get(a); if (p != null && renewOnOverwrite) queue.remove(new Pair(p.a, a)); byKey.put(a, pair(timeout, b)); change(); if (p == null || renewOnOverwrite) queue.add(new Pair(timeout, a)); return pairB(p); } synchronized public B remove(Object a) { clean(); Pair p = byKey.get(a); if (p == null) return null; queue.remove(new Pair(p.a, a)); byKey.remove(a); change(); return p.b; } synchronized public B get(Object a) { clean(); Pair p = byKey.get(a); if (renewOnGet && p != null) { queue.remove(new Pair(p.a, a)); long timeout = sysTime()+standardExpiryTime; byKey.put((A) a, pair(timeout, p.b)); queue.add(new Pair(timeout, a)); } return pairB(p); } synchronized public Set> entrySet() { clean(); // TODO: mutex return synchronizedSet(mapValues("pairB", byKey).entrySet()); } synchronized public Set keySet() { clean(); return synchronizedSet(byKey.keySet()); } synchronized public int size() { clean(); return byKey.size(); } void setStandardExpiryTime(long ms) { standardExpiryTime = ms; } synchronized ExpiringMap2 setMap(Map innerMap) { byKey = innerMap; return this; } } static class JavaXClassLoaderWithParent2 extends JavaXClassLoader { ClassLoader virtualParent; List classesToSkip; // classes that should be taken from parent JavaXClassLoaderWithParent2(String progID, List files, ClassLoader virtualParent, List classesToSkip) { super(progID, files); this.virtualParent = virtualParent; this.classesToSkip = classesToSkip; } protected Class findClass(String name) throws ClassNotFoundException { if (shouldDelegate(name)) { Class c = virtualParent.loadClass(name); if (c != null) return c; } return super.findClass(name); } boolean shouldDelegate(String name) { for (String s : classesToSkip) if (eq(name, s) || startsWith(name, s + "$")) return true; return false; } }static interface IF2 { C get(A a, B b); }static interface Producer { public A next(); }static ThreadLocal DynamicObject_loading = new ThreadLocal(); static class DynamicObject { String className; // just the name, without the "main$" /*new XXX - not initializing anymore - may cause problems in the odd legacy program */ LinkedHashMap fieldValues; DynamicObject() {} // className = just the name, without the "main$" DynamicObject(String className) { this.className = className;} Map _map() { return fieldValues; } }static interface IF1 { B get(A a); }static class PersistableThrowable { String className; String msg; String stacktrace; PersistableThrowable() {} PersistableThrowable(Throwable e) { if (e == null) className = "Crazy Null Error"; else { className = getClassName(e).replace('/', '.'); msg = e.getMessage(); stacktrace = getStackTrace_noRecord(e); } } public String toString() { return nempty(msg) ? className + ": " + msg : className; } }static interface IVar { void set(A a); A get(); default boolean has() { return get() != null; } default void clear() { set(null); } }static class Cache { Object maker; // func -> A A value; long loaded; static boolean debug = false; long changeCount; Lock lock = lock(); Cache() {} Cache(Object maker) { this.maker = maker;} A get() { if (hasLock(lock)) return value; // Must be called from within maker Lock __2188 = lock; lock(__2188); try { if (loaded == 0) { value = make(); changeCount++; loaded = sysNow(); } return value; } finally { unlock(__2188); } } void clear() { Lock __2189 = lock; lock(__2189); try { if (debug && loaded != 0) print("Clearing cache"); value = null; changeCount++; loaded = 0; } finally { unlock(__2189); } } // clear if older than x seconds // 0 does not do anything void clear(double seconds) { Lock __2190 = lock; lock(__2190); try { if (seconds != 0 && loaded != 0 && sysNow() >= loaded+seconds*1000) clear(); } finally { unlock(__2190); } } // override void set(A a) { Lock __2191 = lock; lock(__2191); try { value = a; ++changeCount; loaded = sysNow(); } finally { unlock(__2191); } } A make() { return (A) callF(maker); } } static interface IVF1 { void get(A a); }// uses HashMap by default static class MultiSet { Map map = new HashMap(); MultiSet(boolean useTreeMap) { if (useTreeMap) map = new TreeMap(); } MultiSet() {} MultiSet(Iterable c) { addAll(c); } MultiSet(MultiSet ms) { synchronized(ms) { for (A a : ms.keySet()) add(a, ms.get(a)); }} synchronized void add(A key) { add(key, 1); } synchronized void addAll(Iterable c) { if (c != null) for (A a : c) add(a); } synchronized void addAll(MultiSet ms) { for (A a : ms.keySet()) add(a, ms.get(a)); } synchronized void add(A key, int count) { if (count <= 0) return; if (map.containsKey(key)) map.put(key, map.get(key)+count); else map.put(key, count); } synchronized int get(A key) { Integer i = map.get(key); return i != null ? i : 0; //ret key != null && map.containsKey(key) ? map.get(key) : 0; } synchronized boolean contains(A key) { return map.containsKey(key); } synchronized void remove(A key) { Integer i = map.get(key); if (i != null && i > 1) map.put(key, i - 1); else map.remove(key); } synchronized List topTen() { return getTopTen(); } synchronized List getTopTen() { return getTopTen(10); } synchronized List getTopTen(int maxSize) { List list = getSortedListDescending(); return list.size() > maxSize ? list.subList(0, maxSize) : list; } synchronized List highestFirst() { return getSortedListDescending(); } synchronized List lowestFirst() { return reversedList(getSortedListDescending()); } synchronized List getSortedListDescending() { List list = new ArrayList(map.keySet()); Collections.sort(list, new Comparator() { public int compare(A a, A b) { return map.get(b).compareTo(map.get(a)); } }); return list; } synchronized int getNumberOfUniqueElements() { return map.size(); } synchronized int uniqueSize() { return map.size(); } synchronized Set asSet() { return map.keySet(); } synchronized NavigableSet navigableSet() { return navigableKeys((NavigableMap) map); } synchronized Set keySet() { return map.keySet(); } synchronized A getMostPopularEntry() { int max = 0; A a = null; for (Map.Entry entry : map.entrySet()) { if (entry.getValue() > max) { max = entry.getValue(); a = entry.getKey(); } } return a; } synchronized void removeAll(A key) { map.remove(key); } synchronized int size() { int size = 0; for (int i : map.values()) size += i; return size; } synchronized MultiSet mergeWith(MultiSet set) { MultiSet result = new MultiSet(); for (A a : set.asSet()) { result.add(a, set.get(a)); } return result; } synchronized boolean isEmpty() { return map.isEmpty(); } synchronized public String toString() { // hmm. sync this? return str(map); } synchronized void clear() { map.clear(); } synchronized Map asMap() { return cloneMap(map); } } static B pairB(Pair p) { return p == null ? null : p.b; } static Set allInterfacesImplementedBy(Class c) { if (c == null) return null; HashSet set = new HashSet(); allInterfacesImplementedBy_find(c, set); return set; } static void allInterfacesImplementedBy_find(Class c, Set set) { if (c.isInterface() && !set.add(c)) return; do { for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set); } while ((c = c.getSuperclass()) != null); } static Method findMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args); } static boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static Method findStaticMethod(Class c, String method, Object... args) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args)) continue; return m; } c = c.getSuperclass(); } return null; } static boolean findStaticMethod_checkArgs(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) return false; return true; } static void addAllNonNulls(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) if (a != null) c.add(a); } static void addAllNonNulls(Collection c, B... b) { if (c != null && b != null) for (A a : b) if (a != null) c.add(a); } static int lengthLevel2_maps(Collection l) { int sum = 0; for (Map c : l) sum += l(c); return sum; } static int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } static void fixACCInClassLoader(Object o) { try { AccessControlContext acc = vm_globalACC(); if (acc != null) replaceACCInClassLoader(o, acc); } catch (Throwable __e) { _handleException(__e); } } static String systemHashCodeHex(Object o) { return intToHex(identityHashCode(o)); } static boolean stdEq2(Object a, Object b) { if (a == null) return b == null; if (b == null) return false; if (a.getClass() != b.getClass()) return false; for (String field : allFields(a)) if (neq(getOpt(a, field), getOpt(b, field))) return false; return true; } static int stdHash2(Object a) { if (a == null) return 0; return stdHash(a, toStringArray(allFields(a))); } static UnsupportedOperationException unsupportedOperation() { throw new UnsupportedOperationException(); } static LinkedHashMap cloneLinkedHashMap(Map map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } static long sysTime() { return sysNow(); } static void remove(List l, int i) { if (l != null && i >= 0 && i < l(l)) l.remove(i); } static void remove(Collection l, A a) { if (l != null) l.remove(a); } static Map mapValues(Object func, Map map) { Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(key, callF(func, map.get(key))); return m; } static Map mapValues(Map map, IF1 f) { return mapValues(f, map); } static Map mapValues(Map map, Object func) { return mapValues(func, map); } static Set keySet(Map map) { return map == null ? new HashSet() : map.keySet(); } static Set keySet(Object map) { return keys((Map) map); } static Set keySet(MultiSet ms) { return ms.keySet(); } static boolean hasLock(Lock lock) { return ((ReentrantLock) lock).isHeldByCurrentThread(); } static NavigableSet navigableKeys(NavigableMap map) { return map == null ? new TreeSet() : map.navigableKeySet(); } static NavigableSet navigableKeys(MultiSet ms) { return ((NavigableMap) ms.map).navigableKeySet(); } static Map cloneMap(Map map) { if (map == null) return new HashMap(); // assume mutex is equal to collection synchronized(map) { return map instanceof TreeMap ? new TreeMap((TreeMap) map) // copies comparator : map instanceof LinkedHashMap ? new LinkedHashMap(map) : new HashMap(map); } } static Method findMethod_cached(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { _MethodCache cache = callOpt_getCache(((Class) o)); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false)) return m; return null; } else { _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (findMethod_checkArgs(m, args, false)) return m; return null; } } catch (Exception __e) { throw rethrow(__e); } } static AccessControlContext vm_globalACC() { return (AccessControlContext) vm_generalMap_get("Global ACC"); } static void replaceACCInClassLoader(Object o, AccessControlContext newACC) { ClassLoader cl = getClassLoaderOrSame(o); if (cl instanceof URLClassLoader) { try { setOpt(cl, "acc" , newACC); try { setOpt((Object) getOpt(cl, "ucp"), "acc" , newACC); } catch (Throwable e) { printShortException("replaceACCInClassLoader: ", e); if (java10OrHigher()) if (addDefaultVMOption("--add-opens java.base/jdk.internal.loader=ALL-UNNAMED")) print("Please restart the OS"); } } catch (Throwable __e) { _handleException(__e); }} } static String intToHex(int i) { return bytesToHex(intToBytes(i)); } static Set allFields(Object o) { TreeSet fields = new TreeSet(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) fields.add(f.getName()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static int stdHash(Object a, String... fields) { if (a == null) return 0; int hash = getClassName(a).hashCode(); for (String field : fields) hash = boostHashCombine(hash, hashCode(getOpt(a, field))); return hash; } static Map similarEmptyMap(Map m) { if (m instanceof TreeMap) return new TreeMap(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashMap(); // default to a hash map return new HashMap(); } static ClassLoader getClassLoaderOrSame(Object o) { return o instanceof ClassLoader ? (ClassLoader) o : getClassLoader(o); } static void printShortException(Throwable e) { print(exceptionToStringShort(e)); } static void printShortException(String s, Throwable e) { print(s, exceptionToStringShort(e)); } static boolean java10OrHigher() { return parseFirstInt(javaVersion()) >= 10; } static boolean addDefaultVMOption(String option) { String s = defaultVMArgs(), old = s; if (!s.contains(option)) // rough s = trim(s + " " + option); if (eq(old, s)) return false; { setDefaultVMArgs(s); return true; } } static byte[] intToBytes(int i) { return new byte[] { (byte) (i >>> 24), (byte) (i >>> 16), (byte) (i >>> 8), (byte) i}; } static int boostHashCombine(int a, int b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } static ClassLoader getClassLoader(Object o) { return o == null ? null : _getClass(o).getClassLoader(); } static int parseFirstInt(String s) { return parseInt(jextract("", s)); } static String javaVersion() { return System.getProperty("java.version"); } static String defaultVMArgs() { return javaxDefaultVMArgs(); } static void setDefaultVMArgs(String args) { String oldArgs = javaxDefaultVMArgs(); args = trim(args); if (neq(unnull(oldArgs), unnull(args))) { print(); print("Changing default VM arguments from"); print(" " + oldArgs); print("to"); print(" " + args); print(); saveTextFile(javaxDataDir("default-vm-args"), nullIfEmpty(args)); } } // returns from C to C static String jextract(String pat, String s) { return jextract(pat, javaTok(s)); } static String jextract(String pat, List tok) { List tokpat = javaTok(pat); jfind_preprocess(tokpat); int i = jfind(tok, tokpat); if (i < 0) return null; int j = i + l(tokpat) - 2; return joinSubList(tok, i, j); } static String javaxDefaultVMArgs() { File fileNew, fileOld; String text = loadTextFile(fileNew = javaxDataDir("default-vm-args")); if (text == null) { text = loadTextFile(fileOld = programFile("#1005850", "default-vm-args")); if (text != null) moveFile(fileOld, fileNew); } return trim(unnull(text)); } static String nullIfEmpty(String s) { return isEmpty(s) ? null : s; } static Map nullIfEmpty(Map map) { return isEmpty(map) ? null : map; } static List nullIfEmpty(List l) { return isEmpty(l) ? null : l; } static File programFile(String name) { return prepareProgramFile(name); } static File programFile(String progID, String name) { return prepareProgramFile(progID, name); } static void moveFile(File a, File b) { if (!renameFile(a, b)) throw fail("File move failed: " + a + " to " + b); } static boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static boolean isEmpty(byte[] a) { return a == null || a.length == 0; } static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static File prepareProgramFile(String name) { return mkdirsForFile(getProgramFile(name)); } static File prepareProgramFile(String progID, String name) { return mkdirsForFile(getProgramFile(progID, name)); } static boolean renameFile(File a, File b) { mkdirsForFile(b); return a.renameTo(b); } static boolean renameFile(File a, String newName) { return renameFile(a, fileInSameDir(a, newName)); } }