mirror of
https://github.com/logos-storage/questionable.git
synced 2026-01-04 06:43:10 +00:00
Better errors when using a proc without a return type in a .? chain
This commit is contained in:
parent
b9a090d001
commit
4967084d22
@ -1,5 +1,6 @@
|
|||||||
import std/options
|
import std/options
|
||||||
import std/macros
|
import std/macros
|
||||||
|
import std/strformat
|
||||||
|
|
||||||
func isSym(node: NimNode): bool =
|
func isSym(node: NimNode): bool =
|
||||||
node.kind in {nnkSym, nnkOpenSymChoice, nnkClosedSymChoice}
|
node.kind in {nnkSym, nnkOpenSymChoice, nnkClosedSymChoice}
|
||||||
@ -7,14 +8,20 @@ func isSym(node: NimNode): bool =
|
|||||||
func expectSym(node: NimNode) =
|
func expectSym(node: NimNode) =
|
||||||
node.expectKind({nnkSym, nnkOpenSymChoice, nnkClosedSymChoice})
|
node.expectKind({nnkSym, nnkOpenSymChoice, nnkClosedSymChoice})
|
||||||
|
|
||||||
|
macro expectReturnType(identifier: untyped, expression: untyped): untyped =
|
||||||
|
let message =
|
||||||
|
fmt"'{identifier}' doesn't have a return type, it can't be in a .? chain"
|
||||||
|
quote do:
|
||||||
|
when compiles(`expression`) and not compiles(typeof `expression`):
|
||||||
|
{.error: `message`.}
|
||||||
|
|
||||||
template `.?`*(option: typed, identifier: untyped{nkIdent}): untyped =
|
template `.?`*(option: typed, identifier: untyped{nkIdent}): untyped =
|
||||||
## The `.?` chaining operator is used to safely access fields and call procs
|
## The `.?` chaining operator is used to safely access fields and call procs
|
||||||
## on Options or Results. The expression is only evaluated when the preceding
|
## on Options or Results. The expression is only evaluated when the preceding
|
||||||
## Option or Result has a value.
|
## Option or Result has a value.
|
||||||
|
|
||||||
# chain is of shape: option.?identifier
|
# chain is of shape: option.?identifier
|
||||||
when not compiles(typeof(option.unsafeGet.identifier)):
|
expectReturnType(identifier, option.unsafeGet.identifier)
|
||||||
{.error: ".? chain cannot return void".}
|
|
||||||
option ->? option.unsafeGet.identifier
|
option ->? option.unsafeGet.identifier
|
||||||
|
|
||||||
macro `.?`*(option: typed, infix: untyped{nkInfix}): untyped =
|
macro `.?`*(option: typed, infix: untyped{nkInfix}): untyped =
|
||||||
@ -70,7 +77,9 @@ macro `.?`*(option: typed, call: untyped{nkCall}): untyped =
|
|||||||
else:
|
else:
|
||||||
# chain is of shape: option.?procedure(arguments)
|
# chain is of shape: option.?procedure(arguments)
|
||||||
call.insert(1, quote do: `option`.unsafeGet)
|
call.insert(1, quote do: `option`.unsafeGet)
|
||||||
quote do: `option` ->? `call`
|
quote do:
|
||||||
|
expectReturnType(`procedure`, `call`)
|
||||||
|
`option` ->? `call`
|
||||||
|
|
||||||
macro `.?`*(option: typed, symbol: untyped): untyped =
|
macro `.?`*(option: typed, symbol: untyped): untyped =
|
||||||
## The `.?` chaining operator is used to safely access fields and call procs
|
## The `.?` chaining operator is used to safely access fields and call procs
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user