X-Git-Url: http://git.megacz.com/?p=org.ibex.js.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fjs%2FJSArray.java;h=8e2fdd2cbcc645e63e4e7f0cc09119e163f1bf8b;hp=70387269b1dcdd8f557c6673f2aa6ec44afa47bb;hb=a1e6b7e9307319c0195b0efbe5e5354c128be481;hpb=19d66e161db458135518efd3539048f44e1e5622 diff --git a/src/org/ibex/js/JSArray.java b/src/org/ibex/js/JSArray.java index 7038726..8e2fdd2 100644 --- a/src/org/ibex/js/JSArray.java +++ b/src/org/ibex/js/JSArray.java @@ -1,176 +1,131 @@ -// 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; +import java.io.InputStream; import org.ibex.util.*; -import java.util.*; /** A JavaScript JSArray */ -public class JSArray extends JS.O { - private static final Object NULL = new Object(); - private final BalancedTree bt = new BalancedTree(); - - public JSArray() { } - public JSArray(int size) { setSize(size); } - - /*private static int intVal(Object o) { - if (o instanceof Number) { - int intVal = ((Number)o).intValue(); - if (intVal == ((Number)o).doubleValue()) return intVal; - return Integer.MIN_VALUE; - } - if (!(o instanceof String)) return Integer.MIN_VALUE; - String s = (String)o; - for(int i=0; i '9') return Integer.MIN_VALUE; - return Integer.parseInt(s); - }*/ - - public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { - //#switch(JS.toString(method)) - case "pop": { - int oldSize = size(); - if(oldSize == 0) return null; - return removeElementAt(oldSize-1); +class JSArray extends Basket.Array implements JS, Basket.CompareFunc { + private static final JS.Method METHOD = new JS.Method(); + private static final String[] empty = new String[0]; + + JSArray() { } + JSArray(int size) { super(size); } + JSArray(JS[] args) { super(args.length); addAll(args); } + JSArray(JS arg) { super(1); add(arg); } + + public JS unclone() { return this; } + public JS.Enumeration keys() throws JSExn { + return new Enumeration(null) { + private int n = 0; + public boolean _hasNext() { return n < size(); } + public JS _next() { return JSU.N(n++); } + }; + } + public JS get(JS key) throws JSExn { + if (key == null || !(key instanceof JSNumber.I)) { + //#switch(JSU.str(key)) + case "pop": return METHOD; + case "reverse": return METHOD; + case "toString": return METHOD; + case "shift": return METHOD; + case "join": return METHOD; + case "sort": return METHOD; + case "slice": return METHOD; + case "push": return METHOD; + case "unshift": return METHOD; + case "splice": return METHOD; + case "length": return JSU.N(size()); + //#end + throw new JSExn("arrays only support positive integer keys, can not use: "+JSU.str(key)); } - case "reverse": return reverse(); + return (JS)get(((JSNumber.I)key).toInt()); + } + public void put(JS key, JS val) throws JSExn { + if (JSU.str(key).equals("length")) { setSize(JSU.toInt(val)); } + + if (key == null || !(key instanceof JSNumber.I)) throw new JSExn( + "arrays only support positive integer keys, can not use: "+JSU.str(key)); + int i = ((JSNumber.I)key).toInt(); + if (i < 0) throw new JSExn("arrays can not use negative integer keys "+i); + size(i + 1); while (size() < i) add(null); + set(i, val); + } + public InputStream getInputStream() { return null; } + + public String[] getFormalArgs() { return empty; } + public String coerceToString() { return "array"; } // FIXME + + public boolean hasKey(JS key) { + if (key == null || !(key instanceof JSNumber.I)) return false; + int i = ((JSNumber.I)key).toInt(); + return 0 <= i && i < size(); + } + + public Object run(Object o) throws JSExn { return call(null); } + public void pause() throws NotPausableException { throw new NotPausableException(); } + public JS call(JS[] args) throws JSExn { throw new JSExn("can not call an array as a function"); } + public JS call(JS method, JS[] args) throws JSExn { + //#switch(JSU.str(method)) + case "pop": return size() == 0 ? null : (JS)remove(size() - 1); + case "push": addAll(args); return JSU.N(size()); + case "reverse": reverse(); return this; case "toString": return join(","); - case "shift": - if(length() == 0) return null; - return removeElementAt(0); - case "join": - return join(nargs == 0 ? "," : JS.toString(a0)); - case "sort": - return sort(nargs < 1 ? null : a0); + case "shift": return size() == 0 ? null : (JS)remove(0); + case "join": return join(args.length == 0 ? "," : JSU.str(args[0])); + case "sort": return sort(args.length == 0 ? null : args[0]); case "slice": - int start = toInt(nargs < 1 ? null : a0); - int end = nargs < 2 ? length() : toInt(a1); + int start = JSU.toInt(args.length < 1 ? null : args[0]); + int end = args.length < 2 ? size() : JSU.toInt(args[1]); return slice(start, end); - case "push": { - int oldSize = size(); - for(int i=0; i= size()) return null; - return elementAt(i); - } - //#switch(JS.toString(key)) - case "pop": return METHOD; - case "reverse": return METHOD; - case "toString": return METHOD; - case "shift": return METHOD; - case "join": return METHOD; - case "sort": return METHOD; - case "slice": return METHOD; - case "push": return METHOD; - case "unshift": return METHOD; - case "splice": return METHOD; - case "length": return N(size()); + for (int i=0; i < args.length; i++) add(i, args[i]); + return JSU.N(size()); + case "splice": return splice(args); //#end - return super.get(key); - } - public void put(JS key, JS val) throws JSExn { - if (isInt(key)) { - int i = toInt(key); - int oldSize = size(); - if(i < oldSize) { - setElementAt(val,i); - } else { - if(i > oldSize) setSize(i); - insertElementAt(val,i); - } - return; - } - if(isString(key)) { - if (JS.toString(key).equals("length")) { - setSize(JS.toInt(val)); - return; - } - } - super.put(key,val); + throw new JSExn("arrays have no function: "+JSU.str(method)); } - public Enumeration keys() throws JSExn { - return new Enumeration(super.keys()) { - private int n = 0; - public boolean _hasMoreElements() { return n < size(); } - public JS _nextElement() { - return n >= size() ? null : JS.N(n++); - } - }; - } + public JS putAndTriggerTraps(JS key, JS val) throws JSExn { put(key, val); return val; } + public JS getAndTriggerTraps(JS key) throws JSExn { return get(key); } + public JS justTriggerTraps(JS key, JS val) throws JSExn { return val; } - public final void setSize(int newSize) { - // FEATURE: This could be done a lot more efficiently in BalancedTree - int oldSize = size(); - for(int i=oldSize;i=newSize;i--) removeElementAt(i); - } - - public final int length() { return size(); } - public final JS elementAt(int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - Object o = bt.getNode(i); - return o == NULL ? (JS)null : (JS)o; - } - public final void addElement(JS o) { - bt.insertNode(size(),o==null ? NULL : o); - } - public final void setElementAt(JS o, int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - bt.replaceNode(i,o==null ? NULL : o); - } - public final void insertElementAt(JS o, int i) { - if(i < 0 || i > size()) throw new ArrayIndexOutOfBoundsException(i); - bt.insertNode(i,o==null ? NULL : o); - } - public final JS removeElementAt(int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - Object o = bt.deleteNode(i); - return o == NULL ? (JS)null : (JS)o; + public void addTrap(JS k, JS f) throws JSExn { throw new JSExn("arrays do not support traps"); } + public void delTrap(JS k, JS f) throws JSExn { throw new JSExn("arrays do not support traps"); } + public JS.Trap getTrap(JS k) throws JSExn { throw new JSExn("arrays do not support traps"); } + + /** FIXME: move to specialised ArrayStore superclass. */ + public void addAll(JS[] entries) { for (int i=0; i < entries.length; i++) add(entries[i]); } + + public void setSize(int newSize) { + size(newSize); + for (int i=size(); i < newSize; i++) add(null); + for (int i=size() - 1; i >= newSize; i--) remove(i); } - - public final int size() { return bt.treeSize(); } - + + + // ECMA Implementation //////////////////////////////////////////////////// + private JS join(String sep) throws JSExn { int length = size(); - if(length == 0) return JS.S(""); + if(length == 0) return JSU.S(""); StringBuffer sb = new StringBuffer(64); int i=0; while(true) { - JS o = elementAt(i); - if(o != null) sb.append(JS.toString(o)); + JS o = (JS)get(i); + if(o != null) sb.append(JSU.toString(o)); if(++i == length) break; sb.append(sep); } - return JS.S(sb.toString()); - } - - // FEATURE: Implement this more efficiently - private JS reverse() { - int size = size(); - if(size < 2) return this; - Vec vec = toVec(); - bt.clear(); - for(int i=size-1,j=0;i>=0;i--,j++) insertElementAt((JS)vec.elementAt(i),j); - return this; + return JSU.S(sb.toString()); } - + private JS slice(int start, int end) { - int length = length(); + int length = size(); if(start < 0) start = length+start; if(end < 0) end = length+end; if(start < 0) start = 0; @@ -178,45 +133,16 @@ public class JSArray extends JS.O { if(start > length) start = length; if(end > length) end = length; JSArray a = new JSArray(end-start); - for(int i=0;i 0) { setSize(newLength); for(int i=newLength-1;i>=start+newCount;i--) - setElementAt(elementAt(i-lengthChange),i); + set(i, get(i-lengthChange)); } else if(lengthChange < 0) { for(int i=start+newCount;i