toptions.nim 5.1 KB

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