toptions.nim 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. result = none(int)
  40. for i, c in haystack:
  41. if c == needle:
  42. return some i
  43. doAssert("abc".find('c').get() == 2)
  44. let result = "team".find('i')
  45. doAssert result == intNone
  46. doAssert result.isNone
  47. block some:
  48. doAssert some(6).get() == 6
  49. doAssert some("a").unsafeGet() == "a"
  50. doAssert some(6).isSome
  51. doAssert some("a").isSome
  52. block none:
  53. doAssertRaises UnpackDefect:
  54. discard none(int).get()
  55. doAssert(none(int).isNone)
  56. doAssert(not none(string).isSome)
  57. block equality:
  58. doAssert some("a") == some("a")
  59. doAssert some(7) != some(6)
  60. doAssert some("a") != stringNone
  61. doAssert intNone == intNone
  62. when compiles(some("a") == some(5)):
  63. doAssert false
  64. when compiles(none(string) == none(int)):
  65. doAssert false
  66. block get_with_a_default_value:
  67. doAssert(some("Correct").get("Wrong") == "Correct")
  68. doAssert(stringNone.get("Correct") == "Correct")
  69. block stringify:
  70. doAssert($(some("Correct")) == "some(\"Correct\")")
  71. doAssert($(stringNone) == "none(string)")
  72. disableJsVm:
  73. block map_with_a_void_result:
  74. var procRan = 0
  75. # TODO closure anonymous functions doesn't work in VM with JS
  76. # Error: cannot evaluate at compile time: procRan
  77. some(123).map(proc (v: int) = procRan = v)
  78. doAssert procRan == 123
  79. intNone.map(proc (v: int) = doAssert false)
  80. block map:
  81. doAssert(some(123).map(proc (v: int): int = v * 2) == some(246))
  82. doAssert(intNone.map(proc (v: int): int = v * 2).isNone)
  83. block filter:
  84. doAssert(some(123).filter(proc (v: int): bool = v == 123) == some(123))
  85. doAssert(some(456).filter(proc (v: int): bool = v == 123).isNone)
  86. doAssert(intNone.filter(proc (v: int): bool = raiseAssert "false").isNone)
  87. block flatMap:
  88. proc addOneIfNotZero(v: int): Option[int] =
  89. if v != 0:
  90. result = some(v + 1)
  91. else:
  92. result = none(int)
  93. doAssert(some(1).flatMap(addOneIfNotZero) == some(2))
  94. doAssert(some(0).flatMap(addOneIfNotZero) == none(int))
  95. doAssert(some(1).flatMap(addOneIfNotZero).flatMap(addOneIfNotZero) == some(3))
  96. proc maybeToString(v: int): Option[string] =
  97. if v != 0:
  98. result = some($v)
  99. else:
  100. result = none(string)
  101. doAssert(some(1).flatMap(maybeToString) == some("1"))
  102. proc maybeExclaim(v: string): Option[string] =
  103. if v != "":
  104. result = some v & "!"
  105. else:
  106. result = none(string)
  107. doAssert(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
  108. doAssert(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
  109. block SomePointer:
  110. var intref: ref int = nil
  111. doAssert(option(intref).isNone)
  112. intref.new
  113. doAssert(option(intref).isSome)
  114. let tmp = option(intref)
  115. doAssert(sizeof(tmp) == sizeof(ptr int))
  116. var prc = proc (x: int): int = x + 1
  117. doAssert(option(prc).isSome)
  118. prc = nil
  119. doAssert(option(prc).isNone)
  120. block:
  121. doAssert(none[int]().isNone)
  122. doAssert(none(int) == none[int]())
  123. # "$ on typed with .name"
  124. block:
  125. type Named = object
  126. name: string
  127. let nobody = none(Named)
  128. doAssert($nobody == "none(Named)")
  129. # "$ on type with name()"
  130. block:
  131. type Person = object
  132. myname: string
  133. let noperson = none(Person)
  134. doAssert($noperson == "none(Person)")
  135. # "Ref type with overloaded `==`"
  136. block:
  137. let p = some(RefPerson.new())
  138. doAssert p.isSome
  139. block: # test cstring
  140. block:
  141. let x = some("".cstring)
  142. doAssert x.isSome
  143. doAssert x.get == ""
  144. block:
  145. let x = some("12345".cstring)
  146. doAssert x.isSome
  147. doAssert x.get == "12345"
  148. block:
  149. let x = "12345".cstring
  150. let y = some(x)
  151. doAssert y.isSome
  152. doAssert y.get == "12345"
  153. block:
  154. let x = none(cstring)
  155. doAssert x.isNone
  156. doAssert $x == "none(cstring)"
  157. static: main()
  158. main()
  159. when not defined(js):
  160. block: # bug #22932
  161. var it = iterator: int {.closure.} = discard
  162. doAssert it.option.isSome # Passes.
  163. it = nil
  164. doAssert it.option.isNone # Passes.