parent
7e07fc5893
commit
5cf789ac3f
2 changed files with 64 additions and 48 deletions
|
|
@ -509,10 +509,6 @@ macro check*(conditions: untyped): untyped =
|
||||||
## "AKB48".toLowerAscii() == "akb48"
|
## "AKB48".toLowerAscii() == "akb48"
|
||||||
## 'C' in teams
|
## 'C' in teams
|
||||||
let checked = callsite()[1]
|
let checked = callsite()[1]
|
||||||
var
|
|
||||||
argsAsgns = newNimNode(nnkStmtList)
|
|
||||||
argsPrintOuts = newNimNode(nnkStmtList)
|
|
||||||
counter = 0
|
|
||||||
|
|
||||||
template asgn(a: untyped, value: typed) =
|
template asgn(a: untyped, value: typed) =
|
||||||
var a = value # XXX: we need "var: var" here in order to
|
var a = value # XXX: we need "var: var" here in order to
|
||||||
|
|
@ -522,66 +518,71 @@ macro check*(conditions: untyped): untyped =
|
||||||
when compiles(string($value)):
|
when compiles(string($value)):
|
||||||
checkpoint(name & " was " & $value)
|
checkpoint(name & " was " & $value)
|
||||||
|
|
||||||
proc inspectArgs(exp: NimNode): NimNode =
|
proc inspectArgs(exp: NimNode): tuple[assigns, check, printOuts: NimNode] =
|
||||||
result = copyNimTree(exp)
|
result.check = copyNimTree(exp)
|
||||||
|
result.assigns = newNimNode(nnkStmtList)
|
||||||
|
result.printOuts = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
|
var counter = 0
|
||||||
|
|
||||||
if exp[0].kind == nnkIdent and
|
if exp[0].kind == nnkIdent and
|
||||||
$exp[0] in ["and", "or", "not", "in", "notin", "==", "<=",
|
$exp[0] in ["not", "in", "notin", "==", "<=",
|
||||||
">=", "<", ">", "!=", "is", "isnot"]:
|
">=", "<", ">", "!=", "is", "isnot"]:
|
||||||
for i in countup(1, exp.len - 1):
|
|
||||||
|
for i in 1 ..< exp.len:
|
||||||
if exp[i].kind notin nnkLiterals:
|
if exp[i].kind notin nnkLiterals:
|
||||||
inc counter
|
inc counter
|
||||||
var arg = newIdentNode(":p" & $counter)
|
let argStr = exp[i].toStrLit
|
||||||
var argStr = exp[i].toStrLit
|
let paramAst = exp[i]
|
||||||
var paramAst = exp[i]
|
|
||||||
if exp[i].kind == nnkIdent:
|
if exp[i].kind == nnkIdent:
|
||||||
argsPrintOuts.add getAst(print(argStr, paramAst))
|
result.printOuts.add getAst(print(argStr, paramAst))
|
||||||
if exp[i].kind in nnkCallKinds:
|
if exp[i].kind in nnkCallKinds + { nnkDotExpr, nnkBracketExpr }:
|
||||||
var callVar = newIdentNode(":c" & $counter)
|
let callVar = newIdentNode(":c" & $counter)
|
||||||
argsAsgns.add getAst(asgn(callVar, paramAst))
|
result.assigns.add getAst(asgn(callVar, paramAst))
|
||||||
result[i] = callVar
|
result.check[i] = callVar
|
||||||
argsPrintOuts.add getAst(print(argStr, callVar))
|
result.printOuts.add getAst(print(argStr, callVar))
|
||||||
if exp[i].kind == nnkExprEqExpr:
|
if exp[i].kind == nnkExprEqExpr:
|
||||||
# ExprEqExpr
|
# ExprEqExpr
|
||||||
# Ident !"v"
|
# Ident !"v"
|
||||||
# IntLit 2
|
# IntLit 2
|
||||||
result[i] = exp[i][1]
|
result.check[i] = exp[i][1]
|
||||||
if exp[i].typekind notin {ntyTypeDesc}:
|
if exp[i].typekind notin {ntyTypeDesc}:
|
||||||
argsAsgns.add getAst(asgn(arg, paramAst))
|
let arg = newIdentNode(":p" & $counter)
|
||||||
argsPrintOuts.add getAst(print(argStr, arg))
|
result.assigns.add getAst(asgn(arg, paramAst))
|
||||||
|
result.printOuts.add getAst(print(argStr, arg))
|
||||||
if exp[i].kind != nnkExprEqExpr:
|
if exp[i].kind != nnkExprEqExpr:
|
||||||
result[i] = arg
|
result.check[i] = arg
|
||||||
else:
|
else:
|
||||||
result[i][1] = arg
|
result.check[i][1] = arg
|
||||||
|
|
||||||
case checked.kind
|
case checked.kind
|
||||||
of nnkCallKinds:
|
of nnkCallKinds:
|
||||||
template rewrite(call, lineInfoLit, callLit,
|
|
||||||
argAssgs, argPrintOuts) =
|
|
||||||
block:
|
|
||||||
argAssgs #all callables (and assignments) are run here
|
|
||||||
if not call:
|
|
||||||
checkpoint(lineInfoLit & ": Check failed: " & callLit)
|
|
||||||
argPrintOuts
|
|
||||||
fail()
|
|
||||||
|
|
||||||
var checkedStr = checked.toStrLit
|
let (assigns, check, printOuts) = inspectArgs(checked)
|
||||||
let parameterizedCheck = inspectArgs(checked)
|
let lineinfo = newStrLitNode(checked.lineinfo)
|
||||||
result = getAst(rewrite(parameterizedCheck, checked.lineinfo, checkedStr,
|
let callLit = checked.toStrLit
|
||||||
argsAsgns, argsPrintOuts))
|
result = quote do:
|
||||||
|
block:
|
||||||
|
`assigns`
|
||||||
|
if not `check`:
|
||||||
|
checkpoint(`lineinfo` & ": Check failed: " & `callLit`)
|
||||||
|
`printOuts`
|
||||||
|
fail()
|
||||||
|
|
||||||
of nnkStmtList:
|
of nnkStmtList:
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
for i in countup(0, checked.len - 1):
|
for node in checked:
|
||||||
if checked[i].kind != nnkCommentStmt:
|
if node.kind != nnkCommentStmt:
|
||||||
result.add(newCall(!"check", checked[i]))
|
result.add(newCall(!"check", node))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
template rewrite(exp, lineInfoLit, expLit) =
|
let lineinfo = newStrLitNode(checked.lineinfo)
|
||||||
if not exp:
|
let callLit = checked.toStrLit
|
||||||
checkpoint(lineInfoLit & ": Check failed: " & expLit)
|
|
||||||
fail()
|
|
||||||
|
|
||||||
result = getAst(rewrite(checked, checked.lineinfo, checked.toStrLit))
|
result = quote do:
|
||||||
|
if not `checked`:
|
||||||
|
checkpoint(`lineinfo` & ": Check failed: " & `callLit`)
|
||||||
|
fail()
|
||||||
|
|
||||||
template require*(conditions: untyped) =
|
template require*(conditions: untyped) =
|
||||||
## Same as `check` except any failed test causes the program to quit
|
## Same as `check` except any failed test causes the program to quit
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,23 @@
|
||||||
discard """
|
discard """
|
||||||
nimout: "compile start\ncompile end"
|
output: '''[Suite] suite with only teardown
|
||||||
|
|
||||||
|
[Suite] suite with only setup
|
||||||
|
|
||||||
|
[Suite] suite with none
|
||||||
|
|
||||||
|
[Suite] suite with both
|
||||||
|
|
||||||
|
[Suite] bug #4494
|
||||||
|
|
||||||
|
[Suite] bug #5571
|
||||||
|
|
||||||
|
[Suite] bug #5784
|
||||||
|
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import unittest, sequtils
|
import unittest, sequtils
|
||||||
|
|
||||||
static:
|
|
||||||
echo "compile start"
|
|
||||||
|
|
||||||
proc doThings(spuds: var int): int =
|
proc doThings(spuds: var int): int =
|
||||||
spuds = 24
|
spuds = 24
|
||||||
return 99
|
return 99
|
||||||
|
|
@ -103,5 +114,9 @@ suite "bug #5571":
|
||||||
check: line == "a"
|
check: line == "a"
|
||||||
doTest()
|
doTest()
|
||||||
|
|
||||||
static:
|
suite "bug #5784":
|
||||||
echo "compile end"
|
test "`or` should short circuit":
|
||||||
|
type Obj = ref object
|
||||||
|
field: int
|
||||||
|
var obj: Obj
|
||||||
|
check obj.isNil or obj.field == 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue