Skip to content

Commit

Permalink
Add overloads that declare an implicit variable
Browse files Browse the repository at this point in the history
They use `std/with` and are thus unavailable prior to Nim 1.2.
  • Loading branch information
SirNickolas committed Mar 6, 2023
1 parent b63600d commit 0e71e0c
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 6 deletions.
101 changes: 95 additions & 6 deletions letUtils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
## as much as practical.

import std/macros
when (NimMajor, NimMinor) >= (1, 2):
import std/with

func unreachable {.noReturn, inline.} = discard

Expand All @@ -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
Expand All @@ -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 <https://nim-lang.org/docs/with.html>`_
]##
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
Expand All @@ -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 <https://nim-lang.org/docs/with.html>`_
]##
scope:
var tmp = val
with tmp:
body
tmp

template viaVar*[T](t: typedesc[T]; name, body: untyped): T =
##[
Equivalent to:
Expand All @@ -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 <https://nim-lang.org/docs/with.html>`_
]##
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.
Expand Down
43 changes: 43 additions & 0 deletions tests/test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 0e71e0c

Please sign in to comment.