mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
Nested with blocks (#22042)
* Implemented with-nesting in underscoredCalls() * Add tests for nested with
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
|
||||
import macros
|
||||
|
||||
proc underscoredCalls*(result, calls, arg0: NimNode)
|
||||
|
||||
proc underscoredCall(n, arg0: NimNode): NimNode =
|
||||
proc underscorePos(n: NimNode): int =
|
||||
for i in 1 ..< n.len:
|
||||
@@ -19,13 +21,19 @@ proc underscoredCall(n, arg0: NimNode): NimNode =
|
||||
return 0
|
||||
|
||||
if n.kind in nnkCallKinds:
|
||||
result = copyNimNode(n)
|
||||
result.add n[0]
|
||||
if n[0].kind in {nnkIdent, nnkSym} and n[0].eqIdent("with"):
|
||||
expectKind n[1], {nnkIdent, nnkSym}
|
||||
|
||||
let u = underscorePos(n)
|
||||
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]
|
||||
result = newStmtList()
|
||||
underscoredCalls(result, n[2 .. ^1].newStmtList, newDotExpr(arg0, n[1]))
|
||||
else:
|
||||
result = copyNimNode(n)
|
||||
result.add n[0]
|
||||
|
||||
let u = underscorePos(n)
|
||||
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("_"):
|
||||
|
||||
@@ -35,5 +35,15 @@ macro with*(arg: typed; calls: varargs[untyped]): untyped =
|
||||
-= 5
|
||||
doAssert a == 43
|
||||
|
||||
# Nesting works for object types too!
|
||||
var foo = (bar: 1, qux: (baz: 2))
|
||||
with foo:
|
||||
bar = 2
|
||||
with qux:
|
||||
baz = 3
|
||||
doAssert foo.bar == 2
|
||||
doAssert foo.qux.baz == 3
|
||||
|
||||
result = newNimNode(nnkStmtList, arg)
|
||||
underscoredCalls(result, calls, arg)
|
||||
echo result.astGenRepr
|
||||
|
||||
@@ -26,3 +26,19 @@ with f:
|
||||
doAssert f.col == "(2, 3, 4)"
|
||||
doAssert f.pos == "(0.0, 1.0)"
|
||||
doAssert f.name == "bar"
|
||||
|
||||
type
|
||||
Baz* = object
|
||||
a*, b*: int
|
||||
Bar* = object
|
||||
x*: int
|
||||
baz*: Baz
|
||||
|
||||
var bar: Bar
|
||||
with bar:
|
||||
x = 1
|
||||
with baz:
|
||||
a = 2
|
||||
|
||||
doAssert bar.x == 1
|
||||
doAssert bar.baz.a == 2
|
||||
|
||||
Reference in New Issue
Block a user