questionable/questionable/chaining.nim
2021-03-13 11:02:27 +01:00

40 lines
1.2 KiB
Nim

import std/macros
template `?.`*(option: typed, identifier: untyped{nkIdent}): untyped =
# chain is of shape: option?.identifier
option ->? option.unsafeGet.identifier
macro `?.`*(option: typed, infix: untyped{nkInfix}): untyped =
# chain is of shape: option?.left `operator` right
let left = infix[1]
infix[1] = quote do: `option`?.`left`
infix
macro `?.`*(option: typed, bracket: untyped{nkBracketExpr}): untyped =
# chain is of shape: option?.left[right]
let left = bracket[0]
bracket[0] = quote do: `option`?.`left`
bracket
macro `?.`*(option: typed, dot: untyped{nkDotExpr}): untyped =
# chain is of shape: option?.left.right
let left = dot[0]
dot[0] = quote do: `option`?.`left`
dot
macro `?.`*(option: typed, call: untyped{nkCall}): untyped =
let procedure = call[0]
if call.len == 1:
# chain is of shape: option?.procedure()
quote do: `option`?.`procedure`
elif procedure.kind == nnkDotExpr:
# chain is of shape: option?.left.right(arguments)
let (left, right) = (procedure[0], procedure[1])
call[0] = right
call.insert(1, quote do: `option`?.`left`)
call
else:
# chain is of shape: option?.procedure(arguments)
call.insert(1, quote do: `option`.unsafeGet)
quote do: `option` ->? `call`