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 /src/cli/runtime/Var.cs | |
| parent | ac65dac6b044e965d244e78ee5f7d49a62440c92 (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.cs | 39 |
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);
}
}
}
|
