diff options
author | PMunch <peterme@peterme.net> | 2018-10-31 22:14:29 +0100 |
---|---|---|
committer | Arne Döring <arne.doering@gmx.net> | 2018-10-31 22:14:29 +0100 |
commit | e9ed4dccb6f305beb637c890de66a465c8bb7bbe (patch) | |
tree | 9368b08a86f49c289c856f19ebc04daff2f56620 /compiler | |
parent | d56312624e23ad830a060ac3733488ce2b69ae70 (diff) | |
download | Nim-e9ed4dccb6f305beb637c890de66a465c8bb7bbe.tar.gz |
Quote do now works with result in block (#7343)
* Fix result not being able to use in quote do This fixes the annoying issue of not be able to use result inside a quote do block. It works by a simple trick. The quote do mechanic is based on dynamically creating a template and immediately calling it with the arguments found within the quote do block. Since this is called in the scope of the macro the result variable is shadowed. This trick works by changing all occurences of result (which shouldn't cause any issues as result isn't used for anything else for the same reason) to another name and then passing in an IdentNode with result as a named parameter with that name. Note that currently this just replaces it with a fixed named variable "res" which should be changed to a non-colliding, dynamically created name. * Fix hard coded parameter "res" to anonymous symbol This fixes the hard coded parameter "res" to be an anonymous symbol instead so it won't collide with other parts of the argument list. * Add test case for result in quote do block A simple test case based on GitHub issue #7323 on how you can't put result in a quote do block. This test verifies that it actually works correctly now. * Add test for explicit capturing of result * Rebased against devel
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semexprs.nim | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 1725d7a31..10ae49b12 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1811,6 +1811,7 @@ proc processQuotations(c: PContext; n: var PNode, op: string, ids.add n return + if n.kind == nkPrefix: checkSonsLen(n, 2, c.config) if n[0].kind == nkIdent: @@ -1821,6 +1822,9 @@ proc processQuotations(c: PContext; n: var PNode, op: string, n.sons[0] = newIdentNode(getIdent(c.cache, examinedOp.substr(op.len)), n.info) elif n.kind == nkAccQuoted and op == "``": returnQuote n[0] + elif n.kind == nkIdent: + if n.ident.s == "result": + n = ids[0] for i in 0 ..< n.safeLen: processQuotations(c, n.sons[i], op, quotes, ids) @@ -1832,15 +1836,18 @@ proc semQuoteAst(c: PContext, n: PNode): PNode = var quotedBlock = n[^1] op = if n.len == 3: expectString(c, n[1]) else: "``" - quotes = newSeq[PNode](1) + quotes = newSeq[PNode](2) # the quotes will be added to a nkCall statement - # leave some room for the callee symbol - ids = newSeq[PNode]() + # leave some room for the callee symbol and the result symbol + ids = newSeq[PNode](1) # this will store the generated param names + # leave some room for the result symbol if quotedBlock.kind != nkStmtList: localError(c.config, n.info, errXExpected, "block") + # This adds a default first field to pass the result symbol + ids[0] = newAnonSym(c, skParam, n.info).newSymNode processQuotations(c, quotedBlock, op, quotes, ids) var dummyTemplate = newProcNode( @@ -1859,6 +1866,8 @@ proc semQuoteAst(c: PContext, n: PNode): PNode = var tmpl = semTemplateDef(c, dummyTemplate) quotes[0] = tmpl[namePos] + # This adds a call to newIdentNode("result") as the first argument to the template call + quotes[1] = newNode(nkCall, n.info, @[newIdentNode(getIdent(c.cache, "newIdentNode"), n.info), newStrNode(nkStrLit, "result")]) result = newNode(nkCall, n.info, @[ createMagic(c.graph, "getAst", mExpandToAst).newSymNode, newNode(nkCall, n.info, quotes)]) |