summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-06-10 21:18:14 +0000
committerRich Hickey <richhickey@gmail.com>2006-06-10 21:18:14 +0000
commitfa698dcab12e029587f1b79f5b99cc4b1cd50a01 (patch)
tree8f6475343481845073a9262ab6638ab0cbae978f
parentac65dac6b044e965d244e78ee5f7d49a62440c92 (diff)
finished tld purge, moved to wide dynamic binding on Vars
-rw-r--r--src/cli/runtime/BigNum.cs18
-rw-r--r--src/cli/runtime/Binding.cs29
-rw-r--r--src/cli/runtime/DoubleNum.cs22
-rw-r--r--src/cli/runtime/FixNum.cs18
-rw-r--r--src/cli/runtime/Num.cs16
-rw-r--r--src/cli/runtime/RatioNum.cs22
-rw-r--r--src/cli/runtime/Var.cs39
-rw-r--r--src/org/clojure/runtime/BigNum.java18
-rw-r--r--src/org/clojure/runtime/Binding.java25
-rw-r--r--src/org/clojure/runtime/DoubleNum.java22
-rw-r--r--src/org/clojure/runtime/FixNum.java18
-rw-r--r--src/org/clojure/runtime/Num.java16
-rw-r--r--src/org/clojure/runtime/RatioNum.java22
-rw-r--r--src/org/clojure/runtime/RestFn0.java2
-rw-r--r--src/org/clojure/runtime/Var.java232
15 files changed, 303 insertions, 216 deletions
diff --git a/src/cli/runtime/BigNum.cs b/src/cli/runtime/BigNum.cs
index 629f09de..805404f7 100644
--- a/src/cli/runtime/BigNum.cs
+++ b/src/cli/runtime/BigNum.cs
@@ -174,25 +174,25 @@ override public Num divide(RatioNum x)
return Num.divide(x.numerator, x.denominator.multiply(val));
}
-override public Object truncateDivide(ThreadLocalData tld, Num num)
+override public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, val);
+ return num.truncateBy( val);
}
-override public Object truncateBy(ThreadLocalData tld, int div)
+override public Object truncateBy( int div)
{
- return Num.truncateBigints(tld, val, BigInteger.valueOf(div));
+ return Num.truncateBigints( val, BigInteger.valueOf(div));
}
-override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+override public Object truncateBy( BigInteger div)
{
- return Num.truncateBigints(tld, val, div);
+ return Num.truncateBigints( val, div);
}
-override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+override 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));
}
override public Num negate()
diff --git a/src/cli/runtime/Binding.cs b/src/cli/runtime/Binding.cs
new file mode 100644
index 00000000..51c1313f
--- /dev/null
+++ b/src/cli/runtime/Binding.cs
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ **/
+
+using System;
+
+namespace org.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/cli/runtime/DoubleNum.cs b/src/cli/runtime/DoubleNum.cs
index f3fcc278..b88ca151 100644
--- a/src/cli/runtime/DoubleNum.cs
+++ b/src/cli/runtime/DoubleNum.cs
@@ -160,40 +160,40 @@ override 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 <= Int32.MaxValue && q >= Int32.MinValue)
{
- 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));
}
}
-override public Object truncateBy(ThreadLocalData tld, BigInteger x)
+override public Object truncateBy( BigInteger x)
{
- return truncate(tld, val, x.doubleValue());
+ return truncate( val, x.doubleValue());
}
-override public Object truncateBy(ThreadLocalData tld, int x)
+override public Object truncateBy( int x)
{
- return truncate(tld, val, x);
+ return truncate( val, x);
}
-override public Object truncateBy(ThreadLocalData tld, RatioNum x)
+override public Object truncateBy( RatioNum x)
{
- return truncate(tld, val, x.doubleValue());
+ return truncate( val, x.doubleValue());
}
-override public Object truncateDivide(ThreadLocalData tld, Num num)
+override public Object truncateDivide( Num num)
{
- return truncate(tld, num.doubleValue(), val);
+ return truncate( num.doubleValue(), val);
}
override public Num negate()
diff --git a/src/cli/runtime/FixNum.cs b/src/cli/runtime/FixNum.cs
index 99750aa7..f4a8d52d 100644
--- a/src/cli/runtime/FixNum.cs
+++ b/src/cli/runtime/FixNum.cs
@@ -149,25 +149,25 @@ override public Num multiply(RatioNum x)
return x.multiply(val);
}
-override public Object truncateDivide(ThreadLocalData tld, Num num)
+override public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, val);
+ return num.truncateBy( val);
}
-override public Object truncateBy(ThreadLocalData tld, int div)
+override 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));
}
-override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+override public Object truncateBy( BigInteger div)
{
- return Num.truncateBigints(tld, BigInteger.valueOf(val), div);
+ return Num.truncateBigints( BigInteger.valueOf(val), div);
}
-override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+override 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));
}
override public Num divideBy(Num rhs)
diff --git a/src/cli/runtime/Num.cs b/src/cli/runtime/Num.cs
index 682381f1..8758b198 100644
--- a/src/cli/runtime/Num.cs
+++ b/src/cli/runtime/Num.cs
@@ -153,23 +153,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]));
}
internal static BigInteger BIG_ONE = BigInteger.valueOf(1);
diff --git a/src/cli/runtime/RatioNum.cs b/src/cli/runtime/RatioNum.cs
index 945a233f..c09d6b13 100644
--- a/src/cli/runtime/RatioNum.cs
+++ b/src/cli/runtime/RatioNum.cs
@@ -174,28 +174,28 @@ override public Num divide(RatioNum n)
}
-override public Object truncateDivide(ThreadLocalData tld, Num num)
+override public Object truncateDivide( Num num)
{
- return num.truncateBy(tld, this);
+ return num.truncateBy( this);
}
-override public Object truncateBy(ThreadLocalData tld, int div)
+override 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));
}
-override public Object truncateBy(ThreadLocalData tld, BigInteger div)
+override 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));
}
-override public Object truncateBy(ThreadLocalData tld, RatioNum div)
+override 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/cli/runtime/Var.cs b/src/cli/runtime/Var.cs
index dfbb4ea1..c928b1d9 100644
--- a/src/cli/runtime/Var.cs
+++ b/src/cli/runtime/Var.cs
@@ -9,17 +9,48 @@
**/
using System;
+using System.Threading;
namespace org.clojure.runtime
{
public class Var : AFn
{
-public readonly Symbol sym; public Namespace ns; public Box binding; public IFn fn; //todo, bind to throw stub? public IFn setfn; internal Var(Symbol sym, Namespace ns) { if(sym.GetType() != typeof(Symbol)) throw new ArgumentException("Only simple symbols can be vars"); this.ns = ns; this.sym = sym; } public String toString() { if(ns == null) return "#:" + sym; return ns.name + ":" + sym; } public Var bind(Object val) { if(binding == null) binding = new Box(val); else binding.val = val;
+public readonly Symbol sym; public Namespace ns; public Binding binding; public IFn fn; //todo, bind to throw stub? public IFn setfn; volatile IPersistentMap threadBindings = PersistentArrayIdentityMap.EMPTY; internal Var(Symbol sym, Namespace ns) { if(sym.GetType() != typeof(Symbol)) throw new ArgumentException("Only simple symbols can be vars"); this.ns = ns; this.sym = sym; } public String toString() { if(ns == null) return "#:" + sym; return ns.name + ":" + sym; } public Var bind(Object val) { if(binding == null)
+ binding = new Binding(val); else binding.val = val;
if (val is 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 InvalidOperationException(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 InvalidOperationException(this.toString() + " is unbound."); if(val is IFn) this.fn = (IFn) val; else this.fn = null; //todo, bind to throw stub? return binding.val = val; } public Box getDynamicBinding(ThreadLocalData tld) { return (Box) tld.dynamicBindings[this]; } public Box establishDynamicBinding(ThreadLocalData tld, Object val) { Box ret = getDynamicBinding(tld); tld.dynamicBindings[this] = new Box(val); return ret; } public void restoreDynamicBinding(ThreadLocalData tld, Box old) { tld.dynamicBindings[this] = old;
- } override public Object invoke() /*throws Exception*/ { return fn.invoke(); } override public Object invoke( Object arg1) /*throws Exception*/ { return fn.invoke(arg1); } override public Object invoke( Object arg1, Object arg2) /*throws Exception*/ { return fn.invoke(arg1,arg2); } override public Object invoke( Object arg1, Object arg2, Object arg3) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4,arg5); } override 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); } }
+ this.fn = null; //todo, bind to throw stub? return this; } public Object getValue() {
+ Binding binding = getBinding(); if(binding != null) return binding.val; throw new InvalidOperationException(this.toString() + " is unbound."); } public Object setValue(Object val) {
+ Binding b = getThreadBinding(); if(b != null) return b.val = val; if(binding == null)
+ throw new InvalidOperationException(this.toString() + " is unbound."); if(val is 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);
+}
+
+Binding getBinding() {
+ Binding b = getThreadBinding(); if(b != null) return b; return binding; }
+Binding getThreadBinding() {
+ if (threadBindings.count() > 0)
+ return (Binding)threadBindings.get(Thread.CurrentThread); return null; } void setThreadBinding(Binding b) {
+ Thread thread = Thread.CurrentThread;
+ IPersistentMap tb;
+ IPersistentMap newtb;
+ do
+ {
+ tb = threadBindings;
+ if (b == null)
+ newtb = tb.remove(thread);
+ else
+ newtb = tb.put(thread, b);
+ } while (tb != Interlocked.CompareExchange(ref threadBindings, newtb, tb));
+} override public Object invoke() /*throws Exception*/ { return fn.invoke(); } override public Object invoke( Object arg1) /*throws Exception*/ { return fn.invoke(arg1); } override public Object invoke( Object arg1, Object arg2) /*throws Exception*/ { return fn.invoke(arg1,arg2); } override public Object invoke( Object arg1, Object arg2, Object arg3) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4); } override public Object invoke( Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) /*throws Exception*/ { return fn.invoke(arg1,arg2,arg3,arg4,arg5); } override 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); } }
}
diff --git a/src/org/clojure/runtime/BigNum.java b/src/org/clojure/runtime/BigNum.java
index 3955fe6a..a032ca89 100644
--- a/src/org/clojure/runtime/BigNum.java
+++ b/src/org/clojure/runtime/BigNum.java
@@ -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/org/clojure/runtime/Binding.java b/src/org/clojure/runtime/Binding.java
new file mode 100644
index 00000000..86fcd5fa
--- /dev/null
+++ b/src/org/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 org.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/org/clojure/runtime/DoubleNum.java b/src/org/clojure/runtime/DoubleNum.java
index 00ec7c7a..59ff1428 100644
--- a/src/org/clojure/runtime/DoubleNum.java
+++ b/src/org/clojure/runtime/DoubleNum.java
@@ -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/org/clojure/runtime/FixNum.java b/src/org/clojure/runtime/FixNum.java
index 31ecf1cb..c34557cd 100644
--- a/src/org/clojure/runtime/FixNum.java
+++ b/src/org/clojure/runtime/FixNum.java
@@ -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/org/clojure/runtime/Num.java b/src/org/clojure/runtime/Num.java
index 182955e2..a5a2d6b5 100644
--- a/src/org/clojure/runtime/Num.java
+++ b/src/org/clojure/runtime/Num.java
@@ -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/org/clojure/runtime/RatioNum.java b/src/org/clojure/runtime/RatioNum.java
index e0efe5d1..9bc5e7d0 100644
--- a/src/org/clojure/runtime/RatioNum.java
+++ b/src/org/clojure/runtime/RatioNum.java
@@ -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/org/clojure/runtime/RestFn0.java b/src/org/clojure/runtime/RestFn0.java
index 352d1bb8..5dc8f2a1 100644
--- a/src/org/clojure/runtime/RestFn0.java
+++ b/src/org/clojure/runtime/RestFn0.java
@@ -21,7 +21,7 @@ public Object applyTo( ISeq arglist) throws Exception
return doInvoke( arglist);
}
-public Object invoke(ThreadLocalData tld) throws Exception
+public Object invoke() throws Exception
{
return doInvoke( null);
}
diff --git a/src/org/clojure/runtime/Var.java b/src/org/clojure/runtime/Var.java
index b362a9a3..6d17bafa 100644
--- a/src/org/clojure/runtime/Var.java
+++ b/src/org/clojure/runtime/Var.java
@@ -12,129 +12,131 @@
package org.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() 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);
- }
+}
+
+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);
+}
}