PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Backend/Runtime/Dict.cs

https://bitbucket.org/AdamMil/boaold
C# | 203 lines | 155 code | 24 blank | 24 comment | 16 complexity | 172a1acb698139547a170cedcdbd949f MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. Boa is the reference implementation for a language similar to Python,
  3. also called Boa. This implementation is both interpreted and compiled,
  4. targeting the Microsoft .NET Framework.
  5. http://www.adammil.net/
  6. Copyright (C) 2004-2005 Adam Milazzo
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. using System;
  20. using System.Collections;
  21. using System.Collections.Specialized;
  22. // TODO: don't allow __repr__ to go into an infinite loop with circular references
  23. // TODO: make IDictionary.GetEnumerator() (returns DictionaryEntry) different from
  24. // IEnumerator.GetEnumerator() (returns keys), if possible
  25. // TODO: make objects that boa considers equal be the same key
  26. namespace Boa.Runtime
  27. {
  28. [BoaType("dict")]
  29. public class Dict : HybridDictionary, IComparable, IMapping, ICloneable, IRepresentable
  30. { public Dict() { }
  31. public Dict(IDictionary dict) { foreach(DictionaryEntry e in dict) Add(e.Key, e.Value); }
  32. public Dict(object o)
  33. { IEnumerator e = Ops.GetEnumerator(o);
  34. int i=0;
  35. while(e.MoveNext())
  36. { Tuple tup = e.Current as Tuple;
  37. if(tup==null || tup.Count!=2) throw Ops.TypeError("dict(): sequence element #{0} is not a 2-tuple", i);
  38. Add(tup.items[0], tup.items[1]);
  39. }
  40. }
  41. public Dict(int size) : base(size) { }
  42. #region DictEnumerator
  43. public class DictEnumerator : IEnumerator
  44. { public DictEnumerator(IDictionary dict) { e=dict.GetEnumerator(); }
  45. public object Current
  46. { get
  47. { if(current!=null) return current;
  48. DictionaryEntry e = (DictionaryEntry)this.e.Current;
  49. return current=new Tuple(e.Key, e.Value);
  50. }
  51. }
  52. public bool MoveNext() { current=null; return e.MoveNext(); }
  53. public void Reset() { current=null; e.Reset(); }
  54. IDictionaryEnumerator e;
  55. Tuple current;
  56. }
  57. #endregion
  58. public override bool Equals(object o)
  59. { if(o is Dict)
  60. { List l1 = items();
  61. l1.sort();
  62. List l2 = ((Dict)o).items();
  63. l2.sort();
  64. return l1.Equals(l2);
  65. }
  66. else return false;
  67. }
  68. public override int GetHashCode() { throw Ops.TypeError("dict objects are unhashable"); }
  69. public override string ToString() { return __repr__(); }
  70. #region IComparable Members
  71. public int CompareTo(object o)
  72. { if(o is Dict)
  73. { List l1 = items();
  74. l1.sort();
  75. List l2 = ((Dict)o).items();
  76. l2.sort();
  77. return l1.CompareTo(l2);
  78. }
  79. else return -1; // FIXME: compare by type names, like python does
  80. }
  81. #endregion
  82. #region IMapping Members
  83. public void clear() { Clear(); }
  84. public object copy() { return Clone(); }
  85. public object get(object key) { return this[key]; }
  86. public object get(object key, object defaultValue)
  87. { return Contains(key) ? this[key] : defaultValue;
  88. }
  89. public bool has_key(object key) { return Contains(key); }
  90. static Dict fromkeys(object seq) { return fromkeys(seq, null); }
  91. static Dict fromkeys(object seq, object value)
  92. { Dict d = new Dict();
  93. IEnumerator e = Ops.GetEnumerator(seq);
  94. while(e.MoveNext()) d[e.Current] = value;
  95. return d;
  96. }
  97. public object pop(object key)
  98. { object value = __getitem__(key);
  99. Remove(key);
  100. return value;
  101. }
  102. public object pop(object key, object defaultValue)
  103. { object value = Contains(key) ? this[key] : defaultValue;
  104. Remove(key);
  105. return value;
  106. }
  107. public Tuple popitem() // TODO: this is inefficient. any way to speed it up?
  108. { if(Count==0) throw Ops.KeyError("popitem(): dictionary is empty");
  109. IDictionaryEnumerator e = GetEnumerator();
  110. e.MoveNext();
  111. return new Tuple(e.Key, e.Value);
  112. }
  113. public object setdefault(object key) { return setdefault(key, null); }
  114. public object setdefault(object key, object defaultValue)
  115. { if(Contains(key)) return this[key];
  116. this[key] = defaultValue;
  117. return defaultValue;
  118. }
  119. public void update(object dict)
  120. { IDictionary d = dict as IDictionary;
  121. if(d!=null) foreach(DictionaryEntry e in d) this[e.Key] = e.Value;
  122. else
  123. { IMapping m = dict as IMapping;
  124. if(m!=null)
  125. { IEnumerator e = Ops.GetEnumerator(m.keys());
  126. while(e.MoveNext()) this[e.Current] = m.get(e.Current);
  127. }
  128. else
  129. { object getitem = Ops.GetAttr(dict, "__getitem__");
  130. IEnumerator e = Ops.GetEnumerator(Ops.Invoke(dict, "keys"));
  131. while(e.MoveNext()) this[e.Current] = Ops.Call(getitem, e.Current);
  132. }
  133. }
  134. }
  135. public List items()
  136. { List ret = new List(Count);
  137. foreach(DictionaryEntry e in this) ret.Add(new Tuple(e.Key, e.Value));
  138. return ret;
  139. }
  140. public List keys() { return new List(Keys); }
  141. public List values() { return new List(Values); }
  142. public IEnumerator iteritems() { return new DictEnumerator(this); }
  143. public IEnumerator iterkeys() { return Keys.GetEnumerator(); }
  144. public IEnumerator itervalues() { return Values.GetEnumerator(); }
  145. public void __delitem__(object key)
  146. { if(!Contains(key)) throw Ops.KeyError(Ops.Repr(key));
  147. Remove(key);
  148. }
  149. public object __getitem__(object key)
  150. { if(Contains(key)) return this[key];
  151. else throw Ops.KeyError(Ops.Repr(key));
  152. }
  153. public void __setitem__(object key, object value) { this[key]=value; }
  154. public int __len__() { return Count; }
  155. public bool __contains__(object key) { return Contains(key); }
  156. #endregion
  157. #region ICloneable Members
  158. public object Clone() { return new Dict(this); }
  159. #endregion
  160. #region IRepresentable Members
  161. public string __repr__()
  162. { System.Text.StringBuilder sb = new System.Text.StringBuilder();
  163. sb.Append('{');
  164. bool first=true;
  165. foreach(DictionaryEntry e in this)
  166. { if(first) first=false;
  167. else sb.Append(", ");
  168. sb.Append(Ops.Repr(e.Key));
  169. sb.Append(": ");
  170. sb.Append(Ops.Repr(e.Value));
  171. }
  172. sb.Append('}');
  173. return sb.ToString();
  174. }
  175. #endregion
  176. }
  177. } // namespace Boa.Runtime