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=52c1878ce670a18beb70b810fce9f9ad4e45898f;hb=a1e6b7e9307319c0195b0efbe5e5354c128be481;hpb=e43daa0ce0ebd7cf6045430ed62a2562c0502c23 diff --git a/src/org/ibex/js/JSArray.java b/src/org/ibex/js/JSArray.java index 52c1878..8e2fdd2 100644 --- a/src/org/ibex/js/JSArray.java +++ b/src/org/ibex/js/JSArray.java @@ -1,174 +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 { - private static final Object NULL = new Object(); +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); } - private BalancedTree arr = 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; + 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)); } - 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); + return (JS)get(((JSNumber.I)key).toInt()); } - - public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn { - //#switch(method) - case "pop": { - int oldSize = size(); - if(oldSize == 0) return null; - return removeElementAt(oldSize-1); - } - case "reverse": return reverse(); + 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(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(Object key, Object val) throws JSExn { - if (key.equals("length")) setSize(toInt(val)); - int i = intVal(key); - if (i == Integer.MIN_VALUE) - super.put(key, val); - else { - int oldSize = size(); - if(i < oldSize) { - setElementAt(val,i); - } else { - if(i > oldSize) setSize(i); - insertElementAt(val,i); - } - } + throw new JSExn("arrays have no function: "+JSU.str(method)); } - public Enumeration keys() { - return new Enumeration() { - private int n = size(); - public boolean hasMoreElements() { return n > 0; } - public Object nextElement() { - if(n == 0) throw new NoSuchElementException(); - return new Integer(--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 Object elementAt(int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - Object o = arr.getNode(i); - return o == NULL ? null : o; - } - public final void addElement(Object o) { - arr.insertNode(size(),o==null ? NULL : o); - } - public final void setElementAt(Object o, int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - arr.replaceNode(i,o==null ? NULL : o); - } - public final void insertElementAt(Object o, int i) { - if(i < 0 || i > size()) throw new ArrayIndexOutOfBoundsException(i); - arr.insertNode(i,o==null ? NULL : o); - } - public final Object removeElementAt(int i) { - if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i); - Object o = arr.deleteNode(i); - return o == NULL ? null : 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 arr.treeSize(); } - public String typeName() { return "array"; } - - private Object join(String sep) { + + + // ECMA Implementation //////////////////////////////////////////////////// + + private JS join(String sep) throws JSExn { int length = size(); - if(length == 0) return ""; + if(length == 0) return JSU.S(""); StringBuffer sb = new StringBuffer(64); int i=0; while(true) { - Object 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 sb.toString(); + return JSU.S(sb.toString()); } - - // FEATURE: Implement this more efficiently - private Object reverse() { - int size = size(); - if(size < 2) return this; - Vec vec = toVec(); - arr.clear(); - for(int i=size-1,j=0;i>=0;i--,j++) insertElementAt(vec.elementAt(i),j); - return this; - } - - private Object slice(int start, int end) { - int length = length(); + + private JS slice(int start, int end) { + int length = size(); if(start < 0) start = length+start; if(end < 0) end = length+end; if(start < 0) start = 0; @@ -176,45 +133,16 @@ public class JSArray extends JS { 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