PageRenderTime 58ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Otp/Erlang/Tuple.cs

https://github.com/saleyn/otp.net
C# | 351 lines | 194 code | 35 blank | 122 comment | 51 complexity | a5bc95adeee5083936220159d2ad66f8 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 tuples. Tuples are created
  26. * from one or more arbitrary Erlang terms.
  27. *
  28. * <p> The arity of the tuple is the number of elements it contains.
  29. * Elements are indexed from 0 to (arity-1) and can be retrieved
  30. * individually by using the appropriate index.
  31. **/
  32. [Serializable]
  33. public class Tuple:Erlang.Object, IEnumerable<Object>
  34. {
  35. private Object[] elems = null;
  36. /*
  37. * Create a unary tuple containing the given element.
  38. *
  39. * @param elem the element to create the tuple from.
  40. *
  41. * @exception C#.lang.IllegalArgumentException if the array is
  42. * empty (null).
  43. *
  44. public Tuple(Object elem)
  45. {
  46. if (elem == null)
  47. {
  48. throw new System.ArgumentException("Tuple element cannot be null");
  49. }
  50. this.elems = new Object[1];
  51. elems[0] = elem;
  52. }
  53. */
  54. /*
  55. * Create a tuple from an array of terms.
  56. *
  57. * @param elems the array of terms to create the tuple from.
  58. *
  59. * @exception C#.lang.IllegalArgumentException if the array is
  60. * empty (null) or contains null elements.
  61. */
  62. public Tuple(Object[] elems):this(elems, 0, elems.Length)
  63. {
  64. }
  65. /*
  66. * Create a tuple from an array of terms.
  67. *
  68. * @param elems the array of terms to create the tuple from.
  69. * @param start the offset of the first term to insert.
  70. * @param count the number of terms to insert.
  71. *
  72. * @exception C#.lang.IllegalArgumentException if the array is
  73. * empty (null) or contains null elements.
  74. */
  75. public Tuple(Object[] elems, int start, int count)
  76. {
  77. if ((elems == null) || (count < 1))
  78. {
  79. throw new System.ArgumentException("Cannot make an empty tuple");
  80. }
  81. else
  82. {
  83. this.elems = new Object[count];
  84. for (int i = 0; i < count; i++)
  85. {
  86. if (elems[start + i] != null)
  87. {
  88. this.elems[i] = elems[start + i];
  89. }
  90. else
  91. {
  92. throw new System.ArgumentException("Tuple element cannot be null (element" + (start + i) + ")");
  93. }
  94. }
  95. }
  96. }
  97. /*
  98. * Create a tuple from an array of terms.
  99. *
  100. * @param elems the array of terms to create the tuple from.
  101. * @param start the offset of the first term to insert.
  102. * @param count the number of terms to insert.
  103. *
  104. * @exception C#.lang.IllegalArgumentException if the array is
  105. * empty (null) or contains null elements.
  106. **/
  107. public Tuple(params object[] elems)
  108. {
  109. if (elems == null)
  110. elems = new Object[] {};
  111. else
  112. {
  113. this.elems = new Object[elems.Length];
  114. for (int i = 0; i < elems.Length; i++)
  115. {
  116. if (elems[i] == null)
  117. throw new System.ArgumentException("Tuple element cannot be null (element" + i + ")");
  118. else
  119. {
  120. object o = elems[i];
  121. if (o is int) this.elems[i] = new Int((int)o);
  122. else if (o is string) this.elems[i] = new String((string)o);
  123. else if (o is float) this.elems[i] = new Double((float)o);
  124. else if (o is double) this.elems[i] = new Double((double)o);
  125. else if (o is Erlang.Object) this.elems[i] = (Erlang.Object)o;
  126. //else if (o is BigInteger) this.elems[i] = (BigInteger)o;
  127. else if (o is uint) this.elems[i] = new UInt((int)o);
  128. else if (o is short) this.elems[i] = new Short((short)o);
  129. else if (o is ushort) this.elems[i] = new UShort((short)o);
  130. else if (o is bool) this.elems[i] = new Boolean((bool)o);
  131. else if (o is char) this.elems[i] = new Char((char)o);
  132. else
  133. throw new System.ArgumentException("Unknown type of element[" + i + "]: " + o.GetType().ToString());
  134. }
  135. }
  136. }
  137. }
  138. /*
  139. * Create a tuple from a stream containing an tuple encoded in Erlang
  140. * external format.
  141. *
  142. * @param buf the stream containing the encoded tuple.
  143. *
  144. * @exception DecodeException if the buffer does not
  145. * contain a valid external representation of an Erlang tuple.
  146. **/
  147. public Tuple(OtpInputStream buf)
  148. {
  149. int arity = buf.read_tuple_head();
  150. if (arity > 0)
  151. {
  152. this.elems = new Object[arity];
  153. for (int i = 0; i < arity; i++)
  154. {
  155. elems[i] = buf.read_any();
  156. }
  157. }
  158. }
  159. public override Type Type { get { return GetType(); } }
  160. public override TermType TermType { get { return TermType.Tuple; } }
  161. /*
  162. * Get the arity of the tuple.
  163. *
  164. * @return the number of elements contained in the tuple.
  165. **/
  166. public virtual int arity()
  167. {
  168. return elems.Length;
  169. }
  170. /*
  171. * Get the specified element from the tuple.
  172. *
  173. * @param i the index of the requested element. Tuple elements are
  174. * numbered as array elements, starting at 0.
  175. *
  176. * @return the requested element, of null if i is not a valid
  177. * element index.
  178. **/
  179. public virtual Object elementAt(int i)
  180. {
  181. if ((i >= arity()) || (i < 0))
  182. return null;
  183. return elems[i];
  184. }
  185. /*
  186. * Get all the elements from the tuple as an array.
  187. *
  188. * @return an array containing all of the tuple's elements.
  189. **/
  190. public virtual Object[] elements()
  191. {
  192. Object[] res = new Object[arity()];
  193. Array.Copy(this.elems, 0, res, 0, res.Length);
  194. return res;
  195. }
  196. public Object this[int index]
  197. {
  198. get { return this.elems[index]; }
  199. set { this.elems[index] = value; }
  200. }
  201. /*
  202. * Get the string representation of the tuple.
  203. *
  204. * @return the string representation of the tuple.
  205. **/
  206. public override System.String ToString()
  207. {
  208. int i;
  209. System.Text.StringBuilder s = new System.Text.StringBuilder();
  210. int arity = (int) (elems.Length);
  211. s.Append("{");
  212. for (i = 0; i < arity; i++)
  213. {
  214. if (i > 0)
  215. s.Append(",");
  216. s.Append(elems[i].ToString());
  217. }
  218. s.Append("}");
  219. return s.ToString();
  220. }
  221. /*
  222. * Convert this tuple to the equivalent Erlang external representation.
  223. *
  224. * @param buf an output stream to which the encoded tuple should be
  225. * written.
  226. **/
  227. public override void encode(OtpOutputStream buf)
  228. {
  229. int arity = (int) (elems.Length);
  230. buf.write_tuple_head(arity);
  231. for (int i = 0; i < arity; i++)
  232. {
  233. buf.write_any(elems[i]);
  234. }
  235. }
  236. /*
  237. * Determine if two tuples are equal. Tuples are equal if they have
  238. * the same arity and all of the elements are equal.
  239. *
  240. * @param o the tuple to compare to.
  241. *
  242. * @return true if the tuples have the same arity and all the
  243. * elements are equal.
  244. **/
  245. public override bool Equals(System.Object o)
  246. {
  247. if (!(o is Tuple))
  248. return false;
  249. Tuple t = (Tuple) o;
  250. int a = this.arity();
  251. if (a != t.arity())
  252. return false;
  253. for (int i = 0; i < a; i++)
  254. {
  255. if (!this.elems[i].Equals(t.elems[i]))
  256. return false;
  257. // early exit
  258. }
  259. return true;
  260. }
  261. public override int GetHashCode()
  262. {
  263. return 1;
  264. }
  265. public override System.Object clone()
  266. {
  267. Tuple newTuple = (Tuple) (base.clone());
  268. newTuple.elems = new Object[elems.Length];
  269. elems.CopyTo(newTuple.elems, 0);
  270. return newTuple;
  271. }
  272. public override bool subst(ref Object a_term, VarBind binding)
  273. {
  274. System.Collections.Generic.List<Erlang.Object> result =
  275. new System.Collections.Generic.List<Erlang.Object>();
  276. bool changed = false;
  277. foreach (Erlang.Object term in this.elems)
  278. {
  279. Erlang.Object obj = null;
  280. if (term.subst(ref obj, binding))
  281. result.Add(obj);
  282. else
  283. {
  284. changed = true;
  285. result.Add(term);
  286. }
  287. }
  288. if (!changed)
  289. return false;
  290. a_term = new Erlang.Tuple(result.ToArray());
  291. return true;
  292. }
  293. public override bool match(Erlang.Object pattern, VarBind binding)
  294. {
  295. if (pattern is Erlang.Var)
  296. pattern.match(this, binding);
  297. else if (!(pattern is Erlang.Tuple))
  298. return false;
  299. Erlang.Tuple tup = pattern as Erlang.Tuple;
  300. if (arity() != tup.arity())
  301. return false;
  302. for (int i = 0; i < arity(); ++i)
  303. if (!elems[i].match(tup[i], binding))
  304. return false;
  305. return true;
  306. }
  307. IEnumerator<Object> IEnumerable<Object>.GetEnumerator()
  308. {
  309. return ((IEnumerable<Object>)elems).GetEnumerator();
  310. }
  311. IEnumerator IEnumerable.GetEnumerator()
  312. {
  313. return elems.GetEnumerator();
  314. }
  315. }
  316. }