diff options
author | Araq <rumpf_a@web.de> | 2012-09-04 23:57:39 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-09-04 23:57:39 +0200 |
commit | 30c00aba07cd8b86dc935209bcad74558bae26ad (patch) | |
tree | a083279303f3eefefd85b7eb514413f6c3c8d943 | |
parent | 3a1a1976645ac9ad2c449b0afea57c7c154ec37f (diff) | |
download | Nim-30c00aba07cd8b86dc935209bcad74558bae26ad.tar.gz |
bugfixes and improvements for term rewriting macros
-rw-r--r-- | compiler/parampatterns.nim | 2 | ||||
-rw-r--r-- | compiler/patterns.nim | 29 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 6 | ||||
-rw-r--r-- | tests/patterns/tstar.nim | 2 | ||||
-rw-r--r-- | tests/patterns/tstmtlist.nim | 10 |
5 files changed, 30 insertions, 19 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 83585dbd4..3b5c8f6fa 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -135,7 +135,7 @@ proc checkForSideEffects(n: PNode): TSideEffectAnalysis = # only calls can produce side effects: let op = n.sons[0] if op.kind == nkSym and isRoutine(op.sym): - let s = n.sym + let s = op.sym if sfSideEffect in s.flags: return seSideEffect # assume no side effect: diff --git a/compiler/patterns.nim b/compiler/patterns.nim index 110fae08a..48ad55023 100644 --- a/compiler/patterns.nim +++ b/compiler/patterns.nim @@ -53,15 +53,15 @@ proc sameTrees(a, b: PNode): bool = result = true proc inSymChoice(sc, x: PNode): bool = - if sc.kind == nkClosedSymChoice: - for i in 0.. <sc.len: - if sc.sons[i].sym == x.sym: return true - elif sc.kind == nkOpenSymChoice: + 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: + for i in 0.. <sc.len: + if sc.sons[i].sym == x.sym: return true proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool = - # check param constraints first here as this quite optimized: + # check param constraints first here as this is quite optimized: if p.typ.constraint != nil: result = matchNodeKinds(p.typ.constraint, n) if not result: return @@ -147,11 +147,20 @@ proc matches(c: PPatternContext, p, n: PNode): bool = if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs: for i in countup(0, plen - 2): if not matches(c, p.sons[i], n.sons[i]): return - var arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1) - # f(1, 2, 3) - # p(X) - for i in countup(0, sonsLen(n) - plen): - arglist.sons[i] = n.sons[i + plen - 1] + + var arglist: PNode + if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and + lastSon(n).sons[1].kind == nkBracket: + # unpack varargs: + let n = lastSon(n).sons[1] + arglist = newNodeI(nkArgList, n.info, n.len) + for i in 0.. <n.len: arglist.sons[i] = n.sons[i] + else: + arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1) + # f(1, 2, 3) + # 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) if plen == sonsLen(n): diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index efdfce78f..9e0e0ebab 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -432,7 +432,9 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode = elif templToExpand(s): result = semPatternBody(c, semTemplateExpr(c.c, n, s, false)) else: - result = symChoice(c.c, n, s, scOpen) + # 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 @@ -504,7 +506,7 @@ 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, scOpen) + return symChoice(c.c, n, s, scForceOpen) of nkPar: if n.len == 1: return semPatternBody(c, n.sons[0]) else: nil diff --git a/tests/patterns/tstar.nim b/tests/patterns/tstar.nim index 6dbff3cd6..55d841c3a 100644 --- a/tests/patterns/tstar.nim +++ b/tests/patterns/tstar.nim @@ -15,5 +15,5 @@ template optConc{ `&&` * a }(a: expr): expr = &&a let space = " " echo "my" && (space & "awe" && "some " ) && "concat" -# check that it's been properly optimized: +# check that it's been optimized properly: doAssert calls == 1 diff --git a/tests/patterns/tstmtlist.nim b/tests/patterns/tstmtlist.nim index 391c93d47..138384227 100644 --- a/tests/patterns/tstmtlist.nim +++ b/tests/patterns/tstmtlist.nim @@ -5,14 +5,14 @@ discard """ """ template optWrite{ - write(stdout, x) - write(stdout, y) -}(x, y: string) = - write(stdout, "|", x, y, "|") + write(f, x) + ((write|writeln){w})(f, y) +}(x, y: varargs[expr], f, w: expr) = + w(f, "|", x, y, "|") if true: echo "0" write stdout, "1" - write stdout, "2" + writeln stdout, "2" write stdout, "3" echo "4" |