...
1
2
3
4
5
6
7
8
9
10
11
12 package devirt
13
14
15
16
17
18
19 import (
20 "fmt"
21
22 "example.com/pgo/devirtualize/mult.pkg"
23 )
24
25 var sink int
26
27 type Adder interface {
28 Add(a, b int) int
29 }
30
31 type Add struct{}
32
33 func (Add) Add(a, b int) int {
34 for i := 0; i < 1000; i++ {
35 sink++
36 }
37 return a + b
38 }
39
40 type Sub struct{}
41
42 func (Sub) Add(a, b int) int {
43 for i := 0; i < 1000; i++ {
44 sink++
45 }
46 return a - b
47 }
48
49
50
51
52 func ExerciseIface(iter int, a1, a2 Adder, m1, m2 mult.Multiplier) int {
53
54
55
56
57 selectI := 0
58 selectA := func(gotI int) Adder {
59 if gotI != selectI {
60 panic(fmt.Sprintf("selectA not called once per iteration; got i %d want %d", gotI, selectI))
61 }
62 selectI++
63
64 if gotI%10 == 0 {
65 return a2
66 }
67 return a1
68 }
69 oneI := 0
70 one := func(gotI int) int {
71 if gotI != oneI {
72 panic(fmt.Sprintf("one not called once per iteration; got i %d want %d", gotI, oneI))
73 }
74 oneI++
75
76
77
78 if selectI != oneI {
79 panic(fmt.Sprintf("selectA not called before not called before one; got i %d want %d", selectI, oneI))
80 }
81
82 return 1
83 }
84
85 val := 0
86 for i := 0; i < iter; i++ {
87 m := m1
88 if i%10 == 0 {
89 m = m2
90 }
91
92
93
94
95
96
97
98
99
100
101 val += m.Multiply(42, selectA(i).Add(one(i), 2))
102 }
103 return val
104 }
105
106 type AddFunc func(int, int) int
107
108 func AddFn(a, b int) int {
109 for i := 0; i < 1000; i++ {
110 sink++
111 }
112 return a + b
113 }
114
115 func SubFn(a, b int) int {
116 for i := 0; i < 1000; i++ {
117 sink++
118 }
119 return a - b
120 }
121
122
123
124
125 func ExerciseFuncConcrete(iter int, a1, a2 AddFunc, m1, m2 mult.MultFunc) int {
126
127
128
129
130 selectI := 0
131 selectA := func(gotI int) AddFunc {
132 if gotI != selectI {
133 panic(fmt.Sprintf("selectA not called once per iteration; got i %d want %d", gotI, selectI))
134 }
135 selectI++
136
137 if gotI%10 == 0 {
138 return a2
139 }
140 return a1
141 }
142 oneI := 0
143 one := func(gotI int) int {
144 if gotI != oneI {
145 panic(fmt.Sprintf("one not called once per iteration; got i %d want %d", gotI, oneI))
146 }
147 oneI++
148
149
150
151 if selectI != oneI {
152 panic(fmt.Sprintf("selectA not called before not called before one; got i %d want %d", selectI, oneI))
153 }
154
155 return 1
156 }
157
158 val := 0
159 for i := 0; i < iter; i++ {
160 m := m1
161 if i%10 == 0 {
162 m = m2
163 }
164
165
166
167
168
169
170
171
172
173 val += int(m(42, int64(selectA(i)(one(i), 2))))
174 }
175 return val
176 }
177
178
179
180
181
182
183
184 func ExerciseFuncField(iter int, a1, a2 AddFunc, m1, m2 mult.MultFunc) int {
185 ops := struct {
186 a AddFunc
187 m mult.MultFunc
188 }{}
189
190 val := 0
191 for i := 0; i < iter; i++ {
192 ops.a = a1
193 ops.m = m1
194 if i%10 == 0 {
195 ops.a = a2
196 ops.m = m2
197 }
198
199
200
201
202
203
204
205
206
207 val += int(ops.m(42, int64(ops.a(1, 2))))
208 }
209 return val
210 }
211
212
213 func AddClosure() AddFunc {
214
215 var a Add
216 return a.Add
217 }
218
219
220 func SubClosure() AddFunc {
221 var s Sub
222 return s.Add
223 }
224
225
226
227
228
229
230
231 func ExerciseFuncClosure(iter int, a1, a2 AddFunc, m1, m2 mult.MultFunc) int {
232 val := 0
233 for i := 0; i < iter; i++ {
234 a := a1
235 m := m1
236 if i%10 == 0 {
237 a = a2
238 m = m2
239 }
240
241
242
243
244
245
246
247
248
249 val += int(m(42, int64(a(1, 2))))
250 }
251 return val
252 }
253
View as plain text