From fa698dcab12e029587f1b79f5b99cc4b1cd50a01 Mon Sep 17 00:00:00 2001 From: Rich Hickey Date: Sat, 10 Jun 2006 21:18:14 +0000 Subject: finished tld purge, moved to wide dynamic binding on Vars --- src/cli/runtime/BigNum.cs | 18 +++++++++--------- src/cli/runtime/Binding.cs | 29 +++++++++++++++++++++++++++++ src/cli/runtime/DoubleNum.cs | 22 +++++++++++----------- src/cli/runtime/FixNum.cs | 18 +++++++++--------- src/cli/runtime/Num.cs | 16 ++++++++-------- src/cli/runtime/RatioNum.cs | 22 +++++++++++----------- src/cli/runtime/Var.cs | 39 +++++++++++++++++++++++++++++++++++---- 7 files changed, 112 insertions(+), 52 deletions(-) create mode 100644 src/cli/runtime/Binding.cs (limited to 'src/cli') 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); } } } -- cgit v1.2.3-70-g09d2