diff --git a/letUtils.nim b/letUtils.nim index 241143d..802bfbc 100644 --- a/letUtils.nim +++ b/letUtils.nim @@ -2,6 +2,8 @@ ## as much as practical. import std/macros +when (NimMajor, NimMinor) >= (1, 2): + import std/with func unreachable {.noReturn, inline.} = discard @@ -21,12 +23,12 @@ template scope*(body: untyped): auto = else: unreachable() -template asLet*(value, name, body: untyped): auto = +template asLet*(val, name, body: untyped): auto = ##[ Equivalent to: .. code-block:: nim - let name = value + let name = val body name @@ -38,16 +40,45 @@ template asLet*(value, name, body: untyped): auto = obj.field = 1 ]## scope: - let name = value + let name = val body name -template asVar*(value, name, body: untyped): auto = +when declared with: + template asLet*(val, body: untyped): auto = + ##[ + Equivalent to: + + .. code-block:: nim + let tmp = val + with tmp: + body + tmp + + **Example:** + + .. code-block:: nim + processObj: + getObj().asLet: + field = 1 + + **Since:** Nim 1.2. + + **See also:** + * `std/with `_ + ]## + scope: + let tmp = val + with tmp: + body + tmp + +template asVar*(val, name, body: untyped): auto = ##[ Equivalent to: .. code-block:: nim - var name = value + var name = val body name @@ -61,10 +92,37 @@ template asVar*(value, name, body: untyped): auto = s.strip ]## scope: - var name = value + var name = val body name +when declared with: + template asVar*(val, body: untyped): auto = + ##[ + Equivalent to: + + .. code-block:: nim + var tmp = val + with tmp: + body + tmp + ]## + runnableExamples: + from std/strbasics import strip + + assert " test\n".asVar(strip) == "test" + ##[ + **Since:** Nim 1.2. + + **See also:** + * `std/with `_ + ]## + scope: + var tmp = val + with tmp: + body + tmp + template viaVar*[T](t: typedesc[T]; name, body: untyped): T = ##[ Equivalent to: @@ -91,6 +149,37 @@ template viaVar*[T](t: typedesc[T]; name, body: untyped): T = body name +when declared with: + template viaVar*[T](t: typedesc[T]; body: untyped): T = + ##[ + Equivalent to: + + .. code-block:: nim + var tmp: T + with tmp: + body + tmp + + **Example:** + + .. code-block:: nim + run: + Config.viaVar: + logFile = "prog.log" + verbosity = 1 + merge loadFromFile "config.kdl" + + **Since:** Nim 1.2. + + **See also:** + * `std/with `_ + ]## + scope: + var tmp: T + with tmp: + body + tmp + macro freezeVars*(body: untyped): auto = ## Create a `let` binding for each top-level `var` in `body`; make other declarations inaccessible ## from outside. diff --git a/tests/test.nim b/tests/test.nim index 337de3b..68e5b78 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -69,6 +69,49 @@ test "`viaVar` without UFCS works": check a == ["msg"] check: not declared b +suite "with implicit variable": + when (NimMajor, NimMinor) >= (1, 2): + template checkEq(x, y: typed) = + check x == y + + test "`asLet` works": + let a = (let b = 1; b).asLet: + checkEq 1 + check a == 1 + check b == 1 + + test "`asLet` without UFCS works": + let a = asLet((let b = 1; b)): + checkEq 1 + check a == 1 + check: not declared b # Different from the test above! + + test "`asVar` works": + let a = (let b = 1; b).asVar: + checkEq 1 + inc + check a == 2 + check b == 1 + + test "`asVar` without UFCS works": + let a = asVar((let b = 1; b)): + checkEq 1 + inc + check a == 2 + check: not declared b # Different from the test above! + + test "`viaVar` works": + let a = seq[string].viaVar: + add "msg" + checkEq ["msg"] + check a == ["msg"] + + test "`viaVar` without UFCS works": + let a = viaVar seq[string]: + add "msg" + checkEq ["msg"] + check a == ["msg"] + test "`freezeVars` works": freezeVars: var fib = @[0, 1]