summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/parampatterns.nim7
-rw-r--r--compiler/patterns.nim31
-rwxr-xr-xcompiler/semtempl.nim12
3 files changed, 28 insertions, 22 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index 3b5c8f6fa..44e41f7a0 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -101,7 +101,7 @@ proc compileConstraints(p: PNode, result: var TPatternCode) =
       InternalAssert int(high(TNodeKind)) < 255
       for i in low(TNodeKind)..high(TNodeKind):
         if cmpIgnoreStyle($i, spec) == 0:
-          result.add(ppSymKind)
+          result.add(ppNodeKind)
           result.add(chr(i.ord))
           return
       patternError(p)
@@ -199,7 +199,8 @@ proc matchNodeKinds*(p, n: PNode): bool =
       let kind = TNodeKind(code[pc+1])
       push n.kind == kind
       inc pc
-    of ppSideEffect: push checkForSideEffects(n) != seNoSideEffect
-    of ppNoSideEffect: push checkForSideEffects(n) == seNoSideEffect
+    of ppSideEffect: push checkForSideEffects(n) == seSideEffect
+    of ppNoSideEffect: push checkForSideEffects(n) != seSideEffect
     inc pc
   result = stack[sp-1]
+  
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 48ad55023..402283b76 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -53,13 +53,13 @@ proc sameTrees(a, b: PNode): bool =
         result = true
 
 proc inSymChoice(sc, x: PNode): bool =
-  if sc.kind == nkOpenSymChoice:
-    # same name suffices for open sym choices!
-    result = sc.sons[0].sym.name.id == x.sym.name.id
-  elif sc.kind == nkClosedSymChoice:
+  if sc.kind == nkClosedSymChoice:
     for i in 0.. <sc.len:
       if sc.sons[i].sym == x.sym: return true
-
+  elif sc.kind == nkOpenSymChoice:
+    # same name suffices for open sym choices!
+    result = sc.sons[0].sym.name.id == x.sym.name.id
+  
 proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool =
   # check param constraints first here as this is quite optimized:
   if p.typ.constraint != nil:
@@ -86,7 +86,7 @@ proc bindOrCheck(c: PPatternContext, param: PSym, n: PNode): bool =
     IdNodeTablePutLazy(c.mapping, param, n)
     result = true
 
-proc matchStar(c: PPatternContext, p, n: PNode): bool =
+proc matchNested(c: PPatternContext, p, n: PNode): bool =
   # match ``op*param``
 
   proc matchStarAux(c: PPatternContext, op, n, arglist: PNode) =
@@ -109,6 +109,8 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
   # hidden conversions (?)
   if isPatternParam(c, p):
     result = bindOrCheck(c, p.sym, n)
+  elif n.kind == nkSym and p.kind == nkIdent:
+    result = p.ident.id == n.sym.name.id
   elif n.kind == nkSym and inSymChoice(p, n):
     result = true
   elif n.kind == nkSym and n.sym.kind == skConst:
@@ -120,7 +122,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
     let opr = p.sons[0].ident.s
     case opr
     of "|": result = matchChoice(c, p, n)
-    of "*": result = matchStar(c, p, n)
+    of "*": result = matchNested(c, p, n)
     of "~": result = not matches(c, p.sons[1], n)
     else: InternalError(p.info, "invalid pattern")
     # template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) = 
@@ -142,13 +144,12 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
       var plen = sonsLen(p)
       # special rule for p(X) ~ f(...); this also works for stuff like
       # partial case statements, etc! - Not really ... :-/
-      if plen <= sonsLen(n):
-        let v = lastSon(p)
-        if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
+      let v = lastSon(p)
+      if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
+        var arglist: PNode
+        if plen <= sonsLen(n):
           for i in countup(0, plen - 2):
             if not matches(c, p.sons[i], n.sons[i]): return
-          
-          var arglist: PNode
           if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and
               lastSon(n).sons[1].kind == nkBracket:
             # unpack varargs:
@@ -161,7 +162,11 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
             # p(X)
             for i in countup(0, sonsLen(n) - plen):
               arglist.sons[i] = n.sons[i + plen - 1]
-          # check or bind 'X':
+          return bindOrCheck(c, v.sym, arglist)
+        elif plen-1 == sonsLen(n):
+          for i in countup(0, plen - 2):
+            if not matches(c, p.sons[i], n.sons[i]): return
+          arglist = newNodeI(nkArgList, n.info)
           return bindOrCheck(c, v.sym, arglist)
       if plen == sonsLen(n):
         for i in countup(0, sonsLen(p) - 1):
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 9e0e0ebab..0887e1789 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -423,6 +423,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
     s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
   
   proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
+    result = n
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
         incl(s.flags, sfUsed)
@@ -432,11 +433,9 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
       elif templToExpand(s):
         result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
       else:
-        # we use 'scForceOpen' here so that e.g. "writeln" (which is a
-        # non ambiguous generic) will match its instantiations:
-        result = symChoice(c.c, n, s, scForceOpen)
-    else:
-      result = n
+        nil
+        # we keep the ident unbound for matching instantiated symbols and
+        # more flexibility
   
   proc expectParam(c: var TemplCtx, n: PNode): PNode =
     let s = QualifiedLookUp(c.c, n, {})
@@ -506,7 +505,8 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
       if s != nil:
         if Contains(c.toBind, s.id):
           return symChoice(c.c, n, s, scClosed)
-        return symChoice(c.c, n, s, scForceOpen)
+        else:
+          return newIdentNode(s.name, n.info)
     of nkPar:
       if n.len == 1: return semPatternBody(c, n.sons[0])
     else: nil