summary refs log tree commit diff stats
path: root/tests/converter/tconverter_unique_ptr.nim
blob: 23c1a3d96db3a1a66e82e75a340f2bc32786db36 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
discard """
  targets: "c cpp"
  output: ""
"""

## Bugs 9698 and 9699

type
  UniquePtr*[T] = object
    ## non copyable pointer to object T, exclusive ownership of the object is assumed
    val: ptr T

  MyLen* = distinct int

  MySeq* = object
    ## Vectorized matrix
    len: MyLen  # scalar size
    data: ptr UncheckedArray[float]

proc `$`(x: MyLen): string {.borrow.}
proc `==`(x1, x2: MyLen): bool {.borrow.}


proc `=destroy`*(m: var MySeq) {.inline.} =
  if m.data != nil:
    deallocShared(m.data)
    m.data = nil

proc `=`*(m: var MySeq, m2: MySeq) =
  if m.data == m2.data: return
  if m.data != nil:
    `=destroy`(m)

  m.len = m2.len
  let bytes = m.len.int * sizeof(float)
  if bytes > 0:
    m.data = cast[ptr UncheckedArray[float]](allocShared(bytes))
    copyMem(m.data, m2.data, bytes)

proc `=sink`*(m: var MySeq, m2: MySeq) {.inline.} =
  if m.data != m2.data:
    if m.data != nil:
      `=destroy`(m)
    m.len = m2.len
    m.data = m2.data

proc len*(m: MySeq): MyLen {.inline.} = m.len

proc lenx*(m: var MySeq): MyLen {.inline.} = m.len

proc `[]`*(m: MySeq; i: MyLen): float {.inline.} =
  m.data[i.int]

proc `[]`*(m: var MySeq; i: MyLen): var float {.inline.} =
  m.data[i.int]

proc `[]=`*(m: var MySeq; i: MyLen, val: float) {.inline.} =
  m.data[i.int] = val

proc setTo(s: var MySeq, val: float) =
  for i in 0..<s.len.int:
    s.data[i] = val

proc newMySeq*(size: int, initial_value = 0.0): MySeq =
  result.len = size.MyLen
  if size > 0:
    result.data = cast[ptr UncheckedArray[float]](createShared(float, size))

  result.setTo(initial_value)

converter literalToLen*(x: int{lit}): MyLen =
  x.MyLen


#-------------------------------------------------------------
# Unique pointer implementation
#-------------------------------------------------------------

proc `=destroy`*[T](p: var UniquePtr[T]) =
  if p.val != nil:
    `=destroy`(p.val[])
    dealloc(p.val)
    p.val = nil

proc `=`*[T](dest: var UniquePtr[T], src: UniquePtr[T]) {.error.}

proc `=sink`*[T](dest: var UniquePtr[T], src: UniquePtr[T]) {.inline.} =
  if dest.val != nil and dest.val != src.val:
    `=destroy`(dest)
  dest.val = src.val

proc newUniquePtr*[T](val: sink T): UniquePtr[T] =
  result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
  reset(result.val[])
  result.val[] = val

converter convertPtrToObj*[T](p: UniquePtr[T]): var T =
  result = p.val[]

var pu = newUniquePtr(newMySeq(5, 1.0))
let pu2 = newUniquePtr(newMySeq(5, 1.0))
doAssert: pu.len == 5
doAssert: pu2.len == 5
doAssert: pu.lenx == 5
doAssert: pu2.lenx == 5

pu[0] = 2.0
pu2[0] = 2.0
doAssert pu[0] == 2.0
doAssert: pu2[0] == 2.0

##-----------------------------------------------------------------------------------------
## Bugs #9735 and #9736
type
  ConstPtr*[T] = object
    ## This pointer makes it impossible to change underlying value
    ## as it returns only `lent T`
    val: ptr T

proc `=destroy`*[T](p: var ConstPtr[T]) =
  if p.val != nil:
    `=destroy`(p.val[])
    dealloc(p.val)
    p.val = nil

proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.}

proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} =
  if dest.val != nil and dest.val != src.val:
    `=destroy`(dest)
  dest.val = src.val

proc newConstPtr*[T](val: sink T): ConstPtr[T] =
  result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
  reset(result.val[])
  result.val[] = val

converter convertConstPtrToObj*[T](p: ConstPtr[T]): lent T =
  result = p.val[]

var pc = newConstPtr(newMySeq(3, 1.0))
let pc2 = newConstPtr(newMySeq(3, 1.0))
doAssert: pc.len == 3
doAssert: pc.len == 3
doAssert: compiles(pc.lenx == 2) == false
doAssert: compiles(pc2.lenx == 2) == false
doAssert: compiles(pc[0] = 2.0) == false
doAssert: compiles(pc2[0] = 2.0) == false

doAssert: pc[0] == 1.0
doAssert: pc2[0] == 1.0