nimsets.nim 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # this unit handles Nim sets; it implements symbolic sets
  10. import
  11. ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
  12. proc toBitSet*(s: PNode, b: var TBitSet)
  13. # this function is used for case statement checking:
  14. proc overlap*(a, b: PNode): bool
  15. proc inSet*(s: PNode, elem: PNode): bool
  16. proc someInSet*(s: PNode, a, b: PNode): bool
  17. proc emptyRange*(a, b: PNode): bool
  18. proc setHasRange*(s: PNode): bool
  19. # returns true if set contains a range (needed by the code generator)
  20. # these are used for constant folding:
  21. proc unionSets*(a, b: PNode): PNode
  22. proc diffSets*(a, b: PNode): PNode
  23. proc intersectSets*(a, b: PNode): PNode
  24. proc symdiffSets*(a, b: PNode): PNode
  25. proc containsSets*(a, b: PNode): bool
  26. proc equalSets*(a, b: PNode): bool
  27. proc cardSet*(s: PNode): BiggestInt
  28. # implementation
  29. proc inSet(s: PNode, elem: PNode): bool =
  30. if s.kind != nkCurly:
  31. internalError(s.info, "inSet")
  32. return false
  33. for i in countup(0, sonsLen(s) - 1):
  34. if s.sons[i].kind == nkRange:
  35. if leValue(s.sons[i].sons[0], elem) and
  36. leValue(elem, s.sons[i].sons[1]):
  37. return true
  38. else:
  39. if sameValue(s.sons[i], elem):
  40. return true
  41. result = false
  42. proc overlap(a, b: PNode): bool =
  43. if a.kind == nkRange:
  44. if b.kind == nkRange:
  45. # X..Y and C..D overlap iff (X <= D and C <= Y)
  46. result = leValue(a.sons[0], b.sons[1]) and
  47. leValue(b.sons[0], a.sons[1])
  48. else:
  49. result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
  50. else:
  51. if b.kind == nkRange:
  52. result = leValue(b.sons[0], a) and leValue(a, b.sons[1])
  53. else:
  54. result = sameValue(a, b)
  55. proc someInSet(s: PNode, a, b: PNode): bool =
  56. # checks if some element of a..b is in the set s
  57. if s.kind != nkCurly:
  58. internalError(s.info, "SomeInSet")
  59. return false
  60. for i in countup(0, sonsLen(s) - 1):
  61. if s.sons[i].kind == nkRange:
  62. if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
  63. leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
  64. return true
  65. else:
  66. # a <= elem <= b
  67. if leValue(a, s.sons[i]) and leValue(s.sons[i], b):
  68. return true
  69. result = false
  70. proc toBitSet(s: PNode, b: var TBitSet) =
  71. var first, j: BiggestInt
  72. first = firstOrd(s.typ.sons[0])
  73. bitSetInit(b, int(getSize(s.typ)))
  74. for i in countup(0, sonsLen(s) - 1):
  75. if s.sons[i].kind == nkRange:
  76. j = getOrdValue(s.sons[i].sons[0])
  77. while j <= getOrdValue(s.sons[i].sons[1]):
  78. bitSetIncl(b, j - first)
  79. inc(j)
  80. else:
  81. bitSetIncl(b, getOrdValue(s.sons[i]) - first)
  82. proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
  83. var
  84. a, b, e, first: BiggestInt # a, b are interval borders
  85. elemType: PType
  86. n: PNode
  87. elemType = settype.sons[0]
  88. first = firstOrd(elemType)
  89. result = newNodeI(nkCurly, info)
  90. result.typ = settype
  91. result.info = info
  92. e = 0
  93. while e < len(s) * ElemSize:
  94. if bitSetIn(s, e):
  95. a = e
  96. b = e
  97. while true:
  98. inc(b)
  99. if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
  100. dec(b)
  101. let aa = newIntTypeNode(nkIntLit, a + first, elemType)
  102. aa.info = info
  103. if a == b:
  104. addSon(result, aa)
  105. else:
  106. n = newNodeI(nkRange, info)
  107. n.typ = elemType
  108. addSon(n, aa)
  109. let bb = newIntTypeNode(nkIntLit, b + first, elemType)
  110. bb.info = info
  111. addSon(n, bb)
  112. addSon(result, n)
  113. e = b
  114. inc(e)
  115. template nodeSetOp(a, b: PNode, op: untyped) {.dirty.} =
  116. var x, y: TBitSet
  117. toBitSet(a, x)
  118. toBitSet(b, y)
  119. op(x, y)
  120. result = toTreeSet(x, a.typ, a.info)
  121. proc unionSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
  122. proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
  123. proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
  124. proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
  125. proc containsSets(a, b: PNode): bool =
  126. var x, y: TBitSet
  127. toBitSet(a, x)
  128. toBitSet(b, y)
  129. result = bitSetContains(x, y)
  130. proc equalSets(a, b: PNode): bool =
  131. var x, y: TBitSet
  132. toBitSet(a, x)
  133. toBitSet(b, y)
  134. result = bitSetEquals(x, y)
  135. proc complement*(a: PNode): PNode =
  136. var x: TBitSet
  137. toBitSet(a, x)
  138. for i in countup(0, high(x)): x[i] = not x[i]
  139. result = toTreeSet(x, a.typ, a.info)
  140. proc cardSet(s: PNode): BiggestInt =
  141. # here we can do better than converting it into a compact set
  142. # we just count the elements directly
  143. result = 0
  144. for i in countup(0, sonsLen(s) - 1):
  145. if s.sons[i].kind == nkRange:
  146. result = result + getOrdValue(s.sons[i].sons[1]) -
  147. getOrdValue(s.sons[i].sons[0]) + 1
  148. else:
  149. inc(result)
  150. proc setHasRange(s: PNode): bool =
  151. if s.kind != nkCurly:
  152. internalError(s.info, "SetHasRange")
  153. return false
  154. for i in countup(0, sonsLen(s) - 1):
  155. if s.sons[i].kind == nkRange:
  156. return true
  157. result = false
  158. proc emptyRange(a, b: PNode): bool =
  159. result = not leValue(a, b) # a > b iff not (a <= b)