--- /dev/null
+package org.ibex.js;
+
+abstract class JSNumber extends JSPrimitive {
+ boolean jsequals(JS o) {
+ if(o == this) return true;
+ if(o instanceof JSNumber) {
+ JSNumber n = (JSNumber) o;
+ if(this instanceof D || n instanceof D) return n.toDouble() == toDouble();
+ return n.toLong() == toLong();
+ } else if(o instanceof JSString) {
+ String s = ((JSString)o).s.trim();
+ try {
+ if(this instanceof D || s.indexOf('.') != -1) return Double.parseDouble(s) == toDouble();
+ return Long.parseLong(s) == toLong();
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ // FEATURE: Better hash function? (if d != (int) d then do something double specific)
+ public int hashCode() { return toInt(); }
+
+ abstract int toInt();
+ long toLong() { return toInt(); }
+ boolean toBoolean() { return toInt() != 0; }
+ double toDouble() { return toLong(); }
+ float toFloat() { return (float) toDouble(); }
+
+ final static class I extends JSNumber {
+ final int i;
+ I(int i) { this.i = i; }
+ int toInt() { return i; }
+ public String coerceToString() { return Integer.toString(i); }
+ }
+
+ final static class L extends JSNumber {
+ private final long l;
+ L(long l) { this.l = l; }
+ int toInt() { return (int) l; }
+ long toLong() { return l; }
+ public String coerceToString() { return Long.toString(l); }
+ }
+
+ final static class D extends JSNumber {
+ private final double d;
+ D(double d) { this.d = d; }
+ int toInt() { return (int) d; }
+ long toLong() { return (long) d; }
+ double toDouble() { return d; }
+ boolean toBoolean() { return d == d && d != 0.0; }
+ public String coerceToString() { return d == (long) d ? Long.toString((long)d) : Double.toString(d); }
+ }
+
+ final static class B extends JSNumber {
+ private final boolean b;
+ B(boolean b) { this.b = b; }
+ int toInt() { return b ? 1 : 0; }
+ public String coerceToString() { return b ? "true" : "false"; }
+ }
+}