mirror of
https://github.com/logos-storage/questionable.git
synced 2026-01-07 00:03:10 +00:00
Fix: ensure that overridden =? operator does not remain in scope
This commit is contained in:
parent
ef29000f94
commit
a748d22350
@ -1,22 +1,39 @@
|
|||||||
|
import std/macros
|
||||||
import ./binding
|
import ./binding
|
||||||
import ./without
|
import ./without
|
||||||
|
|
||||||
template without*(expression, errorname, body) =
|
macro replaceInfix(expression, operator, replacement): untyped =
|
||||||
|
## Replaces an infix operator in an expression. The AST of the expression is
|
||||||
|
## traversed to find and replace all instances of the operator.
|
||||||
|
|
||||||
|
proc replace(expression, operator, replacement: NimNode): NimNode =
|
||||||
|
if expression.kind == nnkInfix and eqIdent(expression[0], operator):
|
||||||
|
expression[0] = replacement
|
||||||
|
expression[2] = replace(expression[2], operator, replacement)
|
||||||
|
else:
|
||||||
|
for i in 0..<expression.len:
|
||||||
|
expression[i] = replace(expression[i], operator, replacement)
|
||||||
|
expression
|
||||||
|
|
||||||
|
replace(expression, operator, replacement)
|
||||||
|
|
||||||
|
template without*(condition, errorname, body) =
|
||||||
## Used to place guards that ensure that a Result contains a value.
|
## Used to place guards that ensure that a Result contains a value.
|
||||||
## Exposes error when Result does not contain a value.
|
## Exposes error when Result does not contain a value.
|
||||||
|
|
||||||
var error: ref CatchableError
|
var error: ref CatchableError
|
||||||
|
|
||||||
# override =? operator such that it stores the error if there is one
|
# override =? operator such that it stores the error if there is one
|
||||||
template `=?`(name, result): bool =
|
template `override=?`(name, expression): bool {.gensym, used.} =
|
||||||
when result is Result:
|
let optional = expression
|
||||||
if result.isFailure:
|
when optional is Result:
|
||||||
error = result.error
|
if optional.isFailure:
|
||||||
when result is Option:
|
error = optional.error
|
||||||
if result.isNone:
|
when optional is Option:
|
||||||
|
if optional.isNone:
|
||||||
error = newException(ValueError, "Option is set to `none`")
|
error = newException(ValueError, "Option is set to `none`")
|
||||||
binding.`=?`(name, result)
|
name =? optional
|
||||||
|
|
||||||
without expression:
|
without replaceInfix(condition, `=?`, `override=?`):
|
||||||
template errorname: ref CatchableError = error
|
template errorname: ref CatchableError = error
|
||||||
body
|
body
|
||||||
|
|||||||
@ -243,6 +243,28 @@ suite "result":
|
|||||||
test1()
|
test1()
|
||||||
test2()
|
test2()
|
||||||
|
|
||||||
|
test "without statement with error can be used more than once":
|
||||||
|
proc test =
|
||||||
|
without a =? 42.success, error:
|
||||||
|
discard error
|
||||||
|
fail
|
||||||
|
without b =? 42.success, error:
|
||||||
|
discard error
|
||||||
|
fail
|
||||||
|
|
||||||
|
test()
|
||||||
|
|
||||||
|
test "without statement with error works with deeply nested =? operators":
|
||||||
|
proc test =
|
||||||
|
let fail1 = int.failure "error 1"
|
||||||
|
let fail2 = int.failure "error 2"
|
||||||
|
without (block: a =? (if b =? fail1: b.success else: fail2)), error:
|
||||||
|
check error.msg == "error 2"
|
||||||
|
return
|
||||||
|
fail
|
||||||
|
|
||||||
|
test()
|
||||||
|
|
||||||
test "catch can be used to convert exceptions to results":
|
test "catch can be used to convert exceptions to results":
|
||||||
check parseInt("42").catch == 42.success
|
check parseInt("42").catch == 42.success
|
||||||
check parseInt("foo").catch.error of ValueError
|
check parseInt("foo").catch.error of ValueError
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user