v2 / vlib / v / tests / conditions / ifs / if_smartcast_test.v
344 lines · 290 sloc · 4.52 KB · c6afba84ade4f27bf4ba448bac7b300bffbacd37
Raw
1struct Abc {
2mut:
3 val string
4}
5
6struct Xyz {
7 name string
8}
9
10type Alphabet = Abc | Xyz
11
12fn test_if_smartcast() {
13 x := Alphabet(Abc{'test'})
14 if x is Abc {
15 assert x.val == 'test'
16 }
17}
18
19fn test_mutable() {
20 mut x := Alphabet(Abc{'original'})
21 if mut x is Abc {
22 assert x.val == 'original'
23 x.val = 'changed'
24 assert x.val == 'changed'
25 }
26 if mut x is Abc {
27 assert x.val == 'changed'
28 }
29}
30
31fn test_mut_smartcast_reassign_same_variant() {
32 mut x := Xya(1)
33 if mut x is int {
34 x = 3
35 assert x == 3
36 } else {
37 assert false
38 }
39 if x is int {
40 assert x == 3
41 } else {
42 assert false
43 }
44}
45
46fn test_nested_if_smartcast() {
47 x := Alphabet(Abc{'test'})
48 y := Alphabet(Xyz{'foo'})
49 if x is Abc {
50 if y is Xyz {
51 assert y.name == 'foo'
52 }
53 }
54}
55
56type Bar = Test | string
57type Xya = int | string
58
59struct Test {
60 x string
61 xya Xya
62}
63
64struct BarWrapper {
65 y Bar
66}
67
68fn test_nested_selector_smartcast() {
69 f := BarWrapper{
70 y: Bar(Test{
71 x: 'Hi'
72 xya: Xya(int(5))
73 })
74 }
75
76 if f.y is Test {
77 z := f.y.x
78 assert f.y.x == 'Hi'
79 assert z == 'Hi'
80 if f.y.xya is int {
81 assert f.y.xya == 5
82 }
83 }
84}
85
86type Inner = int | string
87
88struct InnerStruct {
89 x Inner
90}
91
92type Outer = InnerStruct | string
93
94fn test_nested_if_is() {
95 b := Outer(InnerStruct{Inner(0)})
96 if b is InnerStruct {
97 if b.x is int {
98 assert b.x == 0
99 }
100 }
101}
102
103struct MutContainer {
104mut:
105 abc Alphabet
106}
107
108struct Container {
109 abc Alphabet
110}
111
112fn test_mutable_with_struct() {
113 mut c := MutContainer{Abc{'original'}}
114 if mut c.abc is Abc {
115 assert c.abc.val == 'original'
116 c.abc.val = 'xyz'
117 assert c.abc.val == 'xyz'
118 }
119 if mut c.abc is Abc {
120 // Note: in this second smart cast, `another` is
121 // the same wrapped value, that was changed in
122 // the first smart cast:
123 assert c.abc.val == 'xyz'
124 }
125}
126
127fn test_as_cast_with_struct() {
128 x := Container{Abc{'test'}}
129 if x.abc is Abc {
130 assert x.abc.val == 'test'
131 }
132}
133
134struct CellStr {
135 str string
136}
137
138struct CellInt {
139 itg i64
140}
141
142struct CellFloat {
143 flt f64
144}
145
146struct CellU32 {
147 u u32
148}
149
150type Cell = CellFloat | CellInt | CellStr | CellU32
151
152fn test_mutability() {
153 my_str := 'the quick brown fox jumps over the lazy dog.'
154 my_itg := -1234567890
155 my_flt := 3.14159265358979323846
156 my_u32 := u32(4294967295)
157 cell_str := CellStr{
158 str: my_str
159 }
160 cell_itg := CellInt{
161 itg: my_itg
162 }
163 cell_flt := CellFloat{
164 flt: my_flt
165 }
166 cell_u32 := CellU32{
167 u: my_u32
168 }
169 mut cell := Cell{}
170 cell = cell_str
171 if mut cell is CellStr {
172 println('${cell.str}')
173 }
174 cell = cell_itg
175 if mut cell is CellInt {
176 println('${cell.itg}')
177 }
178 cell = cell_flt
179 if mut cell is CellFloat {
180 println('${cell.flt}')
181 }
182 cell = cell_u32
183 if mut cell is CellU32 {
184 println('${cell.u}')
185 }
186}
187
188type Expr = CTempVarExpr | CallExpr
189
190struct ExprWrapper {
191mut:
192 expr Expr
193}
194
195struct CallExpr {
196 y int
197 x string
198}
199
200struct CTempVarExpr {
201 x string
202}
203
204fn gen(_ Expr) CTempVarExpr {
205 return CTempVarExpr{}
206}
207
208fn test_reassign_from_function_with_parameter_selector() {
209 mut f := ExprWrapper{Expr(CallExpr{})}
210 expr := f.expr
211 if expr is CallExpr {
212 f.expr = gen(expr)
213 }
214}
215
216type Node = Expr | string
217
218fn test_nested_sumtype() {
219 c := Node(Expr(CallExpr{
220 y: 1
221 }))
222 if c is Expr {
223 if c is CallExpr {
224 assert c.y == 1
225 } else {
226 assert false
227 }
228 } else {
229 assert false
230 }
231}
232
233type Food = Eggs | Milk
234
235struct FoodWrapper {
236mut:
237 food Food
238}
239
240struct Milk {
241mut:
242 name string
243}
244
245struct Eggs {
246mut:
247 name string
248}
249
250fn test_if_mut_selector() {
251 mut f := FoodWrapper{Food(Milk{'test'})}
252 if mut f.food is Milk {
253 f.food.name = 'milk'
254 assert f.food.name == 'milk'
255 }
256}
257
258struct NodeWrapper {
259 node Node
260}
261
262fn test_nested_sumtype_selector() {
263 c := NodeWrapper{Node(Expr(CallExpr{
264 y: 1
265 }))}
266 if c.node is Expr {
267 if c.node is CallExpr {
268 assert c.node.y == 1
269 } else {
270 assert false
271 }
272 } else {
273 assert false
274 }
275}
276
277struct Foo1 {
278 a int
279}
280
281struct Foo2 {
282 a int
283}
284
285struct Bar1 {
286 a int
287}
288
289struct Bar2 {
290 a int
291}
292
293type Sum1 = Foo1 | Foo2
294
295type Sum2 = Bar1 | Bar2
296
297type SumAll = Sum1 | Sum2
298
299struct All_in_one {
300pub mut:
301 ptrs []&SumAll
302 ptr &SumAll
303}
304
305fn test_nested_pointer_smartcast() {
306 mut s := All_in_one{
307 ptr: &Sum1(Foo1{
308 a: 1
309 })
310 ptrs: [&SumAll(Sum2(Bar1{
311 a: 3
312 }))]
313 }
314
315 if mut s.ptr is Sum1 {
316 if mut s.ptr is Foo1 {
317 assert s.ptr.a == 1
318 }
319 }
320
321 a := s.ptrs[0]
322 if a is Sum1 {
323 if a is Foo1 {
324 assert a.a == 3
325 }
326 }
327}
328
329struct RefVariantType {
330 value int
331}
332
333type RefSmartcastSum = RefVariantType | int
334
335fn test_reference_sumtype_variant_smartcast() {
336 sum_ref := &RefSmartcastSum(RefVariantType{
337 value: 7
338 })
339 if sum_ref is &RefVariantType {
340 assert sum_ref.value == 7
341 } else {
342 assert false
343 }
344}
345