summaryrefslogtreecommitdiff
path: root/src/cli/runtime/Var.cs
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 /src/cli/runtime/Var.cs
parentac65dac6b044e965d244e78ee5f7d49a62440c92 (diff)
finished tld purge, moved to wide dynamic binding on Vars
Diffstat (limited to 'src/cli/runtime/Var.cs')
-rw-r--r--src/cli/runtime/Var.cs39
1 files changed, 35 insertions, 4 deletions
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); } }
}