diff --git a/questionable/binding.nim b/questionable/binding.nim index 5cf91e9..55bf8f0 100644 --- a/questionable/binding.nim +++ b/questionable/binding.nim @@ -14,15 +14,17 @@ macro `=?`*(name, expression): bool = ## instance in an `if` statement. name.expectKind({nnkIdent, nnkVarTy}) + + # Outside of the quote do to avoid binding symbol too early + let unpacker = newCall("questionableUnpack", expression) + if name.kind == nnkIdent: quote do: - mixin questionableUnpack - let (`name` {.used.}, isOk) = questionableUnpack(`expression`) + let (`name` {.used.}, isOk) = `unpacker` isOk else: let name = name[0] quote do: - mixin questionableUnpack - var (`name` {.used.}, isOk) = questionableUnpack(`expression`) + var (`name` {.used.}, isOk) = `unpacker` isOk diff --git a/questionable/results.nim b/questionable/results.nim index 220dd1a..4f6cb7c 100644 --- a/questionable/results.nim +++ b/questionable/results.nim @@ -110,14 +110,21 @@ proc option*[T,E](value: Result[T,E]): ?T = else: T.none -template questionableUnpack*[T, E](expression: Result[T, E]): (T, bool) = +macro questionableUnpack*[T, E](expression: Result[T, E]): (T, bool) = ## Used internally - let res = expression - when declared(internalWithoutError): - if res.isFailure: - internalWithoutError = res.error - questionableUnpack(res.option) + # expression must be resolved before quote do to avoid binding issues + let + resSymbol = genSym() + res = newNimNode(nnkLetSection).add( + newIdentDefs(resSymbol, newEmptyNode(), expression) + ) + quote do: + `res` + when declared(internalWithoutError): + if `resSymbol`.isFailure: + internalWithoutError = `resSymbol`.error + questionableUnpack(`resSymbol`.option) Result.liftUnary(`-`) Result.liftUnary(`+`)