64 lines
1.8 KiB
Nim
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)
|