mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 18:32:11 +00:00
On 32-bit system the mask would have a size of 32-bit, which is smaller than the BiggestInt (usually 64-bit) it was masked against. For some reason this only affect 32-bit Windows but not 32-bit Linux. Might just be a difference in how gcc handle out of bound shifts for Windows and Linux.
501 lines
10 KiB
Nim
501 lines
10 KiB
Nim
discard """
|
|
nimout: '''
|
|
IntLit 5
|
|
proc (x: int): string => typeDesc[proc[string, int]]
|
|
proc (x: int): void => typeDesc[proc[void, int]]
|
|
proc (x: int) => typeDesc[proc[void, int]]
|
|
x => seq[int]
|
|
a
|
|
s
|
|
d
|
|
f
|
|
TTaa
|
|
TTaa
|
|
TTaa
|
|
TTaa
|
|
true
|
|
true
|
|
nil
|
|
42
|
|
false
|
|
true
|
|
@[i0, i1, i2, i3, i4]
|
|
@[tmp, tmp, tmp, tmp, tmp]
|
|
'''
|
|
|
|
output: '''
|
|
range[0 .. 100]
|
|
array[0 .. 100, int]
|
|
10
|
|
test
|
|
0o377'i8
|
|
0o000000000755'i32
|
|
1
|
|
2
|
|
3
|
|
foo1
|
|
foo2
|
|
foo3
|
|
true
|
|
false
|
|
true
|
|
false
|
|
1.0
|
|
'''
|
|
"""
|
|
|
|
|
|
import macros, parseutils
|
|
|
|
|
|
block t7723:
|
|
macro foo1(): untyped =
|
|
result = newStmtList()
|
|
result.add quote do:
|
|
proc init(foo: int, bar: typedesc[int]): int =
|
|
foo
|
|
|
|
#expandMacros:
|
|
foo1()
|
|
|
|
doAssert init(1, int) == 1
|
|
|
|
|
|
|
|
block t8706:
|
|
macro varargsLen(args:varargs[untyped]): untyped =
|
|
doAssert args.kind == nnkArglist
|
|
doAssert args.len == 0
|
|
result = newLit(args.len)
|
|
|
|
template bar(a0:varargs[untyped]): untyped =
|
|
varargsLen(a0)
|
|
|
|
template foo(x: int, a0:varargs[untyped]): untyped =
|
|
bar(a0)
|
|
|
|
doAssert foo(42) == 0
|
|
doAssert bar() == 0
|
|
|
|
|
|
|
|
block t9194:
|
|
type
|
|
Foo1 = range[0 .. 100]
|
|
Foo2 = array[0 .. 100, int]
|
|
|
|
macro get(T: typedesc): untyped =
|
|
# Get the X out of typedesc[X]
|
|
let tmp = getTypeImpl(T)
|
|
result = newStrLitNode(getTypeImpl(tmp[1]).repr)
|
|
|
|
echo Foo1.get
|
|
echo Foo2.get
|
|
|
|
|
|
|
|
block t1944:
|
|
template t(e: untyped): untyped =
|
|
macro m(eNode: untyped): untyped =
|
|
echo eNode.treeRepr
|
|
m e
|
|
|
|
t 5
|
|
|
|
|
|
block t926:
|
|
proc test(f: var NimNode) {.compileTime.} =
|
|
f = newNimNode(nnkStmtList)
|
|
f.add newCall(newIdentNode("echo"), newLit(10))
|
|
|
|
macro blah(prc: untyped): untyped =
|
|
result = prc
|
|
test(result)
|
|
|
|
proc test() {.blah.} =
|
|
echo 5
|
|
|
|
|
|
|
|
block t2211:
|
|
macro showType(t:typed): untyped =
|
|
let ty = t.getType
|
|
echo t.repr, " => ", ty.repr
|
|
|
|
showType(proc(x:int): string)
|
|
showType(proc(x:int): void)
|
|
showType(proc(x:int))
|
|
|
|
var x: seq[int]
|
|
showType(x)
|
|
|
|
|
|
|
|
block t1140:
|
|
proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} =
|
|
var splitValue: string
|
|
var read = value.parseUntil(splitValue, '$', index)
|
|
|
|
# when false:
|
|
if false:
|
|
var identifier: string
|
|
read = value.parseWhile(identifier, {}, index)
|
|
node.add newCall("add", ident("result"), newCall("$", ident(identifier)))
|
|
|
|
if splitValue.len > 0:
|
|
node.insert node.len, newCall("add", ident("result"), newStrLitNode(splitValue))
|
|
|
|
proc parse_template(node: NimNode, value: string) {.compiletime.} =
|
|
var index = 0
|
|
while index < value.len and
|
|
parse_until_symbol(node, value, index): discard
|
|
|
|
macro tmpli(body: untyped): typed =
|
|
result = newStmtList()
|
|
result.add parseExpr("result = \"\"")
|
|
result.parse_template body[1].strVal
|
|
|
|
|
|
proc actual: string {.used.} = tmpli html"""
|
|
<p>Test!</p>
|
|
"""
|
|
|
|
proc another: string {.used.} = tmpli html"""
|
|
<p>what</p>
|
|
"""
|
|
|
|
|
|
|
|
block tbugs:
|
|
type
|
|
Foo = object
|
|
s: char
|
|
|
|
iterator test2(f: string): Foo =
|
|
for i in f:
|
|
yield Foo(s: i)
|
|
|
|
macro test(): untyped =
|
|
for i in test2("asdf"):
|
|
echo i.s
|
|
|
|
test()
|
|
|
|
|
|
# bug 1297
|
|
|
|
type TType = tuple[s: string]
|
|
|
|
macro echotest(): untyped =
|
|
var t: TType
|
|
t.s = ""
|
|
t.s.add("test")
|
|
result = newCall(newIdentNode("echo"), newStrLitNode(t.s))
|
|
|
|
echotest()
|
|
|
|
# bug #1103
|
|
|
|
type
|
|
Td = tuple
|
|
a:string
|
|
b:int
|
|
|
|
proc get_data(d: Td) : string {.compileTime.} =
|
|
result = d.a # Works if a literal string is used here.
|
|
# Bugs if line A or B is active. Works with C
|
|
result &= "aa" # A
|
|
#result.add("aa") # B
|
|
#result = result & "aa" # C
|
|
|
|
macro m(s:static[Td]) : untyped =
|
|
echo get_data(s)
|
|
echo get_data(s)
|
|
result = newEmptyNode()
|
|
|
|
const s = ("TT", 3)
|
|
m(s)
|
|
m(s)
|
|
|
|
# bug #933
|
|
|
|
proc nilcheck(): NimNode {.compileTime.} =
|
|
echo(result == nil) # true
|
|
echo(result.isNil) # true
|
|
echo(repr(result)) # nil
|
|
|
|
macro testnilcheck(): untyped =
|
|
result = newNimNode(nnkStmtList)
|
|
discard nilcheck()
|
|
|
|
testnilcheck()
|
|
|
|
# bug #1323
|
|
|
|
proc calc(): array[1, int] =
|
|
result[0].inc()
|
|
result[0].inc()
|
|
|
|
const c = calc()
|
|
doAssert c[0] == 2
|
|
|
|
|
|
# bug #3046
|
|
|
|
macro sampleMacroInt(i: int): untyped =
|
|
echo i.intVal
|
|
|
|
macro sampleMacroBool(b: bool): untyped =
|
|
echo b.boolVal
|
|
|
|
sampleMacroInt(42)
|
|
sampleMacroBool(false)
|
|
sampleMacroBool(system.true)
|
|
|
|
|
|
# bug #11131
|
|
macro toRendererBug(n): untyped =
|
|
result = newLit repr(n)
|
|
|
|
echo toRendererBug(0o377'i8)
|
|
echo toRendererBug(0o755'i32)
|
|
|
|
# bug #12129
|
|
macro foobar() =
|
|
var loopVars = newSeq[NimNode](5)
|
|
for i, sym in loopVars.mpairs():
|
|
sym = ident("i" & $i)
|
|
echo loopVars
|
|
for sym in loopVars.mitems():
|
|
sym = ident("tmp")
|
|
echo loopVars
|
|
|
|
foobar()
|
|
|
|
|
|
# bug #13253
|
|
import macros
|
|
|
|
type
|
|
FooBar = object
|
|
a: seq[int]
|
|
|
|
macro genFoobar(a: static FooBar): untyped =
|
|
result = newStmtList()
|
|
for b in a.a:
|
|
result.add(newCall(bindSym"echo", newLit b))
|
|
|
|
proc foobar(a: static FooBar) =
|
|
genFoobar(a) # removing this make it work
|
|
for b in a.a:
|
|
echo "foo" & $b
|
|
|
|
proc main() =
|
|
const a: seq[int] = @[1, 2,3]
|
|
# Error: type mismatch: got <array[0..2, int]> but expected 'seq[int]'
|
|
const fb = Foobar(a: a)
|
|
foobar(fb)
|
|
main()
|
|
|
|
# bug #13484
|
|
|
|
proc defForward(id, nid: NimNode): NimNode =
|
|
result = newProc(id, @[newIdentNode("bool"), newIdentDefs(nid, newIdentNode("int"))], body=newEmptyNode())
|
|
|
|
proc defEven(evenid, oddid, nid: NimNode): NimNode =
|
|
result = quote do:
|
|
proc `evenid`(`nid`: int): bool =
|
|
if `nid` == 0:
|
|
return true
|
|
else:
|
|
return `oddid`(`nid` - 1)
|
|
|
|
proc defOdd(evenid, oddid, nid: NimNode): NimNode =
|
|
result = quote do:
|
|
proc `oddid`(`nid`: int): bool =
|
|
if `nid` == 0:
|
|
return false
|
|
else:
|
|
return `evenid`(`nid` - 1)
|
|
|
|
proc callNode(funid, param: NimNode): NimNode =
|
|
result = quote do:
|
|
`funid`(`param`)
|
|
|
|
macro testEvenOdd3(): untyped =
|
|
let
|
|
evenid = newIdentNode("even3")
|
|
oddid = newIdentNode("odd3")
|
|
nid = newIdentNode("n")
|
|
oddForward = defForward(oddid, nid)
|
|
even = defEven(evenid, oddid, nid)
|
|
odd = defOdd(evenid, oddid, nid)
|
|
callEven = callNode(evenid, newLit(42))
|
|
callOdd = callNode(oddid, newLit(42))
|
|
result = quote do:
|
|
`oddForward`
|
|
`even`
|
|
`odd`
|
|
echo `callEven`
|
|
echo `callOdd`
|
|
|
|
macro testEvenOdd4(): untyped =
|
|
let
|
|
evenid = newIdentNode("even4")
|
|
oddid = newIdentNode("odd4")
|
|
nid = newIdentNode("n")
|
|
oddForward = defForward(oddid, nid)
|
|
even = defEven(evenid, oddid, nid)
|
|
odd = defOdd(evenid, oddid, nid)
|
|
callEven = callNode(evenid, newLit(42))
|
|
callOdd = callNode(oddid, newLit(42))
|
|
# rewrite the body of proc node.
|
|
oddForward[6] = newStmtList()
|
|
result = quote do:
|
|
`oddForward`
|
|
`even`
|
|
`odd`
|
|
echo `callEven`
|
|
echo `callOdd`
|
|
|
|
macro testEvenOdd5(): untyped =
|
|
let
|
|
evenid = genSym(nskProc, "even5")
|
|
oddid = genSym(nskProc, "odd5")
|
|
nid = newIdentNode("n")
|
|
oddForward = defForward(oddid, nid)
|
|
even = defEven(evenid, oddid, nid)
|
|
odd = defOdd(evenid, oddid, nid)
|
|
callEven = callNode(evenid, newLit(42))
|
|
callOdd = callNode(oddid, newLit(42))
|
|
result = quote do:
|
|
`oddForward`
|
|
`even`
|
|
`odd`
|
|
echo `callEven`
|
|
echo `callOdd`
|
|
|
|
macro testEvenOdd6(): untyped =
|
|
let
|
|
evenid = genSym(nskProc, "even6")
|
|
oddid = genSym(nskProc, "odd6")
|
|
nid = newIdentNode("n")
|
|
oddForward = defForward(oddid, nid)
|
|
even = defEven(evenid, oddid, nid)
|
|
odd = defOdd(evenid, oddid, nid)
|
|
callEven = callNode(evenid, newLit(42))
|
|
callOdd = callNode(oddid, newLit(42))
|
|
# rewrite the body of proc node.
|
|
oddForward[6] = newStmtList()
|
|
result = quote do:
|
|
`oddForward`
|
|
`even`
|
|
`odd`
|
|
echo `callEven`
|
|
echo `callOdd`
|
|
|
|
# it works
|
|
testEvenOdd3()
|
|
|
|
# it causes an error (redefinition of odd4), which is correct
|
|
assert not compiles testEvenOdd4()
|
|
|
|
# it caused an error (still forwarded: odd5)
|
|
testEvenOdd5()
|
|
|
|
# it works, because the forward decl and definition share the symbol and the compiler is forgiving here
|
|
#testEvenOdd6() #Don't test it though, the compiler may become more strict in the future
|
|
|
|
# bug #15385
|
|
var captured_funcs {.compileTime.}: seq[NimNode] = @[]
|
|
|
|
macro aad*(fns: varargs[typed]): typed =
|
|
result = newStmtList()
|
|
for fn in fns:
|
|
captured_funcs.add fn[0]
|
|
result.add fn
|
|
|
|
func exp*(x: float): float ## get different error if you remove forward declaration
|
|
|
|
func exp*(x: float): float {.aad.} =
|
|
var x1 = min(max(x, -708.4), 709.8)
|
|
var result: float ## looks weird because it is taken from template expansion
|
|
result = x1 + 1.0
|
|
result
|
|
|
|
template check_accuracy(f: untyped, rng: Slice[float], n: int, verbose = false): auto =
|
|
|
|
proc check_accuracy: tuple[avg_ulp: float, max_ulp: int] {.gensym.} =
|
|
let k = (rng.b - rng.a) / (float) n
|
|
var
|
|
res, x: float
|
|
i, max_ulp = 0
|
|
avg_ulp = 0.0
|
|
|
|
x = rng.a
|
|
while (i < n):
|
|
res = f(x)
|
|
i.inc
|
|
x = x + 0.001
|
|
(avg_ulp, max_ulp)
|
|
check_accuracy()
|
|
|
|
discard check_accuracy(exp, -730.0..709.4, 4)
|
|
|
|
# And without forward decl
|
|
macro aad2*(fns: varargs[typed]): typed =
|
|
result = newStmtList()
|
|
for fn in fns:
|
|
captured_funcs.add fn[0]
|
|
result.add fn
|
|
|
|
func exp2*(x: float): float {.aad2.} =
|
|
var x1 = min(max(x, -708.4), 709.8)
|
|
var result: float ## looks weird because it is taken from template expansion
|
|
result = x1 + 1.0
|
|
result
|
|
|
|
template check_accuracy2(f: untyped, rng: Slice[float], n: int, verbose = false): auto =
|
|
|
|
proc check_accuracy2: tuple[avg_ulp: float, max_ulp: int] {.gensym.} =
|
|
let k = (rng.b - rng.a) / (float) n
|
|
var
|
|
res, x: float
|
|
i, max_ulp = 0
|
|
avg_ulp = 0.0
|
|
|
|
x = rng.a
|
|
while (i < n):
|
|
res = f(x)
|
|
i.inc
|
|
x = x + 0.001
|
|
(avg_ulp, max_ulp)
|
|
check_accuracy2()
|
|
|
|
discard check_accuracy2(exp2, -730.0..709.4, 4)
|
|
|
|
# And minimized:
|
|
macro aadMin(fn: typed): typed = fn
|
|
|
|
func expMin: float
|
|
|
|
func expMin: float {.aadMin.} = 1
|
|
|
|
echo expMin()
|
|
|
|
|
|
# issue #15389
|
|
block double_sem_for_procs:
|
|
|
|
macro aad(fns: varargs[typed]): typed =
|
|
result = newStmtList()
|
|
for fn in fns:
|
|
result.add fn
|
|
|
|
func exp(x: float): float {.aad.} =
|
|
var x1 = min(max(x, -708.4), 709.8)
|
|
if x1 > 0.0:
|
|
return x1 + 1.0
|
|
result = 10.0
|
|
|
|
discard exp(5.0) |