bugfix: tuple access in macros (issue #17)
This commit is contained in:
parent
3005955d20
commit
f9c6cec90c
2 changed files with 56 additions and 9 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
21
tests/accept/compile/tmacro1.nim
Normal file
21
tests/accept/compile/tmacro1.nim
Normal 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"
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue