-// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
package org.xwt.js;
import org.xwt.util.*;
}
}
- private static JSExn je(String s) { return new JSExn(JS.getSourceName() + ":" + JS.getLine() + " " + s); }
+ static int getLine() {
+ Interpreter c = Interpreter.current();
+ return c == null || c.f == null || c.pc < 0 || c.pc >= c.f.size ? -1 : c.f.line[c.pc];
+ }
+
+ static String getSourceName() {
+ Interpreter c = Interpreter.current();
+ return c == null || c.f == null ? null : c.f.sourceName;
+ }
+
+ private static JSExn je(String s) { return new JSExn(getSourceName() + ":" + getLine() + " " + s); }
// FIXME: double check the trap logic
private Object run() throws JSExn {
case ASSERT: if (!JS.toBoolean(stack.pop())) throw je("xwt.assertion.failed" /*FEATURE: line number*/); break;
case BITNOT: stack.push(JS.N(~JS.toLong(stack.pop()))); break;
case BANG: stack.push(JS.B(!JS.toBoolean(stack.pop()))); break;
- case NEWFUNCTION: stack.push(((JSFunction)arg).cloneWithNewParentScope(scope)); break;
+ case NEWFUNCTION: stack.push(((JSFunction)arg)._cloneWithNewParentScope(scope)); break;
case LABEL: break;
case TYPEOF: {
Object o = stack.pop();
if (o == null) stack.push(null);
- else if (o instanceof JS) stack.push(((JS)o).typeName());
+ else if (o instanceof JS) stack.push("object");
else if (o instanceof String) stack.push("string");
else if (o instanceof Number) stack.push("number");
else if (o instanceof Boolean) stack.push("boolean");
- else stack.push("unknown");
+ else throw new Error("this should not happen");
break;
}
}
}
throw new Error("CONTINUE/BREAK invoked but couldn't find LoopMarker at " +
- JS.getSourceName() + ":" + JS.getLine());
+ getSourceName() + ":" + getLine());
case TRY: {
int[] jmps = (int[]) arg;
} else if (o instanceof CallMarker) {
if (scope instanceof Trap.TrapScope) { // handles return component of a read trap
Trap.TrapScope ts = (Trap.TrapScope)scope;
- if (retval != null) ts.cascadeHappened = true;
+ if (retval != null && retval instanceof Boolean && ((Boolean)retval).booleanValue())
+ ts.cascadeHappened = true;
if (!ts.cascadeHappened) {
ts.cascadeHappened = true;
Trap t = ts.t.next;
case THROW:
throw new JSExn(stack.pop());
+ case MAKE_GRAMMAR: {
+ final Grammar r = (Grammar)arg;
+ final JSScope final_scope = scope;
+ Grammar r2 = new Grammar() {
+ public int match(String s, int start, Hash v, JSScope scope) throws JSExn {
+ return r.match(s, start, v, final_scope);
+ }
+ public int matchAndWrite(String s, int start, Hash v, JSScope scope, String key) throws JSExn {
+ return r.matchAndWrite(s, start, v, final_scope, key);
+ }
+ public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ Hash v = new Hash();
+ r.matchAndWrite((String)a0, 0, v, final_scope, "foo");
+ return v.get("foo");
+ }
+ };
+ Object obj = stack.pop();
+ if (obj != null && obj instanceof Grammar) r2 = new Grammar.Alternative((Grammar)obj, r2);
+ stack.push(r2);
+ break;
+ }
+
+ case ADD_TRAP: case DEL_TRAP: {
+ Object val = stack.pop();
+ Object key = stack.pop();
+ Object obj = stack.peek();
+ // A trap addition/removal
+ JS js = obj instanceof JSScope ? ((JSScope)obj).top() : (JS) obj;
+ if(op == ADD_TRAP) js.addTrap(key, (JSFunction)val);
+ else js.delTrap(key, (JSFunction)val);
+ break;
+ }
+
case ASSIGN_SUB: case ASSIGN_ADD: {
Object val = stack.pop();
Object key = stack.pop();
Object obj = stack.peek();
- if (val instanceof JSFunction && obj instanceof JS) {
- // A trap addition/removal
- JS js = obj instanceof JSScope ? ((JSScope)obj).top() : (JS) obj;
- if(op == ASSIGN_ADD) js.addTrap(key, (JSFunction)val);
- else js.delTrap(key, (JSFunction)val);
- pc += ((Integer)arg).intValue() - 1;
- } else {
- // The following setup is VERY important. The generated bytecode depends on the stack
- // being setup like this (top to bottom) KEY, OBJ, VAL, KEY, OBJ
- stack.push(key);
- stack.push(val);
- stack.push(obj);
- stack.push(key);
- }
+ // The following setup is VERY important. The generated bytecode depends on the stack
+ // being setup like this (top to bottom) KEY, OBJ, VAL, KEY, OBJ
+ stack.push(key);
+ stack.push(val);
+ stack.push(obj);
+ stack.push(key);
break;
}