X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fjs%2FCompiledFunctionImpl.java;h=692db3f7cb4987a67edd2b586b63bbe125d90274;hp=ae92d06a7d9428b44e635d1aba7eedc5bc38f4ee;hb=b32cea3f3e272ab00899d134d75a8bd7bcf6c8c0;hpb=6d2f9fba912164ddc3024078aab83258a9d9e522 diff --git a/src/org/xwt/js/CompiledFunctionImpl.java b/src/org/xwt/js/CompiledFunctionImpl.java index ae92d06..692db3f 100644 --- a/src/org/xwt/js/CompiledFunctionImpl.java +++ b/src/org/xwt/js/CompiledFunctionImpl.java @@ -16,7 +16,7 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke /** the first line of this function */ private int firstLine; public int getFirstLine() throws JS.Exn { return firstLine; } - + /** the line numbers */ private int[] line = new int[10]; @@ -37,48 +37,48 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke // Constructors //////////////////////////////////////////////////////// private CompiledFunctionImpl cloneWithNewParentScope(JS.Scope s) throws IOException { - CompiledFunctionImpl ret = new JS.CompiledFunction(sourceName, firstLine, null, s); - ret.paste(this); - return ret; + CompiledFunctionImpl ret = new JS.CompiledFunction(sourceName, firstLine, null, s); + ret.paste(this); + return ret; } protected CompiledFunctionImpl(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException { - this.sourceName = sourceName; - this.firstLine = firstLine; - this.parentScope = parentScope; - if (sourceCode == null) return; - Parser p = new Parser(sourceCode, sourceName, firstLine); - try { - while(true) { - int s = size(); - p.parseStatement(this, null); - if (s == size()) break; - } - add(-1, Tokens.RETURN); - } catch (Exception e) { - if (Log.on) Log.log(Parser.class, e); - } + this.sourceName = sourceName; + this.firstLine = firstLine; + this.parentScope = parentScope; + if (sourceCode == null) return; + Parser p = new Parser(sourceCode, sourceName, firstLine); + try { + while(true) { + int s = size(); + p.parseStatement(this, null); + if (s == size()) break; + } + add(-1, Tokens.RETURN); + } catch (Exception e) { + if (Log.on) Log.log(Parser.class, e); + } } public Object call(JS.Array args) throws JS.Exn { return call(args, new FunctionScope(sourceName, parentScope)); } public Object call(JS.Array args, JS.Scope scope) throws JS.Exn { - CompiledFunctionImpl saved = (CompiledFunctionImpl)Context.currentFunction.get(Thread.currentThread()); - try { - Context.currentFunction.put(Thread.currentThread(), this); - Context cx = Context.getContextForThread(Thread.currentThread()); - int size = cx.stack.size(); - cx.stack.push(new Context.CallMarker()); - cx.stack.push(args); - eval(scope); - 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 " + Context.getCurrentSourceNameAndLine()); - return ret; - } finally { - if (saved == null) Context.currentFunction.remove(Thread.currentThread()); - else Context.currentFunction.put(Thread.currentThread(), saved); - } + CompiledFunctionImpl saved = (CompiledFunctionImpl)Context.currentFunction.get(Thread.currentThread()); + try { + Context.currentFunction.put(Thread.currentThread(), this); + Context cx = Context.getContextForThread(Thread.currentThread()); + int size = cx.stack.size(); + cx.stack.push(new Context.CallMarker()); + cx.stack.push(args); + eval(scope); + 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 " + Context.getCurrentSourceNameAndLine()); + return ret; + } finally { + if (saved == null) Context.currentFunction.remove(Thread.currentThread()); + else Context.currentFunction.put(Thread.currentThread(), saved); + } } @@ -95,7 +95,7 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke Object[] arg2 = new Object[op.length * 2]; System.arraycopy(arg, 0, arg2, 0, arg.length); arg = arg2; int[] op2 = new int[op.length * 2]; System.arraycopy(op, 0, op2, 0, op.length); op = op2; } - this.line[size] = line; + this.line[size] = line; op[size] = op_; arg[size] = arg_; size++; @@ -107,10 +107,10 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke int pc = 0; void eval(JS.Scope s) { - final Vec t = Context.getContextForThread(Thread.currentThread()).stack; + final Vec t = Context.getContextForThread(Thread.currentThread()).stack; OUTER: for(pc=0; pc 0 && op[pc - 1] == LABEL ? (String)arg[pc - 1] : (String)null)); - t.push(Boolean.TRUE); - break; - } + t.push(s); + t.push(new Context.LoopMarker(pc, pc > 0 && op[pc - 1] == LABEL ? (String)arg[pc - 1] : (String)null)); + t.push(Boolean.TRUE); + break; + } case BREAK: - case CONTINUE: - while(t.size() > 0) { - Object o = t.pop(); - if (o instanceof Context.CallMarker) ee("break or continue not within a loop"); - if (o != null && o instanceof Context.LoopMarker) { - if (arg[pc] == null || arg[pc].equals(((Context.LoopMarker)o).label)) { - int loopInstructionLocation = ((Context.LoopMarker)o).location; - int endOfLoop = ((Integer)arg[loopInstructionLocation]).intValue() + loopInstructionLocation; - s = (JS.Scope)t.pop(); - if (op[pc] == CONTINUE) { t.push(s); t.push(o); t.push(Boolean.FALSE); } - pc = op[pc] == BREAK ? endOfLoop - 1 : loopInstructionLocation; - continue OUTER; - } - } - } - throw new Error("CONTINUE/BREAK invoked but couldn't find a LoopMarker at " + sourceName + ":" + line); + case CONTINUE: + while(t.size() > 0) { + Object o = t.pop(); + if (o instanceof Context.CallMarker) ee("break or continue not within a loop"); + if (o != null && o instanceof Context.LoopMarker) { + if (arg[pc] == null || arg[pc].equals(((Context.LoopMarker)o).label)) { + int loopInstructionLocation = ((Context.LoopMarker)o).location; + int endOfLoop = ((Integer)arg[loopInstructionLocation]).intValue() + loopInstructionLocation; + s = (JS.Scope)t.pop(); + if (op[pc] == CONTINUE) { t.push(s); t.push(o); t.push(Boolean.FALSE); } + pc = op[pc] == BREAK ? endOfLoop - 1 : loopInstructionLocation; + continue OUTER; + } + } + } + throw new Error("CONTINUE/BREAK invoked but couldn't find a LoopMarker at " + sourceName + ":" + line); case TRY: { - t.push(new Context.TryMarker(pc + ((Integer)arg[pc]).intValue(), s)); - break; - } + t.push(new Context.TryMarker(pc + ((Integer)arg[pc]).intValue(), s)); + break; + } case RETURN: { - Object retval = t.pop(); - while(t.size() > 0) { - Object o = t.pop(); - if (o != null && o instanceof Context.CallMarker) { - t.push(retval); - return; - } - } - throw new Error("error: RETURN invoked but couldn't find a CallMarker!"); - } + Object retval = t.pop(); + while(t.size() > 0) { + Object o = t.pop(); + if (o != null && o instanceof Context.CallMarker) { + t.push(retval); + return; + } + } + throw new Error("error: RETURN invoked but couldn't find a CallMarker!"); + } case PUT: { Object val = t.pop(); Object key = t.pop(); - Object target = t.peek(); + Object target = t.peek(); if (target == null) - throw je("tried to put a value to the " + key + " property on the null value"); + throw je("tried to put a value to the " + key + " property on the null value"); if (!(target instanceof JS)) - throw je("tried to put a value to the " + key + " property on a " + target.getClass().getName()); + throw je("tried to put a value to the " + key + " property on a " + target.getClass().getName()); ((JS)target).put(key, val); t.push(val); break; @@ -217,27 +217,27 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke case GET: case GET_PRESERVE: { - Object o, v; - if (op[pc] == GET) { - v = t.pop(); - o = t.pop(); - } else { - v = t.pop(); - o = t.peek(); - t.push(v); - } - Object ret = null; - if (o == null) throw je("tried to get property \"" + v + "\" from the null value"); - if (v == null) throw je("tried to get the null key from " + v); - if (o instanceof String) { - ret = getFromString((String)o, v); - } else if (o instanceof Boolean) { - throw je("Not Implemented: properties on Boolean objects"); - } else if (o instanceof Number) { - Log.log(this, "Not Implemented: properties on Number objects"); - } else if (o instanceof JS) { - ret = ((JS)o).get(v); - } + Object o, v; + if (op[pc] == GET) { + v = t.pop(); + o = t.pop(); + } else { + v = t.pop(); + o = t.peek(); + t.push(v); + } + Object ret = null; + if (o == null) throw je("tried to get property \"" + v + "\" from the null value"); + if (v == null) throw je("tried to get the null key from " + v); + if (o instanceof String) { + ret = getFromString((String)o, v); + } else if (o instanceof Boolean) { + throw je("Not Implemented: properties on Boolean objects"); + } else if (o instanceof Number) { + Log.log(this, "Not Implemented: properties on Number objects"); + } else if (o instanceof JS) { + ret = ((JS)o).get(v); + } t.push(ret); break; } @@ -249,27 +249,27 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(t.pop(), j); JS.Callable f = (JS.Callable)t.pop(); if (f == null) throw je("attempted to call null"); - try { - t.push(f.call(arguments)); - break; - } catch (JS.Exn e) { - t.push(e); - } + try { + t.push(f.call(arguments)); + break; + } catch (JS.Exn e) { + t.push(e); + } } // fall through if exception was thrown - case THROW: { - Object exn = t.pop(); - while(t.size() > 0) { - Object o = t.pop(); - if (o instanceof Context.TryMarker) { - t.push(exn); - pc = ((Context.TryMarker)o).location - 1; - s = ((Context.TryMarker)o).scope; - continue OUTER; - } - } - throw new JS.Exn(exn); - } + case THROW: { + Object exn = t.pop(); + while(t.size() > 0) { + Object o = t.pop(); + if (o instanceof Context.TryMarker) { + t.push(exn); + pc = ((Context.TryMarker)o).location - 1; + s = ((Context.TryMarker)o).scope; + continue OUTER; + } + } + throw new JS.Exn(exn); + } case INC: case DEC: { boolean isPrefix = JS.toBoolean(arg[pc]); @@ -316,21 +316,21 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke case URSH: t.push(new Long(JS.toLong(left) >>> JS.toLong(right))); break; case LT: case LE: case GT: case GE: { - if (left == null) left = new Integer(0); - if (right == null) right = new Integer(0); - int result = 0; - if (left instanceof String || right instanceof String) { - result = left.toString().compareTo(right.toString()); - } else { - result = (int)java.lang.Math.ceil(JS.toDouble(left) - JS.toDouble(right)); - } - t.push(new Boolean((op[pc] == LT && result < 0) || (op[pc] == LE && result <= 0) || - (op[pc] == GT && result > 0) || (op[pc] == GE && result >= 0))); - break; - } + if (left == null) left = new Integer(0); + if (right == null) right = new Integer(0); + int result = 0; + if (left instanceof String || right instanceof String) { + result = left.toString().compareTo(right.toString()); + } else { + result = (int)java.lang.Math.ceil(JS.toDouble(left) - JS.toDouble(right)); + } + t.push(new Boolean((op[pc] == LT && result < 0) || (op[pc] == LE && result <= 0) || + (op[pc] == GT && result > 0) || (op[pc] == GE && result >= 0))); + break; + } case EQ: - case NE: { + case NE: { Object l = left; Object r = right; boolean ret; @@ -346,45 +346,45 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke default: throw new Error("unknown opcode " + op[pc]); } } } - } + } } // Helpers for Number, String, and Boolean //////////////////////////////////////// private Object getFromString(final String o, final Object v) { - if (v.equals("length")) return new Integer(((String)o).length()); - else if (v.equals("substring")) return new JS.Callable() { - public Object call(JS.Array args) { - if (args.length() == 1) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue()); - else if (args.length() == 2) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue(), - JS.toNumber(args.elementAt(1)).intValue()); - else throw je("String.substring() can only take one or two arguments"); - } - }; - else if (v.equals("toLowerCase")) return new JS.Callable() { - public Object call(JS.Array args) { - return ((String)o).toLowerCase(); - } }; - else if (v.equals("toUpperCase")) return new JS.Callable() { - public Object call(JS.Array args) { - return ((String)o).toString().toUpperCase(); - } }; - else if (v.equals("charAt")) return new JS.Callable() { - public Object call(JS.Array args) { - return ((String)o).charAt(JS.toNumber(args.elementAt(0)).intValue()) + ""; - } }; - else if (v.equals("lastIndexOf")) return new JS.Callable() { - public Object call(JS.Array args) { - if (args.length() != 1) return null; - return new Integer(((String)o).lastIndexOf(args.elementAt(0).toString())); - } }; - else if (v.equals("indexOf")) return new JS.Callable() { - public Object call(JS.Array args) { - if (args.length() != 1) return null; - return new Integer(((String)o).indexOf(args.elementAt(0).toString())); - } }; - throw je("Not Implemented: propery " + v + " on String objects"); + if (v.equals("length")) return new Integer(((String)o).length()); + else if (v.equals("substring")) return new JS.Callable() { + public Object call(JS.Array args) { + if (args.length() == 1) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue()); + else if (args.length() == 2) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue(), + JS.toNumber(args.elementAt(1)).intValue()); + else throw je("String.substring() can only take one or two arguments"); + } + }; + else if (v.equals("toLowerCase")) return new JS.Callable() { + public Object call(JS.Array args) { + return ((String)o).toLowerCase(); + } }; + else if (v.equals("toUpperCase")) return new JS.Callable() { + public Object call(JS.Array args) { + return ((String)o).toString().toUpperCase(); + } }; + else if (v.equals("charAt")) return new JS.Callable() { + public Object call(JS.Array args) { + return ((String)o).charAt(JS.toNumber(args.elementAt(0)).intValue()) + ""; + } }; + else if (v.equals("lastIndexOf")) return new JS.Callable() { + public Object call(JS.Array args) { + if (args.length() != 1) return null; + return new Integer(((String)o).lastIndexOf(args.elementAt(0).toString())); + } }; + else if (v.equals("indexOf")) return new JS.Callable() { + public Object call(JS.Array args) { + if (args.length() != 1) return null; + return new Integer(((String)o).indexOf(args.elementAt(0).toString())); + } }; + throw je("Not Implemented: propery " + v + " on String objects"); } @@ -398,13 +398,13 @@ public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Toke // FunctionScope ///////////////////////////////////////////////////////////////// private class FunctionScope extends JS.Scope { - String sourceName; - public FunctionScope(String sourceName, Scope parentScope) { super(parentScope); this.sourceName = sourceName; } - public String getSourceName() { return sourceName; } - public Object get(Object key) throws JS.Exn { - if (key.equals("trapee")) return org.xwt.Trap.currentTrapee(); - else if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction; - return super.get(key); - } + String sourceName; + public FunctionScope(String sourceName, Scope parentScope) { super(parentScope); this.sourceName = sourceName; } + public String getSourceName() { return sourceName; } + public Object get(Object key) throws JS.Exn { + if (key.equals("trapee")) return org.xwt.Trap.currentTrapee(); + else if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction; + return super.get(key); + } } }