Skip to content

Commit

Permalink
first cut of chunked seqs
Browse files Browse the repository at this point in the history
Chunked seqs, initial Java-side support
  • Loading branch information
richhickey committed May 28, 2009
1 parent b045a37 commit ff27522
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 13 deletions.
5 changes: 5 additions & 0 deletions clojure.iml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
<setting name="buildJar" value="true" />
<setting name="mainClass" value="clojure.lang.Compiler" />
</component>
<component name="FacetManager">
<facet type="Clojure" name="Clojure">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/classes" />
<exclude-output />
Expand Down
32 changes: 32 additions & 0 deletions src/jvm/clojure/lang/ArrayChunk.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
74 changes: 74 additions & 0 deletions src/jvm/clojure/lang/ChunkedCons.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
23 changes: 23 additions & 0 deletions src/jvm/clojure/lang/IChunkedSeq.java
Original file line number Diff line number Diff line change
@@ -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;

}
4 changes: 1 addition & 3 deletions src/jvm/clojure/lang/IPersistentVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
* 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);
Expand Down
17 changes: 17 additions & 0 deletions src/jvm/clojure/lang/Indexed.java
Original file line number Diff line number Diff line change
@@ -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);
}
24 changes: 21 additions & 3 deletions src/jvm/clojure/lang/LazySeq.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
public final class LazySeq extends Obj implements ISeq, List{

private IFn fn;
private Object sv;
private ISeq s;

public LazySeq(IFn fn){
Expand All @@ -33,26 +34,43 @@ 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)
{
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;
}

Expand Down
80 changes: 77 additions & 3 deletions src/jvm/clojure/lang/PersistentVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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());
}
Expand Down
8 changes: 4 additions & 4 deletions src/jvm/clojure/lang/RT.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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())
Expand Down

0 comments on commit ff27522

Please sign in to comment.