X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fjs%2FJSScope.java;h=6570840deeccba7249d225671e2940f6f313f7d1;hb=73131826a18c93af4fb04672bc3ec820e1197ad1;hp=675ddc7334b2eaf9154965a7c184c469cf8fe063;hpb=b1fa73c17b31f268fca5695d0876d7314fbacce3;p=org.ibex.js.git diff --git a/src/org/ibex/js/JSScope.java b/src/org/ibex/js/JSScope.java index 675ddc7..6570840 100644 --- a/src/org/ibex/js/JSScope.java +++ b/src/org/ibex/js/JSScope.java @@ -1,26 +1,63 @@ -// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache Public Source License 2.0 ("the License"). +// You may not use this file except in compliance with the License. + package org.ibex.js; -// FIXME: should allow parentScope to be a JS, not a JSScope /** Implementation of a JavaScript Scope */ -public class JSScope extends JS { +class JSScope extends JS.O { + + private final int base; + private final JS[] vars; + final JSScope parent; + public static class Top extends JSScope { + private final JS global; + public Top(JS global) { super(null,0,0); this.global = global; } + JS get(int i) throws JSExn { throw new JSExn("scope index out of range"); } + void put(int i, JS o) throws JSExn { throw new JSExn("scope index out of range"); } + JS getGlobal() { return global; } + }; + + // NOTE: We can't just set base to parent.base + parent.vars.length + // sometimes we only access part of a parent's scope + public JSScope(JSScope parent, int base, int size) { + this.parent = parent; + this.base = base; + this.vars = new JS[size]; + } + + JS get(int i) throws JSExn { return i < base ? parent.get(i) : vars[i-base]; } + void put(int i, JS o) throws JSExn { if(i < base) parent.put(i,o); else vars[i-base] = o; } + + JS getGlobal() { return parent.getGlobal(); } + private JSScope parentScope; - private static final Object NULL_PLACEHOLDER = new Object(); + private static final JS NULL_PLACEHOLDER = new JS() { }; - public JSScope(JSScope parentScope) { this.parentScope = parentScope; } - public void declare(String s) throws JSExn { super.put(s, NULL_PLACEHOLDER); } + public JSScope(JSScope parentScope) { this(parentScope, 0, 0); } + public void declare(JS s) throws JSExn { super.put(s, NULL_PLACEHOLDER); } public JSScope getParentScope() { return parentScope; } - public Object get(Object key) throws JSExn { - Object o = super.get(key); + public JS get(JS key) throws JSExn { + if (key instanceof JSNumber) try { + return get(JS.toInt(key)); + } catch(ArrayIndexOutOfBoundsException e) { + throw new JSExn("scope index out of range"); + } + JS o = super.get(key); if (o != null) return o == NULL_PLACEHOLDER ? null : o; else return parentScope == null ? null : parentScope.get(key); } - public boolean has(Object key) throws JSExn { return super.get(key) != null; } - public void put(Object key, Object val) throws JSExn { + public boolean has(JS key) throws JSExn { return super.get(key) != null; } + public void put(JS key, JS val) throws JSExn { + if (key instanceof JSNumber) try { + put(JS.toInt(key),val); + } catch(ArrayIndexOutOfBoundsException e) { + throw new JSExn("scope index out of range"); + } if (parentScope != null && !has(key)) parentScope.put(key, val); else super.put(key, val == null ? NULL_PLACEHOLDER : val); } @@ -32,73 +69,69 @@ public class JSScope extends JS { } public static class Global extends JSScope { - private final static Double NaN = new Double(Double.NaN); - private final static Double POSITIVE_INFINITY = new Double(Double.POSITIVE_INFINITY); + private final static JS NaN = JS.N(Double.NaN); + private final static JS POSITIVE_INFINITY = JS.N(Double.POSITIVE_INFINITY); public Global() { super(null); } - public Object get(Object key) throws JSExn { - //#switch(key) - case "NaN": return NaN; + public Global(JSScope p) { super(p); } + + public void declare(JS k) throws JSExn { throw new JSExn("can't declare variables in the global scope"); } + + // HACK: "this" gets lost on the way back through the scope chain + // We'll have to do something better with this when Scope is rewritten + public JS get(JS key) throws JSExn { + JS ret = _get(key); + if(ret == JS.METHOD) return new Interpreter.Stub(this,key); + return ret; + } + + public JS _get(JS key) throws JSExn { + //#switch(JS.toString(key)) + case "JS.NaN": return JS.NaN; case "Infinity": return POSITIVE_INFINITY; case "undefined": return null; - case "stringFromCharCode": return METHOD; - case "parseInt": return METHOD; - case "isNaN": return METHOD; - case "isFinite": return METHOD; - case "decodeURI": return METHOD; - case "decodeURIComponent": return METHOD; - case "encodeURI": return METHOD; - case "encodeURIComponent": return METHOD; - case "escape": return METHOD; - case "unescape": return METHOD; - case "parseInt": return METHOD; + case "stringFromCharCode": return JS.METHOD; + case "parseInt": return JS.METHOD; + case "parseFloat": return JS.METHOD; + case "isJS.NaN": return JS.METHOD; + case "isFinite": return JS.METHOD; + case "decodeURI": return JS.METHOD; + case "decodeURIComponent": return JS.METHOD; + case "encodeURI": return JS.METHOD; + case "encodeURIComponent": return JS.METHOD; + case "escape": return JS.METHOD; + case "unescape": return JS.METHOD; + default: return super.get(key); //#end return super.get(key); } - public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn { - switch(nargs) { - case 0: { - //#switch(method) - case "stringFromCharCode": - char buf[] = new char[nargs]; - for(int i=0; i 36)) return NaN; + if(radix != 0 && (radix < 2 || radix > 36)) return JS.NaN; while(start < length && Character.isWhitespace(s.charAt(start))) start++; if((length >= start+1) && (s.charAt(start) == '+' || s.charAt(start) == '-')) { sign = s.charAt(start) == '+' ? 1 : -1; @@ -115,7 +148,7 @@ public class JSScope extends JS { } } if(radix == 0) radix = 10; - if(length == start || Character.digit(s.charAt(start),radix) == -1) return NaN; + if(length == start || Character.digit(s.charAt(start),radix) == -1) return JS.NaN; // try the fast way first try { String s2 = start == 0 ? s : s.substring(start); @@ -126,14 +159,14 @@ public class JSScope extends JS { int digit = Character.digit(s.charAt(i),radix); if(digit < 0) break; n = n*radix + digit; - if(n < 0) return NaN; // overflow; + if(n < 0) return JS.NaN; // overflow; } if(n <= Integer.MAX_VALUE) return JS.N(sign*(int)n); return JS.N((long)sign*n); } - private Object parseFloat(Object arg) { - String s = (String)arg; + private JS parseFloat(JS arg) throws JSExn { + String s = JS.toString(arg); int start = 0; int length = s.length(); while(start < length && Character.isWhitespace(s.charAt(0))) start++; @@ -142,11 +175,11 @@ public class JSScope extends JS { // trailing garbage while(start < end) { try { - return JS.N(s.substring(start,length)); + return JS.N(new Double(s.substring(start,length))); } catch(NumberFormatException e) { } end--; } - return NaN; + return JS.NaN; } } }