- /** Anything that is callable */
- public static class Function extends Obj {
- ByteCodeBlock bytecodes;
- int line;
- String sourceName;
- Scope parentScope;
- public Function(int line, String sourceName, ByteCodeBlock bytecodes, Scope parentScope) {
- this.sourceName = sourceName;
- this.line = line;
- this.bytecodes = bytecodes;
- this.parentScope = parentScope;
- }
- public Function cloneWithNewParentScope(Scope s) {
- if (this.getClass() != Function.class)
- throw new Error("org.xwt.js.JS.Function.cloneWithNewParentScope() is not valid for subclasses");
- return new Function(line, sourceName, bytecodes, s);
- }
- public String getSourceName() throws JS.Exn { return sourceName; }
- public int getLine() throws JS.Exn { return line; }
- public Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException {
- if (bytecodes == null) throw new Error("tried to call() a JS.Function with bytecodes == null");
- Context cx = Context.getContextForCurrentThread();
- int size = cx.stack.size();
- cx.stack.push(new Context.CallMarker());
- cx.stack.push(args);
- bytecodes.eval(args == null ? parentScope : new FunctionScope(sourceName, parentScope));
- Object ret = cx.stack.pop();
- if (cx.stack.size() > size) {
- Log.log(this, "warning, stack grew by " + (cx.stack.size() - size) +
- " elements during call to " + getSourceName() + ":" + getLine());
- Log.log(this, "top element is " + cx.stack.peek());
- }
- return ret;
- }
- public final Object call(JS.Array args) throws JS.Exn {
- Function saved = (Function)currentFunction.get(Thread.currentThread());
- if (!getSourceName().equals("java")) currentFunction.put(Thread.currentThread(), this);
- try {
- return _call(args);
- } catch (ByteCodeBlock.ReturnException e) { // ignore
- return e.retval;
- } catch (ByteCodeBlock.ControlTransferException e) {
- throw new RuntimeException(getSourceName() + ":" + getLine() +
- " error, ControlTransferException tried to leave a function");
- } finally {
- if (saved == null) currentFunction.remove(Thread.currentThread());
- else currentFunction.put(Thread.currentThread(), saved);
- }
- }
+ /** Any object which becomes part of the scope chain must support this interface */
+ public static class Scope extends ScopeImpl {
+ public Scope(Scope parentScope) { this(parentScope, false); }
+ public Scope(Scope parentScope, boolean sealed) { super(parentScope, sealed); }
+ /** transparent scopes are not returned by THIS */
+ public boolean isTransparent() { return super.isTransparent(); }
+ public boolean has(Object key) { return super.has(key); }
+ public Object get(Object key) { return super.get(key); }
+ public void put(Object key, Object val) { super.put(key, val); }
+ public void declare(String s) { super.declare(s); }
+ }
+
+ /** anything that is callable with the () operator */
+ public static abstract class Callable extends JS.Obj {
+ public abstract Object call(JS.Array args) throws JS.Exn;