Warning : session_start(): open(/var/lib/php/sessions/sess_umjqep7btrlog59fs1odp9k4eu, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning : session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
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 java.util.function.*;
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 java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import static x30_pkg.x30_util.DynamicObject;
import java.util.jar.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.Timer;
import java.text.*;
import java.awt.geom.*;
import java.text.NumberFormat;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.awt.datatransfer.StringSelection;
import javax.swing.undo.UndoManager;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.nio.charset.Charset;
import javax.swing.Icon;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.nio.file.Path;
class main {
public static void main(final String[] args) throws Exception {
test_leftArrowScript_forEach();
}
static void test_leftArrowScript_forEach() {
String script = trimAllLines(
" l <- ll 2 3\r\n sum <- 0\r\n for number in l { sum <- plus sum number }\r\n sum\r\n ");
assertEqualsVerbose(5, leftArrowVerbose((String) script));
}
static BigInteger plus(BigInteger a, BigInteger b) {
return a.add(b);
}
static BigInteger plus(BigInteger a, long b) {
return a.add(bigint(b));
}
static long plus(long a, long b) { return a+b; }
static int plus(int a, int b) { return a+b; }
static float plus(float a, float b) { return a+b; }
static double plus(double a, double b) { return a+b; }
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static String trimAllLines(String s) {
return lines(trimAll(lines(s)));
}
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 leftArrowVerbose(String script) {
GazelleV_LeftArrowScriptParser parser = new GazelleV_LeftArrowScriptParser();
parser.allowTheWorld();
var parsedScript = parser.parse(script);
parser.printFunctionDefs();
print(parsedScript);
return parsedScript.get();
}
static BigInteger bigint(String s) {
return new BigInteger(s);
}
static BigInteger bigint(long l) {
return BigInteger.valueOf(l);
}
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 List trimAll(String... l) {
return trimAll(asList(l));
}
static List trimAll(Collection l) {
List l2 = new ArrayList();
if (l != null) for (String s : l)
l2.add(trim(s));
return l2;
}
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 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 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(BitSet bs) { return !empty(bs); }
static boolean nempty(Map m) {
return !empty(m);
}
static boolean nempty(Iterator i) {
return i != null && i.hasNext();
}
static boolean nempty(MultiMap mm) { return mm != null && !mm.isEmpty(); }
static boolean nempty(Object o) { return !empty(o); }
static boolean nempty(Rect r) { return r != null && r.w != 0 && r.h != 0; }
static boolean nempty(MultiSet ms) { return ms != null && !ms.isEmpty(); }
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
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(combinePrintParameters(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 = o + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
print_raw(s);
}
static void print_raw(String 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);
if (printAlsoToSystemOut)
System.out.print(s);
vmBus_send("printed", mc(), s);
}
static void print_autoRotate() {
}
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(BitSet bs) { return bs == null || bs.isEmpty(); }
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(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(Rect r) { return !(r != null && r.w != 0 && r.h != 0); }
static boolean empty(Chain c) { return c == null; }
static boolean empty(AppendableChain c) { return c == null; }
static String appendColonIfNempty(String s) {
return empty(s) ? "" : s + ": ";
}
static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) {
return print_byThread().get() == null ? tempInterceptPrint(f) : null;
}
// 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));
}
// 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(short[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (short 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(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 ArrayList asList(ReverseChain c) {
return c == null ? emptyList() : c.toList();
}
static List asList(Pair p) {
return p == null ? null : ll(p.a, p.b);
}
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 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 String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static RuntimeException asRuntimeException(Throwable t) {
return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static String combinePrintParameters(String s, Object o) {
return (endsWithLetterOrDigit(s) ? s + ": " : s) + o;
}
static void ping_okInCleanUp() {
}
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 void vmBus_send(String msg, Object... args) {
Object arg = vmBus_wrapArgs(args);
pcallFAll_minimalExceptionHandling(vm_busListeners_live(), msg, arg);
pcallFAll_minimalExceptionHandling(vm_busListenersByMessage_live().get(msg), msg, arg);
}
static void vmBus_send(String msg) {
vmBus_send(msg, (Object) null);
}
static Class mc() {
return main.class;
}
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 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 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 CloseableIterableIterator linesFromFile(File f) { return linesFromFile(f, null); }
static CloseableIterableIterator linesFromFile(File f, IResourceHolder resourceHolder) { try {
if (!f.exists()) return emptyCloseableIterableIterator();
if (ewic(f.getName(), ".gz"))
return linesFromReader(utf8bufferedReader(newGZIPInputStream(f)), resourceHolder);
return linesFromReader(utf8bufferedReader(f), resourceHolder);
} catch (Exception __e) { throw rethrow(__e); } }
static CloseableIterableIterator linesFromFile(String path) { return linesFromFile(path, null); }
static CloseableIterableIterator linesFromFile(String path, IResourceHolder resourceHolder) {
return linesFromFile(newFile(path), resourceHolder);
}
static Set keys(Map map) {
return map == null ? new HashSet() : map.keySet();
}
// convenience shortcut for keys_gen
static Set keys(Object map) {
return keys((Map) map);
}
static Set keys(MultiSet ms) {
return ms.keySet();
}
static Set keys(MultiMap mm) {
return mm.keySet();
}
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 boolean endsWithLetterOrDigit(String s) {
return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length()-1));
}
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 RuntimeException rethrow(Throwable t) {
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static Object vmBus_wrapArgs(Object... args) {
return empty(args) ? null
: l(args) == 1 ? args[0]
: args;
}
static void pcallFAll_minimalExceptionHandling(Collection l, Object... args) {
if (l != null) for (Object f : cloneList(l)) { ping(); pcallF_minimalExceptionHandling(f, args); }
}
static void pcallFAll_minimalExceptionHandling(Iterator it, Object... args) {
while (it.hasNext()) { ping(); pcallF_minimalExceptionHandling(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 String getClassName(Object o) {
return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
}
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 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 > A max(A a, A b) {
return cmp(a, b) >= 0 ? a : b;
}
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(AppendableChain a) { return a == null ? 0 : a.size; }
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) { return linesFromReader(r, null); }
static CloseableIterableIterator linesFromReader(Reader r, IResourceHolder resourceHolder) {
final BufferedReader br = bufferedReader(r);
return holdResource(resourceHolder, iteratorFromFunction_f0_autoCloseable(new F0() { public String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "return readLineFromReaderWithClose(br);"; }}, _wrapIOCloseable(r)));
}
static BufferedReader utf8bufferedReader(InputStream in) { try {
return in == null ? null : 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 GZIPInputStream newGZIPInputStream(File f) {
return gzInputStream(f);
}
static GZIPInputStream newGZIPInputStream(InputStream in) {
return gzInputStream(in);
}
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 boolean ping() { return ping(pingSource()); }
static boolean ping(PingSource source) {
ping_v3(source);
return true;
}
// don't think this is of any use anymore
static boolean ping_impl(boolean okInCleanUp) { return ping(); }
//sbool ping_okInCleanUp() { ret ping(); }
// phase this out too!
static volatile boolean ping_pauseAll = false;
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 B callF(A a, IF1 f) {
return f == null ? null : f.get(a);
}
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 void callF(A a, IVF1 f) {
if (f != null) f.get(a);
}
static void callF(IVF1 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) {
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) {
if (f instanceof String)
throw fail("Legacy call: " + f);
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 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 Object pcallF_minimalExceptionHandling(Object f, Object... args) {
try {
return callFunction(f, args);
} catch (Throwable e) {
System.out.println(getStackTrace(e));
_storeException(e);
}
return null;
}
static Set vm_generalIdentityHashSet(Object name) {
synchronized(vm_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(vm_generalMap()) {
Map m = (Map) (vm_generalMap_get(name));
if (m == null)
vm_generalMap_put(name, m = syncHashMap());
return m;
}
}
static A setThreadLocal(ThreadLocal tl, A value) {
if (tl == null) return null;
A old = tl.get();
tl.set(value);
return old;
}
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(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(long a, long 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 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 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;
if (m != null)
m.m = new String[] { substring(a, 0, l(a)-l(b)) };
return true;
}
static BufferedReader bufferedReader(Reader r) { return bufferedReader(r, 8192); }
static BufferedReader bufferedReader(Reader r, int bufSize) {
if (r == null) return null;
return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r, bufSize), r);
}
static A holdResource(IResourceHolder holder, A a) {
{ if (holder != null) holder.add(a); }
return a;
}
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 A _registerIOWrap(A wrapper, Object wrapped) {
return wrapper;
}
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;
}
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); } }
// assumptions:
// -pingSource() stays constant within a stack frame (so you can cache it)
// -all changes happen with tempSetPingSource
// -multiple threads can share a PingSource
static PingSource pingSource() {
return pingSource_tl().get();
}
static PingSource pingSource(Thread thread) {
return pingSource_tl().get(thread);
}
// always returns true for convenience
static boolean ping_v3() { return ping_v3(pingSource()); }
static boolean ping_v3(PingSource source) {
{ if (source != null) source.get(); }
return true;
}
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 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 Field makeAccessible(Field f) {
try {
f.setAccessible(true);
} catch (Throwable e) {
// Note: The error reporting only works with Java VM option --illegal-access=deny
}
return f;
}
static Method makeAccessible(Method m) {
try {
m.setAccessible(true);
} catch (Throwable e) {
}
return m;
}
static Constructor makeAccessible(Constructor c) {
try {
c.setAccessible(true);
} catch (Throwable e) {
}
return c;
}
// TODO: JDK 17!! ?? No! Yes? Yes!!
static Object collectionMutex(List l) {
return l;
}
static Object collectionMutex(Object o) {
if (o instanceof List) return o;
// TODO: actually use our own maps so we can get the mutex properly
String c = className(o);
return o;
}
static Object callFunction(Object f, Object... args) {
return callF(f, args);
}
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 String getStackTrace(String msg) {
return getStackTrace_noRecord(new Throwable(msg));
}
static Throwable _storeException_value;
static void _storeException(Throwable e) {
_storeException_value = e;
}
static Map vm_generalMap_map;
static Map vm_generalMap() {
if (vm_generalMap_map == null)
vm_generalMap_map = synchroHashMap();
return vm_generalMap_map;
}
static Object vm_generalMap_get(Object key) {
return vm_generalMap().get(key);
}
static Object vm_generalMap_put(Object key, Object value) {
return mapPutOrRemove(vm_generalMap(), key, value);
}
static Set syncIdentityHashSet() {
return (Set) synchronizedSet(identityHashSet());
}
static Map syncHashMap() {
return synchroHashMap();
}
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");
}
} catch (Exception __e) { throw rethrow(__e); } }
static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) {
return a != null && a.regionMatches(true, offsetA, b, offsetB, len);
}
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;
int n = s.length();
if (y < x) y = x;
if (y > n) y = n;
if (x >= y) return "";
return s.substring(x, y);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
static void _registerIO(Object object, String path, boolean opened) {
}
static BetterThreadLocal pingSource_tl_var = new BetterThreadLocal() {
@Override
public PingSource initialValue() {
return ping_v3_pingSourceMaker().get();
}
};
static BetterThreadLocal pingSource_tl() {
return pingSource_tl_var;
}
static List _registerDangerousWeakMap_preList;
static A _registerDangerousWeakMap(A map) {
return _registerDangerousWeakMap(map, null);
}
static A _registerDangerousWeakMap(A map, Object init) {
return map;
}
static void _onLoad_registerDangerousWeakMap() {
}
static Map synchroMap() {
return synchroHashMap();
}
static Map synchroMap(Map map) {
return Collections.synchronizedMap(map);
}
static Throwable getExceptionCause(Throwable e) {
Throwable c = e.getCause();
return c != null ? c : e;
}
static String joinWithSpace(Iterable c) {
return join(" ", c);
}
static String joinWithSpace(String... c) {
return join(" ", c);
}
static List classNames(Collection l) {
return getClassNames(l);
}
static List classNames(Object[] l) {
return getClassNames(Arrays.asList(l));
}
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 className(Object o) {
return getClassName(o);
}
// 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 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|cookie)=[^&\\s\"]*", "$1$2=");
}
static String hideCredentials(Object o) {
return hideCredentials(str(o));
}
static Map synchroHashMap() {
return synchronizedMap(new HashMap());
}
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 Set synchronizedSet() {
return synchroHashSet();
}
static Set synchronizedSet(Set set) {
return Collections.synchronizedSet(set);
}
static Set identityHashSet() {
return Collections.newSetFromMap(new IdentityHashMap());
}
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); } }
// no longer synchronizes! (see #1102990)
static _MethodCache callOpt_getCache(Class c) {
_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 String joinWithComma(Collection c) {
return join(", ", c);
}
static String joinWithComma(Object... 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 int strL(String s) {
return s == null ? 0 : s.length();
}
static int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static IF0 ping_v3_pingSourceMaker_cache;
static IF0 ping_v3_pingSourceMaker() { if (ping_v3_pingSourceMaker_cache == null) ping_v3_pingSourceMaker_cache = ping_v3_pingSourceMaker_load(); return ping_v3_pingSourceMaker_cache; }
static IF0 ping_v3_pingSourceMaker_load() {
return or((IF0) vm_generalMap_get("ping_v3_pingSourceMaker"), () -> null);
}
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));
}
public static String join(String glue, Object... 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 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 PersistableThrowable persistableThrowable(Throwable e) {
return e == null ? null : new PersistableThrowable(e);
}
static boolean startsWithOneOf(String s, String... l) {
for (String x : l) if (startsWith(s, x)) return true; return false;
}
static boolean startsWithOneOf(String s, Matches m, String... l) {
for (String x : l) if (startsWith(s, x, m)) return true; return false;
}
static boolean isAGIBlueDomain(String domain) {
return domainIsUnder(domain, theAGIBlueDomain());
}
static String hostNameFromURL(String url) { try {
return empty(url) ? null : new URL(url).getHost();
} catch (Exception __e) { throw rethrow(__e); } }
static Map synchronizedMap() {
return synchroMap();
}
static Map synchronizedMap(Map map) {
return synchroMap(map);
}
static Set synchroHashSet() {
return synchronizedSet(new HashSet ());
}
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, Math.min(a.length, b.length));
}
static void arraycopy(Object src, int srcPos, int destPos, int n) { arraycopy(src, srcPos, src, destPos, n); }
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 A or(A a, A b) {
return a != null ? a : b;
}
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 Pair first(Map map) {
return mapEntryToPair(first(entrySet(map)));
}
static Pair first(MultiMap mm) {
if (mm == null) return null;
var e = first(mm.data.entrySet());
if (e == null) return null;
return pair(e.getKey(), first(e.getValue()));
}
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 A first(T3 t) {
return t == null ? null : t.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 A first(AppendableChain a) {
return a == null ? null : a.element;
}
static boolean startsWith(String a, String b) {
return a != null && a.startsWith(unnull(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;
if (m != null) 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 domainIsUnder(String domain, String mainDomain) {
return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain);
}
static String theAGIBlueDomain() {
return "agi.blue";
}
static A[] makeArray(Class type, int n) {
return (A[]) Array.newInstance(type, n);
}
static Pair mapEntryToPair(Map.Entry e) {
return e == null ? null : pair(e.getKey(), e.getValue());
}
static Set> entrySet(Map map) {
return _entrySet(map);
}
static Pair pair(A a, B b) {
return new Pair(a, b);
}
static Pair pair(A a) {
return new Pair(a, a);
}
static A firstThat(Iterable l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(A[] l, IF1 pred) {
for (A a : unnullForIteration(l))
if (pred.get(a))
return a;
return null;
}
static A firstThat(IF1 pred, Iterable l) {
return firstThat(l, pred);
}
static A firstThat(IF1 pred, A[] l) {
return firstThat(l, pred);
}
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;
}
static Pt unnull(Pt p) {
return p == null ? new Pt() : p;
}
//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 nemptyString(String s) {
return s != null && s.length() > 0;
}
static int listL(Collection l) {
return l == null ? 0 : l.size();
}
static boolean neq(Object a, Object b) {
return !eq(a, b);
}
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 Set> _entrySet(Map map) {
return map == null ? Collections.EMPTY_SET : map.entrySet();
}
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;
}
static Pt unnullForIteration(Pt p) {
return p == null ? new Pt() : p;
}
//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 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 Map emptyMap() {
return new HashMap();
}
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 String asString(Object o) {
return o == null ? null : o.toString();
}
static List immutableEmptyList() {
return Collections.emptyList();
}
static short[] emptyShortArray = new short[0];
static short[] emptyShortArray() { return emptyShortArray; }
static Map immutableEmptyMap() {
return Collections.emptyMap();
}
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 interface IResourceHolder {
A add(A a);
Collection takeAll();
}
// immutable, has strong refs
// Do not run in a synchronized block - it goes wrong in the presence
// of elaborate classloaders (like in Gazelle BEA)
// see #1102990 and #1102991
final static class _MethodCache {
final Class c;
final HashMap> cache = new HashMap();
_MethodCache(Class c) {
this.c = c; _init(); }
void _init() {
Class _c = c;
Module myModule = getClass().getModule();
boolean anyHiddenClasses = false;
while (_c != null) {
boolean exported = classIsExportedTo(_c, myModule);
if (!exported)
anyHiddenClasses = true;
else
for (Method m : _c.getDeclaredMethods())
if ((anyHiddenClasses || !isAbstract(m))
&& !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.
// If any classes in the hierarchy were inaccessible, we add
// all interface methods (see test_callForbiddenMethodByReflection for a test)
for (Class intf : allInterfacesImplementedBy(c))
for (Method m : intf.getDeclaredMethods())
if ((anyHiddenClasses || 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 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 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); }
}
// for the version with MasterSymbol (used WAY back in "Smart Bot"!) see #1010608
static class Symbol implements CharSequence {
String text;
Symbol() {}
Symbol(String text, boolean dummy) {
this.text = text;} // weird signature to prevent accidental calling
public int hashCode() { return _hashCode(text); }
public String toString() { return text; }
public boolean equals(Object o) {
return this == o;
}
// implementation of CharSequence methods
public int length() { return text.length(); }
public char charAt(int index) { return text.charAt(index); }
public CharSequence subSequence(int start, int end) {
return text.substring(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();
}
}
/* e.g.
overlay <- ScreenOverlay
bounds <- rightScreenBounds
overlay bounds bounds
overlay show
Can separate commands with ";" also.
For how to define functions in a script see #1033988.
Note: LeftArrowScriptAutoCompleter uses a lot of this class's internals
*/
static class GazelleV_LeftArrowScriptParser extends SimpleLeftToRightParser {
final public GazelleV_LeftArrowScriptParser setG22utils(G22Utils g22utils){ return g22utils(g22utils); }
public GazelleV_LeftArrowScriptParser g22utils(G22Utils g22utils) { this.g22utils = g22utils; return this; } final public G22Utils getG22utils(){ return g22utils(); }
public G22Utils g22utils() { return g22utils; } G22Utils g22utils = new G22Utils();
List functionContainers;
LinkedHashSet knownVars = new LinkedHashSet();
Map functionDefs = new HashMap();
// object can be a class
static class MethodOnObject implements IFieldsToList{
static final String _fieldOrder = "object method";
Object object;
String method;
MethodOnObject() {}
MethodOnObject(Object object, String method) {
this.method = method;
this.object = object;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + object + ", " + method + ")"; }
public boolean equals(Object o) {
if (!(o instanceof MethodOnObject)) return false;
MethodOnObject __3 = (MethodOnObject) o;
return eq(object, __3.object) && eq(method, __3.method);
}
public int hashCode() {
int h = 791808543;
h = boostHashCombine(h, _hashCode(object));
h = boostHashCombine(h, _hashCode(method));
return h;
}
public Object[] _fieldsToList() { return new Object[] {object, method}; }
}
GazelleV_LeftArrowScript.Script parse(String text) {
setText(text);
return parseScript();
}
GazelleV_LeftArrowScript.Script parseScript() {
GazelleV_LeftArrowScript.Script script = new GazelleV_LeftArrowScript.Script();
script.functionDefs = functionDefs;
try {
parseScript_2(script);
return script;
} catch (Throwable e) {
print("Parsed so far:\n" + script);
throw rethrowAndAppendToMessage(e, squareBracketed(str(lineAndColumn())));
}
}
void parseScript_2(GazelleV_LeftArrowScript.Script script) {
while (mainLoop()) {
if (is(";")) { next(); continue; }
if (is("}")) break;
String t = token();
print("First token of command: " + t);
if (is("def"))
{ parseFunctionDefinition(); continue; }
if (is("while"))
{ script.add(parseWhileLoop()); continue; }
if (is("for"))
{ script.add(parseForEach()); continue; }
if (is("if"))
{ script.add(parseIfStatement()); continue; }
print("next tokens: " + quote(token(1)) + " " + quote(token(2)));
if (isIdentifier(t) && eq(token(1), "<") && eq(token(2), "-")) {
print("Found assignment");
next(3);
knownVars.add(t);
script.add(new GazelleV_LeftArrowScript.Assignment(t, parseExpr()));
} else
addUnlessNull(script, parseExpr());
}
}
GazelleV_LeftArrowScript.Evaluable parseOptionalInnerExpression() {
printVars("parseOptionalInnerExpression", "token", token());
if (atCmdEnd() || is("{")) return null;
return parseInnerExpr();
}
GazelleV_LeftArrowScript.Evaluable _const(Object o) { return new GazelleV_LeftArrowScript.Const(o); }
GazelleV_LeftArrowScript.Evaluable parseInnerExpr() { return parseExpr(true); }
GazelleV_LeftArrowScript.Evaluable parseExpr() { return parseExpr(false); }
GazelleV_LeftArrowScript.Evaluable parseExpr(boolean inner) {
if (atEnd()) return null;
String t = token();
printVars("parseExpr", "token" , t);
if (is(";")) return null;
// int or double literal
if (is("-") && empty(nextSpace()) && startsWithDigit(token(1))
|| startsWithDigit(t)) {
t = consumeUntilSpaceOrCmdEnd();
return isInteger(t) ? _const(parseInt(t)) : _const(parseDouble(t));
}
if (isQuoted(t)) {
consume();
return _const(unquote(t));
}
if (isIdentifier(t)) {
consume();
print("Consumed identifier " + t + ", next token: " + token() + ", inner: " + inner);
return parseExprStartingWithIdentifier(t, inner);
}
throw fail("Identifier expected");
}
// t is last consumed token (the identifier the expression starts with)
GazelleV_LeftArrowScript.Evaluable parseExprStartingWithIdentifier(String t, boolean inner) {
if (eq(t, "true")) return _const(true);
if (eq(t, "false")) return _const(false);
if (eq(t, "null")) return _const(null);
if (eq(t, "new")) {
String className = assertIdentifier(tpp());
Object o = findExternalObject(className);
if (o instanceof Class)
return new GazelleV_LeftArrowScript.NewObject(((Class) o), parseArguments());
throw fail("Class not found: " + className);
}
if (knownVars.contains(t)) {
var e = new GazelleV_LeftArrowScript.GetVar(t);
print("Found var acccess: " + e + ", " + (!inner ? "Checking for call" : "Returning expression"));
return inner ? e : parseCall(e);
}
if (!inner) {
var fdef = functionDefs.get(t);
if (fdef != null)
return new GazelleV_LeftArrowScript.CallFunction(fdef, parseArguments());
}
Object o = findExternalObject(t);
if (o == null)
throw fail("Unknown object: " + t);
else if (inner)
return _const(o);
else if (o instanceof Class) {
/*if (atCmdEnd())
ret new Toolbox.NewObject(o);*/
/* old object creation syntax (e.g. Pair new a b)
if (is("new")) {
next();
ret new Toolbox.NewObject(o, parseArguments());
} else*/ if (isIdentifier()) {
String name = tpp();
// look for method first
if (hasMethodNamed(((Class) o), name))
return new GazelleV_LeftArrowScript.CallMethod(_const((Class) o), name, parseArguments());
// look for field second
var field = getField(((Class) o), name);
if (field != null) {
assertCmdEnd();
return new GazelleV_LeftArrowScript.GetStaticField(field);
}
throw fail(name + " not found in " + ((Class) o) + " (looked for method or field)");
} else
throw fail("Method name expected: " + token());
} else if (o instanceof MethodOnObject) {
if (inner) throw fail("Can't call methods in arguments");
return new GazelleV_LeftArrowScript.CallMethod(_const(((MethodOnObject) o).object), ((MethodOnObject) o).method, parseArguments());
} else
return parseCall(_const(o));
}
List parseArguments() {
//ret collectWhileNotNull(-> parseOptionalInnerExpression());
List l = new ArrayList();
try {
while (true) {
GazelleV_LeftArrowScript.Evaluable a = parseOptionalInnerExpression();
if (a == null) break;
l.add(a);
}
return l;
} catch (Throwable _e) {
print("Arguments parsed so far: " + l);
throw rethrow(_e); }
}
String consumeUntilSpaceOrCmdEnd() {
return consumeUntilSpaceOr(() -> atCmdEnd());
}
boolean atCmdEnd() { return atEndOrLineBreak() || is(";") || is("}"); }
void assertCmdEnd() { if (!atCmdEnd()) throw fail("Expected end of command"); }
GazelleV_LeftArrowScript.Evaluable parseCall(GazelleV_LeftArrowScript.Evaluable target) {
if (!isIdentifier()) return target;
String methodName = tpp();
var args = parseArguments();
if (nempty(args))
return new GazelleV_LeftArrowScript.CallMethod(target, methodName, args);
else
return new GazelleV_LeftArrowScript.CallMethodOrGetField(target, methodName);
}
// can return MethodOnObject
transient IF1 findExternalObject;
Object findExternalObject(String name) { return findExternalObject != null ? findExternalObject.get(name) : findExternalObject_base(name); }
final Object findExternalObject_fallback(IF1 _f, String name) { return _f != null ? _f.get(name) : findExternalObject_base(name); }
Object findExternalObject_base(String name) { try {
//try object findClassThroughDefaultClassFinder(name);
//try object findClassInStandardImports(name);
String fullName = globalClassNames().get(name);
if (fullName != null)
return Class.forName(fullName);
for (var container : unnullForIteration(functionContainers))
if (hasMethodNamed(container, name))
return new MethodOnObject(container, name);
return null;
} catch (Exception __e) { throw rethrow(__e); } }
GazelleV_LeftArrowScriptParser allowTheWorld() { return allowTheWorld(mc()); }
GazelleV_LeftArrowScriptParser allowTheWorld(Object... functionContainers) {
this.functionContainers = asList(functionContainers);
globalClassNames_cache = null; // recalculate
return this;
}
void printFunctionDefs() {
print(values(functionDefs));
}
void parseFunctionDefinition() {
consume("def");
String functionName = assertIdentifier(tpp());
List args = new ArrayList();
while (isIdentifier())
args.add(tpp());
AutoCloseable __1 = tempAddAll(knownVars, args); try {
var functionBody = parseCurlyBlock();
functionDefs.put(functionName, new GazelleV_LeftArrowScript.FunctionDef(functionName, args, functionBody));
} finally { _close(__1); }}
GazelleV_LeftArrowScript.Evaluable parseCurlyBlock() {
//print(+knownVars);
consume("{");
var script = parseScript();
consume("}");
return script;
}
GazelleV_LeftArrowScript.Evaluable parseWhileLoop() {
consume("while");
var condition = parseExpr();
var body = parseCurlyBlock();
return new GazelleV_LeftArrowScript.While(condition, body);
}
GazelleV_LeftArrowScript.Evaluable parseForEach() {
consume("for");
String var = assertIdentifier(tpp());
print("for var", var);
consume("in");
var collection = parseExpr();
print("collection", collection);
AutoCloseable __2 = tempAdd(knownVars, var); try {
var body = parseCurlyBlock();
return new GazelleV_LeftArrowScript.ForEach(collection, var, body);
} finally { _close(__2); }}
GazelleV_LeftArrowScript.Evaluable parseIfStatement() {
consume("if");
var condition = parseExpr();
var body = parseCurlyBlock();
return new GazelleV_LeftArrowScript.IfThen(condition, body);
}
// declare an external variable
void addVar(String var) { knownVars.add(var); }
// short name to full name
Map globalClassNames_cache;
Map globalClassNames() { if (globalClassNames_cache == null) globalClassNames_cache = globalClassNames_load(); return globalClassNames_cache; }
Map globalClassNames_load() {
var packages = mapToTreeSet(importedPackages(), pkg -> pkg + ".");
// add inner classes of function containers
var classContainers = classContainerPrefixes();
Map out = new HashMap();
for (var className : g22utils.classNameResolver().allFullyQualifiedClassNames()) {
if (!contains(className, '$')) {
String pkg = longestPrefixInTreeSet(className, packages);
if (pkg != null) {
String shortName = dropPrefix(pkg, className);
if (!shortName.contains("."))
out.put(shortName, className);
}
}
String container = longestPrefixInTreeSet(className, classContainers);
if (container != null)
out.put(dropPrefix(container, className), className);
}
return out;
}
transient IF0> importedPackages;
Collection importedPackages() { return importedPackages != null ? importedPackages.get() : importedPackages_base(); }
final Collection importedPackages_fallback(IF0> _f) { return _f != null ? _f.get() : importedPackages_base(); }
Collection importedPackages_base() {
return itemPlus("java.lang", standardImports_fullyImportedPackages());
}
TreeSet classContainerPrefixes() {
return mapToTreeSet(functionContainers, fc -> className(fc) + "$");
}
}
// In the newest pinging system (with flag PingV3), a ping source
// is the object that "allows" some code to run.
// When that code calls ping(), the ping source's action (if defined)
// is triggered.
// This allows randomly interrupting code execution, for example.
static class PingSource {
// returns true if it slept
final public PingSource setAction(IF0 action){ return action(action); }
public PingSource action(IF0 action) { this.action = action; return this; } final public IF0 getAction(){ return action(); }
public IF0 action() { return action; } volatile IF0 action;
// optional description of this ping source
String text;
// optional thread pool that this ping source likes to run in
ThreadPool threadPool;
PingSource() {}
PingSource(ThreadPool threadPool) {
this.threadPool = threadPool;}
PingSource(ThreadPool threadPool, String text) {
this.text = text;
this.threadPool = threadPool;}
PingSource(IF0 action) {
this.action = action;}
// returns true if it slept
final boolean get() {
var a = action;
return a != null && a.get();
}
final void ping() {
var a = action;
if (a != null) a.get();
}
void cancel() {
action = new Cancelled();
}
class Cancelled implements IF0 {
public Boolean get() { throw new PingSourceCancelledException(PingSource.this); }
}
class Encapsulated implements Runnable , IFieldsToList{
Runnable r;
Encapsulated() {}
Encapsulated(Runnable r) {
this.r = r;}public Object[] _fieldsToList() { return new Object[] {r}; }
public void run() { try {
//System.out.println("Encapsulated running: " + r);
try {
pingSource_tl().set(PingSource.this);
//System.out.println("Ping source set");
ping();
r.run();
//System.out.println("Done running");
} finally {
//System.out.println("Finally");
pingSource_tl().set(null);
}
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return PingSource.this + ": " + r; }
}
void dO(Runnable r) {
if (r == null) return;
threadPool.acquireThreadOrQueue(new Encapsulated(r));
}
public String toString() { String t = text; return nempty(t) ? t : super.toString(); }
ISleeper_v2 sleeper() { return threadPool.sleeper(); }
}
static class MultiMap {
Map > data = new HashMap >();
int fullSize;
MultiMap() {}
MultiMap(boolean useTreeMap) { if (useTreeMap) data = new TreeMap(); }
MultiMap(MultiMap map) { putAll(map); }
MultiMap(Map > data) {
this.data = data;}
void put(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
list.add(value);
++fullSize;
}}
void add(A key, B value) { put(key, value); }
void addAll(A key, Collection values) { putAll(key, values); }
void addAllIfNotThere(A key, Collection values) { synchronized(data) {
for (B value : values)
setPut(key, value);
}}
void setPut(A key, B value) { synchronized(data) {
if (!containsPair(key, value))
put(key, value);
}}
boolean containsPair(A key, B value) { synchronized(data) {
return get(key).contains(value);
}}
void putAll(Collection keys, B value) { synchronized(data) {
for (A key : unnullForIteration(keys))
put(key, value);
}}
void putAll(A key, Collection values) { synchronized(data) {
if (nempty(values)) getActual(key).addAll(values);
}}
void putAll(Iterable> pairs) { synchronized(data) {
for (Pair p : unnullForIteration(pairs))
put(p.a, p.b);
}}
void removeAll(A key, Collection values) { synchronized(data) {
for (B value : values)
remove(key, value);
}}
List get(A key) { synchronized(data) {
List list = data.get(key);
return list == null ? Collections. emptyList() : list;
}}
List getOpt(A key) { synchronized(data) {
return data.get(key);
}}
List getAndClear(A key) { synchronized(data) {
List l = cloneList(data.get(key));
remove(key);
return l;
}}
// returns actual mutable live list
// creates the list if not there
List getActual(A key) { synchronized(data) {
List list = data.get(key);
if (list == null)
data.put(key, list = _makeEmptyList());
return list;
}}
void clean(A key) { synchronized(data) {
List list = data.get(key);
if (list != null && list.isEmpty()) {
fullSize -= l(list);
data.remove(key);
}
}}
Set keySet() { synchronized(data) {
return data.keySet();
}}
Set keys() { synchronized(data) {
return data.keySet();
}}
void remove(A key) { synchronized(data) {
fullSize -= l(this.getOpt(key));
data.remove(key);
}}
final void remove(Pair p){ removePair(p); }
void removePair(Pair p) {
if (p != null) remove(p.a, p.b);
}
void remove(A key, B value) { synchronized(data) {
List list = data.get(key);
if (list != null) {
if (list.remove(value))
fullSize--;
if (list.isEmpty())
data.remove(key);
}
}}
void clear() { synchronized(data) {
data.clear();
}}
boolean containsKey(A key) { synchronized(data) {
return data.containsKey(key);
}}
B getFirst(A key) { synchronized(data) {
List list = get(key);
return list.isEmpty() ? null : list.get(0);
}}
void addAll(MultiMap map) { putAll(map); }
void putAll(MultiMap map) { synchronized(data) {
for (A key : map.keySet())
putAll(key, map.get(key));
}}
void putAll(Map map) { synchronized(data) {
if (map != null) for (Map.Entry e : map.entrySet())
put(e.getKey(), e.getValue());
}}
final int keyCount(){ return keysSize(); }
int keysSize() { synchronized(data) { return l(data); }}
// full size - note: expensive operation
final int fullSize(){ return size(); }
int size() { synchronized(data) {
return fullSize;
}}
// expensive operation
List reverseGet(B b) { synchronized(data) {
List l = new ArrayList();
for (A key : data.keySet())
if (data.get(key).contains(b))
l.add(key);
return l;
}}
Map > asMap() { synchronized(data) {
return cloneMap(data);
}}
boolean isEmpty() { synchronized(data) { return data.isEmpty(); }}
// override in subclasses
List _makeEmptyList() {
return new ArrayList();
}
// returns live lists
Collection> allLists() {
synchronized(data) {
return new ArrayList(data.values());
}
}
Collection> values() { return allLists(); }
List allValues() {
return concatLists(data.values());
}
Object mutex() { return data; }
public String toString() { return "mm" + str(data); }
}
static interface IF0 {
A get();
}
static interface Hasher {
int hashCode(A a);
boolean equals(A a, A b);
}
static abstract class CloseableIterableIterator extends IterableIterator implements AutoCloseable {
public void close() throws Exception {}
}
static interface IF2 {
C get(A a, B b);
}
// Note: This does have the values problem (complicated values can cause memory leaks)
static class BetterThreadLocal {
Map map = newWeakHashMap();
BetterThreadLocal() {}
BetterThreadLocal(A value) { set(value); }
boolean isSet() { return map.containsKey(currentThread()); }
A get() {
if (map.containsKey(currentThread()))
return map.get(currentThread());
A value = initialValue();
set(value);
return value;
}
A get(Thread thread) {
return thread == null ? null : map.get(thread);
}
void set(A a) {
map.put(currentThread(), a);
}
public A initialValue() { return null; }
}
static interface IF1 {
B get(A a);
}
/*
* @(#)WeakHashMap.java 1.5 98/09/30
*
* Copyright 1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
// From https://github.com/mernst/plume-lib/blob/df0bfafc3c16848d88f4ea0ef3c8bf3367ae085e/java/src/plume/WeakHasherMap.java
static final class WeakHasherMap extends AbstractMap implements Map {
private Hasher hasher = null;
/*@Pure*/
private boolean keyEquals(Object k1, Object k2) {
return (hasher==null ? k1.equals(k2)
: hasher.equals(k1, k2));
}
/*@Pure*/
private int keyHashCode(Object k1) {
return (hasher==null ? k1.hashCode()
: hasher.hashCode(k1));
}
// The WeakKey class can't be static because it depends on the hasher.
// That in turn means that its methods can't be static.
// However, I need to be able to call the methods such as create() that
// were static in the original version of this code.
// This finesses that.
private /*@Nullable*/ WeakKey WeakKeyCreate(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private /*@Nullable*/ WeakKey WeakKeyCreate(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
// Cannot be a static class: uses keyHashCode() and keyEquals()
private final class WeakKey extends WeakReference {
private int hash; /* Hashcode of key, stored here since the key
may be tossed by the GC */
private WeakKey(K k) {
super(k);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k) {
if (k == null) return null;
else return new WeakKey(k);
}
private WeakKey(K k, ReferenceQueue super K> q) {
super(k, q);
hash = keyHashCode(k);
}
private /*@Nullable*/ WeakKey create(K k, ReferenceQueue super K> q) {
if (k == null) return null;
else return new WeakKey(k, q);
}
/* A WeakKey is equal to another WeakKey iff they both refer to objects
that are, in turn, equal according to their own equals methods */
/*@Pure*/
@Override
public boolean equals(/*@Nullable*/ Object o) {
if (o == null) return false; // never happens
if (this == o) return true;
// This test is illegal because WeakKey is a generic type,
// so use the getClass hack below instead.
// if (!(o instanceof WeakKey)) return false;
if (!(o.getClass().equals(WeakKey.class))) return false;
Object t = this.get();
@SuppressWarnings("unchecked")
Object u = ((WeakKey)o).get();
if ((t == null) || (u == null)) return false;
if (t == u) return true;
return keyEquals(t, u);
}
/*@Pure*/
@Override
public int hashCode() {
return hash;
}
}
/* Hash table mapping WeakKeys to values */
private HashMap hash;
/* Reference queue for cleared WeakKeys */
private ReferenceQueue super K> queue = new ReferenceQueue();
/* Remove all invalidated entries from the map, that is, remove all entries
whose keys have been discarded. This method should be invoked once by
each public mutator in this class. We don't invoke this method in
public accessors because that can lead to surprising
ConcurrentModificationExceptions. */
@SuppressWarnings("unchecked")
private void processQueue() {
WeakKey wk;
while ((wk = (WeakKey)queue.poll()) != null) { // unchecked cast
hash.remove(wk);
}
}
/* -- Constructors -- */
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the given load factor.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @param loadFactor the load factor of the WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero, or if the load factor is
* nonpositive
*/
public WeakHasherMap(int initialCapacity, float loadFactor) {
hash = new HashMap(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty WeakHashMap with the given
* initial capacity and the default load factor, which is
* 0.75.
*
* @param initialCapacity the initial capacity of the
* WeakHashMap
*
* @throws IllegalArgumentException If the initial capacity is less than
* zero
*/
public WeakHasherMap(int initialCapacity) {
hash = new HashMap(initialCapacity);
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
*/
public WeakHasherMap() {
hash = new HashMap();
}
/**
* Constructs a new, empty WeakHashMap with the default
* capacity and the default load factor, which is 0.75.
* The WeakHashMap uses the specified hasher for hashing
* keys and comparing them for equality.
* @param h the Hasher to use when hashing values for this map
*/
public WeakHasherMap(Hasher h) {
hash = new HashMap();
hasher = h;
}
/* -- Simple queries -- */
/**
* Returns the number of key-value mappings in this map.
* Note: In contrast to most implementations of the
* Map interface, the time required by this operation is
* linear in the size of the map.
*/
/*@Pure*/
@Override
public int size() {
return entrySet().size();
}
/**
* Returns true if this map contains no key-value mappings.
*/
/*@Pure*/
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
/**
* Returns true if this map contains a mapping for the
* specified key.
*
* @param key the key whose presence in this map is to be tested
*/
/*@Pure*/
@Override
public boolean containsKey(Object key) {
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.containsKey(WeakKeyCreate(kkey));
}
/* -- Lookup and modification operations -- */
/**
* Returns the value to which this map maps the specified key.
* If this map does not contain a value for this key, then return
* null.
*
* @param key the key whose associated value, if any, is to be returned
*/
/*@Pure*/
@Override
public /*@Nullable*/ V get(Object key) { // type of argument is Object, not K
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.get(WeakKeyCreate(kkey));
}
/**
* Updates this map so that the given key maps to the given
* value. If the map previously contained a mapping for
* key then that mapping is replaced and the previous value is
* returned.
*
* @param key the key that is to be mapped to the given
* value
* @param value the value to which the given key is to be
* mapped
*
* @return the previous value to which this key was mapped, or
* null if if there was no mapping for the key
*/
@Override
public V put(K key, V value) {
processQueue();
return hash.put(WeakKeyCreate(key, queue), value);
}
/**
* Removes the mapping for the given key from this map, if
* present.
*
* @param key the key whose mapping is to be removed
*
* @return the value to which this key was mapped, or null if
* there was no mapping for the key
*/
@Override
public V remove(Object key) { // type of argument is Object, not K
processQueue();
@SuppressWarnings("unchecked")
K kkey = (K) key;
return hash.remove(WeakKeyCreate(kkey));
}
/**
* Removes all mappings from this map.
*/
@Override
public void clear() {
processQueue();
hash.clear();
}
/* -- Views -- */
/* Internal class for entries */
// This can't be static, again because of dependence on hasher.
@SuppressWarnings("TypeParameterShadowing")
private final class Entry implements Map.Entry {
private Map.Entry ent;
private K key; /* Strong reference to key, so that the GC
will leave it alone as long as this Entry
exists */
Entry(Map.Entry ent, K key) {
this.ent = ent;
this.key = key;
}
/*@Pure*/
@Override
public K getKey() {
return key;
}
/*@Pure*/
@Override
public V getValue() {
return ent.getValue();
}
@Override
public V setValue(V value) {
return ent.setValue(value);
}
/*@Pure*/
private boolean keyvalEquals(K o1, K o2) {
return (o1 == null) ? (o2 == null) : keyEquals(o1, o2);
}
/*@Pure*/
private boolean valEquals(V o1, V o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
/*@Pure*/
@SuppressWarnings("NonOverridingEquals")
public boolean equals(Map.Entry e /* Object o*/) {
// if (! (o instanceof Map.Entry)) return false;
// Map.Entry e = (Map.Entry)o;
return (keyvalEquals(key, e.getKey())
&& valEquals(getValue(), e.getValue()));
}
/*@Pure*/
@Override
public int hashCode() {
V v;
return (((key == null) ? 0 : keyHashCode(key))
^ (((v = getValue()) == null) ? 0 : v.hashCode()));
}
}
/* Internal class for entry sets */
private final class EntrySet extends AbstractSet> {
Set> hashEntrySet = hash.entrySet();
@Override
public Iterator> iterator() {
return new Iterator>() {
Iterator> hashIterator = hashEntrySet.iterator();
Map.Entry next = null;
@Override
public boolean hasNext() {
while (hashIterator.hasNext()) {
Map.Entry ent = hashIterator.next();
WeakKey wk = ent.getKey();
K k = null;
if ((wk != null) && ((k = wk.get()) == null)) {
/* Weak key has been cleared by GC */
continue;
}
next = new Entry(ent, k);
return true;
}
return false;
}
@Override
public Map.Entry next() {
if ((next == null) && !hasNext())
throw new NoSuchElementException();
Map.Entry e = next;
next = null;
return e;
}
@Override
public void remove() {
hashIterator.remove();
}
};
}
/*@Pure*/
@Override
public boolean isEmpty() {
return !(iterator().hasNext());
}
/*@Pure*/
@Override
public int size() {
int j = 0;
for (Iterator> i = iterator(); i.hasNext(); i.next()) j++;
return j;
}
@Override
public boolean remove(Object o) {
processQueue();
if (!(o instanceof Map.Entry,?>)) return false;
@SuppressWarnings("unchecked")
Map.Entry e = (Map.Entry)o; // unchecked cast
Object ev = e.getValue();
WeakKey wk = WeakKeyCreate(e.getKey());
Object hv = hash.get(wk);
if ((hv == null)
? ((ev == null) && hash.containsKey(wk)) : hv.equals(ev)) {
hash.remove(wk);
return true;
}
return false;
}
/*@Pure*/
@Override
public int hashCode() {
int h = 0;
for (Iterator> i = hashEntrySet.iterator(); i.hasNext(); ) {
Map.Entry ent = i.next();
WeakKey wk = ent.getKey();
Object v;
if (wk == null) continue;
h += (wk.hashCode()
^ (((v = ent.getValue()) == null) ? 0 : v.hashCode()));
}
return h;
}
}
private /*@Nullable*/ Set> entrySet = null;
/**
* Returns a Set view of the mappings in this map.
*/
/*@SideEffectFree*/
@Override
public Set> entrySet() {
if (entrySet == null) entrySet = new EntrySet();
return entrySet;
}
// find matching key
K findKey(Object key) {
processQueue();
K kkey = (K) key;
// TODO: use replacement for HashMap to avoid reflection
WeakKey wkey = WeakKeyCreate(kkey);
WeakKey found = hashMap_findKey(hash, wkey);
return found == null ? null : found.get();
}
}
static class PersistableThrowable extends DynamicObject {
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 IVF1 {
void get(A a);
}
static class Fail extends RuntimeException implements IFieldsToList{
Object[] objects;
Fail() {}
Fail(Object... objects) {
this.objects = objects;}public Object[] _fieldsToList() { return new Object[] {objects}; }
Fail(Throwable cause, Object... objects) {
super(cause);
this.objects = objects;
}
public String toString() { return joinNemptiesWithColon("Fail", commaCombine(getCause(), objects)); }
}
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 PingSourceCancelledException extends RuntimeException implements IFieldsToList{
PingSource pingSource;
PingSourceCancelledException() {}
PingSourceCancelledException(PingSource pingSource) {
this.pingSource = pingSource;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + pingSource + ")"; }public Object[] _fieldsToList() { return new Object[] {pingSource}; }
}
static interface ISleeper_v2 {
Sleeping doLater(Timestamp targetTime, Runnable r);
public default Sleeping doAfter(double seconds, Runnable r) {
return doLater(tsNow().plusSeconds(seconds), r);
}
}
static interface IFieldsToList {
Object[] _fieldsToList();
}
// The idea is to leave max as the actual number of cores the system
// has (numberOfCores()), and in case of being fully booked, raise an
// alert (customerMustWaitAlert) which can be handled by a strategy
// object (different reactions are possible).
// If nothing is done in such an event, clients are processed serially
// (no guarantees of order), split up among the available threads.
/* SYNChronisation order:
1. PooledThread
2. ThreadPool */
static class ThreadPool implements AutoCloseable {
int max = numberOfCores();
List all = new ArrayList();
Set used = new HashSet();
Set free = new HashSet();
boolean verbose, retired;
// our own ping surce so we can start threads & keep them running
class InternalPingSource extends PingSource {}
InternalPingSource internalPingSource = new InternalPingSource();
MultiSleeper sleeper = new MultiSleeper();
ThreadPool() {}
ThreadPool(int max) {
this.max = max;}
synchronized int maxSize() { return max; }
synchronized int total() { return l(used)+l(free); }
transient List onCustomerMustWaitAlert;
public ThreadPool onCustomerMustWaitAlert(Runnable r) { onCustomerMustWaitAlert = syncAddOrCreate(onCustomerMustWaitAlert, r); return this; }
public ThreadPool removeCustomerMustWaitAlertListener(Runnable r) { main.remove(onCustomerMustWaitAlert, r); return this; }
void customerMustWaitAlert() { pcallFAll(onCustomerMustWaitAlert); }
void fireCustomerMustWaitAlert() {
vmBus_send("customerMustWaitAlert", this, currentThread());
customerMustWaitAlert();
}
// DOESN'T WAIT. adds action to a thread's queue if nothing is
// available immediately.
PooledThread acquireThreadOrQueue(Runnable action) {
if (action == null) return null;
PooledThread t;
synchronized(this) {
if (_hasFreeAfterCreating()) {
t = _firstFreeThread();
markUsed(t);
} else
t = _anyThread();
}
t.addWork(action); // will move it from free to used
return t;
}
// run in synchronized block
boolean _hasFreeAfterCreating() {
checkNotRetired();
if (nempty(free)) return true;
if (total() < max) {
PooledThread t = newThread();
all.add(t);
free.add(t);
return true;
}
return false;
}
// WAITS until thread is available
PooledThread acquireThreadOrWait(Runnable action) { try {
if (action == null) return null;
PooledThread t;
while (true) {
synchronized(this) {
if (_hasFreeAfterCreating()) {
t = _firstFreeThread();
break;
} else
_waitWaitWait();
}
}
t.addWork(action);
return t;
} catch (Exception __e) { throw rethrow(__e); } }
PooledThread _firstFreeThread() {
return first(free);
}
PooledThread _anyThread() {
return random(used);
}
class PooledThread extends Thread {
PooledThread(String name) { super(name); }
AppendableChain q;
synchronized Runnable _grabWorkOrSleep() { try {
Runnable r = first(q);
if (r == null) {
markFree(this);
if (verbose) print("Thread sleeps");
synchronized(this) { wait(); }
if (verbose) print("Thread woke up");
return null;
}
q = popFirst(q);
return r;
} catch (Exception __e) { throw rethrow(__e); } }
public void run() { try {
pingSource_tl().set(internalPingSource);
while (!retired()) { ping();
Runnable r = _grabWorkOrSleep();
if (verbose) print(this + " work: " + r);
if (r != null)
try {
if (verbose) print(this + " running: " + r);
r.run();
pingSource_tl().set(internalPingSource);
if (verbose) print(this + " done");
} catch (Throwable e) {
pingSource_tl().set(internalPingSource);
if (verbose) print(this + " error");
printStackTrace(e);
} finally {
pingSource_tl().set(internalPingSource);
if (verbose) print("ThreadPool finally");
}
}
} catch (Exception __e) { throw rethrow(__e); } }
synchronized boolean isEmpty() { return empty(q); }
// append to q (do later)
void addWork(Runnable r) {
if (verbose) print("Added work to " + this + ": " + r);
synchronized(this) {
q = chainPlus(q, r);
notifyAll();
}
}
}
PooledThread newThread() {
PooledThread t = new PooledThread("Thread Pool Inhabitant " + n2(total()+1));
t.start();
return t;
}
synchronized void markFree(PooledThread t) {
used.remove(t);
free.add(t);
notifyAll();
}
synchronized void markUsed(PooledThread t) {
free.remove(t);
used.add(t);
}
synchronized public String toString() {
return retired()
? "Retired ThreadPool"
: "ThreadPool " + roundBracket(commaCombine(
n2(used) + " used out of " + n2(total()),
max <= total() ? null : "could grow to " + n2(max)));
}
synchronized boolean retired() { return retired; }
synchronized void retire() {
if (verbose) print("ThreadPool Retiring");
retired = true;
for (var thread : free) syncNotifyAll(thread); // wake it up so it exits
}
void checkNotRetired() {
if (retired()) throw fail("retired");
}
// We could do a soft-close here (stop the idle threads, let running threads finish, then end those too, stop accepting new orders)
// or a hard close (interrupt all threads, stop accepting new orders)
synchronized public void close() { try {
retire();
} catch (Exception __e) { throw rethrow(__e); } }
// run in synchronized block
void _waitWaitWait() { try {
do {
fireCustomerMustWaitAlert();
wait();
checkNotRetired();
} while (empty(free));
} catch (Exception __e) { throw rethrow(__e); } }
void dO(String text, Runnable r) {
if (r == null) return;
new PingSource(this, text).dO(r);
}
ISleeper_v2 sleeper() { return sleeper; }
}
// See GazelleV_LeftArrowScriptParser
// TODO: decide whether we allow calling methods/getting fields on
// a null reference (just returning null), or whether we throw a
// NullPointerException.
static class GazelleV_LeftArrowScript {
interface Evaluable {
public default Object get() { return get(new VarContext()); }
public Object get(VarContext ctx);
}
// We're using SynchronizedList as a list wrapper
//sclass Script extends ArrayList {
static class Script extends SynchronizedList implements Evaluable {
Map functionDefs;
Script() { super(new ArrayList()); }
public Object get(VarContext ctx) {
Object result = null;
for (var step : this) {
ping();
result = step.get(ctx);
}
return result;
}
public String toString() { return pnlToLines(this); }
FunctionDef getFunction(String name) { return mapGet(functionDefs, name); }
} // end of Script
static class FunctionDef implements IFieldsToList{
String name;
List args;
Evaluable body;
FunctionDef() {}
FunctionDef(String name, List args, Evaluable body) {
this.body = body;
this.args = args;
this.name = name;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + name + ", " + args + ", " + body + ")"; }public Object[] _fieldsToList() { return new Object[] {name, args, body}; }
public Object call(VarContext ctx, Object... args) {
var ctx2 = new VarContext(ctx);
int n = min(l(args), l(this.args));
for (int i = 0; i < n; i++)
ctx2.put(this.args.get(i), args[i]);
return body.get(ctx2);
}
}
static class Assignment implements Evaluable , IFieldsToList{
String var;
Evaluable expression;
Assignment() {}
Assignment(String var, Evaluable expression) {
this.expression = expression;
this.var = var;}public Object[] _fieldsToList() { return new Object[] {var, expression}; }
public Object get(VarContext ctx) {
Object o = expression.get(ctx);
ctx.set(var, o);
return o;
}
public String toString() { return var + " <- " + expression; }
}
static class NewObject implements Evaluable {
NewObject() {}
Class c;
List args;
NewObject(Class c) {
this.c = c;}
NewObject(Class c, List args) {
this.args = args;
this.c = c;}
public Object get(VarContext ctx) {
return callConstructor(c, mapToArray(args, arg -> arg.get(ctx)));
}
public String toString() { return "new " + formatFunctionCall(className(c), args); }
}
static class CallFunction implements Evaluable , IFieldsToList{
FunctionDef f;
List args;
CallFunction() {}
CallFunction(FunctionDef f, List args) {
this.args = args;
this.f = f;}public Object[] _fieldsToList() { return new Object[] {f, args}; }
public Object get(VarContext ctx) {
//ping();
return f.call(ctx, mapToArray(args, a -> a.get(ctx)));
}
public String toString() { return formatFunctionCall(f.name, args); }
}
static class GetVar implements Evaluable , IFieldsToList{
String var;
GetVar() {}
GetVar(String var) {
this.var = var;}public Object[] _fieldsToList() { return new Object[] {var}; }
public Object get(VarContext ctx) {
return ctx.get(var);
}
public String toString() { return var; }
}
static class Const implements Evaluable , IFieldsToList{
Object value;
Const() {}
Const(Object value) {
this.value = value;}public Object[] _fieldsToList() { return new Object[] {value}; }
public Object get(VarContext ctx) {
return value;
}
public String toString() { return strOrClassName(value); }
}
static class GetStaticField implements Evaluable , IFieldsToList{
Field field;
GetStaticField() {}
GetStaticField(Field field) {
this.field = field;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + field + ")"; }public Object[] _fieldsToList() { return new Object[] {field}; }
public Object get(VarContext ctx) { try {
return field.get(null);
} catch (Exception __e) { throw rethrow(__e); } }
}
static class CallMethodOrGetField implements Evaluable , IFieldsToList{
Evaluable target;
String name;
CallMethodOrGetField() {}
CallMethodOrGetField(Evaluable target, String name) {
this.name = name;
this.target = target;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + target + ", " + name + ")"; }public Object[] _fieldsToList() { return new Object[] {target, name}; }
public Object get(VarContext ctx) {
Object object = target.get(ctx);
if (object == null)
return null; // throw new NullPointerException();
// could optimize more for sure
if (canCallWithVarargs(object, name))
return call(object, name);
return _get(object, name);
}
}
static class CallMethod implements Evaluable , IFieldsToList{
static final String _fieldOrder = "target methodName args";
Evaluable target;
String methodName;
List args;
CallMethod() {}
CallMethod(Evaluable target, String methodName, List args) {
this.args = args;
this.methodName = methodName;
this.target = target;}
public boolean equals(Object o) {
if (!(o instanceof CallMethod)) return false;
CallMethod __1 = (CallMethod) o;
return eq(target, __1.target) && eq(methodName, __1.methodName) && eq(args, __1.args);
}
public int hashCode() {
int h = -898542337;
h = boostHashCombine(h, _hashCode(target));
h = boostHashCombine(h, _hashCode(methodName));
h = boostHashCombine(h, _hashCode(args));
return h;
}
public Object[] _fieldsToList() { return new Object[] {target, methodName, args}; }
public Object get(VarContext ctx) {
return call(target.get(ctx), methodName, mapToArray(args, arg -> arg.get(ctx)));
}
public String toString() { return target + "." + formatFunctionCall(methodName, args); }
}
static class While implements Evaluable , IFieldsToList{
static final String _fieldOrder = "condition body";
Evaluable condition;
Evaluable body;
While() {}
While(Evaluable condition, Evaluable body) {
this.body = body;
this.condition = condition;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof While)) return false;
While __2 = (While) o;
return eq(condition, __2.condition) && eq(body, __2.body);
}
public int hashCode() {
int h = 83548945;
h = boostHashCombine(h, _hashCode(condition));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {condition, body}; }
public Object get(VarContext ctx) {
while (ping() && (Boolean) condition.get(ctx)) {
body.get(ctx);
}
// while loops don't return anything
return null;
}
}
static class ForEach implements Evaluable , IFieldsToList{
static final String _fieldOrder = "collection var body";
Evaluable collection;
String var;
Evaluable body;
ForEach() {}
ForEach(Evaluable collection, String var, Evaluable body) {
this.body = body;
this.var = var;
this.collection = collection;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + collection + ", " + var + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof ForEach)) return false;
ForEach __3 = (ForEach) o;
return eq(collection, __3.collection) && eq(var, __3.var) && eq(body, __3.body);
}
public int hashCode() {
int h = 986017354;
h = boostHashCombine(h, _hashCode(collection));
h = boostHashCombine(h, _hashCode(var));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {collection, var, body}; }
public Object get(VarContext ctx) {
var coll = collection.get(ctx);
Iterator iterator;
if (coll instanceof Object[])
for (var element : ((Object[]) coll)) {
ping();
ctx.set(var, element);
body.get(ctx);
}
else if (coll instanceof Iterable) {
for (var element : ((Iterable) coll)) {
ping();
ctx.set(var, element);
body.get(ctx);
}
} else if (coll == null) {} // ok
else
throw fail("Not iterable: " + className(coll));
ctx.unset(var);
return null;
}
}
static class IfThen implements Evaluable , IFieldsToList{
static final String _fieldOrder = "condition body";
Evaluable condition;
Evaluable body;
IfThen() {}
IfThen(Evaluable condition, Evaluable body) {
this.body = body;
this.condition = condition;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + condition + ", " + body + ")"; }
public boolean equals(Object o) {
if (!(o instanceof IfThen)) return false;
IfThen __4 = (IfThen) o;
return eq(condition, __4.condition) && eq(body, __4.body);
}
public int hashCode() {
int h = -2108234502;
h = boostHashCombine(h, _hashCode(condition));
h = boostHashCombine(h, _hashCode(body));
return h;
}
public Object[] _fieldsToList() { return new Object[] {condition, body}; }
public Object get(VarContext ctx) {
if ((Boolean) condition.get(ctx))
return body.get(ctx);
else
return null;
}
}
}
static class SimpleLeftToRightParser {
String text;
List tok;
ListAndIndex ptr, mainLoopPtr;
String currentToken;
boolean caseInsensitive = false;
List warnings = new ArrayList();
SimpleLeftToRightParser() {}
SimpleLeftToRightParser(String text) {
this.text = text;}
SimpleLeftToRightParser(List tok) {
this.tok = tok;}
final String token(){ return t(); }
String t() { return currentToken; }
String token(int i) { return get(tok, ptr.idx()+i*2); }
String tpp() { var t = t(); next(); return t; }
String lastSpace() { return get(tok, ptr.idx()-1); }
String nextSpace() { return get(tok, ptr.idx()+1); }
boolean is(String t) { return eqOrEqic(caseInsensitive, currentToken, t); }
boolean was(String t) { return eqOrEqic(caseInsensitive, token(-1), t); }
boolean isInteger() { return isInteger(t()); }
boolean isInteger(String s) { return main.isInteger(s); }
boolean isIdentifier() { return isIdentifier(t()); }
boolean isIdentifier(String s) { return main.isIdentifier(s); }
final void consume(){ next(); }
void next() { if (!endOfText()) ptr(ptr.plus(2)); }
void consume(String token) {
if (!is(token)) throw fail("Expected " + quote(token));
consume();
}
void ptr(ListAndIndex ptr) { this.ptr = ptr; fetch(); }
int idx() { return ptr.idx(); }
int lTok() { return l(tok); }
final boolean endOfText(){ return atEnd(); }
boolean atEnd() { return ptr.atEnd(); }
void fetch() { currentToken = ptr.get(); }
boolean lineBreak() { return containsLineBreak(get(tok, ptr.idx()-1)); }
boolean atEndOrLineBreak() { return atEnd() || lineBreak(); }
void init() {
if (tok == null) tok = javaTok(text);
if (ptr == null) ptr(new ListAndIndex(tok, 1));
}
boolean mainLoop() {
init();
if (atEnd()) return false;
if (eq(mainLoopPtr, ptr))
throw fail("main loop didn't advance (current token: " + quote(token()) + ")");
mainLoopPtr = ptr;
return true;
}
void unknownToken() {
warn("Unknown token: " + t());
}
void warn(String msg) {
warnings.add(print(msg));
}
void next(int n) {
ptr(ptr.idx()+n*2);
}
// if i points to an N token, it is incremented
void ptr(int i) {
ptr(new ListAndIndex(tok, min(i | 1, l(tok))));
}
LineAndColumn lineAndColumn() {
return tokenToLineAndColumn(ptr);
}
String consumeUntilSpaceOr(IF0 pred) {
int i = idx();
do next(); while (!atEnd() && empty(lastSpace()) && !pred.get());
return joinSubList(tok, i, idx()-1);
}
void setText(String text) {
this.text = text;
tok = null;
ptr = null;
}
}
static class G22Utils {
final public CombinedStringifier getStringifier(){ return stringifier(); }
public CombinedStringifier stringifier() { return stringifier; } CombinedStringifier stringifier = new CombinedStringifier(
o -> o instanceof BufferedImage ? "Image (" + ((BufferedImage) o).getWidth() + "*" + ((BufferedImage) o).getHeight() + " px)" : null
);
ImageSurface stdImageSurface() {
var is = pixelatedImageSurface().setAutoZoomToDisplay(true).repaintInThread(false);
is.specialPurposed = true;
new ImageSurface_PositionToolTip(is);
return is;
}
ImageSurface stdImageSurface(MakesBufferedImage img) { return stdImageSurface(toBufferedImage(img)); }
ImageSurface stdImageSurface(BufferedImage img) {
var is = stdImageSurface();
is.setImage(img);
return is;
}
String stringify(Object o) { return stringifier.toString(o); }
transient IVF1 modifyLeftArrowParser;
void modifyLeftArrowParser(GazelleV_LeftArrowScriptParser parser) { if (modifyLeftArrowParser != null) modifyLeftArrowParser.get(parser); else modifyLeftArrowParser_base(parser); }
final void modifyLeftArrowParser_fallback(IVF1 _f, GazelleV_LeftArrowScriptParser parser) { if (_f != null) _f.get(parser); else modifyLeftArrowParser_base(parser); }
void modifyLeftArrowParser_base(GazelleV_LeftArrowScriptParser parser) {}
GazelleV_LeftArrowScriptParser leftArrowParser() {
GazelleV_LeftArrowScriptParser parser = new GazelleV_LeftArrowScriptParser();
parser.g22utils(this);
modifyLeftArrowParser(parser);
return parser;
}
void basicParserTest() {
var parser = leftArrowParser();
print("classContainerPrefixes" , parser.classContainerPrefixes());
assertEquals(pair(1, 2), parser.parse("new Pair 1 2").get());
}
File byteCodePath() {
return assertNotNull(getBytecodePathForClass(this));
}
ClassNameResolver classNameResolver_cache;
ClassNameResolver classNameResolver() { if (classNameResolver_cache == null) classNameResolver_cache = classNameResolver_load(); return classNameResolver_cache; }
ClassNameResolver classNameResolver_load() {
return new ClassNameResolver().byteCodePath(byteCodePath()).init();
}
}
// takes ~70 ms to set up, do it only once if possible
static class ClassNameResolver {
final public ClassNameResolver setByteCodePath(File byteCodePath){ return byteCodePath(byteCodePath); }
public ClassNameResolver byteCodePath(File byteCodePath) { this.byteCodePath = byteCodePath; return this; } final public File getByteCodePath(){ return byteCodePath(); }
public File byteCodePath() { return byteCodePath; } File byteCodePath = byteCodePathForClass(getClass());
List importedPackages = itemPlusList("java.lang",
endingWith_dropSuffix(standardImports(), ".*"));
Set allFullyQualifiedClassNames_cache;
Set allFullyQualifiedClassNames() { if (allFullyQualifiedClassNames_cache == null) allFullyQualifiedClassNames_cache = allFullyQualifiedClassNames_load(); return allFullyQualifiedClassNames_cache; }
Set allFullyQualifiedClassNames_load() {
Set set = new HashSet();
assertNotNull(byteCodePath);
set.addAll(classNamesInJarOrDir(byteCodePath));
printVars("ClassNameResolver", "byteCodePath", byteCodePath, "classesFound" , l(set));
set.addAll(classNamesInLoadedJigsawModules());
return set;
}
ClassNameResolver init() { allFullyQualifiedClassNames(); return this; }
String findClass(String name) {
for (String pkg : importedPackages) {
String fullName = pkg + "." + name;
if (allFullyQualifiedClassNames().contains(fullName))
return fullName;
}
return null;
}
void printMe() {
printVars("ClassNameResolver", "byteCodePath", byteCodePath);
print("importedPackages", importedPackages);
}
}
static class VarContext {
VarContext parent;
Map vars;
VarContext() {}
VarContext(VarContext parent) {
this.parent = parent;}
Object get(String name) {
if (containsKey(vars, name))
return mapGet(vars, name);
if (parent != null)
return parent.get(name);
return null;
}
final void put(String name, Object value){ set(name, value); }
void set(String name, Object value) {
vars = mapPutOrCreate(vars, name, value);
}
void unset(String name) {
remove(vars, name);
}
}
// Both lines and columns are numbered from 1
static class LineAndColumn {
int line, col;
LineAndColumn(int line, int col) {
this.col = col;
this.line = line;}
// get text of a line. may return null if no text available
transient IF1 getLineText;
String getLineText(int line) { return getLineText != null ? getLineText.get(line) : getLineText_base(line); }
final String getLineText_fallback(IF1 _f, int line) { return _f != null ? _f.get(line) : getLineText_base(line); }
String getLineText_base(int line) { return null; }
public String toString() { return "Line " + n2(line) + ", col " + n2(col); }
}
static class FailedRule extends RuleWithParams {
List satisfiedConditions;
Exp remainingCondition;
FailedRule() {}
FailedRule(IfThen rule, VarMatches matches, Exp remainingCondition) {
this.remainingCondition = remainingCondition;
this.matches = matches;
this.rule = rule;}
FailedRule(IfThen rule, VarMatches matches, List satisfiedConditions, Exp remainingCondition) {
this.remainingCondition = remainingCondition;
this.satisfiedConditions = satisfiedConditions;
this.matches = matches;
this.rule = rule;}
}
static class RuleWithParams implements IFieldsToList{
static final String _fieldOrder = "rule matches";
IfThen rule;
VarMatches matches;
RuleWithParams() {}
RuleWithParams(IfThen rule, VarMatches matches) {
this.matches = matches;
this.rule = rule;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + rule + ", " + matches + ")"; }
public boolean equals(Object o) {
if (!(o instanceof RuleWithParams)) return false;
RuleWithParams __7 = (RuleWithParams) o;
return eq(rule, __7.rule) && eq(matches, __7.matches);
}
public int hashCode() {
int h = 1254104616;
h = boostHashCombine(h, _hashCode(rule));
h = boostHashCombine(h, _hashCode(matches));
return h;
}
public Object[] _fieldsToList() { return new Object[] {rule, matches}; }
String ruleID() { return rule.globalID; }
}
static class IfThen implements IFieldsToList{
static final String _fieldOrder = "in out globalID options originalText";
Exp in;
Exp out;
IfThen() {}
IfThen(Exp in, Exp out) {
this.out = out;
this.in = in;}
public boolean equals(Object o) {
if (!(o instanceof IfThen)) return false;
IfThen __8 = (IfThen) o;
return eq(in, __8.in) && eq(out, __8.out);
}
public int hashCode() {
int h = -2108234502;
h = boostHashCombine(h, _hashCode(in));
h = boostHashCombine(h, _hashCode(out));
return h;
}
public Object[] _fieldsToList() { return new Object[] {in, out}; }
String globalID;
Set options;
String originalText;
String text() {
Collection opt = options;
if (nempty(globalID)) opt = concatLists(ll("id: " + globalID), opt);
return (nempty(opt) ? "[" + joinWithComma(opt) + "] " : "")
+ (in == null ? "" : in.text() + "\n => ") + nlLogic_text(out);
}
public String toString() { return text(); }
}
abstract static class Exp {
abstract String text();
public String toString() { return text(); }
}
static class Func extends Exp implements IFieldsToList{
String name;
Exp arg;
Func() {}
Func(String name, Exp arg) {
this.arg = arg;
this.name = name;}
public boolean equals(Object o) {
if (!(o instanceof Func)) return false;
Func __0 = (Func) o;
return eq(name, __0.name) && eq(arg, __0.arg);
}
public int hashCode() {
int h = 2201316;
h = boostHashCombine(h, _hashCode(name));
h = boostHashCombine(h, _hashCode(arg));
return h;
}
public Object[] _fieldsToList() { return new Object[] {name, arg}; }
List options;
Func(String name, List options, Exp arg) {
this.arg = arg;
this.options = options;
this.name = name;}
String text() {
return name
+ (empty(options) ? "" : "[" + joinWithComma(options) + "]")
+ "(" + arg.text() + ")";
}
String argText() { return nlLogic_text(arg); }
}
static class And extends Exp implements IFieldsToList{
Exp a;
Exp b;
And() {}
And(Exp a, Exp b) {
this.b = b;
this.a = a;}
public boolean equals(Object o) {
if (!(o instanceof And)) return false;
And __1 = (And) o;
return eq(a, __1.a) && eq(b, __1.b);
}
public int hashCode() {
int h = 65975;
h = boostHashCombine(h, _hashCode(a));
h = boostHashCombine(h, _hashCode(b));
return h;
}
public Object[] _fieldsToList() { return new Object[] {a, b}; }
String text() {
return a.text() + "\n && " + b.text();
}
}
static class ExpNot extends Exp implements IFieldsToList{
Exp a;
ExpNot() {}
ExpNot(Exp a) {
this.a = a;}
public boolean equals(Object o) {
if (!(o instanceof ExpNot)) return false;
ExpNot __2 = (ExpNot) o;
return eq(a, __2.a);
}
public int hashCode() {
int h = 2089649046;
h = boostHashCombine(h, _hashCode(a));
return h;
}
public Object[] _fieldsToList() { return new Object[] {a}; }
String text() {
return "!" + a.text();
}
}
abstract static class Literal extends Exp {}
static class Sentence extends Literal implements IFieldsToList{
List tok;
Sentence() {}
Sentence(List tok) {
this.tok = tok;}
public boolean equals(Object o) {
if (!(o instanceof Sentence)) return false;
Sentence __3 = (Sentence) o;
return eq(tok, __3.tok);
}
public int hashCode() {
int h = 1327381123;
h = boostHashCombine(h, _hashCode(tok));
return h;
}
public Object[] _fieldsToList() { return new Object[] {tok}; }
String text() { return join(tok); } }
static class Sentence2 extends Literal implements IFieldsToList{
String text;
Sentence2() {}
Sentence2(String text) {
this.text = text;}
public boolean equals(Object o) {
if (!(o instanceof Sentence2)) return false;
Sentence2 __4 = (Sentence2) o;
return eq(text, __4.text);
}
public int hashCode() {
int h = -1800858097;
h = boostHashCombine(h, _hashCode(text));
return h;
}
public Object[] _fieldsToList() { return new Object[] {text}; }
String text() { return text; } }
static class Eq extends Exp implements IFieldsToList{
Exp left;
Exp right;
Eq() {}
Eq(Exp left, Exp right) {
this.right = right;
this.left = left;}
public boolean equals(Object o) {
if (!(o instanceof Eq)) return false;
Eq __5 = (Eq) o;
return eq(left, __5.left) && eq(right, __5.right);
}
public int hashCode() {
int h = 2252;
h = boostHashCombine(h, _hashCode(left));
h = boostHashCombine(h, _hashCode(right));
return h;
}
public Object[] _fieldsToList() { return new Object[] {left, right}; }
String text() {
return left.text() + " = " + right.text();
}
}
static class ImageSurface extends Surface {
BufferedImage image;
double zoomX = 1, zoomY = 1, zoomFactor = 1.5;
private Rectangle selection;
List tools = new ArrayList();
// use overlays now
Object overlay; // voidfunc(Graphics2D)
List overlays = syncL();
Runnable onSelectionChange;
static boolean verbose = false;
boolean noMinimumSize = true;
String titleForUpload;
Object onZoom;
boolean specialPurposed = false; // true = don't show image changing commands in popup menu
boolean zoomable = true;
boolean noAlpha = false; // set to true to speed up drawing if you don't use alpha
Object interpolationMode = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
Object onNewImage;
BufferedImage imageToDraw; // if you want to draw a different image
File file; // where image was loaded from
boolean autoZoomToDisplay = false; // only works 100% when not in scrollpane
final public ImageSurface setRepaintInThread(boolean repaintInThread){ return repaintInThread(repaintInThread); }
public ImageSurface repaintInThread(boolean repaintInThread) { this.repaintInThread = repaintInThread; return this; } final public boolean getRepaintInThread(){ return repaintInThread(); }
public boolean repaintInThread() { return repaintInThread; } boolean repaintInThread = false; // after setImage, repaint in same thread
BoolVar showingVar;
Pt mousePosition;
transient List onMousePositionChanged;
public ImageSurface onMousePositionChanged(Runnable r) { onMousePositionChanged = syncAddOrCreate(onMousePositionChanged, r); return this; }
public ImageSurface removeMousePositionChangedListener(Runnable r) { main.remove(onMousePositionChanged, r); return this; }
void mousePositionChanged() { pcallFAll(onMousePositionChanged); }
public ImageSurface() {
this(dummyImage());
}
static BufferedImage dummyImage() {
return new RGBImage(1, 1, new int[] { 0xFFFFFF }).getBufferedImage();
}
ImageSurface(MakesBufferedImage image) {
this(image != null ? image.getBufferedImage() : dummyImage());
}
ImageSurface(BufferedImage image) {
setImage(image);
clearSurface = false;
onResize(this, () -> performAutoZoom());
bindToComponent(this, () -> performAutoZoom(), null);
componentPopupMenu2(this, ImageSurface_popupMenuMaker());
new ImageSurfaceSelector(this);
jHandleFileDrop(this, new VF1() { public void get(File f) { try { setImage(loadBufferedImage(f)) ; } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "setImage(loadBufferedImage(f))"; }});
imageSurfaceOnHover(this, p -> {
mousePosition = p;
mousePositionChanged();
});
}
public ImageSurface(RGBImage image, double zoom) {
this(image);
setZoom(zoom);
}
// point is already in image coordinates
protected void fillPopupMenu(JPopupMenu menu, final Point point) {
if (zoomable) {
JMenuItem miZoomReset = new JMenuItem("Zoom 100%");
miZoomReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
setZoom(1.0);
centerPoint(point);
}
});
menu.add(miZoomReset);
JMenuItem miZoomIn = new JMenuItem("Zoom in");
miZoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomIn(zoomFactor);
centerPoint(point);
}
});
menu.add(miZoomIn);
JMenuItem miZoomOut = new JMenuItem("Zoom out");
miZoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomOut(zoomFactor);
centerPoint(point);
}
});
menu.add(miZoomOut);
/*JMenuItem miZoomToWindow = new JMenuItem("Zoom to window");
miZoomToWindow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
zoomToDisplaySize();
}
});
menu.add(miZoomToWindow);*/
menu.add(jCheckBoxMenuItem_dyn(/*"Auto-zoom to window"*/"Zoom to window",
() -> autoZoomToDisplay,
b -> { setAutoZoomToDisplay(b); }));
addMenuItem(menu, "Show full screen", new Runnable() { public void run() { try { showFullScreen() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showFullScreen()"; }});
addMenuItem(menu, "Point: " + point.x + "," + point.y + " (image: " + w() + "*" + h() + ")", null);
menu.addSeparator();
}
if (!specialPurposed)
addMenuItem(menu, "Load image...", new Runnable() { public void run() { try { selectFile("Load image",
new VF1() { public void get(File f) { try { setImage(loadImage2(f)) ; } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "setImage(loadImage2(f))"; }}) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "selectFile(\"Load image\",\r\n new VF1() { public void get(File f) c..."; }});
addMenuItem(menu, "Save image...", new Runnable() { public void run() { try { saveImage() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "saveImage()"; }});
addMenuItem(menu, "Upload image...", new Runnable() { public void run() { try { uploadTheImage() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uploadTheImage()"; }});
addMenuItem(menu, "Copy image to clipboard", new Runnable() { public void run() { try { copyImageToClipboard(getImage()) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyImageToClipboard(getImage())"; }});
if (!specialPurposed) {
addMenuItem(menu, "Paste image from clipboard", new Runnable() { public void run() { try { loadFromClipboard() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadFromClipboard()"; }});
addMenuItem(menu, "Load image snippet...", new Runnable() { public void run() { try {
selectImageSnippet(new VF1() { public void get(String imageID) { try {
setImage(loadImage2(imageID))
; } catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "setImage(loadImage2(imageID))"; }});
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "selectImageSnippet(new VF1() { public void get(String imageID) ctex {..."; }});
}
if (selection != null)
addMenuItem(menu, "Crop", new Runnable() { public void run() { try { crop() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "crop()"; }});
if (!specialPurposed)
addMenuItem(menu, "No image", new Runnable() { public void run() { try { noImage() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "noImage()"; }});
}
void noImage() { setImage((BufferedImage) null); }
void crop() {
if (selection == null) return;
BufferedImage img = cloneClipBufferedImage(getImage(), selection);
selection = null;
setImage(img);
}
void loadFromClipboard() {
BufferedImage img = getImageFromClipboard();
if (img != null)
setImage(img);
}
void saveImage() {
RGBImage image = new RGBImage(getImage(), null);
JFileChooser fileChooser = new JFileChooser(getProgramDir());
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
image.save(file = fileChooser.getSelectedFile());
} catch (IOException e) {
popup(e);
}
}
}
void drawImageItself(int w, int h, Graphics2D g) {
int iw = getZoomedWidth(), ih = getZoomedHeight();
if (interpolationMode == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR || zoomX >= 1 || zoomY >= 1)
g.drawImage(image, 0, 0, iw, ih, null);
else
g.drawImage(resizeImage(image, iw, ih), 0, 0, null); // smoother
}
public void render(int w, int h, Graphics2D g) {
if (verbose) _print("render");
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolationMode);
g.setColor(Color.white);
BufferedImage image = or(imageToDraw, this.image);
if (!hasImage())
g.fillRect(0, 0, w, h);
else {
boolean alpha = !noAlpha && hasTransparency(image);
if (alpha) g.fillRect(0, 0, w, h);
drawImageItself(w, h, g);
int iw = getZoomedWidth(), ih = getZoomedHeight();
if (!alpha) {
g.fillRect(iw, 0, w-iw, h);
g.fillRect(0, ih, iw, h-ih);
}
}
if (overlay != null) {
if (verbose) _print("render overlay");
pcallF(overlay, g);
}
for (var overlay : cloneList(overlays)) { try {
overlay.drawOn(g);
} catch (Throwable __e) { printStackTrace(__e); }}
if (selection != null) {
if (verbose) _print("render selection");
// drawRect is inclusive, selection is exclusive, so... whatever, tests show it's cool.
drawSelectionRect(g, selection, Color.green, Color.white);
}
}
public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white) {
drawSelectionRect(g, selection, green, white, zoomX, zoomY);
}
public void drawSelectionRect(Graphics2D g, Rectangle selection, Color green, Color white, double zoomX, double zoomY) {
g.setColor(green);
int top = (int) (selection.y * zoomY);
int bottom = (int) ((selection.y+selection.height) * zoomY);
int left = (int) (selection.x * zoomX);
int right = (int) ((selection.x+selection.width) * zoomX);
g.drawRect(left-1, top-1, right-left+1, bottom-top+1);
g.setColor(white);
g.drawRect(left - 2, top - 2, right - left + 3, bottom - top + 3);
}
public ImageSurface setZoom(double zoom) {
setZoom(zoom, zoom);
return this;
}
public void setZoom(double zoomX, double zoomY) {
autoZoomToDisplay = false;
setZoom_dontChangeAutoZoom(zoomX, zoomY);
}
public void setZoom_dontChangeAutoZoom(double zoomX) { setZoom_dontChangeAutoZoom(zoomX, zoomX); }
public void setZoom_dontChangeAutoZoom(double zoomX, double zoomY) {
if (this.zoomX == zoomX && this.zoomY == zoomY) return;
if (verbose) _print("Setting zoom");
this.zoomX = zoomX;
this.zoomY = zoomY;
revalidate();
repaint();
centerPoint(new Point(getImage().getWidth()/2, getImage().getHeight()/2));
pcallF(onZoom);
}
public Dimension getMinimumSize() {
if (metaGet("scaffolding") != null) scaffoldCalled(this, "getMinimumSize");
if (noMinimumSize) return new Dimension(1, 1);
int w = getZoomedWidth();
int h = getZoomedHeight();
Dimension min = super.getMinimumSize();
return printIfScaffoldingEnabled(this, new Dimension(Math.max(w, min.width), Math.max(h, min.height)));
}
int getZoomedHeight() {
return (int) (h() * zoomY);
}
int getZoomedWidth() {
return (int) (w() * zoomX);
}
boolean isShowing_quick() {
if (showingVar == null) { swing(() -> {
if (showingVar == null) showingVar = componentShowingVar(ImageSurface.this);
}); }
return showingVar.get();
}
public void setImageIfShowing_thisThread(MakesBufferedImage image) { setImageIfShowing_thisThread(toBufferedImage(image)); }
public void setImageIfShowing_thisThread(BufferedImage image) {
if (isShowing_quick())
setImage_thisThread(image);
}
public void setImage(MakesBufferedImage image) { swing(() -> {
setImage_thisThread(image);
}); }
public void setImage(BufferedImage img) { swing(() -> {
setImage_thisThread(img);
}); }
public void setImage_thisThread(MakesBufferedImage img) { setImage_thisThread(toBufferedImage(img)); }
public void setImage_thisThread(BufferedImage img) {
BufferedImage newImage = img != null ? img : dummyImage();
BufferedImage oldImage = image;
image = newImage;
boolean sameSize = !imagesHaveSameSize(oldImage, newImage);
if (!sameSize) {
if (verbose) _print("New image size");
revalidate(); // do we need this?
}
quickRepaint();
pcallF(onNewImage);
if (!sameSize && autoZoomToDisplay) zoomToDisplaySize();
}
void setImageAndZoomToDisplay(BufferedImage img) {
setImage(img);
zoomToDisplaySize();
}
public BufferedImage getImage() {
return image;
}
public double getZoomX() {
return zoomX;
}
public double getZoomY() {
return zoomY;
}
public Dimension getPreferredSize() {
if (metaGet("scaffolding") != null) scaffoldCalled(this, "getPreferredSize");
return printIfScaffoldingEnabled(this, new Dimension(getZoomedWidth(), getZoomedHeight()));
}
/** returns a scrollpane with the scroll-mode prevent-garbage-drawing fix applied */
public JScrollPane makeScrollPane() {
JScrollPane scrollPane = new JScrollPane(this);
scrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
return scrollPane;
}
public void zoomToWindow() { zoomToDisplaySize(); }
public void zoomToDisplaySize() { swing(() -> {
if (!hasImage()) return;
Dimension display = getDisplaySize();
if (display.width == 0 || display.height == 0) return;
int w = w(), h = h();
double xRatio = (display.width-5)/(double) w;
double yRatio = (display.height-5)/(double) h;
if (scaffoldingEnabled(this))
printVars("zoomToDisplaySize", "display", display, "w", w, "h", h, "xRatio", xRatio, "yRatio", yRatio);
setZoom_dontChangeAutoZoom(min(xRatio, yRatio));
revalidate();
}); }
/** tricky magic to get parent scroll pane */
private Dimension getDisplaySize() {
if (metaGet("scaffolding") != null) scaffoldCalled(this, "getDisplaySize");
Container c = getParent();
while (c != null) {
if (c instanceof JScrollPane)
return c.getSize();
c = c.getParent();
}
return getSize();
}
public void setSelection(Rect r) {
setSelection(toRectangle(r));
}
public void setSelection(Rectangle r) {
if (neq(selection, r)) {
selection = r;
pcallF(onSelectionChange);
quickRepaint();
}
}
public Rectangle getSelection() {
return selection;
}
public RGBImage getRGBImage() {
return new RGBImage(getImage());
}
// p is in image coordinates
void centerPoint(Point p) {
JScrollPane sp = enclosingScrollPane(this);
if (sp == null) return;
p = new Point((int) (p.x*getZoomX()), (int) (p.y*getZoomY()));
final JViewport viewport = sp.getViewport();
Dimension viewSize = viewport.getExtentSize();
//_print("centerPoint " + p);
int x = max(0, p.x-viewSize.width/2);
int y = max(0, p.y-viewSize.height/2);
//_print("centerPoint " + p + " => " + x + "/" + y);
p = new Point(x,y);
//_print("centerPoint " + p);
final Point _p = p;
awtLater(new Runnable() { public void run() { try {
viewport.setViewPosition(_p);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "viewport.setViewPosition(_p);"; }});
}
Pt pointFromEvent(MouseEvent e) {
return pointFromComponentCoordinates(new Pt(e.getX(), e.getY()));
}
Pt pointFromComponentCoordinates(Pt p) {
return new Pt((int) (p.x/zoomX), (int) (p.y/zoomY));
}
Pt pointToComponentCoordinates(double x, double y) {
return new Pt((int) (x*zoomX), (int) (y*zoomY));
}
void uploadTheImage() {
call(hotwire(/*#1007313*/"#1016427"), "go", getImage(), titleForUpload);
}
void showFullScreen() {
showFullScreenImageSurface(getImage());
}
void zoomIn(double f) { setZoom(getZoomX()*f, getZoomY()*f); }
void zoomOut(double f) { setZoom(getZoomX()/f, getZoomY()/f); }
ImageSurface setFile(File f) { file = f; return this; }
void setOverlay(IVF1 overlay) {
this.overlay = overlay;
}
boolean hasImage() { return image != null; }
int w() { return image.getWidth(); }
int h() { return image.getHeight(); }
void setPixelated(boolean b) {
assertTrue(b);
imageSurface_pixelated(this);
}
ImageSurface setAutoZoomToDisplay(boolean b) {
if (autoZoomToDisplay = b)
zoomToDisplaySize();
return this;
}
void quickRepaint() {
if (repaintInThread)
paintImmediately(0, 0, getWidth(), getHeight());
else
repaint();
}
void removeTool(AutoCloseable tool) { swing(() -> {
if (tools.contains(tool)) {
close(tool);
tools.remove(tool);
}
}); }
void removeAllTools() {
closeAllAndClear(tools);
}
void performAutoZoom() {
if (autoZoomToDisplay) zoomToDisplaySize();
}
} // end of ImageSurface
// static function allows garbage collection
static VF2 ImageSurface_popupMenuMaker() {
return new VF2() { public void get(ImageSurface is, JPopupMenu menu) { try {
Point p = is.pointFromEvent(componentPopupMenu_mouseEvent.get()).getPoint();
is.fillPopupMenu(menu, p);
} catch (Exception __e) { throw rethrow(__e); } }
public String toString() { return "Point p = is.pointFromEvent(componentPopupMenu_mouseEvent.get()).getPoint();\r..."; }};
}
static class CombinedStringifier implements IStringifier {
CopyOnWriteArrayList> stringifiers = new CopyOnWriteArrayList();
IStringifier defaultStringifier = new Stringifier_ToString();
CombinedStringifier(IPartialStringifier ... stringifiers) {
addAll(this.stringifiers, stringifiers);
}
public String toString(A o) {
for (var stringifier : stringifiers) {
String s = stringifier.toStringOpt(o);
if (s != null) return s;
}
return defaultStringifier.toString(o);
}
public String toString() {
return formatFunctionCall("CombinedStringifier",
listPlus((List) stringifiers, defaultStringifier)
);
}
}
static class Timestamp implements Comparable , IFieldsToList{
long date;
Timestamp(long date) {
this.date = date;}
public boolean equals(Object o) {
if (!(o instanceof Timestamp)) return false;
Timestamp __1 = (Timestamp) o;
return date == __1.date;
}
public int hashCode() {
int h = 2059094262;
h = boostHashCombine(h, _hashCode(date));
return h;
}
public Object[] _fieldsToList() { return new Object[] {date}; }
Timestamp() { date = now(); }
long unixDate() { return date; }
public String toString() { return formatLocalDateWithSeconds(date); }
// Hmm. Should Timestamp(0) be equal to null? Question, questions...
public int compareTo(Timestamp t) {
return t == null ? 1 : cmp(date, t.date);
}
Timestamp plus(Seconds seconds) {
return plus(seconds == null ? null : seconds.getDouble());
}
final Timestamp plusSeconds(double seconds){ return plus(seconds); }
Timestamp plus(double seconds) {
return new Timestamp(date+toMS(seconds));
}
// returns milliseconds
long minus(Timestamp ts) {
return unixDate()-ts.unixDate();
}
long sysTime() {
return clockTimeToSystemTime(date);
}
}
static interface MakesBufferedImage extends WidthAndHeight {
BufferedImage getBufferedImage();
public default void drawAt(Graphics2D g, int x, int y) {
g.drawImage(getBufferedImage(), x, y, null);
}
}
abstract static class Sleeping implements AutoCloseable , IFieldsToList{
Timestamp targetTime;
Runnable action;
Sleeping() {}
Sleeping(Timestamp targetTime, Runnable action) {
this.action = action;
this.targetTime = targetTime;}
public String toString() { return shortClassName_dropNumberPrefix(this) + "(" + targetTime + ", " + action + ")"; }public Object[] _fieldsToList() { return new Object[] {targetTime, action}; }
long remainingMS() { return targetTime.minus(tsNow()); }
}
// AppendableChain has one "smart" head element (with size counter
// and pointer to the chain's last element), all the other nodes are
// maximally simple (MinimalChain).
// This allows O(1) front insertion, front removal and back insertion
// (not removal at the back though) which is fine for what I need this
// for (event queues).
//
// Stefan Reich, Oct 21
static class AppendableChain extends MinimalChain implements Iterable {
MinimalChain last; // pointer to last element in chain (which may be us)
int size; // total length of chain
AppendableChain() {} // only used internally
AppendableChain(A element) {
this.element = element; size = 1; last = this; }
// intermediate constructor called by itemPlusChain()
AppendableChain(A element, AppendableChain next) {
this.next = next;
this.element = element;
if (next == null) return;
MinimalChain b = new MinimalChain();
b.element = next.element;
b.next = next.next;
this.next = b;
last = next.last;
size = next.size+1;
}
public String toString() { return str(toList()); }
// append at the end
boolean add(A a) {
MinimalChain newLast = new MinimalChain(a);
last.next = newLast;
last = newLast;
++size;
return true;
}
// drop first element
AppendableChain popFirst() {
if (next == null) return null;
element = next.element;
if (last == next) last = this;
next = next.next;
--size;
return this;
}
ArrayList toList() {
ArrayList l = emptyList(size);
MinimalChain c = this;
while (c != null) {
l.add(c.element);
c = c.next;
}
return l;
}
//public Iterator iterator() { ret toList().iterator(); }
class ACIt extends IterableIterator < A > {
MinimalChain c = AppendableChain.this;
public boolean hasNext() {
return c != null;
}
public A next() {
var a = c.element;
c = c.next;
return a;
}
}
public IterableIterator iterator() {
return new ACIt();
}
}
static class MultiSleeper extends RestartableCountdown implements ISleeper_v2 {
TreeMultiMap entries = new TreeMultiMap();
void check() {
var time = nextWakeUpTime();
var action = firstValue(entries);
setTargetTime(time == null ? 0 : time.sysTime(), new Runnable() { public void run() { try {
List toCall;
synchronized(MultiSleeper.this) {
toCall = entries.get(time);
entries.remove(time);
}
check();
pcallFAll(toCall);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "List toCall;\r\n synchronized(MultiSleeper.this) {\r\n toCa..."; }});
}
synchronized void removeEntry(Timestamp targetTime, Runnable action) {
entries.remove(targetTime, action);
}
// API
synchronized Timestamp nextWakeUpTime() {
return firstKey(entries);
}
public synchronized Sleeping doLater(Timestamp targetTime, Runnable r) {
if (r == null || targetTime == null) return null;
targetTime = max(targetTime, tsNow());
entries.put(targetTime, r);
check();
return new Sleeping(targetTime, r) {
public void close() { try {
removeEntry(targetTime, r);
} catch (Exception __e) { throw rethrow(__e); } }
};
}
}
static class ImageSurface_PositionToolTip extends ImageSurfaceMouseHandler {
ImageSurface_PositionToolTip(ImageSurface is) {
if (containsInstance(is.tools, ImageSurface_PositionToolTip.class)) return;
register(is);
}
final public void mouseDragged(MouseEvent e){ mouseMoved(e); }
public void mouseMoved(MouseEvent e) {
setToolTip(is, getPt(e));
}
}
static class ListAndIndex implements IFieldsToList{
static final String _fieldOrder = "list idx";
List list;
int idx;
ListAndIndex() {}
ListAndIndex(List list, int idx) {
this.idx = idx;
this.list = list;}
public boolean equals(Object o) {
if (!(o instanceof ListAndIndex)) return false;
ListAndIndex __1 = (ListAndIndex) o;
return eq(list, __1.list) && idx == __1.idx;
}
public int hashCode() {
int h = 276903961;
h = boostHashCombine(h, _hashCode(list));
h = boostHashCombine(h, _hashCode(idx));
return h;
}
public Object[] _fieldsToList() { return new Object[] {list, idx}; }
boolean atEnd() { return idx >= l(list); }
A get() { return _get(list, idx); }
int size() { return l(list); }
public String toString() {
return subList(list, 0, idx) + ", then " + subList(list, idx);
}
ListAndIndex plus(int ofs) { return new ListAndIndex(list, idx+ofs); }
List list() { return list; }
final int idx(){ return index(); }
int index() { return idx; }
}
static class SynchronizedList
extends SynchronizedCollection
implements List {
SynchronizedList() {}
/*final*/ List list;
SynchronizedList(List