mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
fix the do notation when used with procs
This commit is contained in:
@@ -456,6 +456,7 @@ type
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 30)
|
||||
tfVarargs, # procedure has C styled varargs
|
||||
# tyArray type represeting a varargs list
|
||||
tfNoSideEffect, # procedure type does not allow side effects
|
||||
tfFinal, # is the object final?
|
||||
tfInheritable, # is the object inheritable?
|
||||
|
||||
@@ -90,7 +90,11 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
|
||||
|
||||
result = newNodeI(nkArgList, n.info)
|
||||
for i in 1 .. givenRegularParams:
|
||||
result.addSon n.sons[i]
|
||||
let p = n[i]
|
||||
if p != nil and p.kind == nkDo and s.typ.sons[i].kind in {tyStmt, tyExpr}:
|
||||
result.addSon p[bodyPos]
|
||||
else:
|
||||
result.addSon p
|
||||
|
||||
# handle parameters with default values, which were
|
||||
# not supplied by the user
|
||||
|
||||
@@ -2327,8 +2327,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkCurly: result = semSetConstr(c, n)
|
||||
of nkBracket: result = semArrayConstr(c, n, flags)
|
||||
of nkObjConstr: result = semObjConstr(c, n, flags)
|
||||
of nkLambda: result = semLambda(c, n, flags)
|
||||
of nkDo: result = semDo(c, n, flags)
|
||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||
of nkDerefExpr: result = semDeref(c, n)
|
||||
of nkAddr:
|
||||
result = n
|
||||
|
||||
@@ -1066,13 +1066,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
popOwner(c)
|
||||
result.typ = s.typ
|
||||
|
||||
proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# 'do' without params produces a stmt:
|
||||
if n[genericParamsPos].kind == nkEmpty and n[paramsPos].kind == nkEmpty:
|
||||
result = semStmt(c, n[bodyPos])
|
||||
else:
|
||||
result = semLambda(c, n, flags)
|
||||
|
||||
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
|
||||
var n = n
|
||||
|
||||
|
||||
@@ -1061,6 +1061,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
# varargs[expr] is special too but handled earlier. So we only need to
|
||||
# handle varargs[stmt] which is the same as varargs[typed]:
|
||||
if f.kind == tyVarargs:
|
||||
if tfVarargs in a.flags:
|
||||
return typeRel(c, f.base, a.lastSon)
|
||||
if tfOldSchoolExprStmt in f.sons[0].flags:
|
||||
if f.sons[0].kind == tyExpr: return
|
||||
elif f.sons[0].kind == tyStmt: return
|
||||
@@ -2055,6 +2057,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
#assert(container == nil)
|
||||
if container.isNil:
|
||||
container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
|
||||
container.typ.flags.incl tfVarargs
|
||||
else:
|
||||
incrIndexType(container.typ)
|
||||
addSon(container, arg)
|
||||
|
||||
@@ -1599,7 +1599,8 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg =
|
||||
putIntoReg(result, x)
|
||||
else:
|
||||
result.kind = rkNode
|
||||
var n = x
|
||||
var n = if typ.kind in {tyStmt,tyExpr} and x.kind == nkDo: x[bodyPos]
|
||||
else: x
|
||||
if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
|
||||
n = n.canonValue
|
||||
n.flags.incl nfIsRef
|
||||
|
||||
47
tests/closure/tdonotation.nim
Normal file
47
tests/closure/tdonotation.nim
Normal file
@@ -0,0 +1,47 @@
|
||||
discard """
|
||||
output: '''
|
||||
click at 10,20
|
||||
lost focus 2
|
||||
registered handler for UserEvent 1
|
||||
registered handler for UserEvent 3'''
|
||||
"""
|
||||
|
||||
import future
|
||||
|
||||
type
|
||||
Button = object
|
||||
Event = object
|
||||
x, y: int
|
||||
|
||||
proc onClick(x: Button, handler: proc(x: Event)) =
|
||||
handler(Event(x: 10, y: 20))
|
||||
|
||||
proc onFocusLost(x: Button, handler: proc()) =
|
||||
handler()
|
||||
|
||||
proc onUserEvent(x: Button, eventName: string, handler: proc) =
|
||||
echo "registered handler for ", eventName
|
||||
|
||||
var b = Button()
|
||||
|
||||
b.onClick do (e: Event):
|
||||
echo "click at ", e.x, ",", e.y
|
||||
|
||||
when false:
|
||||
# this syntax doesn't work yet
|
||||
b.onFocusLost:
|
||||
echo "lost focus 1"
|
||||
|
||||
b.onFocusLost do:
|
||||
echo "lost focus 2"
|
||||
|
||||
b.onUserEvent("UserEvent 1") do:
|
||||
discard
|
||||
|
||||
when false:
|
||||
# this syntax doesn't work yet
|
||||
b.onUserEvent("UserEvent 2"):
|
||||
discard
|
||||
|
||||
b.onUserEvent("UserEvent 3", () => echo "event 2")
|
||||
|
||||
Reference in New Issue
Block a user