PageRenderTime 163ms CodeModel.GetById 40ms RepoModel.GetById 27ms app.codeStats 0ms

/DLR_Main/Languages/IronPython/Scripts/generate_set.py

https://bitbucket.org/mdavid/dlr
Python | 482 lines | 437 code | 31 blank | 14 comment | 6 complexity | 13e4d9a0e2066c4961a20148361a9525 MD5 | raw file
  1. #####################################################################################
  2. #
  3. # Copyright (c) Microsoft Corporation. All rights reserved.
  4. #
  5. # This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. # copy of the license can be found in the License.html file at the root of this distribution. If
  7. # you cannot locate the Apache License, Version 2.0, please send an email to
  8. # ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. # by the terms of the Apache License, Version 2.0.
  10. #
  11. # You must not remove this notice, or any other, from this software.
  12. #
  13. #
  14. #####################################################################################
  15. from generate import generate
  16. def get_type(mutable):
  17. if mutable:
  18. return 'SetCollection'
  19. else:
  20. return 'FrozenSetCollection'
  21. def get_arg_ts(mutable):
  22. return [get_type(mutable), get_type(not mutable), 'object']
  23. def get_clrname(name):
  24. return ''.join(map(str.capitalize, name.split('_')))
  25. def get_items(arg_t):
  26. if arg_t == 'object':
  27. return 'SetStorage.GetItems(set)'
  28. else:
  29. return 'set._items'
  30. def copy(cw, mutable):
  31. if mutable:
  32. cw.writeline('return copy();')
  33. else:
  34. cw.writeline('return Make(_items);')
  35. def copy_op(cw, mutable, name):
  36. t = get_type(mutable)
  37. cw.enter_block('public %s %s()' % (t, name))
  38. copy(cw, mutable)
  39. cw.exit_block()
  40. cw.writeline()
  41. def simple_op(cw, t, arg_t, name):
  42. clrname = get_clrname(name)
  43. cw.enter_block('public %s %s(%s set)' % (t, name, arg_t))
  44. simple_op_worker(cw, t, arg_t, name)
  45. cw.exit_block()
  46. cw.writeline()
  47. def simple_op_worker(cw, t, arg_t, name):
  48. clrname = get_clrname(name)
  49. if arg_t == 'object':
  50. cw.writeline('SetStorage items;')
  51. cw.enter_block('if (SetStorage.GetItems(set, out items))')
  52. cw.writeline('items = SetStorage.%s(_items, items);' % clrname)
  53. cw.else_block()
  54. cw.writeline('items.%sUpdate(_items);' % clrname)
  55. cw.exit_block()
  56. cw.writeline('return Make(items);')
  57. else:
  58. cw.writeline(
  59. 'return Make(SetStorage.%s(_items, set._items));' % clrname
  60. )
  61. def enter_multiarg_op(cw, t, name):
  62. cw.enter_block('public %s %s([NotNull]params object[]/*!*/ sets)' % (t, name))
  63. cw.writeline('Debug.Assert(sets != null);')
  64. cw.writeline()
  65. def union_multiarg(cw, mutable):
  66. t = get_type(mutable)
  67. enter_multiarg_op(cw, t, 'union')
  68. cw.writeline('SetStorage res = _items.Clone();')
  69. cw.enter_block('foreach (object set in sets)')
  70. cw.writeline('res.UnionUpdate(SetStorage.GetItems(set));')
  71. cw.exit_block()
  72. cw.writeline()
  73. cw.writeline('return Make(res);')
  74. cw.exit_block()
  75. cw.writeline()
  76. def intersection_multiarg(cw, mutable):
  77. t = get_type(mutable)
  78. enter_multiarg_op(cw, t, 'intersection')
  79. cw.enter_block('if (sets.Length == 0)')
  80. copy(cw, mutable)
  81. cw.exit_block()
  82. cw.writeline()
  83. cw.writeline('SetStorage res = _items;')
  84. cw.enter_block('foreach (object set in sets)')
  85. cw.writeline('SetStorage items, x = res, y;')
  86. cw.enter_block('if (SetStorage.GetItems(set, out items))')
  87. cw.writeline('y = items;')
  88. cw.writeline('SetStorage.SortBySize(ref x, ref y);')
  89. cw.writeline()
  90. cw.enter_block('if (%s(x, items) || %s(x, _items))' %
  91. (('object.ReferenceEquals',) * 2))
  92. cw.writeline('x = x.Clone();')
  93. cw.exit_block()
  94. cw.else_block()
  95. cw.writeline('y = items;')
  96. cw.writeline('SetStorage.SortBySize(ref x, ref y);')
  97. cw.writeline()
  98. cw.enter_block('if (object.ReferenceEquals(x, _items))')
  99. cw.writeline('x = x.Clone();')
  100. cw.exit_block()
  101. cw.exit_block()
  102. cw.writeline('x.IntersectionUpdate(y);')
  103. cw.writeline('res = x;')
  104. cw.exit_block()
  105. cw.writeline()
  106. cw.writeline('Debug.Assert(!object.ReferenceEquals(res, _items));')
  107. cw.writeline('return Make(res);')
  108. cw.exit_block()
  109. cw.writeline()
  110. def difference(cw, t, arg_t):
  111. items = get_items(arg_t)
  112. cw.enter_block('public %s difference(%s set)' % (t, arg_t))
  113. if (t == arg_t):
  114. cw.enter_block('if (object.ReferenceEquals(set, this))')
  115. cw.writeline('return Empty;')
  116. cw.exit_block()
  117. cw.writeline()
  118. cw.writeline('return Make(')
  119. cw.indent()
  120. cw.writeline('SetStorage.Difference(_items, %s)' % items)
  121. cw.dedent()
  122. cw.writeline(');');
  123. cw.exit_block()
  124. cw.writeline()
  125. def difference_multiarg(cw, mutable):
  126. t = get_type(mutable)
  127. enter_multiarg_op(cw, t, 'difference')
  128. cw.enter_block('if (sets.Length == 0)')
  129. copy(cw, mutable)
  130. cw.exit_block()
  131. cw.writeline()
  132. cw.writeline('SetStorage res = _items;')
  133. cw.enter_block('foreach (object set in sets)')
  134. cw.enter_block('if (object.ReferenceEquals(set, this))')
  135. cw.writeline('return Empty;')
  136. cw.exit_block()
  137. cw.writeline()
  138. cw.writeline('SetStorage items = SetStorage.GetItems(set);')
  139. cw.enter_block('if (object.ReferenceEquals(res, _items))')
  140. cw.writeline('res = SetStorage.Difference(_items, items);')
  141. cw.else_block()
  142. cw.writeline('res.DifferenceUpdate(items);')
  143. cw.exit_block()
  144. cw.exit_block()
  145. cw.writeline()
  146. cw.writeline('Debug.Assert(!object.ReferenceEquals(res, _items));')
  147. cw.writeline('return Make(res);')
  148. cw.exit_block()
  149. cw.writeline()
  150. def symmetric_difference(cw, t, arg_t):
  151. cw.enter_block('public %s symmetric_difference(%s set)' % (t, arg_t))
  152. if (t == arg_t):
  153. cw.enter_block('if (object.ReferenceEquals(set, this))')
  154. cw.writeline('return Empty;')
  155. cw.exit_block()
  156. cw.writeline()
  157. simple_op_worker(cw, t, arg_t, 'symmetric_difference')
  158. cw.exit_block()
  159. cw.writeline()
  160. def gen_setops(mutable):
  161. def _gen_setops(cw):
  162. t = get_type(mutable)
  163. arg_ts = get_arg_ts(mutable)
  164. for arg_t in arg_ts:
  165. items = get_items(arg_t)
  166. cw.enter_block('public bool isdisjoint(%s set)' % arg_t)
  167. cw.writeline('return _items.IsDisjoint(%s);' % items)
  168. cw.exit_block()
  169. cw.writeline()
  170. for arg_t in arg_ts:
  171. items = get_items(arg_t)
  172. cw.enter_block('public bool issubset(%s set)' % arg_t)
  173. cw.writeline('return _items.IsSubset(%s);' % items)
  174. cw.exit_block()
  175. cw.writeline()
  176. for arg_t in arg_ts:
  177. items = get_items(arg_t)
  178. cw.enter_block('public bool issuperset(%s set)' % arg_t)
  179. cw.writeline('return %s.IsSubset(_items);' % items)
  180. cw.exit_block()
  181. cw.writeline()
  182. copy_op(cw, mutable, 'union')
  183. for arg_t in arg_ts:
  184. simple_op(cw, t, arg_t, 'union')
  185. union_multiarg(cw, mutable)
  186. copy_op(cw, mutable, 'intersection')
  187. for arg_t in arg_ts:
  188. simple_op(cw, t, arg_t, 'intersection')
  189. intersection_multiarg(cw, mutable)
  190. copy_op(cw, mutable, 'difference')
  191. for arg_t in arg_ts:
  192. difference(cw, t, arg_t)
  193. difference_multiarg(cw, mutable)
  194. for arg_t in arg_ts:
  195. symmetric_difference(cw, t, arg_t)
  196. return _gen_setops
  197. op_symbols = [ '|', '&', '^', '-' ]
  198. op_names = [ 'union', 'intersection', 'symmetric_difference', 'difference' ]
  199. op_upnames = [ 'update' ] + map(lambda x: x + '_update', op_names[1:])
  200. op_clrnames = [ 'BitwiseOr', 'BitwiseAnd', 'ExclusiveOr', 'Subtract' ]
  201. def gen_op(cw, t_left, t_right, symbol, name):
  202. cw.enter_block(
  203. 'public static %s operator %s(%s x, %s y)' %
  204. (t_left, symbol, t_left, t_right)
  205. )
  206. cw.writeline('return x.%s(y);' % name)
  207. cw.exit_block()
  208. cw.writeline()
  209. def gen_ops(mutable):
  210. def _gen_ops(cw):
  211. t = get_type(mutable)
  212. u = get_type(not mutable)
  213. ops = zip(op_symbols, op_names)
  214. for symbol, name in ops:
  215. gen_op(cw, t, t, symbol, name)
  216. for symbol, name in ops:
  217. gen_op(cw, t, u, symbol, name)
  218. return _gen_ops
  219. def gen_mutating_op(cw, t, arg_t, symbol, upname, clrname):
  220. cw.writeline('[SpecialName]')
  221. cw.enter_block('public %s InPlace%s(%s set)' % (t, clrname, arg_t))
  222. if arg_t == 'object':
  223. cw.enter_block(
  224. 'if (set is %s || set is %s)' %
  225. tuple(map(get_type, [False, True]))
  226. )
  227. cw.writeline('%s(set);' % upname)
  228. cw.writeline('return this;')
  229. if arg_t == 'object':
  230. cw.exit_block()
  231. cw.writeline()
  232. cw.writeline('throw PythonOps.TypeError(')
  233. cw.indent()
  234. cw.writeline(
  235. '''"unsupported operand type(s) for %s=: '{0}' and '{1}'",''' %
  236. symbol
  237. )
  238. cw.writeline('%s(this), %s(set)' % (('PythonTypeOps.GetName',) * 2))
  239. cw.dedent()
  240. cw.writeline(');')
  241. cw.exit_block()
  242. cw.writeline()
  243. def gen_mutating_ops(cw):
  244. t = get_type(True)
  245. arg_ts = get_arg_ts(True)
  246. for op in zip(op_symbols, op_upnames, op_clrnames):
  247. for arg_t in arg_ts:
  248. gen_mutating_op(cw, t, arg_t, *op)
  249. compares = [ '>', '<', '>=', '<=' ]
  250. def is_subset(compare):
  251. return compare == '<' or compare == '<='
  252. def is_strict(compare):
  253. return not compare.endswith('=')
  254. def gen_comparison(cw, t, compare):
  255. cw.enter_block(
  256. 'public static bool operator %s(%s self, object other)' %
  257. (compare, t)
  258. )
  259. cw.writeline('SetStorage items;')
  260. cw.enter_block('if (SetStorage.GetItemsIfSet(other, out items))')
  261. if is_subset(compare):
  262. left = 'self._items'
  263. right = 'items'
  264. else:
  265. left = 'items'
  266. right = 'self._items'
  267. if is_strict(compare):
  268. func = 'IsStrictSubset'
  269. else:
  270. func = 'IsSubset'
  271. cw.writeline('return %s.%s(%s);' % (left, func, right))
  272. cw.exit_block()
  273. cw.writeline()
  274. cw.writeline('throw PythonOps.TypeError("can only compare to a set");')
  275. cw.exit_block()
  276. cw.writeline()
  277. def suppress(cw, *msgs):
  278. if len(msgs) == 0:
  279. return
  280. comma = ''
  281. res = '['
  282. for msg in msgs:
  283. res += comma + 'System.Diagnostics.CodeAnalysis.SuppressMessage('
  284. res += msg + ')'
  285. comma = ' ,'
  286. res += ']'
  287. cw.writeline(res)
  288. def gen_comparisons(cw, t):
  289. cw.writeline('#region IRichComparable')
  290. cw.writeline()
  291. for compare in compares:
  292. gen_comparison(cw, t, compare)
  293. ca1822 = '"Microsoft.Performance", "CA1822:MarkMembersAsStatic"'
  294. ca1801 = '"Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "o"'
  295. throw_msg = 'throw PythonOps.TypeError("cannot compare sets using cmp()");'
  296. suppress(cw, ca1822, ca1801)
  297. cw.writeline('[SpecialName]')
  298. cw.enter_block('public int Compare(object o)')
  299. cw.writeline(throw_msg)
  300. cw.exit_block()
  301. cw.writeline()
  302. suppress(cw, ca1822, ca1801)
  303. cw.enter_block('public int __cmp__(object o)')
  304. cw.writeline(throw_msg)
  305. cw.exit_block()
  306. cw.writeline()
  307. cw.writeline('#endregion')
  308. cw.writeline()
  309. def gen_ienumerable(cw, mutable):
  310. cw.writeline('#region IEnumerable Members')
  311. cw.writeline()
  312. cw.enter_block('IEnumerator IEnumerable.GetEnumerator()')
  313. cw.writeline('return new SetIterator(_items, %s);' % str(mutable).lower())
  314. cw.exit_block()
  315. cw.writeline()
  316. cw.writeline('#endregion')
  317. cw.writeline()
  318. cw.writeline('#region IEnumerable<object> Members')
  319. cw.writeline()
  320. cw.enter_block('IEnumerator<object> IEnumerable<object>.GetEnumerator()')
  321. cw.writeline('return new SetIterator(_items, %s);' % str(mutable).lower())
  322. cw.exit_block()
  323. cw.writeline()
  324. cw.writeline('#endregion')
  325. cw.writeline()
  326. def gen_icodeformattable(cw):
  327. cw.writeline('#region ICodeFormattable Members')
  328. cw.writeline()
  329. cw.enter_block('public virtual string/*!*/ __repr__(CodeContext/*!*/ context)')
  330. cw.writeline('return SetStorage.SetToString(context, this, _items);')
  331. cw.exit_block()
  332. cw.writeline()
  333. cw.writeline('#endregion')
  334. cw.writeline()
  335. def gen_icollection(cw):
  336. cw.writeline('#region ICollection Members')
  337. cw.writeline()
  338. cw.enter_block('void ICollection.CopyTo(Array array, int index)')
  339. cw.writeline('int i = 0;')
  340. cw.enter_block('foreach (object o in this)')
  341. cw.writeline('array.SetValue(o, index + i++);')
  342. cw.exit_block()
  343. cw.exit_block()
  344. cw.writeline()
  345. cw.enter_block('public int Count')
  346. cw.writeline('[PythonHidden]')
  347. cw.writeline('get { return _items.Count; }')
  348. cw.exit_block()
  349. cw.writeline()
  350. cw.enter_block('bool ICollection.IsSynchronized')
  351. cw.writeline('get { return false; }')
  352. cw.exit_block()
  353. cw.writeline()
  354. cw.enter_block('object ICollection.SyncRoot')
  355. cw.writeline('get { return this; }')
  356. cw.exit_block()
  357. cw.writeline()
  358. cw.writeline('#endregion')
  359. cw.writeline()
  360. def gen_interfaces(mutable):
  361. def _gen_interfaces(cw):
  362. t = get_type(mutable)
  363. gen_comparisons(cw, t)
  364. gen_ienumerable(cw, mutable)
  365. gen_icodeformattable(cw)
  366. gen_icollection(cw)
  367. return _gen_interfaces
  368. def main():
  369. generators = [
  370. ('NonOperator Operations', gen_setops),
  371. ('Operators', gen_ops),
  372. ('Interface Implementations', gen_interfaces),
  373. ]
  374. mutable_generators = [
  375. ('Mutating Operators', gen_mutating_ops),
  376. ]
  377. _generators = []
  378. for title, func in generators:
  379. for bit in [True, False]:
  380. _generators.append((
  381. title + ' (' + get_type(bit) + ')',
  382. func(bit)
  383. ))
  384. _generators.extend(mutable_generators)
  385. return generate(*_generators)
  386. if __name__ == '__main__':
  387. main()