term rewriting macros fully implemented; still buggy

This commit is contained in:
Araq 2012-09-03 00:55:44 +02:00
commit af7c92c003
22 changed files with 676 additions and 138 deletions

View file

@ -19,14 +19,17 @@ type
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
# new symbol
proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx): PNode =
#inc genSymBaseId
proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
case templ.kind
of nkSym:
var s = templ.sym
if s.owner.id == c.owner.id:
if s.kind == skParam:
result = copyTree(actual.sons[s.position])
let x = actual.sons[s.position]
if x.kind == nkArgList:
for y in items(x): result.add(y)
else:
result.add copyTree(x)
else:
InternalAssert sfGenSym in s.flags
var x = PSym(IdTableGet(c.mapping, s))
@ -34,16 +37,42 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx): PNode =
x = copySym(s, false)
x.owner = c.genSymOwner
IdTablePut(c.mapping, s, x)
result = newSymNode(x, templ.info)
result.add newSymNode(x, templ.info)
else:
result.add copyNode(templ)
of nkNone..nkIdent, nkType..nkNilLit: # atom
result.add copyNode(templ)
else:
var res = copyNode(templ)
for i in countup(0, sonsLen(templ) - 1):
evalTemplateAux(templ.sons[i], actual, c, res)
result.add res
when false:
proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx): PNode =
case templ.kind
of nkSym:
var s = templ.sym
if s.owner.id == c.owner.id:
if s.kind == skParam:
result = copyTree(actual.sons[s.position])
else:
InternalAssert sfGenSym in s.flags
var x = PSym(IdTableGet(c.mapping, s))
if x == nil:
x = copySym(s, false)
x.owner = c.genSymOwner
IdTablePut(c.mapping, s, x)
result = newSymNode(x, templ.info)
else:
result = copyNode(templ)
of nkNone..nkIdent, nkType..nkNilLit: # atom
result = copyNode(templ)
else:
result = copyNode(templ)
of nkNone..nkIdent, nkType..nkNilLit: # atom
result = copyNode(templ)
else:
result = copyNode(templ)
newSons(result, sonsLen(templ))
for i in countup(0, sonsLen(templ) - 1):
result.sons[i] = evalTemplateAux(templ.sons[i], actual, c)
newSons(result, sonsLen(templ))
for i in countup(0, sonsLen(templ) - 1):
result.sons[i] = evalTemplateAux(templ.sons[i], actual, c)
proc evalTemplateArgs(n: PNode, s: PSym): PNode =
# if the template has zero arguments, it can be called without ``()``
@ -78,6 +107,19 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
ctx.owner = tmpl
ctx.genSymOwner = genSymOwner
initIdTable(ctx.mapping)
result = evalTemplateAux(tmpl.getBody, args, ctx)
let body = tmpl.getBody
if isAtom(body):
result = newNodeI(nkPar, body.info)
evalTemplateAux(body, args, ctx, result)
if result.len == 1: result = result.sons[0]
else:
GlobalError(result.info, errIllFormedAstX,
renderTree(result, {renderNoComments}))
else:
result = copyNode(body)
#evalTemplateAux(body, args, ctx, result)
for i in countup(0, safeLen(body) - 1):
evalTemplateAux(body.sons[i], args, ctx, result)
dec(evalTemplateCounter)