diff options
author | slangmgh <37659406+slangmgh@users.noreply.github.com> | 2020-08-15 07:33:21 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-15 01:33:21 +0200 |
commit | ba042af9cc6194cd3c3e67e5daf0165b4b3630c0 (patch) | |
tree | 960fe34914af04ed3cacb294cd70b5858a49b3f8 | |
parent | 957bf15a08d5443a50452909743747d19b5f29f8 (diff) | |
download | Nim-ba042af9cc6194cd3c3e67e5daf0165b4b3630c0.tar.gz |
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>
-rw-r--r-- | changelog.md | 15 | ||||
-rw-r--r-- | lib/pure/sugar.nim | 26 | ||||
-rw-r--r-- | lib/std/private/underscored_calls.nim | 25 | ||||
-rw-r--r-- | lib/std/with.nim | 7 |
4 files changed, 60 insertions, 13 deletions
diff --git a/changelog.md b/changelog.md index f6f1f94cd..eebccb62f 100644 --- a/changelog.md +++ b/changelog.md @@ -148,6 +148,21 @@ - Added `deques.toDeque`, which creates a deque from an openArray. The usage is similar to procs such as `sets.toHashSet` and `tables.toTable`. Previously, 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 - The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim index 00f4de5d8..0edcc5697 100644 --- a/lib/pure/sugar.nim +++ b/lib/pure/sugar.nim @@ -337,6 +337,32 @@ macro collect*(init, body: untyped): untyped {.since: (1, 1).} = when isMainModule: 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 var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9] diff --git a/lib/std/private/underscored_calls.nim b/lib/std/private/underscored_calls.nim index c7aeb6ae2..f0bcbcc74 100644 --- a/lib/std/private/underscored_calls.nim +++ b/lib/std/private/underscored_calls.nim @@ -26,6 +26,12 @@ proc underscoredCall(n, arg0: NimNode): NimNode = for i in 1..u-1: result.add n[i] result.add arg0 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: # handle e.g. 'x.dup(sort)' result = newNimNode(nnkCall, n) @@ -33,17 +39,10 @@ proc underscoredCall(n, arg0: NimNode): NimNode = result.add arg0 proc underscoredCalls*(result, calls, arg0: NimNode) = - proc handleStmtList(result, n, arg0: NimNode) = - 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: + expectKind calls, {nnkArgList, nnkStmtList, nnkStmtListExpr} + + for call in calls: + if call.kind in {nnkStmtList, nnkStmtListExpr}: + underscoredCalls(result, call, arg0) + else: result.add underscoredCall(call, arg0) diff --git a/lib/std/with.nim b/lib/std/with.nim index c1ac96fcb..ea26065a1 100644 --- a/lib/std/with.nim +++ b/lib/std/with.nim @@ -41,6 +41,7 @@ when isMainModule: type Foo = object col, pos: string + name: string 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) @@ -49,3 +50,9 @@ when isMainModule: with(f, setColor(2, 3, 4), setPosition(0.0, 1.0)) echo f + f = Foo() + with f: + col = $(2, 3, 4) + pos = $(0.0, 1.0) + _.name = "bar" + echo f |