123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- discard """
- targets: "c js"
- matrix: "--mm:refc; --mm:orc"
- output: '''
- x + y = 30
- '''
- """
- import std/[sugar, algorithm, random, sets, tables, strutils, sequtils]
- import std/[syncio, assertions]
- type # for capture test, ref #20679
- FooCapture = ref object
- x: int
- proc mainProc() =
- block: # bug #16967
- var s = newSeq[proc (): int](5)
- {.push exportc.}
- proc bar() =
- for i in 0 ..< s.len:
- let foo = i + 1
- capture foo:
- s[i] = proc(): int = foo
- {.pop.}
- bar()
- for i, p in s.pairs:
- let foo = i + 1
- doAssert p() == foo
- template main() =
- block: # `=>`
- block:
- let f1 = () => 42
- doAssert f1() == 42
- let f2 = (x: int) => x + 1
- doAssert f2(42) == 43
- let f3 = (x, y: int) => x + y
- doAssert f3(1, 2) == 3
- var x = 0
- let f4 = () => (x = 12)
- f4()
- doAssert x == 12
- let f5 = () => (discard) # simplest proc that returns void
- f5()
- block:
- proc call1(f: () -> int): int = f()
- doAssert call1(() => 12) == 12
- proc call2(f: int -> int): int = f(42)
- doAssert call2(x => x) == 42
- doAssert call2((x) => x) == 42
- doAssert call2((x: int) => x) == 42
- proc call3(f: (int, int) -> int): int = f(1, 2)
- doAssert call3((x, y) => x + y) == 3
- doAssert call3((x, y: int) => x + y) == 3
- doAssert call3((x: int, y: int) => x + y) == 3
- var a = 0
- proc call4(f: int -> void) = f(42)
- call4((x: int) => (a = x))
- doAssert a == 42
- proc call5(f: (int {.noSideEffect.} -> int)): int = f(42)
- doAssert call5(x {.noSideEffect.} => x + 1) == 43
- block: # `->`
- doAssert $(() -> int) == "proc (): int{.closure.}"
- doAssert $(float -> int) == "proc (i0: float): int{.closure.}"
- doAssert $((float) -> int) == "proc (i0: float): int{.closure.}"
- doAssert $((float, bool) -> int) == "proc (i0: float, i1: bool): int{.closure.}"
- doAssert $(() -> void) == "proc (){.closure.}"
- doAssert $(float -> void) == "proc (i0: float){.closure.}"
- doAssert $((float) -> void) == "proc (i0: float){.closure.}"
- doAssert $((float, bool) -> void) == "proc (i0: float, i1: bool){.closure.}"
- doAssert $(() {.inline.} -> int) == "proc (): int{.inline.}"
- doAssert $(float {.inline.} -> int) == "proc (i0: float): int{.inline.}"
- doAssert $((float) {.inline.} -> int) == "proc (i0: float): int{.inline.}"
- doAssert $((float, bool) {.inline.} -> int) == "proc (i0: float, i1: bool): int{.inline.}"
- block: # capture
- var closure1: () -> int
- for i in 0 .. 10:
- if i == 5:
- capture i:
- closure1 = () => i
- doAssert closure1() == 5
- var closure2: () -> (int, int)
- for i in 0 .. 10:
- for j in 0 .. 10:
- if i == 5 and j == 3:
- capture i, j:
- closure2 = () => (i, j)
- doAssert closure2() == (5, 3)
- block: # issue #20679
- # this should compile. Previously was broken as `var int` is an `nnkHiddenDeref`
- # which was not handled correctly
- block:
- var x = 5
- var s1 = newSeq[proc (): int](2)
- proc function(data: var int) =
- for i in 0 ..< 2:
- data = (i+1) * data
- capture data:
- s1[i] = proc(): int = data
- function(x)
- doAssert s1[0]() == 5
- doAssert s1[1]() == 10
- block:
- var y = @[5, 10]
- var s2 = newSeq[proc (): seq[int]](2)
- proc functionS(data: var seq[int]) =
- for i in 0 ..< 2:
- data.add (i+1) * 5
- capture data:
- s2[i] = proc(): seq[int] = data
- functionS(y)
- doAssert s2[0]() == @[5, 10, 5]
- doAssert s2[1]() == @[5, 10, 5, 10]
- template typeT(typ, val: untyped): untyped =
- var x = val
- var s = newSeq[proc (): typ](2)
- proc functionT[T](data: var T) =
- for i in 0 ..< 2:
- if i == 1:
- data = default(T)
- capture data:
- s[i] = proc (): T = data
- functionT(x)
- doAssert s[0]() == val
- doAssert s[1]() == x # == default
- doAssert s[1]() == default(typ)
- block:
- var x = 1.1
- typeT(float, x)
- block:
- var x = "hello"
- typeT(string, x)
- block:
- var f = FooCapture(x: 5)
- typeT(FooCapture, f)
- block: # dup
- block dup_with_field:
- type
- Foo = object
- col, pos: int
- name: string
- proc inc_col(foo: var Foo) = inc(foo.col)
- proc inc_pos(foo: var Foo) = inc(foo.pos)
- proc name_append(foo: var Foo, s: string) = foo.name &= s
- let a = Foo(col: 1, pos: 2, name: "foo")
- block:
- let b = a.dup(inc_col, inc_pos):
- _.pos = 3
- name_append("bar")
- inc_pos
- doAssert(b == Foo(col: 2, pos: 4, name: "foobar"))
- block:
- let b = a.dup(inc_col, pos = 3, name = "bar"):
- name_append("bar")
- inc_pos
- doAssert(b == Foo(col: 2, pos: 4, name: "barbar"))
- block:
- var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
- doAssert dup(a, sort(_)) == sorted(a)
- doAssert a.dup(sort) == sorted(a)
- # Chaining:
- var aCopy = a
- aCopy.insert(10)
- doAssert a.dup(insert(10)).dup(sort()) == sorted(aCopy)
- block:
- when nimvm: discard
- else:
- const b = @[0, 1, 2]
- discard b.dup shuffle()
- doAssert b[0] == 0
- doAssert b[1] == 1
- block: # collect
- let data = @["bird", "word"] # if this gets stuck in your head, its not my fault
- doAssert collect(newSeq, for (i, d) in data.pairs: (if i mod 2 == 0: d)) == @["bird"]
- doAssert collect(initTable(2), for (i, d) in data.pairs: {i: d}) ==
- {0: "bird", 1: "word"}.toTable
- doAssert collect(initHashSet(), for d in data.items: {d}) == data.toHashSet
- block:
- let x = collect(newSeqOfCap(4)):
- for (i, d) in data.pairs:
- if i mod 2 == 0: d
- doAssert x == @["bird"]
- block: # bug #12874
- let bug = collect(
- newSeq,
- for (i, d) in data.pairs:(
- block:
- if i mod 2 == 0:
- d
- else:
- d & d
- )
- )
- doAssert bug == @["bird", "wordword"]
- block:
- let y = collect(newSeq):
- for (i, d) in data.pairs:
- try: parseInt(d) except: 0
- doAssert y == @[0, 0]
- block:
- let z = collect(newSeq):
- for (i, d) in data.pairs:
- case d
- of "bird": "word"
- else: d
- doAssert z == @["word", "word"]
- block:
- proc tforum(): seq[int] =
- collect(newSeq):
- for y in 0..10:
- if y mod 5 == 2:
- for x in 0..y:
- x
- doAssert tforum() == @[0, 1, 2, 0, 1, 2, 3, 4, 5, 6, 7]
- block:
- let x = collect:
- for d in data.items:
- when d is int: "word"
- else: d
- doAssert x == @["bird", "word"]
- block:
- doAssert collect(for (i, d) in pairs(data): (i, d)) == @[(0, "bird"), (1, "word")]
- doAssert collect(for d in data.items: (try: parseInt(d) except: 0)) == @[0, 0]
- doAssert collect(for (i, d) in pairs(data): {i: d}) ==
- {1: "word", 0: "bird"}.toTable
- doAssert collect(for d in data.items: {d}) == data.toHashSet
- block: # bug #14332
- template foo =
- discard collect(newSeq, for i in 1..3: i)
- foo()
- block: # dump
- # symbols in templates are gensym'd
- let
- x {.inject.} = 10
- y {.inject.} = 20
- dump(x + y) # x + y = 30
- block: # dumpToString
- template square(x): untyped = x * x
- let x {.inject.} = 10
- doAssert dumpToString(square(x)) == "square(x): x * x = 100"
- let s = dumpToString(doAssert 1+1 == 2)
- doAssert "failedAssertImpl" in s
- let s2 = dumpToString:
- doAssertRaises(AssertionDefect): doAssert false
- doAssert "except AssertionDefect" in s2
- block: # bug #20704
- proc test() =
- var xs, ys: seq[int]
- for i in 0..5:
- xs.add(i)
- xs.apply(proc (d: auto) = ys.add(d))
- # ^ can be turned into d => ys.add(d) when we can infer void return type, #16906
- doAssert ys == @[0, 1, 2, 3, 4, 5]
- test()
- mainProc()
- when not defined(js): # TODO fixme JS VM
- static:
- main()
- main()
|