added some files that had been left out
authoradam <adam@megacz.com>
Mon, 27 Dec 2004 10:37:26 +0000 (10:37 +0000)
committeradam <adam@megacz.com>
Mon, 27 Dec 2004 10:37:26 +0000 (10:37 +0000)
darcs-hash:20041227103726-5007d-84747b3a4904d401e726210244ac6f862061d503.gz

src/org/ibex/js/JSNumber.java [new file with mode: 0644]
src/org/ibex/js/JSPrimitive.java [new file with mode: 0644]
src/org/ibex/js/JSString.java [new file with mode: 0644]
src/org/ibex/js/Test.java [new file with mode: 0644]

diff --git a/src/org/ibex/js/JSNumber.java b/src/org/ibex/js/JSNumber.java
new file mode 100644 (file)
index 0000000..8137cbc
--- /dev/null
@@ -0,0 +1,62 @@
+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"; }
+    }
+}
diff --git a/src/org/ibex/js/JSPrimitive.java b/src/org/ibex/js/JSPrimitive.java
new file mode 100644 (file)
index 0000000..575b60b
--- /dev/null
@@ -0,0 +1,109 @@
+package org.ibex.js;
+
+class JSPrimitive extends JS {
+    public JS callMethod(JS method, JS arg0, JS arg1, JS arg2, JS[] rest, int alength) throws JSExn {
+        //#switch(JS.toString(method))
+        case "toFixed": throw new JSExn("toFixed() not implemented");
+        case "toExponential": throw new JSExn("toExponential() not implemented");
+        case "toPrecision": throw new JSExn("toPrecision() not implemented");
+        case "toString": return this instanceof JSString ? this : JS.S(JS.toString(this));
+        //#end
+            
+        String s = coerceToString();
+        int slength = s.length();
+            
+        //#switch(JS.toString(method))
+        case "substring": {
+            int a = alength >= 1 ? JS.toInt(arg0) : 0;
+            int b = alength >= 2 ? JS.toInt(arg1) : slength;
+            if (a > slength) a = slength;
+            if (b > slength) b = slength;
+            if (a < 0) a = 0;
+            if (b < 0) b = 0;
+            if (a > b) { int tmp = a; a = b; b = tmp; }
+            return JS.S(s.substring(a,b));
+        }
+        case "substr": {
+            int start = alength >= 1 ? JS.toInt(arg0) : 0;
+            int len = alength >= 2 ? JS.toInt(arg1) : Integer.MAX_VALUE;
+            if (start < 0) start = slength + start;
+            if (start < 0) start = 0;
+            if (len < 0) len = 0;
+            if (len > slength - start) len = slength - start;
+            if (len <= 0) return JS.S("");
+            return JS.S(s.substring(start,start+len));
+        }
+        case "charAt": {
+            int p = alength >= 1 ? JS.toInt(arg0) : 0;
+            if (p < 0 || p >= slength) return JS.S("");
+            return JS.S(s.substring(p,p+1));
+        }
+        case "charCodeAt": {
+            int p = alength >= 1 ? JS.toInt(arg0) : 0;
+            if (p < 0 || p >= slength) return JS.N(Double.NaN);
+            return JS.N(s.charAt(p));
+        }
+        case "concat": {
+            StringBuffer sb = new StringBuffer(slength*2).append(s);
+            for(int i=0;i<alength;i++) sb.append(i==0?arg0:i==1?arg1:i==2?arg2:rest[i-3]);
+            return JS.S(sb.toString());
+        }
+        case "indexOf": {
+            String search = alength >= 1 ? JS.toString(arg0) : "null";
+            int start = alength >= 2 ? JS.toInt(arg1) : 0;
+            // Java's indexOf handles an out of bounds start index, it'll return -1
+            return JS.N(s.indexOf(search,start));
+        }
+        case "lastIndexOf": {
+            String search = alength >= 1 ? JS.toString(arg0) : "null";
+            int start = alength >= 2 ? JS.toInt(arg1) : 0;
+            // Java's indexOf handles an out of bounds start index, it'll return -1
+            return JS.N(s.lastIndexOf(search,start));            
+        }
+        case "match": return JSRegexp.stringMatch(this,arg0);
+        case "replace": return JSRegexp.stringReplace(this,arg0,arg1);
+        case "search": return JSRegexp.stringSearch(this,arg0);
+        case "split": return JSRegexp.stringSplit(this,arg0,arg1,alength);
+        case "toLowerCase": return JS.S(s.toLowerCase());
+        case "toUpperCase": return JS.S(s.toUpperCase());
+        case "slice": {
+            int a = alength >= 1 ? JS.toInt(arg0) : 0;
+            int b = alength >= 2 ? JS.toInt(arg1) : slength;
+            if (a < 0) a = slength + a;
+            if (b < 0) b = slength + b;
+            if (a < 0) a = 0;
+            if (b < 0) b = 0;
+            if (a > slength) a = slength;
+            if (b > slength) b = slength;
+            if (a > b) return JS.S("");
+            return JS.S(s.substring(a,b));
+        }
+        //#end
+        return super.callMethod(method,arg0,arg1,arg2,rest,alength);
+    }
+    
+    public JS get(JS key) throws JSExn {
+        //#switch(JS.toString(key))
+        case "length": return JS.N(JS.toString(this).length());
+        case "substring": return METHOD;
+        case "charAt": return METHOD;
+        case "charCodeAt": return METHOD;
+        case "concat": return METHOD;
+        case "indexOf": return METHOD;
+        case "lastIndexOf": return METHOD; 
+        case "match": return METHOD;
+        case "replace": return METHOD;
+        case "search": return METHOD;
+        case "slice": return METHOD;
+        case "split": return METHOD;
+        case "toLowerCase": return METHOD; 
+        case "toUpperCase": return METHOD; 
+        case "toString": return METHOD; 
+        case "substr": return METHOD;  
+        case "toPrecision": return METHOD;
+        case "toExponential": return METHOD;
+        case "toFixed": return METHOD;
+        //#end
+        return super.get(key);
+    }
+}
diff --git a/src/org/ibex/js/JSString.java b/src/org/ibex/js/JSString.java
new file mode 100644 (file)
index 0000000..5dc2334
--- /dev/null
@@ -0,0 +1,35 @@
+package org.ibex.js;
+
+import org.ibex.util.*;
+
+class JSString extends JSPrimitive {
+    final String s;
+    public JSString(String s) { this.s = s; }
+    public int hashCode() { return s.hashCode(); }
+    
+    public boolean jsequals(JS o) {
+        if(o == this) return true;
+        if(o instanceof JSString) {
+            return ((JSString)o).s.equals(s);
+        } else if(o instanceof JSNumber) {
+            return o.jsequals(this);
+        } else {
+            return false;
+        }
+    }
+    
+    private final static Hash internHash = new Hash();
+    static synchronized JS intern(String s) {
+        synchronized(internHash) {
+            JS js = (JS)internHash.get(s);
+            if(js == null) internHash.put(s,js = new Intern(s));
+            return js;
+        }
+    }
+    static class Intern extends JSString {
+        public Intern(String s) { super(s); }
+        protected void finalize() { synchronized(internHash) { internHash.put(s,null); } }
+    }
+    
+    String coerceToString() { return s; }
+}
diff --git a/src/org/ibex/js/Test.java b/src/org/ibex/js/Test.java
new file mode 100644 (file)
index 0000000..1bf62e1
--- /dev/null
@@ -0,0 +1,83 @@
+package org.ibex.js;
+
+import java.io.*;
+
+public class Test extends JS {
+    static JS.UnpauseCallback up = null;
+    static String action;
+    
+    public static void main(String[] args) throws Exception {
+        if(args.length == 0) { System.err.println("Usage Test filename"); System.exit(1); }
+        JS f = JS.fromReader(args[0],1,new FileReader(args[0]));
+        System.out.println(((JSFunction)f).dump());
+        JS s = new JS.O();
+        s.put(JS.S("sys"),new Test());
+        f = JS.cloneWithNewGlobalScope(f,s);
+        //JS ret = f.call(null,null,null,null,0);
+        Interpreter i = new Interpreter((JSFunction)f, true, new Interpreter.JSArgs(f));
+        JS ret = i.resume();
+        while(up != null) {
+            JS.UnpauseCallback up = Test.up; Test.up = null;
+            if("throw".equals(action)) ret = up.unpause(new JSExn("this was thrown to a paused context"));
+            else if("bgget".equals(action)) ret = up.unpause(JS.S("I'm returning this from a get request"));
+            else {
+                System.out.println("got a background put " + action);
+                ret = up.unpause();
+            }
+        }
+        System.out.println("Script returned: " + JS.toString(ret));
+    }
+    
+    public JS get(JS key) throws JSExn {
+        if(!JS.isString(key)) return null;
+        if("print".equals(JS.toString(key))) return METHOD;
+        if("clone".equals(JS.toString(key))) return METHOD;
+        if("firethis".equals(JS.toString(key))) return METHOD;
+        if("bgget".equals(JS.toString(key))) {
+            action = "bgget";
+            try {
+                up = JS.pause();
+            } catch(NotPauseableException e) {
+                throw new Error("should never happen");
+            }
+            return null;
+        }
+        return super.get(key);
+    }
+        
+    public void put(JS key, JS val) throws JSExn {
+        if("bgput".equals(JS.toString(key))) {
+            action = JS.toString(val);
+            try {
+                up = JS.pause();
+            } catch(NotPauseableException e) {
+                throw new Error("should never happen");
+            }
+            return;
+        }   
+        if("exit".equals(JS.toString(key))) {
+            System.exit(JS.toInt(val));
+            return;
+        }
+        super.put(key,val);
+    }
+    
+    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
+        if(!JS.isString(method)) return null;
+        if("print".equals(JS.toString(method))) {
+            System.out.println(JS.debugToString(a0));
+            return null;
+        }
+        if("clone".equals(JS.toString(method))) return a0 == null ? null : a0.jsclone();
+        if("firethis".equals(JS.toString(method))) {
+            String action = JS.toString(a0);
+            JS target = a1;
+            JS key = a2;
+            if(action.equals("get")) return a1.getAndTriggerTraps(key);
+            else if(action.equals("put")) a1.putAndTriggerTraps(key,JS.S("some value"));
+            else if(action.equals("trigger")) return target.justTriggerTraps(key,JS.S("some trigger value"));
+            return null;
+        }
+        return null;
+    }
+}