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 static x30_pkg.x30_util.DynamicObject;
class main {
static void test_tok_multiTypeArguments() {
testTranspilationFunction(__14 -> tok_multiTypeArguments_v2(__14),
" sS loadTextFile(File/S file) { ... } ",
"\r\n sS loadTextFile(S file) { return loadTextFile(newFile(file)); }\r\n sS loadTextFile(File file) { ... }\r\n ",
" sS loadTextFile(File/S file, S def) { ... } ",
"\r\n sS loadTextFile(S file, S def) { return loadTextFile(newFile(file), def); }\r\n sS loadTextFile(File file, S def) { ... }\r\n ",
" sS loadTextFile(File/S file) { ... } ",
"\r\n sS loadTextFile(S file) { return loadTextFile(newFile(file)); }\r\n sS loadTextFile(File file) { ... }\r\n ",
" void bla(Graphics2D etc g, int x, int y) { yo; } ",
"\r\n void bla(BufferedImage g, int x, int y) { bla(graphics(g), x, y); }\r\n void bla(Graphics2D g, int x, int y) { yo; }\r\n ",
" void bla(Iterable or A[] l) { yo; } ",
"\r\n void bla(A[] l) { bla(asList(l)); }\r\n void bla(Iterable l) { yo; }\r\n ",
" void bla(Iterable or A... l) { yo; } ",
"\r\n void bla(A... l) { bla(asList(l)); }\r\n void bla(Iterable l) { yo; }\r\n ",
" void bla(Cl or O... l) { yo; } ",
"\r\n void bla(O... l) { bla(asList(l)); }\r\n void bla(Cl l) { yo; }\r\n ",
" void bla(Pt etc p) { yo; } ",
"\r\n void bla(int p_x, int p_y) { bla(pt(p_x, p_y)); }\r\n void bla(Pt p) { yo; }\r\n ");
}
static void testTranspilationFunction(IVF1> f, String in, String out, String... moreInOut) {
List tok = jtok(in);
makeVar_varCount.set(0);
f.get(tok);
assertJavaSourceEqualsVerbose(in, out, tok);
for (Pair p : unnullForIteration(paramsToPairs(moreInOut)))
testTranspilationFunction(f, p.a, p.b);
}
// just apply and return transpilation
static String testTranspilationFunction(IVF1> f, String s) {
return applyTranspilationFunction(f, s);
}
// example:
// sS loadTextFile(File/S file) { ... }
static void tok_multiTypeArguments_v2(List tok) {
int i;
// File/S
while ((i = jfind(tok, "File/ ", (_tok, nIdx) ->
eqGetOneOf(_tok, nIdx+5, "S", "String"))) >= 0) {
String argName = tok.get(i+6);
String mainType = tok.get(i), altType = tok.get(i+4);
String converter = "newFile";
String expr = converter + "(" + argName + ")";
tok_expandMultiTypeArgument(tok,
i, i+8,
argName,
mainType, altType, expr);
}
// Graphics2D etc, IIntegralImage etc, ...
while ((i = jfind(tok, " etc ")) >= 0) {
String mainType = tok.get(i);
String argName = tok.get(i+4);
int iArgEnd = i+6;
List> alts = new ArrayList(); // altType, converter
if (eq(mainType, "Graphics2D"))
alts.add(pair("BufferedImage", "graphics"));
else if (eq(mainType, "IIntegralImage")) {
alts.add(pair("BufferedImage", "IntegralImage"));
alts.add(pair("MakesBufferedImage", "IntegralImage"));
} else if (eq(mainType, "BufferedImage"))
alts.add(pair("MakesBufferedImage", "toBufferedImage"));
else if (eq(mainType, "Pt")) {
alts.add(pair(("int " + argName + "_x, int " + argName + "_y"),
("pt(" + argName + "_x, " + argName + "_y)")));
tok_expandMultiTypeArgument_v3(tok,
i, iArgEnd,
argName,
mainType, alts);
continue;
}
if (empty(alts))
throw fail("Unknown multi-type: " + joinSubList(tok, i, iArgEnd));
alts = mapPairB(alts, converter -> converter + "(" + argName + ")");
tok_expandMultiTypeArgument_v2(tok,
i, iArgEnd,
argName,
mainType, alts);
}
// Iterable or X[], Iterable<> or X...
IntRange r;
for (String modifier : ll("[]", "..."))
while ((r = jfind_range(tok, "Iterable<> or " + modifier + " ")) != null) {
i = r.start+1;
String mainType = joinSubList(tok, i, i+7);
String altType = joinSubList(tok, i+10, r.end-3);
String argName = tok.get(r.end-2);
String converter = "asList";
String expr = converter + "(" + argName + ")";
tok_expandMultiTypeArgument(tok, i, r.end, argName, mainType, altType, expr);
}
// Iterable or O[], Iterable or X..., Cl or O[] etc
for (String modifier : ll("[]", "..."))
while ((r = jfind_range(tok, " or O" + modifier + " ", new F2, Integer, Object>() { public Object get(List tok, Integer nIdx) { try { return eqOneOf(tok.get(nIdx+1), "Iterable", "Cl", "L"); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "eqOneOf(tok.get(nIdx+1), \"Iterable\", \"Cl\", \"L\")"; }})) != null) {
i = r.start+1;
String mainType = tok.get(i);
String altType = joinSubList(tok, i+4, r.end-3);
String argName = tok.get(r.end-2);
String converter = "asList";
String expr = converter + "(" + argName + ")";
tok_expandMultiTypeArgument(tok, i, r.end, argName, mainType, altType, expr);
}
}
static AtomicInteger makeVar_varCount = new AtomicInteger();
static String makeVar(String name) {
return "_" + name + "_" + getAndInc(makeVar_varCount);
}
static String makeVar() { return makeVar(""); }
static List jtok(String s) {
return javaTok(s);
}
static List jtok(List tok) {
return javaTok(tok);
}
static void assertJavaSourceEqualsVerbose(String src, List tok) { assertJavaSourceEqualsVerbose("", src, tok); }
static void assertJavaSourceEqualsVerbose(String msg, String src, List tok) {
// \n for better printing
assertEqualsVerboseUnder(msg, s ->
"\n" + join(tok_insertAFewSpaces(javaTok_simpleSpacesAndTrim(s))), src,
"\n" + join(tok));
}
static String unnullForIteration(String s) {
return s == null ? "" : s;
}
static Collection unnullForIteration(Collection l) {
return l == null ? immutableEmptyList() : l;
}
static List unnullForIteration(List l) { return l == null ? immutableEmptyList() : l; }
static int[] unnullForIteration(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnullForIteration(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnullForIteration(double[] l) { return l == null ? emptyDoubleArray() : l; }
static short[] unnullForIteration(short[] l) { return l == null ? emptyShortArray() : l; }
static Map unnullForIteration(Map l) {
return l == null ? immutableEmptyMap() : l;
}
static Iterable unnullForIteration(Iterable i) {
return i == null ? immutableEmptyList() : i;
}
static A[] unnullForIteration(A[] a) {
return a == null ? (A[]) emptyObjectArray() : a;
}
static BitSet unnullForIteration(BitSet b) {
return b == null ? new BitSet() : b;
}
//ifclass Symbol
static Symbol unnullForIteration(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnullForIteration(Pair p) {
return p != null ? p : new Pair(null, null);
}
static long unnullForIteration(Long l) { return l == null ? 0L : l; }
static List> paramsToPairs(A... params) {
if (l(params) == 1 && params[0] instanceof Map)
return mapToPairs((Map) params[0]);
List> l = emptyList(l(params)/2);
for (int i = 0; i+1 < l(params); i += 2)
l.add(pair(params[i], params[i+1]));
return l;
}
static String applyTranspilationFunction(IVF1> f, String s) {
if (f == null) return s;
List tok = javaTok(s);
f.get(tok);
return join(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, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); }
static int jfind(List tok, int startIndex, String in, ITokCondition condition) {
return jfind(tok, startIndex, in, toTokCondition(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;
}
static boolean eqGetOneOf(List l, int i, A... options) {
return eqOneOf(get(l, i), options);
}
// only one multi-type argument per declaration for now
// also allows only one combo right now (File/S with newFile)
// example:
// sS loadTextFile(File/S file) { ... }
static void tok_expandMultiTypeArgument(List tok,
int iArgStart, int iArgEnd, // start and end of argument
String argName, String mainType, String altType, String conversionExpr) {
iArgEnd |= 1;
int iOpening = lastIndexOf(tok, iArgStart, "("); // TODO: brackets
int iClosing = findEndOfBracketPart2(tok, iOpening)-1;
// function name
int iName = iOpening-2;
String name = assertIdentifier(get(tok, iName));
int iType = tok_leftScanType(tok, iName);
int iStart = tok_leftScanTypeArgsOpt(tok, iType);
iStart = leftScanModifiers(tok, iStart);
//print("Found method head: " + joinSubList(tok, iStart, iClosing+1));
List _args1 = subList(tok, iOpening+1, iArgStart);
List _args2 = subList(tok, iArgEnd&~1, iClosing);
List args1 = tok_parseArgsDeclList2(_args1);
List args2 = tok_parseArgsDeclList2(_args2);
List type = subList(tok, iType-1, iName);
boolean isVoid = containsOneOf(codeTokens(type), javaxVoidAliases());
//printVars(+expr, +_args1, +_args2, +args1, +args2, +type, +isVoid);
String altHead = joinSubList(tok, iStart, iOpening+1)
+ joinWithComma(concatLists(
args1,
ll(altType + " " + argName),
args2)) + ")";
replaceTokens_reTok(tok, iArgStart|1, iArgEnd, mainType + " " + argName);
tokPrepend_reTok(tok, iStart, altHead + " { "
+ (isVoid ? "" : "return ") + name + "(" +
joinWithComma(concatLists(
map(__15 -> tok_lastIdentifier(__15), args1),
ll(conversionExpr),
map(__16 -> tok_lastIdentifier(__16), args2))) + "); }\n");
}
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
// a little kludge for stuff like eq(symbol, "$X")
static boolean eq(Symbol a, String b) {
return eq(str(a), b);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static void tok_expandMultiTypeArgument_v3(List tok,
int iArgStart, int iArgEnd, // start and end of argument
String argName, String mainType, List> alts) {
iArgEnd |= 1;
int iOpening = lastIndexOf(tok, iArgStart, "("); // TODO: brackets
int iClosing = findEndOfBracketPart2(tok, iOpening)-1;
// function name
int iName = iOpening-2;
String name = assertIdentifier(get(tok, iName));
int iType = tok_leftScanType(tok, iName);
int iStart = tok_leftScanTypeArgsOpt(tok, iType);
iStart = leftScanModifiers(tok, iStart);
//print("Found method head: " + joinSubList(tok, iStart, iClosing+1));
List _args1 = subList(tok, iOpening+1, iArgStart);
List _args2 = subList(tok, iArgEnd&~1, iClosing);
List args1 = tok_parseArgsDeclList2(_args1);
List args2 = tok_parseArgsDeclList2(_args2);
List type = subList(tok, iType-1, iName);
boolean isVoid = containsOneOf(codeTokens(type), javaxVoidAliases());
//printVars(+expr, +_args1, +_args2, +args1, +args2, +type, +isVoid);
List altFunctions = new ArrayList();
for (Pair __0 : alts) { String altDecl = pairA(__0); String conversionExpr = pairB(__0);
String altHead = joinSubList(tok, iStart, iOpening+1)
+ joinWithComma(concatLists(
args1,
ll(altDecl),
args2)) + ")";
altFunctions.add(altHead + " { "
+ (isVoid ? "" : "return ") + name + "(" +
joinWithComma(concatLists(
map(__17 -> tok_lastIdentifier(__17), args1),
ll(conversionExpr),
map(__18 -> tok_lastIdentifier(__18), args2))) + "); }\n");
}
replaceTokens_reTok(tok, iArgStart|1, iArgEnd, mainType + " " + argName);
tokPrepend_reTok(tok, iStart, lines(altFunctions));
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
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(double[] a) { return a == null || a.length == 0; }
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(File f) { return getFileSize(f) == 0; }
static boolean empty(IntRange r) { return r == null || r.empty(); }
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(Object... objects) { throw new Fail(objects); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
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 List> mapPairB(final Object f, Iterable> l) {
return map(l, new F1, Pair>() { public Pair get(Pair p) { try {
return p == null ? null : pair(p.a, (C) callF(f, p.b));
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "p == null ? null : pair(p.a, (C) callF(f, p.b))"; }});
}
static List> mapPairB(final F1 f, Iterable> l) {
return mapPairB((Object) f, l);
}
static List> mapPairB(final IF1 f, Iterable> l) {
return mapPairB((Object) f, l);
}
static List> mapPairB(Iterable> l, IF1 f) {
return mapPairB((Object) f, l);
}
static Pair mapPairB(IF1 f, Pair p) {
return pairMapB(f, p);
}
static Pair mapPairB(Pair p, IF1 f) {
return pairMapB(f, p);
}
static void tok_expandMultiTypeArgument_v2(List tok,
int iArgStart, int iArgEnd, // start and end of argument
String argName, String mainType, List> alts) {
iArgEnd |= 1;
int iOpening = lastIndexOf(tok, iArgStart, "("); // TODO: brackets
int iClosing = findEndOfBracketPart2(tok, iOpening)-1;
// function name
int iName = iOpening-2;
String name = assertIdentifier(get(tok, iName));
int iType = tok_leftScanType(tok, iName);
int iStart = tok_leftScanTypeArgsOpt(tok, iType);
iStart = leftScanModifiers(tok, iStart);
//print("Found method head: " + joinSubList(tok, iStart, iClosing+1));
List _args1 = subList(tok, iOpening+1, iArgStart);
List _args2 = subList(tok, iArgEnd&~1, iClosing);
List args1 = tok_parseArgsDeclList2(_args1);
List args2 = tok_parseArgsDeclList2(_args2);
List type = subList(tok, iType-1, iName);
boolean isVoid = containsOneOf(codeTokens(type), javaxVoidAliases());
//printVars(+expr, +_args1, +_args2, +args1, +args2, +type, +isVoid);
List altFunctions = new ArrayList();
for (Pair __0 : alts) { String altType = pairA(__0); String conversionExpr = pairB(__0);
String altHead = joinSubList(tok, iStart, iOpening+1)
+ joinWithComma(concatLists(
args1,
ll(altType + " " + argName),
args2)) + ")";
altFunctions.add(altHead + " { "
+ (isVoid ? "" : "return ") + name + "(" +
joinWithComma(concatLists(
map(__19 -> tok_lastIdentifier(__19), args1),
ll(conversionExpr),
map(__20 -> tok_lastIdentifier(__20), args2))) + "); }\n");
}
replaceTokens_reTok(tok, iArgStart|1, iArgEnd, mainType + " " + argName);
tokPrepend_reTok(tok, iStart, lines(altFunctions));
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static TokenRange jfind_range(List tok, String in) {
return jfind_range(tok, 1, in);
}
static TokenRange jfind_range(List tok, int startIdx, String in) {
return jfind_range(tok, startIdx, in, null);
}
static TokenRange jfind_range(List tok, String in, Object condition) {
return jfind_range(tok, 1, in, condition);
}
static TokenRange jfind_range(List tok, int startIdx, String in, Object condition) {
return jfind_range(tok, startIdx, javaTokForJFind_array(in), condition);
}
// assumes you preprocessed tokin
static TokenRange jfind_range(List tok, List tokin) {
return jfind_range(tok, 1, tokin);
}
static TokenRange jfind_range(List tok, int startIdx, List tokin) {
return jfind_range(tok, startIdx, tokin, null);
}
static TokenRange jfind_range(List tok, int startIdx, List tokin, Object condition) {
return jfind_range(tok, startIdx, codeTokensAsStringArray(tokin), condition);
}
static TokenRange jfind_range(List tok, int startIdx, String[] tokinC, Object condition) {
int i = findCodeTokens(tok, startIdx, false, tokinC, condition);
return i < 0 ? null : new TokenRange(i-1, i+l(tokinC)*2);
}
static boolean eqOneOf(Object o, Object... l) {
for (Object x : l) if (eq(o, x)) return true; return false;
}
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 int getAndInc(AtomicInteger i) {
return i.getAndIncrement();
}
// 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;
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 && !regionMatches(s, j, "*/"));
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));
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 < l && !regionMatches(s, j, "]]"));
j = Math.min(j+2, l);
} else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') {
do ++j; while (j+2 < l && !regionMatches(s, j, "]=]"));
j = Math.min(j+3, l);
} else
++j;
tok.add(javaTok_substringC(s, i, j));
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 A assertEqualsVerboseUnder(IF1 f, A a, A b) { return assertEqualsVerboseUnder(null, f, a, b); }
static A assertEqualsVerboseUnder(String msg, IF1 f, A a, A b) {
if (f == null)
assertEqualsVerbose(msg, a, b);
else
assertEqualsVerbose(msg, f.get(a), f.get(b));
return b;
}
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 String tok_insertAFewSpaces(String s) {
return join(tok_insertAFewSpaces(javaTok(s)));
}
static List tok_insertAFewSpaces(List tok) {
int n = l(tok);
for (int i = 1; i+2 < n; i += 2) {
if (eqGet(tok, i+1, "")) {
String me = get(tok, i), next = get(tok, i+2);
if (eq(me, "}") && isIdentifier(next))
tok.set(i+1, " ");
}
}
return tok;
}
static List javaTok_simpleSpacesAndTrim(String s) {
return simpleSpacesAndTrim(javaTok(s));
}
static List immutableEmptyList() {
return Collections.emptyList();
}
static int[] emptyIntArray_a = new int[0];
static int[] emptyIntArray() { return emptyIntArray_a; }
static char[] emptyCharArray = new char[0];
static char[] emptyCharArray() { return emptyCharArray; }
static double[] emptyDoubleArray = new double[0];
static double[] emptyDoubleArray() { return emptyDoubleArray; }
static short[] emptyShortArray = new short[0];
static short[] emptyShortArray() { return emptyShortArray; }
static Map immutableEmptyMap() {
return Collections.emptyMap();
}
static Object[] emptyObjectArray_a = new Object[0];
static Object[] emptyObjectArray() { return emptyObjectArray_a; }
static Symbol emptySymbol_value;
static Symbol emptySymbol() {
if (emptySymbol_value == null) emptySymbol_value = symbol("");
return emptySymbol_value;
}
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(IntRange r) { return r == null ? 0 : r.length(); }
static List> mapToPairs(Map map) {
List> l = emptyList(l(map));
if (map != null) for (Map.Entry e : map.entrySet())
l.add(pair(e.getKey(), e.getValue()));
return l;
}
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 TokCondition toTokCondition(ITokCondition condition) {
return condition == null ? null : new TokCondition() {
boolean get(List tok, int i) {
return condition.get(tok, i);
}
};
}
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;
}
// Note: In the transpiler, this version is used: #1025802
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;
if (i >= end) return -1;
// bail out early if first token not found (works great with IndexedList)
String firstToken = tokens[0];
if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) {
// 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 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 ArrayList litlist(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
// syntax 1: replace all occurrences of x in l with y
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;
replaceSublist(l, i, i+l(x), y);
i += l(y);
}
return l;
}
// syntax 2: splice l at fromIndex-toIndex and replace middle part with y
static List replaceSublist(List l, int fromIndex, int toIndex, List y) {
int n = y.size(), toIndex_new = fromIndex+n;
if (toIndex_new < toIndex) {
removeSubList(l, toIndex_new, toIndex);
copyListPart(y, 0, l, fromIndex, n);
} else {
copyListPart(y, 0, l, fromIndex, toIndex-fromIndex);
if (toIndex_new > toIndex)
l.addAll(toIndex, subList(y, toIndex-fromIndex));
}
return l;
}
static List replaceSublist(List l, IntRange r, List y) {
return replaceSublist(l, r.start, r.end, y);
}
// 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 getOptDynOnly(((DynamicObject) o), 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 boolean get(BitSet bs, int idx) {
return bs != null && bs.get(idx);
}
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);
}
// starts searching from i-1
static int lastIndexOf(List l, int i, A a) {
if (l == null) return -1;
for (i = min(l(l), i)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
static int lastIndexOf(List l, A a) {
if (l == null) return -1;
for (int i = l(l)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
// i must point at the (possibly imaginary) opening bracket (any of the 3 types, not type parameters)
// index returned is index of closing bracket + 1
static int findEndOfBracketPart2(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 String assertIdentifier(String s) {
return assertIsIdentifier(s);
}
static String assertIdentifier(String msg, String s) {
return assertIsIdentifier(msg, s);
}
// i = C token to the right of type
static int tok_leftScanType(List tok, int i) {
// first skip ellipsis
if (subListEq(tok, i-6, ".", "", ".", "", "."))
i -= 6;
// skip array brackets
while (eqGet(tok, i-2, "]") && eqGet(tok, i-4, "["))
i -= 4;
i = tok_leftScanTypeArgsOpt(tok, i);
do {
if (!isIdentifier(get(tok, i-2))) return i; // weird
i = tok_leftScanType(tok, i-2); // Is this really supposed to be recursive??
} while (eqGet(tok, i-2, "."));
return i;
}
// returns index of opening <
static int tok_leftScanTypeArgsOpt(List tok, int i) {
if (!eqGet(tok, i-2, ">")) return i;
int level = 0;
while (i > 1) {
String t = tok.get(i-2);
if (eq(t, ">")) level++;
else if (eq(t, "<")) {
level--;
if (level == 0) return i-2;
}
i -= 2;
}
return i;
}
static int leftScanModifiers(List tok, int i) {
List mod = getJavaModifiers();
while (i > 1 && mod.contains(tok.get(i-2)))
i -= 2;
return i;
}
static List subList(List l, int startIndex) {
return subList(l, startIndex, l(l));
}
static List subList(int startIndex, List l) {
return subList(l, startIndex);
}
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 List tok_parseArgsDeclList2(List tok) {
return tok_parseArgsDeclList2(tok, getBracketMapIncludingAngleBrackets(tok));
}
static List tok_parseArgsDeclList2(List tok, Map bracketMap) {
int argStart = 1;
if (eqGet(tok, argStart, ",")) argStart += 2;
int i = argStart;
List args = new ArrayList();
while (i < l(tok) && 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;
}
// unclear semantics when l is a special set (e.g. ciSet)
static boolean containsOneOf(Collection l, A... x) {
if (l instanceof Set) {
if (x != null)
for (A a : x)
if (l.contains(a))
return true;
} else {
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 List codeTokens(List tok) {
return codeTokensOnly(tok);
}
static Set javaxVoidAliases_cache;
static Set javaxVoidAliases() { if (javaxVoidAliases_cache == null) javaxVoidAliases_cache = javaxVoidAliases_load(); return javaxVoidAliases_cache; }
static Set javaxVoidAliases_load() {
return litset("void", "svoid");
}
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 concatLists(Iterable... lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static List concatLists(Collection extends Iterable> lists) {
List l = new ArrayList();
if (lists != null) for (Iterable list : lists)
addAll(l, list);
return l;
}
static void replaceTokens_reTok(List tok, int i, int j, String s) {
replaceTokens(tok, i, j, s);
reTok(tok, i, j);
}
static void tokPrepend_reTok(List tok, int i, String s) {
tokPrepend(tok, i, s);
reTok(tok, i, i+1);
}
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)
{ ping(); 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)
{ ping(); 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)
{ ping(); 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)
{ ping(); 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()) { ping();
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);
}
// new magic alias for mapLL - does it conflict?
static List map(IF1 f, A data1, A... moreData) {
List x = emptyList(l(moreData)+1);
x.add(f.get(data1));
if (moreData != null) for (A o : moreData)
{ ping(); x.add(f.get(o)); }
return x;
}
static String tok_lastIdentifier(String s) {
return lastIdentifier(javaTokC(s));
}
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static A pairA(Pair p) {
return p == null ? null : p.a;
}
static B pairB(Pair p) {
return p == null ? null : p.b;
}
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); }
// convenience map call
static String lines(Iterable l, IF1 f) {
return mapToLines(l, f);
}
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 RuntimeException asRuntimeException(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
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(Runnable r) { { if (r != null) r.run(); } return null; }
static Object callF(Object f, Object... args) {
if (f instanceof String)
return callMCWithVarArgs((String) f, args); // possible SLOWDOWN over callMC
return safeCallF(f, args);
}
static Object safeCallF(Object f, Object... 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));
}
// 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 Pair pairMapB(Object f, Pair p) {
return p == null ? null : pair(p.a, callF(f, p.b));
}
static Pair pairMapB(IF1 f, Pair p) {
return p == null ? null : pair(p.a, f.get(p.b));
}
static Pair pairMapB(Pair p, Object f) {
return pairMap(f, p);
}
static void _handleError(Error e) {
call(javax(), "_handleError", e);
}
static boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) {
return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len);
}
static boolean regionMatches(String a, int offsetA, String b) {
return regionMatches(a, offsetA, b, 0, l(b));
}
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 A assertEqualsVerbose(Object x, A y) {
assertEqualsVerbose((String) null, x, y);
return y;
}
// x = expected, y = actual
static A assertEqualsVerbose(String msg, Object x, A y) {
if (!eq(x, y)) {
throw fail((nempty(msg) ? msg + ": " : "") + "expected: "+ x + ", got: " + y);
} else
print("OK" + (empty(msg) ? "" : " " + msg) + ": " + /*sfu*/(x));
return y;
}
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 Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static A first(A[] l, IF1 pred) {
return firstThat(l, pred);
}
static A first(Iterable l, IF1 pred) {
return firstThat(l, pred);
}
static A first(IF1 pred, Iterable l) {
return firstThat(pred, l);
}
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);
}
static boolean isIdentifier(String s) {
return isJavaIdentifier(s);
}
// Convert all spacing to a single space, so everything's neat & on one line.
static List simpleSpacesAndTrim(List tok) {
tok = cloneList(tok);
int n = l(tok);
for (int i = 0; i < n; i += 2)
tok.set(i, i == 0 || i == n-1 || empty(tok.get(i)) ? "" : " ");
return tok;
}
static String simpleSpacesAndTrim(String s) {
return join(simpleSpacesAndTrim(nlTok(s)));
}
static WeakHasherMap symbol_map = new WeakHasherMap(new Hasher() {
public int hashCode(Symbol symbol) { return symbol.text.hashCode(); }
public boolean equals(Symbol a, Symbol b) {
if (a == null) return b == null;
return b != null && eq(a.text, b.text);
}
});
static Symbol symbol(String s) {
if (s == null) return null;
synchronized(symbol_map) {
// TODO: avoid object creation by passing the string to findKey
Symbol symbol = new Symbol(s, true);
Symbol existingSymbol = symbol_map.findKey(symbol);
if (existingSymbol == null)
symbol_map.put(existingSymbol = symbol, true);
return existingSymbol;
}
}
static Symbol symbol(CharSequence s) {
if (s == null) return null;
if (s instanceof Symbol) return (Symbol) s;
if (s instanceof String) return symbol((String) s);
return symbol(str(s));
}
static Symbol symbol(Object o) {
return symbol((CharSequence) o);
}
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); } }
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 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 Map synchronizedMRUCache(int maxSize) {
return synchroMap(new MRUCache(maxSize));
}
static HashSet lithashset(A... items) {
HashSet set = new HashSet();
for (A a : items) set.add(a);
return set;
}
// supports the usual quotings (", variable length double brackets) except ' quoting
static boolean isQuoted(String s) {
if (isNormalQuoted(s)) return true; // use the exact version
return isMultilineQuoted(s);
}
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 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(Symbol a, Symbol b) {
return eq(a, b);
}
static boolean eqic(Symbol a, String b) {
return eqic(asString(a), 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 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 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 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 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 Object getOptDynOnly(DynamicObject o, String field) {
if (o == null || o.fieldValues == null) return null;
return o.fieldValues.get(field);
}
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 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 boolean subListEq(List l, List pat, int i) {
return subListEquals(l, pat, i);
}
static boolean subListEq(List l, int i, A... pat) {
return subListEquals(l, i, pat);
}
static List getJavaModifiers_list = litlist("static", "abstract", "public", "private", "protected", "final", "native", "volatile", "synchronized", "transient");
static List getJavaModifiers() {
return getJavaModifiers_list;
}
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 boolean neq(Object a, Object b) {
return !eq(a, b);
}
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)));
}
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 int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; }
static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; }
static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : 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[]) emptyObjectArray() : a;
}
static BitSet unnull(BitSet b) {
return b == null ? new BitSet() : b;
}
//ifclass Symbol
static Symbol unnull(Symbol s) {
return s == null ? emptySymbol() : s;
}
//endif
static Pair unnull(Pair p) {
return p != null ? p : new Pair(null, null);
}
static int unnull(Integer i) { return i == null ? 0 : i; }
static long unnull(Long l) { return l == null ? 0L : l; }
static double unnull(Double l) { return l == null ? 0.0 : 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 List codeTokensOnly(List tok) {
int n = l(tok);
List l = emptyList(n/2);
for (int i = 1; i < n; i += 2)
l.add(tok.get(i));
return l;
}
static HashSet litset(A... items) {
return lithashset(items);
}
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 && b != null && c.addAll(Arrays.asList(b));
}
static Map addAll(Map a, Map extends A,? extends B> b) {
if (a != null && b != null) a.putAll(b);
return a;
}
static void replaceTokens(List tok, IntRange r, String s) {
replaceTokens(tok, r.start, r.end, s);
}
static void replaceTokens(List tok, int i, int j, String s) {
clearAllTokens(tok, i+1, j);
tok.set(i, s);
}
static void replaceTokens(List tok, String s) {
clearAllTokens(tok, 1, l(tok));
tok.set(0, s);
}
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 void tokPrepend(List tok, String s) { tokPrepend(tok, 0, s); }
static void tokPrepend(List tok, int i, String s) {
tok.set(i, s + tok.get(i));
}
//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() {
//ifdef useNewPing
newPing();
//endifdef
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); } }
// unclear semantics as to whether return null on null
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(long[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (long 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(double[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static ArrayList asList(Iterator it) {
ArrayList l = new ArrayList();
if (it != null)
while (it.hasNext())
l.add(it.next());
return l;
}
// disambiguation
static ArrayList asList(IterableIterator s) {
return asList((Iterator) s);
}
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(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
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 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;
}
// 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) {
int n = s.length();
for (int i = start; i < n; i++) {
char c = s.charAt(i);
if (c == '\r' || c == '\n')
return i;
}
return -1;
}
static List mapToLines(Map map) {
List l = new ArrayList();
for (Object key : keys(map))
l.add(str(key) + " = " + str(map.get(key)));
return l;
}
static String mapToLines(Map map, Object f) {
return lines(map(map, f));
}
static String mapToLines(Object f, Map map) {
return lines(map(map, f));
}
static String mapToLines(Object f, Iterable l) {
return lines(map(f, l));
}
static String mapToLines(Iterable l, IF1 f) {
return mapToLines((Object) f, l);
}
static String mapToLines(IF1 f, Iterable l) {
return mapToLines((Object) f, l);
}
static String mapToLines(Map map, IF2 f) {
return lines(map(map, f));
}
static String mapToLines(IF1 f, A data1, A... moreData) {
return lines(map(f, data1, moreData));
}
static String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
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 Object callMCWithVarArgs(String method, Object... args) {
return call_withVarargs(mc(), method, args);
}
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 Pair pairMap(Object f, Pair p) {
return p == null ? null : pair(callF(f, p.a), callF(f, p.b));
}
static Pair pairMap(IF1 f, Pair p) {
return p == null ? null : pair(callF(f, p.a), callF(f, p.b));
}
static Pair pairMap(Pair p, Object f) {
return pairMap(f, p);
}
static Class javax() {
return getJavaX();
}
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 boolean nempty(IntRange r) { return !empty(r); }
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