2003/06/12 17:57:37
[org.ibex.core.git] / src / org / xwt / js / JS.java
1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] 
2
3 package org.xwt.js; 
4 import org.xwt.util.*; 
5 import java.io.*;
6 import java.util.*;
7
8 /**
9  *  The public API for the JS engine; JS itself is actually a class
10  *  implementing the minimal amount of functionality for an Object
11  *  which can be manipulated by JavaScript code.
12  */
13 public abstract class JS { 
14
15     // Public Helper Methods //////////////////////////////////////////////////////////////////////
16
17     public static boolean toBoolean(Object o) {
18         if (o == null) return false;
19         if (o instanceof Boolean) return ((Boolean)o).booleanValue();
20         if (o instanceof Number) return o.equals(new Integer(0));
21         return true;
22     }
23
24     public static long toLong(Object o) { return toNumber(o).longValue(); }
25     public static double toDouble(Object o) { return toNumber(o).doubleValue(); }
26     public static Number toNumber(Object o) {
27         if (o == null) return new Long(0);
28         if (o instanceof Number) return ((Number)o);
29         if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); }
30         if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0);
31         if (o instanceof JS) return ((JS)o).coerceToNumber();
32         throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
33     }
34
35
36     // Instance Methods ////////////////////////////////////////////////////////////////////
37  
38     public abstract Object get(Object key) throws JS.Exn; 
39     public abstract void put(Object key, Object val) throws JS.Exn; 
40     public abstract Object[] keys(); 
41
42     public Number coerceToNumber() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Number"); }
43     public String coerceToString() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a String"); }
44     public boolean coerceToBoolean() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Boolean"); }
45
46
47     // Subclasses /////////////////////////////////////////////////////////////////////////
48
49     /** A slightly more featureful version of JS */
50     public static class Obj extends JS {
51         private Hash entries = new Hash();
52         private boolean sealed = false;
53         public Obj() { this(false); }
54         public Obj(boolean sealed) { this.sealed = sealed; }
55         public void setSeal(boolean sealed) { this.sealed = sealed; }
56         public Object get(Object key) { return entries.get(key); }
57         public void put(Object key, Object val) { if (!sealed) entries.put(key, val); }
58         public Object[] keys() { return(entries.keys()); }
59     }
60
61     /** An exception which can be thrown and caught by JavaScripts */
62     public static class Exn extends RuntimeException { 
63         private Object js = null; 
64         public Exn(Object js) { this.js = js; } 
65         public String toString() { return "JS.Exn: " + js; }
66         public String getMessage() { return toString(); }
67         public Object getObject() { return js; } 
68     } 
69
70     /** Any object which becomes part of the scope chain must support this interface */ 
71     public static class Scope extends Obj { 
72         private Scope parentScope;
73         private static Object NULL = new Object();
74         public Scope(Scope parentScope) { this(parentScope, false); }
75         public Scope(Scope parentScope, boolean sealed) { super(sealed); this.parentScope = parentScope; }
76         public Scope getParentScope() { return parentScope; }
77
78         // transparent scopes are not returned by THIS
79         public boolean isTransparent() { return false; }
80
81         public boolean has(Object key) { return super.get(key) != null; }
82         public Object get(Object key) {
83             if (!has(key)) return parentScope == null ? null : getParentScope().get(key);
84             Object ret = super.get(key); return ret == NULL ? null : ret;
85         }
86         public void put(Object key, Object val) {
87             if (!has(key) && parentScope != null) getParentScope().put(key, val);
88             else super.put(key, val == null ? NULL : val);
89         }
90         public Object[] keys() { throw new Error("you can't enumerate the properties of a Scope"); }
91         public void declare(String s) {
92             if (isTransparent()) getParentScope().declare(s);
93             else super.put(s, NULL);
94         }
95     } 
96
97     public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException {
98         return new CompiledFunction(sourceName, firstLine, sourceCode, parentScope);
99     }
100  
101     /** anything that is callable with the () operator */
102     public static abstract class Callable extends JS.Obj {
103         public abstract Object call(Array args) throws JS.Exn;
104     }
105
106
107
108
109
110