diff options
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 6 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/semstmts.nim | 7 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 3 | ||||
-rw-r--r-- | compiler/vm.nim | 3 | ||||
-rw-r--r-- | tests/closure/tdonotation.nim | 47 |
7 files changed, 59 insertions, 11 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 1791c742d..982654229 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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? diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 5bd274a3e..50ed4e32b 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -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 diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index fff16092c..f925a65af 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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 diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 13670b0d3..63fea997a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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 diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2152e3652..0aa972093 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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) diff --git a/compiler/vm.nim b/compiler/vm.nim index 14800fb13..d311de255 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -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 diff --git a/tests/closure/tdonotation.nim b/tests/closure/tdonotation.nim new file mode 100644 index 000000000..795b18f86 --- /dev/null +++ b/tests/closure/tdonotation.nim @@ -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") + |