bugfix: tuple access in macros (issue #17)

This commit is contained in:
Araq 2011-03-07 00:33:43 +01:00
commit f9c6cec90c
2 changed files with 56 additions and 9 deletions

View file

@ -196,6 +196,23 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
result = evalFinally(c, n, exc) result = evalFinally(c, n, exc)
else: result = evalFinally(c, n, emptyNode) else: result = evalFinally(c, n, emptyNode)
proc getNullValue(typ: PType, info: TLineInfo): PNode
proc getNullValueAux(obj: PNode, result: PNode) =
case obj.kind
of nkRecList:
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result)
of nkRecCase:
getNullValueAux(obj.sons[0], result)
for i in countup(1, sonsLen(obj) - 1):
getNullValueAux(lastSon(obj.sons[i]), result)
of nkSym:
var s = obj.sym
var p = newNodeIT(nkExprColonExpr, result.info, s.typ)
addSon(p, newSymNode(s, result.info))
addSon(p, getNullValue(s.typ, result.info))
addSon(result, p)
else: InternalError(result.info, "getNullValueAux")
proc getNullValue(typ: PType, info: TLineInfo): PNode = proc getNullValue(typ: PType, info: TLineInfo): PNode =
var t = skipTypes(typ, abstractRange) var t = skipTypes(typ, abstractRange)
result = emptyNode result = emptyNode
@ -209,7 +226,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
of tyObject: of tyObject:
result = newNodeIT(nkPar, info, t) result = newNodeIT(nkPar, info, t)
internalError(info, "init to implement") # XXX getNullValueAux(t.n, result)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
result = newNodeIT(nkBracket, info, t) result = newNodeIT(nkBracket, info, t)
for i in countup(0, int(lengthOrd(t)) - 1): for i in countup(0, int(lengthOrd(t)) - 1):
@ -217,7 +234,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyTuple: of tyTuple:
result = newNodeIT(nkPar, info, t) result = newNodeIT(nkPar, info, t)
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
addSon(result, getNullValue(t.sons[i], info)) var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
var field = if t.n != nil: t.n.sons[i].sym else: newSym(
skField, getIdent(":tmp" & $i), t.owner)
addSon(p, newSymNode(field, info))
addSon(p, getNullValue(t.sons[i], info))
addSon(result, p)
else: InternalError("getNullValue") else: InternalError("getNullValue")
proc evalVar(c: PEvalContext, n: PNode): PNode = proc evalVar(c: PEvalContext, n: PNode): PNode =
@ -286,7 +308,11 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
var idx = getOrdValue(result) var idx = getOrdValue(result)
result = emptyNode result = emptyNode
case x.kind case x.kind
of nkBracket, nkPar, nkMetaNode: of nkPar:
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)].sons[1]
else: stackTrace(c, n, errIndexOutOfBounds)
if not aliasNeeded(result, flags): result = copyTree(result)
of nkBracket, nkMetaNode:
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
else: stackTrace(c, n, errIndexOutOfBounds) else: stackTrace(c, n, errIndexOutOfBounds)
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
@ -303,18 +329,18 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
else: stackTrace(c, n, errNilAccess) else: stackTrace(c, n, errNilAccess)
proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
# a real field access; proc calls have already been # a real field access; proc calls have already been transformed
# transformed
# XXX: field checks! # XXX: field checks!
result = evalAux(c, n.sons[0], flags) result = evalAux(c, n.sons[0], flags)
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
if x.kind != nkPar: InternalError(n.info, "evalFieldAccess") if x.kind != nkPar: InternalError(n.info, "evalFieldAccess")
var field = n.sons[1].sym var field = n.sons[1].sym
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(x) - 1):
if x.sons[i].kind != nkExprColonExpr: var it = x.sons[i]
InternalError(n.info, "evalFieldAccess") if it.kind != nkExprColonExpr:
if x.sons[i].sons[0].sym.name.id == field.name.id: InternalError(it.info, "evalFieldAccess")
if it.sons[0].sym.name.id == field.name.id:
result = x.sons[i].sons[1] result = x.sons[i].sons[1]
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
return return

View file

@ -0,0 +1,21 @@
import macros
macro test*(a: stmt): stmt =
var nodes: tuple[a, b: int]
nodes.a = 4
nodes[1] = 45
type
TTypeEx = object
x, y: int
case b: bool
of false: nil
of true: z: float
var t: TTypeEx
t.b = true
t.z = 4.5
test:
"hi"