case OBJECT: stack.push(new JS.Obj()); break;
case ARRAY: stack.push(new JSArray(Script.toInt((JS)arg))); break;
//case DECLARE: scope.declare((JS)(arg==null ? stack.peek() : arg)); if(arg != null) stack.push((JS)arg); break;
- case JT: if (Script.toBoolean(stack.pop())) pc += Script.toInt((JS)arg) - 1; break;
- case JF: if (!Script.toBoolean(stack.pop())) pc += Script.toInt((JS)arg) - 1; break;
+ case JT: if (Script.toBoolean((JS)stack.pop())) pc += Script.toInt((JS)arg) - 1; break;
+ case JF: if (!Script.toBoolean((JS)stack.pop())) pc += Script.toInt((JS)arg) - 1; break;
case JMP: pc += Script.toInt((JS)arg) - 1; break;
case POP: stack.pop(); break;
case SWAP: stack.swap(); break;
case OLDSCOPE: scope = scope.parent; break;
case GLOBALSCOPE: stack.push(scope.getGlobal()); break;
case SCOPEGET: stack.push(scope.get((JS)arg)); break;
- case SCOPEPUT: scope.put((JS)arg,stack.peek()); break;
- case ASSERT: if (!Script.toBoolean(stack.pop())) throw je("ibex.assertion.failed"); break;
- case BITNOT: stack.push(Script.N(~Script.toLong(stack.pop()))); break;
- case BANG: stack.push(Script.B(!Script.toBoolean(stack.pop()))); break;
+ case SCOPEPUT: scope.put((JS)arg, (JS)stack.peek()); break;
+ case ASSERT: if (!Script.toBoolean((JS)stack.pop())) throw je("ibex.assertion.failed"); break;
+ case BITNOT: stack.push(Script.N(~Script.toLong((JS)stack.pop()))); break;
+ case BANG: stack.push(Script.B(!Script.toBoolean((JS)stack.pop()))); break;
case NEWFUNCTION: stack.push(((JSFunction)arg)._cloneWithNewParentScope(scope)); break;
case LABEL: break;
int loopInstructionLocation = ((LoopMarker)o).location;
int endOfLoop = Script.toInt((JS)f.arg[loopInstructionLocation]) + loopInstructionLocation;
scope = ((LoopMarker)o).scope;
- if (op == CONTINUE) { stack.push(o); stack.push(JS.F); }
+ if (op == CONTINUE) { stack.push(o); stack.push(Script.F); }
pc = op == BREAK ? endOfLoop - 1 : loopInstructionLocation;
continue OUTER;
}
case CASCADE: {
boolean write = Script.toBoolean((JS)arg);
- JS val = write ? stack.pop() : null;
+ JS val = write ? (JS)stack.pop() : null;
CallMarker o = stack.findCall();
if(!(o instanceof TrapMarker)) throw new JSExn("tried to CASCADE while not in a trap");
TrapMarker tm = (TrapMarker) o;
boolean ret;
if(left == null && right == null) ret = true;
else if(left == null || right == null) ret = false;
- else ret = left.jsequals(right);
+ else ret = left.equals(right);
stack.push(Script.B(op == EQ ? ret : !ret)); break;
}
if(cm.f == null) break;
String s = cm.f.sourceName + ":" + cm.f.line[cm.pc-1];
if(cm instanceof Interpreter.TrapMarker)
- s += " (trap on " + Script.str(((Interpreter.TrapMarker)cm).t.key) + ")";
+ s += " (trap on " + Script.str(((Interpreter.TrapMarker)cm).t.key()) + ")";
e.addBacktrace(s);
}
}
return (JS)new Interpreter(t, val, true).run(null);
}
- /** returns a callback which will restart the context; expects a value to be pushed onto the stack when unpaused */
- public static UnpauseCallback pause() throws NotPauseableException {
- Interpreter i = Interpreter.current();
- if (i.pausecount == -1) throw new NotPauseableException();
- boolean get;
- switch(i.f.op[i.pc]) {
- case Tokens.RETURN: case ByteCodes.PUT: get = false; break;
- case ByteCodes.GET: case ByteCodes.CALL: get = true; break;
- default: throw new Error("should never happen");
+ public void addTrap(JS key, JS f) throws JSExn {
+ if (f.getFormalArgs() == null || f.getFormalArgs().length > 1) throw new JSExn(
+ "traps must take either one argument (write) or no arguments (read)");
+ int i = indexOf(key); if (i < 0) i = put(i, key);
+ for (Trap t = (Trap)entries[i + 2]; t != null; t = t.next())
+ if (t.function().equals(f)) return;
+ entries[i + 2] = new TrapHolder(this, key, f, (Trap)entries[i + 2]);
}
public void delTrap(JS key, JS f) throws JSExn {
// fall through
}
default: {
- JS[] args = new JS[nargs];
- for(int i=0; i<nargs; i++) args[i] = i==0 ? a0 : i==1 ? a1 : i==2 ? a2 : rest[i-3];
//#switch(Script.toString(method))
case "setMilliseconds": return Script.N(this.makeTime(args, 1, true));
case "setUTCMilliseconds": return Script.N(this.makeTime(args, 1, false));
}
case 1: {
double date;
- if(Script.isString(a0))
- date = date_parseString(Script.toString(a0));
+ if(Script.isString(args[0]))
+ date = date_parseString(Script.toString(args[0]));
else
date = _toNumber(args[0]);
obj.date = TimeClip(date);
package org.ibex.js;
/** The JavaScript Math object */
-class JSMath extends JS {
+class JSMath extends JS.Immutable {
+ private static final JS.Method METHOD = new JS.Method();
+
private static final JS E = Script.N(java.lang.Math.E);
private static final JS PI = Script.N(java.lang.Math.PI);
private static final JS LN10 = Script.N(java.lang.Math.log(10));
private static final JS SQRT1_2 = Script.N(1/java.lang.Math.sqrt(2));
private static final JS SQRT2 = Script.N(java.lang.Math.sqrt(2));
- public JS callMethod(JS method, JS[] args) throws JSExn {
+ public JS call(JS method, JS[] args) throws JSExn {
switch(args.length) {
case 0: {
//#switch(Script.toString(method))
//#switch(Script.toString(method))
case "substring": {
- int a = alength >= 1 ? Script.toInt(arg0) : 0;
- int b = alength >= 2 ? Script.toInt(arg1) : slength;
+ int a = args.length >= 1 ? Script.toInt(args[0]) : 0;
+ int b = args.length >= 2 ? Script.toInt(args[1]) : slength;
if (a > slength) a = slength;
if (b > slength) b = slength;
if (a < 0) a = 0;
return Script.S(s.substring(a,b));
}
case "substr": {
- int start = alength >= 1 ? Script.toInt(arg0) : 0;
- int len = alength >= 2 ? Script.toInt(arg1) : Integer.MAX_VALUE;
+ int start = args.length >= 1 ? Script.toInt(args[0]) : 0;
+ int len = args.length >= 2 ? Script.toInt(args[1]) : Integer.MAX_VALUE;
if (start < 0) start = slength + start;
if (start < 0) start = 0;
if (len < 0) len = 0;
return Script.S(s.substring(start,start+len));
}
case "charAt": {
- int p = alength >= 1 ? Script.toInt(arg0) : 0;
+ int p = args.length >= 1 ? Script.toInt(args[0]) : 0;
if (p < 0 || p >= slength) return Script.S("");
return Script.S(s.substring(p,p+1));
}
case "charCodeAt": {
- int p = alength >= 1 ? Script.toInt(arg0) : 0;
+ int p = args.length >= 1 ? Script.toInt(args[0]) : 0;
if (p < 0 || p >= slength) return Script.N(Double.NaN);
return Script.N(s.charAt(p));
}
return Script.S(sb.toString());
}
case "indexOf": {
- String search = alength >= 1 ? Script.toString(arg0) : "null";
- int start = alength >= 2 ? Script.toInt(arg1) : 0;
+ String search = args.length >= 1 ? Script.toString(args[0]) : "null";
+ int start = args.length >= 2 ? Script.toInt(args[1]) : 0;
// Java's indexOf handles an out of bounds start index, it'll return -1
return Script.N(s.indexOf(search,start));
}
case "lastIndexOf": {
- String search = alength >= 1 ? Script.toString(arg0) : "null";
- int start = alength >= 2 ? Script.toInt(arg1) : 0;
+ String search = args.length >= 1 ? Script.toString(args[0]) : "null";
+ int start = args.length >= 2 ? Script.toInt(args[1]) : 0;
// Java's indexOf handles an out of bounds start index, it'll return -1
return Script.N(s.lastIndexOf(search,start));
}
- case "match": return JSRegexp.stringMatch(this,arg0);
- case "replace": return JSRegexp.stringReplace(this,arg0,arg1);
- case "search": return JSRegexp.stringSearch(this,arg0);
- case "split": return JSRegexp.stringSplit(this,arg0,arg1,alength);
+ case "match": return JSRegexp.stringMatch(this,args[0]);
+ case "replace": return JSRegexp.stringReplace(this,args[0],args[1]);
+ case "search": return JSRegexp.stringSearch(this,args[0]);
+ case "split": return JSRegexp.stringSplit(this,args[0],args[1],args.length);
case "toLowerCase": return Script.S(s.toLowerCase());
case "toUpperCase": return Script.S(s.toUpperCase());
case "slice": {
- int a = alength >= 1 ? Script.toInt(arg0) : 0;
- int b = alength >= 2 ? Script.toInt(arg1) : slength;
+ int a = args.length >= 1 ? Script.toInt(args[0]) : 0;
+ int b = args.length >= 2 ? Script.toInt(args[1]) : slength;
if (a < 0) a = slength + a;
if (b < 0) b = slength + b;
if (a < 0) a = 0;
case 1: {
//#switch(Script.str(method))
case "exec": {
- String s = Script.toString(a0);
+ String s = Script.toString(args[0]);
int start = global ? lastIndex : 0;
if(start < 0 || start >= s.length()) { lastIndex = 0; return null; }
GnuRegexp.REMatch match = re.getMatch(s,start);
return match == null ? null : matchToExecResult(match,re,s);
}
case "test": {
- String s = Script.toString(a0);
- if (!global) return B(re.getMatch(s) != null);
+ String s = Script.toString(args[0]);
+ if (!global) return Script.B(re.getMatch(s) != null);
int start = global ? lastIndex : 0;
if(start < 0 || start >= s.length()) { lastIndex = 0; return null; }
GnuRegexp.REMatch match = re.getMatch(s,start);
lastIndex = match != null ? s.length() : match.getEndIndex();
- return B(match != null);
+ return Script.B(match != null);
}
case "toString": return Script.S(args[0].coerceToString());
//#end
if(sep != null && sep.length()==0) {
int len = s.length();
for(int i=0;i<len;i++)
- ret.addElement(Script.S(s.substring(i,i+1)));
+ ret.add(Script.S(s.substring(i,i+1)));
return ret;
}
GnuRegexp.REMatch m = re.getMatch(s,p);
if(m == null) break OUTER;
boolean zeroLength = m.getStartIndex() == m.getEndIndex();
- ret.addElement(Script.S(s.substring(p,zeroLength ? m.getStartIndex()+1 : m.getStartIndex())));
+ ret.add(Script.S(s.substring(p,zeroLength ? m.getStartIndex()+1 : m.getStartIndex())));
p = zeroLength ? p + 1 : m.getEndIndex();
if(!zeroLength) {
for(int i=1;i<=re.getNumSubs();i++) {
- ret.addElement(Script.S(m.toString(i)));
- if(ret.length() == limit) break OUTER;
+ ret.add(Script.S(m.toString(i)));
+ if(ret.size() == limit) break OUTER;
}
}
} else {
int x = s.indexOf(sep,p);
if(x == -1) break OUTER;
- ret.addElement(Script.S(s.substring(p,x)));
+ ret.add(Script.S(s.substring(p,x)));
p = x + sep.length();
}
- if(ret.length() == limit) break;
+ if(ret.size() == limit) break;
}
- if(p < s.length() && ret.length() != limit)
- ret.addElement(Script.S(s.substring(p)));
+ if(p < s.length() && ret.size() != limit)
+ ret.add(Script.S(s.substring(p)));
return ret;
}
// FEATURE: Update for new api
/** A JS interface to a Java '.properties' file; very crude */
-public class PropertyFile extends JS {
+public class PropertyFile extends JS.Immutable {
/*private final Properties p = new Properties();
private final Hash cache = new Hash(10, 3);
public static void main(String[] args) throws Exception {
if(args.length == 0) { System.err.println("Usage Test filename"); System.exit(1); }
- JS f = JS.fromReader(args[0],1,new FileReader(args[0]));
+ JS f = Script.fromReader(args[0],1,new FileReader(args[0]));
System.out.println(((JSFunction)f).dump());
- JS s = new JS.O();
+ JS s = new JS.Obj();
s.put(Script.S("sys"),new Test());
f = Script.cloneWithNewGlobalScope(f,s);
//JS ret = f.call(null,null,null,null,0);
}
public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
- if(!JS.isString(method)) return null;
+ if(!Script.isString(method)) return null;
if("print".equals(Script.toString(method))) {
System.out.println(Script.str(a0));
return null;
}
- if("clone".equals(Script.toString(method))) return a0 == null ? null : a0.jsclone();
+ if("clone".equals(Script.toString(method))) return a0 == null ? null : new JS.Clone(a0);
if("firethis".equals(Script.toString(method))) {
String action = Script.toString(a0);
JS target = a1;