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"
StrLit test Call
StmtList StrLit test
DiscardStmt StmtList
Empty DiscardStmt
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,18 +64,19 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo120"
IntLit 1 IntLit 1
Par Call
Infix Par
Ident !"+" Infix
IntLit 2 Ident !"+"
IntLit 3 IntLit 2
StmtList IntLit 3
DiscardStmt StmtList
Empty DiscardStmt
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,25 +127,26 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo160"
Ident !"x" Call
Do Ident !"x"
Empty Do
Empty
Empty
FormalParams
Empty Empty
IdentDefs Empty
Ident !"y" Empty
Empty FormalParams
Empty
Empty
Empty
StmtList
DiscardStmt
Empty Empty
IdentDefs
Ident !"y"
Empty
Empty
Empty
Empty
StmtList
DiscardStmt
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,62 +167,63 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident !"foo" Ident !"foo190"
Ident !"x" Call
Do Ident !"x"
Empty Do
Empty
Empty
FormalParams
Empty Empty
IdentDefs Empty
Ident !"y" Empty
FormalParams
Empty Empty
Empty IdentDefs
Empty Ident !"y"
Empty Empty
StmtList Empty
DiscardStmt Empty
Empty Empty
Do StmtList
Empty DiscardStmt
Empty Empty
Empty Do
FormalParams Empty
Ident !"int" Empty
IdentDefs Empty
Ident !"z" FormalParams
Empty
Empty
Empty
Empty
StmtList
DiscardStmt
Empty
Do
Empty
Empty
Empty
FormalParams
Ident !"int"
IdentDefs
Ident !"w"
Ident !"int" Ident !"int"
Empty IdentDefs
Empty Ident !"z"
Empty Empty
StmtList Empty
DiscardStmt
Empty
StmtList
DiscardStmt
Empty Empty
Else Empty
StmtList
DiscardStmt
Empty
Do
Empty
Empty
Empty
FormalParams
Ident !"int"
IdentDefs
Ident !"w"
Ident !"int"
Empty
Empty
Empty
StmtList
DiscardStmt
Empty
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Else
StmtList
DiscardStmt
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,8 +295,78 @@ StmtList
Ident !"a" Ident !"a"
Empty Empty
Command Command
Ident !"foo" Ident !"foo280"
Ident !"x" Call
Ident !"x"
Do
Empty
Empty
Empty
FormalParams
Empty
IdentDefs
Ident !"y"
Empty
Empty
Empty
Empty
StmtList
DiscardStmt
Empty
Else
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Ident !"foo290"
Asgn
Ident !"a"
Call
Ident !"foo300"
Asgn
Ident !"a"
Call
Ident !"foo310"
Ident !"x"
Asgn
Ident !"a"
Command
Ident !"foo320"
Ident !"x"
Asgn
Ident !"a"
Call
Ident !"foo330"
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Call
Ident !"foo340"
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Call
Ident !"foo350"
StmtList
DiscardStmt
Empty
Else
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Command
Ident !"foo360"
Call
DotExpr
Ident !"x"
Ident !"bar"
Do Do
Empty Empty
Empty Empty
@ -305,75 +386,18 @@ StmtList
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Command
Ident !"a" DotExpr
Ident !"foo" Ident !"foo370"
Asgn Ident !"add"
Ident !"a"
Call Call
Ident !"foo" Ident !"quote"
Asgn
Ident !"a"
Call
Ident !"foo"
Ident !"x"
Asgn
Ident !"a"
Command
Ident !"foo"
Ident !"x"
Asgn
Ident !"a"
Call
Ident !"foo"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn
Ident !"a"
Call
Ident !"foo"
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Call
Ident !"foo"
StmtList
DiscardStmt
Empty
Else
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Command
Ident !"foo"
Ident !"x"
Do
Empty
Empty
Empty
FormalParams
Empty
IdentDefs
Ident !"y"
Empty
Empty
Empty
Empty
StmtList
DiscardStmt
Empty
Else
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])