term rewriting macros fully implemented; still buggy
This commit is contained in:
parent
b56df72a32
commit
af7c92c003
22 changed files with 676 additions and 138 deletions
|
|
@ -89,7 +89,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
|
|||
for x in items(sc): toBind.incl(x.sym.id)
|
||||
else:
|
||||
illFormedAst(a)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result = newNodeI(nkNilLit, n.info)
|
||||
|
||||
proc replaceIdentBySym(n: var PNode, s: PNode) =
|
||||
case n.kind
|
||||
|
|
@ -98,16 +98,10 @@ proc replaceIdentBySym(n: var PNode, s: PNode) =
|
|||
of nkIdent, nkAccQuoted, nkSym: n = s
|
||||
else: illFormedAst(n)
|
||||
|
||||
# This code here is the first pass over a template's body. The same code also
|
||||
# implements the first pass over a pattern's body:
|
||||
|
||||
type
|
||||
TBodyKind = enum
|
||||
bkTemplate, bkPattern
|
||||
TemplCtx {.pure, final.} = object
|
||||
c: PContext
|
||||
toBind: TIntSet
|
||||
bodyKind: TBodyKind
|
||||
owner: PSym
|
||||
|
||||
proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||
|
|
@ -188,8 +182,6 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
|||
result = newSymNode(s, n.info)
|
||||
elif Contains(c.toBind, s.id):
|
||||
result = symChoice(c.c, n, s, scClosed)
|
||||
elif c.bodyKind == bkPattern:
|
||||
result = symChoice(c.c, n, s, scOpen)
|
||||
elif s.owner == c.owner and sfGenSym in s.flags:
|
||||
# template tmp[T](x: var seq[T]) =
|
||||
# var yz: T
|
||||
|
|
@ -305,8 +297,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
|||
# so we use the generic code for nkDotExpr too
|
||||
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||
let s = QualifiedLookUp(c.c, n, {})
|
||||
if s != nil and Contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
if s != nil:
|
||||
if Contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
result = n
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result.sons[i] = semTemplBody(c, n.sons[i])
|
||||
|
|
@ -405,7 +398,6 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
|||
ctx.toBind = initIntSet()
|
||||
ctx.c = c
|
||||
ctx.owner = s
|
||||
ctx.bodyKind = bkTemplate
|
||||
if sfDirty in s.flags:
|
||||
n.sons[bodyPos] = semTemplBodyDirty(ctx, n.sons[bodyPos])
|
||||
else:
|
||||
|
|
@ -426,17 +418,109 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
|||
else:
|
||||
SymTabReplace(c.tab.stack[curScope], proto, s)
|
||||
|
||||
proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||
template templToExpand(s: expr): expr =
|
||||
s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
|
||||
|
||||
proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
|
||||
if s != nil:
|
||||
if s.owner == c.owner and s.kind == skParam:
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
elif Contains(c.toBind, s.id):
|
||||
result = symChoice(c.c, n, s, scClosed)
|
||||
elif templToExpand(s):
|
||||
result = semPatternBody(c, semTemplateExpr(c.c, n, s, false))
|
||||
else:
|
||||
result = symChoice(c.c, n, s, scOpen)
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc expectParam(c: var TemplCtx, n: PNode): PNode =
|
||||
let s = QualifiedLookUp(c.c, n, {})
|
||||
if s != nil and s.owner == c.owner and s.kind == skParam:
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
localError(n.info, errInvalidExpression)
|
||||
result = n
|
||||
|
||||
result = n
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
let s = QualifiedLookUp(c.c, n, {})
|
||||
result = handleSym(c, n, s)
|
||||
of nkBindStmt:
|
||||
result = semBindStmt(c.c, n, c.toBind)
|
||||
of nkEmpty, nkSym..nkNilLit: nil
|
||||
of nkCurlyExpr:
|
||||
# we support '(pattern){x}' to bind a subpattern to a parameter 'x':
|
||||
if n.len != 2 or n.sons[1].kind != nkIdent:
|
||||
localError(n.info, errInvalidExpression)
|
||||
else:
|
||||
n.sons[0] = semPatternBody(c, n.sons[0])
|
||||
n.sons[1] = expectParam(c, n.sons[1])
|
||||
of nkCallKinds:
|
||||
let s = QualifiedLookUp(c.c, n.sons[0], {})
|
||||
if s != nil:
|
||||
if s.owner == c.owner and s.kind == skParam: nil
|
||||
elif Contains(c.toBind, s.id): nil
|
||||
elif templToExpand(s):
|
||||
return semPatternBody(c, semTemplateExpr(c.c, n, s, false))
|
||||
|
||||
if n.kind == nkInfix and n.sons[0].kind == nkIdent:
|
||||
# we interpret `*` and `|` only as pattern operators if they occur in
|
||||
# infix notation, so that '`*`(a, b)' can be used for verbatim matching:
|
||||
let opr = n.sons[0]
|
||||
if opr.ident.s == "*":
|
||||
result = newNodeI(nkPattern, n.info, n.len)
|
||||
result.sons[0] = opr
|
||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||
result.sons[2] = expectParam(c, n.sons[2])
|
||||
return
|
||||
elif opr.ident.s == "|":
|
||||
result = newNodeI(nkPattern, n.info, n.len)
|
||||
result.sons[0] = opr
|
||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||
result.sons[2] = semPatternBody(c, n.sons[2])
|
||||
return
|
||||
|
||||
if n.kind == nkPrefix and n.sons[0].kind == nkIdent:
|
||||
let opr = n.sons[0]
|
||||
if opr.ident.s == "~":
|
||||
result = newNodeI(nkPattern, n.info, n.len)
|
||||
result.sons[0] = opr
|
||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||
return
|
||||
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||
else:
|
||||
# dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
|
||||
# so we use the generic code for nkDotExpr too
|
||||
case n.kind
|
||||
of nkDotExpr, nkAccQuoted:
|
||||
let s = QualifiedLookUp(c.c, n, {})
|
||||
if s != nil:
|
||||
if Contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
return symChoice(c.c, n, s, scOpen)
|
||||
of nkPar:
|
||||
if n.len == 1: return semPatternBody(c, n.sons[0])
|
||||
else: nil
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||
|
||||
proc semPattern(c: PContext, n: PNode): PNode =
|
||||
# not much to do here: We don't replace operators ``$``, ``*``, ``+``,
|
||||
# ``|``, ``~`` as meta operators and strip the leading ``\`` of all
|
||||
# operators.
|
||||
openScope(c.tab)
|
||||
var ctx: TemplCtx
|
||||
ctx.toBind = initIntSet()
|
||||
ctx.c = c
|
||||
ctx.owner = getCurrOwner()
|
||||
ctx.bodyKind = bkPattern
|
||||
result = semTemplBody(ctx, n)
|
||||
if result.kind in {nkStmtList, nkStmtListExpr} and result.len == 1:
|
||||
result = result.sons[0]
|
||||
result = flattenStmts(semPatternBody(ctx, n))
|
||||
if result.kind in {nkStmtList, nkStmtListExpr}:
|
||||
if result.len == 1:
|
||||
result = result.sons[0]
|
||||
elif result.len == 0:
|
||||
LocalError(n.info, errInvalidExpression)
|
||||
closeScope(c.tab)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue