diff --git a/compiler/evals.nim b/compiler/evals.nim index 6b756ab362..84f0266ea7 100644 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -287,41 +287,52 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = result = newNodeIT(nkCurly, info, t) else: InternalError("getNullValue: " & $t.kind) -proc evalVar(c: PEvalContext, n: PNode): PNode = - for i in countup(0, sonsLen(n) - 1): - var a = n.sons[i] - if a.kind == nkCommentStmt: continue - if a.kind != nkIdentDefs: return raiseCannotEval(c, n.info) - # XXX var (x, y) = z support? +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 = + for i in countup(0, sonsLen(n) - 1): + let a = n.sons[i] + if a.kind == nkCommentStmt: continue #assert(a.sons[0].kind == nkSym) can happen for transformed vars - if a.sons[2].kind != nkEmpty: - result = evalAux(c, a.sons[2], {}) - if result.kind in {nkType..nkNilLit}: + if a.kind == nkVarTuple: + result = evalVarValue(c, a.lastSon) + if result.kind in {nkType..nkNilLit}: result = result.copyNode 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: - result = getNullValue(a.sons[0].typ, a.sons[0].info) - if a.sons[0].kind == nkSym: - 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 + if a.sons[2].kind != nkEmpty: + result = evalVarValue(c, a.sons[2]) + if isSpecial(result): return else: - if x.kind notin {nkEmpty..nkNilLit}: - discardSons(x) - for j in countup(0, sonsLen(result) - 1): addSon(x, result.sons[j]) + result = getNullValue(a.sons[0].typ, a.sons[0].info) + if a.sons[0].kind == nkSym: + 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 proc aliasNeeded(n: PNode, flags: TEvalFlags): bool = diff --git a/compiler/msgs.nim b/compiler/msgs.nim index e57c41f71a..711a3c7332 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -798,11 +798,12 @@ proc addSourceLine*(fileIdx: int32, line: string) = proc sourceLine*(i: TLineInfo): PRope = if i.fileIndex < 0: return nil - if not optPreserveOrigSource and - fileInfos[i.fileIndex].lines.len == 0: - for line in lines(i.toFullPath): - addSourceLine i.fileIndex, line.string - + if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0: + try: + for line in lines(i.toFullPath): + addSourceLine i.fileIndex, line.string + except EIO: + discard InternalAssert i.fileIndex < fileInfos.len # can happen if the error points to EOF: if i.line > fileInfos[i.fileIndex].lines.len: return nil diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 47b591d83a..64ef7f4d6b 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -380,11 +380,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = # side of the '=': if warnShadowIdent in gNotes and not identWithin(def, v.name): 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 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 b = newNodeI(nkIdentDefs, a.info) if importantComments(): @@ -394,7 +394,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = addSon(b, a.sons[length-2]) # keep type desc for doc generator addSon(b, copyTree(def)) addSon(result, b) - else: + else: + if def.kind == nkPar: v.ast = def[j] v.typ = tup.sons[j] b.sons[j] = newSymNode(v) checkNilable(v) diff --git a/todo.txt b/todo.txt index 35c6a57044..bf06a1fb0a 100644 --- a/todo.txt +++ b/todo.txt @@ -15,6 +15,7 @@ version 0.9.4 Bugs ==== +- REPL: after an error no evaluation is performed for the next line - simple closure iterator doesn't work - docgen: sometimes effects are listed twice - 'result' is not properly cleaned for NRVO --> use uninit checking instead