diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-06-10 21:18:14 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-06-10 21:18:14 +0000 |
commit | fa698dcab12e029587f1b79f5b99cc4b1cd50a01 (patch) | |
tree | 8f6475343481845073a9262ab6638ab0cbae978f | |
parent | ac65dac6b044e965d244e78ee5f7d49a62440c92 (diff) |
finished tld purge, moved to wide dynamic binding on Vars
-rw-r--r-- | src/cli/runtime/BigNum.cs | 18 | ||||
-rw-r--r-- | src/cli/runtime/Binding.cs | 29 | ||||
-rw-r--r-- | src/cli/runtime/DoubleNum.cs | 22 | ||||
-rw-r--r-- | src/cli/runtime/FixNum.cs | 18 | ||||
-rw-r--r-- | src/cli/runtime/Num.cs | 16 | ||||
-rw-r--r-- | src/cli/runtime/RatioNum.cs | 22 | ||||
-rw-r--r-- | src/cli/runtime/Var.cs | 39 | ||||
-rw-r--r-- | src/org/clojure/runtime/BigNum.java | 18 | ||||
-rw-r--r-- | src/org/clojure/runtime/Binding.java | 25 | ||||
-rw-r--r-- | src/org/clojure/runtime/DoubleNum.java | 22 | ||||
-rw-r--r-- | src/org/clojure/runtime/FixNum.java | 18 | ||||
-rw-r--r-- | src/org/clojure/runtime/Num.java | 16 | ||||
-rw-r--r-- | src/org/clojure/runtime/RatioNum.java | 22 | ||||
-rw-r--r-- | src/org/clojure/runtime/RestFn0.java | 2 | ||||
-rw-r--r-- | src/org/clojure/runtime/Var.java | 232 |
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); +} } |