diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-05-28 13:42:16 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-05-28 13:42:16 +0000 |
commit | ff27522840fb3c1681c331ad1fb44a313bd44e0a (patch) | |
tree | ea768d176e1bb88323e9e62cba1db3f962a7f3d2 /src | |
parent | b045a379215d1f48e6a2e6cedcdb41526cd5bb25 (diff) |
first cut of chunked seqs
Chunked seqs, initial Java-side support
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/ArrayChunk.java | 32 | ||||
-rw-r--r-- | src/jvm/clojure/lang/ChunkedCons.java | 74 | ||||
-rw-r--r-- | src/jvm/clojure/lang/IChunkedSeq.java | 23 | ||||
-rw-r--r-- | src/jvm/clojure/lang/IPersistentVector.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Indexed.java | 17 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LazySeq.java | 24 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentVector.java | 80 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 8 |
8 files changed, 249 insertions, 13 deletions
diff --git a/src/jvm/clojure/lang/ArrayChunk.java b/src/jvm/clojure/lang/ArrayChunk.java new file mode 100644 index 00000000..92240440 --- /dev/null +++ b/src/jvm/clojure/lang/ArrayChunk.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich May 24, 2009 */ + +package clojure.lang; + +public class ArrayChunk implements Indexed{ + +final Object[] array; +final int off; + +public ArrayChunk(Object[] array, int off){ + this.array = array; + this.off = off; +} + +public Object nth(int i){ + return array[off + i]; +} + +public int count(){ + return array.length - off; +} +} diff --git a/src/jvm/clojure/lang/ChunkedCons.java b/src/jvm/clojure/lang/ChunkedCons.java new file mode 100644 index 00000000..37f5f47c --- /dev/null +++ b/src/jvm/clojure/lang/ChunkedCons.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich May 25, 2009 */ + +package clojure.lang; + +final public class ChunkedCons extends ASeq implements IChunkedSeq{ + +final Indexed chunk; +final ISeq _more; +final int offset; + +ChunkedCons(IPersistentMap meta, Indexed chunk, int offset, ISeq more){ + super(meta); + this.chunk = chunk; + this.offset = offset; + this._more = more; +} +public ChunkedCons(Indexed chunk, ISeq more){ + this(chunk, 0, more); +} + +public ChunkedCons(Indexed chunk, int offset, ISeq more){ + this.chunk = chunk; + this.offset = offset; + this._more = more; +} + +public Obj withMeta(IPersistentMap meta){ + if(meta != _meta) + return new ChunkedCons(meta, chunk, offset, _more); + return this; +} + +public Object first(){ + return chunk.nth(offset); +} + +public ISeq next(){ + if(offset + 1 < chunk.count()) + return new ChunkedCons(chunk, offset + 1, _more); + return chunkedNext(); +} + +public ISeq more(){ + if(offset + 1 < chunk.count()) + return new ChunkedCons(chunk, offset + 1, _more); + if(_more == null) + return PersistentList.EMPTY; + return _more; +} + +public Indexed chunkedFirst(){ + return chunk; +} + +public ISeq chunkedNext(){ + return chunkedMore().seq(); +} + +public ISeq chunkedMore(){ + if(_more == null) + return PersistentList.EMPTY; + return _more; +} +} diff --git a/src/jvm/clojure/lang/IChunkedSeq.java b/src/jvm/clojure/lang/IChunkedSeq.java new file mode 100644 index 00000000..f53c3534 --- /dev/null +++ b/src/jvm/clojure/lang/IChunkedSeq.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich May 24, 2009 */ + +package clojure.lang; + +public interface IChunkedSeq extends ISeq{ + +Indexed chunkedFirst() throws Exception; + +ISeq chunkedNext() throws Exception; + +ISeq chunkedMore() throws Exception; + +} diff --git a/src/jvm/clojure/lang/IPersistentVector.java b/src/jvm/clojure/lang/IPersistentVector.java index b85f2ab2..c9fdf3ec 100644 --- a/src/jvm/clojure/lang/IPersistentVector.java +++ b/src/jvm/clojure/lang/IPersistentVector.java @@ -10,11 +10,9 @@ package clojure.lang; * You must not remove this notice, or any other, from this software.
*/
-public interface IPersistentVector extends Associative, Sequential, IPersistentStack, Reversible, Counted{
+public interface IPersistentVector extends Associative, Sequential, IPersistentStack, Reversible, Indexed{
int length();
-Object nth(int i);
-
IPersistentVector assocN(int i, Object val);
IPersistentVector cons(Object o);
diff --git a/src/jvm/clojure/lang/Indexed.java b/src/jvm/clojure/lang/Indexed.java new file mode 100644 index 00000000..6f251377 --- /dev/null +++ b/src/jvm/clojure/lang/Indexed.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich May 24, 2009 */ + +package clojure.lang; + +public interface Indexed extends Counted{ +Object nth(int i); +} diff --git a/src/jvm/clojure/lang/LazySeq.java b/src/jvm/clojure/lang/LazySeq.java index 7711a554..a853e9b3 100644 --- a/src/jvm/clojure/lang/LazySeq.java +++ b/src/jvm/clojure/lang/LazySeq.java @@ -17,6 +17,7 @@ import java.util.*; public final class LazySeq extends Obj implements ISeq, List{ private IFn fn; +private Object sv; private ISeq s; public LazySeq(IFn fn){ @@ -33,12 +34,12 @@ public Obj withMeta(IPersistentMap meta){ return new LazySeq(meta, seq()); } -final synchronized public ISeq seq(){ +final synchronized Object sval(){ if(fn != null) { try { - s = RT.seq(fn.invoke()); + sv = fn.invoke(); fn = null; } catch(Exception e) @@ -46,13 +47,30 @@ final synchronized public ISeq seq(){ throw new RuntimeException(e); } } + if(sv != null) + return sv; + return s; +} + +final synchronized public ISeq seq(){ + sval(); + if(sv != null) + { + Object ls = sv; + sv = null; + while(ls instanceof LazySeq) + { + ls = ((LazySeq)ls).sval(); + } + s = RT.seq(ls); + } return s; } public int count(){ int c = 0; for(ISeq s = seq(); s != null; s = s.next()) - ++c; + ++c; return c; } diff --git a/src/jvm/clojure/lang/PersistentVector.java b/src/jvm/clojure/lang/PersistentVector.java index 9b8e40da..c62215a5 100644 --- a/src/jvm/clojure/lang/PersistentVector.java +++ b/src/jvm/clojure/lang/PersistentVector.java @@ -89,19 +89,24 @@ final int tailoff(){ return cnt - tail.length; } -public Object nth(int i){ +public Object[] nodeFor(int i){ if(i >= 0 && i < cnt) { if(i >= tailoff()) - return tail[i & 0x01f]; + return tail; Object[] arr = root; for(int level = shift; level > 0; level -= 5) arr = (Object[]) arr[(i >>> level) & 0x01f]; - return arr[i & 0x01f]; + return arr; } throw new IndexOutOfBoundsException(); } +public Object nth(int i){ + Object[] node = nodeFor(i); + return node[i & 0x01f]; +} + public PersistentVector assocN(int i, Object val){ if(i >= 0 && i < cnt) { @@ -163,6 +168,75 @@ public PersistentVector cons(Object val){ return new PersistentVector(meta(), cnt + 1, newshift, newroot, new Object[]{val}); } +public IChunkedSeq chunkedSeq(){ + if(count() == 0) + return null; + return new ChunkedSeq(this,0,0); +} + +static public final class ChunkedSeq extends ASeq implements IChunkedSeq{ + + final PersistentVector vec; + final Object[] node; + final int i; + final int offset; + + public ChunkedSeq(PersistentVector vec, int i, int offset){ + this.vec = vec; + this.i = i; + this.offset = offset; + this.node = vec.nodeFor(i); + } + + ChunkedSeq(IPersistentMap meta, PersistentVector vec, Object[] node, int i, int offset){ + super(meta); + this.vec = vec; + this.node = node; + this.i = i; + this.offset = offset; + } + + ChunkedSeq(PersistentVector vec, Object[] node, int i, int offset){ + this.vec = vec; + this.node = node; + this.i = i; + this.offset = offset; + } + + public Indexed chunkedFirst() throws Exception{ + return new ArrayChunk(node, offset); + } + + public ISeq chunkedNext(){ + if(i + node.length < vec.cnt) + return new ChunkedSeq(vec,i+ node.length,0); + return null; + } + + public ISeq chunkedMore(){ + ISeq s = chunkedNext(); + if(s == null) + return PersistentList.EMPTY; + return s; + } + + public Obj withMeta(IPersistentMap meta){ + if(meta == this._meta) + return this; + return new ChunkedSeq(meta, vec, node, i, offset); + } + + public Object first(){ + return node[offset]; + } + + public ISeq next(){ + if(offset + 1 < node.length) + return new ChunkedSeq(vec, node, i, offset + 1); + return chunkedNext(); + } +} + public IPersistentCollection empty(){ return EMPTY.withMeta(meta()); } diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 5d683e48..2053273d 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -494,10 +494,10 @@ static public IPersistentMap meta(Object x){ } public static int count(Object o){ + if(o instanceof Counted) + return ((Counted) o).count(); if(o == null) return 0; - else if(o instanceof Counted) - return ((Counted) o).count(); else if(o instanceof IPersistentCollection) { ISeq s = seq(o); o = null; @@ -712,10 +712,10 @@ static public Object dissoc(Object coll, Object key) throws Exception{ } static public Object nth(Object coll, int n){ + if(coll instanceof Indexed) + return ((Indexed) coll).nth(n); if(coll == null) return null; - else if(coll instanceof IPersistentVector) - return ((IPersistentVector) coll).nth(n); else if(coll instanceof String) return Character.valueOf(((String) coll).charAt(n)); else if(coll.getClass().isArray()) |