std/with support field assign (#14484)
* std/with support filed assign * add changelog * add support x.dup.with * add example * revert support x.dup.with; add example * update changelog; fix assignment in parameter * Update changelog.md * add example for assignment in parameter * Remove colon style assign Co-authored-by: Clyybber <darkmine956@gmail.com>
This commit is contained in:
parent
957bf15a08
commit
ba042af9cc
4 changed files with 59 additions and 12 deletions
15
changelog.md
15
changelog.md
|
|
@ -149,6 +149,21 @@
|
||||||
similar to procs such as `sets.toHashSet` and `tables.toTable`. Previously,
|
similar to procs such as `sets.toHashSet` and `tables.toTable`. Previously,
|
||||||
it was necessary to create an empty deque and add items manually.
|
it was necessary to create an empty deque and add items manually.
|
||||||
|
|
||||||
|
- `std/with`, `sugar.dup` now support object field assignment expression:
|
||||||
|
```nim
|
||||||
|
import std/with
|
||||||
|
|
||||||
|
type Foo = object
|
||||||
|
x, y: int
|
||||||
|
|
||||||
|
var foo = Foo()
|
||||||
|
with foo:
|
||||||
|
x = 10
|
||||||
|
y = 20
|
||||||
|
|
||||||
|
echo foo
|
||||||
|
```
|
||||||
|
|
||||||
## Language changes
|
## Language changes
|
||||||
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
|
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
|
||||||
`wasMoved` calls where needed.
|
`wasMoved` calls where needed.
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,32 @@ macro collect*(init, body: untyped): untyped {.since: (1, 1).} =
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
since (1, 1):
|
since (1, 1):
|
||||||
|
block dup_with_field:
|
||||||
|
type
|
||||||
|
Foo = object
|
||||||
|
col, pos: int
|
||||||
|
name: string
|
||||||
|
|
||||||
|
proc inc_col(foo: var Foo) = inc(foo.col)
|
||||||
|
proc inc_pos(foo: var Foo) = inc(foo.pos)
|
||||||
|
proc name_append(foo: var Foo, s: string) = foo.name &= s
|
||||||
|
|
||||||
|
let a = Foo(col: 1, pos: 2, name: "foo")
|
||||||
|
block:
|
||||||
|
let b = a.dup(inc_col, inc_pos):
|
||||||
|
_.pos = 3
|
||||||
|
name_append("bar")
|
||||||
|
inc_pos
|
||||||
|
|
||||||
|
doAssert(b == Foo(col: 2, pos: 4, name: "foobar"))
|
||||||
|
|
||||||
|
block:
|
||||||
|
let b = a.dup(inc_col, pos = 3, name = "bar"):
|
||||||
|
name_append("bar")
|
||||||
|
inc_pos
|
||||||
|
|
||||||
|
doAssert(b == Foo(col: 2, pos: 4, name: "barbar"))
|
||||||
|
|
||||||
import algorithm
|
import algorithm
|
||||||
|
|
||||||
var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@ proc underscoredCall(n, arg0: NimNode): NimNode =
|
||||||
for i in 1..u-1: result.add n[i]
|
for i in 1..u-1: result.add n[i]
|
||||||
result.add arg0
|
result.add arg0
|
||||||
for i in u+1..n.len-1: result.add n[i]
|
for i in u+1..n.len-1: result.add n[i]
|
||||||
|
elif n.kind in {nnkAsgn, nnkExprEqExpr}:
|
||||||
|
var field = n[0]
|
||||||
|
if n[0].kind == nnkDotExpr and n[0][0].eqIdent("_"):
|
||||||
|
# handle _.field = ...
|
||||||
|
field = n[0][1]
|
||||||
|
result = newDotExpr(arg0, field).newAssignment n[1]
|
||||||
else:
|
else:
|
||||||
# handle e.g. 'x.dup(sort)'
|
# handle e.g. 'x.dup(sort)'
|
||||||
result = newNimNode(nnkCall, n)
|
result = newNimNode(nnkCall, n)
|
||||||
|
|
@ -33,17 +39,10 @@ proc underscoredCall(n, arg0: NimNode): NimNode =
|
||||||
result.add arg0
|
result.add arg0
|
||||||
|
|
||||||
proc underscoredCalls*(result, calls, arg0: NimNode) =
|
proc underscoredCalls*(result, calls, arg0: NimNode) =
|
||||||
proc handleStmtList(result, n, arg0: NimNode) =
|
expectKind calls, {nnkArgList, nnkStmtList, nnkStmtListExpr}
|
||||||
for a in n:
|
|
||||||
if a.kind in {nnkStmtList, nnkStmtListExpr}:
|
|
||||||
handleStmtList(result, a, arg0)
|
|
||||||
else:
|
|
||||||
result.add underscoredCall(a, arg0)
|
|
||||||
|
|
||||||
expectKind calls, nnkArgList
|
|
||||||
if calls.len == 1 and calls[0].kind in {nnkStmtList, nnkStmtListExpr}:
|
|
||||||
# the 'macro: body' syntax is used:
|
|
||||||
handleStmtList(result, calls[0], arg0)
|
|
||||||
else:
|
|
||||||
for call in calls:
|
for call in calls:
|
||||||
|
if call.kind in {nnkStmtList, nnkStmtListExpr}:
|
||||||
|
underscoredCalls(result, call, arg0)
|
||||||
|
else:
|
||||||
result.add underscoredCall(call, arg0)
|
result.add underscoredCall(call, arg0)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ when isMainModule:
|
||||||
type
|
type
|
||||||
Foo = object
|
Foo = object
|
||||||
col, pos: string
|
col, pos: string
|
||||||
|
name: string
|
||||||
|
|
||||||
proc setColor(f: var Foo; r, g, b: int) = f.col = $(r, g, b)
|
proc setColor(f: var Foo; r, g, b: int) = f.col = $(r, g, b)
|
||||||
proc setPosition(f: var Foo; x, y: float) = f.pos = $(x, y)
|
proc setPosition(f: var Foo; x, y: float) = f.pos = $(x, y)
|
||||||
|
|
@ -49,3 +50,9 @@ when isMainModule:
|
||||||
with(f, setColor(2, 3, 4), setPosition(0.0, 1.0))
|
with(f, setColor(2, 3, 4), setPosition(0.0, 1.0))
|
||||||
echo f
|
echo f
|
||||||
|
|
||||||
|
f = Foo()
|
||||||
|
with f:
|
||||||
|
col = $(2, 3, 4)
|
||||||
|
pos = $(0.0, 1.0)
|
||||||
|
_.name = "bar"
|
||||||
|
echo f
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue