Allow void macro result (#11286)

* allow void macro result
* add test for void macro result type
This commit is contained in:
Arne Döring 2019-05-21 21:31:40 +02:00 • committed by Andreas Rumpf
commit f94ec363ab
25 changed files with 143 additions and 60 deletions

View file

@ -1,7 +1,7 @@
# bug #1679
import macros, tables, hashes
proc hash(v: NimNode): Hash = 4 # performance is for suckers
macro test(body: untyped): typed =
macro test(body: untyped) =
var a = initCountTable[NimNode]()
a.inc(body)

View file

@ -46,7 +46,7 @@ block ttemplate:
for name, value in (n: "v").fieldPairs:
echo name
template wrapper: typed =
template wrapper(): void =
for name, value in (n: "v").fieldPairs:
echo name
wrapper()

View file

@ -12,7 +12,7 @@ import unittest, macros
# bug #4555
macro memo(n: untyped): typed =
macro memo(n: untyped) =
result = n
proc fastFib(n: int): int {.memo.} = 40

View file

@ -32,7 +32,7 @@ proc foo(): seq[NimNode] {.compiletime.} =
result.add test()
result.add parseExpr("echo(5+56)")
macro bar(): typed =
macro bar() =
result = newNimNode(nnkStmtList)
let x = foo()
for xx in x:

View file

@ -22,7 +22,7 @@ proc symToIdent(x: NimNode): NimNode =
result.add symToIdent(c)
# check getTypeInst and getTypeImpl for given symbol x
macro testX(x,inst0: typed; recurse: static[bool]; implX: typed): typed =
macro testX(x,inst0: typed; recurse: static[bool]; implX: typed) =
# check that getTypeInst(x) equals inst0
let inst = x.getTypeInst
let instr = inst.symToIdent.treeRepr

View file

@ -38,7 +38,7 @@ macro importImpl_forward(name, returns: untyped): untyped =
decls.add res
echo(repr(res))
macro importImpl(name, returns, body: untyped): typed =
macro importImpl(name, returns, body: untyped) =
#var res = getAST(importImpl_forward(name, returns))
discard getAST(importImpl_forward(name, returns))
var res = copyNimTree(decls[decls.high])
@ -46,7 +46,7 @@ macro importImpl(name, returns, body: untyped): typed =
echo repr(res)
impls.add res
macro okayy: typed =
macro okayy() =
result = newNimNode(nnkStmtList)
for node in decls: result.add node
for node in impls: result.add node

75
tests/macros/tmacro6.nim Normal file
View file

@ -0,0 +1,75 @@
discard """
errormsg: "expression '123' is of type 'int literal(123)' and has to be discarded"
line: 71
"""
import macros
proc foo(a,b,c: int): int =
result += a
result += b
result += c
macro bar(a,b,c: int): int =
result = newCall(ident"echo")
result.add a
result.add b
result.add c
macro baz(a,b,c: int): int =
let stmt = nnkStmtListExpr.newTree()
stmt.add newCall(ident"echo", a)
stmt.add newCall(ident"echo", b)
stmt.add newCall(ident"echo", c)
stmt.add newLit(123)
return c
# test no result type with explicit return
macro baz2(a,b,c: int) =
let stmt = nnkStmtListExpr.newTree()
stmt.add newCall(ident"echo", a)
stmt.add newCall(ident"echo", b)
stmt.add newCall(ident"echo", c)
return stmt
# test explicit void type with explicit return
macro baz3(a,b,c: int): void =
let stmt = nnkStmtListExpr.newTree()
stmt.add newCall(ident"echo", a)
stmt.add newCall(ident"echo", b)
stmt.add newCall(ident"echo", c)
return stmt
# test no result type with result variable
macro baz4(a,b,c: int) =
result = nnkStmtListExpr.newTree()
result.add newCall(ident"echo", a)
result.add newCall(ident"echo", b)
result.add newCall(ident"echo", c)
# test explicit void type with result variable
macro baz5(a,b,c: int): void =
let result = nnkStmtListExpr.newTree()
result.add newCall(ident"echo", a)
result.add newCall(ident"echo", b)
result.add newCall(ident"echo", c)
macro foobar1(): int =
result = quote do:
echo "Hello World"
1337
echo foobar1()
# this should create an error message, because 123 has to be discarded.
macro foobar2() =
result = quote do:
echo "Hello World"
123
echo foobar2()

View file

@ -18,15 +18,16 @@ case_token: inc i
#bug #488
macro foo: typed =
macro foo() =
var exp = newCall("whatwhat", newIntLitNode(1))
if compiles(getAst(exp)): return exp
if compiles(getAst(exp)):
return exp
else: echo "Does not compute! (test OK)"
foo()
#------------------------------------
# bug #8287
# bug #8287
type MyString = distinct string
proc `$` (c: MyString): string {.borrow.}
@ -37,7 +38,7 @@ proc `!!` (c: cstring): int =
proc f(name: MyString): int =
!! $ name
macro repr_and_parse(fn: typed): typed =
macro repr_and_parse(fn: typed) =
let fn_impl = fn.getImpl
fn_impl.name = genSym(nskProc, $fn_impl.name)
echo fn_impl.repr
@ -51,7 +52,7 @@ repr_and_parse(f)
#------------------------------------
# bugs #8343 and #8344
# bugs #8343 and #8344
proc one_if_proc(x, y : int): int =
if x < y: result = x
else: result = y
@ -76,7 +77,7 @@ proc test_cond_stmtlist(x, y: int): int =
#------------------------------------
# bug #8762
proc t2(a, b: int): int =
proc t2(a, b: int): int =
`+`(a, b)
@ -92,23 +93,23 @@ proc fn2(x, y: float): float =
proc fn3(x, y: int): bool =
(((x and 3) div 4) or (x mod (y xor -1))) == 0 or y notin [1,2]
proc fn4(x: int): int =
proc fn4(x: int): int =
if x mod 2 == 0: return x + 2
else: return 0
#------------------------------------
# bug #10807
proc fn_unsafeaddr(x: int): int =
proc fn_unsafeaddr(x: int): int =
cast[int](unsafeAddr(x))
static:
echo fn_unsafeaddr.repr_to_string
echo fn_unsafeaddr.repr_to_string
let fn1s = "proc fn1(x, y: int): int =\n result = 2 * (x + y)\n"
let fn2s = "proc fn2(x, y: float): float =\n result = (y + 2 * x) / (x - y)\n"
let fn3s = "proc fn3(x, y: int): bool =\n result = ((x and 3) div 4 or x mod (y xor -1)) == 0 or not contains([1, 2], y)\n"
let fn4s = "proc fn4(x: int): int =\n if x mod 2 == 0:\n return x + 2\n else:\n return 0\n"
let fnAddr = "proc fn_unsafeaddr(x: int): int =\n result = cast[int](unsafeAddr(x))\n"
doAssert fn1.repr_to_string == fn1s
doAssert fn2.repr_to_string == fn2s
doAssert fn3.repr_to_string == fn3s
@ -134,4 +135,3 @@ repr_and_parse(test_block)
repr_and_parse(test_cond_stmtlist)
repr_and_parse(t2)
repr_and_parse(test_pure_enums)

View file

@ -34,7 +34,7 @@ block t898:
block t7528:
macro bar(n: untyped): typed =
macro bar(n: untyped) =
result = newNimNode(nnkStmtList, n)
result.add(newCall("write", newIdentNode("stdout"), n))

View file

@ -77,7 +77,7 @@ block generic_templates:
block tgetast_typeliar:
proc error(s: string) = quit s
macro assertOrReturn(condition: bool; message: string): typed =
macro assertOrReturn2(condition: bool; message: string) =
var line = condition.lineInfo()
result = quote do:
block:
@ -86,8 +86,10 @@ block tgetast_typeliar:
return
macro assertOrReturn(condition: bool): typed =
var message = condition.toStrLit()
result = getAst assertOrReturn(condition, message)
var message : NimNode = newLit(condition.repr)
# echo message
result = getAst assertOrReturn2(condition, message)
echo result.repr
proc point(size: int16): tuple[x, y: int16] =
# returns random point in square area with given `size`
@ -245,7 +247,3 @@ block ttempl5:
block templreturntype:
template `=~` (a: int, b: int): bool = false
var foo = 2 =~ 3

View file

@ -18,7 +18,7 @@ proc initOpts(): set[nlOptions] =
const cOpts = initOpts()
macro nlo(): typed =
macro nlo() =
nlOpts.incl(nloNone)
nlOpts.excl(nloDebug)
result = newEmptyNode()

View file

@ -24,7 +24,7 @@ bb
const s = @[1,2,3]
macro foo: typed =
macro foo() =
for e in s:
echo e
@ -55,7 +55,7 @@ static:
var m2: TData = data
for x in m2.numbers: echo x
macro ff(d: static[TData]): typed =
macro ff(d: static[TData]) =
for x in d.letters:
echo x

View file

@ -20,7 +20,7 @@ nimout: '''
#bug #2514
macro foo(): typed =
macro foo() =
var x = 8'u8
var y = 9'u16
var z = 17'u32
@ -58,7 +58,7 @@ macro foo(): typed =
var zz = 0x7FFFFFFF'u32
echo zz
macro foo2(): typed =
macro foo2() =
var xx = 0x7FFFFFFFFFFFFFFF
echo xx