toptions.nim 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. discard """
  2. matrix: "--mm:refc; --mm:orc"
  3. targets: "c js"
  4. """
  5. import std/[json, options]
  6. import std/assertions
  7. import std/objectdollar
  8. # RefPerson is used to test that overloaded `==` operator is not called by
  9. # options. It is defined here in the global scope, because otherwise the test
  10. # will not even consider the `==` operator. Different bug?
  11. type RefPerson = ref object
  12. name: string
  13. proc `==`(a, b: RefPerson): bool =
  14. assert(not a.isNil and not b.isNil)
  15. a.name == b.name
  16. template disableJsVm(body) =
  17. # something doesn't work in JS VM
  18. when defined(js):
  19. when nimvm: discard
  20. else: body
  21. else:
  22. body
  23. proc main() =
  24. type
  25. Foo = ref object
  26. test: string
  27. Test = object
  28. foo: Option[Foo]
  29. let js = """{"foo": {"test": "123"}}"""
  30. let parsed = parseJson(js)
  31. let a = parsed.to(Test)
  32. doAssert $(%*a) == """{"foo":{"test":"123"}}"""
  33. block options:
  34. # work around a bug in unittest
  35. let intNone = none(int)
  36. let stringNone = none(string)
  37. block example:
  38. proc find(haystack: string, needle: char): Option[int] =
  39. for i, c in haystack:
  40. if c == needle:
  41. return some i
  42. doAssert("abc".find('c').get() == 2)
  43. let result = "team".find('i')
  44. doAssert result == intNone
  45. doAssert result.isNone
  46. block some:
  47. doAssert some(6).get() == 6
  48. doAssert some("a").unsafeGet() == "a"
  49. doAssert some(6).isSome
  50. doAssert some("a").isSome
  51. block none:
  52. doAssertRaises UnpackDefect:
  53. discard none(int).get()
  54. doAssert(none(int).isNone)
  55. doAssert(not none(string).isSome)
  56. block equality:
  57. doAssert some("a") == some("a")
  58. doAssert some(7) != some(6)
  59. doAssert some("a") != stringNone
  60. doAssert intNone == intNone
  61. when compiles(some("a") == some(5)):
  62. doAssert false
  63. when compiles(none(string) == none(int)):
  64. doAssert false
  65. block get_with_a_default_value:
  66. doAssert(some("Correct").get("Wrong") == "Correct")
  67. doAssert(stringNone.get("Correct") == "Correct")
  68. block stringify:
  69. doAssert($(some("Correct")) == "some(\"Correct\")")
  70. doAssert($(stringNone) == "none(string)")
  71. disableJsVm:
  72. block map_with_a_void_result:
  73. var procRan = 0
  74. # TODO closure anonymous functions doesn't work in VM with JS
  75. # Error: cannot evaluate at compile time: procRan
  76. some(123).map(proc (v: int) = procRan = v)
  77. doAssert procRan == 123
  78. intNone.map(proc (v: int) = doAssert false)
  79. block map:
  80. doAssert(some(123).map(proc (v: int): int = v * 2) == some(246))
  81. doAssert(intNone.map(proc (v: int): int = v * 2).isNone)
  82. block filter:
  83. doAssert(some(123).filter(proc (v: int): bool = v == 123) == some(123))
  84. doAssert(some(456).filter(proc (v: int): bool = v == 123).isNone)
  85. doAssert(intNone.filter(proc (v: int): bool = doAssert false).isNone)
  86. block flatMap:
  87. proc addOneIfNotZero(v: int): Option[int] =
  88. if v != 0:
  89. result = some(v + 1)
  90. else:
  91. result = none(int)
  92. doAssert(some(1).flatMap(addOneIfNotZero) == some(2))
  93. doAssert(some(0).flatMap(addOneIfNotZero) == none(int))
  94. doAssert(some(1).flatMap(addOneIfNotZero).flatMap(addOneIfNotZero) == some(3))
  95. proc maybeToString(v: int): Option[string] =
  96. if v != 0:
  97. result = some($v)
  98. else:
  99. result = none(string)
  100. doAssert(some(1).flatMap(maybeToString) == some("1"))
  101. proc maybeExclaim(v: string): Option[string] =
  102. if v != "":
  103. result = some v & "!"
  104. else:
  105. result = none(string)
  106. doAssert(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
  107. doAssert(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
  108. block SomePointer:
  109. var intref: ref int
  110. doAssert(option(intref).isNone)
  111. intref.new
  112. doAssert(option(intref).isSome)
  113. let tmp = option(intref)
  114. doAssert(sizeof(tmp) == sizeof(ptr int))
  115. var prc = proc (x: int): int = x + 1
  116. doAssert(option(prc).isSome)
  117. prc = nil
  118. doAssert(option(prc).isNone)
  119. block:
  120. doAssert(none[int]().isNone)
  121. doAssert(none(int) == none[int]())
  122. # "$ on typed with .name"
  123. block:
  124. type Named = object
  125. name: string
  126. let nobody = none(Named)
  127. doAssert($nobody == "none(Named)")
  128. # "$ on type with name()"
  129. block:
  130. type Person = object
  131. myname: string
  132. let noperson = none(Person)
  133. doAssert($noperson == "none(Person)")
  134. # "Ref type with overloaded `==`"
  135. block:
  136. let p = some(RefPerson.new())
  137. doAssert p.isSome
  138. block: # test cstring
  139. block:
  140. let x = some("".cstring)
  141. doAssert x.isSome
  142. doAssert x.get == ""
  143. block:
  144. let x = some("12345".cstring)
  145. doAssert x.isSome
  146. doAssert x.get == "12345"
  147. block:
  148. let x = "12345".cstring
  149. let y = some(x)
  150. doAssert y.isSome
  151. doAssert y.get == "12345"
  152. block:
  153. let x = none(cstring)
  154. doAssert x.isNone
  155. doAssert $x == "none(cstring)"
  156. static: main()
  157. main()
  158. when not defined(js):
  159. block: # bug #22932
  160. var it = iterator: int {.closure.} = discard
  161. doAssert it.option.isSome # Passes.
  162. it = nil
  163. doAssert it.option.isNone # Passes.