PageRenderTime 55ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/Backend/Runtime/ArrayOps.cs

https://bitbucket.org/AdamMil/boaold
C# | 176 lines | 161 code | 15 blank | 0 comment | 41 complexity | 6e76c61da79aa3d790c6d9462e61f1b6 MD5 | raw file
Possible License(s): GPL-2.0
  1. using System;
  2. using System.Collections;
  3. using System.Globalization;
  4. namespace Boa.Runtime
  5. {
  6. public sealed class ArrayOps
  7. { ArrayOps() { }
  8. public static int Compare(object a, object b)
  9. { if(b==null) return 1;
  10. Array aa, ab, ret=null;
  11. if(a is Tuple)
  12. { Tuple ta = (Tuple)a, tb = b as Tuple;
  13. if(tb==null) goto badTypes;
  14. aa = ta.items;
  15. ab = tb.items;
  16. }
  17. else if(a is Array)
  18. { if(a.GetType()!=b.GetType()) goto badTypes;
  19. aa = (Array)a;
  20. ab = (Array)b;
  21. ret = Array.CreateInstance(aa.GetType().GetElementType(), aa.Length+ab.Length);
  22. }
  23. else
  24. { aa = ToArray(a);
  25. ab = ToArray(b);
  26. }
  27. if(ret==null) ret = new object[aa.Length+ab.Length];
  28. IList A=aa, B=ab;
  29. int len = Math.Min(aa.Length, ab.Length);
  30. for(int i=0; i<len; i++)
  31. { int c = Ops.Compare(A[i], B[i]);
  32. if(c!=0) return c;
  33. }
  34. return aa.Length==ab.Length ? 0 : aa.Length<ab.Length ? -1 : 1;
  35. badTypes:
  36. throw Ops.TypeError("invalid operand types for sequence comparison: '{0}' and '{1}'",
  37. Ops.TypeName(a), Ops.TypeName(b));
  38. }
  39. public static int Compare(object[] arr1, int len1, object[] arr2, int len2)
  40. { int len = Math.Min(len1, len2);
  41. for(int i=0; i<len; i++)
  42. { int c = Ops.Compare(arr1[i], arr2[i]);
  43. if(c!=0) return c;
  44. }
  45. return len1==len2 ? 0 : len1<len2 ? -1 : 1;
  46. }
  47. public static object Concat(object a, object b)
  48. { Array aa, ab, ret=null;
  49. if(a is Tuple)
  50. { Tuple ta = (Tuple)a, tb = b as Tuple;
  51. if(tb==null) goto badTypes;
  52. aa = ta.items;
  53. ab = tb.items;
  54. }
  55. else if(a is Array)
  56. { if(a.GetType()!=b.GetType()) goto badTypes;
  57. aa = (Array)a;
  58. ab = (Array)b;
  59. ret = Array.CreateInstance(aa.GetType().GetElementType(), aa.Length+ab.Length);
  60. }
  61. else
  62. { aa = ToArray(a);
  63. ab = ToArray(b);
  64. }
  65. if(ret==null) ret = new object[aa.Length+ab.Length];
  66. aa.CopyTo(ret, 0);
  67. ab.CopyTo(ret, aa.Length);
  68. return a is Tuple ? new Tuple((object[])ret) : a is Array ? ret : (object)new List((object[])ret, ret.Length);
  69. badTypes:
  70. throw Ops.TypeError("invalid operand types for sequence concatenation: '{0}' and '{1}'",
  71. Ops.TypeName(a), Ops.TypeName(b));
  72. }
  73. public static object Multiply(object a, object b)
  74. { int bv;
  75. if(b is int) bv = (int)b;
  76. else switch(Convert.GetTypeCode(b))
  77. { case TypeCode.Boolean: if((bool)b) return a; else bv=0; break;
  78. case TypeCode.Byte: bv = (byte)b; break;
  79. case TypeCode.Int16: bv = (short)b; break;
  80. case TypeCode.Int32: bv = (int)b; break;
  81. case TypeCode.Int64:
  82. { long lv = (long)b;
  83. if(lv>int.MaxValue || lv<int.MinValue) throw Ops.OverflowError("long int too large to convert to int");
  84. bv = (int)lv;
  85. break;
  86. }
  87. case TypeCode.Object:
  88. { if(b is Integer) bv = ((Integer)b).ToInt32();
  89. IConvertible ic = b as IConvertible;
  90. if(ic==null) return Ops.Invoke(b, "__rmul__", a);
  91. bv = ic.ToInt32(NumberFormatInfo.InvariantInfo);
  92. break;
  93. }
  94. case TypeCode.SByte: bv = (sbyte)b; break;
  95. case TypeCode.UInt16: bv = (ushort)b; break;
  96. case TypeCode.UInt32:
  97. { uint ui = (uint)b;
  98. if(ui>int.MaxValue) throw Ops.OverflowError("long int too large to convert to int");
  99. bv = (int)ui;
  100. break;
  101. }
  102. case TypeCode.UInt64:
  103. { ulong ul = (uint)b;
  104. if(ul>int.MaxValue) throw Ops.OverflowError("long int too large to convert to int");
  105. bv = (int)ul;
  106. break;
  107. }
  108. default: throw Ops.TypeError("invalid operand types for sequence multiplication: '{0}' and '{1}'",
  109. Ops.TypeName(a), Ops.TypeName(b));
  110. }
  111. if(bv<0) throw Ops.ValueError("multiplier for sequence multiplication cannot be negative");
  112. if(bv==1) return a;
  113. Array source, dest;
  114. if(a is Array)
  115. { source = (Array)a;
  116. dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length*bv);
  117. }
  118. else
  119. { source = ToArray(a);
  120. dest = new object[source.Length*bv];
  121. }
  122. int ai = source.Length, bvb=bv, mask=0;
  123. Array.Copy(source, dest, ai);
  124. while((bv>>=1) != 0) { Array.Copy(dest, 0, dest, ai, ai); ai += ai; mask=mask<<1 | 1; }
  125. bv = bvb&mask;
  126. if(bv>0) Array.Copy(dest, 0, dest, ai, (bvb&mask)*source.Length);
  127. return a is Tuple ? new Tuple((object[])dest) : a is Array ? dest : (object)new List((object[])dest, dest.Length);
  128. }
  129. public static string Repr(Array arr)
  130. { System.Text.StringBuilder sb = new System.Text.StringBuilder();
  131. sb.Append(arr.GetType().FullName);
  132. sb.Append('(');
  133. for(int i=0; i<arr.Length; i++)
  134. { if(i>0) sb.Append(", ");
  135. sb.Append(Ops.Repr(arr.GetValue(i)));
  136. }
  137. sb.Append(')');
  138. return sb.ToString();
  139. }
  140. public static object[] ToArray(object o)
  141. { object[] ret;
  142. if(o is Tuple) ret = ((Tuple)o).items;
  143. else if(o is ICollection)
  144. { ICollection ic = (ICollection)o;
  145. ret = new object[ic.Count];
  146. ic.CopyTo(ret, 0);
  147. }
  148. else if(o is ISequence)
  149. { ISequence s = (ISequence)o;
  150. ret = new object[s.__len__()];
  151. for(int i=0; i<ret.Length; i++) ret[i] = s.__getitem__(i);
  152. }
  153. else
  154. { ret = new object[Ops.ToInt(Ops.Invoke(o, "__len__"))];
  155. object getitem = Ops.GetAttr(o, "__getitem__");
  156. for(int i=0; i<ret.Length; i++) ret[i] = Ops.Call(getitem, i);
  157. }
  158. return ret;
  159. }
  160. }
  161. } // namespace Boa.Runtime