diff options
Diffstat (limited to 'src/cli')
-rw-r--r-- | src/cli/runtime/PersistentListIdentityMap.cs | 47 | ||||
-rw-r--r-- | src/cli/runtime/PersistentListMap.cs | 49 | ||||
-rw-r--r-- | src/cli/runtime/PersistentTreeMap.cs | 32 |
3 files changed, 86 insertions, 42 deletions
diff --git a/src/cli/runtime/PersistentListIdentityMap.cs b/src/cli/runtime/PersistentListIdentityMap.cs index 0a60ebc6..b00fd620 100644 --- a/src/cli/runtime/PersistentListIdentityMap.cs +++ b/src/cli/runtime/PersistentListIdentityMap.cs @@ -31,16 +31,23 @@ namespace clojure.lang * code duplication here is kind of gross, but most efficient
*/
- public class PersistentListIdentityMap : IPersistentMap, IMapEntry, ISeq, ISequential
+ public class PersistentListIdentityMap : Obj, IPersistentMap, IMapEntry, ISeq, ISequential
{
static public PersistentListIdentityMap EMPTY = new PersistentListIdentityMap();
static public PersistentListIdentityMap create(Object key, Object val)
{
- return new Tail(key, val);
+ return new Tail(key, val,null);
}
+ public override Obj withMeta(IPersistentMap meta)
+ {
+ Obj ret = (Obj)MemberwiseClone();
+ ret._meta = meta;
+ return ret;
+ }
+
public virtual Object key()
{
return null;
@@ -78,7 +85,7 @@ namespace clojure.lang public virtual IPersistentMap put(Object key, Object val)
{
- return new Tail(key, val);
+ return new Tail(key, val, _meta);
}
public virtual IPersistentMap remove(Object key)
@@ -134,7 +141,7 @@ namespace clojure.lang first = false;
else
e = e.next();
- return e != EMPTY;
+ return e.count() > 0;
}
public void Reset()
@@ -155,10 +162,11 @@ namespace clojure.lang readonly Object _key;
readonly Object _val;
- internal Tail(Object key, Object val)
+ internal Tail(Object key, Object val, IPersistentMap meta)
{
this._key = key;
this._val = val;
+ this._meta = meta;
}
override internal PersistentListIdentityMap next()
@@ -211,7 +219,7 @@ namespace clojure.lang {
throw new Exception("Key already present");
}
- return new Link(key, val, this);
+ return new Link(key, val, this, _meta);
}
override public IPersistentMap put(Object key, Object val)
@@ -220,15 +228,19 @@ namespace clojure.lang {
if (val == _val)
return this;
- return new Tail(key, val);
+ return new Tail(key, val, _meta);
}
- return new Link(key, val, this);
+ return new Link(key, val, this, _meta);
}
override public IPersistentMap remove(Object key)
{
if ((key == _key))
- return EMPTY;
+ {
+ if (_meta == null)
+ return EMPTY;
+ return (IPersistentMap)EMPTY.withMeta(_meta);
+ }
return this;
}
@@ -254,11 +266,12 @@ namespace clojure.lang readonly Object _val;
readonly PersistentListIdentityMap _rest;
- internal Link(Object key, Object val, PersistentListIdentityMap next)
+ internal Link(Object key, Object val, PersistentListIdentityMap next, IPersistentMap meta)
{
this._key = key;
this._val = val;
this._rest = next;
+ this._meta = meta;
}
override public Object key()
@@ -300,7 +313,7 @@ namespace clojure.lang {
throw new Exception("Key already present");
}
- return new Link(key, val, this);
+ return new Link(key, val, this, _meta);
}
override public IPersistentMap put(Object key, Object val)
@@ -312,13 +325,17 @@ namespace clojure.lang return this;
return create(_key, _val, remove(key));
}
- return new Link(key, val, this);
+ return new Link(key, val, this, _meta);
}
override public IPersistentMap remove(Object key)
{
if ((key == _key))
- return _rest;
+ {
+ if (_rest._meta == _meta)
+ return _rest;
+ return (IPersistentMap)_rest.withMeta(_meta);
+ }
PersistentListIdentityMap r = (PersistentListIdentityMap)_rest.remove(key);
if (r == _rest) //not there
return this;
@@ -356,8 +373,8 @@ namespace clojure.lang PersistentListIdentityMap create(Object k, Object v, IPersistentMap r)
{
if (r == EMPTY)
- return new Tail(k, v);
- return new Link(k, v, (PersistentListIdentityMap)r);
+ return new Tail(k, v, _meta);
+ return new Link(k, v, (PersistentListIdentityMap)r, _meta);
}
}
diff --git a/src/cli/runtime/PersistentListMap.cs b/src/cli/runtime/PersistentListMap.cs index 04065097..a3896c97 100644 --- a/src/cli/runtime/PersistentListMap.cs +++ b/src/cli/runtime/PersistentListMap.cs @@ -27,15 +27,22 @@ namespace clojure.lang *
* null keys and values are ok, but you won't be able to distinguish a null value via get - use contains/find
*/
-public class PersistentListMap : IPersistentMap, IMapEntry, ISeq, ISequential
+public class PersistentListMap : Obj, IPersistentMap, IMapEntry, ISeq, ISequential
{
static public PersistentListMap EMPTY = new PersistentListMap();
static public PersistentListMap create(Object key, Object val){
- return new Tail(key, val);
+ return new Tail(key, val,null);
}
+public override Obj withMeta(IPersistentMap meta)
+ {
+ Obj ret = (Obj)MemberwiseClone();
+ ret._meta = meta;
+ return ret;
+ }
+
public virtual Object key(){
return null;
}
@@ -65,7 +72,7 @@ public virtual IPersistentMap add(Object key, Object val){ }
public virtual IPersistentMap put(Object key, Object val){
- return new Tail(key, val);
+ return new Tail(key, val, _meta);
}
public virtual IPersistentMap remove(Object key){
@@ -118,7 +125,7 @@ public bool MoveNext() first = false;
else
e = e.next();
- return e != EMPTY;
+ return e.count() > 0;
}
public void Reset()
@@ -137,9 +144,10 @@ internal class Tail : PersistentListMap { readonly Object _key;
readonly Object _val;
- internal Tail(Object key,Object val){
+ internal Tail(Object key,Object val,IPersistentMap meta){
this._key = key;
this._val = val;
+ this._meta = meta;
}
override internal PersistentListMap next(){
@@ -191,7 +199,7 @@ internal class Tail : PersistentListMap { {
throw new Exception("Key already present");
}
- return new Link(key, val, this);
+ return new Link(key, val, this,_meta);
}
override public IPersistentMap put(Object key, Object val)
@@ -200,14 +208,18 @@ internal class Tail : PersistentListMap { {
if(val == _val)
return this;
- return new Tail(key,val);
+ return new Tail(key,val,_meta);
}
- return new Link(key,val,this);
+ return new Link(key,val,this,_meta);
}
override public IPersistentMap remove(Object key){
if(equalKey(key,_key))
- return EMPTY;
+ {
+ if(_meta == null)
+ return EMPTY;
+ return (IPersistentMap)EMPTY.withMeta(_meta);
+ }
return this;
}
@@ -232,10 +244,11 @@ internal class Link : PersistentListMap { readonly Object _val;
readonly PersistentListMap _rest;
- internal Link(Object key,Object val,PersistentListMap next){
+ internal Link(Object key,Object val,PersistentListMap next,IPersistentMap meta){
this._key = key;
this._val = val;
this._rest = next;
+ this._meta = meta;
}
override public Object key(){
@@ -271,7 +284,7 @@ internal class Link : PersistentListMap { {
throw new Exception("Key already present");
}
- return new Link(key,val,this);
+ return new Link(key,val,this,_meta);
}
override public IPersistentMap put(Object key, Object val)
@@ -283,13 +296,17 @@ internal class Link : PersistentListMap { return this;
return create(_key,_val,remove(key));
}
- return new Link(key,val,this);
+ return new Link(key,val,this,_meta);
}
override public IPersistentMap remove(Object key)
{
if(equalKey(key,_key))
- return _rest;
+ {
+ if(_rest._meta == _meta)
+ return _rest;
+ return (IPersistentMap)_rest.withMeta(_meta);
+ }
PersistentListMap r = (PersistentListMap)_rest.remove(key);
if(r == _rest) //not there
return this;
@@ -324,9 +341,9 @@ internal class Link : PersistentListMap { PersistentListMap create(Object k, Object v, IPersistentMap r)
{
- if(r == EMPTY)
- return new Tail(k,v);
- return new Link(k, v, (PersistentListMap)r);
+ if(r.count() == 0)
+ return new Tail(k,v,_meta);
+ return new Link(k, v, (PersistentListMap)r,_meta);
}
}
diff --git a/src/cli/runtime/PersistentTreeMap.cs b/src/cli/runtime/PersistentTreeMap.cs index 93335bf9..79831fe1 100644 --- a/src/cli/runtime/PersistentTreeMap.cs +++ b/src/cli/runtime/PersistentTreeMap.cs @@ -25,7 +25,7 @@ namespace clojure.lang * See Okasaki, Kahrs, Larsen et al */ -public class PersistentTreeMap : IPersistentMap, ISequential{ +public class PersistentTreeMap : Obj, IPersistentMap, ISequential{ public readonly IComparer comp; public readonly Node tree; @@ -40,6 +40,13 @@ public PersistentTreeMap(IComparer comp){ _count = 0; } +public override Obj withMeta(IPersistentMap meta)
+ {
+ Obj ret = (Obj)MemberwiseClone();
+ ret._meta = meta;
+ return ret;
+ } + public int count(){ return _count; } @@ -59,7 +66,7 @@ public IPersistentMap add(Object key,Object val){ { throw new Exception("Key already present");
} - return new PersistentTreeMap(comp, t.blacken(), _count + 1); + return new PersistentTreeMap(comp, t.blacken(), _count + 1, _meta); } public IPersistentMap put(Object key, Object val){ @@ -69,10 +76,10 @@ public IPersistentMap put(Object key, Object val){ { Node foundNode = (Node) found.val; if(foundNode.val() == val) //note only get same collection on identity of val, not equals() - return this; - return new PersistentTreeMap(comp, replace(tree, key, val), _count); - } - return new PersistentTreeMap(comp, t.blacken(), _count + 1); + return this;
+ return new PersistentTreeMap(comp, replace(tree, key, val), _count, _meta); + }
+ return new PersistentTreeMap(comp, t.blacken(), _count + 1, _meta); } @@ -83,10 +90,12 @@ public IPersistentMap remove(Object key){ { if(found.val == null)//null == doesn't contain key return this; - //empty - return new PersistentTreeMap(comp); - } - return new PersistentTreeMap(comp, t.blacken(), _count - 1); + //empty
+ PersistentTreeMap ret = new PersistentTreeMap(comp);
+ ret._meta = _meta;
+ return ret;
+ }
+ return new PersistentTreeMap(comp, t.blacken(), _count - 1, _meta); } public ISeq seq() {
@@ -329,10 +338,11 @@ Node replace(Node t, Object key, Object val){ c > 0 ? replace(t.right(), key, val) : t.right()); } -PersistentTreeMap(IComparer comp, Node tree, int count){ +PersistentTreeMap(IComparer comp, Node tree, int count,IPersistentMap meta){ this.comp = comp; this.tree = tree; this._count = count; + this._meta = meta; } static Red red(Object key, Object val, Node left, Node right){ |