PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Otp/Erlang/List.cs

https://github.com/saleyn/otp.net
C# | 359 lines | 191 code | 43 blank | 125 comment | 51 complexity | fc5e9435c324a485e8cc3b52837f3c9f MD5 | raw file
  1. /*``The contents of this file are subject to the Erlang Public License,
  2. * Version 1.1, (the "License"); you may not use this file except in
  3. * compliance with the License. You should have received a copy of the
  4. * Erlang Public License along with this software. If not, it can be
  5. * retrieved via the world wide web at http://www.erlang.org/.
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. * the License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. * AB. All Rights Reserved.''
  15. *
  16. * Converted from Java to C# by Vlad Dumitrescu (vlad_Dumitrescu@hotmail.com)
  17. * Contribution: Serge Aleynikov (added pattern matching)
  18. */
  19. namespace Otp.Erlang
  20. {
  21. using System;
  22. using System.Collections;
  23. using System.Collections.Generic;
  24. /*
  25. * Provides a C# representation of Erlang lists. Lists are created
  26. * from zero or more arbitrary Erlang terms.
  27. *
  28. * <p> The arity of the list is the number of elements it contains.
  29. **/
  30. [Serializable]
  31. public class List:Erlang.Object, IEnumerable<Object>
  32. {
  33. private Object[] elems;
  34. // todo: use a linked structure to make a proper list with append,
  35. // car, cdr etc methods. The current representation is essensially the
  36. // same as for tuples except that empty lists are allowed.
  37. // private Object car = null;
  38. // private Object cdr = null;
  39. // int arity;
  40. /*
  41. * Create an empty list.
  42. **/
  43. public List()
  44. {
  45. this.elems = new Object[0]; // empty list
  46. }
  47. /*
  48. * Create a list of characters.
  49. *
  50. * @param str the characters from which to create the list.
  51. *
  52. public List(System.String str)
  53. {
  54. this.elems = new Object[] { new Erlang.String(str) };
  55. }
  56. * Create a list containing one element.
  57. *
  58. * @param elem the elememet to make the list from.
  59. *
  60. public List(Object elem)
  61. {
  62. this.elems = new Object[1];
  63. elems[0] = elem;
  64. }
  65. */
  66. /*
  67. * Create a list from an array of arbitrary Erlang terms.
  68. *
  69. * @param elems the array of terms from which to create the list.
  70. * @param count the number of terms to insert.
  71. */
  72. public List(Object[] elems): this(elems, 0, elems.Length)
  73. {
  74. }
  75. /*
  76. * Create a list from an array of arbitrary Erlang terms.
  77. *
  78. * @param elems the array of terms from which to create the list.
  79. * @param start the offset of the first term to insert.
  80. * @param count the number of terms to insert.
  81. */
  82. public List(Object[] elems, int start, int count)
  83. {
  84. if ((elems != null) && (count > 0))
  85. {
  86. this.elems = new Object[count];
  87. Array.Copy(elems, 0, this.elems, start, count);
  88. }
  89. }
  90. /*
  91. * Create a list from an array of arbitrary Erlang terms.
  92. *
  93. * @param elems the array of terms from which to create the list.
  94. **/
  95. public List(params object[] elems)
  96. {
  97. int length = (elems != null) ? elems.Length : 0;
  98. this.elems = new Object[length];
  99. for (int i=0; i < length; i++)
  100. {
  101. object o = elems[i];
  102. if (o is int) this.elems[i] = new Int((int)o);
  103. else if (o is string) this.elems[i] = new String((string)o);
  104. else if (o is float) this.elems[i] = new Double((float)o);
  105. else if (o is double) this.elems[i] = new Double((double)o);
  106. else if (o is Erlang.Object) this.elems[i] = (Erlang.Object)o;
  107. //else if (o is BigInteger) this.elems[i] = (BigInteger)o;
  108. else if (o is uint) this.elems[i] = new UInt((int)o);
  109. else if (o is short) this.elems[i] = new Short((short)o);
  110. else if (o is ushort) this.elems[i] = new UShort((short)o);
  111. else if (o is bool) this.elems[i] = new Boolean((bool)o);
  112. else if (o is char) this.elems[i] = new Char((char)o);
  113. else
  114. throw new System.ArgumentException("Unknown type of element[" + i + "]: " + o.GetType().ToString());
  115. }
  116. }
  117. /*
  118. * Create a list from a stream containing an list encoded in Erlang
  119. * external format.
  120. *
  121. * @param buf the stream containing the encoded list.
  122. *
  123. * @exception DecodeException if the buffer does not
  124. * contain a valid external representation of an Erlang list.
  125. **/
  126. public List(OtpInputStream buf)
  127. {
  128. int arity = buf.read_list_head();
  129. if (arity < 0)
  130. arity = 0;
  131. this.elems = new Object[arity];
  132. if (arity > 0)
  133. {
  134. for (int i = 0; i < arity; i++)
  135. {
  136. elems[i] = buf.read_any();
  137. }
  138. /*discard the terminating nil (empty list) */
  139. buf.read_nil();
  140. }
  141. }
  142. public override Type Type { get { return GetType(); } }
  143. public override TermType TermType { get { return TermType.List; } }
  144. /*
  145. * Get the arity of the list.
  146. *
  147. * @return the number of elements contained in the list.
  148. **/
  149. public int arity()
  150. {
  151. return elems.Length;
  152. }
  153. /*
  154. * Get the specified element from the list.
  155. *
  156. * @param i the index of the requested element. List elements are
  157. * numbered as array elements, starting at 0.
  158. *
  159. * @return the requested element, of null if i is not a valid
  160. * element index.
  161. **/
  162. public Object elementAt(int i)
  163. {
  164. if ((i >= arity()) || (i < 0))
  165. return null;
  166. return elems[i];
  167. }
  168. /*
  169. * Get all the elements from the list as an array.
  170. *
  171. * @return an array containing all of the list's elements.
  172. **/
  173. public Object[] elements()
  174. {
  175. if (arity() == 0)
  176. return null;
  177. else
  178. {
  179. Object[] res = new Object[arity()];
  180. Array.Copy(this.elems, 0, res, 0, res.Length);
  181. return res;
  182. }
  183. }
  184. public Object this[int index]
  185. {
  186. get { return elementAt(index); }
  187. set { this.elems[index] = value; }
  188. }
  189. public int Length
  190. {
  191. get { return this.arity(); }
  192. }
  193. /*
  194. * Get the string representation of the list.
  195. *
  196. * @return the string representation of the list.
  197. **/
  198. public override System.String ToString()
  199. {
  200. System.Text.StringBuilder s = new System.Text.StringBuilder();
  201. int _arity = arity();
  202. s.Append("[");
  203. for (int i = 0; i < _arity; i++)
  204. {
  205. if (i > 0)
  206. s.Append(",");
  207. s.Append(elems[i].ToString());
  208. }
  209. s.Append("]");
  210. return s.ToString();
  211. }
  212. /*
  213. * Convert this list to the equivalent Erlang external
  214. * representation. Note that this method never encodes lists as
  215. * strings, even when it is possible to do so.
  216. *
  217. * @param buf An output stream to which the encoded list should be
  218. * written.
  219. *
  220. **/
  221. public override void encode(OtpOutputStream buf)
  222. {
  223. int _arity = arity();
  224. if (_arity > 0)
  225. {
  226. buf.write_list_head(_arity);
  227. for (int i = 0; i < _arity; i++)
  228. {
  229. buf.write_any(elems[i]);
  230. }
  231. }
  232. buf.write_nil();
  233. }
  234. /*
  235. * Determine if two lists are equal. Lists are equal if they have
  236. * the same arity and all of the elements are equal.
  237. *
  238. * @param o the list to compare to.
  239. *
  240. * @return true if the lists have the same arity and all the
  241. * elements are equal.
  242. **/
  243. public override bool Equals(System.Object o)
  244. {
  245. if (!(o is List))
  246. return false;
  247. List l = (List) o;
  248. int a = this.arity();
  249. if (a != l.arity())
  250. return false;
  251. for (int i = 0; i < a; i++)
  252. {
  253. if (!this.elems[i].Equals(l.elems[i]))
  254. return false;
  255. // early exit
  256. }
  257. return true;
  258. }
  259. public override int GetHashCode()
  260. {
  261. return 1;
  262. }
  263. public override System.Object clone()
  264. {
  265. List newList = (List) (base.clone());
  266. newList.elems = new Object[elems.Length];
  267. elems.CopyTo(newList.elems, 0);
  268. return newList;
  269. }
  270. public override bool subst(ref Erlang.Object a_term, VarBind binding)
  271. {
  272. System.Collections.Generic.List<Erlang.Object> result =
  273. new System.Collections.Generic.List<Erlang.Object>();
  274. bool changed = false;
  275. if (this.elems != null)
  276. foreach (Erlang.Object term in this.elems)
  277. {
  278. Erlang.Object obj = null;
  279. if (term.subst(ref obj, binding))
  280. result.Add(obj);
  281. else
  282. {
  283. changed = true;
  284. result.Add(term);
  285. }
  286. }
  287. if (!changed)
  288. return false;
  289. a_term = new Erlang.List(result.ToArray());
  290. return true;
  291. }
  292. public override bool match(Erlang.Object pattern, VarBind binding)
  293. {
  294. if (pattern is Erlang.Var)
  295. pattern.match(this, binding);
  296. else if (!(pattern is Erlang.List))
  297. return false;
  298. Erlang.List tup = pattern as Erlang.List;
  299. if (arity() != tup.arity())
  300. return false;
  301. for (int i = 0; i < arity(); ++i)
  302. if (!elems[i].match(tup[i], binding))
  303. return false;
  304. return true;
  305. }
  306. IEnumerator<Object> IEnumerable<Object>.GetEnumerator()
  307. {
  308. return ((IEnumerable<Object>)elems).GetEnumerator();
  309. }
  310. IEnumerator IEnumerable.GetEnumerator()
  311. {
  312. return elems.GetEnumerator();
  313. }
  314. }
  315. }