[unittest] even deeper inspection of expressions and variables for the check macro

This commit is contained in:
Zahary Karadjov
2012-09-14 00:53:30 +03:00
parent 4a435a8fb4
commit b6f8ab3254
2 changed files with 43 additions and 75 deletions

View File

@@ -93,88 +93,58 @@ template fail* =
checkpoints = @[]
macro check*(conditions: stmt): stmt {.immediate.} =
let conditions = callsite()
let checked = callsite()[1]
case conditions.kind
of nnkCall, nnkCommand, nnkMacroStmt:
case conditions[1].kind
of nnkInfix:
proc rewriteBinaryOp(op: PNimrodNode): PNimrodNode =
template rewrite(op, left, right, lineInfoLit: expr, opLit,
leftLit, rightLit: string, printLhs, printRhs: bool): stmt =
block:
var
lhs = left
rhs = right
var
argsAsgns = newNimNode(nnkStmtList)
argsPrintOuts = newNimNode(nnkStmtList)
counter = 0
if not `op`(lhs, rhs):
checkpoint(lineInfoLit & ": Check failed: " & opLit)
when printLhs: checkpoint(" " & leftLit & " was " & $lhs)
when printRhs: checkpoint(" " & rightLit & " was " & $rhs)
fail()
result = getAst(rewrite(
op[0], op[1], op[2],
op.lineinfo,
op.toStrLit,
op[1].toStrLit,
op[2].toStrLit,
op[1].kind notin nnkLiterals,
op[2].kind notin nnkLiterals))
result = rewriteBinaryOp(conditions[1])
template asgn(a, value: expr): stmt =
let a = value
of nnkCall, nnkCommand:
proc rewriteCall(op: PNimrodNode): PNimrodNode =
template rewrite(call, lineInfoLit: expr, expLit: string,
argAssgs, argPrintOuts: stmt): stmt =
block:
argAssgs
if not call:
checkpoint(lineInfoLit & ": Check failed: " & expLit)
argPrintOuts
fail()
template print(name, value: expr): stmt =
when compiles(string($value)):
checkpoint(name & " was " & $value)
template asgn(a, value: expr): stmt =
let a = value
template print(name, value: expr): stmt =
checkpoint(name & " was " & $value)
proc inspectArgs(exp: PNimrodNode) =
for i in 1 .. <exp.len:
if exp[i].kind notin nnkLiterals:
inc counter
var arg = newIdentNode(":p" & ($counter))
var argStr = exp[i].toStrLit
if exp[i].kind in nnkCallKinds: inspectArgs(exp[i])
argsAsgns.add getAst(asgn(arg, exp[i]))
argsPrintOuts.add getAst(print(argStr, arg))
exp[i] = arg
var
argsAsgns = newNimNode(nnkStmtList)
argsPrintOuts = newNimNode(nnkStmtList)
opStr = op.toStrLit
for i in 1 .. <op.len:
if op[i].kind notin nnkLiterals:
# TODO: print only types that are printable
var arg = newIdentNode(":param" & ($i))
argsAsgns.add getAst(asgn(arg, op[i]))
argsPrintOuts.add getAst(print(op[i].toStrLit, arg))
op[i] = arg
result = getAst(rewrite(op, op.lineinfo, opStr, argsAsgns, argsPrintOuts))
result = rewriteCall(conditions[1])
of nnkStmtList:
result = newNimNode(nnkStmtList)
for i in countup(0, conditions[1].len - 1):
result.add(newCall(!"check", conditions[1][i]))
else:
template rewrite(Exp, lineInfoLit: expr, expLit: string): stmt =
if not Exp:
checkpoint(lineInfoLit & ": Check failed: " & expLit)
case checked.kind
of nnkCallKinds:
template rewrite(call, lineInfoLit: expr, callLit: string,
argAssgs, argPrintOuts: stmt): stmt =
block:
argAssgs
if not call:
checkpoint(lineInfoLit & ": Check failed: " & callLit)
argPrintOuts
fail()
var checkedStr = checked.toStrLit
inspectArgs(checked)
result = getAst(rewrite(checked, checked.lineinfo, checkedStr, argsAsgns, argsPrintOuts))
let e = conditions[1]
result = getAst(rewrite(e, e.lineinfo, e.toStrLit))
of nnkStmtList:
result = newNimNode(nnkStmtList)
for i in countup(0, checked.len - 1):
result.add(newCall(!"check", checked[i]))
else:
var ast = conditions.treeRepr
error conditions.lineinfo & ": Malformed check statement:\n" & ast
template rewrite(Exp, lineInfoLit: expr, expLit: string): stmt =
if not Exp:
checkpoint(lineInfoLit & ": Check failed: " & expLit)
fail()
result = getAst(rewrite(checked, checked.lineinfo, checked.toStrLit))
template require*(conditions: stmt): stmt {.immediate, dirty.} =
block:

View File

@@ -1,5 +1,3 @@
var s = @[]
proc `*` *(a, b: seq[int]): seq[int] =
# allocate a new sequence:
newSeq(result, len(a))