1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
6 /** The public API for the JS engine */
7 // FEATURE: try using mutable, recycled 'Num' objects
10 public abstract Object get(Object key) throws JS.Exn;
11 public abstract void put(Object key, Object val) throws JS.Exn;
12 public abstract Object[] enumerateProperties();
14 public abstract Number coerceToNumber() throws JS.Exn;
15 public abstract boolean coerceToBoolean() throws JS.Exn;
16 public abstract String coerceToString() throws JS.Exn;
18 public static class Obj implements JS {
21 public Object get(Object key) { return entries.get(key); }
22 public void put(Object key, Object val) { entries.put(key, val); }
23 public Object[] enumerateProperties() { return(entries.keys()); }
24 public Number coerceToNumber() { throw new Error("tried to turn a Object into a Number"); }
25 public String coerceToString() { throw new Error("tried to turn a Object into a String"); }
26 public boolean coerceToBoolean() { throw new Error("tried to turn a Object into a Boolean"); }
29 public static class Array extends Obj {
30 private Vec vec = new Vec();
31 private static int intVal(Object o) {
32 if (o instanceof Number) {
33 int intVal = ((Number)o).intValue();
34 if (intVal == ((Number)o).doubleValue()) return intVal;
35 return Integer.MIN_VALUE;
37 if (!(o instanceof String)) return Integer.MIN_VALUE;
39 for(int i=0; i<s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return Integer.MIN_VALUE;
40 return Integer.parseInt(s);
42 public Object get(Object key) {
43 if (key.equals("length")) return new Long(vec.size());
45 if (i == Integer.MIN_VALUE) return super.get(key);
46 return vec.elementAt(i);
48 public void put(Object key, Object val) {
49 if (key.equals("length")) vec.setSize(Expr.toNumber(val).intValue());
51 if (i == Integer.MIN_VALUE) super.put(key, val);
52 else vec.setElementAt(val, i);
54 public Object[] enumerateProperties() { return null; } // FIXME
55 void addElement(Object o) { vec.addElement(o); }
58 public static interface Function extends JS {
59 public abstract Object call(JS.Array args) throws JS.Exn; // FEATURE: try to recycle these arrays?
60 public abstract Scope getParentScopeOfDeclaration();
63 public static abstract class ObjFunction extends Obj implements Function { }
65 /** if JS calls a Java method, and the Java method throws an exception, it can only be caught by JS if it is a subclass of Exn. */
66 public static class Exn extends RuntimeException {
67 private Object js = null;
68 public Exn(Object js) { this.js = js; }
69 public Object getObject() { return js; }
72 /** Any object which becomes part of the scope chain must support this interface */
73 public static class Scope extends Obj {
74 private Scope parentScope;
75 private static Object NULL = new Object();
76 public Scope(Scope parentScope) { this.parentScope = parentScope; }
77 public JS getParentScope() { return parentScope; }
78 public boolean has(Object key) { return super.get(key) != null; }
79 public Object get(Object key) {
80 if (!has(key)) return getParentScope().get(key);
81 Object ret = super.get(key); return ret == NULL ? null : ret;
83 public void put(Object key, Object val) {
84 if (!has(key)) getParentScope().put(key, val);
85 else super.put(key, val == null ? NULL : val);
87 public Object[] enumerateProperties() { throw new Error("you can't enumerate the properties of a Scope"); }
88 public void declare(String s) { super.put(s, NULL); }