2003/06/16 08:03:15
[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 absolute minimal amount of functionality for an
11  *  Object which can be manipulated by JavaScript code.  The static
12  *  methods, fields, and inner classes of JS define the publicly
13  *  visible API for the XWT JavaScript engine; code outside this
14  *  package should never depend on anything not defined in this file.
15  */
16 public abstract class JS { 
17
18     // Public Helper Methods //////////////////////////////////////////////////////////////////////
19
20     /** parse and compile a function */
21     public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode) throws IOException {
22         return new CompiledFunction(sourceName, firstLine, sourceCode, null);
23     }
24
25     /** coerce an object to a Boolean */
26     public static boolean toBoolean(Object o) {
27         if (o == null) return false;
28         if (o instanceof Boolean) return ((Boolean)o).booleanValue();
29         if (o instanceof Number) return o.equals(new Integer(0));
30         return true;
31     }
32
33     /** coerce an object to a Long */
34     public static long toLong(Object o) { return toNumber(o).longValue(); }
35
36     /** coerce an object to a Double */
37     public static double toDouble(Object o) { return toNumber(o).doubleValue(); }
38
39     /** coerce an object to a Number */
40     public static Number toNumber(Object o) {
41         if (o == null) return new Long(0);
42         if (o instanceof Number) return ((Number)o);
43         if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); }
44         if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0);
45         if (o instanceof JS) return ((JS)o).coerceToNumber();
46         throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
47     }
48
49
50     // Instance Methods ////////////////////////////////////////////////////////////////////
51  
52     public abstract Object get(Object key) throws JS.Exn; 
53     public abstract void put(Object key, Object val) throws JS.Exn; 
54     public abstract Object[] keys(); 
55
56     public Number coerceToNumber() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Number"); }
57     public String coerceToString() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a String"); }
58     public boolean coerceToBoolean() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Boolean"); }
59
60
61     // Inner Classes /////////////////////////////////////////////////////////////////////////
62
63     /** A sensible implementation of the abstract methods in the JS class */
64     public static class Obj extends JS {
65         private Hash entries = new Hash();
66         private boolean sealed = false;
67         public Obj() { this(false); }
68         public Obj(boolean sealed) { this.sealed = sealed; }
69         public void setSeal(boolean sealed) { this.sealed = sealed; }
70         public Object get(Object key) { return entries.get(key); }
71         public void put(Object key, Object val) { if (!sealed) entries.put(key, val); }
72         public Object[] keys() { return(entries.keys()); }
73     }
74
75     /** An exception which can be thrown and caught by JavaScript code */
76     public static class Exn extends RuntimeException { 
77         private Object js = null; 
78         public Exn(Object js) { this.js = js; } 
79         public String toString() { return "JS.Exn: " + js; }
80         public String getMessage() { return toString(); }
81         public Object getObject() { return js; } 
82     } 
83
84     /** The publicly-visible face of JavaScript Array objects */
85     public static class Array extends ArrayImpl {
86         public Array() { }
87         public Array(int size) { super(size); }
88         public void setSize(int i) { super.setSize(i); }
89         public int length() { return super.length(); }
90         public Object elementAt(int i) { return super.elementAt(i); }
91         public void addElement(Object o) { super.addElement(o); }
92         public void setElementAt(Object o, int i) { super.setElementAt(o, i); }
93     }
94
95     /** Any object which becomes part of the scope chain must support this interface */ 
96     public static class Scope extends ScopeImpl { 
97         public Scope(Scope parentScope) { this(parentScope, false); }
98         public Scope(Scope parentScope, boolean sealed) { super(parentScope, sealed); }
99         public Scope getParentScope() { return super.getParentScope(); }
100         public boolean isTransparent() { return super.isTransparent(); }
101         public boolean has(Object key) { return super.has(key); }
102         public void declare(String s) { super.declare(s); }
103     } 
104
105     /** anything that is callable with the () operator */
106     public static abstract class Callable extends JS.Obj {
107         public abstract Object call(JS.Array args) throws JS.Exn;
108     }
109
110     /** a Callable which was compiled from JavaScript code */
111     public static class CompiledFunction extends CompiledFunctionImpl {
112         public Object call(JS.Array args, JS.Scope scope) throws JS.Exn { return super.call(args, scope); }
113         CompiledFunction(String sourceName, int firstLine, Reader sourceCode, Scope scope) throws IOException {
114             super(sourceName, firstLine, sourceCode, scope);
115         }
116     }
117  
118
119
120
121
122