github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/calls.go (about) 1 package main 2 3 type Thing struct { 4 name string 5 } 6 7 type ThingOption func(*Thing) 8 9 func WithName(name string) ThingOption { 10 return func(t *Thing) { 11 t.name = name 12 } 13 } 14 15 func NewThing(opts ...ThingOption) *Thing { 16 t := &Thing{} 17 for _, opt := range opts { 18 opt(t) 19 } 20 return t 21 } 22 23 func (t Thing) String() string { 24 return t.name 25 } 26 27 func (t Thing) Print(arg string) { 28 println("Thing.Print:", t.name, "arg:", arg) 29 } 30 31 type Printer interface { 32 Print(string) 33 } 34 35 func main() { 36 thing := &Thing{"foo"} 37 38 // function pointers 39 runFunc(hello, 5) // must be indirect to avoid obvious inlining 40 41 // deferred functions 42 testDefer() 43 44 // defers in loop 45 testDeferLoop() 46 47 //defer func variable call 48 testDeferFuncVar() 49 50 //More complicated func variable call 51 testMultiFuncVar() 52 53 // Take a bound method and use it as a function pointer. 54 // This function pointer needs a context pointer. 55 testBound(thing.String) 56 57 // closures 58 func() { 59 println("thing inside closure:", thing.String()) 60 }() 61 runFunc(func(i int) { 62 println("inside fp closure:", thing.String(), i) 63 }, 3) 64 65 // functional arguments 66 thingFunctionalArgs1 := NewThing() 67 thingFunctionalArgs1.Print("functional args 1") 68 thingFunctionalArgs2 := NewThing(WithName("named thing")) 69 thingFunctionalArgs2.Print("functional args 2") 70 71 // regression testing 72 regression1033() 73 74 //Test deferred builtins 75 testDeferBuiltinClose() 76 testDeferBuiltinDelete() 77 78 // Check for issue 1304. 79 // There are two fields in this struct, one of which is zero-length so the 80 // other covers the entire struct. This led to a verification error for 81 // debug info, which used DW_OP_LLVM_fragment for a field that practically 82 // covered the entire variable. 83 var x issue1304 84 x.call() 85 86 if testDeferElse(false) != 0 { 87 println("else defer returned wrong value") 88 } 89 } 90 91 func runFunc(f func(int), arg int) { 92 f(arg) 93 } 94 95 func hello(n int) { 96 println("hello from function pointer:", n) 97 } 98 99 func testDefer() { 100 defer exportedDefer() 101 102 i := 1 103 defer deferred("...run as defer", i) 104 i++ 105 defer func() { 106 println("...run closure deferred:", i) 107 }() 108 i++ 109 defer deferred("...run as defer", i) 110 i++ 111 112 var t Printer = &Thing{"foo"} 113 defer t.Print("bar") 114 115 println("deferring...") 116 d := dumb{} 117 defer d.Value(0) 118 } 119 120 func testDeferLoop() { 121 for j := 0; j < 4; j++ { 122 defer deferred("loop", j) 123 } 124 } 125 126 func testDeferFuncVar() { 127 dummy, f := deferFunc() 128 dummy++ 129 defer f(1) 130 } 131 132 func testMultiFuncVar() { 133 f := multiFuncDefer() 134 defer f(1) 135 } 136 137 func testDeferBuiltinClose() { 138 i := make(chan int) 139 func() { 140 defer close(i) 141 }() 142 if n, ok := <-i; n != 0 || ok { 143 println("expected to read 0 from closed channel") 144 } 145 } 146 147 func testDeferBuiltinDelete() { 148 m := map[int]int{3: 30, 5: 50} 149 func() { 150 defer delete(m, 3) 151 if m[3] != 30 { 152 println("expected m[3] to be 30") 153 } 154 }() 155 if m[3] != 0 { 156 println("expected m[3] to be 0") 157 } 158 } 159 160 type dumb struct { 161 } 162 163 func (*dumb) Value(key interface{}) interface{} { 164 return nil 165 } 166 167 func deferred(msg string, i int) { 168 println(msg, i) 169 } 170 171 //export __exportedDefer 172 func exportedDefer() { 173 println("...exported defer") 174 } 175 176 func deferFunc() (int, func(int)) { 177 return 0, func(i int) { println("...extracted defer func ", i) } 178 } 179 180 func multiFuncDefer() func(int) { 181 i := 0 182 183 if i > 0 { 184 return func(i int) { println("Should not have gotten here. i = ", i) } 185 } 186 187 return func(i int) { println("Called the correct function. i = ", i) } 188 } 189 190 func testBound(f func() string) { 191 println("bound method:", f()) 192 } 193 194 // regression1033 is a regression test for https://github.com/tinygo-org/tinygo/issues/1033. 195 // In previous versions of the compiler, a deferred call to an interface would create an instruction that did not dominate its uses. 196 func regression1033() { 197 foo(&Bar{}) 198 } 199 200 type Bar struct { 201 empty bool 202 } 203 204 func (b *Bar) Close() error { 205 return nil 206 } 207 208 type Closer interface { 209 Close() error 210 } 211 212 func foo(bar *Bar) error { 213 var a int 214 if !bar.empty { 215 a = 10 216 if a != 5 { 217 return nil 218 } 219 } 220 221 var c Closer = bar 222 defer c.Close() 223 224 return nil 225 } 226 227 type issue1304 struct { 228 a [0]int // zero-length field 229 b int // field 'b' covers entire struct 230 } 231 232 func (x issue1304) call() { 233 // nothing to do 234 } 235 236 type recursiveFuncType func(recursiveFuncType) 237 238 var recursiveFunction recursiveFuncType 239 240 //go:noinline 241 func testDeferElse(b bool) (r int) { 242 if !b { 243 defer func() { 244 r = 0 245 246 }() 247 } 248 249 return 1 250 }