oscon2015/livedemo/coverage2.nim
2015-07-17 10:22:09 +02:00

64 lines
1.8 KiB
Nim

import macros
type HideEffects = proc (x: int) {.raises: [], noSideEffect, tags: [].}
proc wrap(n: NimNode; setter, i: NimNode): NimNode {.compileTime.} =
# XXX better insert as last statement, but move before 'break', 'return' etc.
template callSetterProc(setter, i) =
cast[HideEffects](setter)(i)
result = newTree(nnkStmtList, getAst callSetterProc(setter, i), n)
proc transform(n, setter, data: NimNode): NimNode {.compileTime.} =
# recurse:
result = copyNimNode(n)
for c in n.children:
result.add c.transform(setter, data)
if n.kind in {nnkElifBranch, nnkOfBranch, nnkExceptBranch, nnkElifExpr,
nnkElseExpr, nnkElse, nnkForStmt, nnkWhileStmt}:
let index = newLit(data.len)
data.add(newTree(nnkPar, newLit(result[^1].lineinfo), bindSym"false"))
result[^1] = result[^1].wrap(setter, index)
proc listCoverage(s: openArray[(string, bool)]) =
for x in s:
if not x[1]: echo "NOT EXECUTED ", x[0]
macro cov(p: untyped): untyped =
var data = newNimNode(nnkBracket)
let guard = genSym(nskVar, "guard")
let setter = genSym(nskProc, "guardSetter")
template setterProc(name, guard) =
proc name(x: int) =
guard[x][1] = true
result = transform(p, setter, data)
result = newTree(nnkStmtList, newVarStmt(guard, data),
getAst setterProc(setter, guard),
result,
newCall(bindSym"listCoverage", guard))
cov:
proc toTest(x: int): int {.noSideEffect.} =
if x > 0: result = 88
else: result = 99
proc toTestE(x: int): int =
(if x > 0: 88 else: 99)
proc toTestTry(x: int) =
try:
case x
of 8: echo "8"
of 9: echo "9"
else: echo "foo"
echo "Try it"
except IoError:
echo "IoError"
echo toTest 89
echo toTest(-89)
echo toTestE 89
toTestTry(8)
# echo toTestE(-89)