renamed Script to JSU
[org.ibex.js.git] / src / org / ibex / js / JSU.java
diff --git a/src/org/ibex/js/JSU.java b/src/org/ibex/js/JSU.java
new file mode 100644 (file)
index 0000000..614114f
--- /dev/null
@@ -0,0 +1,129 @@
+package org.ibex.js;
+
+import java.io.Reader;
+import java.io.IOException;
+import org.ibex.util.*;
+
+public class JSU {
+    /** returns a Pausable which will restart the context;
+     *  expects a value to be pushed onto the stack when unpaused. */
+    public static Pausable pause() throws Pausable.NotPausableException {
+        Interpreter i = Interpreter.current();
+        i.pause();
+        return i;
+    }
+
+    /** Coerce a JS object into a boolean. */
+    public static boolean toBoolean(JS o) {
+        if(o == null) return false;
+        if(o instanceof JSNumber) return ((JSNumber)o).toBoolean();
+        if(o instanceof JSString) return ((JSString)o).s.length() != 0;
+        return true;
+    }
+
+    //#repeat long/int/double/float toLong/toInt/toDouble/toFloat Long/Integer/Double/Float parseLong/parseInt/parseDouble/parseFloat
+    /** Coerce a JS object to a long. */
+    public static long toLong(JS o) throws JSExn {
+        if(o == null) return 0;
+        if(o instanceof JSNumber) return ((JSNumber)o).toLong();
+        if(o instanceof JSString) return Long.parseLong(o.coerceToString());
+        throw new JSExn("can't coerce a " + o.getClass().getName() + " to a number");
+    }
+    //#end
+    
+    /** Coerce a JS object to a String. */
+    public static String toString(JS o) throws JSExn {
+        if(o == null) return "null";
+        return o.coerceToString();
+    }
+
+    
+    public static boolean isInt(JS o) {
+        if(o == null) return true;
+        if(o instanceof JSNumber.I) return true;
+        if(o instanceof JSNumber.B) return false;
+        if(o instanceof JSNumber) {
+            JSNumber n = (JSNumber) o;
+            return n.toInt() == n.toDouble();
+        }
+        if(o instanceof JSString) {
+            String s = ((JSString)o).s;
+            for(int i=0;i<s.length();i++)
+                if(s.charAt(i) < '0' || s.charAt(i) > '9') return false;
+            return true;
+        }
+        return false;
+    }
+    
+    public static boolean isString(JS o) {
+        if(o instanceof JSString) return true;
+        return false;
+    }
+    
+    // Instance Methods ////////////////////////////////////////////////////////////////////
+    public final static JS NaN = new JSNumber.D(Double.NaN);
+    public final static JS ZERO = new JSNumber.I(0);
+    public final static JS ONE = new JSNumber.I(1);
+    public final static JS MATH = new JSMath();
+        
+    public static final JS T = new JSNumber.B(true);
+    public static final JS F = new JSNumber.B(false);
+
+    public static final JS B(boolean b) { return b ? T : F; }
+    public static final JS B(int i) { return i==0 ? F : T; }
+    
+    private static final int CACHE_SIZE = 65536 / 4; // must be a power of two
+    private static final JSString[] stringCache = new JSString[CACHE_SIZE];
+    public static final JS S(String s) {
+        if(s == null) return null;
+        int slot = s.hashCode()&(CACHE_SIZE-1);
+        JSString ret = stringCache[slot];
+        if(ret == null || !ret.s.equals(s)) stringCache[slot] = ret = new JSString(s);
+        return ret;
+    }
+    public static final JS S(String s, boolean intern) { return intern ? JSString.intern(s) : S(s); }
+
+    public static final JS N(double d) { return new JSNumber.D(d); }
+    public static final JS N(long l) { return new JSNumber.L(l); }
+    
+    public static final JS N(Number n) {
+        if(n instanceof Integer) return N(n.intValue());
+        if(n instanceof Long) return N(n.longValue());
+        return N(n.doubleValue());
+    }
+
+    private static final JSNumber.I negone = new JSNumber.I(-1);
+    private static final JSNumber.I[] icache = new JSNumber.I[128];
+    static { for (int i=0; i < icache.length; i++) icache[i] = new JSNumber.I(i); }
+    public static final JS N(int i) {
+        return i == -1 ? negone : i >= 0 && i < icache.length ? icache[i] : new JSNumber.I(i);
+    }
+
+    /** Internal method for coercing to String without throwing a JSExn. */
+    static String str(JS o) {
+        try { return toString(o); }
+        catch(JSExn e) { return o.toString(); }
+    }
+
+
+    // Static Interpreter Control Methods ///////////////////////////////////////////////////////////////
+
+    public static JS fromReader(String sourceName, int firstLine, Reader source) throws IOException {
+        return Parser.fromReader(sourceName, firstLine, source); }
+
+    // FIXME
+    public static JS cloneWithNewGlobalScope(JS js, JS s) {
+        if(js instanceof JSFunction)
+            return ((JSFunction)js)._cloneWithNewParentScope(new JSScope.Top(s));
+        else
+            return js;
+    }
+
+    /** log a message with the current JavaScript sourceName/line */
+    public static void log(Object message) { info(message); }
+    public static void debug(Object message) { Log.debug(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
+    public static void info(Object message) { Log.info(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
+    public static void warn(Object message) { Log.warn(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
+    public static void error(Object message) { Log.error(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
+}