vq / vlib / v / tests / interfaces / interface_runtime_conversions_test.v
132 lines · 110 sloc · 2.63 KB · e95239926fac88a905b2dc5047c029263d36a6c7
Raw
1interface Widget {
2}
3
4interface ResizableWidget {
5 Widget
6 resize(x int, y int) int
7}
8
9fn draw(w Widget) {
10 // w.resize(10, 20) // <- this won't work, since all Widgets may not implement resize()
11
12 // however, we can check if the underlying type of w implements a different interface:
13 if w is ResizableWidget {
14 assert w is WidgetB
15 rw := w as ResizableWidget
16 assert rw is WidgetB
17 // if so, we can now safely call that extra method
18 assert rw.resize(10, 20) == 200
19 } else {
20 assert w is WidgetA
21 }
22}
23
24fn draw_ref(w &Widget) {
25 if w is ResizableWidget {
26 rw := w as ResizableWidget
27 assert rw.resize(10, 20) == 200
28 } else {
29 assert false
30 }
31}
32
33// implements Widget, but not ResizableWidget
34struct WidgetA {
35}
36
37// implements both Widget and ResizableWidget
38struct WidgetB {
39}
40
41fn (w WidgetB) resize(x int, y int) int {
42 return x * y
43}
44
45fn test_interface_runtime_conversions() {
46 draw(WidgetA{})
47 draw(WidgetB{})
48}
49
50enum CompositeNodeType {
51 int
52 str
53 list
54 block
55}
56
57interface CompositeValue {
58 type_of() CompositeNodeType
59}
60
61interface CompositeNode {
62 values []CompositeValue
63}
64
65type CompositeInt = int
66
67fn (x CompositeInt) type_of() CompositeNodeType {
68 return .int
69}
70
71type CompositeStr = string
72
73fn (x CompositeStr) type_of() CompositeNodeType {
74 return .str
75}
76
77struct CompositeList {
78 values []CompositeValue
79}
80
81fn (x CompositeList) type_of() CompositeNodeType {
82 return .list
83}
84
85struct CompositeBlock {
86 values []CompositeValue
87}
88
89fn (x CompositeBlock) type_of() CompositeNodeType {
90 return .block
91}
92
93fn composite_values_identical(v1 CompositeValue, v2 CompositeValue) bool {
94 if v1.type_of() != v2.type_of() {
95 return false
96 }
97 return match v1 {
98 CompositeInt { v1 == (v2 as CompositeInt) }
99 CompositeStr { v1 == (v2 as CompositeStr) }
100 CompositeList, CompositeBlock { composite_nodes_identical(v1, v2 as CompositeNode) }
101 else { false }
102 }
103}
104
105fn composite_nodes_identical(s1 CompositeNode, s2 CompositeNode) bool {
106 if s1.values.len != s2.values.len {
107 return false
108 }
109 for i := 0; i < s1.values.len; i++ {
110 if !composite_values_identical(s1.values[i], s2.values[i]) {
111 return false
112 }
113 }
114 return true
115}
116
117fn test_interface_runtime_conversions_from_aggregate_smartcast_to_interface() {
118 list1 := CompositeList{
119 values: [CompositeValue(CompositeInt(34)), CompositeStr('foo')]
120 }
121 list2 := CompositeList{
122 values: [CompositeValue(CompositeInt(34)), CompositeStr('bar')]
123 }
124 block1 := CompositeBlock{
125 values: [CompositeValue(CompositeInt(34)), CompositeStr('foo')]
126 }
127 block2 := CompositeBlock{
128 values: [CompositeValue(CompositeInt(34)), CompositeStr('foo')]
129 }
130 assert !composite_values_identical(list1, list2)
131 assert composite_values_identical(block1, block2)
132}
133