summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/evaltempl.nim6
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semstmts.nim7
-rw-r--r--compiler/sigmatch.nim3
-rw-r--r--compiler/vm.nim3
-rw-r--r--tests/closure/tdonotation.nim47
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")
+