import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
import x30_pkg.x30_util;
import static x30_pkg.x30_util.VF1;
import static x30_pkg.x30_util.l;
import static x30_pkg.x30_util.fail;
import static x30_pkg.x30_util.indexOf;
import static x30_pkg.x30_util.getOpt;
import static x30_pkg.x30_util.setOpt;
import static x30_pkg.x30_util.callOpt;
import static x30_pkg.x30_util.newWeakHashMap;
import static x30_pkg.x30_util.newDangerousWeakHashMap;
import static x30_pkg.x30_util.get;
import static x30_pkg.x30_util.get_raw;
import static x30_pkg.x30_util.assertTrue;
import static x30_pkg.x30_util.isHeadless;
import static x30_pkg.x30_util.isAndroid;
import static x30_pkg.x30_util.isTrue;
import static x30_pkg.x30_util.asList;
import x30_pkg.x30_util.DynamicObject;
import loadableUtils.utils;
import static loadableUtils.utils._threadInfo;
import static loadableUtils.utils._threadInheritInfo;
import static loadableUtils.utils._threadInfo_addMakerAndRetriever;
import static loadableUtils.utils.dm_currentModule;
import static loadableUtils.utils.dm_current_mandatory;
import static loadableUtils.utils.match;
import static loadableUtils.utils.getOpt_raw;
import static loadableUtils.utils.setOpt_raw;
import static loadableUtils.utils.getField;
import static loadableUtils.utils.fieldType;
import static loadableUtils.utils.format3;
import static loadableUtils.utils.vm_generalIdentityHashSet;
import static loadableUtils.utils.vm_generalHashMap;
import static loadableUtils.utils.vm_generalWeakSubMap;
import static loadableUtils.utils.bindToComponent;
import static loadableUtils.utils.struct;
import static loadableUtils.utils.structure;
import static loadableUtils.utils.loadPage;
import static loadableUtils.utils.loadPage_utf8;
import static loadableUtils.utils.loadPageSilentlyWithTimeout;
import static loadableUtils.utils.loadPageSilently;
import static loadableUtils.utils.loadSnippet;
import static loadableUtils.utils.loadSnippetQuietly;
import static loadableUtils.utils.sendToLocalBot;
import static loadableUtils.utils.componentPopupMenu;
import static loadableUtils.utils.componentPopupMenu_top;
import static loadableUtils.utils.componentPopupMenu_getEvent;
import static loadableUtils.utils.componentPopupMenu_initForComponent;
import static loadableUtils.utils.listPopupMenu;
import static loadableUtils.utils.tablePopupMenu;
import static loadableUtils.utils.sexyTableWithoutDrag;
import static loadableUtils.utils.dm_current_generic;
import static loadableUtils.utils.dm_current_mandatory_generic;
import static loadableUtils.utils.cset;
import static loadableUtils.utils.DynamicObject_loading;
import static loadableUtils.utils.concepts_unlisted;
import static loadableUtils.utils.makePopupMenuConditional;
import static loadableUtils.utils.makeConceptsTable_idWidth;
import static loadableUtils.utils.showConceptsTable_afterUpdate;
import static loadableUtils.utils.dynamicObjectIsLoading;
import loadableUtils.utils.F0;
import loadableUtils.utils.F1;
import loadableUtils.utils.IF1;
import loadableUtils.utils.Matches;
import loadableUtils.utils.BetterLabel;
import loadableUtils.utils.SingleComponentPanel;
import loadableUtils.utils.Snippet;
import loadableUtils.utils.Q;
import loadableUtils.utils.ImageSurface;
import loadableUtils.utils.structure_Data;
import loadableUtils.utils.RGBImage;
import loadableUtils.utils.RGB;
import loadableUtils.utils.BWImage;
import loadableUtils.utils.MakesBufferedImage;
import loadableUtils.utils.Concept;
import loadableUtils.utils.Concepts;
import loadableUtils.utils.IConceptIndex;
import loadableUtils.utils.IFieldIndex;
import loadableUtils.utils.Derefable;
import loadableUtils.utils.ImageSurfaceSelector;
import loadableUtils.utils.SimpleCRUD;
import loadableUtils.utils.PersistableThrowable;
import loadableUtils.utils.DynModule;
import loadableUtils.utils.DynPrintLog;
import loadableUtils.utils.DynObjectTable;
import loadableUtils.utils.DynImageSurface;
import loadableUtils.utils.DynCalculatedList;
import loadableUtils.utils.Rect;
import loadableUtils.utils.Pt;

class main {

  public static class Entry {

    public static String _fieldOrder = "text annotation";

    public String text;

    public String annotation;

    public Entry() {
    }

    public Entry(String text, String annotation) {
      this.annotation = annotation;
      this.text = text;
    }

    public String toString() {
      return "Entry(" + text + ", " + annotation + ")";
    }

    public boolean equals(Object o) {
      if (!(o instanceof Entry))
        return false;
      Entry x = (Entry) o;
      return eq(text, x.text) && eq(annotation, x.annotation);
    }

    public int hashCode() {
      int h = 67115090;
      h = h * 2 + _hashCode(text);
      h = h * 2 + _hashCode(annotation);
      return h;
    }
  }

  public static class QuickAnnotator extends DynObjectTable<Entry> {

    public void start() {
      super.start();
      addCountToName();
    }

    public void fillData(Collection<Pair<String, String>> l) {
      setList(map(l, p -> nu(Entry.class, "text", p.a, "annotation", p.b)));
    }

    public void fillData(Map<String, String> map) {
      fillData(mapToPairs(map));
    }

    public void setItems(Collection<String> l) {
      fillData(map(l, s -> pair(s, "")));
    }
  }

  public static boolean _moduleClass_QuickAnnotator;

  public static Object callF(Object f, Object... args) {
    try {
      if (f instanceof String)
        return callMC((String) f, args);
      return x30_util.callF(f, args);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static <A> A callF(F0<A> f) {
    return f == null ? null : f.get();
  }

  public static <A, B> B callF(F1<A, B> f, A a) {
    return f == null ? null : f.get(a);
  }

  public static <A, B> B callF(IF1<A, B> f, A a) {
    return f == null ? null : f.get(a);
  }

  public static <A> void callF(VF1<A> f, A a) {
    if (f != null)
      f.get(a);
  }

  public static Object callMC(String method, Object... args) {
    return call(mc(), method, args);
  }

  public static Object call(Object o) {
    return callF(o);
  }

  public static Object call(Object o, String method, Object... args) {
    return call_withVarargs(o, method, args);
  }

  public static void _onLoad_initUtils() {
    utils.__javax = javax();
  }

  public static void _onLoad_defaultClassFinder() {
    setDefaultClassFinder(new F1<String, Class>() {

      public Class get(String name) {
        try {
          Class c = findClass_fullName(name);
          if (c != null)
            return c;
          if (startsWith(name, "main$"))
            return loadableUtils.utils.findClass_fullName("loadableUtils.utils" + substring(name, 4));
          return null;
        } catch (Exception __e) {
          throw rethrow(__e);
        }
      }

      public String toString() {
        return "Class c = findClass_fullName(name);\r\n    if (c != null) ret c;\r\n    if (start...";
      }
    });
  }

  public static String programID() {
    return getProgramID();
  }

  public static String programID(Object o) {
    return getProgramID(o);
  }

  public static volatile StringBuffer local_log = new StringBuffer();

  public static volatile Appendable print_log = local_log;

  public static volatile int print_log_max = 1024 * 1024;

  public static volatile int local_log_max = 100 * 1024;

  public static boolean print_silent;

  public static Object print_byThread_lock = new Object();

  public static volatile ThreadLocal<Object> print_byThread;

  public static volatile Object print_allThreads;

  public static volatile Object print_preprocess;

  public static void print() {
    print("");
  }

  public static <A> A print(String s, A o) {
    print((endsWithLetterOrDigit(s) ? s + ": " : s) + o);
    return o;
  }

  public static <A> A print(A o) {
    ping_okInCleanUp();
    if (print_silent)
      return o;
    String s = String.valueOf(o) + "\n";
    print_noNewLine(s);
    return o;
  }

  public static void print_noNewLine(String s) {
    Object f = getThreadLocal(print_byThread_dontCreate());
    if (f == null)
      f = print_allThreads;
    if (f != null)
      if (isFalse(f instanceof F1 ? ((F1) f).get(s) : callF(f, s)))
        return;
    print_raw(s);
  }

  public static void print_raw(String s) {
    if (print_preprocess != null)
      s = (String) callF(print_preprocess, s);
    s = fixNewLines(s);
    Appendable loc = local_log;
    Appendable buf = print_log;
    int loc_max = print_log_max;
    if (buf != loc && buf != null) {
      print_append(buf, s, print_log_max);
      loc_max = local_log_max;
    }
    if (loc != null)
      print_append(loc, s, loc_max);
    System.out.print(s);
  }

  public static AutoCloseable tempInterceptPrintIfNotIntercepted(F1<String, Boolean> f) {
    return print_byThread().get() == null ? tempInterceptPrint(f) : null;
  }

  public static boolean eq(Object a, Object b) {
    return a == null ? b == null : a == b || b != null && a.equals(b);
  }

  public static int _hashCode(Object a) {
    return a == null ? 0 : a.hashCode();
  }

  public static List map(Iterable l, Object f) {
    return map(f, l);
  }

  public static List map(Object f, Iterable l) {
    List x = emptyList(l);
    if (l != null)
      for (Object o : l) x.add(callF(f, o));
    return x;
  }

  public static <A, B> List<B> map(Iterable<A> l, F1<A, B> f) {
    return map(f, l);
  }

  public static <A, B> List<B> map(F1<A, B> f, Iterable<A> l) {
    List x = emptyList(l);
    if (l != null)
      for (A o : l) x.add(callF(f, o));
    return x;
  }

  public static <A, B> List<B> map(IF1<A, B> f, Iterable<A> l) {
    return map(l, f);
  }

  public static <A, B> List<B> map(Iterable<A> l, IF1<A, B> f) {
    List x = emptyList(l);
    if (l != null)
      for (A o : l) x.add(f.get(o));
    return x;
  }

  public static <A, B> List<B> map(IF1<A, B> f, A[] l) {
    return map(l, f);
  }

  public static <A, B> List<B> map(A[] l, IF1<A, B> f) {
    List x = emptyList(l);
    if (l != null)
      for (A o : l) x.add(f.get(o));
    return x;
  }

  public static List map(Object f, Object[] l) {
    return map(f, asList(l));
  }

  public static List map(Object[] l, Object f) {
    return map(f, l);
  }

  public static List map(Object f, Map map) {
    return map(map, f);
  }

  public static List map(Map map, Object f) {
    List x = new ArrayList();
    if (map != null)
      for (Object _e : map.entrySet()) {
        Map.Entry e = (Map.Entry) _e;
        x.add(callF(f, e.getKey(), e.getValue()));
      }
    return x;
  }

  public static <A> A nu(Class<A> c, Object... values) {
    A a = nuObject(c);
    setAll(a, values);
    return a;
  }

  public static <A, B> List<Pair<A, B>> mapToPairs(Map<A, B> map) {
    List<Pair<A, B>> l = new ArrayList();
    if (map != null)
      for (Map.Entry<A, B> e : map.entrySet()) l.add(pair(e.getKey(), e.getValue()));
    return l;
  }

  public static <A, B> Pair<A, B> pair(A a, B b) {
    return new Pair(a, b);
  }

  public static <A> Pair<A, A> pair(A a) {
    return new Pair(a, a);
  }

  public static RuntimeException rethrow(Throwable t) {
    if (t instanceof Error)
      _handleError((Error) t);
    throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
  }

  public static RuntimeException rethrow(String msg, Throwable t) {
    throw new RuntimeException(msg, t);
  }

  public static Class mc() {
    return main.class;
  }

  public 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);
        List<Method> 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);
        List<Method> methods = cache.cache.get(method);
        if (methods != null)
          methodSearch: for (Method m : methods) {
            {
              if (!(m.isVarArgs()))
                continue;
            }
            Object[] newArgs = massageArgsForVarArgsCall(m, args);
            if (newArgs != null)
              return invokeMethod(m, o, newArgs);
          }
        throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found in " + c);
      }
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static Class javax() {
    return getJavaX();
  }

  public static void setDefaultClassFinder(Object cf) {
    _defaultClassFinder_value = cf;
  }

  public static HashMap<String, Class> findClass_fullName_cache = new HashMap();

  public static Class findClass_fullName(String name) {
    synchronized (findClass_fullName_cache) {
      if (findClass_fullName_cache.containsKey(name))
        return findClass_fullName_cache.get(name);
      Class c;
      try {
        c = Class.forName(name);
      } catch (ClassNotFoundException e) {
        c = null;
      }
      findClass_fullName_cache.put(name, c);
      return c;
    }
  }

  public static boolean startsWith(String a, String b) {
    return a != null && a.startsWith(b);
  }

  public static boolean startsWith(String a, char c) {
    return nemptyString(a) && a.charAt(0) == c;
  }

  public static boolean startsWith(String a, String b, Matches m) {
    if (!startsWith(a, b))
      return false;
    m.m = new String[] { substring(a, strL(b)) };
    return true;
  }

  public 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;
  }

  public static String substring(String s, int x) {
    return substring(s, x, strL(s));
  }

  public static String substring(String s, int x, int y) {
    if (s == null)
      return null;
    if (x < 0)
      x = 0;
    if (x >= s.length())
      return "";
    if (y < x)
      y = x;
    if (y > s.length())
      y = s.length();
    return s.substring(x, y);
  }

  public static Object _defaultClassFinder_value = defaultDefaultClassFinder();

  public static Object _defaultClassFinder() {
    return _defaultClassFinder_value;
  }

  public static String programID;

  public static String getProgramID() {
    return nempty(programID) ? formatSnippetIDOpt(programID) : "?";
  }

  public static String getProgramID(Class c) {
    String id = (String) getOpt(c, "programID");
    if (nempty(id))
      return formatSnippetID(id);
    return "?";
  }

  public static String getProgramID(Object o) {
    return getProgramID(getMainClass(o));
  }

  public static boolean endsWithLetterOrDigit(String s) {
    return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length() - 1));
  }

  public static void ping_okInCleanUp() {
    if (ping_pauseAll || ping_anyActions)
      ping_impl(true);
  }

  public static Object getThreadLocal(Object o, String name) {
    ThreadLocal t = (ThreadLocal) (getOpt(o, name));
    return t != null ? t.get() : null;
  }

  public static <A> A getThreadLocal(ThreadLocal<A> tl) {
    return tl == null ? null : tl.get();
  }

  public static <A> A getThreadLocal(ThreadLocal<A> tl, A defaultValue) {
    return or(getThreadLocal(tl), defaultValue);
  }

  public static ThreadLocal<Object> print_byThread_dontCreate() {
    return print_byThread;
  }

  public static boolean isFalse(Object o) {
    return eq(false, o);
  }

  public static String fixNewLines(String s) {
    int i = indexOf(s, '\r');
    if (i < 0)
      return s;
    int l = s.length();
    StringBuilder out = new StringBuilder(l);
    out.append(s, 0, i);
    for (; i < l; i++) {
      char c = s.charAt(i);
      if (c != '\r')
        out.append(c);
      else {
        out.append('\n');
        if (i + 1 < l && s.charAt(i + 1) == '\n')
          ++i;
      }
    }
    return out.toString();
  }

  public static void print_append(Appendable _buf, String s, int max) {
    try {
      synchronized (_buf) {
        _buf.append(s);
        if (!(_buf instanceof StringBuilder))
          return;
        StringBuilder buf = (StringBuilder) _buf;
        max /= 2;
        if (buf.length() > max)
          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);
          }
      }
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static ThreadLocal<Object> print_byThread() {
    synchronized (print_byThread_lock) {
      if (print_byThread == null)
        print_byThread = new ThreadLocal();
    }
    return print_byThread;
  }

  public static AutoCloseable tempInterceptPrint(F1<String, Boolean> f) {
    return tempSetThreadLocal(print_byThread(), f);
  }

  public static String str(Object o) {
    return o == null ? "null" : o.toString();
  }

  public static String str(char[] c) {
    return new String(c);
  }

  public static ArrayList emptyList() {
    return new ArrayList();
  }

  public static ArrayList emptyList(int capacity) {
    return new ArrayList(max(0, capacity));
  }

  public static ArrayList emptyList(Iterable l) {
    return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
  }

  public static ArrayList emptyList(Object[] l) {
    return emptyList(l(l));
  }

  public static <A> ArrayList<A> emptyList(Class<A> c) {
    return new ArrayList();
  }

  public static Object nuObject(String className, Object... args) {
    try {
      return nuObject(classForName(className), args);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static <A> A nuObject(Class<A> c, Object... args) {
    try {
      if (args.length == 0)
        return nuObjectWithoutArguments(c);
      Constructor m = nuObject_findConstructor(c, args);
      m.setAccessible(true);
      return (A) m.newInstance(args);
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static Constructor nuObject_findConstructor(Class c, Object... args) {
    for (Constructor m : c.getDeclaredConstructors()) {
      if (!nuObject_checkArgs(m.getParameterTypes(), args, false))
        continue;
      return m;
    }
    throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : ""));
  }

  public static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) {
    if (types.length != args.length) {
      if (debug)
        System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
      return false;
    }
    for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
      if (debug)
        System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
      return false;
    }
    return true;
  }

  public static <A> A setAll(A o, Map<String, Object> fields) {
    if (fields == null)
      return o;
    for (String field : keys(fields)) set(o, field, fields.get(field));
    return o;
  }

  public static <A> A setAll(A o, Object... values) {
    failIfOddCount(values);
    for (int i = 0; i + 1 < l(values); i += 2) {
      String field = (String) values[i];
      Object value = values[i + 1];
      set(o, field, value);
    }
    return o;
  }

  public static void _handleError(Error e) {
    call(javax(), "_handleError", e);
  }

  public static final Map<Class, _MethodCache> callOpt_cache = newDangerousWeakHashMap();

  public 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);
        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);
    }
  }

  public static _MethodCache callOpt_getCache(Class c) {
    synchronized (callOpt_cache) {
      _MethodCache cache = callOpt_cache.get(c);
      if (cache == null)
        callOpt_cache.put(c, cache = new _MethodCache(c));
      return cache;
    }
  }

  public 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);
    }
  }

  public static boolean isStaticMethod(Method m) {
    return methodIsStatic(m);
  }

  public 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;
  }

  public static <A> String joinWithComma(Collection<A> c) {
    return join(", ", c);
  }

  public static String joinWithComma(String... c) {
    return join(", ", c);
  }

  public static String joinWithComma(Pair p) {
    return p == null ? "" : joinWithComma(str(p.a), str(p.b));
  }

  public static List<String> classNames(Collection l) {
    return getClassNames(l);
  }

  public static List<String> classNames(Object[] l) {
    return getClassNames(Arrays.asList(l));
  }

  public static Class __javax;

  public static Class getJavaX() {
    try {
      return __javax;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static boolean nemptyString(String s) {
    return s != null && s.length() > 0;
  }

  public static int strL(String s) {
    return s == null ? 0 : s.length();
  }

  public static int listL(Collection l) {
    return l == null ? 0 : l.size();
  }

  public static boolean neq(Object a, Object b) {
    return !eq(a, b);
  }

  public static Object defaultDefaultClassFinder() {
    return new F1<String, Class>() {

      public Class get(String name) {
        try {
          Class c = findClass_fullName(name);
          if (c != null)
            return c;
          if (startsWith(name, "loadableUtils.utils$"))
            return findClass_fullName("main" + substring(name, 19));
          return null;
        } catch (Exception __e) {
          throw rethrow(__e);
        }
      }

      public String toString() {
        return "Class c = findClass_fullName(name);\r\n    if (c != null) ret c;\r\n    if (start...";
      }
    };
  }

  public static boolean nempty(Collection c) {
    return !empty(c);
  }

  public static boolean nempty(CharSequence s) {
    return !empty(s);
  }

  public static boolean nempty(Object[] o) {
    return !empty(o);
  }

  public static boolean nempty(byte[] o) {
    return !empty(o);
  }

  public static boolean nempty(int[] o) {
    return !empty(o);
  }

  public static boolean nempty(Map m) {
    return !empty(m);
  }

  public static boolean nempty(Iterator i) {
    return i != null && i.hasNext();
  }

  public static boolean nempty(Object o) {
    return !empty(o);
  }

  public static String formatSnippetIDOpt(String s) {
    return isSnippetID(s) ? formatSnippetID(s) : s;
  }

  public static String formatSnippetID(String id) {
    return "#" + parseSnippetID(id);
  }

  public static String formatSnippetID(long id) {
    return "#" + id;
  }

  public static Class getMainClass() {
    return mc();
  }

  public static Class getMainClass(Object o) {
    try {
      if (o == null)
        return null;
      if (o instanceof Class && eq(((Class) o).getName(), "x30"))
        return (Class) o;
      return (o instanceof Class ? (Class) o : o.getClass()).getClassLoader().loadClass("main");
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static volatile boolean ping_pauseAll;

  public static int ping_sleep = 100;

  public static volatile boolean ping_anyActions;

  public static Map<Thread, Object> ping_actions = newWeakHashMap();

  public static ThreadLocal<Boolean> ping_isCleanUpThread = new ThreadLocal();

  public static boolean ping() {
    if (ping_pauseAll || ping_anyActions)
      ping_impl(true);
    return true;
  }

  public static boolean ping_impl(boolean okInCleanUp) {
    try {
      if (ping_pauseAll && !isAWTThread()) {
        do Thread.sleep(ping_sleep); while (ping_pauseAll);
        return true;
      }
      if (ping_anyActions) {
        if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get()))
          failIfUnlicensed();
        Object action = null;
        synchronized (ping_actions) {
          if (!ping_actions.isEmpty()) {
            action = ping_actions.get(currentThread());
            if (action instanceof Runnable)
              ping_actions.remove(currentThread());
            if (ping_actions.isEmpty())
              ping_anyActions = false;
          }
        }
        if (action instanceof Runnable)
          ((Runnable) action).run();
        else if (eq(action, "cancelled"))
          throw fail("Thread cancelled.");
      }
      return false;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static <A> A or(A a, A b) {
    return a != null ? a : b;
  }

  public static <A> AutoCloseable tempSetThreadLocal(final ThreadLocal<A> 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);
      }
    };
  }

  public static int max(int a, int b) {
    return Math.max(a, b);
  }

  public static int max(int a, int b, int c) {
    return max(max(a, b), c);
  }

  public static long max(int a, long b) {
    return Math.max((long) a, b);
  }

  public static long max(long a, long b) {
    return Math.max(a, b);
  }

  public static double max(int a, double b) {
    return Math.max((double) a, b);
  }

  public static float max(float a, float b) {
    return Math.max(a, b);
  }

  public static double max(double a, double b) {
    return Math.max(a, b);
  }

  public static int max(Collection<Integer> c) {
    int x = Integer.MIN_VALUE;
    for (int i : c) x = max(x, i);
    return x;
  }

  public 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;
  }

  public 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;
  }

  public static byte max(byte[] c) {
    byte x = -128;
    for (byte d : c) if (d > x)
      x = d;
    return x;
  }

  public static short max(short[] c) {
    short x = -0x8000;
    for (short d : c) if (d > x)
      x = d;
    return x;
  }

  public static int max(int[] c) {
    int x = Integer.MIN_VALUE;
    for (int d : c) if (d > x)
      x = d;
    return x;
  }

  public static Map<String, Class> classForName_cache = synchroHashMap();

  public static Class classForName(String name) {
    try {
      if (classForName_cache == null)
        return Class.forName(name);
      Class c = classForName_cache.get(name);
      if (c == null)
        classForName_cache.put(name, c = Class.forName(name));
      return c;
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static Map<Class, Constructor> nuObjectWithoutArguments_cache = newDangerousWeakHashMap();

  public static Object nuObjectWithoutArguments(String className) {
    try {
      return nuObjectWithoutArguments(classForName(className));
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static <A> A nuObjectWithoutArguments(Class<A> c) {
    try {
      if (nuObjectWithoutArguments_cache == null)
        return (A) nuObjectWithoutArguments_findConstructor(c).newInstance();
      Constructor m = nuObjectWithoutArguments_cache.get(c);
      if (m == null)
        nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c));
      return (A) m.newInstance();
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static Constructor nuObjectWithoutArguments_findConstructor(Class c) {
    for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) {
      m.setAccessible(true);
      return m;
    }
    throw fail("No default constructor found in " + c.getName());
  }

  public static List<Class> getClasses(Object[] array) {
    List<Class> l = new ArrayList();
    for (Object o : array) l.add(_getClass(o));
    return l;
  }

  public 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);
  }

  public static <A, B> Set<A> keys(Map<A, B> map) {
    return map == null ? new HashSet() : map.keySet();
  }

  public static Set keys(Object map) {
    return keys((Map) map);
  }

  public static <A> A set(A o, String field, Object value) {
    if (o == null)
      return null;
    if (o instanceof Class)
      set((Class) o, field, value);
    else
      try {
        Field f = set_findField(o.getClass(), field);
        f.setAccessible(true);
        smartSet(f, o, value);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    return o;
  }

  public static void set(Class c, String field, Object value) {
    if (c == null)
      return;
    try {
      Field f = set_findStaticField(c, field);
      f.setAccessible(true);
      smartSet(f, null, value);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static Field set_findStaticField(Class<?> c, String field) {
    Class _c = c;
    do {
      for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
        return f;
      _c = _c.getSuperclass();
    } while (_c != null);
    throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
  }

  public static Field set_findField(Class<?> c, String field) {
    Class _c = c;
    do {
      for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field))
        return f;
      _c = _c.getSuperclass();
    } while (_c != null);
    throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
  }

  public static void failIfOddCount(Object... list) {
    if (odd(l(list)))
      throw fail("Odd list size: " + list);
  }

  public static Throwable getExceptionCause(Throwable e) {
    Throwable c = e.getCause();
    return c != null ? c : e;
  }

  public static String joinWithSpace(Collection<String> c) {
    return join(" ", c);
  }

  public static String joinWithSpace(String... c) {
    return join(" ", c);
  }

  public static boolean methodIsStatic(Method m) {
    return (m.getModifiers() & Modifier.STATIC) != 0;
  }

  public static boolean argumentCompatibleWithType(Object arg, Class type) {
    return arg == null ? !type.isPrimitive() : isInstanceX(type, arg);
  }

  public static void arraycopy(Object[] a, Object[] b) {
    if (a != null && b != null)
      arraycopy(a, 0, b, 0, min(a.length, b.length));
  }

  public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) {
    if (n != 0)
      System.arraycopy(src, srcPos, dest, destPos, n);
  }

  public static <A> A[] arrayOfType(Class<A> type, int n) {
    return makeArray(type, n);
  }

  public static <A> A[] arrayOfType(int n, Class<A> type) {
    return arrayOfType(type, n);
  }

  public static <A> String join(String glue, Iterable<A> strings) {
    if (strings == null)
      return "";
    if (strings instanceof Collection) {
      if (((Collection) strings).size() == 1)
        return str(first(((Collection) strings)));
    }
    StringBuilder buf = new StringBuilder();
    Iterator<A> 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 <A> String join(Iterable<A> strings) {
    return join("", strings);
  }

  public static <A> String join(Iterable<A> strings, String glue) {
    return join(glue, strings);
  }

  public static String join(String[] strings) {
    return join("", strings);
  }

  public static String join(String glue, Pair p) {
    return p == null ? "" : str(p.a) + glue + str(p.b);
  }

  public static List<String> getClassNames(Collection l) {
    List<String> out = new ArrayList();
    if (l != null)
      for (Object o : l) out.add(o == null ? null : getClassName(o));
    return out;
  }

  public static boolean empty(Collection c) {
    return c == null || c.isEmpty();
  }

  public static boolean empty(CharSequence s) {
    return s == null || s.length() == 0;
  }

  public static boolean empty(Map map) {
    return map == null || map.isEmpty();
  }

  public static boolean empty(Object[] o) {
    return o == null || o.length == 0;
  }

  public 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));
  }

  public static boolean empty(float[] a) {
    return a == null || a.length == 0;
  }

  public static boolean empty(int[] a) {
    return a == null || a.length == 0;
  }

  public static boolean empty(long[] a) {
    return a == null || a.length == 0;
  }

  public static boolean empty(byte[] a) {
    return a == null || a.length == 0;
  }

  public static boolean empty(File f) {
    return getFileSize(f) == 0;
  }

  public static boolean isSnippetID(String s) {
    try {
      parseSnippetID(s);
      return true;
    } catch (RuntimeException e) {
      return false;
    }
  }

  public static long parseSnippetID(String snippetID) {
    long id = Long.parseLong(shortenSnippetID(snippetID));
    if (id == 0)
      throw fail("0 is not a snippet ID");
    return id;
  }

  public static boolean isAWTThread() {
    if (isAndroid())
      return false;
    if (isHeadless())
      return false;
    return isAWTThread_awt();
  }

  public static boolean isAWTThread_awt() {
    return SwingUtilities.isEventDispatchThread();
  }

  public static void failIfUnlicensed() {
    assertTrue("license off", licensed());
  }

  public static Thread currentThread() {
    return Thread.currentThread();
  }

  public static <A> A setThreadLocal(ThreadLocal<A> tl, A value) {
    if (tl == null)
      return null;
    A old = tl.get();
    tl.set(value);
    return old;
  }

  public static Map synchroHashMap() {
    return Collections.synchronizedMap(new HashMap());
  }

  public static Class<?> _getClass(String name) {
    try {
      return Class.forName(name);
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  public static Class _getClass(Object o) {
    return o == null ? null : o instanceof Class ? (Class) o : o.getClass();
  }

  public static Class _getClass(Object realm, String name) {
    try {
      return getClass(realm).getClassLoader().loadClass(classNameToVM(name));
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  public static void smartSet(Field f, Object o, Object value) throws Exception {
    try {
      f.set(o, value);
    } catch (Exception e) {
      Class type = f.getType();
      if (type == int.class && value instanceof Long)
        value = ((Long) value).intValue();
      if (type == LinkedHashMap.class && value instanceof Map) {
        f.set(o, asLinkedHashMap((Map) value));
        return;
      }
      try {
        if (f.getType() == Concept.Ref.class) {
          f.set(o, ((Concept) o).new Ref((Concept) value));
          return;
        }
        if (o instanceof Concept.Ref) {
          f.set(o, ((Concept.Ref) o).get());
          return;
        }
      } catch (Throwable _e) {
      }
      throw e;
    }
  }

  public static boolean odd(int i) {
    return (i & 1) != 0;
  }

  public static boolean odd(long i) {
    return (i & 1) != 0;
  }

  public static boolean odd(BigInteger i) {
    return odd(toInt(i));
  }

  public static int min(int a, int b) {
    return Math.min(a, b);
  }

  public static long min(long a, long b) {
    return Math.min(a, b);
  }

  public static float min(float a, float b) {
    return Math.min(a, b);
  }

  public static float min(float a, float b, float c) {
    return min(min(a, b), c);
  }

  public static double min(double a, double b) {
    return Math.min(a, b);
  }

  public static double min(double[] c) {
    double x = Double.MAX_VALUE;
    for (double d : c) x = Math.min(x, d);
    return x;
  }

  public static float min(float[] c) {
    float x = Float.MAX_VALUE;
    for (float d : c) x = Math.min(x, d);
    return x;
  }

  public static byte min(byte[] c) {
    byte x = 127;
    for (byte d : c) if (d < x)
      x = d;
    return x;
  }

  public static short min(short[] c) {
    short x = 0x7FFF;
    for (short d : c) if (d < x)
      x = d;
    return x;
  }

  public static int min(int[] c) {
    int x = Integer.MAX_VALUE;
    for (int d : c) if (d < x)
      x = d;
    return x;
  }

  public static <A> A[] makeArray(Class<A> type, int n) {
    return (A[]) Array.newInstance(type, n);
  }

  public static Object first(Object list) {
    return first((Iterable) list);
  }

  public static <A> A first(List<A> list) {
    return empty(list) ? null : list.get(0);
  }

  public static <A> A first(A[] bla) {
    return bla == null || bla.length == 0 ? null : bla[0];
  }

  public static <A> A first(Iterator<A> i) {
    return i == null || !i.hasNext() ? null : i.next();
  }

  public static <A> A first(Iterable<A> i) {
    if (i == null)
      return null;
    Iterator<A> it = i.iterator();
    return it.hasNext() ? it.next() : null;
  }

  public static Character first(String s) {
    return empty(s) ? null : s.charAt(0);
  }

  public static <A, B> A first(Pair<A, B> p) {
    return p == null ? null : p.a;
  }

  public static String getClassName(Object o) {
    return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName();
  }

  public static String getType(Object o) {
    return getClassName(o);
  }

  public static long getFileSize(String path) {
    return path == null ? 0 : new File(path).length();
  }

  public static long getFileSize(File f) {
    return f == null ? 0 : f.length();
  }

  public static String shortenSnippetID(String snippetID) {
    if (snippetID.startsWith("#"))
      snippetID = snippetID.substring(1);
    String httpBlaBla = "http://tinybrain.de/";
    if (snippetID.startsWith(httpBlaBla))
      snippetID = snippetID.substring(httpBlaBla.length());
    return "" + parseLong(snippetID);
  }

  public static volatile boolean licensed_yes = true;

  public static boolean licensed() {
    if (!licensed_yes)
      return false;
    ping_okInCleanUp();
    return true;
  }

  public static void licensed_off() {
    licensed_yes = false;
  }

  public static Class<?> getClass(String name) {
    try {
      return Class.forName(name);
    } catch (ClassNotFoundException e) {
      return null;
    }
  }

  public static Class getClass(Object o) {
    return o instanceof Class ? (Class) o : o.getClass();
  }

  public static Class getClass(Object realm, String name) {
    try {
      try {
        return getClass(realm).getClassLoader().loadClass(classNameToVM(name));
      } catch (ClassNotFoundException e) {
        return null;
      }
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }

  public static String classNameToVM(String name) {
    return name.replace(".", "$");
  }

  public static <A, B> LinkedHashMap<A, B> asLinkedHashMap(Map<A, B> map) {
    if (map instanceof LinkedHashMap)
      return (LinkedHashMap) map;
    LinkedHashMap<A, B> m = new LinkedHashMap();
    if (map != null)
      synchronized (collectionMutex(map)) {
        m.putAll(map);
      }
    return m;
  }

  public static int toInt(Object o) {
    if (o == null)
      return 0;
    if (o instanceof Number)
      return ((Number) o).intValue();
    if (o instanceof String)
      return parseInt((String) o);
    throw fail("woot not int: " + getClassName(o));
  }

  public static int toInt(long l) {
    if (l != (int) l)
      throw fail("Too large for int: " + l);
    return (int) l;
  }

  public static long parseLong(String s) {
    if (s == null)
      return 0;
    return Long.parseLong(dropSuffix("L", s));
  }

  public static long parseLong(Object s) {
    return Long.parseLong((String) s);
  }

  public static Object collectionMutex(Object o) {
    String c = className(o);
    if (eq(c, "java.util.TreeMap$KeySet"))
      c = className(o = getOpt(o, "m"));
    else if (eq(c, "java.util.HashMap$KeySet"))
      c = className(o = get_raw(o, "this$0"));
    if (eqOneOf(c, "java.util.TreeMap$AscendingSubMap", "java.util.TreeMap$DescendingSubMap"))
      c = className(o = get_raw(o, "m"));
    return o;
  }

  public static int parseInt(String s) {
    return empty(s) ? 0 : Integer.parseInt(s);
  }

  public static int parseInt(char c) {
    return Integer.parseInt(str(c));
  }

  public static String dropSuffix(String suffix, String s) {
    return s.endsWith(suffix) ? s.substring(0, l(s) - l(suffix)) : s;
  }

  public static String className(Object o) {
    return getClassName(o);
  }

  public static boolean eqOneOf(Object o, Object... l) {
    for (Object x : l) if (eq(o, x))
      return true;
    return false;
  }

  public static final class _MethodCache {

    public final Class c;

    public final HashMap<String, List<Method>> cache = new HashMap();

    public _MethodCache(Class c) {
      this.c = c;
      _init();
    }

    public void _init() {
      Class _c = c;
      while (_c != null) {
        for (Method m : _c.getDeclaredMethods()) if (!reflection_isForbiddenMethod(m))
          multiMapPut(cache, m.getName(), makeAccessible(m));
        _c = _c.getSuperclass();
      }
      for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if (m.isDefault() && !reflection_isForbiddenMethod(m))
        multiMapPut(cache, m.getName(), makeAccessible(m));
    }

    public Method findMethod(String method, Object[] args) {
      try {
        List<Method> 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);
      }
    }

    public Method findStaticMethod(String method, Object[] args) {
      try {
        List<Method> 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);
      }
    }
  }

  public static class Pair<A, B> implements Comparable<Pair<A, B>> {

    public A a;

    public B b;

    public Pair() {
    }

    public 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<A, B> p) {
      if (p == null)
        return 1;
      int i = ((Comparable<A>) a).compareTo(p.a);
      if (i != 0)
        return i;
      return ((Comparable<B>) b).compareTo(p.b);
    }
  }

  public static boolean reflection_isForbiddenMethod(Method m) {
    return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives");
  }

  public static <A, B> void multiMapPut(Map<A, List<B>> map, A a, B b) {
    List<B> l = map.get(a);
    if (l == null)
      map.put(a, l = new ArrayList());
    l.add(b);
  }

  public static Field makeAccessible(Field f) {
    f.setAccessible(true);
    return f;
  }

  public static Method makeAccessible(Method m) {
    m.setAccessible(true);
    return m;
  }

  public static Set<Class> allInterfacesImplementedBy(Class c) {
    if (c == null)
      return null;
    HashSet<Class> set = new HashSet();
    allInterfacesImplementedBy_find(c, set);
    return set;
  }

  public static void allInterfacesImplementedBy_find(Class c, Set<Class> set) {
    if (c.isInterface() && !set.add(c))
      return;
    do {
      for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set);
    } while ((c = c.getSuperclass()) != null);
  }

  public static Method findMethod(Object o, String method, Object... args) {
    return findMethod_cached(o, method, args);
  }

  public static boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) {
    Class<?>[] types = m.getParameterTypes();
    if (types.length != args.length) {
      if (debug)
        System.out.println("Bad parameter length: " + args.length + " vs " + types.length);
      return false;
    }
    for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) {
      if (debug)
        System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]);
      return false;
    }
    return true;
  }

  public 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;
  }

  public static Method findStaticMethod(Class c, String method, Object... args) {
    Class _c = c;
    while (c != null) {
      for (Method m : c.getDeclaredMethods()) {
        if (!m.getName().equals(method))
          continue;
        if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args))
          continue;
        return m;
      }
      c = c.getSuperclass();
    }
    return null;
  }

  public static boolean findStaticMethod_checkArgs(Method m, Object[] args) {
    Class<?>[] types = m.getParameterTypes();
    if (types.length != args.length)
      return false;
    for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i])))
      return false;
    return true;
  }

  public static int hashCodeFor(Object a) {
    return a == null ? 0 : a.hashCode();
  }

  public static Method findMethod_cached(Object o, String method, Object... args) {
    try {
      if (o == null)
        return null;
      if (o instanceof Class) {
        _MethodCache cache = callOpt_getCache(((Class) o));
        List<Method> methods = cache.cache.get(method);
        if (methods != null)
          for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false))
            return m;
        return null;
      } else {
        _MethodCache cache = callOpt_getCache(o.getClass());
        List<Method> methods = cache.cache.get(method);
        if (methods != null)
          for (Method m : methods) if (findMethod_checkArgs(m, args, false))
            return m;
        return null;
      }
    } catch (Exception __e) {
      throw rethrow(__e);
    }
  }
}