mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
368 lines
6.9 KiB
Nim
368 lines
6.9 KiB
Nim
discard """
|
|
valgrind: true
|
|
cmd: "nim c --gc:arc -d:useMalloc $file"
|
|
output: '''myobj destroyed
|
|
myobj destroyed
|
|
myobj destroyed
|
|
A
|
|
B
|
|
begin
|
|
end
|
|
prevented
|
|
(ok: true, value: "ok")
|
|
@[(kind: P, pChildren: @[])]
|
|
myobj destroyed
|
|
'''
|
|
"""
|
|
|
|
# bug #13102
|
|
|
|
type
|
|
D = ref object
|
|
R = object
|
|
case o: bool
|
|
of false:
|
|
discard
|
|
of true:
|
|
field: D
|
|
|
|
iterator things(): R =
|
|
when true:
|
|
var
|
|
unit = D()
|
|
while true:
|
|
yield R(o: true, field: unit)
|
|
else:
|
|
while true:
|
|
var
|
|
unit = D()
|
|
yield R(o: true, field: unit)
|
|
|
|
proc main =
|
|
var i = 0
|
|
for item in things():
|
|
discard item.field
|
|
inc i
|
|
if i == 2: break
|
|
|
|
main()
|
|
|
|
# bug #13149
|
|
|
|
type
|
|
TMyObj = object
|
|
p: pointer
|
|
len: int
|
|
|
|
proc `=destroy`(o: var TMyObj) =
|
|
if o.p != nil:
|
|
dealloc o.p
|
|
o.p = nil
|
|
echo "myobj destroyed"
|
|
|
|
proc `=copy`(dst: var TMyObj, src: TMyObj) =
|
|
`=destroy`(dst)
|
|
dst.p = alloc(src.len)
|
|
dst.len = src.len
|
|
|
|
proc `=sink`(dst: var TMyObj, src: TMyObj) =
|
|
`=destroy`(dst)
|
|
dst.p = src.p
|
|
dst.len = src.len
|
|
|
|
type
|
|
TObjKind = enum Z, A, B
|
|
TCaseObj = object
|
|
case kind: TObjKind
|
|
of Z: discard
|
|
of A:
|
|
x1: int # this int plays important role
|
|
x2: TMyObj
|
|
of B:
|
|
y: TMyObj
|
|
|
|
proc testSinks: TCaseObj =
|
|
result = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
|
|
result = TCaseObj(kind: B, y: TMyObj(len: 3, p: alloc(3)))
|
|
|
|
proc use(x: TCaseObj) = discard
|
|
|
|
proc testCopies(i: int) =
|
|
var a: array[2, TCaseObj]
|
|
a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
|
|
a[i+1] = a[i] # copy, cannot move
|
|
use(a[i])
|
|
|
|
let x1 = testSinks()
|
|
testCopies(0)
|
|
|
|
# bug #12957
|
|
|
|
type
|
|
PegKind* = enum
|
|
pkCharChoice,
|
|
pkSequence
|
|
Peg* = object ## type that represents a PEG
|
|
case kind: PegKind
|
|
of pkCharChoice: charChoice: ref set[char]
|
|
else: discard
|
|
sons: seq[Peg]
|
|
|
|
proc charSet*(s: set[char]): Peg =
|
|
## constructs a PEG from a character set `s`
|
|
result = Peg(kind: pkCharChoice)
|
|
new(result.charChoice)
|
|
result.charChoice[] = s
|
|
|
|
proc len(a: Peg): int {.inline.} = return a.sons.len
|
|
proc myadd(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
|
|
|
|
proc sequence*(a: openArray[Peg]): Peg =
|
|
result = Peg(kind: pkSequence, sons: @[])
|
|
when false:
|
|
#works too:
|
|
result.myadd(a[0])
|
|
result.myadd(a[1])
|
|
for x in items(a):
|
|
# works:
|
|
#result.sons.add(x)
|
|
# fails:
|
|
result.myadd x
|
|
if result.len == 1:
|
|
result = result.sons[0] # this must not move!
|
|
|
|
when true:
|
|
# bug #12957
|
|
|
|
proc p =
|
|
echo "A"
|
|
let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'}),
|
|
charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})])
|
|
echo "B"
|
|
p()
|
|
|
|
proc testSubObjAssignment =
|
|
echo "begin"
|
|
# There must be extactly one element in the array constructor!
|
|
let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'})])
|
|
echo "end"
|
|
testSubObjAssignment()
|
|
|
|
|
|
#------------------------------------------------
|
|
|
|
type
|
|
MyObject = object
|
|
x1: string
|
|
case kind1: bool
|
|
of false: y1: string
|
|
of true:
|
|
y2: seq[string]
|
|
case kind2: bool
|
|
of true: z1: string
|
|
of false:
|
|
z2: seq[string]
|
|
flag: bool
|
|
x2: string
|
|
|
|
proc test_myobject =
|
|
var x: MyObject = MyObject()
|
|
x.x1 = "x1"
|
|
x.x2 = "x2"
|
|
x.y1 = "ljhkjhkjh"
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind1 = true
|
|
x.y2 = @["1", "2"]
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind2 = true
|
|
x.z1 = "yes"
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind2 = false
|
|
x.z2 = @["1", "2"]
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind2 = true
|
|
x.z1 = "yes"
|
|
x.kind2 = true # should be no effect
|
|
doAssert(x.z1 == "yes")
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind2 = false
|
|
{.cast(uncheckedAssign).}:
|
|
x.kind1 = x.kind2 # support self assignment with effect
|
|
|
|
try:
|
|
x.kind1 = x.flag # flag is not accesible
|
|
except FieldDefect:
|
|
echo "prevented"
|
|
|
|
doAssert(x.x1 == "x1")
|
|
doAssert(x.x2 == "x2")
|
|
|
|
|
|
test_myobject()
|
|
|
|
|
|
#------------------------------------------------
|
|
# bug #14244
|
|
|
|
type
|
|
RocksDBResult*[T] = object
|
|
case ok*: bool
|
|
of true:
|
|
value*: T
|
|
else:
|
|
error*: string
|
|
|
|
proc init(): RocksDBResult[string] =
|
|
result = default(RocksDBResult[string])
|
|
{.cast(uncheckedAssign).}:
|
|
result.ok = true
|
|
result.value = "ok"
|
|
|
|
echo init()
|
|
|
|
|
|
#------------------------------------------------
|
|
# bug #14312
|
|
|
|
type MyObj = object
|
|
case kind: bool
|
|
of false: x0: int # would work with a type like seq[int]; value would be reset
|
|
of true: x1: string
|
|
|
|
var a = MyObj(kind: false, x0: 1234)
|
|
{.cast(uncheckedAssign).}:
|
|
a.kind = true
|
|
doAssert(a.x1 == "")
|
|
|
|
block:
|
|
# bug #15532
|
|
type Kind = enum
|
|
k0, k1
|
|
|
|
type Foo = object
|
|
y: int
|
|
case kind: Kind
|
|
of k0: x0: int
|
|
of k1: x1: int
|
|
|
|
const j0 = Foo(y: 1, kind: k0, x0: 2)
|
|
const j1 = Foo(y: 1, kind: k1, x1: 2)
|
|
|
|
doAssert j0.y == 1
|
|
doAssert j0.kind == k0
|
|
doAssert j1.kind == k1
|
|
|
|
doAssert j1.x1 == 2
|
|
doAssert j0.x0 == 2
|
|
|
|
# ------------------------------------
|
|
# bug #20305
|
|
|
|
type
|
|
ContentNodeKind = enum
|
|
P, Br, Text
|
|
ContentNode = object
|
|
case kind: ContentNodeKind
|
|
of P: pChildren: seq[ContentNode]
|
|
of Br: discard
|
|
of Text: textStr: string
|
|
|
|
proc bug20305 =
|
|
var x = ContentNode(kind: P, pChildren: @[
|
|
ContentNode(kind: P, pChildren: @[ContentNode(kind: Text, textStr: "brrr")])
|
|
])
|
|
x.pChildren.add ContentNode(kind: Br)
|
|
x.pChildren.del(0)
|
|
{.cast(uncheckedAssign).}:
|
|
x.pChildren[0].kind = P
|
|
echo x.pChildren
|
|
|
|
bug20305()
|
|
|
|
# bug #21023
|
|
block:
|
|
block:
|
|
type
|
|
MGErrorKind = enum
|
|
mgeUnexpected, mgeNotFound
|
|
|
|
type Foo = object
|
|
kind: MGErrorKind
|
|
ex: Exception
|
|
|
|
type Boo = object
|
|
a: seq[int]
|
|
|
|
type
|
|
Result2 = object
|
|
case o: bool
|
|
of false:
|
|
e: Foo
|
|
of true:
|
|
v: Boo
|
|
|
|
proc startSessionSync(): Result2 =
|
|
return Result2(o: true)
|
|
|
|
proc mainSync =
|
|
let ff = startSessionSync()
|
|
doAssert ff.o == true
|
|
|
|
mainSync()
|
|
|
|
block:
|
|
type
|
|
MGErrorKind = enum
|
|
mgeUnexpected, mgeNotFound
|
|
|
|
type Foo = object
|
|
kind: MGErrorKind
|
|
ex: Exception
|
|
|
|
type Boo = object
|
|
a: seq[int]
|
|
|
|
type
|
|
Result2 = object
|
|
case o: bool
|
|
of false:
|
|
e: Foo
|
|
of true:
|
|
v: Boo
|
|
s: int
|
|
|
|
proc startSessionSync(): Result2 =
|
|
return Result2(o: true, s: 12)
|
|
|
|
proc mainSync =
|
|
let ff = startSessionSync()
|
|
doAssert ff.s == 12
|
|
|
|
mainSync()
|
|
|
|
import std/sequtils
|
|
|
|
# bug #23690
|
|
type
|
|
SomeObj* = object of RootObj
|
|
|
|
Item* = object
|
|
case kind*: 0..1
|
|
of 0:
|
|
a*: int
|
|
b*: SomeObj
|
|
of 1:
|
|
c*: string
|
|
|
|
ItemExt* = object
|
|
a*: Item
|
|
b*: string
|
|
|
|
proc do1(x: int): seq[(string, Item)] =
|
|
result = @[("zero", Item(kind: 1, c: "first"))]
|
|
|
|
proc do2(x: int, e: ItemExt): seq[(string, ItemExt)] =
|
|
do1(x).map(proc(v: (string, Item)): auto = (v[0], ItemExt(a: v[1], b: e.b)))
|
|
|
|
doAssert $do2(0, ItemExt(a: Item(kind: 1, c: "second"), b: "third")) == """@[("zero", (a: (kind: 1, c: "first"), b: "third"))]"""
|