var tuple unpacking works at compile time

This commit is contained in:
Araq 2013-06-28 08:40:49 +02:00
commit 2ca05eeb16
4 changed files with 54 additions and 40 deletions

View file

@ -287,41 +287,52 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkCurly, info, t) result = newNodeIT(nkCurly, info, t)
else: InternalError("getNullValue: " & $t.kind) else: InternalError("getNullValue: " & $t.kind)
proc evalVarValue(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n, {})
if result.kind in {nkType..nkNilLit}: result = result.copyNode
proc evalVar(c: PEvalContext, n: PNode): PNode = proc evalVar(c: PEvalContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] let a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind != nkIdentDefs: return raiseCannotEval(c, n.info)
# XXX var (x, y) = z support?
#assert(a.sons[0].kind == nkSym) can happen for transformed vars #assert(a.sons[0].kind == nkSym) can happen for transformed vars
if a.sons[2].kind != nkEmpty: if a.kind == nkVarTuple:
result = evalAux(c, a.sons[2], {}) result = evalVarValue(c, a.lastSon)
if result.kind in {nkType..nkNilLit}: if result.kind in {nkType..nkNilLit}:
result = result.copyNode result = result.copyNode
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkPar:
return raiseCannotEval(c, n.info)
for i in 0 .. a.len-3:
var v = a.sons[i].sym
IdNodeTablePut(c.tos.mapping, v, result.sons[i])
else: else:
result = getNullValue(a.sons[0].typ, a.sons[0].info) if a.sons[2].kind != nkEmpty:
if a.sons[0].kind == nkSym: result = evalVarValue(c, a.sons[2])
var v = a.sons[0].sym if isSpecial(result): return
IdNodeTablePut(c.tos.mapping, v, result)
else:
# assign to a.sons[0]:
var x = result
result = evalAux(c, a.sons[0], {})
if isSpecial(result): return
myreset(x)
x.kind = result.kind
x.typ = result.typ
case x.kind
of nkCharLit..nkInt64Lit: x.intVal = result.intVal
of nkFloatLit..nkFloat64Lit: x.floatVal = result.floatVal
of nkStrLit..nkTripleStrLit: x.strVal = result.strVal
of nkIdent: x.ident = result.ident
of nkSym: x.sym = result.sym
else: else:
if x.kind notin {nkEmpty..nkNilLit}: result = getNullValue(a.sons[0].typ, a.sons[0].info)
discardSons(x) if a.sons[0].kind == nkSym:
for j in countup(0, sonsLen(result) - 1): addSon(x, result.sons[j]) var v = a.sons[0].sym
IdNodeTablePut(c.tos.mapping, v, result)
else:
# assign to a.sons[0]:
var x = result
result = evalAux(c, a.sons[0], {})
if isSpecial(result): return
myreset(x)
x.kind = result.kind
x.typ = result.typ
case x.kind
of nkCharLit..nkInt64Lit: x.intVal = result.intVal
of nkFloatLit..nkFloat64Lit: x.floatVal = result.floatVal
of nkStrLit..nkTripleStrLit: x.strVal = result.strVal
of nkIdent: x.ident = result.ident
of nkSym: x.sym = result.sym
else:
if x.kind notin {nkEmpty..nkNilLit}:
discardSons(x)
for j in countup(0, sonsLen(result) - 1): addSon(x, result.sons[j])
result = emptyNode result = emptyNode
proc aliasNeeded(n: PNode, flags: TEvalFlags): bool = proc aliasNeeded(n: PNode, flags: TEvalFlags): bool =

View file

@ -798,11 +798,12 @@ proc addSourceLine*(fileIdx: int32, line: string) =
proc sourceLine*(i: TLineInfo): PRope = proc sourceLine*(i: TLineInfo): PRope =
if i.fileIndex < 0: return nil if i.fileIndex < 0: return nil
if not optPreserveOrigSource and if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0:
fileInfos[i.fileIndex].lines.len == 0: try:
for line in lines(i.toFullPath): for line in lines(i.toFullPath):
addSourceLine i.fileIndex, line.string addSourceLine i.fileIndex, line.string
except EIO:
discard
InternalAssert i.fileIndex < fileInfos.len InternalAssert i.fileIndex < fileInfos.len
# can happen if the error points to EOF: # can happen if the error points to EOF:
if i.line > fileInfos[i.fileIndex].lines.len: return nil if i.line > fileInfos[i.fileIndex].lines.len: return nil

View file

@ -380,11 +380,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
# side of the '=': # side of the '=':
if warnShadowIdent in gNotes and not identWithin(def, v.name): if warnShadowIdent in gNotes and not identWithin(def, v.name):
Message(a.info, warnShadowIdent, v.name.s) Message(a.info, warnShadowIdent, v.name.s)
if def != nil and def.kind != nkEmpty:
# this is needed for the evaluation pass and for the guard checking:
v.ast = def
if sfThread in v.flags: LocalError(def.info, errThreadvarCannotInit)
if a.kind != nkVarTuple: if a.kind != nkVarTuple:
if def != nil and def.kind != nkEmpty:
# this is needed for the evaluation pass and for the guard checking:
v.ast = def
if sfThread in v.flags: LocalError(def.info, errThreadvarCannotInit)
v.typ = typ v.typ = typ
b = newNodeI(nkIdentDefs, a.info) b = newNodeI(nkIdentDefs, a.info)
if importantComments(): if importantComments():
@ -395,6 +395,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
addSon(b, copyTree(def)) addSon(b, copyTree(def))
addSon(result, b) addSon(result, b)
else: else:
if def.kind == nkPar: v.ast = def[j]
v.typ = tup.sons[j] v.typ = tup.sons[j]
b.sons[j] = newSymNode(v) b.sons[j] = newSymNode(v)
checkNilable(v) checkNilable(v)

View file

@ -15,6 +15,7 @@ version 0.9.4
Bugs Bugs
==== ====
- REPL: after an error no evaluation is performed for the next line
- simple closure iterator doesn't work - simple closure iterator doesn't work
- docgen: sometimes effects are listed twice - docgen: sometimes effects are listed twice
- 'result' is not properly cleaned for NRVO --> use uninit checking instead - 'result' is not properly cleaned for NRVO --> use uninit checking instead