Restore the old behavior of parsing "quote do:"

close #5845
This commit is contained in:
Zahary Karadjov 2017-07-18 11:50:06 +03:00 • committed by Andreas Rumpf
commit 7ad115f530
6 changed files with 260 additions and 215 deletions

View file

@ -685,6 +685,11 @@ proc namedParams(p: var TParser, callee: PNode,
# progress guaranteed # progress guaranteed
exprColonEqExprListAux(p, endTok, result) exprColonEqExprListAux(p, endTok, result)
proc commandParam(p: var TParser): PNode =
result = parseExpr(p)
if p.tok.tokType == tkDo:
result = postExprBlocks(p, result)
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode = proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks? #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
#| | doBlocks #| | doBlocks
@ -733,7 +738,7 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
when true: when true:
# progress NOT guaranteed # progress NOT guaranteed
p.hasProgress = false p.hasProgress = false
addSon result, parseExpr(p) addSon result, commandParam(p)
if not p.hasProgress: break if not p.hasProgress: break
else: else:
while p.tok.tokType != tkEof: while p.tok.tokType != tkEof:
@ -1253,14 +1258,12 @@ proc parseExprStmt(p: var TParser): PNode =
while true: while true:
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
var e = parseExpr(p) addSon(result, commandParam(p))
addSon(result, e)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
elif p.tok.indent < 0 and isExprStart(p): elif p.tok.indent < 0 and isExprStart(p):
result = newNode(nkCommand, a.info, @[a]) result = newNode(nkCommand, a.info, @[a])
while true: while true:
var e = parseExpr(p) addSon(result, commandParam(p))
addSon(result, e)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)

View file

@ -248,12 +248,20 @@ calls can use the ``do`` keyword:
.. code-block:: nim .. code-block:: nim
sort(cities) do (x,y: string) -> int: sort(cities) do (x,y: string) -> int:
cmp(x.len, y.len) cmp(x.len, y.len)
# Less parenthesis using the method plus command syntax: # Less parenthesis using the method plus command syntax:
cities = cities.map do (x:string) -> string: cities = cities.map do (x:string) -> string:
"City of " & x "City of " & x
# In macros, the do notation is often used for quasi-quoting
macroResults.add quote do:
if not `ex`:
echo `info`, ": Check failed: ", `expString`
``do`` is written after the parentheses enclosing the regular proc params. ``do`` is written after the parentheses enclosing the regular proc params.
The proc expression represented by the do block is appended to them. The proc expression represented by the do block is appended to them.
In calls using the command syntax, the do block will bind to the immediately
preceeding expression, transforming it in a call.
``do`` with parentheses is an anonymous ``proc``; however a ``do`` without ``do`` with parentheses is an anonymous ``proc``; however a ``do`` without
parentheses is just a block of code. The ``do`` notation can be used to parentheses is just a block of code. The ``do`` notation can be used to

View file

@ -408,20 +408,19 @@ macro `{}`*(typ: typedesc, xs: varargs[untyped]): auto =
kString = quote do: kString = quote do:
when compiles($`k`): $`k` else: "invalid" when compiles($`k`): $`k` else: "invalid"
v = x[1] v = x[1]
body.add(quote do: body.add quote do:
when compiles(`a`.`k`): when compiles(`a`.`k`):
`a`.`k` = `v` `a`.`k` = `v`
elif compiles(`a`[`k`]): elif compiles(`a`[`k`]):
`a`[`k`] = `v` `a`[`k`] = `v`
else: else:
`a`[`kString`] = `v` `a`[`kString`] = `v`
)
else: else:
error("Expression `" & $x.toStrLit & "` not allowed in `{}` macro") error("Expression `" & $x.toStrLit & "` not allowed in `{}` macro")
body.add(quote do: body.add quote do:
return `a` return `a`
)
result = quote do: result = quote do:
proc inner(): `typ` {.gensym.} = proc inner(): `typ` {.gensym.} =

View file

@ -5,7 +5,9 @@ lost focus 1
lost focus 2 lost focus 2
registered handler for UserEvent 1 registered handler for UserEvent 1
registered handler for UserEvent 2 registered handler for UserEvent 2
registered handler for UserEvent 3''' registered handler for UserEvent 3
registered handler for UserEvent 4
'''
""" """
import future import future
@ -35,11 +37,14 @@ b.onFocusLost:
b.onFocusLost do: b.onFocusLost do:
echo "lost focus 2" echo "lost focus 2"
b.onUserEvent "UserEvent 1" do: b.onUserEvent("UserEvent 1") do:
discard discard
b.onUserEvent "UserEvent 2": b.onUserEvent "UserEvent 2":
discard discard
b.onUserEvent("UserEvent 3", () => echo "event 3") b.onUserEvent("UserEvent 3"):
discard
b.onUserEvent("UserEvent 4", () => echo "event 4")

View file

@ -309,11 +309,11 @@ block:
on("click") do (e: Event): on("click") do (e: Event):
console.log e console.log e
jslib.on "reloaded" do: jslib.on("reloaded") do:
console.log jsarguments[0] console.log jsarguments[0]
# this test case is different from the above, because # this test case is different from the above, because
# `subscribe` is not overloaded in the current scope # `subscribe` is not overloaded in the current scope
jslib.subscribe "updates": jslib.subscribe("updates"):
console.log jsarguments[0] console.log jsarguments[0]

View file

@ -1,51 +1,59 @@
discard """ discard """
nimout: ''' nimout: '''
StmtList StmtList
Ident !"foo" Ident !"foo010"
Call Call
Ident !"foo" Ident !"foo020"
Call Call
Ident !"foo" Ident !"foo030"
Ident !"x" Ident !"x"
Command Command
Ident !"foo" Ident !"foo040"
Ident !"x" Ident !"x"
Call Call
Ident !"foo" Ident !"foo050"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo060"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo070"
StrLit test StrLit test
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo080"
StrLit test StrLit test
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo090"
StrLit test StrLit test
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo100"
Call
StrLit test StrLit test
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo101"
Call
IntLit 10
StmtList
DiscardStmt
Empty
Command
Ident !"foo110"
IntLit 1 IntLit 1
Par Par
Infix Infix
@ -56,8 +64,9 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo120"
IntLit 1 IntLit 1
Call
Par Par
Infix Infix
Ident !"+" Ident !"+"
@ -67,7 +76,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo130"
Do Do
Empty Empty
Empty Empty
@ -84,7 +93,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo140"
Do Do
Empty Empty
Empty Empty
@ -101,7 +110,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo150"
Do Do
Empty Empty
Empty Empty
@ -118,7 +127,8 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo160"
Call
Ident !"x" Ident !"x"
Do Do
Empty Empty
@ -136,7 +146,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo170"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -145,7 +155,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo180"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -157,7 +167,8 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo190"
Call
Ident !"x" Ident !"x"
Do Do
Empty Empty
@ -212,7 +223,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident !"foo" Ident !"foo200"
Ident !"x" Ident !"x"
Call Call
Ident !"bar" Ident !"bar"
@ -227,33 +238,33 @@ StmtList
IdentDefs IdentDefs
Ident !"a" Ident !"a"
Empty Empty
Ident !"foo" Ident !"foo210"
VarSection VarSection
IdentDefs IdentDefs
Ident !"a" Ident !"a"
Empty Empty
Call Call
Ident !"foo" Ident !"foo220"
VarSection VarSection
IdentDefs IdentDefs
Ident !"a" Ident !"a"
Empty Empty
Call Call
Ident !"foo" Ident !"foo230"
Ident !"x" Ident !"x"
VarSection VarSection
IdentDefs IdentDefs
Ident !"a" Ident !"a"
Empty Empty
Command Command
Ident !"foo" Ident !"foo240"
Ident !"x" Ident !"x"
VarSection VarSection
IdentDefs IdentDefs
Ident !"a" Ident !"a"
Empty Empty
Call Call
Ident !"foo" Ident !"foo250"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -262,7 +273,7 @@ StmtList
Ident !"a" Ident !"a"
Empty Empty
Call Call
Ident !"foo" Ident !"foo260"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -271,7 +282,7 @@ StmtList
Ident !"a" Ident !"a"
Empty Empty
Call Call
Ident !"foo" Ident !"foo270"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -284,7 +295,8 @@ StmtList
Ident !"a" Ident !"a"
Empty Empty
Command Command
Ident !"foo" Ident !"foo280"
Call
Ident !"x" Ident !"x"
Do Do
Empty Empty
@ -307,39 +319,39 @@ StmtList
Empty Empty
Asgn Asgn
Ident !"a" Ident !"a"
Ident !"foo" Ident !"foo290"
Asgn Asgn
Ident !"a" Ident !"a"
Call Call
Ident !"foo" Ident !"foo300"
Asgn Asgn
Ident !"a" Ident !"a"
Call Call
Ident !"foo" Ident !"foo310"
Ident !"x" Ident !"x"
Asgn Asgn
Ident !"a" Ident !"a"
Command Command
Ident !"foo" Ident !"foo320"
Ident !"x" Ident !"x"
Asgn Asgn
Ident !"a" Ident !"a"
Call Call
Ident !"foo" Ident !"foo330"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident !"a" Ident !"a"
Call Call
Ident !"foo" Ident !"foo340"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident !"a" Ident !"a"
Call Call
Ident !"foo" Ident !"foo350"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -350,8 +362,11 @@ StmtList
Asgn Asgn
Ident !"a" Ident !"a"
Command Command
Ident !"foo" Ident !"foo360"
Call
DotExpr
Ident !"x" Ident !"x"
Ident !"bar"
Do Do
Empty Empty
Empty Empty
@ -371,9 +386,18 @@ StmtList
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command
DotExpr
Ident !"foo370"
Ident !"add"
Call
Ident !"quote"
StmtList
DiscardStmt
Empty
Call Call
DotExpr DotExpr
Ident !"result" Ident !"foo380"
Ident !"add" Ident !"add"
BracketExpr BracketExpr
Call Call
@ -389,62 +413,65 @@ import macros
dumpTree: dumpTree:
# simple calls # simple calls
foo foo010
foo() foo020()
foo(x) foo030(x)
foo x foo040 x
foo: foo050:
discard discard
foo do: foo060 do:
discard discard
foo("test"): foo070("test"):
discard discard
foo("test") do: foo080("test") do:
discard discard
foo "test": foo090 "test":
discard discard
foo "test" do: foo100 "test" do:
discard
foo101 10 do:
discard discard
# more complicated calls # more complicated calls
foo 1, (2+3): foo110 1, (2+3):
discard discard
foo 1, (2+3) do: foo120 1, (2+3) do:
discard discard
foo do (x): foo130 do (x):
discard discard
foo do (x: int): foo140 do (x: int):
discard discard
foo do (x: int) -> int: foo150 do (x: int) -> int:
discard discard
foo x do (y): foo160 x do (y):
discard discard
# extra blocks # extra blocks
foo: foo170:
discard discard
else: else:
discard discard
foo do: foo180 do:
discard discard
do: do:
discard discard
else: else:
discard discard
foo x do (y): foo190 x do (y):
discard discard
do (z) -> int: do (z) -> int:
discard discard
@ -456,58 +483,61 @@ dumpTree:
discard discard
# call with blocks as a param # call with blocks as a param
foo(x, bar do: foo200(x, bar do:
discard discard
else: else:
discard discard
) )
# introduce a variable # introduce a variable
var a = foo var a = foo210
var a = foo() var a = foo220()
var a = foo(x) var a = foo230(x)
var a = foo x var a = foo240 x
var a = foo: var a = foo250:
discard discard
var a = foo do: var a = foo260 do:
discard discard
var a = foo do: var a = foo270 do:
discard discard
else: else:
discard discard
var a = foo x do (y): var a = foo280 x do (y):
discard discard
else: else:
discard discard
# assignments # assignments
a = foo a = foo290
a = foo() a = foo300()
a = foo(x) a = foo310(x)
a = foo x a = foo320 x
a = foo: a = foo330:
discard discard
a = foo do: a = foo340 do:
discard discard
a = foo do: a = foo350 do:
discard discard
else: else:
discard discard
a = foo x do (y): a = foo360 x.bar do (y):
discard discard
else: else:
discard discard
foo370.add quote do:
discard
# some edge cases # some edge cases
result.add((quote do: foo380.add((quote do:
discard discard
)[0]) )[0])