summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-06-11 16:28:11 +0000
committerRich Hickey <richhickey@gmail.com>2006-06-11 16:28:11 +0000
commit6aed462896af74c4a6e692147dcf8fab6b5b6cbd (patch)
treebf428c30b7eab0ccbcb04b8173157d47d9da6f01
parentd1a992e60915cf5715e7b796e340f18cfe9df0bf (diff)
renamed org.clojure to clojure
-rw-r--r--src/jvm/clojure/runtime/AFn.java66
-rw-r--r--src/jvm/clojure/runtime/AGenerator.java2
-rw-r--r--src/jvm/clojure/runtime/Accessor.java22
-rw-r--r--src/jvm/clojure/runtime/BigNum.java20
-rw-r--r--src/jvm/clojure/runtime/Binding.java25
-rw-r--r--src/jvm/clojure/runtime/Box.java2
-rw-r--r--src/jvm/clojure/runtime/Cons.java31
-rw-r--r--src/jvm/clojure/runtime/DoubleNum.java24
-rw-r--r--src/jvm/clojure/runtime/FixNum.java20
-rw-r--r--src/jvm/clojure/runtime/FloatNum.java2
-rw-r--r--src/jvm/clojure/runtime/FnSeq.java30
-rw-r--r--src/jvm/clojure/runtime/IFn.java20
-rw-r--r--src/jvm/clojure/runtime/IMapEntry.java2
-rw-r--r--src/jvm/clojure/runtime/IObj.java8
-rw-r--r--src/jvm/clojure/runtime/IPersistentMap.java31
-rw-r--r--src/jvm/clojure/runtime/ISeq.java24
-rw-r--r--src/jvm/clojure/runtime/ISequential.java18
-rw-r--r--src/jvm/clojure/runtime/Indexer.java2
-rw-r--r--src/jvm/clojure/runtime/IntegerNum.java2
-rw-r--r--src/jvm/clojure/runtime/Iter.java2
-rw-r--r--src/jvm/clojure/runtime/IteratorIter.java2
-rw-r--r--src/jvm/clojure/runtime/Keyword.java26
-rw-r--r--src/jvm/clojure/runtime/LineNumberingPushbackReader.java2
-rw-r--r--src/jvm/clojure/runtime/Namespace.java2
-rw-r--r--src/jvm/clojure/runtime/Num.java18
-rw-r--r--src/jvm/clojure/runtime/Obj.java8
-rw-r--r--src/jvm/clojure/runtime/PersistentArray.java42
-rw-r--r--src/jvm/clojure/runtime/PersistentArrayIdentityMap.java35
-rw-r--r--src/jvm/clojure/runtime/PersistentArrayMap.java212
-rw-r--r--src/jvm/clojure/runtime/PersistentHashtableIdentityMap.java96
-rw-r--r--src/jvm/clojure/runtime/PersistentHashtableMap.java255
-rw-r--r--src/jvm/clojure/runtime/PersistentHybridIdentityMap.java47
-rw-r--r--src/jvm/clojure/runtime/PersistentHybridMap.java104
-rw-r--r--src/jvm/clojure/runtime/PersistentListIdentityMap.java286
-rw-r--r--src/jvm/clojure/runtime/PersistentListMap.java290
-rw-r--r--src/jvm/clojure/runtime/PersistentTree.java809
-rw-r--r--src/jvm/clojure/runtime/RT.java142
-rw-r--r--src/jvm/clojure/runtime/RatioNum.java24
-rw-r--r--src/jvm/clojure/runtime/RationalNum.java2
-rw-r--r--src/jvm/clojure/runtime/RealNum.java2
-rw-r--r--src/jvm/clojure/runtime/Reflector.java8
-rw-r--r--src/jvm/clojure/runtime/RestFn0.java36
-rw-r--r--src/jvm/clojure/runtime/RestFn1.java38
-rw-r--r--src/jvm/clojure/runtime/RestFn2.java40
-rw-r--r--src/jvm/clojure/runtime/RestFn3.java44
-rw-r--r--src/jvm/clojure/runtime/RestFn4.java50
-rw-r--r--src/jvm/clojure/runtime/RestFn5.java60
-rw-r--r--src/jvm/clojure/runtime/Symbol.java2
-rw-r--r--src/jvm/clojure/runtime/TObj.java21
-rw-r--r--src/jvm/clojure/runtime/TRef.java2
-rw-r--r--src/jvm/clojure/runtime/TVal.java2
-rw-r--r--src/jvm/clojure/runtime/ThreadLocalData.java56
-rw-r--r--src/jvm/clojure/runtime/Transaction.java54
-rw-r--r--src/jvm/clojure/runtime/Var.java234
54 files changed, 2800 insertions, 604 deletions
diff --git a/src/jvm/clojure/runtime/AFn.java b/src/jvm/clojure/runtime/AFn.java
index 323fe732..6405b07a 100644
--- a/src/jvm/clojure/runtime/AFn.java
+++ b/src/jvm/clojure/runtime/AFn.java
@@ -10,87 +10,87 @@
/* rich Mar 25, 2006 4:05:37 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public class AFn extends Obj implements IFn{
-public Object invoke(ThreadLocalData tld) throws Exception
+public Object invoke() throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1) throws Exception
+public Object invoke( Object arg1) throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception
+public Object invoke( Object arg1, Object arg2) throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
return throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
return throwArity();
}
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception {
- return applyToHelper(this, tld, arglist);
+public Object applyTo( ISeq arglist) throws Exception {
+ return applyToHelper(this, arglist);
}
-static public Object applyToHelper(IFn ifn,ThreadLocalData tld, Cons arglist) throws Exception
+static public Object applyToHelper(IFn ifn, ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 5))
{
case 0:
- return ifn.invoke(tld);
+ return ifn.invoke();
case 1:
- return ifn.invoke(tld, arglist.first);
+ return ifn.invoke( arglist.first());
case 2:
- return ifn.invoke(tld, arglist.first
- , (arglist = arglist.rest).first
+ return ifn.invoke( arglist.first()
+ , (arglist = arglist.rest()).first()
);
case 3:
- return ifn.invoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return ifn.invoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
case 4:
- return ifn.invoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return ifn.invoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
case 5:
- return ifn.invoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return ifn.invoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
default:
- return ifn.invoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , arglist.rest);
+ return ifn.invoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , arglist.rest());
}
}
diff --git a/src/jvm/clojure/runtime/AGenerator.java b/src/jvm/clojure/runtime/AGenerator.java
index 03b35dac..1494f06e 100644
--- a/src/jvm/clojure/runtime/AGenerator.java
+++ b/src/jvm/clojure/runtime/AGenerator.java
@@ -10,7 +10,7 @@
/* rich Apr 3, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class AGenerator implements Iter{
diff --git a/src/jvm/clojure/runtime/Accessor.java b/src/jvm/clojure/runtime/Accessor.java
index b69bb0bb..2367861a 100644
--- a/src/jvm/clojure/runtime/Accessor.java
+++ b/src/jvm/clojure/runtime/Accessor.java
@@ -10,7 +10,7 @@
/* rich Apr 19, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
public class Accessor extends Symbol implements IFn{
@@ -22,18 +22,17 @@ Accessor(String name)
}
-public Object invoke(ThreadLocalData tld) throws Exception {
+public Object invoke() throws Exception {
return AFn.throwArity();
}
/**
* Indexer implements IFn for attr access
* This single arg version is the getter
- * @param tld
* @param obj - must be Obj
* @return the value of the attr or nil if not found
* @throws Exception
*/
-public Object invoke(ThreadLocalData tld, Object obj) throws Exception
+public Object invoke( Object obj) throws Exception
{
return Reflector.invokeInstanceMember(memberName,obj);
@@ -42,42 +41,41 @@ public Object invoke(ThreadLocalData tld, Object obj) throws Exception
/**
* Indexer implements IFn for attr access
* This two arg version is the setter
- * @param tld
* @param obj - must be Obj
* @param val
* @return val
* @throws Exception
*/
-public Object invoke(ThreadLocalData tld, Object obj, Object val) throws Exception
+public Object invoke( Object obj, Object val) throws Exception
{
return Reflector.invokeInstanceMember(memberName,obj,val);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
return Reflector.invokeInstanceMember(memberName,arg1,arg2,arg3);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
return Reflector.invokeInstanceMember(memberName,arg1,arg2,arg3,arg4);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
return Reflector.invokeInstanceMember(memberName,arg1,arg2,arg3,arg4,arg5);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
return Reflector.invokeInstanceMember(memberName,arg1,arg2,arg3,arg4,arg5,args);
}
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception {
- return AFn.applyToHelper(this, tld, arglist);
+public Object applyTo( ISeq arglist) throws Exception {
+ return AFn.applyToHelper(this, arglist);
}
}
diff --git a/src/jvm/clojure/runtime/BigNum.java b/src/jvm/clojure/runtime/BigNum.java
index 3955fe6a..952520e4 100644
--- a/src/jvm/clojure/runtime/BigNum.java
+++ b/src/jvm/clojure/runtime/BigNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:08:33 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.math.BigInteger;
@@ -171,25 +171,25 @@ public Num divide(RatioNum x)
return Num.divide(x.numerator, x.denominator.multiply(val));
}
-public Object truncateDivide(ThreadLocalData tld, Num num)
+public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, val);
+ return num.truncateBy( val);
}
-public Object truncateBy(ThreadLocalData tld, int div)
+public Object truncateBy( int div)
{
- return Num.truncateBigints(tld, val, BigInteger.valueOf(div));
+ return Num.truncateBigints( val, BigInteger.valueOf(div));
}
-public Object truncateBy(ThreadLocalData tld, BigInteger div)
+public Object truncateBy( BigInteger div)
{
- return Num.truncateBigints(tld, val, div);
+ return Num.truncateBigints( val, div);
}
-public Object truncateBy(ThreadLocalData tld, RatioNum div)
+public Object truncateBy( RatioNum div)
{
- Num q = (Num) Num.truncate(tld, div.denominator.multiply(val), div.numerator);
- return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ Num q = (Num) Num.truncate( div.denominator.multiply(val), div.numerator);
+ return RT.setValues( q, q.multiplyBy(div).subtractFrom(this));
}
public Num negate()
diff --git a/src/jvm/clojure/runtime/Binding.java b/src/jvm/clojure/runtime/Binding.java
new file mode 100644
index 00000000..cf0e8031
--- /dev/null
+++ b/src/jvm/clojure/runtime/Binding.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+public class Binding {
+public Object val;
+public Binding rest;
+
+public Binding(Object val) {
+ this.val = val;
+}
+
+public Binding(Object val, Binding rest) {
+ this.val = val;
+ this.rest = rest;
+}
+}
diff --git a/src/jvm/clojure/runtime/Box.java b/src/jvm/clojure/runtime/Box.java
index e1129029..9909a667 100644
--- a/src/jvm/clojure/runtime/Box.java
+++ b/src/jvm/clojure/runtime/Box.java
@@ -10,7 +10,7 @@
/* rich Mar 27, 2006 8:40:19 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public class Box{
diff --git a/src/jvm/clojure/runtime/Cons.java b/src/jvm/clojure/runtime/Cons.java
index 8cdd3bd9..5a32bd51 100644
--- a/src/jvm/clojure/runtime/Cons.java
+++ b/src/jvm/clojure/runtime/Cons.java
@@ -10,27 +10,28 @@
/* rich Mar 25, 2006 11:01:29 AM */
-package org.clojure.runtime;
+package clojure.runtime;
-public class Cons extends Obj implements Iter{
+public class Cons implements ISeq, ISequential{
-public final Object first;
-public final Cons rest;
+private final Object _first;
+private final ISeq _rest;
-public Cons(Object first, Cons rest)
+public Cons(Object first, ISeq rest)
{
- this.first = first;
- this.rest = rest;
+ this._first = first;
+ this._rest = rest;
}
-public Object get()
- {
- return first;
- }
+public Object first() {
+ return _first;
+}
-public Iter iterate()
- {
- return rest;
- }
+public ISeq rest() {
+ return _rest;
+}
+public ISeq seq() {
+ return this;
+}
}
diff --git a/src/jvm/clojure/runtime/DoubleNum.java b/src/jvm/clojure/runtime/DoubleNum.java
index 00ec7c7a..72f3a979 100644
--- a/src/jvm/clojure/runtime/DoubleNum.java
+++ b/src/jvm/clojure/runtime/DoubleNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:13:45 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.math.BigInteger;
import java.math.BigDecimal;
@@ -160,40 +160,40 @@ public Num divide(RatioNum x)
return Num.from(x.doubleValue() / val);
}
-static Object truncate(ThreadLocalData tld, double n, double d)
+static Object truncate(double n, double d)
{
double q = n / d;
if(q <= Integer.MAX_VALUE && q >= Integer.MIN_VALUE)
{
- return RT.setValues(tld, Num.from((int) q),
+ return RT.setValues(Num.from((int) q),
Num.from(n - ((int) q) * d));
}
else
{ //bigint quotient
Num bq = Num.from(new BigDecimal(q).toBigInteger());
- return RT.setValues(tld, bq,
+ return RT.setValues(bq,
Num.from(n - bq.doubleValue() * d));
}
}
-public Object truncateBy(ThreadLocalData tld, BigInteger x)
+public Object truncateBy( BigInteger x)
{
- return truncate(tld, val, x.doubleValue());
+ return truncate( val, x.doubleValue());
}
-public Object truncateBy(ThreadLocalData tld, int x)
+public Object truncateBy( int x)
{
- return truncate(tld, val, x);
+ return truncate( val, x);
}
-public Object truncateBy(ThreadLocalData tld, RatioNum x)
+public Object truncateBy( RatioNum x)
{
- return truncate(tld, val, x.doubleValue());
+ return truncate( val, x.doubleValue());
}
-public Object truncateDivide(ThreadLocalData tld, Num num)
+public Object truncateDivide( Num num)
{
- return truncate(tld, num.doubleValue(), val);
+ return truncate( num.doubleValue(), val);
}
public Num negate()
diff --git a/src/jvm/clojure/runtime/FixNum.java b/src/jvm/clojure/runtime/FixNum.java
index 31ecf1cb..31de19c8 100644
--- a/src/jvm/clojure/runtime/FixNum.java
+++ b/src/jvm/clojure/runtime/FixNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:09:27 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.math.BigInteger;
@@ -146,25 +146,25 @@ public Num multiply(RatioNum x)
return x.multiply(val);
}
-public Object truncateDivide(ThreadLocalData tld, Num num)
+public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, val);
+ return num.truncateBy( val);
}
-public Object truncateBy(ThreadLocalData tld, int div)
+public Object truncateBy( int div)
{
- return RT.setValues(tld, Num.from(val / div), Num.from(val % div));
+ return RT.setValues( Num.from(val / div), Num.from(val % div));
}
-public Object truncateBy(ThreadLocalData tld, BigInteger div)
+public Object truncateBy( BigInteger div)
{
- return Num.truncateBigints(tld, BigInteger.valueOf(val), div);
+ return Num.truncateBigints( BigInteger.valueOf(val), div);
}
-public Object truncateBy(ThreadLocalData tld, RatioNum div)
+public Object truncateBy( RatioNum div)
{
- Num q = (Num) Num.truncate(tld, div.denominator.multiply(val), div.numerator);
- return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ Num q = (Num) Num.truncate( div.denominator.multiply(val), div.numerator);
+ return RT.setValues( q, q.multiplyBy(div).subtractFrom(this));
}
public Num divideBy(Num rhs)
diff --git a/src/jvm/clojure/runtime/FloatNum.java b/src/jvm/clojure/runtime/FloatNum.java
index 8ea7b6de..477ddc6d 100644
--- a/src/jvm/clojure/runtime/FloatNum.java
+++ b/src/jvm/clojure/runtime/FloatNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:17:21 AM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class FloatNum extends RealNum {
diff --git a/src/jvm/clojure/runtime/FnSeq.java b/src/jvm/clojure/runtime/FnSeq.java
new file mode 100644
index 00000000..430e6e8c
--- /dev/null
+++ b/src/jvm/clojure/runtime/FnSeq.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+public class FnSeq implements ISeq{
+
+Object _first;
+IFn restFn;
+
+public FnSeq(Object first, IFn restFn) {
+ this._first = first;
+ this.restFn = restFn;
+}
+
+public Object first() {
+ return _first;
+}
+
+public ISeq rest() throws Exception {
+ return (ISeq) restFn.invoke();
+}
+}
diff --git a/src/jvm/clojure/runtime/IFn.java b/src/jvm/clojure/runtime/IFn.java
index f5d1194f..3af6ea95 100644
--- a/src/jvm/clojure/runtime/IFn.java
+++ b/src/jvm/clojure/runtime/IFn.java
@@ -10,25 +10,25 @@
/* rich Mar 25, 2006 3:54:03 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public interface IFn{
-public Object invoke(ThreadLocalData tld) throws Exception;
+public Object invoke() throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1) throws Exception;
+public Object invoke(Object arg1) throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception;
+public Object invoke(Object arg1, Object arg2) throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception;
+public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception;
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception;
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
- Cons args) throws Exception;
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+ ISeq args) throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception;
+public Object applyTo(ISeq arglist) throws Exception;
}
diff --git a/src/jvm/clojure/runtime/IMapEntry.java b/src/jvm/clojure/runtime/IMapEntry.java
index fcf93a8b..9b090a82 100644
--- a/src/jvm/clojure/runtime/IMapEntry.java
+++ b/src/jvm/clojure/runtime/IMapEntry.java
@@ -8,7 +8,7 @@
* You must not remove this notice, or any other, from this software.
*/
-package org.clojure.runtime;
+package clojure.runtime;
public interface IMapEntry {
Object key();
diff --git a/src/jvm/clojure/runtime/IObj.java b/src/jvm/clojure/runtime/IObj.java
index e4284aba..cfaa25ab 100644
--- a/src/jvm/clojure/runtime/IObj.java
+++ b/src/jvm/clojure/runtime/IObj.java
@@ -8,7 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-package org.clojure.runtime;
+package clojure.runtime;
/**
* Created by IntelliJ IDEA.
@@ -18,9 +18,9 @@ package org.clojure.runtime;
* To change this template use File | Settings | File Templates.
*/
public interface IObj {
-Object put(ThreadLocalData tld, Comparable key, Object val) throws Exception;
+Object put( Comparable key, Object val) throws Exception;
-Object get(ThreadLocalData tld, Comparable key) throws Exception;
+Object get( Comparable key) throws Exception;
-boolean has(ThreadLocalData tld, Comparable key) throws Exception;
+boolean has( Comparable key) throws Exception;
}
diff --git a/src/jvm/clojure/runtime/IPersistentMap.java b/src/jvm/clojure/runtime/IPersistentMap.java
new file mode 100644
index 00000000..444aa45b
--- /dev/null
+++ b/src/jvm/clojure/runtime/IPersistentMap.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ */
+
+package clojure.runtime;
+
+
+public interface IPersistentMap extends Iterable, ISequential {
+
+int count();
+
+boolean contains(Object key);
+
+IMapEntry find(Object key);
+
+IPersistentMap add(Object key);
+
+IPersistentMap put(Object key, Object val);
+
+IPersistentMap remove(Object key);
+
+Object get(Object key);
+
+int capacity();
+}
diff --git a/src/jvm/clojure/runtime/ISeq.java b/src/jvm/clojure/runtime/ISeq.java
new file mode 100644
index 00000000..2721f9e2
--- /dev/null
+++ b/src/jvm/clojure/runtime/ISeq.java
@@ -0,0 +1,24 @@
+package clojure.runtime;
+
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ */
+
+/**
+ * A persistent, functional, sequence interface
+ *
+ * ISeqs are immutable values, i.e. neither first(), nor rest() changes
+ * or invalidates the ISeq
+ */
+public interface ISeq {
+
+Object first() throws Exception;
+
+ISeq rest() throws Exception;
+}
diff --git a/src/jvm/clojure/runtime/ISequential.java b/src/jvm/clojure/runtime/ISequential.java
new file mode 100644
index 00000000..ecbb12e2
--- /dev/null
+++ b/src/jvm/clojure/runtime/ISequential.java
@@ -0,0 +1,18 @@
+package clojure.runtime;
+
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ */
+
+
+public interface ISequential {
+
+ISeq seq() throws Exception;
+
+}
diff --git a/src/jvm/clojure/runtime/Indexer.java b/src/jvm/clojure/runtime/Indexer.java
index 5eebe489..10cd3bf0 100644
--- a/src/jvm/clojure/runtime/Indexer.java
+++ b/src/jvm/clojure/runtime/Indexer.java
@@ -10,7 +10,7 @@
/* rich Apr 19, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
public class Indexer extends AFn{
}
diff --git a/src/jvm/clojure/runtime/IntegerNum.java b/src/jvm/clojure/runtime/IntegerNum.java
index 6c801dd3..916d812c 100644
--- a/src/jvm/clojure/runtime/IntegerNum.java
+++ b/src/jvm/clojure/runtime/IntegerNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:11:55 AM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class IntegerNum extends RationalNum {
diff --git a/src/jvm/clojure/runtime/Iter.java b/src/jvm/clojure/runtime/Iter.java
index 82e1db5a..017347df 100644
--- a/src/jvm/clojure/runtime/Iter.java
+++ b/src/jvm/clojure/runtime/Iter.java
@@ -10,7 +10,7 @@
/* rich Apr 3, 2006 10:54:14 AM */
-package org.clojure.runtime;
+package clojure.runtime;
/**
diff --git a/src/jvm/clojure/runtime/IteratorIter.java b/src/jvm/clojure/runtime/IteratorIter.java
index bfcec41a..e699ad75 100644
--- a/src/jvm/clojure/runtime/IteratorIter.java
+++ b/src/jvm/clojure/runtime/IteratorIter.java
@@ -10,7 +10,7 @@
/* rich Apr 3, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.Iterator;
diff --git a/src/jvm/clojure/runtime/Keyword.java b/src/jvm/clojure/runtime/Keyword.java
index 63ea4d7d..424f149c 100644
--- a/src/jvm/clojure/runtime/Keyword.java
+++ b/src/jvm/clojure/runtime/Keyword.java
@@ -10,7 +10,7 @@
/* rich Mar 29, 2006 10:39:05 AM */
-package org.clojure.runtime;
+package clojure.runtime;
public class Keyword extends Symbol implements IFn{
@@ -28,62 +28,60 @@ Keyword(String name)
}
-public Object invoke(ThreadLocalData tld) throws Exception {
+public Object invoke() throws Exception {
return AFn.throwArity();
}
/**
* Indexer implements IFn for attr access
* This single arg version is the getter
- * @param tld
* @param obj - must be Obj
* @return the value of the attr or nil if not found
* @throws Exception
*/
-public Object invoke(ThreadLocalData tld, Object obj) throws Exception
+public Object invoke(Object obj) throws Exception
{
if (obj == null)
return null;
- return ((IObj)obj).get(tld,this);
+ return ((IObj)obj).get(this);
}
/**
* Indexer implements IFn for attr access
* This two arg version is the setter
- * @param tld
* @param obj - must be Obj
* @param val
* @return val
* @throws Exception
*/
-public Object invoke(ThreadLocalData tld, Object obj, Object val) throws Exception
+public Object invoke(Object obj, Object val) throws Exception
{
- return ((IObj)obj).put(tld,this,val);
+ return ((IObj)obj).put(this,val);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
return AFn.throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
return AFn.throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
return AFn.throwArity();
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
return AFn.throwArity();
}
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception {
- return AFn.applyToHelper(this, tld, arglist);
+public Object applyTo( ISeq arglist) throws Exception {
+ return AFn.applyToHelper(this, arglist);
}
}
diff --git a/src/jvm/clojure/runtime/LineNumberingPushbackReader.java b/src/jvm/clojure/runtime/LineNumberingPushbackReader.java
index a3a10e1a..bb21c4cc 100644
--- a/src/jvm/clojure/runtime/LineNumberingPushbackReader.java
+++ b/src/jvm/clojure/runtime/LineNumberingPushbackReader.java
@@ -8,7 +8,7 @@
* You must not remove this notice, or any other, from this software.
*/
-package org.clojure.runtime;
+package clojure.runtime;
import java.io.PushbackReader;
import java.io.Reader;
diff --git a/src/jvm/clojure/runtime/Namespace.java b/src/jvm/clojure/runtime/Namespace.java
index 04a7d40e..ecb609cc 100644
--- a/src/jvm/clojure/runtime/Namespace.java
+++ b/src/jvm/clojure/runtime/Namespace.java
@@ -10,7 +10,7 @@
/* rich Mar 27, 2006 1:29:39 PM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.HashMap;
import java.util.IdentityHashMap;
diff --git a/src/jvm/clojure/runtime/Num.java b/src/jvm/clojure/runtime/Num.java
index 182955e2..6e3c8252 100644
--- a/src/jvm/clojure/runtime/Num.java
+++ b/src/jvm/clojure/runtime/Num.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:07:33 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.math.BigInteger;
@@ -115,23 +115,23 @@ abstract public Num divide(BigInteger x);
abstract public Num divide(RatioNum x);
-static public Object truncate(ThreadLocalData tld, Object num, Object div)
+static public Object truncate(Object num, Object div)
{
- return Num.from(div).truncateDivide(tld, Num.from(num));
+ return Num.from(div).truncateDivide( Num.from(num));
}
-abstract public Object truncateDivide(ThreadLocalData tld, Num rhs);
+abstract public Object truncateDivide(Num rhs);
-abstract public Object truncateBy(ThreadLocalData tld, int x);
+abstract public Object truncateBy(int x);
-abstract public Object truncateBy(ThreadLocalData tld, BigInteger x);
+abstract public Object truncateBy(BigInteger x);
-abstract public Object truncateBy(ThreadLocalData tld, RatioNum x);
+abstract public Object truncateBy(RatioNum x);
-static public Object truncateBigints(ThreadLocalData tld, BigInteger n, BigInteger d)
+static public Object truncateBigints(BigInteger n, BigInteger d)
{
BigInteger[] result = n.divideAndRemainder(d);
- return RT.setValues(tld, Num.from(result[0]), Num.from(result[1]));
+ return RT.setValues(Num.from(result[0]), Num.from(result[1]));
}
static public Num divide(BigInteger n, BigInteger d)
diff --git a/src/jvm/clojure/runtime/Obj.java b/src/jvm/clojure/runtime/Obj.java
index c8aa532d..c7b64740 100644
--- a/src/jvm/clojure/runtime/Obj.java
+++ b/src/jvm/clojure/runtime/Obj.java
@@ -10,7 +10,7 @@
/* rich Mar 25, 2006 3:44:58 PM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.IdentityHashMap;
@@ -19,7 +19,7 @@ public class Obj implements IObj {
IdentityHashMap attrs;
public static final int INITIAL_SIZE = 7;
-public Object put(ThreadLocalData tld, Comparable key, Object val)
+public Object put( Comparable key, Object val)
{
if(attrs == null)
attrs = new IdentityHashMap(INITIAL_SIZE);
@@ -27,14 +27,14 @@ public Object put(ThreadLocalData tld, Comparable key, Object val)
return val;
}
-public Object get(ThreadLocalData tld, Comparable key)
+public Object get( Comparable key)
{
if(attrs == null)
return null;
return attrs.get(key);
}
-public boolean has(ThreadLocalData tld, Comparable key){
+public boolean has( Comparable key){
if(attrs == null)
return false;
return attrs.containsKey(key);
diff --git a/src/jvm/clojure/runtime/PersistentArray.java b/src/jvm/clojure/runtime/PersistentArray.java
index b581ecf6..631f5258 100644
--- a/src/jvm/clojure/runtime/PersistentArray.java
+++ b/src/jvm/clojure/runtime/PersistentArray.java
@@ -10,7 +10,7 @@
/* rich Jun 2, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
//import java.util.concurrent.atomic.AtomicInteger;
//import java.util.concurrent.atomic.AtomicReferenceArray;
@@ -46,26 +46,32 @@ import java.util.Random;
* I added hybrid most-recent-sequential-range + shared-bitset idea, multi-thread-safety
*/
-public class PersistentArray implements Iterable{
+public class PersistentArray implements Iterable, ISequential{
public Iterator iterator(){
return new ValIter(this);
}
+public ISeq seq() {
+ if(length() > 0)
+ return new Seq(this, 0);
+ return null;
+}
+
static class Master{
- final Entry[] array;
- final Object defaultVal;
+ final Entry[] array;
+ final Object defaultVal;
int rev;
int load;
- final int maxLoad;
+ final int maxLoad;
final float loadFactor;
Master(int size,Object defaultVal, float loadFactor){
- this.array = new Entry[size];//new AtomicReferenceArray(size);
- this.defaultVal = defaultVal;
+ this.array = new Entry[size];//new AtomicReferenceArray(size);
+ this.defaultVal = defaultVal;
this.rev = 0;//new AtomicInteger(0);
this.load = 0;//new AtomicInteger(0);
- this.maxLoad = (int) (size * loadFactor);
+ this.maxLoad = (int) (size * loadFactor);
this.loadFactor = loadFactor;
}
}
@@ -103,6 +109,26 @@ static class EntryLink extends Entry{
}
}
+static class Seq implements ISeq{
+ final PersistentArray p;
+ final int i;
+
+ Seq(PersistentArray p, int i){
+ this.p = p;
+ this.i = i;
+ }
+
+ public Object first() {
+ return p.get(i);
+ }
+
+ public ISeq rest() {
+ if(i+1 < p.length())
+ return new Seq(p, i + 1);
+ return null;
+ }
+}
+
static class ValIter implements Iterator{
PersistentArray p;
int i;
diff --git a/src/jvm/clojure/runtime/PersistentArrayIdentityMap.java b/src/jvm/clojure/runtime/PersistentArrayIdentityMap.java
new file mode 100644
index 00000000..147a1d91
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentArrayIdentityMap.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+/**
+ * ArrayMap using identity (==) comparison instead of equals
+ */
+public class PersistentArrayIdentityMap extends PersistentArrayMap {
+
+public static PersistentArrayIdentityMap EMPTY = new PersistentArrayIdentityMap();
+
+
+private PersistentArrayIdentityMap() {
+}
+
+IPersistentMap empty() {
+ return EMPTY;
+}
+
+public PersistentArrayIdentityMap(Object[] init) {
+ super(init);
+}
+
+boolean equalKey(Object k1, Object k2) {
+ return k1 == k2;
+}
+}
diff --git a/src/jvm/clojure/runtime/PersistentArrayMap.java b/src/jvm/clojure/runtime/PersistentArrayMap.java
new file mode 100644
index 00000000..19ea16f5
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentArrayMap.java
@@ -0,0 +1,212 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+import java.util.Iterator;
+
+/**
+ * Simple implementation of persistent map on an array
+
+ * Note that instances of this class are constant values
+ * i.e. add/remove etc return new values
+ *
+ * Copies array on every change, so only appropriate for _very_small_ maps
+ *
+ * null keys and values are ok, but you won't be able to distinguish a null value via get - use contains/find
+ */
+
+public class PersistentArrayMap implements IPersistentMap, ISequential {
+
+final Object[] array;
+
+public static PersistentArrayMap EMPTY = new PersistentArrayMap();
+
+protected PersistentArrayMap(){
+ this.array = RT.EMPTY_ARRAY;
+}
+
+/**
+ * This ctor captures/aliases the passed array, so do not modify later
+ * @param init {key1,val1,key2,val2,...}
+ */
+public PersistentArrayMap(Object[] init){
+ this.array = init;
+}
+
+public int count() {
+ return array.length/2;
+}
+
+public boolean contains(Object key){
+ return indexOf(key) >= 0;
+}
+
+public IMapEntry find(Object key) {
+ int i = indexOf(key);
+ if(i >= 0)
+ return new Iter(array,i);
+ return null;
+}
+
+public IPersistentMap add(Object key) {
+
+ return put(key,null);
+}
+
+public IPersistentMap put(Object key, Object val) {
+ int i = indexOf(key);
+ Object[] newArray;
+ if(i >= 0) //already have key, same-sized replacement
+ {
+ if(array[i+1] == val) //no change, no op
+ return this;
+ newArray = array.clone();
+ newArray[i+1] = val;
+ }
+ else //didn't have key, grow
+ {
+ newArray = new Object[array.length + 2];
+ if(array.length > 0)
+ System.arraycopy(array,0,newArray,2,array.length);
+ newArray[0] = key;
+ newArray[1] = val;
+ }
+ return new PersistentArrayMap(newArray);
+}
+
+public IPersistentMap remove(Object key) {
+ int i = indexOf(key);
+ if(i >= 0) //have key, will remove
+ {
+ int newlen = array.length - 2;
+ if(newlen == 0)
+ return empty();
+ Object[] newArray = new Object[newlen];
+ for(int s=0,d=0;s<array.length;s += 2)
+ {
+ if(!equalKey(array[s],key)) //skip removal key
+ {
+ newArray[d] = array[s];
+ newArray[d+1] = array[s+1];
+ d += 2;
+ }
+ }
+ return new PersistentArrayMap(newArray);
+ }
+ //don't have key, no op
+ return this;
+}
+
+IPersistentMap empty() {
+ return EMPTY;
+}
+
+public Object get(Object key) {
+ int i = indexOf(key);
+ if(i >= 0)
+ return array[i + 1];
+ return null;
+}
+
+public int capacity() {
+ return count();
+}
+
+int indexOf(Object key){
+ for(int i=0;i<array.length;i+=2)
+ {
+ if(equalKey(array[i],key))
+ return i;
+ }
+ return -1;
+}
+
+boolean equalKey(Object k1,Object k2){
+ if(k1 == null)
+ return k2 == null;
+ return k1.equals(k2);
+}
+
+public Iterator iterator() {
+ return new Iter(array);
+}
+
+public ISeq seq() {
+ if(array.length > 0)
+ return new Seq(array,0);
+ return null;
+}
+
+static class Seq implements ISeq, IMapEntry{
+ final Object[] array;
+ final int i;
+
+ Seq(Object[] array, int i){
+ this.array = array;
+ this.i = i;
+ }
+
+ public Object key() {
+ return array[i];
+ }
+
+ public Object val() {
+ return array[i+1];
+ }
+
+ public Object first() {
+ return this;
+ }
+
+ public ISeq rest() {
+ if(i+2 < array.length)
+ return new Seq(array, i + 2);
+ return null;
+ }
+}
+
+static class Iter implements Iterator,IMapEntry{
+ Object[] array;
+ int i;
+
+ //for iterator
+ Iter(Object[] array){
+ this(array,-2);
+ }
+
+ //for find
+ Iter(Object[] array, int i){
+ this.array = array;
+ this.i = i;
+ }
+
+ public boolean hasNext() {
+ return i < array.length - 2;
+ }
+
+ public Object next() {
+ i+=2;
+ return this;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object key() {
+ return array[i];
+ }
+
+ public Object val() {
+ return array[i+1];
+ }
+}
+}
diff --git a/src/jvm/clojure/runtime/PersistentHashtableIdentityMap.java b/src/jvm/clojure/runtime/PersistentHashtableIdentityMap.java
new file mode 100644
index 00000000..5a3c9b56
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentHashtableIdentityMap.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+import java.util.Iterator;
+
+public class PersistentHashtableIdentityMap extends PersistentHashtableMap {
+
+public PersistentHashtableIdentityMap(int initialCapacity) {
+ super(initialCapacity);
+}
+
+public PersistentHashtableIdentityMap(Object[] init) {
+ super(init);
+}
+
+PersistentHashtableIdentityMap(int count, PersistentArray array) {
+ super(count, array);
+}
+
+PersistentHashtableIdentityMap(int i, PersistentArray newArray, int growAtCount) {
+ super(i, newArray, growAtCount);
+}
+
+
+public Iterator<IMapEntry> iterator() {
+ return new Iter(array);
+}
+
+
+static class Iter implements Iterator{
+ PersistentArray buckets;
+ int b;
+ PersistentListIdentityMap e;
+
+ Iter(PersistentArray buckets){
+ this.buckets = buckets;
+ this.b = -1;
+ nextBucket();
+ }
+
+ private void nextBucket() {
+ e = null;
+ for(b = b+1;b<buckets.length();b++)
+ {
+ PersistentListIdentityMap a = (PersistentListIdentityMap) buckets.get(b);
+ if(a != null && a != PersistentListIdentityMap.EMPTY)
+ {
+ e = a;
+ break;
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ return e != null;
+ }
+
+ public Object next() {
+ PersistentListIdentityMap ret = e;
+ e = e.next();
+ if(e == PersistentListIdentityMap.EMPTY)
+ nextBucket();
+ return ret;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
+
+IPersistentMap create(int capacity) {
+ return new PersistentHashtableIdentityMap(capacity);
+}
+
+IPersistentMap create(int count, PersistentArray array) {
+ return new PersistentHashtableIdentityMap(count, array);
+}
+
+IPersistentMap create(int i, PersistentArray newArray, int growAtCount){
+ return new PersistentHashtableIdentityMap(i, newArray, growAtCount);
+}
+
+IPersistentMap createListMap(Object key, Object val){
+ return PersistentListIdentityMap.create(key,val);
+}
+
+}
diff --git a/src/jvm/clojure/runtime/PersistentHashtableMap.java b/src/jvm/clojure/runtime/PersistentHashtableMap.java
new file mode 100644
index 00000000..24b46453
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentHashtableMap.java
@@ -0,0 +1,255 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+import java.util.Iterator;
+import java.math.BigInteger;
+
+public class PersistentHashtableMap implements IPersistentMap {
+
+static final float FILL_FACTOR = 0.75f;
+
+final PersistentArray array;
+final int _count;
+final int growAtCount;
+
+public PersistentHashtableMap(int initialCapacity) {
+ array = new PersistentArray(calcPrimeCapacity(initialCapacity));
+ _count = 0;
+ this.growAtCount = (int) (this.array.length()*FILL_FACTOR);
+}
+
+/**
+ * @param init {key1,val1,key2,val2,...}
+ */
+public PersistentHashtableMap(Object[] init){
+ //start halfway to a rehash
+ PersistentArray narray = new PersistentArray(calcPrimeCapacity(init.length));
+ for(int i=0;i<init.length;i+=2)
+ {
+ narray = doPut(bucketFor(init[i],narray),init[i], init[i + 1],narray);
+ }
+ this.array = narray;
+ this._count = init.length/2; //hmmm... presumes no dupe keys in init
+ this.growAtCount = (int) (this.array.length()*FILL_FACTOR);
+}
+
+PersistentHashtableMap(int count,PersistentArray array) {
+ this._count = count;
+ this.array = array;
+ this.growAtCount = (int) (this.array.length()*FILL_FACTOR);
+}
+
+PersistentHashtableMap(int count,PersistentArray array,int growAt) {
+ this._count = count;
+ this.array = array;
+ this.growAtCount = growAt;
+}
+
+int calcPrimeCapacity(int capacity) {
+ return BigInteger.valueOf((long) (capacity/FILL_FACTOR)).nextProbablePrime().intValue();
+}
+
+public int count() {
+ return _count;
+}
+
+public boolean contains(Object key) {
+ IPersistentMap entries = entriesFor(key);
+ return entries != null && entries.contains(key);
+}
+
+public IMapEntry find(Object key) {
+ IPersistentMap entries = entriesFor(key);
+ if(entries != null)
+ return entries.find(key);
+ return null;
+}
+
+public IPersistentMap add(Object key) {
+ return put(key, null);
+}
+
+public IPersistentMap put(Object key, Object val) {
+ if(_count > growAtCount)
+ return grow().put(key, val);
+ int i = bucketFor(key,array);
+ int incr = 1;
+ PersistentArray newArray = doPut(i, key, val, array);
+ if(newArray == array)
+ return this;
+ if(array.get(i) != null && ((IPersistentMap)newArray.get(i)).count() == ((IPersistentMap)array.get(i)).count()) //key already there, no growth
+ incr = 0;
+ return create(_count + incr, newArray, growAtCount);
+}
+
+PersistentArray doPut(int i,Object key,Object val,PersistentArray array){
+ IPersistentMap entries = (IPersistentMap) array.get(i);
+ IPersistentMap newEntries;
+ if (entries != null)
+ {
+ newEntries = entries.put(key, val);
+ if(newEntries == entries) //already there with same value, no op
+ return array;
+ }
+ else
+ newEntries = createListMap(key, val);
+ //newEntries = createArrayMap(new Object[]{key, val});
+
+ return array.set(i, newEntries);
+}
+
+public IPersistentMap remove(Object key) {
+ int i = bucketFor(key,array);
+ IPersistentMap entries = (IPersistentMap) array.get(i);
+ if (entries != null)
+ {
+ IPersistentMap newEntries = entries.remove(key);
+ if (newEntries != entries)
+ return create(_count - 1, array.set(i, newEntries));
+ }
+ //not there, no op
+ return this;
+}
+
+public Object get(Object key) {
+ IPersistentMap entries = entriesFor(key);
+ if(entries != null)
+ return entries.get(key);
+ return null;
+}
+
+public int capacity() {
+ return array.length();
+}
+
+IPersistentMap grow(){
+ PersistentArray newArray = new PersistentArray(calcPrimeCapacity(_count * 2));
+ for (Object o : this)
+ {
+ IMapEntry e = (IMapEntry) o;
+ newArray = doPut(bucketFor(e.key(),newArray),e.key(), e.val(),newArray);
+ }
+ return create(_count,newArray);
+}
+
+public Iterator iterator() {
+ return new Iter(array);
+}
+
+public ISeq seq() throws Exception {
+ return Seq.create(array);
+}
+
+static class Seq implements ISeq{
+ PersistentArray buckets;
+ int b;
+ ISeq e;
+
+
+ static public Seq create(PersistentArray buckets) throws Exception {
+ return next(buckets, -1, null);
+ }
+
+ static Seq next(PersistentArray buckets, int b, ISeq e) throws Exception {
+ if(e != null && e.rest() != null)
+ return new Seq(buckets,b,e.rest());
+ for(b = b+1;b<buckets.length();b++)
+ {
+ ISequential a = (ISequential) buckets.get(b);
+ if(a != null && a.seq() != null)
+ return new Seq(buckets,b,a.seq());
+ }
+ return null;
+ }
+
+ Seq(PersistentArray buckets, int b, ISeq e) {
+ this.buckets = buckets;
+ this.b = b;
+ this.e = e;
+ }
+
+ public Object first() throws Exception {
+ return e.first();
+ }
+
+ public ISeq rest() throws Exception {
+ return next(buckets,b,e);
+ }
+}
+
+static class Iter implements Iterator{
+ PersistentArray buckets;
+ int b;
+ PersistentListMap e;
+
+ Iter(PersistentArray buckets){
+ this.buckets = buckets;
+ this.b = -1;
+ nextBucket();
+ }
+
+ private void nextBucket() {
+ e = null;
+ for(b = b+1;b<buckets.length();b++)
+ {
+ PersistentListMap a = (PersistentListMap) buckets.get(b);
+ if(a != null && a != PersistentListMap.EMPTY)
+ {
+ e = a;
+ break;
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ return e != null;
+ }
+
+ public Object next() {
+ PersistentListMap ret = e;
+ e = e.next();
+ if(e == PersistentListMap.EMPTY)
+ nextBucket();
+ return ret;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
+
+final IPersistentMap entriesFor(Object key){
+ return (IPersistentMap) array.get(bucketFor(key,array));
+}
+
+static int bucketFor(Object key, PersistentArray array) {
+ return (key.hashCode() & 0x7fffffff)%array.length();
+}
+
+IPersistentMap create(int capacity) {
+ return new PersistentHashtableMap(capacity);
+}
+
+IPersistentMap create(int count,PersistentArray array) {
+ return new PersistentHashtableMap(count, array);
+}
+
+IPersistentMap create(int i, PersistentArray newArray, int growAtCount){
+ return new PersistentHashtableMap(i, newArray, growAtCount);
+}
+
+
+IPersistentMap createListMap(Object key, Object val){
+ return PersistentListMap.create(key,val);
+}
+
+}
diff --git a/src/jvm/clojure/runtime/PersistentHybridIdentityMap.java b/src/jvm/clojure/runtime/PersistentHybridIdentityMap.java
new file mode 100644
index 00000000..79548198
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentHybridIdentityMap.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+public class PersistentHybridIdentityMap extends PersistentHybridMap{
+
+public PersistentHybridIdentityMap(Object[] init) {
+ super(init);
+}
+
+public PersistentHybridIdentityMap(int initialCapacity) {
+ super(initialCapacity);
+}
+
+PersistentHybridIdentityMap(IPersistentMap impl) {
+ super(impl);
+}
+
+public IPersistentMap create(IPersistentMap impl) {
+ return new PersistentHybridIdentityMap(impl);
+}
+
+public PersistentArrayMap createArrayMap(Object[] init) {
+ return new PersistentArrayIdentityMap(init);
+}
+
+IPersistentMap createArrayMap() {
+ return PersistentArrayIdentityMap.EMPTY;
+}
+
+IPersistentMap createHashtableMap(Object[] init) {
+ return new PersistentHashtableIdentityMap(init);
+}
+
+IPersistentMap createHashtableMap(int initialCapacity) {
+ return new PersistentHashtableIdentityMap(initialCapacity);
+}
+
+}
diff --git a/src/jvm/clojure/runtime/PersistentHybridMap.java b/src/jvm/clojure/runtime/PersistentHybridMap.java
new file mode 100644
index 00000000..b7eebe1f
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentHybridMap.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+import java.util.Iterator;
+
+public class PersistentHybridMap implements IPersistentMap{
+
+IPersistentMap impl;
+static final int CAPACITY_THRESHOLD = 42;
+
+public PersistentHybridMap(Object[] init){
+ if(init.length/2 < CAPACITY_THRESHOLD)
+ impl = createArrayMap(init);
+ impl = createHashtableMap(init);
+}
+
+public PersistentHybridMap(int initialCapacity){
+ if(initialCapacity < CAPACITY_THRESHOLD)
+ impl = createArrayMap();
+ else
+ impl = createHashtableMap(initialCapacity);
+}
+
+PersistentHybridMap(IPersistentMap impl){
+ this.impl = impl;
+}
+
+public int count() {
+ return impl.count();
+}
+
+public boolean contains(Object key) {
+ return impl.contains(key);
+}
+
+public IMapEntry find(Object key) {
+ return impl.find(key);
+}
+
+public IPersistentMap add(Object key) {
+ return put(key, null);
+}
+
+public IPersistentMap put(Object key, Object val) {
+ IPersistentMap newImpl = impl.put(key,val);
+ if(newImpl.capacity() == CAPACITY_THRESHOLD)
+ {
+ newImpl = createHashtableMap(((PersistentArrayMap)newImpl).array);
+ }
+ return create(newImpl);
+}
+
+public IPersistentMap remove(Object key) {
+ IPersistentMap newImpl = impl.remove(key);
+ if(newImpl != impl)
+ return create(newImpl);
+ return this;
+}
+
+public Object get(Object key) {
+ return impl.get(key);
+}
+
+public int capacity() {
+ return impl.capacity();
+}
+
+public Iterator iterator() {
+ return ((Iterable)impl).iterator();
+}
+
+public IPersistentMap create(IPersistentMap impl) {
+ return new PersistentHybridMap(impl);
+}
+
+public PersistentArrayMap createArrayMap(Object[] init) {
+ return new PersistentArrayMap(init);
+}
+
+IPersistentMap createArrayMap() {
+ return PersistentArrayMap.EMPTY;
+}
+
+IPersistentMap createHashtableMap(Object[] init) {
+ return new PersistentHashtableMap(init);
+}
+
+IPersistentMap createHashtableMap(int initialCapacity) {
+ return new PersistentHashtableMap(initialCapacity);
+}
+
+public ISeq seq() throws Exception {
+ return impl.seq();
+}
+}
diff --git a/src/jvm/clojure/runtime/PersistentListIdentityMap.java b/src/jvm/clojure/runtime/PersistentListIdentityMap.java
new file mode 100644
index 00000000..ac34f936
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentListIdentityMap.java
@@ -0,0 +1,286 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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.
+ **/
+
+package clojure.runtime;
+
+import java.util.Iterator;
+
+/**
+ * Implementation of persistent map on a linked list
+ * Uses identity (==) comparison, vs equals() of PersistentListMap
+
+ * Note that instances of this class are constant values
+ * i.e. add/remove etc return new values
+ *
+ * Lookups/changes are linear, so only appropriate for _very_small_ maps
+ * PersistentArrayMap is generally faster, but this class avoids the double allocation,
+ * and so is better/faster as a bucket for hash tables
+ *
+ * null keys and values are ok, but you won't be able to distinguish a null value via get - use contains/find
+ *
+ * code duplication here is kind of gross, but most efficient
+ */
+
+public class PersistentListIdentityMap implements IPersistentMap, IMapEntry, ISeq, ISequential
+{
+
+static public PersistentListIdentityMap EMPTY = new PersistentListIdentityMap();
+
+static public PersistentListIdentityMap create(Object key, Object val){
+ return new Tail(key, val);
+}
+
+public Object key(){
+ return null;
+}
+
+public Object val(){
+ return null;
+}
+
+PersistentListIdentityMap next(){
+ return this;
+ }
+
+public int count(){
+ return 0;
+}
+
+public boolean contains(Object key){
+ return false;
+}
+
+public IMapEntry find(Object key){
+ return null;
+}
+
+public IPersistentMap add(Object key){
+ return put(key, null);
+}
+
+public PersistentListIdentityMap put(Object key, Object val){
+ return new Tail(key, val);
+}
+
+public PersistentListIdentityMap remove(Object key){
+ return this;
+}
+
+public Object get(Object key){
+ return null;
+}
+
+public int capacity(){
+ return 0;
+}
+
+public Object first() {
+ return null;
+}
+
+public ISeq rest() {
+ return null;
+}
+
+public ISeq seq() {
+ return null;
+}
+
+
+static class Iter implements Iterator{
+ PersistentListIdentityMap e;
+
+ Iter(PersistentListIdentityMap e)
+ {
+ this.e = e;
+ }
+
+ public boolean hasNext(){
+ return e != EMPTY;
+ }
+
+ public Object next(){
+ PersistentListIdentityMap ret = e;
+ e = e.next();
+ return ret;
+ }
+
+ public void remove(){
+ throw new UnsupportedOperationException();
+ }
+}
+
+public Iterator iterator(){
+ return new Iter(this);
+}
+
+static class Tail extends PersistentListIdentityMap {
+ final Object _key;
+ final Object _val;
+
+ Tail(Object key,Object val){
+ this._key = key;
+ this._val = val;
+ }
+
+ PersistentListIdentityMap next(){
+ return EMPTY;
+ }
+
+ public int count(){
+ return 1;
+ }
+
+ public Object get(Object key){
+ if(key ==_key)
+ return _val;
+ return null;
+ }
+
+ public int capacity(){
+ return 1;
+ }
+
+ public Object key(){
+ return _key;
+ }
+
+ public Object val(){
+ return _val;
+ }
+
+ public boolean contains(Object key){
+ return key ==_key;
+ }
+
+ public IMapEntry find(Object key){
+ if(key ==_key)
+ return this;
+ return null;
+ }
+
+ public PersistentListIdentityMap put(Object key, Object val){
+ if(key == _key) //replace
+ {
+ if(val == _val)
+ return this;
+ return new Tail(key,val);
+ }
+ return new Link(key,val,this);
+ }
+
+ public PersistentListIdentityMap remove(Object key){
+ if(key == _key)
+ return EMPTY;
+ return this;
+ }
+
+ public Object first() {
+ return this;
+ }
+
+ public ISeq rest() {
+ return null;
+ }
+
+ public ISeq seq() {
+ return this;
+ }
+}
+
+static class Link extends PersistentListIdentityMap {
+ final Object _key;
+ final Object _val;
+ final PersistentListIdentityMap _rest;
+
+ Link(Object key,Object val,PersistentListIdentityMap next){
+ this._key = key;
+ this._val = val;
+ this._rest = next;
+ }
+
+ public Object key(){
+ return _key;
+ }
+
+ public Object val(){
+ return _val;
+ }
+
+ PersistentListIdentityMap next(){
+ return _rest;
+ }
+
+ public int count(){
+ return 1 + _rest.count();
+ }
+
+ public boolean contains(Object key){
+ return find(key) != null;
+ }
+
+ public IMapEntry find(Object key){
+ if(key ==_key)
+ return this;
+ return _rest.find(key);
+ }
+
+ public PersistentListIdentityMap put(Object key, Object val){
+ IMapEntry e = find(key);
+ if(e != null)
+ {
+ if(e.val() == val)
+ return this;
+ return create(_key,_val,remove(key));
+ }
+ return new Link(key,val,this);
+ }
+
+ public PersistentListIdentityMap remove(Object key){
+ if(key == _key)
+ return _rest;
+ PersistentListIdentityMap r = _rest.remove(key);
+ if(r == _rest) //not there
+ return this;
+ return create(_key,_val,r);
+ }
+
+ public Object get(Object key){
+ IMapEntry e = find(key);
+ if(e != null)
+ return e.val();
+ return null;
+ }
+
+ public int capacity(){
+ return count();
+ }
+
+ public Object first() {
+ return this;
+ }
+
+ public ISeq rest() {
+ return _rest;
+ }
+
+ public ISeq seq() {
+ return this;
+ }
+
+ PersistentListIdentityMap create(Object k,Object v,PersistentListIdentityMap r){
+ if(r == EMPTY)
+ return new Tail(k,v);
+ return new Link(k, v, r);
+ }
+
+}
+
+}
diff --git a/src/jvm/clojure/runtime/PersistentListMap.java b/src/jvm/clojure/runtime/PersistentListMap.java
new file mode 100644
index 00000000..b0e6cb73
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentListMap.java
@@ -0,0 +1,290 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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 Jun 6, 2006 */
+
+package clojure.runtime;
+
+import java.util.Iterator;
+
+/**
+ * Implementation of persistent map on a linked list
+
+ * Note that instances of this class are constant values
+ * i.e. add/remove etc return new values
+ *
+ * Lookups/changes are linear, so only appropriate for _very_small_ maps
+ * PersistentArrayMap is generally faster, but this class avoids the double allocation,
+ * and so is better/faster as a bucket for hash tables
+ *
+ * null keys and values are ok, but you won't be able to distinguish a null value via get - use contains/find
+ */
+public class PersistentListMap implements IPersistentMap, IMapEntry, ISeq, ISequential
+{
+
+static public PersistentListMap EMPTY = new PersistentListMap();
+
+static public PersistentListMap create(Object key, Object val){
+ return new Tail(key, val);
+}
+
+
+public Object key(){
+ return null;
+}
+
+public Object val(){
+ return null;
+}
+
+PersistentListMap next(){
+ return this;
+ }
+
+public int count(){
+ return 0;
+}
+
+public boolean contains(Object key){
+ return false;
+}
+
+public IMapEntry find(Object key){
+ return null;
+}
+
+public IPersistentMap add(Object key){
+ return put(key, null);
+}
+
+public PersistentListMap put(Object key, Object val){
+ return new Tail(key, val);
+}
+
+public PersistentListMap remove(Object key){
+ return this;
+}
+
+public Object get(Object key){
+ return null;
+}
+
+public int capacity(){
+ return 0;
+}
+
+public Object first() {
+ return null;
+}
+
+public ISeq rest() {
+ return null;
+}
+
+public ISeq seq() {
+ return null;
+}
+
+static class Iter implements Iterator{
+ PersistentListMap e;
+
+ Iter(PersistentListMap e)
+ {
+ this.e = e;
+ }
+
+ public boolean hasNext(){
+ return e != EMPTY;
+ }
+
+ public Object next(){
+ PersistentListMap ret = e;
+ e = e.next();
+ return ret;
+ }
+
+ public void remove(){
+ throw new UnsupportedOperationException();
+ }
+}
+
+public Iterator iterator(){
+ return new Iter(this);
+}
+
+static class Tail extends PersistentListMap {
+ final Object _key;
+ final Object _val;
+
+ Tail(Object key,Object val){
+ this._key = key;
+ this._val = val;
+ }
+
+ PersistentListMap next(){
+ return EMPTY;
+ }
+
+ public int count(){
+ return 1;
+ }
+
+ public Object get(Object key){
+ if(equalKey(key,_key))
+ return _val;
+ return null;
+ }
+
+ public int capacity(){
+ return 1;
+ }
+
+ public Object key(){
+ return _key;
+ }
+
+ public Object val(){
+ return _val;
+ }
+
+ public boolean contains(Object key){
+ return equalKey(key,_key);
+ }
+
+ public IMapEntry find(Object key){
+ if(equalKey(key,_key))
+ return this;
+ return null;
+ }
+
+ public PersistentListMap put(Object key, Object val){
+ if(equalKey(key,_key)) //replace
+ {
+ if(val == _val)
+ return this;
+ return new Tail(key,val);
+ }
+ return new Link(key,val,this);
+ }
+
+ public PersistentListMap remove(Object key){
+ if(equalKey(key,_key))
+ return EMPTY;
+ return this;
+ }
+
+ public Object first() {
+ return this;
+ }
+
+ public ISeq rest() {
+ return null;
+ }
+
+ public ISeq seq() {
+ return this;
+ }
+
+}
+
+static class Link extends PersistentListMap {
+ final Object _key;
+ final Object _val;
+ final PersistentListMap _rest;
+
+ Link(Object key,Object val,PersistentListMap next){
+ this._key = key;
+ this._val = val;
+ this._rest = next;
+ }
+
+ public Object key(){
+ return _key;
+ }
+
+ public Object val(){
+ return _val;
+ }
+
+ PersistentListMap next(){
+ return _rest;
+ }
+
+ public int count(){
+ return 1 + _rest.count();
+ }
+
+ public boolean contains(Object key){
+ return find(key) != null;
+ }
+
+ public IMapEntry find(Object key){
+ if(equalKey(key,_key))
+ return this;
+ return _rest.find(key);
+ }
+
+ public PersistentListMap put(Object key, Object val){
+ IMapEntry e = find(key);
+ if(e != null)
+ {
+ if(e.val() == val)
+ return this;
+ return create(_key,_val,remove(key));
+ }
+ return new Link(key,val,this);
+ }
+
+ public PersistentListMap remove(Object key){
+ if(equalKey(key,_key))
+ return _rest;
+ PersistentListMap r = _rest.remove(key);
+ if(r == _rest) //not there
+ return this;
+ return create(_key,_val,r);
+ }
+
+ public Object get(Object key){
+ IMapEntry e = find(key);
+ if(e != null)
+ return e.val();
+ return null;
+ }
+
+ public int capacity(){
+ return count();
+ }
+
+ public Object first() {
+ return this;
+ }
+
+ public ISeq rest() {
+ return _rest;
+ }
+
+ public ISeq seq() {
+ return this;
+ }
+
+ PersistentListMap create(Object k,Object v,PersistentListMap r){
+ if(r == EMPTY)
+ return new Tail(k,v);
+ return new Link(k, v, r);
+ }
+
+}
+
+boolean equalKey(Object k1,Object k2){
+ if(k1 == null)
+ return k2 == null;
+ return k1.equals(k2);
+}
+}
diff --git a/src/jvm/clojure/runtime/PersistentTree.java b/src/jvm/clojure/runtime/PersistentTree.java
new file mode 100644
index 00000000..291d1e69
--- /dev/null
+++ b/src/jvm/clojure/runtime/PersistentTree.java
@@ -0,0 +1,809 @@
+/**
+ * Copyright (c) Rich Hickey. All rights reserved.
+ * The use and distribution terms for this software are covered by the
+ * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ * which can be found in the file CPL.TXT 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 20, 2006 */
+
+package clojure.runtime;
+
+import java.util.*;
+
+/**
+ * Persistent Red Black Tree
+ * Note that instances of this class are constant values
+ * i.e. add/remove etc return new values
+ * <p/>
+ * See Okasaki, Kahrs, Larsen et al
+ */
+
+public class PersistentTree implements IPersistentMap, ISequential {
+
+public final Comparator comp;
+public final Node tree;
+public final int _count;
+
+public PersistentTree(){
+ this(null);
+}
+
+public PersistentTree(Comparator comp){
+ this.comp = comp;
+ tree = null;
+ _count = 0;
+}
+
+public boolean contains(Object key){
+ return find(key) != null;
+}
+
+public PersistentTree add(Object key){
+ return put(key, null);
+}
+
+public PersistentTree put(Object key, Object val){
+ Box found = new Box(null);
+ Node t = add(tree, key, val, found);
+ if(t == null) //null == already contains key
+ {
+ Node foundNode = (Node) found.val;
+ if(foundNode.val() == val) //note only get same collection on identity of val, not equals()
+ return this;
+ return new PersistentTree(comp, replace(tree, key, val), _count);
+ }
+ return new PersistentTree(comp, t.blacken(), _count + 1);
+}
+
+
+public PersistentTree remove(Object key){
+ Box found = new Box(null);
+ Node t = remove(tree, key, found);
+ if(t == null)
+ {
+ if(found.val == null)//null == doesn't contain key
+ return this;
+ //empty
+ return new PersistentTree(comp);
+ }
+ return new PersistentTree(comp, t.blacken(), _count - 1);
+}
+
+public ISeq seq() {
+ if(_count > 0)
+ return Seq.create(tree, true);
+ return null;
+}
+
+public ISeq rseq() {
+ if(_count > 0)
+ return Seq.create(tree, false);
+ return null;
+}
+
+
+public NodeIterator iterator(){
+ return new NodeIterator(tree, true);
+}
+
+public NodeIterator reverseIterator(){
+ return new NodeIterator(tree, false);
+}
+
+public Iterator keys(){
+ return keys(iterator());
+}
+
+public Iterator vals(){
+ return vals(iterator());
+}
+
+public Iterator keys(NodeIterator it){
+ return new KeyIterator(it);
+}
+
+public Iterator vals(NodeIterator it){
+ return new ValIterator(it);
+}
+
+public Object minKey(){
+ Node t = min();
+ return t!=null?t.key:null;
+}
+
+public Node min(){
+ Node t = tree;
+ if(t != null)
+ {
+ while(t.left() != null)
+ t = t.left();
+ }
+ return t;
+}
+
+public Object maxKey(){
+ Node t = max();
+ return t!=null?t.key:null;
+}
+
+public Node max(){
+ Node t = tree;
+ if(t != null)
+ {
+ while(t.right() != null)
+ t = t.right();
+ }
+ return t;
+}
+
+public int depth(){
+ return depth(tree);
+}
+
+int depth(Node t){
+ if(t == null)
+ return 0;
+ return 1 + Math.max(depth(t.left()), depth(t.right()));
+}
+
+public Object get(Object key){
+ Node n = find(key);
+ return (n != null) ? n.val() : null;
+}
+
+public int capacity() {
+ return _count;
+}
+
+public int count() {
+ return _count;
+}
+
+public Node find(Object key){
+ Node t = tree;
+ while(t != null)
+ {
+ int c = compare(key, t.key);
+ if(c == 0)
+ return t;
+ else if(c < 0)
+ t = t.left();
+ else
+ t = t.right();
+ }
+ return t;
+}
+
+int compare(Object k1, Object k2){
+ if(comp != null)
+ return comp.compare(k1, k2);
+ return ((Comparable) k1).compareTo(k2);
+}
+
+Node add(Node t, Object key, Object val, Box found){
+ if(t == null)
+ {
+ if(val == null)
+ return new Red(key);
+ return new RedVal(key, val);
+ }
+ int c = compare(key, t.key);
+ if(c == 0)
+ {
+ found.val = t;
+ return null;
+ }
+ Node ins = c < 0 ? add(t.left(), key, val, found) : add(t.right(), key, val, found);
+ if(ins == null) //found below
+ return null;
+ if(c < 0)
+ return t.addLeft(ins);
+ return t.addRight(ins);
+}
+
+Node remove(Node t, Object key, Box found){
+ if(t == null)
+ return null; //not found indicator
+ int c = compare(key, t.key);
+ if(c == 0)
+ {
+ found.val = t;
+ return append(t.left(), t.right());
+ }
+ Node del = c < 0 ? remove(t.left(), key, found) : remove(t.right(), key, found);
+ if(del == null && found.val == null) //not found below
+ return null;
+ if(c < 0)
+ {
+ if(t.left() instanceof Black)
+ return balanceLeftDel(t.key, t.val(), del, t.right());
+ else
+ return red(t.key, t.val(), del, t.right());
+ }
+ if(t.right() instanceof Black)
+ return balanceRightDel(t.key, t.val(), t.left(), del);
+ return red(t.key, t.val(), t.left(), del);
+// return t.removeLeft(del);
+// return t.removeRight(del);
+}
+
+static Node append(Node left, Node right){
+ if(left == null)
+ return right;
+ else if(right == null)
+ return left;
+ else if(left instanceof Red)
+ {
+ if(right instanceof Red)
+ {
+ Node app = append(left.right(), right.left());
+ if(app instanceof Red)
+ return red(app.key, app.val(),
+ red(left.key, left.val(), left.left(), app.left()),
+ red(right.key, right.val(), app.right(), right.right()));
+ else
+ return red(left.key, left.val(), left.left(), red(right.key, right.val(), app, right.right()));
+ }
+ else
+ return red(left.key, left.val(), left.left(), append(left.right(), right));
+ }
+ else if(right instanceof Red)
+ return red(right.key, right.val(), append(left, right.left()), right.right());
+ else //black/black
+ {
+ Node app = append(left.right(), right.left());
+ if(app instanceof Red)
+ return red(app.key, app.val(),
+ black(left.key, left.val(), left.left(), app.left()),
+ black(right.key, right.val(), app.right(), right.right()));
+ else
+ return balanceLeftDel(left.key, left.val(), left.left(), black(right.key, right.val(), app, right.right()));
+ }
+}
+
+static Node balanceLeftDel(Object key, Object val, Node del, Node right){
+ if(del instanceof Red)
+ return red(key, val, del.blacken(), right);
+ else if(right instanceof Black)
+ return rightBalance(key, val, del, right.redden());
+ else if(right instanceof Red && right.left() instanceof Black)
+ return red(right.left().key, right.left().val(),
+ black(key, val, del, right.left().left()),
+ rightBalance(right.key, right.val(), right.left().right(), right.right().redden()));
+ else
+ throw new UnsupportedOperationException("Invariant violation");
+}
+
+static Node balanceRightDel(Object key, Object val, Node left, Node del){
+ if(del instanceof Red)
+ return red(key, val, left, del.blacken());
+ else if(left instanceof Black)
+ return leftBalance(key, val, left.redden(), del);
+ else if(left instanceof Red && left.right() instanceof Black)
+ return red(left.right().key, left.right().val(),
+ leftBalance(left.key, left.val(), left.left().redden(), left.right().left()),
+ black(key, val, left.right().right(), del));
+ else
+ throw new UnsupportedOperationException("Invariant violation");
+}
+
+static Node leftBalance(Object key, Object val, Node ins, Node right){
+ if(ins instanceof Red && ins.left() instanceof Red)
+ return red(ins.key, ins.val(), ins.left().blacken(), black(key, val, ins.right(), right));
+ else if(ins instanceof Red && ins.right() instanceof Red)
+ return red(ins.right().key, ins.right().val(),
+ black(ins.key, ins.val(), ins.left(), ins.right().left()),
+ black(key, val, ins.right().right(), right));
+ else
+ return black(key, val, ins, right);
+}
+
+
+static Node rightBalance(Object key, Object val, Node left, Node ins){
+ if(ins instanceof Red && ins.right() instanceof Red)
+ return red(ins.key, ins.val(), black(key, val, left, ins.left()), ins.right().blacken());
+ else if(ins instanceof Red && ins.left() instanceof Red)
+ return red(ins.left().key, ins.left().val(),
+ black(key, val, left, ins.left().left()),
+ black(ins.key, ins.val(), ins.left().right(), ins.right()));
+ else
+ return black(key, val, left, ins);
+}
+
+Node replace(Node t, Object key, Object val){
+ int c = compare(key, t.key);
+ return t.replace(t.key,
+ c == 0 ? val : t.val(),
+ c < 0 ? replace(t.left(), key, val) : t.left(),
+ c > 0 ? replace(t.right(), key, val) : t.right());
+}
+
+PersistentTree(Comparator comp, Node tree, int count){
+ this.comp = comp;
+ this.tree = tree;
+ this._count = count;
+}
+
+static Red red(Object key, Object val, Node left, Node right){
+ if(left == null && right == null)
+ {
+ if(val == null)
+ return new Red(key);
+ return new RedVal(key, val);
+ }
+ if(val == null)
+ return new RedBranch(key, left, right);
+ return new RedBranchVal(key, val, left, right);
+}
+
+static Black black(Object key, Object val, Node left, Node right){
+ if(left == null && right == null)
+ {
+ if(val == null)
+ return new Black(key);
+ return new BlackVal(key, val);
+ }
+ if(val == null)
+ return new BlackBranch(key, left, right);
+ return new BlackBranchVal(key, val, left, right);
+}
+
+static abstract class Node implements IMapEntry {
+ final Object key;
+
+ Node(Object key){
+ this.key = key;
+ }
+
+ public Object key(){
+ return key;
+ }
+
+ public Object val(){
+ return null;
+ }
+
+ Node left(){
+ return null;
+ }
+
+ Node right(){
+ return null;
+ }
+
+ abstract Node addLeft(Node ins);
+
+ abstract Node addRight(Node ins);
+
+ abstract Node removeLeft(Node del);
+
+ abstract Node removeRight(Node del);
+
+ abstract Node blacken();
+
+ abstract Node redden();
+
+ Node balanceLeft(Node parent){
+ return black(parent.key, parent.val(), this, parent.right());
+ }
+
+ Node balanceRight(Node parent){
+ return black(parent.key, parent.val(), parent.left(), this);
+ }
+
+ abstract Node replace(Object key, Object val, Node left, Node right);
+
+}
+static class Black extends Node{
+ public Black(Object key){
+ super(key);
+ }
+
+ Node addLeft(Node ins){
+ return ins.balanceLeft(this);
+ }
+
+ Node addRight(Node ins){
+ return ins.balanceRight(this);
+ }
+
+ Node removeLeft(Node del){
+ return balanceLeftDel(key, val(), del, right());
+ }
+
+ Node removeRight(Node del){
+ return balanceRightDel(key, val(), left(), del);
+ }
+
+ Node blacken(){
+ return this;
+ }
+
+ Node redden(){
+ return new Red(key);
+ }
+
+ Node replace(Object key, Object val, Node left, Node right){
+ return black(key, val, left, right);
+ }
+
+}
+static class BlackVal extends Black{
+ final Object val;
+
+ public BlackVal(Object key, Object val){
+ super(key);
+ this.val = val;
+ }
+
+ public Object val(){
+ return val;
+ }
+
+ Node redden(){
+ return new RedVal(key, val);
+ }
+
+}
+static class BlackBranch extends Black{
+ final Node left;
+
+ final Node right;
+
+ public BlackBranch(Object key, Node left, Node right){
+ super(key);
+ this.left = left;
+ this.right = right;
+ }
+
+ public Node left(){
+ return left;
+ }
+
+ public Node right(){
+ return right;
+ }
+
+ Node redden(){
+ return new RedBranch(key, left, right);
+ }
+
+}
+static class BlackBranchVal extends BlackBranch{
+ final Object val;
+
+ public BlackBranchVal(Object key, Object val, Node left, Node right){
+ super(key, left, right);
+ this.val = val;
+ }
+
+ public Object val(){
+ return val;
+ }
+
+ Node redden(){
+ return new RedBranchVal(key, val, left, right);
+ }
+
+}
+static class Red extends Node{
+ public Red(Object key){
+ super(key);
+ }
+
+ Node addLeft(Node ins){
+ return red(key, val(), ins, right());
+ }
+
+ Node addRight(Node ins){
+ return red(key, val(), left(), ins);
+ }
+
+ Node removeLeft(Node del){
+ return red(key, val(), del, right());
+ }
+
+ Node removeRight(Node del){
+ return red(key, val(), left(), del);
+ }
+
+ Node blacken(){
+ return new Black(key);
+ }
+
+ Node redden(){
+ throw new UnsupportedOperationException("Invariant violation");
+ }
+
+ Node replace(Object key, Object val, Node left, Node right){
+ return red(key, val, left, right);
+ }
+
+}
+static class RedVal extends Red{
+ final Object val;
+
+ public RedVal(Object key, Object val){
+ super(key);
+ this.val = val;
+ }
+
+ public Object val(){
+ return val;
+ }
+
+ Node blacken(){
+ return new BlackVal(key, val);
+ }
+
+}
+static class RedBranch extends Red{
+ final Node left;
+
+ final Node right;
+
+ public RedBranch(Object key, Node left, Node right){
+ super(key);
+ this.left = left;
+ this.right = right;
+ }
+
+ public Node left(){
+ return left;
+ }
+
+ public Node right(){
+ return right;
+ }
+
+ Node balanceLeft(Node parent){
+ if(left instanceof Red)
+ return red(key, val(), left.blacken(), black(parent.key, parent.val(), right, parent.right()));
+ else if(right instanceof Red)
+ return red(right.key, right.val(), black(key, val(), left, right.left()),
+ black(parent.key, parent.val(), right.right(), parent.right()));
+ else
+ return super.balanceLeft(parent);
+
+ }
+
+ Node balanceRight(Node parent){
+ if(right instanceof Red)
+ return red(key, val(), black(parent.key, parent.val(), parent.left(), left), right.blacken());
+ else if(left instanceof Red)
+ return red(left.key, left.val(), black(parent.key, parent.val(), parent.left(), left.left()),
+ black(key, val(), left.right(), right));
+ else
+ return super.balanceRight(parent);
+ }
+
+ Node blacken(){
+ return new BlackBranch(key, left, right);
+ }
+
+}
+
+
+static class RedBranchVal extends RedBranch{
+ final Object val;
+
+ public RedBranchVal(Object key, Object val, Node left, Node right){
+ super(key, left, right);
+ this.val = val;
+ }
+
+ public Object val(){
+ return val;
+ }
+
+ Node blacken(){
+ return new BlackBranchVal(key, val, left, right);
+ }
+}
+
+
+static public class Seq implements ISeq{
+ final ISeq stack;
+ final boolean asc;
+
+ public Seq(ISeq stack, boolean asc) {
+ this.stack = stack;
+ this.asc = asc;
+ }
+
+ static Seq create(Node t, boolean asc){
+ return new Seq(push(t, null, asc),asc);
+ }
+
+ static ISeq push(Node t, ISeq stack, boolean asc){
+ while(t != null)
+ {
+ stack = RT.cons(t,stack);
+ t = asc ? t.left() : t.right();
+ }
+ return stack;
+ }
+
+ public Object first() throws Exception {
+ return stack.first();
+ }
+
+ public ISeq rest() throws Exception {
+ Node t = (Node)stack.first();
+ ISeq nextstack = push(asc ? t.right() : t.left(), stack.rest(), asc);
+ if(nextstack != null)
+ {
+ return new Seq(nextstack,asc);
+ }
+ return null;
+ }
+}
+
+static public class NodeIterator implements Iterator{
+ Stack stack = new Stack();
+ boolean asc;
+
+ NodeIterator(Node t, boolean asc){
+ this.asc = asc;
+ push(t);
+ }
+
+ void push(Node t){
+ while(t != null)
+ {
+ stack.push(t);
+ t = asc ? t.left() : t.right();
+ }
+ }
+
+ public boolean hasNext(){
+ return !stack.isEmpty();
+ }
+
+ public Object next(){
+ Node t = (Node) stack.pop();
+ push(asc ? t.right() : t.left());
+ return t;
+ }
+
+ public void remove(){
+ throw new UnsupportedOperationException();
+ }
+}
+
+static class KeyIterator implements Iterator{
+ NodeIterator it;
+
+ KeyIterator(NodeIterator it){
+ this.it = it;
+ }
+
+ public boolean hasNext(){
+ return it.hasNext();
+ }
+
+ public Object next(){
+ return ((Node) it.next()).key;
+ }
+
+ public void remove(){
+ throw new UnsupportedOperationException();
+ }
+}
+
+static class ValIterator implements Iterator{
+ NodeIterator it;
+
+ ValIterator(NodeIterator it){
+ this.it = it;
+ }
+
+ public boolean hasNext(){
+ return it.hasNext();
+ }
+
+ public Object next(){
+ return ((Node) it.next()).val();
+ }
+
+ public void remove(){
+ throw new UnsupportedOperationException();
+ }
+}
+
+static public void main(String args[]){
+ if(args.length != 1)
+ System.err.println("Usage: RBTree n");
+ int n = Integer.parseInt(args[0]);
+ Integer[] ints = new Integer[n];
+ for(int i = 0; i < ints.length; i++)
+ {
+ ints[i] = new Integer(i);
+ }
+ Collections.shuffle(Arrays.asList(ints));
+ //force the ListMap class loading now
+ PersistentListMap.EMPTY.add(1).add(2).add(3);
+ System.out.println("Building set");
+ //IPersistentMap set = new PersistentHybridMap(1001);
+ IPersistentMap set = new PersistentHashtableMap(1001);
+ //IPersistentMap set = new ListMap();
+ //IPersistentMap set = new ArrayMap();
+ //IPersistentMap set = new RBTree();
+// for(int i = 0; i < ints.length; i++)
+// {
+// Integer anInt = ints[i];
+// set = set.add(anInt);
+// }
+ long startTime = System.nanoTime();
+ for(int i = 0; i < ints.length; i++)
+ {
+ Integer anInt = ints[i];
+ set = set.put(anInt, anInt);
+ }
+ //System.out.println("_count = " + set.count());
+
+
+// System.out.println("_count = " + set._count + ", min: " + set.minKey() + ", max: " + set.maxKey()
+// + ", depth: " + set.depth());
+ Iterator it = set.iterator();
+ while(it.hasNext())
+ {
+ IMapEntry o = (IMapEntry) it.next();
+ if(!set.contains(o.key()))
+ System.err.println("Can't find: " + o);
+ //else if(n < 2000)
+ // System.out.print(o.key().toString() + ",");
+ }
+
+ for(int i = 0; i < ints.length/2; i++)
+ {
+ Integer anInt = ints[i];
+ set = set.remove(anInt);
+ }
+
+ long estimatedTime = System.nanoTime() - startTime;
+ System.out.println();
+
+ System.out.println("_count = " + set.count() + ", time: " + estimatedTime/10000);
+
+ System.out.println("Building ht");
+ Hashtable ht = new Hashtable(1001);
+ startTime = System.nanoTime();
+// for(int i = 0; i < ints.length; i++)
+// {
+// Integer anInt = ints[i];
+// ht.put(anInt,null);
+// }
+ for(int i = 0; i < ints.length; i++)
+ {
+ Integer anInt = ints[i];
+ ht.put(anInt, anInt);
+ }
+ //System.out.println("size = " + ht.size());
+ it = ht.entrySet().iterator();
+ while(it.hasNext())
+ {
+ Map.Entry o = (Map.Entry) it.next();
+ if(!ht.containsKey(o.getKey()))
+ System.err.println("Can't find: " + o);
+ //else if(n < 2000)
+ // System.out.print(o.toString() + ",");
+ }
+
+ for(int i = 0; i < ints.length/2; i++)
+ {
+ Integer anInt = ints[i];
+ ht.remove(anInt);
+ }
+ estimatedTime = System.nanoTime() - startTime;
+ System.out.println();
+ System.out.println("size = " + ht.size() + ", time: " + estimatedTime/10000);
+
+// System.out.println("_count = " + set._count + ", min: " + set.minKey() + ", max: " + set.maxKey()
+// + ", depth: " + set.depth());
+}
+}
diff --git a/src/jvm/clojure/runtime/RT.java b/src/jvm/clojure/runtime/RT.java
index 4298a4c9..c0eee9f6 100644
--- a/src/jvm/clojure/runtime/RT.java
+++ b/src/jvm/clojure/runtime/RT.java
@@ -10,7 +10,7 @@
/* rich Mar 25, 2006 4:28:27 PM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.Iterator;
import java.io.Reader;
@@ -49,18 +49,18 @@ public class RT{
return null;
}
- static public Object equal(Object arg1, Object arg2) {
- if(arg1 == null)
- return arg2 == null ? Boolean.TRUE : null;
- else if(arg2 == null)
- return null;
- return (eql(arg1,arg2) != null
- || (arg1.getClass() == Cons.class
- && arg2.getClass() == Cons.class
- && equal(((Cons)arg1).first,((Cons)arg2).first)!=null
- && equal(((Cons)arg1).rest,((Cons)arg2).rest)!=null))
- ?Boolean.TRUE:null;
- }
+// static public Object equal(Object arg1, Object arg2) {
+// if(arg1 == null)
+// return arg2 == null ? Boolean.TRUE : null;
+// else if(arg2 == null)
+// return null;
+// return (eql(arg1,arg2) != null
+// || (arg1.getClass() == Cons.class
+// && arg2.getClass() == Cons.class
+// && equal(((Cons)arg1)._first,((Cons)arg2)._first)!=null
+// && equal(((Cons)arg1)._rest,((Cons)arg2)._rest)!=null))
+// ?Boolean.TRUE:null;
+// }
static public Iter iter(Object coll)
{
@@ -174,7 +174,7 @@ static public double doubleCast(Object x)
/******************************************* list support ********************************/
-static public Cons cons(Object x, Cons y)
+static public Cons cons(Object x, ISeq y)
{
return new Cons(x, y);
}
@@ -209,27 +209,27 @@ static public Cons list(Object arg1, Object arg2, Object arg3, Object arg4, Obje
return listStar(arg1, arg2, arg3, arg4, arg5, null);
}
-static public Cons listStar(Object arg1, Cons rest)
+static public Cons listStar(Object arg1, ISeq rest)
{
return cons(arg1, rest);
}
-static public Cons listStar(Object arg1, Object arg2, Cons rest)
+static public Cons listStar(Object arg1, Object arg2, ISeq rest)
{
return cons(arg1, cons(arg2, rest));
}
-static public Cons listStar(Object arg1, Object arg2, Object arg3, Cons rest)
+static public Cons listStar(Object arg1, Object arg2, Object arg3, ISeq rest)
{
return cons(arg1, cons(arg2, cons(arg3, rest)));
}
-static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, Cons rest)
+static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, ISeq rest)
{
return cons(arg1, cons(arg2, cons(arg3, cons(arg4, rest))));
}
-static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons rest)
+static public Cons listStar(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq rest)
{
return cons(arg1, cons(arg2, cons(arg3, cons(arg4, cons(arg5, rest)))));
}
@@ -241,25 +241,23 @@ static public Cons arrayToList(Object[] a){
return ret;
}
-static public int length(Cons list)
+static public int length(ISeq list) throws Exception {
+int i = 0;
+for(ISeq c = list; c != null; c = c.rest())
{
- int i = 0;
- for(Cons c = list; c != null; c = c.rest)
- {
- i++;
- }
- return i;
+ i++;
}
+return i;
+}
-static public int boundedLength(Cons list, int limit)
+static public int boundedLength(ISeq list, int limit) throws Exception {
+int i = 0;
+for(ISeq c = list; c != null && i <= limit; c = c.rest())
{
- int i = 0;
- for(Cons c = list; c != null && i <= limit; c = c.rest)
- {
- i++;
- }
- return i;
+ i++;
}
+return i;
+}
///////////////////////////////// reader support ////////////////////////////////
@@ -310,80 +308,12 @@ static public boolean isLineNumberingReader(Reader r) {
///////////////////////////////// values //////////////////////////
-static public Object setValues(ThreadLocalData tld, Object arg1)
- {
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 1;
- tld.mvArray[0] = arg1;
- return arg1;
- }
-
-static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2)
- {
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 2;
- tld.mvArray[0] = arg1;
- tld.mvArray[1] = arg2;
- return arg1;
- }
-
-static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3)
- {
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 3;
- tld.mvArray[0] = arg1;
- tld.mvArray[1] = arg2;
- tld.mvArray[2] = arg3;
- return arg1;
- }
-
-static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4)
- {
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 4;
- tld.mvArray[0] = arg1;
- tld.mvArray[1] = arg2;
- tld.mvArray[2] = arg3;
- tld.mvArray[3] = arg4;
- return arg1;
- }
-
-static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4,
- Object arg5)
+static public Object setValues(Object... vals)
{
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 5;
- tld.mvArray[0] = arg1;
- tld.mvArray[1] = arg2;
- tld.mvArray[2] = arg3;
- tld.mvArray[3] = arg4;
- tld.mvArray[4] = arg5;
- return arg1;
- }
-
-static public Object setValues(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4,
- Object arg5, Cons args) throws Exception
- {
- if(tld == null)
- tld = ThreadLocalData.get();
- tld.mvCount = 5;
- tld.mvArray[0] = arg1;
- tld.mvArray[1] = arg2;
- tld.mvArray[2] = arg3;
- tld.mvArray[3] = arg4;
- tld.mvArray[4] = arg5;
- for(int i = 5; args != null && i < ThreadLocalData.MULTIPLE_VALUES_LIMIT; i++, args = args.rest)
- {
- tld.mvArray[i] = args.first;
- }
- if(args != null)
- throw new IllegalArgumentException("Too many arguments to values (> ThreadLocalData.MULTIPLE_VALUES_LIMIT)");
- return arg1;
+ ThreadLocalData.setValues(vals);
+ if(vals.length > 0)
+ return vals[0];
+ return null;
}
}
diff --git a/src/jvm/clojure/runtime/RatioNum.java b/src/jvm/clojure/runtime/RatioNum.java
index e0efe5d1..8f39d1e0 100644
--- a/src/jvm/clojure/runtime/RatioNum.java
+++ b/src/jvm/clojure/runtime/RatioNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:14:44 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.math.BigInteger;
@@ -172,28 +172,28 @@ public Num divide(RatioNum n)
}
-public Object truncateDivide(ThreadLocalData tld, Num num)
+public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, this);
+ return num.truncateBy( this);
}
-public Object truncateBy(ThreadLocalData tld, int div)
+public Object truncateBy( int div)
{
- Num q = (Num) Num.truncate(tld, numerator, denominator.multiply(div));
- return RT.setValues(tld, q, q.multiply(div).subtractFrom(this));
+ Num q = (Num) Num.truncate( numerator, denominator.multiply(div));
+ return RT.setValues( q, q.multiply(div).subtractFrom(this));
}
-public Object truncateBy(ThreadLocalData tld, BigInteger div)
+public Object truncateBy( BigInteger div)
{
- Num q = (Num) Num.truncate(tld, numerator, denominator.multiply(div));
- return RT.setValues(tld, q, q.multiply(div).subtractFrom(this));
+ Num q = (Num) Num.truncate( numerator, denominator.multiply(div));
+ return RT.setValues( q, q.multiply(div).subtractFrom(this));
}
-public Object truncateBy(ThreadLocalData tld, RatioNum div)
+public Object truncateBy( RatioNum div)
{
- Num q = (Num) Num.truncate(tld, numerator.multiplyBy(div.denominator),
+ Num q = (Num) Num.truncate( numerator.multiplyBy(div.denominator),
denominator.multiplyBy(div.numerator));
- return RT.setValues(tld, q, q.multiplyBy(div).subtractFrom(this));
+ return RT.setValues( q, q.multiplyBy(div).subtractFrom(this));
}
diff --git a/src/jvm/clojure/runtime/RationalNum.java b/src/jvm/clojure/runtime/RationalNum.java
index 81cd16b5..814122d5 100644
--- a/src/jvm/clojure/runtime/RationalNum.java
+++ b/src/jvm/clojure/runtime/RationalNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:12:30 AM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RationalNum extends RealNum {
diff --git a/src/jvm/clojure/runtime/RealNum.java b/src/jvm/clojure/runtime/RealNum.java
index 387f0a23..4f069e79 100644
--- a/src/jvm/clojure/runtime/RealNum.java
+++ b/src/jvm/clojure/runtime/RealNum.java
@@ -10,7 +10,7 @@
/* rich Mar 28, 2006 10:13:00 AM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RealNum extends Num {
diff --git a/src/jvm/clojure/runtime/Reflector.java b/src/jvm/clojure/runtime/Reflector.java
index c81a6341..fd0526cf 100644
--- a/src/jvm/clojure/runtime/Reflector.java
+++ b/src/jvm/clojure/runtime/Reflector.java
@@ -10,7 +10,7 @@
/* rich Apr 19, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
import java.lang.reflect.*;
import java.util.ArrayList;
@@ -167,7 +167,7 @@ public static Object invokeInstanceMember(String name, Object target, Object arg
public static Object invokeInstanceMember(String name, Object target, Object arg1, Object arg2, Object arg3,
Object arg4,
- Cons arglist)
+ ISeq arglist)
throws Exception
{
Object[] args = new Object[4 + RT.length(arglist)];
@@ -175,8 +175,8 @@ public static Object invokeInstanceMember(String name, Object target, Object arg
args[1] = arg2;
args[2] = arg3;
args[3] = arg4;
- for(int i = 4; arglist != null; i++, arglist = arglist.rest)
- args[i] = arglist.first;
+ for(int i = 4; arglist != null; i++, arglist = arglist.rest())
+ args[i] = arglist.first();
return invokeInstanceMethod(name, target, args);
}
diff --git a/src/jvm/clojure/runtime/RestFn0.java b/src/jvm/clojure/runtime/RestFn0.java
index b6886c8b..bfc23ad5 100644
--- a/src/jvm/clojure/runtime/RestFn0.java
+++ b/src/jvm/clojure/runtime/RestFn0.java
@@ -10,51 +10,51 @@
/* rich Mar 27, 2006 7:34:25 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn0 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Cons rest) throws Exception;
+protected abstract Object doInvoke( ISeq rest) throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
- return doInvoke(tld, arglist);
+ return doInvoke( arglist);
}
-public Object invoke(ThreadLocalData tld) throws Exception
+public Object invoke() throws Exception
{
- return doInvoke(tld, null);
+ return doInvoke( null);
}
-public Object invoke(ThreadLocalData tld, Object arg1) throws Exception
+public Object invoke( Object arg1) throws Exception
{
- return doInvoke(tld, RT.list(arg1));
+ return doInvoke( RT.list(arg1));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception
+public Object invoke( Object arg1, Object arg2) throws Exception
{
- return doInvoke(tld, RT.list(arg1, arg2));
+ return doInvoke( RT.list(arg1, arg2));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
- return doInvoke(tld, RT.list(arg1, arg2, arg3));
+ return doInvoke( RT.list(arg1, arg2, arg3));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
- return doInvoke(tld, RT.list(arg1, arg2, arg3, arg4));
+ return doInvoke( RT.list(arg1, arg2, arg3, arg4));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, RT.list(arg1, arg2, arg3, arg4, arg5));
+ return doInvoke( RT.list(arg1, arg2, arg3, arg4, arg5));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, RT.listStar(arg1, arg2, arg3, arg4, arg5, args));
+ return doInvoke( RT.listStar(arg1, arg2, arg3, arg4, arg5, args));
}
}
diff --git a/src/jvm/clojure/runtime/RestFn1.java b/src/jvm/clojure/runtime/RestFn1.java
index f763b0c4..b401f763 100644
--- a/src/jvm/clojure/runtime/RestFn1.java
+++ b/src/jvm/clojure/runtime/RestFn1.java
@@ -10,56 +10,56 @@
/* rich Mar 27, 2006 8:00:28 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn1 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Cons rest) throws Exception;
+protected abstract Object doInvoke( Object arg1, ISeq rest) throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 1))
{
case 0:
- return invoke(tld);
+ return invoke();
case 1:
- return invoke(tld,arglist.first);
+ return invoke(arglist.first());
default:
- return doInvoke(tld, arglist.first
- , arglist.rest);
+ return doInvoke( arglist.first()
+ , arglist.rest());
}
}
-public Object invoke(ThreadLocalData tld, Object arg1) throws Exception
+public Object invoke( Object arg1) throws Exception
{
- return doInvoke(tld, arg1, null);
+ return doInvoke( arg1, null);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception
+public Object invoke( Object arg1, Object arg2) throws Exception
{
- return doInvoke(tld, arg1, RT.list(arg2));
+ return doInvoke( arg1, RT.list(arg2));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
- return doInvoke(tld, arg1, RT.list(arg2, arg3));
+ return doInvoke( arg1, RT.list(arg2, arg3));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
- return doInvoke(tld, arg1, RT.list(arg2, arg3, arg4));
+ return doInvoke( arg1, RT.list(arg2, arg3, arg4));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, arg1, RT.list(arg2, arg3, arg4, arg5));
+ return doInvoke( arg1, RT.list(arg2, arg3, arg4, arg5));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, arg1, RT.listStar(arg2, arg3, arg4, arg5, args));
+ return doInvoke( arg1, RT.listStar(arg2, arg3, arg4, arg5, args));
}
}
diff --git a/src/jvm/clojure/runtime/RestFn2.java b/src/jvm/clojure/runtime/RestFn2.java
index 8f12ade0..fb8ce4af 100644
--- a/src/jvm/clojure/runtime/RestFn2.java
+++ b/src/jvm/clojure/runtime/RestFn2.java
@@ -10,57 +10,57 @@
/* rich Mar 27, 2006 8:05:10 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn2 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Cons rest) throws Exception;
+protected abstract Object doInvoke( Object arg1, Object arg2, ISeq rest) throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 2))
{
case 0:
- return invoke(tld);
+ return invoke();
case 1:
- return invoke(tld,arglist.first);
+ return invoke(arglist.first());
case 2:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
);
default:
- return doInvoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , arglist.rest);
+ return doInvoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , arglist.rest());
}
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception
+public Object invoke( Object arg1, Object arg2) throws Exception
{
- return doInvoke(tld, arg1, arg2, null);
+ return doInvoke( arg1, arg2, null);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
- return doInvoke(tld, arg1, arg2, RT.list(arg3));
+ return doInvoke( arg1, arg2, RT.list(arg3));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
- return doInvoke(tld, arg1, arg2, RT.list(arg3, arg4));
+ return doInvoke( arg1, arg2, RT.list(arg3, arg4));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, arg1, arg2, RT.list(arg3, arg4, arg5));
+ return doInvoke( arg1, arg2, RT.list(arg3, arg4, arg5));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, arg1, arg2, RT.listStar(arg3, arg4, arg5, args));
+ return doInvoke( arg1, arg2, RT.listStar(arg3, arg4, arg5, args));
}
}
diff --git a/src/jvm/clojure/runtime/RestFn3.java b/src/jvm/clojure/runtime/RestFn3.java
index 9efcbc3e..00aeeb5b 100644
--- a/src/jvm/clojure/runtime/RestFn3.java
+++ b/src/jvm/clojure/runtime/RestFn3.java
@@ -10,58 +10,58 @@
/* rich Mar 27, 2006 8:19:54 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn3 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Cons rest) throws Exception;
+protected abstract Object doInvoke( Object arg1, Object arg2, Object arg3, ISeq rest) throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 3))
{
case 0:
- return invoke(tld);
+ return invoke();
case 1:
- return invoke(tld,arglist.first);
+ return invoke(arglist.first());
case 2:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
);
case 3:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
default:
- return doInvoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , arglist.rest);
+ return doInvoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , arglist.rest());
}
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3) throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3,null);
+ return doInvoke( arg1, arg2, arg3,null);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, RT.list(arg4));
+ return doInvoke( arg1, arg2, arg3, RT.list(arg4));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, RT.list(arg4, arg5));
+ return doInvoke( arg1, arg2, arg3, RT.list(arg4, arg5));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, RT.listStar(arg4, arg5, args));
+ return doInvoke( arg1, arg2, arg3, RT.listStar(arg4, arg5, args));
}
}
diff --git a/src/jvm/clojure/runtime/RestFn4.java b/src/jvm/clojure/runtime/RestFn4.java
index 1114bce1..45044386 100644
--- a/src/jvm/clojure/runtime/RestFn4.java
+++ b/src/jvm/clojure/runtime/RestFn4.java
@@ -10,61 +10,61 @@
/* rich Mar 27, 2006 8:21:51 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn4 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Cons rest)
+protected abstract Object doInvoke( Object arg1, Object arg2, Object arg3, Object arg4, ISeq rest)
throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 4))
{
case 0:
- return invoke(tld);
+ return invoke();
case 1:
- return invoke(tld,arglist.first);
+ return invoke(arglist.first());
case 2:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
);
case 3:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
case 4:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
default:
- return doInvoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , arglist.rest);
+ return doInvoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , arglist.rest());
}
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, arg4, null);
+ return doInvoke( arg1, arg2, arg3, arg4, null);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, arg4, RT.list(arg5));
+ return doInvoke( arg1, arg2, arg3, arg4, RT.list(arg5));
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, arg4, RT.listStar(arg5, args));
+ return doInvoke( arg1, arg2, arg3, arg4, RT.listStar(arg5, args));
}
}
diff --git a/src/jvm/clojure/runtime/RestFn5.java b/src/jvm/clojure/runtime/RestFn5.java
index 7b8b414a..6271e0b2 100644
--- a/src/jvm/clojure/runtime/RestFn5.java
+++ b/src/jvm/clojure/runtime/RestFn5.java
@@ -10,64 +10,64 @@
/* rich Mar 27, 2006 8:24:31 PM */
-package org.clojure.runtime;
+package clojure.runtime;
public abstract class RestFn5 extends AFn{
-protected abstract Object doInvoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
- Cons rest)
+protected abstract Object doInvoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+ ISeq rest)
throws Exception;
-public Object applyTo(ThreadLocalData tld, Cons arglist) throws Exception
+public Object applyTo( ISeq arglist) throws Exception
{
switch(RT.boundedLength(arglist, 5))
{
case 0:
- return invoke(tld);
+ return invoke();
case 1:
- return invoke(tld,arglist.first);
+ return invoke(arglist.first());
case 2:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
);
case 3:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
case 4:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
case 5:
- return invoke(tld,arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
+ return invoke(arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
);
default:
- return doInvoke(tld, arglist.first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , (arglist = arglist.rest).first
- , arglist.rest);
+ return doInvoke( arglist.first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , (arglist = arglist.rest()).first()
+ , arglist.rest());
}
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, arg4, arg5, null);
+ return doInvoke( arg1, arg2, arg3, arg4, arg5, null);
}
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
+public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
throws Exception
{
- return doInvoke(tld, arg1, arg2, arg3, arg4, arg5, args);
+ return doInvoke( arg1, arg2, arg3, arg4, arg5, args);
}
}
diff --git a/src/jvm/clojure/runtime/Symbol.java b/src/jvm/clojure/runtime/Symbol.java
index 269becfa..40e43587 100644
--- a/src/jvm/clojure/runtime/Symbol.java
+++ b/src/jvm/clojure/runtime/Symbol.java
@@ -10,7 +10,7 @@
/* rich Mar 25, 2006 11:42:47 AM */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/src/jvm/clojure/runtime/TObj.java b/src/jvm/clojure/runtime/TObj.java
index 8a0acb57..ece3a128 100644
--- a/src/jvm/clojure/runtime/TObj.java
+++ b/src/jvm/clojure/runtime/TObj.java
@@ -8,29 +8,30 @@
* You must not remove this notice, or any other, from this software.
**/
-package org.clojure.runtime;
+package clojure.runtime;
public class TObj implements IObj{
TRef attrs;
-public TObj(ThreadLocalData tld) throws Exception{
- this.attrs = Transaction.tref(tld,new RBTree());
+public TObj() throws Exception{
+ this.attrs = Transaction.tref(new PersistentTree());
}
-public Object put(ThreadLocalData tld, Comparable key, Object val) throws Exception {
- RBTree t = (RBTree) Transaction.get(tld, attrs);
+
+public Object put( Comparable key, Object val) throws Exception {
+ PersistentTree t = (PersistentTree) Transaction.get2( attrs);
t = t.put(key, val);
- Transaction.set(tld,attrs,t);
+ Transaction.set2(attrs,t);
return val;
}
-public Object get(ThreadLocalData tld, Comparable key) throws Exception {
- RBTree t = (RBTree) Transaction.get(tld, attrs);
+public Object get( Comparable key) throws Exception {
+ PersistentTree t = (PersistentTree) Transaction.get2( attrs);
return t.get(key);
}
-public boolean has(ThreadLocalData tld, Comparable key) throws Exception {
- RBTree t = (RBTree) Transaction.get(tld, attrs);
+public boolean has( Comparable key) throws Exception {
+ PersistentTree t = (PersistentTree) Transaction.get2( attrs);
return t.contains(key);
}
}
diff --git a/src/jvm/clojure/runtime/TRef.java b/src/jvm/clojure/runtime/TRef.java
index a955cdf5..501674a6 100644
--- a/src/jvm/clojure/runtime/TRef.java
+++ b/src/jvm/clojure/runtime/TRef.java
@@ -10,7 +10,7 @@
/* rich May 30, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
diff --git a/src/jvm/clojure/runtime/TVal.java b/src/jvm/clojure/runtime/TVal.java
index 1bc72a9b..8330839b 100644
--- a/src/jvm/clojure/runtime/TVal.java
+++ b/src/jvm/clojure/runtime/TVal.java
@@ -10,7 +10,7 @@
/* rich May 30, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
public class TVal{
volatile Object val;
diff --git a/src/jvm/clojure/runtime/ThreadLocalData.java b/src/jvm/clojure/runtime/ThreadLocalData.java
index 0bc9c665..85bda6ff 100644
--- a/src/jvm/clojure/runtime/ThreadLocalData.java
+++ b/src/jvm/clojure/runtime/ThreadLocalData.java
@@ -10,52 +10,28 @@
/* rich Mar 25, 2006 11:45:22 AM */
-package org.clojure.runtime;
-
-import java.util.IdentityHashMap;
+package clojure.runtime;
public class ThreadLocalData{
-final public static int MULTIPLE_VALUES_LIMIT = 20;
-public int mvCount = 0;
-public Object[] mvArray = new Object[MULTIPLE_VALUES_LIMIT];
+private static ThreadLocal<Transaction> transaction = new ThreadLocal<Transaction>();
+private static ThreadLocal<Object[]> values = new ThreadLocal<Object[]>();
+
+static public Object[] getValues(){
+ return values.get();
+}
+
+static public void setValues(Object[] vals) {
+ values.set(vals);
+}
-IdentityHashMap dynamicBindings = new IdentityHashMap();
-Transaction transaction;
+static public Transaction getTransaction() {
+ return transaction.get();
-public Transaction getTransaction() throws Exception{
- if(transaction == null)
- throw new Exception("No active transaction");
- return transaction;
}
-public ThreadLocalData(IdentityHashMap dynamicBindings)
- {
- this.mvCount = 0;
- this.mvArray = new Object[MULTIPLE_VALUES_LIMIT];
- this.dynamicBindings = dynamicBindings;
- }
-
-public ThreadLocalData()
- {
- this(new IdentityHashMap());
- }
-
-public static ThreadLocalData get()
- {
- return (ThreadLocalData) tld.get();
- }
-
-static InheritableThreadLocal tld = new InheritableThreadLocal(){
- protected Object childValue(Object object)
- {
- return new ThreadLocalData((IdentityHashMap) ((ThreadLocalData) object).dynamicBindings.clone());
- }
-
- protected Object initialValue()
- {
- return new ThreadLocalData();
- }
-};
+static public void setTransaction(Transaction t){
+ transaction.set(t);
+}
}
diff --git a/src/jvm/clojure/runtime/Transaction.java b/src/jvm/clojure/runtime/Transaction.java
index d6f4cab6..b0c65ca8 100644
--- a/src/jvm/clojure/runtime/Transaction.java
+++ b/src/jvm/clojure/runtime/Transaction.java
@@ -10,7 +10,7 @@
/* rich May 30, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
import java.util.*;
@@ -44,46 +44,48 @@ Info info;
int startSeq;
IdentityHashMap<TRef,Object> sets;
-IdentityHashMap<TRef,Cons> commutates;
+IdentityHashMap<TRef,ISeq> commutates;
-static public Object runInTransaction(ThreadLocalData tld,IFn fn) throws Exception{
- if(tld.transaction != null)
- return fn.invoke(tld);
- tld.transaction = new Transaction();
+static public Object runInTransaction(IFn fn) throws Exception{
+ if(ThreadLocalData.getTransaction() != null)
+ return fn.invoke();
+ Transaction t = new Transaction();
+ ThreadLocalData.setTransaction(t);
try{
- return tld.transaction.run(tld, fn);
+ return t.run(fn);
}
finally{
- tld.transaction = null;
+ ThreadLocalData.setTransaction(null);
}
}
-static public TRef tref(ThreadLocalData tld, Object val) throws Exception{
- Transaction trans = tld.getTransaction();
+static public TRef tref(Object val) throws Exception{
+ Transaction trans = ThreadLocalData.getTransaction();
TRef tref = new TRef();
trans.set(tref, val);
return tref;
}
-static public Object get(ThreadLocalData tld, TRef tref) throws Exception{
- return tld.getTransaction().get(tref);
+//*
+static public Object get2(TRef tref) throws Exception{
+ return ThreadLocalData.getTransaction().get(tref);
}
-static public Object set(ThreadLocalData tld, TRef tref, Object val) throws Exception{
- return tld.getTransaction().set(tref,val);
+static public Object set2(TRef tref, Object val) throws Exception{
+ return ThreadLocalData.getTransaction().set(tref,val);
}
-static public void touch(ThreadLocalData tld, TRef tref) throws Exception{
- tld.getTransaction().touch(tref);
+static public void touch2(TRef tref) throws Exception{
+ ThreadLocalData.getTransaction().touch(tref);
}
-static public void commutate(ThreadLocalData tld, TRef tref, IFn fn) throws Exception{
- tld.getTransaction().commutate(tref, fn);
+static public void commutate2(TRef tref, IFn fn) throws Exception{
+ ThreadLocalData.getTransaction().commutate(tref, fn);
}
+//*/
-
-Object run(ThreadLocalData tld, IFn fn) throws Exception{
+Object run(IFn fn) throws Exception{
boolean done = false;
Object ret = null;
ArrayList<TRef> locks = null;
@@ -93,7 +95,7 @@ Object run(ThreadLocalData tld, IFn fn) throws Exception{
while(!done){
try
{
- ret = fn.invoke(tld);
+ ret = fn.invoke();
if(locks == null && (sets != null || commutates != null))
locks = new ArrayList<TRef>();
if(sets != null)
@@ -123,15 +125,15 @@ Object run(ThreadLocalData tld, IFn fn) throws Exception{
//at this point all write targets are locked
//turn commutates into sets
- for(Map.Entry<TRef, Cons> e : commutates.entrySet())
+ for(Map.Entry<TRef, ISeq> e : commutates.entrySet())
{
TRef tref = e.getKey();
//note this will npe if tref has never been set, as designed
Object val = getCurrent(tref).val;
- for(Cons c = e.getValue();c!=null;c = c.rest)
+ for(ISeq c = e.getValue();c!=null;c = c.rest())
{
- IFn f = (IFn) c.first;
- val = f.invoke(tld, val);
+ IFn f = (IFn) c.first();
+ val = f.invoke(val);
}
sets.put(tref, val);
}
@@ -225,7 +227,7 @@ void touch(TRef tref) throws Exception{
void commutate(TRef tref, IFn fn) throws Exception{
if(commutates == null)
- commutates = new IdentityHashMap<TRef,Cons>();
+ commutates = new IdentityHashMap<TRef,ISeq>();
if(sets != null && sets.containsKey(tref))
throw new Exception("Can't commutate and set a TRef in the same transaction");
commutates.put(tref, RT.cons(fn, commutates.get(tref)));
diff --git a/src/jvm/clojure/runtime/Var.java b/src/jvm/clojure/runtime/Var.java
index 9e6fe46f..ab1f76b2 100644
--- a/src/jvm/clojure/runtime/Var.java
+++ b/src/jvm/clojure/runtime/Var.java
@@ -10,131 +10,133 @@
/* rich Apr 19, 2006 */
-package org.clojure.runtime;
+package clojure.runtime;
-public class Var extends AFn{
+import java.util.concurrent.atomic.AtomicReference;
+
+public class Var extends AFn {
public final Symbol sym;
public Namespace namespace;
-public Box binding;
+public Binding binding;
public IFn fn; //todo, bind to throw stub?
public IFn setfn;
+AtomicReference<IPersistentMap> threadBindings = new AtomicReference(PersistentArrayIdentityMap.EMPTY);
-Var(Symbol sym, Namespace ns)
- {
- if(!(sym.getClass() == Symbol.class))
+Var(Symbol sym, Namespace ns) {
+ if (!(sym.getClass() == Symbol.class))
throw new IllegalArgumentException("Only simple symbols can be vars");
this.namespace = ns;
- this.sym = sym;
- }
-
-public String toString()
- {
- if(namespace == null)
- return "#:" + sym;
- return namespace.name + ":" + sym;
- }
-
-public Var bind(Object val)
- {
- if(binding == null)
- binding = new Box(val);
- else
- binding.val = val;
-
- if(val instanceof IFn)
- this.fn = (IFn) val;
- else
- this.fn = null; //todo, bind to throw stub?
-
+ this.sym = sym;
+}
+
+public String toString() {
+ if (namespace == null)
+ return "#:" + sym;
+ return namespace.name + ":" + sym;
+}
+
+public Var bind(Object val) {
+ if (binding == null)
+ binding = new Binding(val);
+ else
+ binding.val = val;
+
+ if (val instanceof IFn)
+ this.fn = (IFn) val;
+ else
+ this.fn = null; //todo, bind to throw stub?
+
return this;
- }
-
-public Box getBinding(ThreadLocalData tld)
- {
- Box b = getDynamicBinding(tld);
- if(b != null)
- return b;
- return binding;
- }
-
-public Object getValue(ThreadLocalData tld)
- {
- Box binding = getBinding(tld);
- if(binding != null)
- return binding.val;
- throw new IllegalStateException(this.toString() + " is unbound.");
- }
-
-public Object setValue(ThreadLocalData tld, Object val)
- {
- Box b = getDynamicBinding(tld);
- if(b != null)
- return b.val = val;
- //allow global set to create binding like this?
- if(binding == null)
- throw new IllegalStateException(this.toString() + " is unbound.");
-
- if(val instanceof IFn)
- this.fn = (IFn) val;
- else
- this.fn = null; //todo, bind to throw stub?
-
- return binding.val = val;
- }
-
-final public Box getDynamicBinding(ThreadLocalData tld)
- {
- return (Box) tld.dynamicBindings.get(this);
- }
-
-final public Box establishDynamicBinding(ThreadLocalData tld, Object val)
- {
- Box ret = getDynamicBinding(tld);
- tld.dynamicBindings.put(this, new Box(val));
- return ret;
- }
-
-final public void restoreDynamicBinding(ThreadLocalData tld, Box old)
- {
- tld.dynamicBindings.put(this, old);
- }
-
-public Object invoke(ThreadLocalData tld) throws Exception
- {
- return fn.invoke(tld);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1) throws Exception
- {
- return fn.invoke(tld,arg1);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2) throws Exception
- {
- return fn.invoke(tld,arg1,arg2);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3) throws Exception
- {
- return fn.invoke(tld,arg1,arg2,arg3);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4) throws Exception
- {
- return fn.invoke(tld,arg1,arg2,arg3,arg4);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
- throws Exception
- {
- return fn.invoke(tld,arg1,arg2,arg3,arg4,arg5);
- }
-
-public Object invoke(ThreadLocalData tld, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Cons args)
- throws Exception
- {
- return fn.invoke(tld,arg1,arg2,arg3,arg4,arg5,args);
- }
+}
+
+public Object getValue() {
+ Binding binding = getBinding();
+ if (binding != null)
+ return binding.val;
+ throw new IllegalStateException(this.toString() + " is unbound.");
+}
+
+public Object setValue(Object val) {
+ Binding b = getThreadBinding();
+ if (b != null)
+ return b.val = val;
+ if (binding == null)
+ throw new IllegalStateException(this.toString() + " is unbound.");
+
+ if (val instanceof IFn)
+ this.fn = (IFn) val;
+ else
+ this.fn = null; //todo, bind to throw stub?
+
+ return binding.val = val;
+}
+
+public Binding pushThreadBinding(Object val) {
+ Binding ret = new Binding(val, getThreadBinding());
+ setThreadBinding(ret);
+ return ret;
+}
+
+public void popThreadBinding() {
+ setThreadBinding(getThreadBinding().rest);
+}
+
+private Binding getThreadBinding() {
+ if (threadBindings.get().count() > 0)
+ return (Binding) threadBindings.get().get(Thread.currentThread());
+ return null;
+}
+
+private Binding getBinding() {
+ Binding b = getThreadBinding();
+ if (b != null)
+ return b;
+ return binding;
+}
+
+private void setThreadBinding(Binding b) {
+ Thread thread = Thread.currentThread();
+ IPersistentMap tb;
+ IPersistentMap newtb;
+ do
+ {
+ tb = threadBindings.get();
+ if (b == null)
+ newtb = tb.remove(thread);
+ else
+ newtb = tb.put(thread, b);
+ } while (!threadBindings.compareAndSet(tb, newtb));
+}
+
+public Object invoke() throws Exception {
+ return fn.invoke();
+}
+
+public Object invoke(Object arg1) throws Exception {
+ return fn.invoke(arg1);
+}
+
+public Object invoke(Object arg1, Object arg2) throws Exception {
+ return fn.invoke(arg1, arg2);
+}
+
+public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception {
+ return fn.invoke(arg1, arg2, arg3);
+}
+
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception {
+ return fn.invoke(arg1, arg2, arg3, arg4);
+}
+
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
+ throws Exception {
+ return fn.invoke(arg1, arg2, arg3, arg4, arg5);
+}
+
+public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq args)
+ throws Exception {
+ return fn.invoke(arg1, arg2, arg3, arg4, arg5, args);
+}
}