bugfixes and improvements for term rewriting macros

This commit is contained in:
Araq
2012-09-04 23:57:39 +02:00
parent 3a1a197664
commit 30c00aba07
5 changed files with 30 additions and 19 deletions

View File

@@ -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:

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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"