mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
* fix #16967 [backport:1.2]
* move test to tsugar
(cherry picked from commit 49ee2f7f3b)
This commit is contained in:
@@ -219,7 +219,7 @@ macro capture*(locals: varargs[typed], body: untyped): untyped {.since: (1, 1).}
|
||||
error("The variable name cannot be `result`!", arg)
|
||||
params.add(newIdentDefs(ident(arg.strVal), freshIdentNodes getTypeInst arg))
|
||||
result = newNimNode(nnkCall)
|
||||
result.add(newProc(newEmptyNode(), params, body, nnkProcDef))
|
||||
result.add(newProc(newEmptyNode(), params, body, nnkLambda))
|
||||
for arg in locals: result.add(arg)
|
||||
|
||||
since (1, 1):
|
||||
|
||||
233
tests/stdlib/tsugar.nim
Normal file
233
tests/stdlib/tsugar.nim
Normal file
@@ -0,0 +1,233 @@
|
||||
discard """
|
||||
output: '''
|
||||
x + y = 30
|
||||
'''
|
||||
"""
|
||||
import std/[sugar, algorithm, random, sets, tables, strutils]
|
||||
|
||||
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: # 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
|
||||
|
||||
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()
|
||||
|
||||
proc mainProc() =
|
||||
block: # dump
|
||||
# symbols in templates are gensym'd
|
||||
let
|
||||
x = 10
|
||||
y = 20
|
||||
dump(x + y) # x + y = 30
|
||||
|
||||
block: # dumpToString
|
||||
template square(x): untyped = x * x
|
||||
let x = 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
|
||||
|
||||
static:
|
||||
main()
|
||||
mainProc()
|
||||
main()
|
||||
mainProc()
|
||||
Reference in New Issue
Block a user