bugfixes and improvements for term rewriting macros
This commit is contained in:
parent
3a1a197664
commit
30c00aba07
5 changed files with 30 additions and 19 deletions
|
|
@ -135,7 +135,7 @@ proc checkForSideEffects(n: PNode): TSideEffectAnalysis =
|
||||||
# only calls can produce side effects:
|
# only calls can produce side effects:
|
||||||
let op = n.sons[0]
|
let op = n.sons[0]
|
||||||
if op.kind == nkSym and isRoutine(op.sym):
|
if op.kind == nkSym and isRoutine(op.sym):
|
||||||
let s = n.sym
|
let s = op.sym
|
||||||
if sfSideEffect in s.flags:
|
if sfSideEffect in s.flags:
|
||||||
return seSideEffect
|
return seSideEffect
|
||||||
# assume no side effect:
|
# assume no side effect:
|
||||||
|
|
|
||||||
|
|
@ -53,15 +53,15 @@ proc sameTrees(a, b: PNode): bool =
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc inSymChoice(sc, x: PNode): bool =
|
proc inSymChoice(sc, x: PNode): bool =
|
||||||
if sc.kind == nkClosedSymChoice:
|
if sc.kind == nkOpenSymChoice:
|
||||||
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!
|
# same name suffices for open sym choices!
|
||||||
result = sc.sons[0].sym.name.id == x.sym.name.id
|
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 =
|
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:
|
if p.typ.constraint != nil:
|
||||||
result = matchNodeKinds(p.typ.constraint, n)
|
result = matchNodeKinds(p.typ.constraint, n)
|
||||||
if not result: return
|
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:
|
if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
|
||||||
for i in countup(0, plen - 2):
|
for i in countup(0, plen - 2):
|
||||||
if not matches(c, p.sons[i], n.sons[i]): return
|
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)
|
var arglist: PNode
|
||||||
# p(X)
|
if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and
|
||||||
for i in countup(0, sonsLen(n) - plen):
|
lastSon(n).sons[1].kind == nkBracket:
|
||||||
arglist.sons[i] = n.sons[i + plen - 1]
|
# 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':
|
# check or bind 'X':
|
||||||
return bindOrCheck(c, v.sym, arglist)
|
return bindOrCheck(c, v.sym, arglist)
|
||||||
if plen == sonsLen(n):
|
if plen == sonsLen(n):
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,9 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
elif templToExpand(s):
|
elif templToExpand(s):
|
||||||
result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
|
result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
|
||||||
else:
|
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:
|
else:
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
|
|
@ -504,7 +506,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
if s != nil:
|
if s != nil:
|
||||||
if Contains(c.toBind, s.id):
|
if Contains(c.toBind, s.id):
|
||||||
return symChoice(c.c, n, s, scClosed)
|
return symChoice(c.c, n, s, scClosed)
|
||||||
return symChoice(c.c, n, s, scOpen)
|
return symChoice(c.c, n, s, scForceOpen)
|
||||||
of nkPar:
|
of nkPar:
|
||||||
if n.len == 1: return semPatternBody(c, n.sons[0])
|
if n.len == 1: return semPatternBody(c, n.sons[0])
|
||||||
else: nil
|
else: nil
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,5 @@ template optConc{ `&&` * a }(a: expr): expr = &&a
|
||||||
let space = " "
|
let space = " "
|
||||||
echo "my" && (space & "awe" && "some " ) && "concat"
|
echo "my" && (space & "awe" && "some " ) && "concat"
|
||||||
|
|
||||||
# check that it's been properly optimized:
|
# check that it's been optimized properly:
|
||||||
doAssert calls == 1
|
doAssert calls == 1
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,14 @@ discard """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template optWrite{
|
template optWrite{
|
||||||
write(stdout, x)
|
write(f, x)
|
||||||
write(stdout, y)
|
((write|writeln){w})(f, y)
|
||||||
}(x, y: string) =
|
}(x, y: varargs[expr], f, w: expr) =
|
||||||
write(stdout, "|", x, y, "|")
|
w(f, "|", x, y, "|")
|
||||||
|
|
||||||
if true:
|
if true:
|
||||||
echo "0"
|
echo "0"
|
||||||
write stdout, "1"
|
write stdout, "1"
|
||||||
write stdout, "2"
|
writeln stdout, "2"
|
||||||
write stdout, "3"
|
write stdout, "3"
|
||||||
echo "4"
|
echo "4"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue