805224b7749f23dc7e74d2f42f86243bda107f45
[org.ibex.js.git] / src / org / ibex / js / JSU.java
1 package org.ibex.js;
2
3 import java.io.Reader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import org.ibex.util.*;
7
8 public class JSU {
9
10     public static final JS[] emptyArgs = new JS[] { };
11
12     public static InputStream getInputStream(JS j) throws IOException {
13         while(j != null && j instanceof JS.Cloneable) j = j.unclone();
14         if (j != null && j instanceof Fountain) return ((Fountain)j).getInputStream();
15         return null;
16     }
17
18     /** returns a Pausable which will restart the context;
19      *  expects a value to be pushed onto the stack when unpaused. */
20     public static Pausable pause() throws Pausable.NotPausableException {
21         Interpreter i = Interpreter.current();
22         i.pause();
23         return i;
24     }
25
26     /** Coerce a JS object into a boolean. */
27     public static boolean toBoolean(JS o) {
28         if(o == null) return false;
29         if(o instanceof JSNumber) return ((JSNumber)o).toBoolean();
30         if(o instanceof JSString) return ((JSString)o).s.length() != 0;
31         return true;
32     }
33
34     //#repeat long/int/double/float toLong/toInt/toDouble/toFloat Long/Integer/Double/Float parseLong/parseInt/parseDouble/parseFloat
35     /** Coerce a JS object to a long. */
36     public static long toLong(JS o) throws JSExn {
37         if(o == null) return 0;
38         if(o instanceof JSNumber) return ((JSNumber)o).toLong();
39         if(o instanceof JSString) return Long.parseLong(o.coerceToString());
40         throw new JSExn("can't coerce a " + o.getClass().getName() + " to a number");
41     }
42     //#end
43     
44     /** Coerce a JS object to a String. */
45     public static String toString(JS o) throws JSExn {
46         if(o == null) return "null";
47         return o.coerceToString();
48     }
49
50     
51     public static boolean isInt(JS o) {
52         if(o == null) return true;
53         if(o instanceof JSNumber.I) return true;
54         if(o instanceof JSNumber.B) return false;
55         if(o instanceof JSNumber) {
56             JSNumber n = (JSNumber) o;
57             return n.toInt() == n.toDouble();
58         }
59         if(o instanceof JSString) {
60             String s = ((JSString)o).s;
61             for(int i=0;i<s.length();i++)
62                 if(s.charAt(i) < '0' || s.charAt(i) > '9') return false;
63             return true;
64         }
65         return false;
66     }
67     
68     public static boolean isString(JS o) {
69         if(o instanceof JSString) return true;
70         return false;
71     }
72     
73     // Instance Methods ////////////////////////////////////////////////////////////////////
74  
75     public final static JS NaN = new JSNumber.D(Double.NaN);
76     public final static JS ZERO = new JSNumber.I(0);
77     public final static JS ONE = new JSNumber.I(1);
78     public final static JS MATH = new JSMath();
79         
80     public static final JS T = new JSNumber.B(true);
81     public static final JS F = new JSNumber.B(false);
82
83     public static final JS B(boolean b) { return b ? T : F; }
84     public static final JS B(int i) { return i==0 ? F : T; }
85     
86     private static final int CACHE_SIZE = 65536 / 4; // must be a power of two
87     private static final JSString[] stringCache = new JSString[CACHE_SIZE];
88     public static final JS S(String s) {
89         if(s == null) return null;
90         int slot = s.hashCode()&(CACHE_SIZE-1);
91         JSString ret = stringCache[slot];
92         if(ret == null || !ret.s.equals(s)) stringCache[slot] = ret = new JSString(s);
93         return ret;
94     }
95     public static final JS S(String s, boolean intern) { return intern ? JSString.intern(s) : S(s); }
96
97     public static final JS N(double d) { return new JSNumber.D(d); }
98     public static final JS N(long l) { return new JSNumber.L(l); }
99     
100     public static final JS N(Number n) {
101         if(n instanceof Integer) return N(n.intValue());
102         if(n instanceof Long) return N(n.longValue());
103         return N(n.doubleValue());
104     }
105
106     private static final JSNumber.I negone = new JSNumber.I(-1);
107     private static final JSNumber.I[] icache = new JSNumber.I[128];
108     static { for (int i=0; i < icache.length; i++) icache[i] = new JSNumber.I(i); }
109     public static final JS N(int i) {
110         return i == -1 ? negone : i >= 0 && i < icache.length ? icache[i] : new JSNumber.I(i);
111     }
112
113     /** Internal method for coercing to String without throwing a JSExn. */
114     public static String str(JS o) {
115         try { return toString(o); }
116         catch(JSExn e) { return o.toString(); }
117     }
118
119
120     // Static Interpreter Control Methods ///////////////////////////////////////////////////////////////
121
122     public static JS fromReader(String sourceName, int firstLine, Reader source) throws IOException {
123         return Parser.fromReader(sourceName, firstLine, source); }
124
125     public static JS cloneWithNewGlobalScope(JS js, JS s) {
126         return js instanceof JSFunction ?  ((JSFunction)js)._cloneWithNewParentScope(new JSScope.Top(s)) : js; }
127
128     /** log a message with the current JavaScript sourceName/line */
129     public static void log(Object message) { info(message); }
130     public static void debug(Object message) { Log.debug(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
131     public static void info(Object message) { Log.info(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
132     public static void warn(Object message) { Log.warn(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
133     public static void error(Object message) { Log.error(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
134 }