From: adam Date: Mon, 27 Dec 2004 10:37:26 +0000 (+0000) Subject: added some files that had been left out X-Git-Url: http://git.megacz.com/?p=org.ibex.js.git;a=commitdiff_plain;h=9ed8d93bbb0b40791a4ce31a9a8d79d24a379eb9 added some files that had been left out darcs-hash:20041227103726-5007d-84747b3a4904d401e726210244ac6f862061d503.gz --- diff --git a/src/org/ibex/js/JSNumber.java b/src/org/ibex/js/JSNumber.java new file mode 100644 index 0000000..8137cbc --- /dev/null +++ b/src/org/ibex/js/JSNumber.java @@ -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 index 0000000..575b60b --- /dev/null +++ b/src/org/ibex/js/JSPrimitive.java @@ -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= 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 index 0000000..5dc2334 --- /dev/null +++ b/src/org/ibex/js/JSString.java @@ -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 index 0000000..1bf62e1 --- /dev/null +++ b/src/org/ibex/js/Test.java @@ -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; + } +}