Skip to content

Commit

Permalink
treat do with pragmas but no parens as proc (#19191)
Browse files Browse the repository at this point in the history
fixes #19188

(cherry picked from commit 1ef9456)
  • Loading branch information
metagn authored and narimiran committed Apr 24, 2023
1 parent c5df4ed commit 4857d92
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
12 changes: 9 additions & 3 deletions compiler/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1125,11 +1125,14 @@ proc optPragmas(p: var Parser): PNode =

proc parseDoBlock(p: var Parser; info: TLineInfo): PNode =
#| doBlock = 'do' paramListArrow pragma? colcom stmt
let params = parseParamList(p, retColon=false)
var params = parseParamList(p, retColon=false)
let pragmas = optPragmas(p)
colcom(p, result)
result = parseStmt(p)
if params.kind != nkEmpty:
if params.kind != nkEmpty or pragmas.kind != nkEmpty:
if params.kind == nkEmpty:
params = newNodeP(nkFormalParams, p)
params.add(p.emptyNode) # return type
result = newProcNode(nkDo, info,
body = result, params = params, name = p.emptyNode, pattern = p.emptyNode,
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
Expand Down Expand Up @@ -1406,7 +1409,10 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
if stmtList[0].kind == nkStmtList: stmtList = stmtList[0]

stmtList.flags.incl nfBlockArg
if openingParams.kind != nkEmpty:
if openingParams.kind != nkEmpty or openingPragmas.kind != nkEmpty:
if openingParams.kind == nkEmpty:
openingParams = newNodeP(nkFormalParams, p)
openingParams.add(p.emptyNode) # return type
result.add newProcNode(nkDo, stmtList.info, body = stmtList,
params = openingParams,
name = p.emptyNode, pattern = p.emptyNode,
Expand Down
36 changes: 36 additions & 0 deletions doc/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3832,6 +3832,42 @@ executable code. The `sugar <sugar.html>`_ module contains the `=>` macro
which enables a more succinct syntax for anonymous procedures resembling
lambdas as they are in languages like JavaScript, C#, etc.

Do notation
-----------

As a special convenience notation that keeps most elements of a
regular proc expression, the `do` keyword can be used to pass
anonymous procedures to routines:

.. code-block:: nim
var cities = @["Frankfurt", "Tokyo", "New York", "Kyiv"]
sort(cities) do (x, y: string) -> int:
cmp(x.len, y.len)
# Less parentheses using the method plus command syntax:
cities = cities.map do (x: string) -> string:
"City of " & x
`do` is written after the parentheses enclosing the regular proc params.
The proc expression represented by the `do` block is appended to the routine
call as the last argument. In calls using the command syntax, the `do` block
will bind to the immediately preceding expression rather than the command call.

`do` with a parameter list or pragma list corresponds to an anonymous `proc`,
however `do` without parameters or pragmas is treated as a normal statement
list. This allows macros to receive both indented statement lists as an
argument in inline calls, as well as a direct mirror of Nim's routine syntax.

.. code-block:: nim
# Passing a statement list to an inline macro:
macroResults.add quote do:
if not `ex`:
echo `info`, ": Check failed: ", `expString`
# Processing a routine definition in a macro:
rpc(router, "add") do (a, b: int) -> int:
result = a + b
Func
----
Expand Down
19 changes: 17 additions & 2 deletions tests/parser/tdo.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
discard """
output: '''true
output: '''
true
true
true inner B'''
true
true inner B
running with pragma
ran with pragma
'''
"""

template withValue(a, b, c, d, e: untyped) =
Expand Down Expand Up @@ -77,3 +81,14 @@ proc main2 =
echo "true inner B"

main2()

proc withPragma(foo: int, bar: proc() {.raises: [].}) =
echo "running with pragma"
bar()

withPragma(3) do {.raises: [].}:
echo "ran with pragma"

doAssert not (compiles do:
withPragma(3) do {.raises: [].}:
raise newException(Exception))

0 comments on commit 4857d92

Please sign in to comment.