Merge tests into a larger file (part 8 of ∞) (#9583)
* merge tuple tests * merge trmacros tests * merge template tests
This commit is contained in:
parent
c735b75f6f
commit
66a76d3165
51 changed files with 862 additions and 835 deletions
|
|
@ -1,2 +0,0 @@
|
||||||
import i2416
|
|
||||||
i2416()
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "8.0"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2057
|
|
||||||
|
|
||||||
proc mpf_get_d(x: int): float = float(x)
|
|
||||||
proc mpf_cmp_d(a: int; b: float): int = 0
|
|
||||||
|
|
||||||
template toFloatHelper(result, tooSmall, tooLarge: untyped) =
|
|
||||||
result = mpf_get_d(a)
|
|
||||||
if result == 0.0 and mpf_cmp_d(a,0.0) != 0:
|
|
||||||
tooSmall
|
|
||||||
if result == Inf:
|
|
||||||
tooLarge
|
|
||||||
|
|
||||||
proc toFloat*(a: int): float =
|
|
||||||
toFloatHelper(result) do:
|
|
||||||
raise newException(ValueError, "number too small")
|
|
||||||
do:
|
|
||||||
raise newException(ValueError, "number too large")
|
|
||||||
|
|
||||||
echo toFloat(8)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
discard """
|
|
||||||
output: 33
|
|
||||||
"""
|
|
||||||
|
|
||||||
import mcan_access_hidden_field
|
|
||||||
|
|
||||||
var myfoo = createFoo(33, 44)
|
|
||||||
|
|
||||||
echo myfoo.geta
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
# bug #2629
|
|
||||||
import sequtils, os
|
|
||||||
|
|
||||||
template glob_rst(basedir: string = ""): untyped =
|
|
||||||
if baseDir.len == 0:
|
|
||||||
to_seq(walk_files("*.rst"))
|
|
||||||
else:
|
|
||||||
to_seq(walk_files(basedir/"*.rst"))
|
|
||||||
|
|
||||||
let
|
|
||||||
rst_files = concat(glob_rst(), glob_rst("docs"))
|
|
||||||
|
|
||||||
when isMainModule: echo rst_files
|
|
||||||
209
tests/template/template_issues.nim
Normal file
209
tests/template/template_issues.nim
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
@[]
|
||||||
|
5
|
||||||
|
0
|
||||||
|
a
|
||||||
|
hi
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import macros, json
|
||||||
|
|
||||||
|
|
||||||
|
block t2057:
|
||||||
|
proc mpf_get_d(x: int): float = float(x)
|
||||||
|
proc mpf_cmp_d(a: int; b: float): int = 0
|
||||||
|
|
||||||
|
template toFloatHelper(result, tooSmall, tooLarge: untyped) =
|
||||||
|
result = mpf_get_d(a)
|
||||||
|
if result == 0.0 and mpf_cmp_d(a,0.0) != 0:
|
||||||
|
tooSmall
|
||||||
|
if result == Inf:
|
||||||
|
tooLarge
|
||||||
|
|
||||||
|
proc toFloat(a: int): float =
|
||||||
|
toFloatHelper(result) do:
|
||||||
|
raise newException(ValueError, "number too small")
|
||||||
|
do:
|
||||||
|
raise newException(ValueError, "number too large")
|
||||||
|
|
||||||
|
doAssert toFloat(8) == 8.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import sequtils, os
|
||||||
|
block t2629:
|
||||||
|
template glob_rst(basedir: string = ""): untyped =
|
||||||
|
if baseDir.len == 0:
|
||||||
|
to_seq(walk_files("*.rst"))
|
||||||
|
else:
|
||||||
|
to_seq(walk_files(basedir/"*.rst"))
|
||||||
|
|
||||||
|
let rst_files = concat(glob_rst(), glob_rst("docs"))
|
||||||
|
|
||||||
|
when isMainModule: echo rst_files
|
||||||
|
|
||||||
|
|
||||||
|
block t5417:
|
||||||
|
macro genBody: untyped =
|
||||||
|
let sbx = genSym(nskLabel, "test")
|
||||||
|
when true:
|
||||||
|
result = quote do:
|
||||||
|
block `sbx`:
|
||||||
|
break `sbx`
|
||||||
|
else:
|
||||||
|
template foo(s1, s2) =
|
||||||
|
block s1:
|
||||||
|
break s2
|
||||||
|
result = getAst foo(sbx, sbx)
|
||||||
|
|
||||||
|
proc test() =
|
||||||
|
genBody()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t909:
|
||||||
|
template baz() =
|
||||||
|
proc bar() =
|
||||||
|
var x = 5
|
||||||
|
iterator foo(): int {.closure.} =
|
||||||
|
echo x
|
||||||
|
var y = foo
|
||||||
|
discard y()
|
||||||
|
|
||||||
|
macro test(): untyped =
|
||||||
|
result = getAst(baz())
|
||||||
|
|
||||||
|
test()
|
||||||
|
bar()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t993:
|
||||||
|
type PNode = ref object of RootObj
|
||||||
|
|
||||||
|
template litNode(name, ty) =
|
||||||
|
type name = ref object of PNode
|
||||||
|
val: ty
|
||||||
|
litNode PIntNode, int
|
||||||
|
|
||||||
|
template withKey(j: JsonNode; key: string; varname,
|
||||||
|
body: untyped): typed =
|
||||||
|
if j.hasKey(key):
|
||||||
|
let varname{.inject.}= j[key]
|
||||||
|
block:
|
||||||
|
body
|
||||||
|
|
||||||
|
var j = parsejson("{\"zzz\":1}")
|
||||||
|
withkey(j, "foo", x):
|
||||||
|
echo(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t1337:
|
||||||
|
template someIt(a, pred): untyped =
|
||||||
|
var it {.inject.} = 0
|
||||||
|
pred
|
||||||
|
|
||||||
|
proc aProc(n: auto) =
|
||||||
|
n.someIt(echo(it))
|
||||||
|
|
||||||
|
aProc(89)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import mlt
|
||||||
|
block t4564:
|
||||||
|
type Bar = ref object of RootObj
|
||||||
|
proc foo(a: Bar): int = 0
|
||||||
|
var a: Bar
|
||||||
|
let b = a.foo() > 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t8052:
|
||||||
|
type
|
||||||
|
UintImpl[N: static[int], T: SomeUnsignedInt] = object
|
||||||
|
raw_data: array[N, T]
|
||||||
|
|
||||||
|
template genLoHi(TypeImpl: untyped): untyped =
|
||||||
|
template loImpl[N: static[int], T: SomeUnsignedInt](dst: TypeImpl[N div 2, T], src: TypeImpl[N, T]) =
|
||||||
|
let halfSize = N div 2
|
||||||
|
for i in 0 ..< halfSize:
|
||||||
|
dst.raw_data[i] = src.raw_data[i]
|
||||||
|
|
||||||
|
proc lo[N: static[int], T: SomeUnsignedInt](x: TypeImpl[N,T]): TypeImpl[N div 2, T] {.inline.}=
|
||||||
|
loImpl(result, x)
|
||||||
|
|
||||||
|
genLoHi(UintImpl)
|
||||||
|
|
||||||
|
var a: UintImpl[4, uint32]
|
||||||
|
|
||||||
|
a.raw_data = [1'u32, 2'u32, 3'u32, 4'u32]
|
||||||
|
doAssert a.lo.raw_data.len == 2
|
||||||
|
doAssert a.lo.raw_data[0] == 1
|
||||||
|
doAssert a.lo.raw_data[1] == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t2585:
|
||||||
|
type
|
||||||
|
RenderPass = object
|
||||||
|
state: ref int
|
||||||
|
RenderData = object
|
||||||
|
fb: int
|
||||||
|
walls: seq[RenderPass]
|
||||||
|
Mat2 = int
|
||||||
|
Vector2[T] = T
|
||||||
|
Pixels=int
|
||||||
|
|
||||||
|
template use(fb: int, st: untyped): untyped =
|
||||||
|
echo "a ", $fb
|
||||||
|
st
|
||||||
|
echo "a ", $fb
|
||||||
|
|
||||||
|
proc render(rdat: var RenderData; passes: var openarray[RenderPass]; proj: Mat2;
|
||||||
|
indexType = 1) =
|
||||||
|
for i in 0 ..< len(passes):
|
||||||
|
echo "blah ", repr(passes[i])
|
||||||
|
|
||||||
|
proc render2(rdat: var RenderData; screenSz: Vector2[Pixels]; proj: Mat2) =
|
||||||
|
use rdat.fb:
|
||||||
|
render(rdat, rdat.walls, proj, 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4292:
|
||||||
|
template foo(s: string): string = s
|
||||||
|
proc variadicProc(v: varargs[string, foo]) = echo v[0]
|
||||||
|
variadicProc("a")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t2670:
|
||||||
|
template testTemplate(b: bool): typed =
|
||||||
|
when b:
|
||||||
|
var a = "hi"
|
||||||
|
else:
|
||||||
|
var a = 5
|
||||||
|
echo a
|
||||||
|
testTemplate(true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block t4097:
|
||||||
|
var i {.compileTime.} = 2
|
||||||
|
|
||||||
|
template defineId(t: typedesc) =
|
||||||
|
const id {.genSym.} = i
|
||||||
|
static: inc(i)
|
||||||
|
proc idFor(T: typedesc[t]): int {.inline, raises: [].} = id
|
||||||
|
|
||||||
|
defineId(int8)
|
||||||
|
defineId(int16)
|
||||||
|
|
||||||
|
doAssert idFor(int8) == 2
|
||||||
|
doAssert idFor(int16) == 3
|
||||||
251
tests/template/template_various.nim
Normal file
251
tests/template/template_various.nim
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
i2416
|
||||||
|
33
|
||||||
|
foo55
|
||||||
|
foo8.0
|
||||||
|
fooaha
|
||||||
|
bar7
|
||||||
|
immediate
|
||||||
|
10
|
||||||
|
4true
|
||||||
|
132
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import i2416
|
||||||
|
i2416()
|
||||||
|
|
||||||
|
|
||||||
|
import mcan_access_hidden_field
|
||||||
|
var myfoo = createFoo(33, 44)
|
||||||
|
echo myfoo.geta
|
||||||
|
|
||||||
|
|
||||||
|
import mgensym_generic_cross_module
|
||||||
|
foo(55)
|
||||||
|
foo 8.0
|
||||||
|
foo "aha"
|
||||||
|
bar 7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block generic_templates:
|
||||||
|
type
|
||||||
|
SomeObj = object of RootObj
|
||||||
|
Foo[T, U] = object
|
||||||
|
x: T
|
||||||
|
y: U
|
||||||
|
|
||||||
|
template someTemplate[T](): tuple[id: int32, obj: T] =
|
||||||
|
var result: tuple[id: int32, obj: T] = (0'i32, T())
|
||||||
|
result
|
||||||
|
|
||||||
|
let ret = someTemplate[SomeObj]()
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/7829
|
||||||
|
proc inner[T](): int =
|
||||||
|
discard
|
||||||
|
|
||||||
|
template outer[A](): untyped =
|
||||||
|
inner[A]()
|
||||||
|
|
||||||
|
template outer[B](x: int): untyped =
|
||||||
|
inner[B]()
|
||||||
|
|
||||||
|
var i1 = outer[int]()
|
||||||
|
var i2 = outer[int](i1)
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/7883
|
||||||
|
template t1[T: int|int64](s: string): T =
|
||||||
|
var t: T
|
||||||
|
t
|
||||||
|
|
||||||
|
template t1[T: int|int64](x: int, s: string): T =
|
||||||
|
var t: T
|
||||||
|
t
|
||||||
|
|
||||||
|
var i3: int = t1[int]("xx")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tgetast_typeliar:
|
||||||
|
proc error(s: string) = quit s
|
||||||
|
|
||||||
|
macro assertOrReturn(condition: bool; message: string): typed =
|
||||||
|
var line = condition.lineInfo()
|
||||||
|
result = quote do:
|
||||||
|
block:
|
||||||
|
if not likely(`condition`):
|
||||||
|
error("Assertion failed: " & $(`message`) & "\n" & `line`)
|
||||||
|
return
|
||||||
|
|
||||||
|
macro assertOrReturn(condition: bool): typed =
|
||||||
|
var message = condition.toStrLit()
|
||||||
|
result = getAst assertOrReturn(condition, message)
|
||||||
|
|
||||||
|
proc point(size: int16): tuple[x, y: int16] =
|
||||||
|
# returns random point in square area with given `size`
|
||||||
|
assertOrReturn size > 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
MyFloat = object
|
||||||
|
val: float
|
||||||
|
converter to_myfloat(x: float): MyFloat {.inline.} =
|
||||||
|
MyFloat(val: x)
|
||||||
|
|
||||||
|
block pattern_with_converter:
|
||||||
|
proc `+`(x1, x2: MyFloat): MyFloat =
|
||||||
|
MyFloat(val: x1.val + x2.val)
|
||||||
|
|
||||||
|
proc `*`(x1, x2: MyFloat): MyFloat =
|
||||||
|
MyFloat(val: x1.val * x2.val)
|
||||||
|
|
||||||
|
template optMul{`*`(a, 2.0)}(a: MyFloat): MyFloat =
|
||||||
|
a + a
|
||||||
|
|
||||||
|
func floatMyFloat(x: MyFloat): MyFloat =
|
||||||
|
result = x * 2.0
|
||||||
|
|
||||||
|
func floatDouble(x: float): float =
|
||||||
|
result = x * 2.0
|
||||||
|
|
||||||
|
doAssert floatDouble(5) == 10.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block prefer_immediate:
|
||||||
|
# Test that immediate templates are preferred over non-immediate templates
|
||||||
|
|
||||||
|
template foo(a, b: untyped) = echo "foo expr"
|
||||||
|
template foo(a, b: int) = echo "foo int"
|
||||||
|
template foo(a, b: float) = echo "foo float"
|
||||||
|
template foo(a, b: string) = echo "foo string"
|
||||||
|
template foo(a, b: untyped) {.immediate.} = echo "immediate"
|
||||||
|
template foo(a, b: bool) = echo "foo bool"
|
||||||
|
template foo(a, b: char) = echo "foo char"
|
||||||
|
|
||||||
|
foo(undeclaredIdentifier, undeclaredIdentifier2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block procparshadow:
|
||||||
|
template something(name: untyped) =
|
||||||
|
proc name(x: int) =
|
||||||
|
var x = x # this one should not be rejected by the compiler (#5225)
|
||||||
|
echo x
|
||||||
|
|
||||||
|
something(what)
|
||||||
|
what(10)
|
||||||
|
|
||||||
|
# bug #4750
|
||||||
|
type
|
||||||
|
O = object
|
||||||
|
i: int
|
||||||
|
OP = ptr O
|
||||||
|
|
||||||
|
template alf(p: pointer): untyped =
|
||||||
|
cast[OP](p)
|
||||||
|
|
||||||
|
proc t1(al: pointer) =
|
||||||
|
var o = alf(al)
|
||||||
|
|
||||||
|
proc t2(alf: pointer) =
|
||||||
|
var x = alf
|
||||||
|
var o = alf(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block symchoicefield:
|
||||||
|
type Foo = object
|
||||||
|
len: int
|
||||||
|
|
||||||
|
var f = Foo(len: 40)
|
||||||
|
|
||||||
|
template getLen(f: Foo): int = f.len
|
||||||
|
|
||||||
|
doAssert f.getLen == 40
|
||||||
|
# This fails, because `len` gets the nkOpenSymChoice
|
||||||
|
# treatment inside the template early pass and then
|
||||||
|
# it can't be recognized as a field anymore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import os, times
|
||||||
|
include "sunset.tmpl"
|
||||||
|
block ttempl:
|
||||||
|
const
|
||||||
|
tabs = [["home", "index"],
|
||||||
|
["news", "news"],
|
||||||
|
["documentation", "documentation"],
|
||||||
|
["download", "download"],
|
||||||
|
["FAQ", "question"],
|
||||||
|
["links", "links"]]
|
||||||
|
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
for item in items(tabs):
|
||||||
|
var content = $i
|
||||||
|
var file: File
|
||||||
|
if open(file, changeFileExt(item[1], "html"), fmWrite):
|
||||||
|
write(file, sunsetTemplate(current=item[1], ticker="", content=content,
|
||||||
|
tabs=tabs))
|
||||||
|
close(file)
|
||||||
|
else:
|
||||||
|
write(stdout, "cannot open file for writing")
|
||||||
|
inc(i)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block ttempl4:
|
||||||
|
template `:=`(name, val: untyped): typed =
|
||||||
|
var name = val
|
||||||
|
|
||||||
|
ha := 1 * 4
|
||||||
|
hu := "ta-da" == "ta-da"
|
||||||
|
echo ha, hu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import mtempl5
|
||||||
|
block ttempl5:
|
||||||
|
echo templ()
|
||||||
|
|
||||||
|
#bug #892
|
||||||
|
proc parse_to_close(value: string, index: int, open='(', close=')'): int =
|
||||||
|
discard
|
||||||
|
|
||||||
|
# Call parse_to_close
|
||||||
|
template get_next_ident: typed =
|
||||||
|
discard "{something}".parse_to_close(0, open = '{', close = '}')
|
||||||
|
|
||||||
|
get_next_ident()
|
||||||
|
|
||||||
|
#identifier expected, but found '(open|open|open)'
|
||||||
|
#bug #880 (also example in the manual!)
|
||||||
|
template typedef(name: untyped, typ: typedesc) =
|
||||||
|
type
|
||||||
|
`T name` {.inject.} = typ
|
||||||
|
`P name` {.inject.} = ref `T name`
|
||||||
|
|
||||||
|
typedef(myint, int)
|
||||||
|
var x: PMyInt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block templreturntype:
|
||||||
|
template `=~` (a: int, b: int): bool = false
|
||||||
|
var foo = 2 =~ 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
type
|
|
||||||
SomeObj = object of RootObj
|
|
||||||
|
|
||||||
Foo[T, U] = object
|
|
||||||
x: T
|
|
||||||
y: U
|
|
||||||
|
|
||||||
template someTemplate[T](): tuple[id: int32, obj: T] =
|
|
||||||
var result: tuple[id: int32, obj: T] = (0'i32, T())
|
|
||||||
result
|
|
||||||
|
|
||||||
let ret = someTemplate[SomeObj]()
|
|
||||||
|
|
||||||
# https://github.com/nim-lang/Nim/issues/7829
|
|
||||||
proc inner*[T](): int =
|
|
||||||
discard
|
|
||||||
|
|
||||||
template outer*[A](): untyped =
|
|
||||||
inner[A]()
|
|
||||||
|
|
||||||
template outer*[B](x: int): untyped =
|
|
||||||
inner[B]()
|
|
||||||
|
|
||||||
var i1 = outer[int]()
|
|
||||||
var i2 = outer[int](i1)
|
|
||||||
|
|
||||||
# https://github.com/nim-lang/Nim/issues/7883
|
|
||||||
template t1[T: int|int64](s: string): T =
|
|
||||||
var t: T
|
|
||||||
t
|
|
||||||
|
|
||||||
template t1[T: int|int64](x: int, s: string): T =
|
|
||||||
var t: T
|
|
||||||
t
|
|
||||||
|
|
||||||
var i3: int = t1[int]("xx")
|
|
||||||
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''foo55
|
|
||||||
foo8.0
|
|
||||||
fooaha
|
|
||||||
bar7'''
|
|
||||||
"""
|
|
||||||
# bug #5419
|
|
||||||
import mgensym_generic_cross_module
|
|
||||||
|
|
||||||
foo(55)
|
|
||||||
foo 8.0
|
|
||||||
foo "aha"
|
|
||||||
bar 7
|
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
# bug #5417
|
|
||||||
import macros
|
|
||||||
|
|
||||||
macro genBody: untyped =
|
|
||||||
let sbx = genSym(nskLabel, "test")
|
|
||||||
when true:
|
|
||||||
result = quote do:
|
|
||||||
block `sbx`:
|
|
||||||
break `sbx`
|
|
||||||
else:
|
|
||||||
template foo(s1, s2) =
|
|
||||||
block s1:
|
|
||||||
break s2
|
|
||||||
result = getAst foo(sbx, sbx)
|
|
||||||
|
|
||||||
proc test() =
|
|
||||||
genBody()
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
# just ensure this keeps compiling:
|
|
||||||
|
|
||||||
import macros
|
|
||||||
|
|
||||||
proc error(s: string) = quit s
|
|
||||||
|
|
||||||
macro assertOrReturn*(condition: bool; message: string): typed =
|
|
||||||
var line = condition.lineInfo()
|
|
||||||
result = quote do:
|
|
||||||
block:
|
|
||||||
if not likely(`condition`):
|
|
||||||
error("Assertion failed: " & $(`message`) & "\n" & `line`)
|
|
||||||
return
|
|
||||||
|
|
||||||
macro assertOrReturn*(condition: bool): typed =
|
|
||||||
var message = condition.toStrLit()
|
|
||||||
result = getAst assertOrReturn(condition, message)
|
|
||||||
|
|
||||||
proc point*(size: int16): tuple[x, y: int16] =
|
|
||||||
# returns random point in square area with given `size`
|
|
||||||
|
|
||||||
assertOrReturn size > 0
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import macros
|
|
||||||
|
|
||||||
template baz() =
|
|
||||||
proc bar() =
|
|
||||||
var x = 5
|
|
||||||
iterator foo(): int {.closure.} =
|
|
||||||
echo x
|
|
||||||
var y = foo
|
|
||||||
discard y()
|
|
||||||
|
|
||||||
macro test(): untyped =
|
|
||||||
result = getAst(baz())
|
|
||||||
echo(treeRepr(result))
|
|
||||||
|
|
||||||
test()
|
|
||||||
bar()
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
type PNode* = ref object of RootObj
|
|
||||||
|
|
||||||
template litNode(name, ty) =
|
|
||||||
type name* = ref object of PNode
|
|
||||||
val*: ty
|
|
||||||
litNode PIntNode, int
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
template withKey*(j: JsonNode; key: string; varname,
|
|
||||||
body: untyped): typed =
|
|
||||||
if j.hasKey(key):
|
|
||||||
let varname{.inject.}= j[key]
|
|
||||||
block:
|
|
||||||
body
|
|
||||||
|
|
||||||
var j = parsejson("{\"zzz\":1}")
|
|
||||||
withkey(j, "foo", x):
|
|
||||||
echo(x)
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
# bug #1337
|
|
||||||
|
|
||||||
template someIt(a, pred): untyped =
|
|
||||||
var it {.inject.} = 0
|
|
||||||
pred
|
|
||||||
|
|
||||||
proc aProc(n: auto) =
|
|
||||||
n.someIt(echo(it))
|
|
||||||
|
|
||||||
aProc(89)
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
import mlt
|
|
||||||
# bug #4564
|
|
||||||
type Bar* = ref object of RootObj
|
|
||||||
proc foo(a: Bar): int = 0
|
|
||||||
var a: Bar
|
|
||||||
let b = a.foo() > 0
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# bug #8052
|
|
||||||
|
|
||||||
type
|
|
||||||
UintImpl*[N: static[int], T: SomeUnsignedInt] = object
|
|
||||||
raw_data*: array[N, T]
|
|
||||||
|
|
||||||
template genLoHi(TypeImpl: untyped): untyped =
|
|
||||||
template loImpl[N: static[int], T: SomeUnsignedInt](dst: TypeImpl[N div 2, T], src: TypeImpl[N, T]) =
|
|
||||||
let halfSize = N div 2
|
|
||||||
for i in 0 ..< halfSize:
|
|
||||||
dst.raw_data[i] = src.raw_data[i]
|
|
||||||
|
|
||||||
proc lo*[N: static[int], T: SomeUnsignedInt](x: TypeImpl[N,T]): TypeImpl[N div 2, T] {.inline.}=
|
|
||||||
loImpl(result, x)
|
|
||||||
|
|
||||||
genLoHi(UintImpl)
|
|
||||||
|
|
||||||
var a: UintImpl[4, uint32]
|
|
||||||
|
|
||||||
a.raw_data = [1'u32, 2'u32, 3'u32, 4'u32]
|
|
||||||
assert a.lo.raw_data.len == 2
|
|
||||||
assert a.lo.raw_data[0] == 1
|
|
||||||
assert a.lo.raw_data[1] == 2
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
discard """
|
|
||||||
output: 10.0
|
|
||||||
"""
|
|
||||||
|
|
||||||
type
|
|
||||||
MyFloat = object
|
|
||||||
val: float
|
|
||||||
|
|
||||||
converter to_myfloat*(x: float): MyFloat {.inline.} =
|
|
||||||
MyFloat(val: x)
|
|
||||||
|
|
||||||
proc `+`(x1, x2: MyFloat): MyFloat =
|
|
||||||
MyFloat(val: x1.val + x2.val)
|
|
||||||
|
|
||||||
proc `*`(x1, x2: MyFloat): MyFloat =
|
|
||||||
MyFloat(val: x1.val * x2.val)
|
|
||||||
|
|
||||||
template optMul{`*`(a, 2.0)}(a: MyFloat): MyFloat =
|
|
||||||
a + a
|
|
||||||
|
|
||||||
func floatMyFloat(x: MyFloat): MyFloat =
|
|
||||||
result = x * 2.0
|
|
||||||
|
|
||||||
func floatDouble(x: float): float =
|
|
||||||
result = x * 2.0
|
|
||||||
|
|
||||||
echo floatDouble(5)
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''immediate'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Test that immediate templates are preferred over non-immediate templates
|
|
||||||
|
|
||||||
template foo(a, b: untyped) = echo "foo expr"
|
|
||||||
template foo(a, b: int) = echo "foo int"
|
|
||||||
template foo(a, b: float) = echo "foo float"
|
|
||||||
template foo(a, b: string) = echo "foo string"
|
|
||||||
template foo(a, b: untyped) {.immediate.} = echo "immediate"
|
|
||||||
template foo(a, b: bool) = echo "foo bool"
|
|
||||||
template foo(a, b: char) = echo "foo char"
|
|
||||||
|
|
||||||
foo(undeclaredIdentifier, undeclaredIdentifier2)
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "10"
|
|
||||||
"""
|
|
||||||
|
|
||||||
template something(name: untyped) =
|
|
||||||
proc name(x: int) =
|
|
||||||
var x = x # this one should not be rejected by the compiler (#5225)
|
|
||||||
echo x
|
|
||||||
|
|
||||||
something(what)
|
|
||||||
what(10)
|
|
||||||
|
|
||||||
# bug #4750
|
|
||||||
|
|
||||||
type
|
|
||||||
O = object
|
|
||||||
i: int
|
|
||||||
|
|
||||||
OP = ptr O
|
|
||||||
|
|
||||||
template alf(p: pointer): untyped =
|
|
||||||
cast[OP](p)
|
|
||||||
|
|
||||||
|
|
||||||
proc t1(al: pointer) =
|
|
||||||
var o = alf(al)
|
|
||||||
|
|
||||||
proc t2(alf: pointer) =
|
|
||||||
var x = alf
|
|
||||||
var o = alf(x)
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
|
|
||||||
# bug #2585
|
|
||||||
|
|
||||||
type
|
|
||||||
RenderPass = object
|
|
||||||
state: ref int
|
|
||||||
|
|
||||||
RenderData* = object
|
|
||||||
fb: int
|
|
||||||
walls: seq[RenderPass]
|
|
||||||
|
|
||||||
Mat2 = int
|
|
||||||
Vector2[T] = T
|
|
||||||
Pixels=int
|
|
||||||
|
|
||||||
template use*(fb: int, st: untyped): untyped =
|
|
||||||
echo "a ", $fb
|
|
||||||
st
|
|
||||||
echo "a ", $fb
|
|
||||||
|
|
||||||
proc render(rdat: var RenderData; passes: var openarray[RenderPass]; proj: Mat2;
|
|
||||||
indexType = 1) =
|
|
||||||
for i in 0 .. <len(passes):
|
|
||||||
echo "blah ", repr(passes[i])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc render2*(rdat: var RenderData; screenSz: Vector2[Pixels]; proj: Mat2) =
|
|
||||||
use rdat.fb:
|
|
||||||
render(rdat, rdat.walls, proj, 1)
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
type Foo = object
|
|
||||||
len: int
|
|
||||||
|
|
||||||
var f = Foo(len: 40)
|
|
||||||
|
|
||||||
template getLen(f: Foo): int = f.len
|
|
||||||
|
|
||||||
echo f.getLen
|
|
||||||
# This fails, because `len` gets the nkOpenSymChoice
|
|
||||||
# treatment inside the template early pass and then
|
|
||||||
# it can't be recognized as a field anymore
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''a'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #4292
|
|
||||||
|
|
||||||
template foo(s: string): string = s
|
|
||||||
proc variadicProc*(v: varargs[string, foo]) = echo v[0]
|
|
||||||
variadicProc("a")
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
# Test the new template file mechanism
|
|
||||||
|
|
||||||
import
|
|
||||||
os, times
|
|
||||||
|
|
||||||
include "sunset.tmpl"
|
|
||||||
|
|
||||||
const
|
|
||||||
tabs = [["home", "index"],
|
|
||||||
["news", "news"],
|
|
||||||
["documentation", "documentation"],
|
|
||||||
["download", "download"],
|
|
||||||
["FAQ", "question"],
|
|
||||||
["links", "links"]]
|
|
||||||
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
for item in items(tabs):
|
|
||||||
var content = $i
|
|
||||||
var file: File
|
|
||||||
if open(file, changeFileExt(item[1], "html"), fmWrite):
|
|
||||||
write(file, sunsetTemplate(current=item[1], ticker="", content=content,
|
|
||||||
tabs=tabs))
|
|
||||||
close(file)
|
|
||||||
else:
|
|
||||||
write(stdout, "cannot open file for writing")
|
|
||||||
inc(i)
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
template `:=`(name, val: untyped): typed =
|
|
||||||
var name = val
|
|
||||||
|
|
||||||
ha := 1 * 4
|
|
||||||
hu := "ta-da" == "ta-da"
|
|
||||||
echo ha, hu
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
import mtempl5
|
|
||||||
|
|
||||||
echo templ()
|
|
||||||
|
|
||||||
#bug #892
|
|
||||||
|
|
||||||
proc parse_to_close(value: string, index: int, open='(', close=')'): int =
|
|
||||||
discard
|
|
||||||
|
|
||||||
# Call parse_to_close
|
|
||||||
template get_next_ident: typed =
|
|
||||||
discard "{something}".parse_to_close(0, open = '{', close = '}')
|
|
||||||
|
|
||||||
get_next_ident()
|
|
||||||
|
|
||||||
|
|
||||||
#identifier expected, but found '(open|open|open)'
|
|
||||||
|
|
||||||
#bug #880 (also example in the manual!)
|
|
||||||
|
|
||||||
template typedef(name: untyped, typ: typedesc) =
|
|
||||||
type
|
|
||||||
`T name`* {.inject.} = typ
|
|
||||||
`P name`* {.inject.} = ref `T name`
|
|
||||||
|
|
||||||
typedef(myint, int)
|
|
||||||
var x: PMyInt
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
template `=~` (a: int, b: int): bool = false
|
|
||||||
var foo = 2 =~ 3
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "hi"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #2670
|
|
||||||
template testTemplate(b: bool): typed =
|
|
||||||
when b:
|
|
||||||
var a = "hi"
|
|
||||||
else:
|
|
||||||
var a = 5
|
|
||||||
echo a
|
|
||||||
|
|
||||||
testTemplate(true)
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''2 3'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #4097
|
|
||||||
|
|
||||||
var i {.compileTime.} = 2
|
|
||||||
|
|
||||||
template defineId*(t: typedesc) =
|
|
||||||
const id {.genSym.} = i
|
|
||||||
static: inc(i)
|
|
||||||
proc idFor*(T: typedesc[t]): int {.inline, raises: [].} = id
|
|
||||||
|
|
||||||
defineId(int8)
|
|
||||||
defineId(int16)
|
|
||||||
|
|
||||||
echo idFor(int8), " ", idFor(int16)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "12false3ha"
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc f(x: varargs[string, `$`]) = discard
|
|
||||||
template optF{f(x)}(x: varargs[untyped]) =
|
|
||||||
writeLine(stdout, x)
|
|
||||||
|
|
||||||
f 1, 2, false, 3, "ha"
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "4"
|
|
||||||
"""
|
|
||||||
|
|
||||||
template cse{f(a, a, x)}(a: typed{(nkDotExpr|call|nkBracketExpr)&noSideEffect},
|
|
||||||
f: typed, x: varargs[typed]): untyped =
|
|
||||||
let aa = a
|
|
||||||
f(aa, aa, x)+4
|
|
||||||
|
|
||||||
var
|
|
||||||
a: array[0..10, int]
|
|
||||||
i = 3
|
|
||||||
echo a[i] + a[i]
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''true
|
|
||||||
true'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import pegs
|
|
||||||
|
|
||||||
template optPeg{peg(pattern)}(pattern: string{lit}): Peg =
|
|
||||||
var gl {.global, gensym.} = peg(pattern)
|
|
||||||
gl
|
|
||||||
|
|
||||||
echo match("(a b c)", peg"'(' @ ')'")
|
|
||||||
echo match("W_HI_Le", peg"\y 'while'")
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "21"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import macros
|
|
||||||
|
|
||||||
type
|
|
||||||
TMat = object
|
|
||||||
dummy: int
|
|
||||||
|
|
||||||
proc `*`(a, b: TMat): TMat = nil
|
|
||||||
proc `+`(a, b: TMat): TMat = nil
|
|
||||||
proc `-`(a, b: TMat): TMat = nil
|
|
||||||
proc `$`(a: TMat): string = result = $a.dummy
|
|
||||||
proc mat21(): TMat =
|
|
||||||
result.dummy = 21
|
|
||||||
|
|
||||||
macro optOps{ (`+`|`-`|`*`) ** a }(a: TMat): untyped =
|
|
||||||
echo treeRepr(a)
|
|
||||||
result = newCall(bindSym"mat21")
|
|
||||||
|
|
||||||
#macro optPlus{ `+` * a }(a: varargs[TMat]): expr =
|
|
||||||
# result = newIntLitNode(21)
|
|
||||||
|
|
||||||
var x, y, z: TMat
|
|
||||||
|
|
||||||
echo x + y * z - x
|
|
||||||
|
|
||||||
#echo x + y + z
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "23"
|
|
||||||
"""
|
|
||||||
|
|
||||||
template optslice{a = b + c}(a: untyped{noalias}, b, c: untyped): typed =
|
|
||||||
a = b
|
|
||||||
inc a, c
|
|
||||||
|
|
||||||
var
|
|
||||||
x = 12
|
|
||||||
y = 10
|
|
||||||
z = 13
|
|
||||||
|
|
||||||
x = y+z
|
|
||||||
|
|
||||||
echo x
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''0'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
# bug #206
|
|
||||||
template optimizeOut{testFunc(a, b)}(a: int, b: int{alias}): untyped = 0
|
|
||||||
|
|
||||||
proc testFunc(a, b: int): int = result = a + b
|
|
||||||
var testVar = 1
|
|
||||||
echo testFunc(testVar, testVar)
|
|
||||||
|
|
||||||
|
|
||||||
template ex{a = b + c}(a : int{noalias}, b, c : int) =
|
|
||||||
a = b
|
|
||||||
inc a, b
|
|
||||||
echo "came here"
|
|
||||||
|
|
||||||
var x = 5
|
|
||||||
x = x + x
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "4"
|
|
||||||
"""
|
|
||||||
|
|
||||||
# test that an endless recursion is avoided:
|
|
||||||
|
|
||||||
template optLen{len(x)}(x: typed): int = len(x)
|
|
||||||
|
|
||||||
var s = "lala"
|
|
||||||
echo len(s)
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''-2'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc p(x, y: int; cond: bool): int =
|
|
||||||
result = if cond: x + y else: x - y
|
|
||||||
|
|
||||||
template optP{p(x, y, true)}(x, y): untyped = x - y
|
|
||||||
template optP{p(x, y, false)}(x, y): untyped = x + y
|
|
||||||
|
|
||||||
echo p(2, 4, true)
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''48
|
|
||||||
hel
|
|
||||||
lo'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
template optZero{x+x}(x: int): int = x*3
|
|
||||||
template andthen{`*`(x,3)}(x: int): int = x*4
|
|
||||||
template optSubstr1{x = substr(x, a, b)}(x: string, a, b: int) = setlen(x, b+1)
|
|
||||||
|
|
||||||
var y = 12
|
|
||||||
echo y+y
|
|
||||||
|
|
||||||
var s: array[0..2, string]
|
|
||||||
s[0] = "hello"
|
|
||||||
s[0] = substr(s[0], 0, 2)
|
|
||||||
|
|
||||||
echo s[0]
|
|
||||||
|
|
||||||
# Test varargs matching
|
|
||||||
proc someVarargProc(k: varargs[string]) = doAssert(false) # this should not get called
|
|
||||||
template someVarargProcSingleArg{someVarargProc([a])}(a: string) = echo a
|
|
||||||
someVarargProc("lo")
|
|
||||||
110
tests/trmacros/trmacros_various.nim
Normal file
110
tests/trmacros/trmacros_various.nim
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
12false3ha
|
||||||
|
21
|
||||||
|
optimized
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import macros, pegs
|
||||||
|
|
||||||
|
|
||||||
|
block arglist:
|
||||||
|
proc f(x: varargs[string, `$`]) = discard
|
||||||
|
template optF{f(x)}(x: varargs[untyped]) =
|
||||||
|
writeLine(stdout, x)
|
||||||
|
|
||||||
|
f 1, 2, false, 3, "ha"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tcse:
|
||||||
|
template cse{f(a, a, x)}(a: typed{(nkDotExpr|call|nkBracketExpr)&noSideEffect},
|
||||||
|
f: typed, x: varargs[typed]): untyped =
|
||||||
|
let aa = a
|
||||||
|
f(aa, aa, x)+4
|
||||||
|
|
||||||
|
var
|
||||||
|
a: array[0..10, int]
|
||||||
|
i = 3
|
||||||
|
doAssert a[i] + a[i] == 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block hoist:
|
||||||
|
template optPeg{peg(pattern)}(pattern: string{lit}): Peg =
|
||||||
|
var gl {.global, gensym.} = peg(pattern)
|
||||||
|
gl
|
||||||
|
doAssert match("(a b c)", peg"'(' @ ')'")
|
||||||
|
doAssert match("W_HI_Le", peg"\y 'while'")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tmatrix:
|
||||||
|
type
|
||||||
|
TMat = object
|
||||||
|
dummy: int
|
||||||
|
|
||||||
|
proc `*`(a, b: TMat): TMat = nil
|
||||||
|
proc `+`(a, b: TMat): TMat = nil
|
||||||
|
proc `-`(a, b: TMat): TMat = nil
|
||||||
|
proc `$`(a: TMat): string = result = $a.dummy
|
||||||
|
proc mat21(): TMat =
|
||||||
|
result.dummy = 21
|
||||||
|
|
||||||
|
macro optOps{ (`+`|`-`|`*`) ** a }(a: TMat): untyped =
|
||||||
|
result = newCall(bindSym"mat21")
|
||||||
|
|
||||||
|
#macro optPlus{ `+` * a }(a: varargs[TMat]): expr =
|
||||||
|
# result = newIntLitNode(21)
|
||||||
|
|
||||||
|
var x, y, z: TMat
|
||||||
|
echo x + y * z - x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tnoalias:
|
||||||
|
template optslice{a = b + c}(a: untyped{noalias}, b, c: untyped): typed =
|
||||||
|
a = b
|
||||||
|
inc a, c
|
||||||
|
var
|
||||||
|
x = 12
|
||||||
|
y = 10
|
||||||
|
z = 13
|
||||||
|
x = y+z
|
||||||
|
doAssert x == 23
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tnoendlessrec:
|
||||||
|
# test that an endless recursion is avoided:
|
||||||
|
template optLen{len(x)}(x: typed): int = len(x)
|
||||||
|
|
||||||
|
var s = "lala"
|
||||||
|
doAssert len(s) == 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tstatic_t_bug:
|
||||||
|
# bug #4227
|
||||||
|
type Vector64[N: static[int]] = array[N, int]
|
||||||
|
|
||||||
|
proc `*`[N: static[int]](a: Vector64[N]; b: float64): Vector64[N] =
|
||||||
|
result = a
|
||||||
|
|
||||||
|
proc `+=`[N: static[int]](a: var Vector64[N]; b: Vector64[N]) =
|
||||||
|
echo "regular"
|
||||||
|
|
||||||
|
proc linearCombinationMut[N: static[int]](a: float64, v: var Vector64[N], w: Vector64[N]) {. inline .} =
|
||||||
|
echo "optimized"
|
||||||
|
|
||||||
|
template rewriteLinearCombinationMut{v += `*`(w, a)}(a: float64, v: var Vector64, w: Vector64): auto =
|
||||||
|
linearCombinationMut(a, v, w)
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
const scaleVal = 9.0
|
||||||
|
var a, b: Vector64[7]
|
||||||
|
a += b * scaleval
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
79
tests/trmacros/trmacros_various2.nim
Normal file
79
tests/trmacros/trmacros_various2.nim
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
0
|
||||||
|
-2
|
||||||
|
48
|
||||||
|
hel
|
||||||
|
lo
|
||||||
|
my awesome concat
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
block tnoalias2:
|
||||||
|
# bug #206
|
||||||
|
template optimizeOut{testFunc(a, b)}(a: int, b: int{alias}): untyped = 0
|
||||||
|
|
||||||
|
proc testFunc(a, b: int): int = result = a + b
|
||||||
|
var testVar = 1
|
||||||
|
echo testFunc(testVar, testVar)
|
||||||
|
|
||||||
|
|
||||||
|
template ex{a = b + c}(a : int{noalias}, b, c : int) =
|
||||||
|
a = b
|
||||||
|
inc a, b
|
||||||
|
echo "came here"
|
||||||
|
|
||||||
|
var x = 5
|
||||||
|
x = x + x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tpartial:
|
||||||
|
proc p(x, y: int; cond: bool): int =
|
||||||
|
result = if cond: x + y else: x - y
|
||||||
|
|
||||||
|
template optP{p(x, y, true)}(x, y): untyped = x - y
|
||||||
|
template optP{p(x, y, false)}(x, y): untyped = x + y
|
||||||
|
|
||||||
|
echo p(2, 4, true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tpatterns:
|
||||||
|
template optZero{x+x}(x: int): int = x*3
|
||||||
|
template andthen{`*`(x,3)}(x: int): int = x*4
|
||||||
|
template optSubstr1{x = substr(x, a, b)}(x: string, a, b: int) = setlen(x, b+1)
|
||||||
|
|
||||||
|
var y = 12
|
||||||
|
echo y+y
|
||||||
|
|
||||||
|
var s: array[0..2, string]
|
||||||
|
s[0] = "hello"
|
||||||
|
s[0] = substr(s[0], 0, 2)
|
||||||
|
|
||||||
|
echo s[0]
|
||||||
|
|
||||||
|
# Test varargs matching
|
||||||
|
proc someVarargProc(k: varargs[string]) = doAssert(false) # this should not get called
|
||||||
|
template someVarargProcSingleArg{someVarargProc([a])}(a: string) = echo a
|
||||||
|
someVarargProc("lo")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tstar:
|
||||||
|
var
|
||||||
|
calls = 0
|
||||||
|
|
||||||
|
proc `&&`(s: varargs[string]): string =
|
||||||
|
result = s[0]
|
||||||
|
for i in 1..len(s)-1: result.add s[i]
|
||||||
|
inc calls
|
||||||
|
|
||||||
|
template optConc{ `&&` * a }(a: string): string = &&a
|
||||||
|
|
||||||
|
let space = " "
|
||||||
|
echo "my" && (space & "awe" && "some " ) && "concat"
|
||||||
|
|
||||||
|
# check that it's been optimized properly:
|
||||||
|
doAssert calls == 1
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "my awesome concat"
|
|
||||||
"""
|
|
||||||
|
|
||||||
var
|
|
||||||
calls = 0
|
|
||||||
|
|
||||||
proc `&&`(s: varargs[string]): string =
|
|
||||||
result = s[0]
|
|
||||||
for i in 1..len(s)-1: result.add s[i]
|
|
||||||
inc calls
|
|
||||||
|
|
||||||
template optConc{ `&&` * a }(a: string): string = &&a
|
|
||||||
|
|
||||||
let space = " "
|
|
||||||
echo "my" && (space & "awe" && "some " ) && "concat"
|
|
||||||
|
|
||||||
# check that it's been optimized properly:
|
|
||||||
doAssert calls == 1
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
discard """
|
|
||||||
output: "optimized"
|
|
||||||
"""
|
|
||||||
# bug #4227
|
|
||||||
type Vector64[N: static[int]] = array[N, int]
|
|
||||||
|
|
||||||
proc `*`*[N: static[int]](a: Vector64[N]; b: float64): Vector64[N] =
|
|
||||||
result = a
|
|
||||||
|
|
||||||
proc `+=`*[N: static[int]](a: var Vector64[N]; b: Vector64[N]) =
|
|
||||||
echo "regular"
|
|
||||||
|
|
||||||
proc linearCombinationMut[N: static[int]](a: float64, v: var Vector64[N], w: Vector64[N]) {. inline .} =
|
|
||||||
echo "optimized"
|
|
||||||
|
|
||||||
template rewriteLinearCombinationMut*{v += `*`(w, a)}(a: float64, v: var Vector64, w: Vector64): auto =
|
|
||||||
linearCombinationMut(a, v, w)
|
|
||||||
|
|
||||||
proc main() =
|
|
||||||
const scaleVal = 9.0
|
|
||||||
var a, b: Vector64[7]
|
|
||||||
a += b * scaleval
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''61, 125
|
|
||||||
(Field0: 0) (Field0: 13)'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import macros
|
|
||||||
|
|
||||||
proc `^` (a, b: int): int =
|
|
||||||
result = 1
|
|
||||||
for i in 1..b: result = result * a
|
|
||||||
|
|
||||||
var m = (0, 5)
|
|
||||||
var n = (56, 3)
|
|
||||||
|
|
||||||
m = (n[0] + m[1], m[1] ^ n[1])
|
|
||||||
|
|
||||||
echo m[0], ", ", m[1]
|
|
||||||
|
|
||||||
# also test we can produce unary anon tuples in a macro:
|
|
||||||
macro mm(): untyped =
|
|
||||||
result = newTree(nnkTupleConstr, newLit(13))
|
|
||||||
|
|
||||||
proc nowTuple(): (int,) =
|
|
||||||
result = (0,)
|
|
||||||
|
|
||||||
echo nowTuple(), " ", mm()
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# Bug 4479
|
|
||||||
|
|
||||||
type
|
|
||||||
MyTuple = tuple
|
|
||||||
num: int
|
|
||||||
strings: seq[string]
|
|
||||||
ints: seq[int]
|
|
||||||
|
|
||||||
var foo = MyTuple((
|
|
||||||
num: 7,
|
|
||||||
strings: @[],
|
|
||||||
ints: @[],
|
|
||||||
))
|
|
||||||
|
|
||||||
var bar = (
|
|
||||||
num: 7,
|
|
||||||
strings: @[],
|
|
||||||
ints: @[],
|
|
||||||
).MyTuple
|
|
||||||
|
|
||||||
var fooUnnamed = MyTuple((7, @[], @[]))
|
|
||||||
var n = 7
|
|
||||||
var fooSym = MyTuple((num: n, strings: @[], ints: @[]))
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
# bug #1910
|
|
||||||
import tables
|
|
||||||
|
|
||||||
var p: OrderedTable[tuple[a:int], int]
|
|
||||||
var q: OrderedTable[tuple[x:int], int]
|
|
||||||
for key in p.keys:
|
|
||||||
echo key.a
|
|
||||||
for key in q.keys:
|
|
||||||
echo key.x
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
# bug #2121
|
|
||||||
|
|
||||||
type
|
|
||||||
Item[K,V] = tuple
|
|
||||||
key: K
|
|
||||||
value: V
|
|
||||||
|
|
||||||
var q = newseq[Item[int,int]](0)
|
|
||||||
let (x,y) = q[0]
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
# bug #2369
|
|
||||||
|
|
||||||
type HashedElem[T] = tuple[num: int, storedVal: ref T]
|
|
||||||
|
|
||||||
proc append[T](tab: var seq[HashedElem[T]], n: int, val: ref T) =
|
|
||||||
#tab.add((num: n, storedVal: val))
|
|
||||||
var he: HashedElem[T] = (num: n, storedVal: val)
|
|
||||||
#tab.add(he)
|
|
||||||
|
|
||||||
var g: seq[HashedElem[int]] = @[]
|
|
||||||
|
|
||||||
proc foo() =
|
|
||||||
var x: ref int
|
|
||||||
new(x)
|
|
||||||
x[] = 77
|
|
||||||
g.append(44, x)
|
|
||||||
77
tests/tuples/ttuples_issues.nim
Normal file
77
tests/tuples/ttuples_issues.nim
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import tables
|
||||||
|
|
||||||
|
|
||||||
|
block t4479:
|
||||||
|
type
|
||||||
|
MyTuple = tuple
|
||||||
|
num: int
|
||||||
|
strings: seq[string]
|
||||||
|
ints: seq[int]
|
||||||
|
|
||||||
|
var foo = MyTuple((
|
||||||
|
num: 7,
|
||||||
|
strings: @[],
|
||||||
|
ints: @[],
|
||||||
|
))
|
||||||
|
|
||||||
|
var bar = (
|
||||||
|
num: 7,
|
||||||
|
strings: @[],
|
||||||
|
ints: @[],
|
||||||
|
).MyTuple
|
||||||
|
|
||||||
|
var fooUnnamed = MyTuple((7, @[], @[]))
|
||||||
|
var n = 7
|
||||||
|
var fooSym = MyTuple((num: n, strings: @[], ints: @[]))
|
||||||
|
|
||||||
|
|
||||||
|
block t1910:
|
||||||
|
var p = newOrderedTable[tuple[a:int], int]()
|
||||||
|
var q = newOrderedTable[tuple[x:int], int]()
|
||||||
|
for key in p.keys:
|
||||||
|
echo key.a
|
||||||
|
for key in q.keys:
|
||||||
|
echo key.x
|
||||||
|
|
||||||
|
|
||||||
|
block t2121:
|
||||||
|
type
|
||||||
|
Item[K,V] = tuple
|
||||||
|
key: K
|
||||||
|
value: V
|
||||||
|
|
||||||
|
var q = newseq[Item[int,int]](1)
|
||||||
|
let (x,y) = q[0]
|
||||||
|
|
||||||
|
|
||||||
|
block t2369:
|
||||||
|
type HashedElem[T] = tuple[num: int, storedVal: ref T]
|
||||||
|
|
||||||
|
proc append[T](tab: var seq[HashedElem[T]], n: int, val: ref T) =
|
||||||
|
#tab.add((num: n, storedVal: val))
|
||||||
|
var he: HashedElem[T] = (num: n, storedVal: val)
|
||||||
|
#tab.add(he)
|
||||||
|
|
||||||
|
var g: seq[HashedElem[int]] = @[]
|
||||||
|
|
||||||
|
proc foo() =
|
||||||
|
var x: ref int
|
||||||
|
new(x)
|
||||||
|
x[] = 77
|
||||||
|
g.append(44, x)
|
||||||
|
|
||||||
|
|
||||||
|
block t1986:
|
||||||
|
proc test(): int64 =
|
||||||
|
return 0xdeadbeef.int64
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
(var1: test(), var2: 100'u32),
|
||||||
|
(var1: test(), var2: 192'u32)
|
||||||
|
]
|
||||||
136
tests/tuples/ttuples_various.nim
Normal file
136
tests/tuples/ttuples_various.nim
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
it's nil
|
||||||
|
@[1, 2, 3]
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
|
||||||
|
block anontuples:
|
||||||
|
proc `^` (a, b: int): int =
|
||||||
|
result = 1
|
||||||
|
for i in 1..b: result = result * a
|
||||||
|
|
||||||
|
var m = (0, 5)
|
||||||
|
var n = (56, 3)
|
||||||
|
|
||||||
|
m = (n[0] + m[1], m[1] ^ n[1])
|
||||||
|
|
||||||
|
doAssert m == (61, 125)
|
||||||
|
|
||||||
|
# also test we can produce unary anon tuples in a macro:
|
||||||
|
macro mm(): untyped =
|
||||||
|
result = newTree(nnkTupleConstr, newLit(13))
|
||||||
|
|
||||||
|
proc nowTuple(): (int,) =
|
||||||
|
result = (0,)
|
||||||
|
|
||||||
|
doAssert nowTuple() == (Field0: 0)
|
||||||
|
doAssert mm() == (Field0: 13)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block unpack_asgn:
|
||||||
|
proc foobar(): (int, int) = (2, 4)
|
||||||
|
|
||||||
|
# test within a proc:
|
||||||
|
proc pp(x: var int) =
|
||||||
|
var y: int
|
||||||
|
(y, x) = foobar()
|
||||||
|
|
||||||
|
template pt(x) =
|
||||||
|
var y: int
|
||||||
|
(x, y) = foobar()
|
||||||
|
|
||||||
|
# test within a generic:
|
||||||
|
proc pg[T](x, y: var T) =
|
||||||
|
pt(x)
|
||||||
|
|
||||||
|
# test as a top level statement:
|
||||||
|
var x, y, a, b: int
|
||||||
|
# test for regression:
|
||||||
|
(x, y) = (1, 2)
|
||||||
|
(x, y) = fooBar()
|
||||||
|
|
||||||
|
doAssert x == 2
|
||||||
|
doAssert y == 4
|
||||||
|
|
||||||
|
pp(a)
|
||||||
|
doAssert a == 4
|
||||||
|
|
||||||
|
pg(a, b)
|
||||||
|
doAssert a == 2
|
||||||
|
doAssert b == 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tuple_subscript:
|
||||||
|
proc`[]` (t: tuple, key: string): string =
|
||||||
|
for name, field in fieldPairs(t):
|
||||||
|
if name == key:
|
||||||
|
return $field
|
||||||
|
return ""
|
||||||
|
|
||||||
|
proc`[]` [A,B](t: tuple, key: string, op: (proc(x: A): B)): B =
|
||||||
|
for name, field in fieldPairs(t):
|
||||||
|
when field is A:
|
||||||
|
if name == key:
|
||||||
|
return op(field)
|
||||||
|
|
||||||
|
proc`[]=`[T](t: var tuple, key: string, val: T) =
|
||||||
|
for name, field in fieldPairs(t):
|
||||||
|
when field is T:
|
||||||
|
if name == key:
|
||||||
|
field = val
|
||||||
|
|
||||||
|
var tt = (a: 1, b: "str1")
|
||||||
|
|
||||||
|
# test built in operator
|
||||||
|
tt[0] = 5
|
||||||
|
|
||||||
|
doAssert tt[0] == 5
|
||||||
|
doAssert `[]`(tt, 0) == 5
|
||||||
|
|
||||||
|
# test overloaded operator
|
||||||
|
tt["b"] = "str2"
|
||||||
|
doAssert tt["b"] == "str2"
|
||||||
|
doAssert `[]`(tt, "b") == "str2"
|
||||||
|
doAssert tt["b", proc(s: string): int = s.len] == 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
block tuple_with_seq:
|
||||||
|
template foo(s: string = "") =
|
||||||
|
if s.len == 0:
|
||||||
|
echo "it's nil"
|
||||||
|
else:
|
||||||
|
echo s
|
||||||
|
foo
|
||||||
|
|
||||||
|
# bug #2632
|
||||||
|
proc takeTup(x: tuple[s: string;x: seq[int]]) =
|
||||||
|
discard
|
||||||
|
takeTup(("foo", @[]))
|
||||||
|
|
||||||
|
#proc foobar(): () =
|
||||||
|
proc f(xs: seq[int]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc g(t: tuple[n:int, xs:seq[int]]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
f(@[]) # OK
|
||||||
|
g((1,@[1])) # OK
|
||||||
|
g((0,@[])) # NG
|
||||||
|
|
||||||
|
# bug #2630
|
||||||
|
type T = tuple[a: seq[int], b: int]
|
||||||
|
var t: T = (@[1,2,3], 7)
|
||||||
|
|
||||||
|
proc test(s: seq[int]): T =
|
||||||
|
echo s
|
||||||
|
(s, 7)
|
||||||
|
t = test(t.a)
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# bug #1986 found by gdmoore
|
|
||||||
|
|
||||||
proc test(): int64 =
|
|
||||||
return 0xdeadbeef.int64
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
(var1: test(), var2: 100'u32),
|
|
||||||
(var1: test(), var2: 192'u32)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''2 4
|
|
||||||
4
|
|
||||||
2 0'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc foobar(): (int, int) = (2, 4)
|
|
||||||
|
|
||||||
# test within a proc:
|
|
||||||
proc pp(x: var int) =
|
|
||||||
var y: int
|
|
||||||
(y, x) = foobar()
|
|
||||||
|
|
||||||
template pt(x) =
|
|
||||||
var y: int
|
|
||||||
(x, y) = foobar()
|
|
||||||
|
|
||||||
# test within a generic:
|
|
||||||
proc pg[T](x, y: var T) =
|
|
||||||
pt(x)
|
|
||||||
|
|
||||||
# test as a top level statement:
|
|
||||||
var x, y, a, b: int
|
|
||||||
# test for regression:
|
|
||||||
(x, y) = (1, 2)
|
|
||||||
(x, y) = fooBar()
|
|
||||||
|
|
||||||
echo x, " ", y
|
|
||||||
|
|
||||||
pp(a)
|
|
||||||
echo a
|
|
||||||
|
|
||||||
pg(a, b)
|
|
||||||
echo a, " ", b
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''5
|
|
||||||
5
|
|
||||||
str2
|
|
||||||
str2
|
|
||||||
4'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
proc`[]` (t: tuple, key: string): string =
|
|
||||||
for name, field in fieldPairs(t):
|
|
||||||
if name == key:
|
|
||||||
return $field
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
proc`[]` [A,B](t: tuple, key: string, op: (proc(x: A): B)): B =
|
|
||||||
for name, field in fieldPairs(t):
|
|
||||||
when field is A:
|
|
||||||
if name == key:
|
|
||||||
return op(field)
|
|
||||||
|
|
||||||
proc`[]=`[T](t: var tuple, key: string, val: T) =
|
|
||||||
for name, field in fieldPairs(t):
|
|
||||||
when field is T:
|
|
||||||
if name == key:
|
|
||||||
field = val
|
|
||||||
|
|
||||||
var tt = (a: 1, b: "str1")
|
|
||||||
|
|
||||||
# test built in operator
|
|
||||||
tt[0] = 5
|
|
||||||
echo tt[0]
|
|
||||||
echo `[]`(tt, 0)
|
|
||||||
|
|
||||||
|
|
||||||
# test overloaded operator
|
|
||||||
tt["b"] = "str2"
|
|
||||||
echo tt["b"]
|
|
||||||
echo `[]`(tt, "b")
|
|
||||||
echo tt["b", proc(s: string) : int = s.len]
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''it's nil
|
|
||||||
@[1, 2, 3]'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
template foo(s: string = "") =
|
|
||||||
if s.len == 0:
|
|
||||||
echo "it's nil"
|
|
||||||
else:
|
|
||||||
echo s
|
|
||||||
|
|
||||||
foo
|
|
||||||
|
|
||||||
|
|
||||||
# bug #2632
|
|
||||||
|
|
||||||
proc takeTup(x: tuple[s: string;x: seq[int]]) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
takeTup(("foo", @[]))
|
|
||||||
|
|
||||||
|
|
||||||
#proc foobar(): () =
|
|
||||||
|
|
||||||
proc f(xs: seq[int]) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc g(t: tuple[n:int, xs:seq[int]]) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
f(@[]) # OK
|
|
||||||
g((1,@[1])) # OK
|
|
||||||
g((0,@[])) # NG
|
|
||||||
|
|
||||||
|
|
||||||
# bug #2630
|
|
||||||
type T = tuple[a: seq[int], b: int]
|
|
||||||
|
|
||||||
var t: T = (@[1,2,3], 7)
|
|
||||||
|
|
||||||
proc test(s: seq[int]): T =
|
|
||||||
echo s
|
|
||||||
(s, 7)
|
|
||||||
|
|
||||||
t = test(t.a)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue