main.go raw
1 package main
2
3 import (
4 "fmt"
5 "os"
6 "os/exec"
7 "path/filepath"
8 "strings"
9 "unsafe"
10
11 "github.com/ebitengine/purego"
12 )
13
14 func concatMxSources(dir string, files []string) ([]byte, int, int) {
15 imports := map[string]bool{}
16 var bodies [][]byte
17 totalLines := 0
18 fileCount := 0
19 for _, name := range files {
20 data, err := os.ReadFile(filepath.Join(dir, name))
21 if err != nil {
22 fmt.Fprintf(os.Stderr, "SKIP file %s: %v\n", name, err)
23 continue
24 }
25 fileCount++
26 totalLines += strings.Count(string(data), "\n")
27 lines := strings.Split(string(data), "\n")
28 var body []string
29 i := 0
30 for i < len(lines) {
31 line := strings.TrimSpace(lines[i])
32 if strings.HasPrefix(line, "package ") {
33 i++
34 continue
35 }
36 if line == "import (" {
37 i++
38 for i < len(lines) {
39 imp := strings.TrimSpace(lines[i])
40 i++
41 if imp == ")" {
42 break
43 }
44 if imp != "" {
45 imports[imp] = true
46 }
47 }
48 continue
49 }
50 if strings.HasPrefix(line, "import ") && !strings.HasPrefix(line, "import (") {
51 imp := strings.TrimPrefix(line, "import ")
52 imports[imp] = true
53 i++
54 continue
55 }
56 body = append(body, lines[i])
57 i++
58 }
59 bodies = append(bodies, []byte(strings.Join(body, "\n")))
60 }
61 var out []byte
62 out = append(out, []byte("package main\n")...)
63 if len(imports) > 0 {
64 out = append(out, []byte("import (\n")...)
65 for imp := range imports {
66 out = append(out, '\t')
67 out = append(out, []byte(imp)...)
68 out = append(out, '\n')
69 }
70 out = append(out, []byte(")\n")...)
71 }
72 for _, b := range bodies {
73 out = append(out, b...)
74 out = append(out, '\n')
75 }
76 return out, fileCount, totalLines
77 }
78
79 func main() {
80 if len(os.Args) < 2 {
81 fmt.Fprintf(os.Stderr, "usage: %s <path-to-compile.so>\n", os.Args[0])
82 os.Exit(1)
83 }
84 soPath := os.Args[1]
85 if !filepath.IsAbs(soPath) {
86 wd, _ := os.Getwd()
87 soPath = filepath.Join(wd, soPath)
88 }
89
90 lib, err := purego.Dlopen(soPath, purego.RTLD_NOW|purego.RTLD_GLOBAL)
91 if err != nil {
92 fmt.Fprintf(os.Stderr, "dlopen %s: %v\n", soPath, err)
93 os.Exit(1)
94 }
95
96 var compileToIR func(uintptr, int32, uintptr, int32, uintptr, int32) int32
97 purego.RegisterLibFunc(&compileToIR, lib, "moxie_compile_to_ir")
98
99 var irLen func(int32) int32
100 purego.RegisterLibFunc(&irLen, lib, "moxie_compile_ir_len")
101
102 var irCopy func(int32, uintptr, int32) int32
103 purego.RegisterLibFunc(&irCopy, lib, "moxie_compile_ir_copy")
104
105 var irFree func(int32)
106 purego.RegisterLibFunc(&irFree, lib, "moxie_compile_ir_free")
107
108 var registerPackage func(uintptr, int32, uintptr, int32)
109 purego.RegisterLibFunc(®isterPackage, lib, "moxie_register_package")
110
111 var registerFunc func(uintptr, int32, uintptr, int32, uintptr, int32)
112 purego.RegisterLibFunc(®isterFunc, lib, "moxie_register_func")
113
114 var registerVar func(uintptr, int32, uintptr, int32, uintptr, int32)
115 purego.RegisterLibFunc(®isterVar, lib, "moxie_register_var")
116
117 var clearImports func()
118 purego.RegisterLibFunc(&clearImports, lib, "moxie_clear_imports")
119
120 var registerIface func(uintptr, int32, uintptr, int32, uintptr, int32)
121 purego.RegisterLibFunc(®isterIface, lib, "moxie_register_iface")
122
123 regPkg := func(path, name string) {
124 pb := []byte(path)
125 nb := []byte(name)
126 registerPackage(uintptr(unsafe.Pointer(&pb[0])), int32(len(pb)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)))
127 }
128 regFn := func(pkgPath, name, sig string) {
129 pp := []byte(pkgPath)
130 nb := []byte(name)
131 if sig == "" {
132 registerFunc(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), 0, 0)
133 return
134 }
135 sb := []byte(sig)
136 registerFunc(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), uintptr(unsafe.Pointer(&sb[0])), int32(len(sb)))
137 }
138 regVar := func(pkgPath, name, typ string) {
139 pp := []byte(pkgPath)
140 nb := []byte(name)
141 tb := []byte(typ)
142 registerVar(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), uintptr(unsafe.Pointer(&tb[0])), int32(len(tb)))
143 }
144 _ = regVar
145 regIface := func(pkgPath, name, methods string) {
146 pp := []byte(pkgPath)
147 nb := []byte(name)
148 mb := []byte(methods)
149 registerIface(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), uintptr(unsafe.Pointer(&mb[0])), int32(len(mb)))
150 }
151 _ = regIface
152
153 // Subprocess mode: compile a single file and report result
154 if len(os.Args) >= 4 && os.Args[2] == "--compile-file" {
155 src, err := os.ReadFile(os.Args[3])
156 if err != nil {
157 fmt.Fprintf(os.Stderr, "read error: %v", err)
158 os.Exit(1)
159 }
160 // Warm up: compile a trivial source to initialize universe types (Typ[] etc.)
161 // before registering imports that depend on parseTypeDesc.
162 warmup := []byte("package main\nfunc main() {}\n")
163 wpkg := []byte("main")
164 wh := compileToIR(
165 uintptr(unsafe.Pointer(&warmup[0])), int32(len(warmup)),
166 uintptr(unsafe.Pointer(&wpkg[0])), int32(len(wpkg)),
167 uintptr(unsafe.Pointer(&[]byte("x86_64-unknown-linux-musl")[0])), 25,
168 )
169 irFree(wh)
170 clearImports()
171 regPkg("go/token", "token")
172 regVar("go/token", "ARROW", "int")
173 regVar("go/token", "DEFAULT", "int")
174 regPkg("go/constant", "constant")
175 regIface("go/constant", "Value", "Kind=->int;String=->string;ExactString=->string")
176 regFn("go/constant", "MakeInt64", "int64->interface{}")
177 regFn("go/constant", "MakeFloat64", "float64->interface{}")
178 regFn("go/constant", "MakeString", "string->interface{}")
179 regFn("go/constant", "MakeFromLiteral", "string,int,int->interface{}")
180 regFn("go/constant", "BinaryOp", "interface{},int,interface{}->interface{}")
181 regFn("go/constant", "UnaryOp", "int,interface{},int->interface{}")
182 regFn("go/constant", "Compare", "interface{},int,interface{}->bool")
183 regFn("go/constant", "StringVal", "interface{}->string")
184 regFn("go/constant", "Int64Val", "interface{}->int64,bool")
185 regFn("go/constant", "Uint64Val", "interface{}->uint64,bool")
186 regFn("go/constant", "Float64Val", "interface{}->float64,bool")
187 regFn("go/constant", "BitLen", "interface{}->int")
188 regFn("go/constant", "Sign", "interface{}->int")
189 regPkg("fmt", "fmt")
190 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
191 regFn("fmt", "Fprintf", "interface{},string,interface{},interface{}->int,error")
192 regPkg("os", "os")
193 regVar("os", "Stderr", "interface{}")
194 regPkg("strconv", "strconv")
195 regFn("strconv", "Itoa", "int->string")
196 regFn("strconv", "FormatInt", "int64,int->string")
197 regFn("strconv", "FormatFloat", "float64,byte,int,int->string")
198 regPkg("bytes", "bytes")
199 regFn("bytes", "NewReader", "*byte->interface{}")
200 regFn("bytes", "IndexByte", "[]byte,byte->int")
201 regFn("bytes", "HasPrefix", "[]byte,[]byte->bool")
202 regFn("bytes", "TrimSpace", "[]byte->[]byte")
203 regPkg("io", "io")
204 regIface("io", "Reader", "Read=[]byte->int,error")
205 regVar("io", "EOF", "error")
206 regVar("io", "ErrNoProgress", "error")
207 regPkg("runtime", "runtime")
208 regFn("runtime", "InitCShared", "")
209 regPkg("unsafe", "unsafe")
210 regPkg("unicode", "unicode")
211 regFn("unicode", "IsLetter", "int32->bool")
212 regFn("unicode", "IsDigit", "int32->bool")
213 regFn("unicode", "IsSpace", "int32->bool")
214 regPkg("unicode/utf8", "utf8")
215 regFn("unicode/utf8", "DecodeRune", "[]byte->int32,int")
216 regFn("unicode/utf8", "RuneLen", "int32->int")
217 regVar("unicode/utf8", "RuneSelf", "int")
218 regVar("unicode/utf8", "UTFMax", "int")
219 regVar("unicode/utf8", "RuneError", "int32")
220 regFn("unicode/utf8", "FullRune", "[]byte->bool")
221 triple := []byte("x86_64-unknown-linux-musl")
222 pkg := []byte("main")
223 fmt.Fprintf(os.Stderr, "[sub] compiling %d bytes from %s\n", len(src), os.Args[3])
224 h := compileToIR(
225 uintptr(unsafe.Pointer(&src[0])), int32(len(src)),
226 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
227 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
228 )
229 fmt.Fprintf(os.Stderr, "[sub] compile returned h=%d\n", h)
230 l := irLen(h)
231 if l == 0 {
232 fmt.Print("IR=0")
233 os.Exit(0)
234 }
235 buf := make([]byte, l)
236 irCopy(h, uintptr(unsafe.Pointer(&buf[0])), l)
237 ir := string(buf)
238 funcCount := strings.Count(ir, "\ndefine ")
239 if funcCount == 0 {
240 fmt.Printf("IR=%d funcs=%d\n%s", len(ir), funcCount, ir)
241 } else {
242 fmt.Printf("IR=%d funcs=%d", len(ir), funcCount)
243 }
244 if len(os.Args) >= 5 && os.Args[4] != "" {
245 os.WriteFile(os.Args[4], []byte(ir), 0644)
246 fmt.Fprintf(os.Stderr, "[sub] wrote IR to %s\n", os.Args[4])
247 }
248 irFree(h)
249 os.Exit(0)
250 }
251
252 pass := 0
253 fail := 0
254 assert := func(name string, cond bool) {
255 if cond {
256 pass++
257 } else {
258 fail++
259 fmt.Fprintf(os.Stderr, "FAIL: %s\n", name)
260 }
261 }
262
263 llvmVerify := func(name, ir string) {
264 if ir == "" {
265 fail++
266 fmt.Fprintf(os.Stderr, "FAIL: %s llvm-verify (empty IR)\n", name)
267 return
268 }
269 cmd := exec.Command("llvm-as-19", "-o", "/dev/null")
270 cmd.Stdin = strings.NewReader(ir)
271 out, err := cmd.CombinedOutput()
272 if err != nil {
273 fail++
274 fmt.Fprintf(os.Stderr, "FAIL: %s llvm-verify: %s\n%s\n", name, err, out)
275 } else {
276 pass++
277 }
278 }
279
280 getIR := func(h int32) string {
281 n := irLen(h)
282 if n <= 0 {
283 return ""
284 }
285 buf := make([]byte, n)
286 got := irCopy(h, uintptr(unsafe.Pointer(&buf[0])), n)
287 return string(buf[:got])
288 }
289
290 name1 := []byte("mypkg")
291 triple := []byte("x86_64-unknown-linux-musl")
292
293 dumpTests := map[int]bool{}
294 test := func(num int, src string, checks func(string)) {
295 srcb := []byte(src)
296 pkg := []byte("main")
297 if strings.HasPrefix(src, "package mypkg") {
298 pkg = name1
299 }
300 h := compileToIR(
301 uintptr(unsafe.Pointer(&srcb[0])), int32(len(srcb)),
302 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
303 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
304 )
305 ir := getIR(h)
306 if ir == "" {
307 fail++
308 fmt.Fprintf(os.Stderr, "FAIL: test %d: empty IR\n", num)
309 irFree(h)
310 return
311 }
312 if dumpTests[num] {
313 fmt.Fprintf(os.Stderr, "=== IR test %d ===\n%s\n", num, ir)
314 }
315 llvmVerify(fmt.Sprintf("test %d", num), ir)
316 checks(ir)
317 irFree(h)
318 }
319 _ = test
320
321 // Test 1: Simple add function
322 src1 := []byte(`package mypkg
323
324 func add(a, b int32) int32 {
325 return a + b
326 }
327 `)
328 h1 := compileToIR(
329 uintptr(unsafe.Pointer(&src1[0])), int32(len(src1)),
330 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
331 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
332 )
333 assert("compile returns handle >= 0", h1 >= 0)
334
335 ir1 := getIR(h1)
336 fmt.Println("=== IR for add ===")
337 fmt.Println(ir1)
338
339 llvmVerify("add", ir1)
340 assert("IR contains target triple", strings.Contains(ir1, "x86_64"))
341 assert("IR contains define", strings.Contains(ir1, "define"))
342 assert("IR contains @mypkg.add", strings.Contains(ir1, "@mypkg.add"))
343 assert("IR contains i32", strings.Contains(ir1, "i32"))
344 assert("IR contains add instruction", strings.Contains(ir1, "add i32"))
345 assert("IR contains ret", strings.Contains(ir1, "ret i32"))
346 assert("IR contains entry block", strings.Contains(ir1, "entry:"))
347
348 irFree(h1)
349
350 // Test 2: Control flow (if/else)
351 src2 := []byte(`package mypkg
352
353 func max(a, b int32) int32 {
354 if a > b {
355 return a
356 }
357 return b
358 }
359 `)
360 h2 := compileToIR(
361 uintptr(unsafe.Pointer(&src2[0])), int32(len(src2)),
362 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
363 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
364 )
365 ir2 := getIR(h2)
366 fmt.Println("=== IR for max ===")
367 fmt.Println(ir2)
368
369 llvmVerify("max", ir2)
370 assert("max IR contains icmp", strings.Contains(ir2, "icmp"))
371 assert("max IR contains br", strings.Contains(ir2, "br"))
372 assert("max IR contains multiple blocks", strings.Count(ir2, ":") >= 2)
373
374 irFree(h2)
375
376 // Test 3: Global variables
377 src3 := []byte(`package mypkg
378
379 var counter int32
380
381 func inc() {
382 counter = counter + 1
383 }
384 `)
385 h3 := compileToIR(
386 uintptr(unsafe.Pointer(&src3[0])), int32(len(src3)),
387 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
388 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
389 )
390 ir3 := getIR(h3)
391 fmt.Println("=== IR for counter ===")
392 fmt.Println(ir3)
393
394 llvmVerify("counter", ir3)
395 assert("counter IR has global", strings.Contains(ir3, "@mypkg.counter"))
396 assert("counter IR has global decl", strings.Contains(ir3, "global"))
397
398 irFree(h3)
399
400 // Test 4: Function calls
401 src4 := []byte(`package mypkg
402
403 func double(x int32) int32 {
404 return x + x
405 }
406
407 func quadruple(x int32) int32 {
408 return double(double(x))
409 }
410 `)
411 h4 := compileToIR(
412 uintptr(unsafe.Pointer(&src4[0])), int32(len(src4)),
413 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
414 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
415 )
416 ir4 := getIR(h4)
417 fmt.Println("=== IR for calls ===")
418 fmt.Println(ir4)
419
420 llvmVerify("calls", ir4)
421 assert("calls IR has call instruction", strings.Contains(ir4, "call"))
422 assert("calls IR has @mypkg.double", strings.Contains(ir4, "@mypkg.double"))
423 assert("calls IR has @mypkg.quadruple", strings.Contains(ir4, "@mypkg.quadruple"))
424
425 irFree(h4)
426
427 // Test 5: For loop
428 src5 := []byte(`package mypkg
429
430 func sum(n int32) int32 {
431 s := int32(0)
432 i := int32(0)
433 for i < n {
434 s = s + i
435 i = i + 1
436 }
437 return s
438 }
439 `)
440 h5 := compileToIR(
441 uintptr(unsafe.Pointer(&src5[0])), int32(len(src5)),
442 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
443 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
444 )
445 ir5 := getIR(h5)
446 fmt.Println("=== IR for loop ===")
447 fmt.Println(ir5)
448
449 llvmVerify("loop", ir5)
450 assert("loop IR has phi or branch back", strings.Contains(ir5, "br"))
451 assert("loop IR has icmp", strings.Contains(ir5, "icmp"))
452 assert("loop IR has multiple blocks", strings.Count(ir5, ":") >= 3)
453
454 irFree(h5)
455
456 // Test 6: Type conversion
457 src6 := []byte(`package mypkg
458
459 func widen(x int32) int64 {
460 return int64(x)
461 }
462
463 func narrow(x int64) int32 {
464 return int32(x)
465 }
466 `)
467 h6 := compileToIR(
468 uintptr(unsafe.Pointer(&src6[0])), int32(len(src6)),
469 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
470 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
471 )
472 ir6 := getIR(h6)
473 fmt.Println("=== IR for conversions ===")
474 fmt.Println(ir6)
475
476 llvmVerify("conversions", ir6)
477 assert("widen IR has sext", strings.Contains(ir6, "sext"))
478 assert("narrow IR has trunc", strings.Contains(ir6, "trunc"))
479
480 irFree(h6)
481
482 // Test 7: Pointer operations
483 src7 := []byte(`package mypkg
484
485 func setPtr(p *int32, v int32) {
486 *p = v
487 }
488
489 func getPtr(p *int32) int32 {
490 return *p
491 }
492 `)
493 h7 := compileToIR(
494 uintptr(unsafe.Pointer(&src7[0])), int32(len(src7)),
495 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
496 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
497 )
498 ir7 := getIR(h7)
499 fmt.Println("=== IR for pointers ===")
500 fmt.Println(ir7)
501
502 llvmVerify("pointers", ir7)
503 assert("setPtr IR has store", strings.Contains(ir7, "store"))
504 assert("getPtr IR has load", strings.Contains(ir7, "load"))
505 assert("pointer IR has ptr param", strings.Contains(ir7, "ptr %p"))
506
507 irFree(h7)
508
509 // Test 8: Boolean operations
510 src8 := []byte(`package mypkg
511
512 func both(a, b bool) bool {
513 if a {
514 if b {
515 return true
516 }
517 }
518 return false
519 }
520 `)
521 h8 := compileToIR(
522 uintptr(unsafe.Pointer(&src8[0])), int32(len(src8)),
523 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
524 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
525 )
526 ir8 := getIR(h8)
527 fmt.Println("=== IR for booleans ===")
528 fmt.Println(ir8)
529
530 llvmVerify("booleans", ir8)
531 assert("bool IR has i1 type", strings.Contains(ir8, "i1"))
532 assert("bool IR has br", strings.Contains(ir8, "br"))
533 assert("bool IR has true/false", strings.Contains(ir8, "true") || strings.Contains(ir8, "false"))
534
535 irFree(h8)
536
537 // Test 9: Structs
538 src9 := []byte(`package mypkg
539
540 type Point struct {
541 X int32
542 Y int32
543 }
544
545 func getX(p Point) int32 {
546 return p.X
547 }
548
549 func setY(p *Point, v int32) {
550 p.Y = v
551 }
552 `)
553 h9 := compileToIR(
554 uintptr(unsafe.Pointer(&src9[0])), int32(len(src9)),
555 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
556 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
557 )
558 ir9 := getIR(h9)
559 fmt.Println("=== IR for structs ===")
560 fmt.Println(ir9)
561
562 llvmVerify("structs", ir9)
563 assert("struct IR has getelementptr", strings.Contains(ir9, "getelementptr"))
564 assert("struct IR has i32 field type", strings.Contains(ir9, "i32"))
565 assert("struct IR has struct type", strings.Contains(ir9, "{") && strings.Contains(ir9, "}"))
566
567 irFree(h9)
568
569 // Test 10: Multiple return values
570 src10 := []byte(`package mypkg
571
572 func divmod(a, b int32) (int32, int32) {
573 return a / b, a % b
574 }
575 `)
576 h10 := compileToIR(
577 uintptr(unsafe.Pointer(&src10[0])), int32(len(src10)),
578 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
579 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
580 )
581 ir10 := getIR(h10)
582 fmt.Println("=== IR for multi-return ===")
583 fmt.Println(ir10)
584
585 llvmVerify("multi-return", ir10)
586 assert("multi-ret IR has sdiv", strings.Contains(ir10, "sdiv"))
587 assert("multi-ret IR has srem", strings.Contains(ir10, "srem"))
588 assert("multi-ret IR has insertvalue", strings.Contains(ir10, "insertvalue"))
589
590 irFree(h10)
591
592 // Test 11: Short variable declaration and address-of
593 src11 := []byte(`package mypkg
594
595 func newInt(v int32) *int32 {
596 x := v
597 return &x
598 }
599 `)
600 h11 := compileToIR(
601 uintptr(unsafe.Pointer(&src11[0])), int32(len(src11)),
602 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
603 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
604 )
605 ir11 := getIR(h11)
606 fmt.Println("=== IR for addr-of ===")
607 fmt.Println(ir11)
608
609 llvmVerify("addr-of", ir11)
610 assert("addr-of IR has alloca", strings.Contains(ir11, "alloca"))
611 assert("addr-of IR returns ptr", strings.Contains(ir11, "ret ptr"))
612
613 irFree(h11)
614
615 // Test 12: Unsigned operations
616 src12 := []byte(`package mypkg
617
618 func udiv(a, b uint32) uint32 {
619 return a / b
620 }
621
622 func ucomp(a, b uint32) bool {
623 return a < b
624 }
625 `)
626 h12 := compileToIR(
627 uintptr(unsafe.Pointer(&src12[0])), int32(len(src12)),
628 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
629 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
630 )
631 ir12 := getIR(h12)
632 fmt.Println("=== IR for unsigned ===")
633 fmt.Println(ir12)
634
635 llvmVerify("unsigned", ir12)
636 assert("unsigned IR has udiv", strings.Contains(ir12, "udiv"))
637 assert("unsigned IR has ult", strings.Contains(ir12, "ult"))
638
639 irFree(h12)
640
641 // Test 13: Extract from multi-return call
642 src13 := []byte(`package mypkg
643
644 func divmod(a, b int32) (int32, int32) {
645 return a / b, a % b
646 }
647
648 func justQuot(a, b int32) int32 {
649 q, _ := divmod(a, b)
650 return q
651 }
652
653 func justRem(a, b int32) int32 {
654 _, r := divmod(a, b)
655 return r
656 }
657 `)
658 h13 := compileToIR(
659 uintptr(unsafe.Pointer(&src13[0])), int32(len(src13)),
660 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
661 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
662 )
663 ir13 := getIR(h13)
664 fmt.Println("=== IR for extract ===")
665 fmt.Println(ir13)
666
667 llvmVerify("extract", ir13)
668 assert("extract IR has call", strings.Contains(ir13, "call {i32, i32}"))
669 assert("extract IR has extractvalue", strings.Contains(ir13, "extractvalue"))
670 assert("extract IR has extractvalue 0", strings.Contains(ir13, ", 0"))
671 assert("extract IR has extractvalue 1", strings.Contains(ir13, ", 1"))
672
673 irFree(h13)
674
675 // Test 14: Slice operations - make, len, cap, index
676 src14 := []byte(`package mypkg
677
678 func sliceLen(s []int32) int32 {
679 return len(s)
680 }
681
682 func sliceCap(s []int32) int32 {
683 return cap(s)
684 }
685
686 func sliceGet(s []int32, i int32) int32 {
687 return s[i]
688 }
689
690 func sliceSet(s []int32, i int32, v int32) {
691 s[i] = v
692 }
693 `)
694 h14 := compileToIR(
695 uintptr(unsafe.Pointer(&src14[0])), int32(len(src14)),
696 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
697 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
698 )
699 ir14 := getIR(h14)
700 fmt.Println("=== IR for slices ===")
701 fmt.Println(ir14)
702
703 llvmVerify("slices", ir14)
704 assert("slice len extracts field 1", strings.Contains(ir14, "extractvalue {ptr, i64, i64}") && strings.Contains(ir14, ", 1"))
705 assert("slice cap extracts field 2", strings.Contains(ir14, ", 2"))
706 assert("slice index has extractvalue 0", strings.Contains(ir14, ", 0"))
707 assert("slice index has getelementptr", strings.Contains(ir14, "getelementptr"))
708
709 irFree(h14)
710
711 // Test 15: Slice sub-expression
712 src15 := []byte(`package mypkg
713
714 func subslice(s []int32, lo, hi int32) []int32 {
715 return s[lo:hi]
716 }
717 `)
718 h15 := compileToIR(
719 uintptr(unsafe.Pointer(&src15[0])), int32(len(src15)),
720 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
721 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
722 )
723 ir15 := getIR(h15)
724 fmt.Println("=== IR for subslice ===")
725 fmt.Println(ir15)
726
727 llvmVerify("subslice", ir15)
728 assert("subslice has extractvalue", strings.Contains(ir15, "extractvalue"))
729 assert("subslice has getelementptr", strings.Contains(ir15, "getelementptr"))
730 assert("subslice has insertvalue", strings.Contains(ir15, "insertvalue"))
731 assert("subslice has sub for new len", strings.Contains(ir15, "sub"))
732
733 irFree(h15)
734
735 // Test 16: make([]T, n) and append
736 src16 := []byte(`package mypkg
737
738 func makeSlice(n int32) []int32 {
739 return make([]int32, n)
740 }
741
742 func makeAndAppend(n int32) []int32 {
743 s := make([]int32, 0, n)
744 i := int32(0)
745 for i < n {
746 s = append(s, i)
747 i = i + 1
748 }
749 return s
750 }
751 `)
752 h16 := compileToIR(
753 uintptr(unsafe.Pointer(&src16[0])), int32(len(src16)),
754 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
755 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
756 )
757 ir16 := getIR(h16)
758 fmt.Println("=== IR for make+append ===")
759 fmt.Println(ir16)
760
761 llvmVerify("make+append", ir16)
762 assert("make has runtime.alloc", strings.Contains(ir16, "@runtime.alloc"))
763 assert("make has insertvalue for slice", strings.Contains(ir16, "insertvalue"))
764 assert("append has sliceAppend", strings.Contains(ir16, "@runtime.sliceAppend"))
765
766 irFree(h16)
767
768 // Test 17: Switch statement
769 src17 := []byte(`package mypkg
770
771 func classify(x int32) int32 {
772 switch {
773 case x < 0:
774 return -1
775 case x == 0:
776 return 0
777 }
778 return 1
779 }
780 `)
781 h17 := compileToIR(
782 uintptr(unsafe.Pointer(&src17[0])), int32(len(src17)),
783 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
784 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
785 )
786 ir17 := getIR(h17)
787 fmt.Println("=== IR for switch ===")
788 fmt.Println(ir17)
789
790 llvmVerify("switch", ir17)
791 assert("switch has icmp", strings.Contains(ir17, "icmp"))
792 assert("switch has multiple br", strings.Count(ir17, "br ") >= 2)
793
794 irFree(h17)
795
796 // Test 18: Nested struct access
797 src18 := []byte(`package mypkg
798
799 type Inner struct {
800 V int32
801 }
802
803 type Outer struct {
804 A Inner
805 B int32
806 }
807
808 func getInnerV(o *Outer) int32 {
809 return o.A.V
810 }
811 `)
812 h18 := compileToIR(
813 uintptr(unsafe.Pointer(&src18[0])), int32(len(src18)),
814 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
815 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
816 )
817 ir18 := getIR(h18)
818 fmt.Println("=== IR for nested struct ===")
819 fmt.Println(ir18)
820
821 llvmVerify("nested struct", ir18)
822 assert("nested struct has getelementptr", strings.Contains(ir18, "getelementptr"))
823 assert("nested struct has load i32", strings.Contains(ir18, "load i32"))
824
825 irFree(h18)
826
827 // Test 19: Nil pointer check
828 src19 := []byte(`package mypkg
829
830 func isNil(p *int32) bool {
831 if p == nil {
832 return true
833 }
834 return false
835 }
836 `)
837 h19 := compileToIR(
838 uintptr(unsafe.Pointer(&src19[0])), int32(len(src19)),
839 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
840 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
841 )
842 ir19 := getIR(h19)
843 fmt.Println("=== IR for nil check ===")
844 fmt.Println(ir19)
845
846 llvmVerify("nil check", ir19)
847 assert("nil check has icmp", strings.Contains(ir19, "icmp"))
848 assert("nil check has null/zeroinit", strings.Contains(ir19, "null") || strings.Contains(ir19, "zeroinitializer"))
849
850 irFree(h19)
851
852 // Test 20: Bitwise operations
853 src20 := []byte(`package mypkg
854
855 func bitAnd(a, b int32) int32 {
856 return a & b
857 }
858
859 func bitXor(a, b int32) int32 {
860 return a ^ b
861 }
862
863 func bitShiftL(a int32, n uint32) int32 {
864 return a << n
865 }
866
867 func bitShiftR(a int32, n uint32) int32 {
868 return a >> n
869 }
870 `)
871 h20 := compileToIR(
872 uintptr(unsafe.Pointer(&src20[0])), int32(len(src20)),
873 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
874 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
875 )
876 ir20 := getIR(h20)
877 fmt.Println("=== IR for bitwise ===")
878 fmt.Println(ir20)
879
880 llvmVerify("bitwise", ir20)
881 assert("bitwise has and", strings.Contains(ir20, "and i32"))
882 assert("bitwise has xor", strings.Contains(ir20, "xor i32"))
883 assert("bitwise has shl", strings.Contains(ir20, "shl i32"))
884 assert("bitwise has ashr", strings.Contains(ir20, "ashr i32"))
885
886 irFree(h20)
887
888 // Test 21: Slice/string concat (| operator -> OpAdd on slice type)
889 src21 := []byte(`package mypkg
890
891 func concat(a, b []int32) []int32 {
892 return a | b
893 }
894 `)
895 h21 := compileToIR(
896 uintptr(unsafe.Pointer(&src21[0])), int32(len(src21)),
897 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
898 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
899 )
900 ir21 := getIR(h21)
901 fmt.Println("=== IR for slice concat ===")
902 fmt.Println(ir21)
903
904 llvmVerify("slice concat", ir21)
905 assert("concat calls sliceAppend", strings.Contains(ir21, "@runtime.sliceAppend"))
906 assert("concat extracts ptr", strings.Contains(ir21, "extractvalue"))
907 assert("concat builds result", strings.Contains(ir21, "insertvalue"))
908
909 irFree(h21)
910
911 // Test 22: for-range over slice
912 src22 := []byte(`package mypkg
913
914 func sumRange(s []int32) int32 {
915 total := int32(0)
916 for _, v := range s {
917 total = total + v
918 }
919 return total
920 }
921 `)
922 h22 := compileToIR(
923 uintptr(unsafe.Pointer(&src22[0])), int32(len(src22)),
924 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
925 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
926 )
927 ir22 := getIR(h22)
928 fmt.Println("=== IR for range ===")
929 fmt.Println(ir22)
930
931 llvmVerify("range", ir22)
932 assert("range has alloca for iter", strings.Contains(ir22, "alloca i64"))
933 assert("range has icmp ult", strings.Contains(ir22, "icmp ult"))
934 assert("range has getelementptr", strings.Contains(ir22, "getelementptr"))
935 assert("range has select", strings.Contains(ir22, "select"))
936
937 irFree(h22)
938
939 // Test 23: Map operations (make, set, get)
940 src23 := []byte(`package mypkg
941
942 func mapSetGet() int32 {
943 m := make(map[int32]int32)
944 m[1] = 42
945 return m[1]
946 }
947 `)
948 h23 := compileToIR(
949 uintptr(unsafe.Pointer(&src23[0])), int32(len(src23)),
950 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
951 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
952 )
953 ir23 := getIR(h23)
954 fmt.Println("=== IR for map ops ===")
955 fmt.Println(ir23)
956
957 llvmVerify("map ops", ir23)
958 assert("map has hashmapMake", strings.Contains(ir23, "@runtime.hashmapMake"))
959 assert("map has hashmapBinarySet", strings.Contains(ir23, "@runtime.hashmapBinarySet"))
960 assert("map has hashmapBinaryGet", strings.Contains(ir23, "@runtime.hashmapBinaryGet"))
961
962 irFree(h23)
963
964 // Test 24: panic
965 src24 := []byte(`package mypkg
966
967 func mustPositive(n int32) int32 {
968 if n <= 0 {
969 panic("negative")
970 }
971 return n
972 }
973 `)
974 h24 := compileToIR(
975 uintptr(unsafe.Pointer(&src24[0])), int32(len(src24)),
976 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
977 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
978 )
979 ir24 := getIR(h24)
980 fmt.Println("=== IR for panic ===")
981 fmt.Println(ir24)
982
983 llvmVerify("panic", ir24)
984 assert("panic has runtime._panic", strings.Contains(ir24, "@runtime._panic"))
985 assert("panic has unreachable", strings.Contains(ir24, "unreachable"))
986
987 irFree(h24)
988
989 // Test 25: copy builtin
990 src25 := []byte(`package mypkg
991
992 func copySlice(dst, src []int32) int32 {
993 return copy(dst, src)
994 }
995 `)
996 h25 := compileToIR(
997 uintptr(unsafe.Pointer(&src25[0])), int32(len(src25)),
998 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
999 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1000 )
1001 ir25 := getIR(h25)
1002 fmt.Println("=== IR for copy ===")
1003 fmt.Println(ir25)
1004
1005 llvmVerify("copy", ir25)
1006 assert("copy calls sliceCopy", strings.Contains(ir25, "@runtime.sliceCopy"))
1007
1008 irFree(h25)
1009
1010 // Test 26: delete from map
1011 src26 := []byte(`package mypkg
1012
1013 func mapDelete(m map[int32]int32, k int32) {
1014 delete(m, k)
1015 }
1016 `)
1017 h26 := compileToIR(
1018 uintptr(unsafe.Pointer(&src26[0])), int32(len(src26)),
1019 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1020 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1021 )
1022 ir26 := getIR(h26)
1023 fmt.Println("=== IR for delete ===")
1024 fmt.Println(ir26)
1025
1026 llvmVerify("delete", ir26)
1027 assert("delete calls hashmapBinaryDelete", strings.Contains(ir26, "@runtime.hashmapBinaryDelete"))
1028
1029 irFree(h26)
1030
1031 // Test 27: float operations
1032 src27 := []byte(`package mypkg
1033
1034 func fadd(a, b float64) float64 {
1035 return a + b
1036 }
1037
1038 func fmul(a, b float64) float64 {
1039 return a * b
1040 }
1041
1042 func fcmp(a, b float64) bool {
1043 return a < b
1044 }
1045 `)
1046 h27 := compileToIR(
1047 uintptr(unsafe.Pointer(&src27[0])), int32(len(src27)),
1048 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1049 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1050 )
1051 ir27 := getIR(h27)
1052 fmt.Println("=== IR for float ===")
1053 fmt.Println(ir27)
1054
1055 llvmVerify("float", ir27)
1056 assert("float has fadd", strings.Contains(ir27, "fadd"))
1057 assert("float has fmul", strings.Contains(ir27, "fmul"))
1058 assert("float has fcmp", strings.Contains(ir27, "fcmp"))
1059
1060 irFree(h27)
1061
1062 // Test 28: Function value (function as first-class value passed as ptr)
1063 src28 := []byte(`package mypkg
1064
1065 func apply(f func(int32) int32, x int32) int32 {
1066 return f(x)
1067 }
1068 `)
1069 h28 := compileToIR(
1070 uintptr(unsafe.Pointer(&src28[0])), int32(len(src28)),
1071 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1072 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1073 )
1074 ir28 := getIR(h28)
1075 fmt.Println("=== IR for func value ===")
1076 fmt.Println(ir28)
1077
1078 llvmVerify("func value", ir28)
1079 assert("func value has call ptr", strings.Contains(ir28, "call i32 %"))
1080
1081 irFree(h28)
1082
1083 // Test 29: Array operations
1084 src29 := []byte(`package mypkg
1085
1086 func arrayGet(a [4]int32, i int32) int32 {
1087 return a[i]
1088 }
1089 `)
1090 h29 := compileToIR(
1091 uintptr(unsafe.Pointer(&src29[0])), int32(len(src29)),
1092 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1093 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1094 )
1095 ir29 := getIR(h29)
1096 fmt.Println("=== IR for array ===")
1097 fmt.Println(ir29)
1098
1099 llvmVerify("array", ir29)
1100 assert("array has [4 x i32]", strings.Contains(ir29, "[4 x i32]"))
1101 assert("array has getelementptr", strings.Contains(ir29, "getelementptr"))
1102
1103 irFree(h29)
1104
1105 // Test 30: Map comma-ok lookup
1106 src30 := []byte(`package mypkg
1107
1108 func mapLookup(m map[int32]int32, k int32) (int32, bool) {
1109 v, ok := m[k]
1110 return v, ok
1111 }
1112 `)
1113 h30 := compileToIR(
1114 uintptr(unsafe.Pointer(&src30[0])), int32(len(src30)),
1115 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1116 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1117 )
1118 ir30 := getIR(h30)
1119 fmt.Println("=== IR for comma-ok ===")
1120 fmt.Println(ir30)
1121
1122 llvmVerify("comma-ok", ir30)
1123 assert("comma-ok has hashmapBinaryGet", strings.Contains(ir30, "@runtime.hashmapBinaryGet"))
1124 assert("comma-ok returns tuple", strings.Contains(ir30, "{i32, i1}") || strings.Contains(ir30, "insertvalue"))
1125
1126 irFree(h30)
1127
1128 // Test 31: println with int and string
1129 src31 := []byte(`package mypkg
1130
1131 func hello(n int32) {
1132 println("hello", n)
1133 }
1134 `)
1135 h31 := compileToIR(
1136 uintptr(unsafe.Pointer(&src31[0])), int32(len(src31)),
1137 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1138 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1139 )
1140 ir31 := getIR(h31)
1141 fmt.Println("=== IR for println ===")
1142 fmt.Println(ir31)
1143
1144 llvmVerify("println", ir31)
1145 assert("println has printlock", strings.Contains(ir31, "@runtime.printlock"))
1146 assert("println has printstring", strings.Contains(ir31, "@runtime.printstring"))
1147 assert("println has printint32", strings.Contains(ir31, "@runtime.printint32"))
1148 assert("println has printspace", strings.Contains(ir31, "@runtime.printspace"))
1149 assert("println has printnl", strings.Contains(ir31, "@runtime.printnl"))
1150 assert("println has printunlock", strings.Contains(ir31, "@runtime.printunlock"))
1151
1152 irFree(h31)
1153
1154 // Test 32: print with bool and float
1155 src32 := []byte(`package mypkg
1156
1157 func debug(ok bool, val float64) {
1158 print(ok, val)
1159 }
1160 `)
1161 h32 := compileToIR(
1162 uintptr(unsafe.Pointer(&src32[0])), int32(len(src32)),
1163 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1164 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1165 )
1166 ir32 := getIR(h32)
1167 fmt.Println("=== IR for print ===")
1168 fmt.Println(ir32)
1169
1170 llvmVerify("print", ir32)
1171 assert("print has printbool", strings.Contains(ir32, "@runtime.printbool"))
1172 assert("print has printfloat64", strings.Contains(ir32, "@runtime.printfloat64"))
1173 assert("print no printspace", !strings.Contains(ir32, "@runtime.printspace"))
1174 assert("print no printnl", !strings.Contains(ir32, "@runtime.printnl"))
1175
1176 irFree(h32)
1177
1178 // Test 33: for-range over map
1179 src33 := []byte(`package mypkg
1180
1181 func sumMap(m map[int32]int32) int32 {
1182 total := int32(0)
1183 for _, v := range m {
1184 total = total + v
1185 }
1186 return total
1187 }
1188 `)
1189 h33 := compileToIR(
1190 uintptr(unsafe.Pointer(&src33[0])), int32(len(src33)),
1191 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1192 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1193 )
1194 ir33 := getIR(h33)
1195 fmt.Println("=== IR for map range ===")
1196 fmt.Println(ir33)
1197
1198 llvmVerify("map range", ir33)
1199 assert("map range has hashmapNext", strings.Contains(ir33, "@runtime.hashmapNext"))
1200 assert("map range has memset", strings.Contains(ir33, "llvm.memset"))
1201 assert("map range has alloca [48 x i8]", strings.Contains(ir33, "alloca [48 x i8]"))
1202
1203 irFree(h33)
1204
1205 // Test 34: string constant in println
1206 src34 := []byte(`package mypkg
1207
1208 func greet(name string) {
1209 println("hello", name)
1210 }
1211 `)
1212 h34 := compileToIR(
1213 uintptr(unsafe.Pointer(&src34[0])), int32(len(src34)),
1214 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1215 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1216 )
1217 ir34 := getIR(h34)
1218 fmt.Println("=== IR for string const ===")
1219 fmt.Println(ir34)
1220
1221 llvmVerify("string const", ir34)
1222 assert("string const has global", strings.Contains(ir34, "@.str."))
1223 assert("string const has c\"hello\"", strings.Contains(ir34, `c"hello"`))
1224 assert("string const has printstring with ptr", strings.Contains(ir34, "{ ptr @.str."))
1225
1226 irFree(h34)
1227
1228 // Test 35: global string variable
1229 src35 := []byte(`package mypkg
1230
1231 var greeting = "world"
1232
1233 func getGreeting() string {
1234 return greeting
1235 }
1236 `)
1237 h35 := compileToIR(
1238 uintptr(unsafe.Pointer(&src35[0])), int32(len(src35)),
1239 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1240 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1241 )
1242 ir35 := getIR(h35)
1243 fmt.Println("=== IR for global string ===")
1244 fmt.Println(ir35)
1245
1246 llvmVerify("global string", ir35)
1247 assert("global string has global var", strings.Contains(ir35, "@mypkg.greeting"))
1248 assert("global string has load slice", strings.Contains(ir35, "load {ptr, i64, i64}"))
1249
1250 irFree(h35)
1251
1252 // Test 36: logical not (unary !)
1253 src36 := []byte(`package mypkg
1254
1255 func negate(b bool) bool {
1256 return !b
1257 }
1258 `)
1259 h36 := compileToIR(
1260 uintptr(unsafe.Pointer(&src36[0])), int32(len(src36)),
1261 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1262 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1263 )
1264 ir36 := getIR(h36)
1265 fmt.Println("=== IR for not ===")
1266 fmt.Println(ir36)
1267
1268 llvmVerify("not", ir36)
1269 assert("not has xor", strings.Contains(ir36, "xor i1"))
1270
1271 irFree(h36)
1272
1273 // Test 37: global int variable (inferred type)
1274 src37 := []byte(`package mypkg
1275
1276 var counter = 42
1277
1278 func getCounter() int {
1279 return counter
1280 }
1281 `)
1282 h37 := compileToIR(
1283 uintptr(unsafe.Pointer(&src37[0])), int32(len(src37)),
1284 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1285 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1286 )
1287 ir37 := getIR(h37)
1288 fmt.Println("=== IR for global int ===")
1289 fmt.Println(ir37)
1290
1291 llvmVerify("global int", ir37)
1292 assert("global int has global var", strings.Contains(ir37, "@mypkg.counter = global i32"))
1293 assert("global int has load i32", strings.Contains(ir37, "load i32"))
1294
1295 irFree(h37)
1296
1297 // Test 38: string comparison
1298 src38 := []byte(`package mypkg
1299
1300 func isHello(s string) bool {
1301 return s == "hello"
1302 }
1303 `)
1304 h38 := compileToIR(
1305 uintptr(unsafe.Pointer(&src38[0])), int32(len(src38)),
1306 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1307 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1308 )
1309 ir38 := getIR(h38)
1310 fmt.Println("=== IR for string compare ===")
1311 fmt.Println(ir38)
1312
1313 llvmVerify("string compare", ir38)
1314 assert("string compare has call", strings.Contains(ir38, "call") || strings.Contains(ir38, "icmp"))
1315
1316 irFree(h38)
1317
1318 // Test 39: tagless switch (switch { case ... })
1319 src39 := []byte(`package mypkg
1320
1321 func classify(x int) int {
1322 switch {
1323 case x < 0:
1324 return -1
1325 case x == 0:
1326 return 0
1327 default:
1328 return 1
1329 }
1330 }
1331 `)
1332 h39 := compileToIR(
1333 uintptr(unsafe.Pointer(&src39[0])), int32(len(src39)),
1334 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1335 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1336 )
1337 ir39 := getIR(h39)
1338 fmt.Println("=== IR for tagless switch ===")
1339 fmt.Println(ir39)
1340
1341 llvmVerify("tagless switch", ir39)
1342 assert("tagless switch has icmp", strings.Contains(ir39, "icmp"))
1343 assert("tagless switch has br", strings.Contains(ir39, "br"))
1344
1345 irFree(h39)
1346
1347 // Test 40: slice of strings
1348 src40 := []byte(`package mypkg
1349
1350 func firstWord(words []string) string {
1351 return words[0]
1352 }
1353 `)
1354 h40 := compileToIR(
1355 uintptr(unsafe.Pointer(&src40[0])), int32(len(src40)),
1356 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1357 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1358 )
1359 ir40 := getIR(h40)
1360 fmt.Println("=== IR for slice of strings ===")
1361 fmt.Println(ir40)
1362
1363 llvmVerify("slice of strings", ir40)
1364 assert("slice of strings has gep", strings.Contains(ir40, "getelementptr"))
1365
1366 irFree(h40)
1367
1368 // Test 41: const declarations
1369 src41 := []byte(`package mypkg
1370
1371 const limit = 100
1372 const name = "test"
1373
1374 func getLimit() int { return limit }
1375 func getName() string { return name }
1376 `)
1377 h41 := compileToIR(
1378 uintptr(unsafe.Pointer(&src41[0])), int32(len(src41)),
1379 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1380 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1381 )
1382 ir41 := getIR(h41)
1383 fmt.Println("=== IR for const decls ===")
1384 fmt.Println(ir41)
1385
1386 llvmVerify("const decls", ir41)
1387 assert("const int returns i32", strings.Contains(ir41, "ret i32 100"))
1388 assert("const string has str ref", strings.Contains(ir41, "@.str."))
1389
1390 irFree(h41)
1391
1392 // Test 42: global variable mutation
1393 src42 := []byte(`package mypkg
1394
1395 var count int
1396
1397 func increment() {
1398 count = count + 1
1399 }
1400 `)
1401 h42 := compileToIR(
1402 uintptr(unsafe.Pointer(&src42[0])), int32(len(src42)),
1403 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1404 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1405 )
1406 ir42 := getIR(h42)
1407 fmt.Println("=== IR for global mutation ===")
1408 fmt.Println(ir42)
1409
1410 llvmVerify("global mutation", ir42)
1411 assert("global mutation has load", strings.Contains(ir42, "load i32, ptr @mypkg.count"))
1412 assert("global mutation has store", strings.Contains(ir42, "store i32"))
1413
1414 irFree(h42)
1415
1416 // Test 43: multiple return with named results
1417 src43 := []byte(`package mypkg
1418
1419 func divmod(a, b int) (int, int) {
1420 return a / b, a % b
1421 }
1422 `)
1423 h43 := compileToIR(
1424 uintptr(unsafe.Pointer(&src43[0])), int32(len(src43)),
1425 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1426 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1427 )
1428 ir43 := getIR(h43)
1429 fmt.Println("=== IR for divmod ===")
1430 fmt.Println(ir43)
1431
1432 llvmVerify("divmod", ir43)
1433 assert("divmod has sdiv", strings.Contains(ir43, "sdiv"))
1434 assert("divmod has srem", strings.Contains(ir43, "srem"))
1435 assert("divmod returns tuple", strings.Contains(ir43, "ret {i32, i32}"))
1436
1437 irFree(h43)
1438
1439 // Test 44: len on string
1440 src44 := []byte(`package mypkg
1441
1442 func strLen(s string) int {
1443 return len(s)
1444 }
1445 `)
1446 h44 := compileToIR(
1447 uintptr(unsafe.Pointer(&src44[0])), int32(len(src44)),
1448 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1449 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1450 )
1451 ir44 := getIR(h44)
1452 fmt.Println("=== IR for strlen ===")
1453 fmt.Println(ir44)
1454
1455 llvmVerify("strlen", ir44)
1456 assert("strlen has extractvalue for len", strings.Contains(ir44, "extractvalue"))
1457 assert("strlen has trunc", strings.Contains(ir44, "trunc"))
1458
1459 irFree(h44)
1460
1461 // Test 45: global bool variable (inferred type)
1462 src45 := []byte(`package mypkg
1463
1464 var enabled = true
1465
1466 func isEnabled() bool { return enabled }
1467 `)
1468 h45 := compileToIR(
1469 uintptr(unsafe.Pointer(&src45[0])), int32(len(src45)),
1470 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1471 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1472 )
1473 ir45 := getIR(h45)
1474 fmt.Println("=== IR for global bool ===")
1475 fmt.Println(ir45)
1476
1477 llvmVerify("global bool", ir45)
1478 assert("global bool has i1", strings.Contains(ir45, "@mypkg.enabled = global i1"))
1479
1480 irFree(h45)
1481
1482 // Test 46: string concat with + (which is | in Moxie SSA)
1483 src46 := []byte(`package mypkg
1484
1485 func greet(name string) string {
1486 return "hello " | name
1487 }
1488 `)
1489 h46 := compileToIR(
1490 uintptr(unsafe.Pointer(&src46[0])), int32(len(src46)),
1491 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1492 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1493 )
1494 ir46 := getIR(h46)
1495 fmt.Println("=== IR for string concat ===")
1496 fmt.Println(ir46)
1497
1498 llvmVerify("string concat", ir46)
1499 assert("string concat calls sliceAppend", strings.Contains(ir46, "@runtime.sliceAppend"))
1500
1501 irFree(h46)
1502
1503 // Test 47: cap on string (strings have len == cap)
1504 src47 := []byte(`package mypkg
1505
1506 func strCap(s string) int {
1507 return cap(s)
1508 }
1509 `)
1510 h47 := compileToIR(
1511 uintptr(unsafe.Pointer(&src47[0])), int32(len(src47)),
1512 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1513 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1514 )
1515 ir47 := getIR(h47)
1516 fmt.Println("=== IR for string cap ===")
1517 fmt.Println(ir47)
1518
1519 llvmVerify("string cap", ir47)
1520 assert("string cap has extractvalue", strings.Contains(ir47, "extractvalue"))
1521
1522 irFree(h47)
1523
1524 // Test 48: nested if/else with multiple returns
1525 src48 := []byte(`package mypkg
1526
1527 func clamp(x, lo, hi int) int {
1528 if x < lo {
1529 return lo
1530 } else if x > hi {
1531 return hi
1532 }
1533 return x
1534 }
1535 `)
1536 h48 := compileToIR(
1537 uintptr(unsafe.Pointer(&src48[0])), int32(len(src48)),
1538 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1539 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1540 )
1541 ir48 := getIR(h48)
1542 fmt.Println("=== IR for clamp ===")
1543 fmt.Println(ir48)
1544
1545 llvmVerify("clamp", ir48)
1546 assert("clamp has icmp slt", strings.Contains(ir48, "icmp slt"))
1547 assert("clamp has icmp sgt", strings.Contains(ir48, "icmp sgt"))
1548
1549 irFree(h48)
1550
1551 // Test 49: Closure (captures variable from outer scope)
1552 src49 := []byte(`package mypkg
1553
1554 func adder(x int32) func(int32) int32 {
1555 return func(y int32) int32 {
1556 return x + y
1557 }
1558 }
1559 `)
1560 h49 := compileToIR(
1561 uintptr(unsafe.Pointer(&src49[0])), int32(len(src49)),
1562 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1563 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1564 )
1565 ir49 := getIR(h49)
1566 fmt.Println("=== IR for closure ===")
1567 fmt.Println(ir49)
1568
1569 llvmVerify("closure", ir49)
1570 assert("closure has anon func", strings.Contains(ir49, "@mypkg.adder$"))
1571 assert("closure has runtime.alloc", strings.Contains(ir49, "@runtime.alloc"))
1572 assert("closure has insertvalue {ptr, ptr}", strings.Contains(ir49, "insertvalue {ptr, ptr}"))
1573 assert("closure has getelementptr for context", strings.Contains(ir49, "getelementptr"))
1574 assert("closure anon has context param", strings.Contains(ir49, "ptr %context"))
1575
1576 irFree(h49)
1577
1578 // Test 50: Closure with multiple captures
1579 src50 := []byte(`package mypkg
1580
1581 func makeCounter(start int32, step int32) func() int32 {
1582 val := start
1583 return func() int32 {
1584 result := val
1585 val = val + step
1586 return result
1587 }
1588 }
1589 `)
1590 h50 := compileToIR(
1591 uintptr(unsafe.Pointer(&src50[0])), int32(len(src50)),
1592 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1593 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1594 )
1595 ir50 := getIR(h50)
1596 fmt.Println("=== IR for multi-capture closure ===")
1597 fmt.Println(ir50)
1598
1599 llvmVerify("multi-capture closure", ir50)
1600 assert("multi-capture has anon func", strings.Contains(ir50, "@mypkg.makeCounter$"))
1601 assert("multi-capture has alloc", strings.Contains(ir50, "@runtime.alloc"))
1602
1603 irFree(h50)
1604
1605 // Test 51: Function value call (indirect call through {ptr, ptr})
1606 src51 := []byte(`package mypkg
1607
1608 func apply(f func(int32) int32, x int32) int32 {
1609 return f(x)
1610 }
1611
1612 func double(x int32) int32 {
1613 return x + x
1614 }
1615
1616 func test() int32 {
1617 return apply(double, 5)
1618 }
1619 `)
1620 h51 := compileToIR(
1621 uintptr(unsafe.Pointer(&src51[0])), int32(len(src51)),
1622 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1623 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1624 )
1625 ir51 := getIR(h51)
1626 fmt.Println("=== IR for func value call ===")
1627 fmt.Println(ir51)
1628
1629 llvmVerify("func value call", ir51)
1630 assert("func value call has extractvalue", strings.Contains(ir51, "extractvalue {ptr, ptr}"))
1631 assert("func value call passes context", strings.Contains(ir51, "ptr %ctx"))
1632
1633 irFree(h51)
1634
1635 // Test 52: Method with value receiver
1636 src52 := []byte(`package mypkg
1637
1638 type Point struct {
1639 X int32
1640 Y int32
1641 }
1642
1643 func (p Point) Sum() int32 {
1644 return p.X + p.Y
1645 }
1646
1647 func test() int32 {
1648 p := Point{X: 3, Y: 4}
1649 return p.Sum()
1650 }
1651 `)
1652 h52 := compileToIR(
1653 uintptr(unsafe.Pointer(&src52[0])), int32(len(src52)),
1654 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1655 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1656 )
1657 ir52 := getIR(h52)
1658 fmt.Println("=== IR for value receiver method ===")
1659 fmt.Println(ir52)
1660
1661 llvmVerify("value receiver method", ir52)
1662 assert("value recv method defined", strings.Contains(ir52, "@mypkg.Point.Sum"))
1663 assert("value recv method takes struct", strings.Contains(ir52, "define i32 @mypkg.Point.Sum("))
1664
1665 irFree(h52)
1666
1667 // Test 53: Method with pointer receiver
1668 src53 := []byte(`package mypkg
1669
1670 type Counter struct {
1671 Val int32
1672 }
1673
1674 func (c *Counter) Inc() {
1675 c.Val = c.Val + 1
1676 }
1677
1678 func (c *Counter) Get() int32 {
1679 return c.Val
1680 }
1681
1682 func test() int32 {
1683 c := Counter{Val: 10}
1684 c.Inc()
1685 c.Inc()
1686 return c.Get()
1687 }
1688 `)
1689 h53 := compileToIR(
1690 uintptr(unsafe.Pointer(&src53[0])), int32(len(src53)),
1691 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1692 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1693 )
1694 ir53 := getIR(h53)
1695 fmt.Println("=== IR for pointer receiver method ===")
1696 fmt.Println(ir53)
1697
1698 llvmVerify("pointer receiver method", ir53)
1699 assert("ptr recv Inc defined", strings.Contains(ir53, "@mypkg.Counter.Inc"))
1700 assert("ptr recv Get defined", strings.Contains(ir53, "@mypkg.Counter.Get"))
1701 assert("ptr recv method takes ptr", strings.Contains(ir53, "define") && strings.Contains(ir53, "@mypkg.Counter.Inc(ptr"))
1702
1703 irFree(h53)
1704
1705 // Test 54: Slice make literal {: syntax rewrite
1706 src54 := []byte(`package mypkg
1707
1708 func test() int32 {
1709 a := []int32{:5}
1710 b := []int32{:0:10}
1711 return int32(len(a)) + int32(len(b))
1712 }
1713 `)
1714 h54 := compileToIR(
1715 uintptr(unsafe.Pointer(&src54[0])), int32(len(src54)),
1716 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1717 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1718 )
1719 ir54 := getIR(h54)
1720 fmt.Println("=== IR for slice make literal ===")
1721 fmt.Println(ir54)
1722
1723 llvmVerify("slice make literal", ir54)
1724 assert("make literal has alloc", strings.Contains(ir54, "@runtime.alloc"))
1725 assert("make literal no parse error", !strings.Contains(ir54, "parse error"))
1726
1727 irFree(h54)
1728
1729 // Test 55: Interface dispatch
1730 src55 := []byte(`package mypkg
1731
1732 type Stringer interface {
1733 String() string
1734 }
1735
1736 type Name struct {
1737 First string
1738 Last string
1739 }
1740
1741 func (n Name) String() string {
1742 return n.First | " " | n.Last
1743 }
1744
1745 func greet(s Stringer) string {
1746 return "Hello, " | s.String()
1747 }
1748
1749 func test() int32 {
1750 n := Name{First: "John", Last: "Doe"}
1751 r := greet(n)
1752 if len(r) > 0 {
1753 return 42
1754 }
1755 return 0
1756 }
1757 `)
1758 h55 := compileToIR(
1759 uintptr(unsafe.Pointer(&src55[0])), int32(len(src55)),
1760 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1761 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1762 )
1763 ir55 := getIR(h55)
1764 fmt.Println("=== IR for interface dispatch ===")
1765 fmt.Println(ir55)
1766
1767 llvmVerify("interface dispatch", ir55)
1768 assert("iface has typeid", strings.Contains(ir55, "typeid"))
1769 assert("iface has makeinterface", strings.Contains(ir55, "insertvalue {ptr, ptr}"))
1770 assert("iface has Name.String method", strings.Contains(ir55, "@mypkg.Name.String"))
1771 assert("iface greet takes iface", strings.Contains(ir55, "define") && strings.Contains(ir55, "@mypkg.greet"))
1772 assert("iface no parse error", !strings.Contains(ir55, "parse error"))
1773
1774 irFree(h55)
1775
1776 // Test 56: Multi-impl interface dispatch
1777 src56 := []byte(`package mypkg
1778
1779 type Sizer interface {
1780 Size() int32
1781 }
1782
1783 type Box struct {
1784 W int32
1785 H int32
1786 }
1787
1788 type Circle struct {
1789 R int32
1790 }
1791
1792 func (b Box) Size() int32 {
1793 return b.W * b.H
1794 }
1795
1796 func (c Circle) Size() int32 {
1797 return c.R * c.R * 3
1798 }
1799
1800 func getSize(s Sizer) int32 {
1801 return s.Size()
1802 }
1803
1804 func test() int32 {
1805 b := Box{W: 3, H: 4}
1806 return getSize(b)
1807 }
1808 `)
1809 h56 := compileToIR(
1810 uintptr(unsafe.Pointer(&src56[0])), int32(len(src56)),
1811 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1812 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1813 )
1814 ir56 := getIR(h56)
1815 fmt.Println("=== IR for multi-impl interface ===")
1816 fmt.Println(ir56)
1817
1818 llvmVerify("multi-impl interface", ir56)
1819 assert("multi has Box.Size", strings.Contains(ir56, "@mypkg.Box.Size"))
1820 assert("multi has Circle.Size", strings.Contains(ir56, "@mypkg.Circle.Size"))
1821 assert("multi has typeid Box", strings.Contains(ir56, "typeid.Box"))
1822 assert("multi has typeid Circle", strings.Contains(ir56, "typeid.Circle"))
1823 assert("multi dispatch has icmp", strings.Contains(ir56, "icmp eq ptr"))
1824 assert("multi no parse error", !strings.Contains(ir56, "parse error"))
1825
1826 irFree(h56)
1827
1828 // Test 57: Type assertion (comma-ok)
1829 src57 := []byte(`package mypkg
1830
1831 type Animal interface {
1832 Sound() string
1833 }
1834
1835 type Dog struct {
1836 Name string
1837 }
1838
1839 func (d Dog) Sound() string {
1840 return "woof"
1841 }
1842
1843 func tryDog(a Animal) int32 {
1844 d, ok := a.(Dog)
1845 if ok {
1846 if len(d.Name) > 0 {
1847 return 1
1848 }
1849 return 2
1850 }
1851 return 0
1852 }
1853
1854 func test() int32 {
1855 d := Dog{Name: "Rex"}
1856 return tryDog(d)
1857 }
1858 `)
1859 h57 := compileToIR(
1860 uintptr(unsafe.Pointer(&src57[0])), int32(len(src57)),
1861 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1862 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1863 )
1864 ir57 := getIR(h57)
1865 fmt.Println("=== IR for type assertion ===")
1866 fmt.Println(ir57)
1867
1868 llvmVerify("type assertion", ir57)
1869 assert("ta has typeid compare", strings.Contains(ir57, "icmp eq ptr") && strings.Contains(ir57, "typeid.Dog"))
1870 assert("ta has extractvalue", strings.Contains(ir57, "extractvalue {ptr, ptr}"))
1871 assert("ta has insertvalue tuple", strings.Contains(ir57, "insertvalue"))
1872 assert("ta no parse error", !strings.Contains(ir57, "parse error"))
1873
1874 irFree(h57)
1875
1876 // Test 58: Type switch
1877 src58 := []byte(`package mypkg
1878
1879 type Shape interface {
1880 Area() int32
1881 }
1882
1883 type Rect struct {
1884 W int32
1885 H int32
1886 }
1887
1888 type Tri struct {
1889 B int32
1890 H int32
1891 }
1892
1893 func (r Rect) Area() int32 {
1894 return r.W * r.H
1895 }
1896
1897 func (t Tri) Area() int32 {
1898 return t.B * t.H / 2
1899 }
1900
1901 func describe(s Shape) int32 {
1902 switch v := s.(type) {
1903 case Rect:
1904 return v.W + v.H
1905 case Tri:
1906 return v.B + v.H
1907 }
1908 return 0
1909 }
1910
1911 func test() int32 {
1912 r := Rect{W: 3, H: 4}
1913 return describe(r)
1914 }
1915 `)
1916 h58 := compileToIR(
1917 uintptr(unsafe.Pointer(&src58[0])), int32(len(src58)),
1918 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1919 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1920 )
1921 ir58 := getIR(h58)
1922 fmt.Println("=== IR for type switch ===")
1923 fmt.Println(ir58)
1924
1925 llvmVerify("type switch", ir58)
1926 assert("ts has typeid Rect", strings.Contains(ir58, "typeid.Rect"))
1927 assert("ts has typeid Tri", strings.Contains(ir58, "typeid.Tri"))
1928 assert("ts has typeassert", strings.Contains(ir58, "icmp eq ptr"))
1929 assert("ts no parse error", !strings.Contains(ir58, "parse error"))
1930
1931 irFree(h58)
1932
1933 // Test 59: Pointer receiver interface dispatch
1934 src59 := []byte(`package mypkg
1935
1936 type Writer interface {
1937 Write(data int32) int32
1938 }
1939
1940 type Buffer struct {
1941 Count int32
1942 }
1943
1944 func (b *Buffer) Write(data int32) int32 {
1945 b.Count = b.Count + data
1946 return b.Count
1947 }
1948
1949 func writeAll(w Writer, v int32) int32 {
1950 return w.Write(v)
1951 }
1952
1953 func test() int32 {
1954 b := Buffer{Count: 0}
1955 return writeAll(&b, 10)
1956 }
1957 `)
1958 h59 := compileToIR(
1959 uintptr(unsafe.Pointer(&src59[0])), int32(len(src59)),
1960 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1961 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1962 )
1963 ir59 := getIR(h59)
1964 fmt.Println("=== IR for ptr recv interface ===")
1965 fmt.Println(ir59)
1966
1967 llvmVerify("ptr recv interface", ir59)
1968 assert("ptr iface has Buffer.Write", strings.Contains(ir59, "@mypkg.Buffer.Write"))
1969 assert("ptr iface dispatch passes ptr", strings.Contains(ir59, "call i32 @mypkg.Buffer.Write(ptr"))
1970 assert("ptr iface no parse error", !strings.Contains(ir59, "parse error"))
1971
1972 irFree(h59)
1973
1974 // Test 60: AndNot operator
1975 src60 := []byte(`package mypkg
1976
1977 func test() int32 {
1978 x := int32(0xFF)
1979 mask := int32(0x0F)
1980 return x &^ mask
1981 }
1982 `)
1983 h60 := compileToIR(
1984 uintptr(unsafe.Pointer(&src60[0])), int32(len(src60)),
1985 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1986 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1987 )
1988 ir60 := getIR(h60)
1989 fmt.Println("=== IR for andnot ===")
1990 fmt.Println(ir60)
1991
1992 llvmVerify("andnot", ir60)
1993 assert("andnot has xor", strings.Contains(ir60, "xor"))
1994 assert("andnot has and", strings.Contains(ir60, " and "))
1995 assert("andnot no parse error", !strings.Contains(ir60, "parse error"))
1996
1997 irFree(h60)
1998
1999 // Test 61: Nil comparison
2000 src61 := []byte(`package mypkg
2001
2002 func test() int32 {
2003 var p *int32
2004 if p == nil {
2005 return 1
2006 }
2007 return 0
2008 }
2009 `)
2010 h61 := compileToIR(
2011 uintptr(unsafe.Pointer(&src61[0])), int32(len(src61)),
2012 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2013 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2014 )
2015 ir61 := getIR(h61)
2016 fmt.Println("=== IR for nil compare ===")
2017 fmt.Println(ir61)
2018
2019 llvmVerify("nil compare", ir61)
2020 assert("nil has icmp eq ptr null", strings.Contains(ir61, "icmp eq ptr") && strings.Contains(ir61, "null"))
2021 assert("nil no parse error", !strings.Contains(ir61, "parse error"))
2022
2023 irFree(h61)
2024
2025 // Test 62: Key-only map range
2026 src62 := []byte(`package mypkg
2027
2028 func test() int32 {
2029 m := map[string]int32{"a": 1, "b": 2, "c": 3}
2030 count := int32(0)
2031 for k := range m {
2032 count = count + int32(len(k))
2033 }
2034 return count
2035 }
2036 `)
2037 h62 := compileToIR(
2038 uintptr(unsafe.Pointer(&src62[0])), int32(len(src62)),
2039 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2040 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2041 )
2042 ir62 := getIR(h62)
2043 fmt.Println("=== IR for key-only map range ===")
2044 fmt.Println(ir62)
2045
2046 llvmVerify("key-only map range", ir62)
2047 assert("key range has hashmapNext", strings.Contains(ir62, "@runtime.hashmapNext"))
2048 assert("key range no parse error", !strings.Contains(ir62, "parse error"))
2049
2050 irFree(h62)
2051
2052 // Test 63: Local closure capturing mutable outer var
2053 src63 := []byte(`package mypkg
2054
2055 func test() int32 {
2056 counter := int32(0)
2057 inc := func() int32 {
2058 counter = counter + 1
2059 return counter
2060 }
2061 inc()
2062 inc()
2063 return inc()
2064 }
2065 `)
2066 h63 := compileToIR(
2067 uintptr(unsafe.Pointer(&src63[0])), int32(len(src63)),
2068 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2069 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2070 )
2071 ir63 := getIR(h63)
2072 fmt.Println("=== IR for mutable closure ===")
2073 fmt.Println(ir63)
2074
2075 llvmVerify("mutable closure", ir63)
2076 assert("closure has makeclosure", strings.Contains(ir63, "insertvalue {ptr, ptr}") || strings.Contains(ir63, "makeclosure"))
2077 assert("closure no parse error", !strings.Contains(ir63, "parse error"))
2078
2079 irFree(h63)
2080
2081 // Test 64: Classic for loop
2082 src64 := []byte(`package mypkg
2083
2084 func test() int32 {
2085 sum := int32(0)
2086 for i := int32(0); i < 10; i++ {
2087 sum = sum + i
2088 }
2089 return sum
2090 }
2091 `)
2092 h64 := compileToIR(
2093 uintptr(unsafe.Pointer(&src64[0])), int32(len(src64)),
2094 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2095 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2096 )
2097 ir64 := getIR(h64)
2098 fmt.Println("=== IR for classic for loop ===")
2099 fmt.Println(ir64)
2100
2101 llvmVerify("classic for loop", ir64)
2102 assert("for has icmp slt", strings.Contains(ir64, "icmp slt"))
2103 assert("for has add", strings.Contains(ir64, "add"))
2104 assert("for no parse error", !strings.Contains(ir64, "parse error"))
2105
2106 irFree(h64)
2107
2108 // Test 65: Multi-return value
2109 src65 := []byte(`package mypkg
2110
2111 func divmod(a, b int32) (int32, int32) {
2112 return a / b, a - (a / b) * b
2113 }
2114
2115 func test() int32 {
2116 q, r := divmod(17, 5)
2117 return q + r
2118 }
2119 `)
2120 h65 := compileToIR(
2121 uintptr(unsafe.Pointer(&src65[0])), int32(len(src65)),
2122 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2123 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2124 )
2125 ir65 := getIR(h65)
2126 fmt.Println("=== IR for multi-return ===")
2127 fmt.Println(ir65)
2128
2129 llvmVerify("multi-return", ir65)
2130 assert("multi-ret has extractvalue", strings.Contains(ir65, "extractvalue"))
2131 assert("multi-ret has divmod", strings.Contains(ir65, "@mypkg.divmod"))
2132 assert("multi-ret no parse error", !strings.Contains(ir65, "parse error"))
2133
2134 irFree(h65)
2135
2136 // Test 66: new() builtin
2137 src66 := []byte(`package mypkg
2138
2139 func test() int32 {
2140 p := new(int32)
2141 *p = 42
2142 return *p
2143 }
2144 `)
2145 h66 := compileToIR(
2146 uintptr(unsafe.Pointer(&src66[0])), int32(len(src66)),
2147 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2148 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2149 )
2150 ir66 := getIR(h66)
2151 fmt.Println("=== IR for new builtin ===")
2152 fmt.Println(ir66)
2153
2154 llvmVerify("new builtin", ir66)
2155 assert("new has alloc or alloca", strings.Contains(ir66, "alloc") || strings.Contains(ir66, "alloca"))
2156 assert("new has store 42", strings.Contains(ir66, "store i32 42"))
2157 assert("new no parse error", !strings.Contains(ir66, "parse error"))
2158
2159 irFree(h66)
2160
2161 // Test 67: Logical AND / OR operators
2162 src67 := []byte(`package mypkg
2163
2164 func test() int32 {
2165 a := true
2166 b := false
2167 c := true
2168 r := int32(0)
2169 if a && c {
2170 r = r + 1
2171 }
2172 if a || b {
2173 r = r + 10
2174 }
2175 if b && c {
2176 r = r + 100
2177 }
2178 if b || c {
2179 r = r + 1000
2180 }
2181 return r
2182 }
2183 `)
2184 h67 := compileToIR(
2185 uintptr(unsafe.Pointer(&src67[0])), int32(len(src67)),
2186 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2187 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2188 )
2189 ir67 := getIR(h67)
2190 fmt.Println("=== IR for logical AND/OR ===")
2191 fmt.Println(ir67)
2192
2193 llvmVerify("logical AND/OR", ir67)
2194 assert("land has and i1", strings.Contains(ir67, "and i1"))
2195 assert("lor has or i1", strings.Contains(ir67, "or i1"))
2196 assert("land/lor no parse error", !strings.Contains(ir67, "parse error"))
2197
2198 irFree(h67)
2199
2200 // Test 68: Multi-value switch case
2201 src68 := []byte(`package mypkg
2202
2203 func test() int32 {
2204 x := int32(3)
2205 r := int32(0)
2206 switch x {
2207 case 1, 2:
2208 r = 10
2209 case 3, 4:
2210 r = 20
2211 case 5:
2212 r = 30
2213 }
2214 return r
2215 }
2216 `)
2217 h68 := compileToIR(
2218 uintptr(unsafe.Pointer(&src68[0])), int32(len(src68)),
2219 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2220 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2221 )
2222 ir68 := getIR(h68)
2223 fmt.Println("=== IR for multi-value switch ===")
2224 fmt.Println(ir68)
2225
2226 llvmVerify("multi-value switch", ir68)
2227 assert("multi-case has icmp", strings.Contains(ir68, "icmp eq"))
2228 assert("multi-case no parse error", !strings.Contains(ir68, "parse error"))
2229
2230 irFree(h68)
2231
2232 // Test 69: Variadic append
2233 src69 := []byte(`package mypkg
2234
2235 func test() int32 {
2236 s := make([]int32, 0)
2237 s = append(s, 10, 20, 30)
2238 return s[0] + s[1] + s[2]
2239 }
2240 `)
2241 h69 := compileToIR(
2242 uintptr(unsafe.Pointer(&src69[0])), int32(len(src69)),
2243 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2244 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2245 )
2246 ir69 := getIR(h69)
2247 fmt.Println("=== IR for variadic append ===")
2248 fmt.Println(ir69)
2249
2250 llvmVerify("variadic append", ir69)
2251 assert("variadic append has sliceAppend", strings.Contains(ir69, "runtime.sliceAppend"))
2252 assert("variadic append no parse error", !strings.Contains(ir69, "parse error"))
2253
2254 irFree(h69)
2255
2256 // Test 70: Iota constants
2257 src70 := []byte(`package mypkg
2258
2259 const (
2260 A = iota
2261 B
2262 C
2263 )
2264
2265 const (
2266 X = 1 << iota
2267 Y
2268 Z
2269 )
2270
2271 func test() int32 {
2272 return int32(A + B + C + X + Y + Z)
2273 }
2274 `)
2275 h70 := compileToIR(
2276 uintptr(unsafe.Pointer(&src70[0])), int32(len(src70)),
2277 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2278 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2279 )
2280 ir70 := getIR(h70)
2281 fmt.Println("=== IR for iota constants ===")
2282 fmt.Println(ir70)
2283
2284 llvmVerify("iota constants", ir70)
2285 assert("iota no parse error", !strings.Contains(ir70, "parse error"))
2286
2287 irFree(h70)
2288
2289 // Test 71: Typed iota const + switch dispatch
2290 src71 := []byte(`package mypkg
2291
2292 type Color int32
2293
2294 const (
2295 Red Color = iota
2296 Green
2297 Blue
2298 )
2299
2300 func describe(c Color) int32 {
2301 switch c {
2302 case Red:
2303 return 1
2304 case Green:
2305 return 2
2306 case Blue:
2307 return 3
2308 }
2309 return 0
2310 }
2311
2312 func test() int32 {
2313 return describe(Red) + describe(Green) + describe(Blue)
2314 }
2315 `)
2316 h71 := compileToIR(
2317 uintptr(unsafe.Pointer(&src71[0])), int32(len(src71)),
2318 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2319 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2320 )
2321 ir71 := getIR(h71)
2322 fmt.Println("=== IR for typed iota switch ===")
2323 fmt.Println(ir71)
2324
2325 llvmVerify("typed iota switch", ir71)
2326 assert("typed iota has icmp", strings.Contains(ir71, "icmp eq"))
2327 assert("typed iota no parse error", !strings.Contains(ir71, "parse error"))
2328
2329 irFree(h71)
2330
2331 // Test 72: String switch
2332 src72 := []byte(`package mypkg
2333
2334 func classify(s string) int32 {
2335 switch s {
2336 case "hello":
2337 return 1
2338 case "world":
2339 return 2
2340 }
2341 return 0
2342 }
2343
2344 func test() int32 {
2345 return classify("hello") + classify("world")
2346 }
2347 `)
2348 h72 := compileToIR(
2349 uintptr(unsafe.Pointer(&src72[0])), int32(len(src72)),
2350 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2351 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2352 )
2353 ir72 := getIR(h72)
2354 fmt.Println("=== IR for string switch ===")
2355 fmt.Println(ir72)
2356
2357 llvmVerify("string switch", ir72)
2358 assert("string switch no parse error", !strings.Contains(ir72, "parse error"))
2359
2360 irFree(h72)
2361
2362 // Test 73: Nested field access (a.b.c pattern)
2363 src73 := []byte(`package mypkg
2364
2365 type Inner struct {
2366 val int32
2367 }
2368 type Outer struct {
2369 inner Inner
2370 extra int32
2371 }
2372
2373 func test() int32 {
2374 o := Outer{inner: Inner{val: 42}, extra: 8}
2375 return o.inner.val + o.extra
2376 }
2377 `)
2378 h73 := compileToIR(
2379 uintptr(unsafe.Pointer(&src73[0])), int32(len(src73)),
2380 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2381 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2382 )
2383 ir73 := getIR(h73)
2384 fmt.Println("=== IR for nested field access ===")
2385 fmt.Println(ir73)
2386
2387 llvmVerify("nested field access", ir73)
2388 assert("nested field has gep", strings.Contains(ir73, "getelementptr"))
2389 assert("nested field no parse error", !strings.Contains(ir73, "parse error"))
2390
2391 irFree(h73)
2392
2393 // Test 74: Method on pointer receiver with field mutation
2394 src74 := []byte(`package mypkg
2395
2396 type Counter struct {
2397 n int32
2398 }
2399
2400 func (c *Counter) inc() {
2401 c.n = c.n + 1
2402 }
2403
2404 func (c *Counter) get() int32 {
2405 return c.n
2406 }
2407
2408 func test() int32 {
2409 c := Counter{n: 0}
2410 c.inc()
2411 c.inc()
2412 c.inc()
2413 return c.get()
2414 }
2415 `)
2416 h74 := compileToIR(
2417 uintptr(unsafe.Pointer(&src74[0])), int32(len(src74)),
2418 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2419 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2420 )
2421 ir74 := getIR(h74)
2422 fmt.Println("=== IR for method mutation ===")
2423 fmt.Println(ir74)
2424
2425 llvmVerify("method mutation", ir74)
2426 assert("method mutation has Counter.inc", strings.Contains(ir74, "Counter.inc"))
2427 assert("method mutation no parse error", !strings.Contains(ir74, "parse error"))
2428
2429 irFree(h74)
2430
2431 // Test 75: Closure capturing method receiver (p := func() { e.field++ })
2432 src75 := []byte(`package mypkg
2433
2434 type Builder struct {
2435 count int32
2436 }
2437
2438 func (b *Builder) build() int32 {
2439 inc := func() {
2440 b.count = b.count + 1
2441 }
2442 inc()
2443 inc()
2444 inc()
2445 return b.count
2446 }
2447
2448 func test() int32 {
2449 b := Builder{count: 0}
2450 return b.build()
2451 }
2452 `)
2453 h75 := compileToIR(
2454 uintptr(unsafe.Pointer(&src75[0])), int32(len(src75)),
2455 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2456 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2457 )
2458 ir75 := getIR(h75)
2459 fmt.Println("=== IR for closure with receiver ===")
2460 fmt.Println(ir75)
2461
2462 llvmVerify("closure with receiver", ir75)
2463 assert("closure recv no parse error", !strings.Contains(ir75, "parse error"))
2464
2465 irFree(h75)
2466
2467 // Test 76: Slice of structs with append and field access
2468 src76 := []byte(`package mypkg
2469
2470 type Item struct {
2471 id int32
2472 val int32
2473 }
2474
2475 func test() int32 {
2476 items := make([]Item, 0)
2477 items = append(items, Item{id: 1, val: 10})
2478 items = append(items, Item{id: 2, val: 20})
2479 return items[0].val + items[1].val
2480 }
2481 `)
2482 h76 := compileToIR(
2483 uintptr(unsafe.Pointer(&src76[0])), int32(len(src76)),
2484 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2485 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2486 )
2487 ir76 := getIR(h76)
2488 fmt.Println("=== IR for slice of structs ===")
2489 fmt.Println(ir76)
2490
2491 llvmVerify("slice of structs", ir76)
2492 assert("slice structs has sliceAppend", strings.Contains(ir76, "sliceAppend"))
2493 assert("slice structs no parse error", !strings.Contains(ir76, "parse error"))
2494
2495 irFree(h76)
2496
2497 // Test 77: Global variable read/write
2498 src77 := []byte(`package mypkg
2499
2500 var counter int32
2501
2502 func inc() {
2503 counter = counter + 1
2504 }
2505
2506 func test() int32 {
2507 inc()
2508 inc()
2509 inc()
2510 return counter
2511 }
2512 `)
2513 h77 := compileToIR(
2514 uintptr(unsafe.Pointer(&src77[0])), int32(len(src77)),
2515 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2516 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2517 )
2518 ir77 := getIR(h77)
2519 fmt.Println("=== IR for global variable ===")
2520 fmt.Println(ir77)
2521
2522 llvmVerify("global variable", ir77)
2523 assert("global has @mypkg.counter", strings.Contains(ir77, "@mypkg.counter"))
2524 assert("global no parse error", !strings.Contains(ir77, "parse error"))
2525
2526 irFree(h77)
2527
2528 // Test 78: String indexing via parameter (string = []byte)
2529 src78 := []byte(`package mypkg
2530
2531 func getByte(s string, i int32) int32 {
2532 return int32(s[i])
2533 }
2534
2535 func test() int32 {
2536 return getByte("hello", 1)
2537 }
2538 `)
2539 h78 := compileToIR(
2540 uintptr(unsafe.Pointer(&src78[0])), int32(len(src78)),
2541 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2542 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2543 )
2544 ir78 := getIR(h78)
2545 fmt.Println("=== IR for string indexing ===")
2546 fmt.Println(ir78)
2547
2548 llvmVerify("string indexing", ir78)
2549 assert("string idx no parse error", !strings.Contains(ir78, "parse error"))
2550
2551 irFree(h78)
2552
2553 // Test 79: Byte slice from string (type conversion)
2554 src79 := []byte(`package mypkg
2555
2556 func test() int32 {
2557 s := "abc"
2558 b := []byte(s)
2559 return int32(b[0]) + int32(b[2])
2560 }
2561 `)
2562 h79 := compileToIR(
2563 uintptr(unsafe.Pointer(&src79[0])), int32(len(src79)),
2564 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2565 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2566 )
2567 ir79 := getIR(h79)
2568 fmt.Println("=== IR for byte slice from string ===")
2569 fmt.Println(ir79)
2570
2571 llvmVerify("byte slice from string", ir79)
2572 assert("byte slice no parse error", !strings.Contains(ir79, "parse error"))
2573
2574 irFree(h79)
2575
2576 // Test 80: Multiple return with named types
2577 src80 := []byte(`package mypkg
2578
2579 type Result struct {
2580 ok bool
2581 val int32
2582 }
2583
2584 func check(x int32) (Result, bool) {
2585 if x > 0 {
2586 return Result{ok: true, val: x}, true
2587 }
2588 return Result{ok: false, val: 0}, false
2589 }
2590
2591 func test() int32 {
2592 r, ok := check(42)
2593 if ok && r.ok {
2594 return r.val
2595 }
2596 return 0
2597 }
2598 `)
2599 h80 := compileToIR(
2600 uintptr(unsafe.Pointer(&src80[0])), int32(len(src80)),
2601 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2602 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2603 )
2604 ir80 := getIR(h80)
2605 fmt.Println("=== IR for struct return + logical AND ===")
2606 fmt.Println(ir80)
2607
2608 llvmVerify("struct return + logical AND", ir80)
2609 assert("struct ret no parse error", !strings.Contains(ir80, "parse error"))
2610
2611 irFree(h80)
2612
2613 // Test 81: Map with string keys and struct values
2614 src81 := []byte(`package mypkg
2615
2616 type Entry struct {
2617 name string
2618 val int32
2619 }
2620
2621 func test() int32 {
2622 m := make(map[string]Entry)
2623 m["x"] = Entry{name: "ex", val: 10}
2624 m["y"] = Entry{name: "why", val: 20}
2625 e := m["x"]
2626 return e.val
2627 }
2628 `)
2629 h81 := compileToIR(
2630 uintptr(unsafe.Pointer(&src81[0])), int32(len(src81)),
2631 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2632 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2633 )
2634 ir81 := getIR(h81)
2635 fmt.Println("=== IR for map struct values ===")
2636 fmt.Println(ir81)
2637
2638 llvmVerify("map struct values", ir81)
2639 assert("map struct no parse error", !strings.Contains(ir81, "parse error"))
2640
2641 irFree(h81)
2642
2643 // Test 82: Interface with two concrete method impls
2644 src82 := []byte(`package mypkg
2645
2646 type Expr interface {
2647 compute() int32
2648 }
2649
2650 type Lit struct {
2651 val int32
2652 }
2653
2654 func (l Lit) compute() int32 {
2655 return l.val
2656 }
2657
2658 type Binop struct {
2659 x int32
2660 y int32
2661 }
2662
2663 func (a Binop) compute() int32 {
2664 return a.x + a.y
2665 }
2666
2667 func run(e Expr) int32 {
2668 return e.compute()
2669 }
2670
2671 func test() int32 {
2672 a := Lit{val: 10}
2673 b := Binop{x: 20, y: 12}
2674 return run(a) + run(b)
2675 }
2676 `)
2677 h82 := compileToIR(
2678 uintptr(unsafe.Pointer(&src82[0])), int32(len(src82)),
2679 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2680 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2681 )
2682 ir82 := getIR(h82)
2683 fmt.Println("=== IR for interface method dispatch ===")
2684 fmt.Println(ir82)
2685
2686 llvmVerify("interface method dispatch", ir82)
2687 assert("iface dispatch has typeid", strings.Contains(ir82, "typeid"))
2688 assert("iface dispatch no parse error", !strings.Contains(ir82, "parse error"))
2689
2690 irFree(h82)
2691
2692 // Test 83: For loop with break
2693 src83 := []byte(`package mypkg
2694
2695 func test() int32 {
2696 sum := int32(0)
2697 for i := int32(0); i < 100; i = i + 1 {
2698 if i == 10 {
2699 break
2700 }
2701 sum = sum + i
2702 }
2703 return sum
2704 }
2705 `)
2706 h83 := compileToIR(
2707 uintptr(unsafe.Pointer(&src83[0])), int32(len(src83)),
2708 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2709 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2710 )
2711 ir83 := getIR(h83)
2712 fmt.Println("=== IR for break in loop ===")
2713 fmt.Println(ir83)
2714
2715 llvmVerify("break in loop", ir83)
2716 assert("break no parse error", !strings.Contains(ir83, "parse error"))
2717
2718 irFree(h83)
2719
2720 // Test 84: Continue in loop
2721 src84 := []byte(`package mypkg
2722
2723 func test() int32 {
2724 sum := int32(0)
2725 for i := int32(0); i < 10; i = i + 1 {
2726 if i == 5 {
2727 continue
2728 }
2729 sum = sum + i
2730 }
2731 return sum
2732 }
2733 `)
2734 h84 := compileToIR(
2735 uintptr(unsafe.Pointer(&src84[0])), int32(len(src84)),
2736 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2737 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2738 )
2739 ir84 := getIR(h84)
2740 fmt.Println("=== IR for continue in loop ===")
2741 fmt.Println(ir84)
2742
2743 llvmVerify("continue in loop", ir84)
2744 assert("continue no parse error", !strings.Contains(ir84, "parse error"))
2745
2746 irFree(h84)
2747
2748 // Test 85: String slicing
2749 src85 := []byte(`package mypkg
2750
2751 func test() int32 {
2752 s := "hello world"
2753 prefix := s[:5]
2754 return int32(len(prefix))
2755 }
2756 `)
2757 h85 := compileToIR(
2758 uintptr(unsafe.Pointer(&src85[0])), int32(len(src85)),
2759 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2760 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2761 )
2762 ir85 := getIR(h85)
2763 fmt.Println("=== IR for string slicing ===")
2764 fmt.Println(ir85)
2765
2766 llvmVerify("string slicing", ir85)
2767 assert("string slice no parse error", !strings.Contains(ir85, "parse error"))
2768
2769 irFree(h85)
2770
2771 // Test 86: Const in expression
2772 src86 := []byte(`package mypkg
2773
2774 const maxSize = 100
2775
2776 func test() int32 {
2777 x := int32(maxSize)
2778 return x + 1
2779 }
2780 `)
2781 h86 := compileToIR(
2782 uintptr(unsafe.Pointer(&src86[0])), int32(len(src86)),
2783 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2784 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2785 )
2786 ir86 := getIR(h86)
2787 fmt.Println("=== IR for const expression ===")
2788 fmt.Println(ir86)
2789
2790 llvmVerify("const expression", ir86)
2791 assert("const expr no parse error", !strings.Contains(ir86, "parse error"))
2792
2793 irFree(h86)
2794
2795 // Test 87: Assign to map value field (m[k] = v pattern)
2796 src87 := []byte(`package mypkg
2797
2798 func test() int32 {
2799 m := make(map[int32]int32)
2800 m[1] = 10
2801 m[2] = 20
2802 v1, ok1 := m[1]
2803 v2, ok2 := m[2]
2804 if ok1 && ok2 {
2805 return v1 + v2
2806 }
2807 return 0
2808 }
2809 `)
2810 h87 := compileToIR(
2811 uintptr(unsafe.Pointer(&src87[0])), int32(len(src87)),
2812 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2813 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2814 )
2815 ir87 := getIR(h87)
2816 fmt.Println("=== IR for map comma-ok ===")
2817 fmt.Println(ir87)
2818
2819 llvmVerify("map comma-ok", ir87)
2820 assert("map comma ok no parse error", !strings.Contains(ir87, "parse error"))
2821
2822 irFree(h87)
2823
2824 // Test 88: Nested if-else chains
2825 src88 := []byte(`package mypkg
2826
2827 func classify(x int32) int32 {
2828 if x < 0 {
2829 return -1
2830 } else if x == 0 {
2831 return 0
2832 } else if x < 10 {
2833 return 1
2834 } else {
2835 return 2
2836 }
2837 }
2838
2839 func test() int32 {
2840 return classify(-5) + classify(0) + classify(5) + classify(50)
2841 }
2842 `)
2843 h88 := compileToIR(
2844 uintptr(unsafe.Pointer(&src88[0])), int32(len(src88)),
2845 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2846 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2847 )
2848 ir88 := getIR(h88)
2849 fmt.Println("=== IR for if-else chain ===")
2850 fmt.Println(ir88)
2851
2852 llvmVerify("if-else chain", ir88)
2853 assert("if-else no parse error", !strings.Contains(ir88, "parse error"))
2854
2855 irFree(h88)
2856
2857 // Test 89: String concatenation via | operator (Moxie-specific)
2858 src89 := []byte(`package mypkg
2859
2860 func test() int32 {
2861 a := "hello"
2862 b := " world"
2863 c := a | b
2864 return int32(len(c))
2865 }
2866 `)
2867 h89 := compileToIR(
2868 uintptr(unsafe.Pointer(&src89[0])), int32(len(src89)),
2869 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2870 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2871 )
2872 ir89 := getIR(h89)
2873 fmt.Println("=== IR for string | concat ===")
2874 fmt.Println(ir89)
2875
2876 llvmVerify("string | concat", ir89)
2877 assert("pipe concat has sliceAppend", strings.Contains(ir89, "sliceAppend"))
2878 assert("pipe concat no parse error", !strings.Contains(ir89, "parse error"))
2879
2880 irFree(h89)
2881
2882 // Test 90: Switch with default case
2883 src90 := []byte(`package mypkg
2884
2885 func test() int32 {
2886 x := int32(99)
2887 switch x {
2888 case 1:
2889 return 10
2890 case 2:
2891 return 20
2892 default:
2893 return 42
2894 }
2895 }
2896 `)
2897 h90 := compileToIR(
2898 uintptr(unsafe.Pointer(&src90[0])), int32(len(src90)),
2899 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2900 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2901 )
2902 ir90 := getIR(h90)
2903 fmt.Println("=== IR for switch default ===")
2904 fmt.Println(ir90)
2905
2906 llvmVerify("switch default", ir90)
2907 assert("switch default no parse error", !strings.Contains(ir90, "parse error"))
2908
2909 irFree(h90)
2910
2911 // Test 91: Boolean negation
2912 src91 := []byte(`package mypkg
2913
2914 func test() int32 {
2915 a := true
2916 b := false
2917 r := int32(0)
2918 if !a {
2919 r = r + 1
2920 }
2921 if !b {
2922 r = r + 10
2923 }
2924 return r
2925 }
2926 `)
2927 h91 := compileToIR(
2928 uintptr(unsafe.Pointer(&src91[0])), int32(len(src91)),
2929 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2930 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2931 )
2932 ir91 := getIR(h91)
2933 fmt.Println("=== IR for boolean negation ===")
2934 fmt.Println(ir91)
2935
2936 llvmVerify("boolean negation", ir91)
2937 assert("bool neg has xor", strings.Contains(ir91, "xor"))
2938 assert("bool neg no parse error", !strings.Contains(ir91, "parse error"))
2939
2940 irFree(h91)
2941
2942 // Test 92: Tuple swap (slice element swap)
2943 src92 := []byte(`package mypkg
2944
2945 func test() int32 {
2946 s := make([]int32, 3)
2947 s[0] = 1
2948 s[1] = 2
2949 s[2] = 3
2950 s[0], s[1] = s[1], s[0]
2951 return s[0] + s[1]*10 + s[2]*100
2952 }
2953 `)
2954 h92 := compileToIR(
2955 uintptr(unsafe.Pointer(&src92[0])), int32(len(src92)),
2956 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2957 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2958 )
2959 ir92 := getIR(h92)
2960 fmt.Println("=== IR for tuple swap ===")
2961 fmt.Println(ir92)
2962
2963 llvmVerify("tuple swap", ir92)
2964 assert("tuple swap no parse error", !strings.Contains(ir92, "parse error"))
2965
2966 irFree(h92)
2967
2968 // Test 93: String less-than comparison
2969 src93 := []byte(`package mypkg
2970
2971 func test() int32 {
2972 a := "apple"
2973 b := "banana"
2974 if a < b {
2975 return 1
2976 }
2977 return 0
2978 }
2979 `)
2980 h93 := compileToIR(
2981 uintptr(unsafe.Pointer(&src93[0])), int32(len(src93)),
2982 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2983 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2984 )
2985 ir93 := getIR(h93)
2986 fmt.Println("=== IR for string less-than ===")
2987 fmt.Println(ir93)
2988
2989 llvmVerify("string less-than", ir93)
2990 assert("str lt has stringLess", strings.Contains(ir93, "stringLess"))
2991 assert("str lt no parse error", !strings.Contains(ir93, "parse error"))
2992
2993 irFree(h93)
2994
2995 // Test 94: Integer negation
2996 src94 := []byte(`package mypkg
2997
2998 func abs(x int32) int32 {
2999 if x < 0 {
3000 return -x
3001 }
3002 return x
3003 }
3004
3005 func test() int32 {
3006 return abs(-5) + abs(3)
3007 }
3008 `)
3009 h94 := compileToIR(
3010 uintptr(unsafe.Pointer(&src94[0])), int32(len(src94)),
3011 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3012 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3013 )
3014 ir94 := getIR(h94)
3015 fmt.Println("=== IR for integer negation ===")
3016 fmt.Println(ir94)
3017
3018 llvmVerify("integer negation", ir94)
3019 assert("int neg has sub i32 0", strings.Contains(ir94, "sub i32 0"))
3020 assert("int neg no parse error", !strings.Contains(ir94, "parse error"))
3021
3022 irFree(h94)
3023
3024 // Test 95: Int64 arithmetic
3025 src95 := []byte(`package mypkg
3026
3027 func test() int32 {
3028 a := int64(1000000)
3029 b := int64(2000000)
3030 c := a + b
3031 return int32(c / int64(1000))
3032 }
3033 `)
3034 h95 := compileToIR(
3035 uintptr(unsafe.Pointer(&src95[0])), int32(len(src95)),
3036 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3037 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3038 )
3039 ir95 := getIR(h95)
3040 fmt.Println("=== IR for int64 arithmetic ===")
3041 fmt.Println(ir95)
3042
3043 llvmVerify("int64 arithmetic", ir95)
3044 assert("int64 has i64", strings.Contains(ir95, "i64"))
3045 assert("int64 no parse error", !strings.Contains(ir95, "parse error"))
3046
3047 irFree(h95)
3048
3049 // Test 96: Global variable with initializer
3050 src96 := []byte(`package mypkg
3051
3052 var offset int32 = 100
3053
3054 func test() int32 {
3055 return offset + 5
3056 }
3057 `)
3058 h96 := compileToIR(
3059 uintptr(unsafe.Pointer(&src96[0])), int32(len(src96)),
3060 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3061 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3062 )
3063 ir96 := getIR(h96)
3064 fmt.Println("=== IR for global var initializer ===")
3065 fmt.Println(ir96)
3066
3067 llvmVerify("global var initializer", ir96)
3068 assert("global init has @mypkg.offset", strings.Contains(ir96, "@mypkg.offset"))
3069 assert("global init no parse error", !strings.Contains(ir96, "parse error"))
3070
3071 irFree(h96)
3072
3073 // Test 97: Blank identifier in multi-return
3074 src97 := []byte(`package mypkg
3075
3076 func pair() (int32, int32) {
3077 return 10, 20
3078 }
3079
3080 func test() int32 {
3081 _, b := pair()
3082 return b
3083 }
3084 `)
3085 h97 := compileToIR(
3086 uintptr(unsafe.Pointer(&src97[0])), int32(len(src97)),
3087 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3088 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3089 )
3090 ir97 := getIR(h97)
3091 fmt.Println("=== IR for blank identifier ===")
3092 fmt.Println(ir97)
3093
3094 llvmVerify("blank identifier", ir97)
3095 assert("blank id no parse error", !strings.Contains(ir97, "parse error"))
3096
3097 irFree(h97)
3098
3099 // Test 98: For range with index only (i := range slice)
3100 src98 := []byte(`package mypkg
3101
3102 func test() int32 {
3103 s := []int32{10, 20, 30, 40}
3104 sum := int32(0)
3105 for i := range s {
3106 sum = sum + int32(i)
3107 }
3108 return sum
3109 }
3110 `)
3111 h98 := compileToIR(
3112 uintptr(unsafe.Pointer(&src98[0])), int32(len(src98)),
3113 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3114 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3115 )
3116 ir98 := getIR(h98)
3117 fmt.Println("=== IR for range index only ===")
3118 fmt.Println(ir98)
3119
3120 llvmVerify("range index only", ir98)
3121 assert("range idx no parse error", !strings.Contains(ir98, "parse error"))
3122
3123 irFree(h98)
3124
3125 // Test 99: Append with variadic expansion (append(buf, s...))
3126 src99 := []byte(`package mypkg
3127
3128 func test() int32 {
3129 buf := make([]byte, 0)
3130 s := "hello"
3131 buf = append(buf, s...)
3132 return int32(len(buf))
3133 }
3134 `)
3135 h99 := compileToIR(
3136 uintptr(unsafe.Pointer(&src99[0])), int32(len(src99)),
3137 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3138 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3139 )
3140 ir99 := getIR(h99)
3141 fmt.Println("=== IR for append with dots ===")
3142 fmt.Println(ir99)
3143
3144 llvmVerify("append with dots", ir99)
3145 assert("append dots has sliceAppend", strings.Contains(ir99, "sliceAppend"))
3146 assert("append dots no parse error", !strings.Contains(ir99, "parse error"))
3147
3148 irFree(h99)
3149
3150 // Test 100: Assign to struct field through pointer
3151 src100 := []byte(`package mypkg
3152
3153 type Node struct {
3154 val int32
3155 next *Node
3156 }
3157
3158 func test() int32 {
3159 a := Node{val: 10}
3160 b := Node{val: 20, next: &a}
3161 return b.val + b.next.val
3162 }
3163 `)
3164 h100 := compileToIR(
3165 uintptr(unsafe.Pointer(&src100[0])), int32(len(src100)),
3166 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3167 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3168 )
3169 ir100 := getIR(h100)
3170 fmt.Println("=== IR for struct pointer chain ===")
3171 fmt.Println(ir100)
3172
3173 llvmVerify("struct pointer chain", ir100)
3174 assert("ptr chain no parse error", !strings.Contains(ir100, "parse error"))
3175
3176 irFree(h100)
3177
3178 // Test 101: Address-of operator
3179 src101 := []byte(`package mypkg
3180
3181 func setVal(p *int32, v int32) {
3182 *p = v
3183 }
3184
3185 func test() int32 {
3186 x := int32(0)
3187 setVal(&x, 42)
3188 return x
3189 }
3190 `)
3191 h101 := compileToIR(
3192 uintptr(unsafe.Pointer(&src101[0])), int32(len(src101)),
3193 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3194 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3195 )
3196 ir101 := getIR(h101)
3197 fmt.Println("=== IR for address-of ===")
3198 fmt.Println(ir101)
3199
3200 llvmVerify("address-of", ir101)
3201 assert("addr-of no parse error", !strings.Contains(ir101, "parse error"))
3202
3203 irFree(h101)
3204
3205 // Test 102: Map delete
3206 src102 := []byte(`package mypkg
3207
3208 func test() int32 {
3209 m := map[string]int32{"a": 1, "b": 2, "c": 3}
3210 delete(m, "b")
3211 _, ok := m["b"]
3212 if ok {
3213 return 0
3214 }
3215 return 1
3216 }
3217 `)
3218 h102 := compileToIR(
3219 uintptr(unsafe.Pointer(&src102[0])), int32(len(src102)),
3220 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3221 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3222 )
3223 ir102 := getIR(h102)
3224 fmt.Println("=== IR for map delete ===")
3225 fmt.Println(ir102)
3226
3227 llvmVerify("map delete", ir102)
3228 assert("map del has hashmapDelete", strings.Contains(ir102, "hashmapDelete") || strings.Contains(ir102, "hashmapBinaryDelete"))
3229 assert("map del no parse error", !strings.Contains(ir102, "parse error"))
3230
3231 irFree(h102)
3232
3233 // Test 103: String constant
3234 src103 := []byte(`package mypkg
3235
3236 const greeting = "hello"
3237
3238 func test() int32 {
3239 s := greeting
3240 return int32(len(s))
3241 }
3242 `)
3243 h103 := compileToIR(
3244 uintptr(unsafe.Pointer(&src103[0])), int32(len(src103)),
3245 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3246 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3247 )
3248 ir103 := getIR(h103)
3249 fmt.Println("=== IR for string const ===")
3250 fmt.Println(ir103)
3251
3252 llvmVerify("string const", ir103)
3253 assert("str const no parse error", !strings.Contains(ir103, "parse error"))
3254
3255 irFree(h103)
3256
3257 // Test 104: Nested method calls (a.b().c())
3258 src104 := []byte(`package mypkg
3259
3260 type Builder struct {
3261 buf []byte
3262 }
3263
3264 func (b *Builder) write(s string) *Builder {
3265 b.buf = append(b.buf, s...)
3266 return b
3267 }
3268
3269 func (b *Builder) length() int32 {
3270 return int32(len(b.buf))
3271 }
3272
3273 func test() int32 {
3274 b := Builder{buf: make([]byte, 0)}
3275 b.write("hello")
3276 b.write(" world")
3277 return b.length()
3278 }
3279 `)
3280 h104 := compileToIR(
3281 uintptr(unsafe.Pointer(&src104[0])), int32(len(src104)),
3282 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3283 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3284 )
3285 ir104 := getIR(h104)
3286 fmt.Println("=== IR for method chaining ===")
3287 fmt.Println(ir104)
3288
3289 llvmVerify("method chaining", ir104)
3290 assert("method chain has Builder.write", strings.Contains(ir104, "Builder.write"))
3291 assert("method chain no parse error", !strings.Contains(ir104, "parse error"))
3292
3293 irFree(h104)
3294
3295 // Test 105: Unary not on comparison
3296 src105 := []byte(`package mypkg
3297
3298 func test() int32 {
3299 x := int32(5)
3300 if !(x > 10) {
3301 return 1
3302 }
3303 return 0
3304 }
3305 `)
3306 h105 := compileToIR(
3307 uintptr(unsafe.Pointer(&src105[0])), int32(len(src105)),
3308 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3309 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3310 )
3311 ir105 := getIR(h105)
3312 fmt.Println("=== IR for not-comparison ===")
3313 fmt.Println(ir105)
3314
3315 llvmVerify("not-comparison", ir105)
3316 assert("not cmp no parse error", !strings.Contains(ir105, "parse error"))
3317
3318 irFree(h105)
3319
3320 // Test 106: Self-compilation pattern - irItoa-like function
3321 src106 := []byte(`package mypkg
3322
3323 func itoa(n int) string {
3324 if n == 0 {
3325 return "0"
3326 }
3327 neg := false
3328 if n < 0 {
3329 neg = true
3330 n = -n
3331 }
3332 buf := make([]byte, 0)
3333 for n > 0 {
3334 buf = append(buf, byte(n%10)+'0')
3335 n = n / 10
3336 }
3337 if neg {
3338 buf = append(buf, '-')
3339 }
3340 result := make([]byte, len(buf))
3341 for i := 0; i < len(buf); i = i + 1 {
3342 result[i] = buf[len(buf)-1-i]
3343 }
3344 return string(result)
3345 }
3346
3347 func test() int32 {
3348 s := itoa(42)
3349 return int32(len(s))
3350 }
3351 `)
3352 h106 := compileToIR(
3353 uintptr(unsafe.Pointer(&src106[0])), int32(len(src106)),
3354 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3355 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3356 )
3357 ir106 := getIR(h106)
3358 fmt.Println("=== IR for itoa self-compilation pattern ===")
3359 fmt.Println(ir106)
3360
3361 llvmVerify("itoa self-compile", ir106)
3362 assert("itoa has sliceAppend", strings.Contains(ir106, "sliceAppend"))
3363 assert("itoa no parse error", !strings.Contains(ir106, "parse error"))
3364
3365 irFree(h106)
3366
3367 // Test 107: Type method returning interface (SSAMember pattern)
3368 src107 := []byte(`package mypkg
3369
3370 type Member interface {
3371 Name() string
3372 }
3373
3374 type Func struct {
3375 name string
3376 }
3377
3378 func (f *Func) Name() string {
3379 return f.name
3380 }
3381
3382 type Global struct {
3383 name string
3384 }
3385
3386 func (g *Global) Name() string {
3387 return g.name
3388 }
3389
3390 func getMember(which int32) Member {
3391 if which == 0 {
3392 return &Func{name: "test"}
3393 }
3394 return &Global{name: "counter"}
3395 }
3396
3397 func test() int32 {
3398 m := getMember(0)
3399 n := m.Name()
3400 return int32(len(n))
3401 }
3402 `)
3403 h107 := compileToIR(
3404 uintptr(unsafe.Pointer(&src107[0])), int32(len(src107)),
3405 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3406 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3407 )
3408 ir107 := getIR(h107)
3409 fmt.Println("=== IR for interface return ===")
3410 fmt.Println(ir107)
3411
3412 llvmVerify("interface return", ir107)
3413 assert("iface ret has typeid", strings.Contains(ir107, "typeid"))
3414 assert("iface ret no parse error", !strings.Contains(ir107, "parse error"))
3415
3416 irFree(h107)
3417
3418 // Test 108: Interface variable assignment
3419 src108 := []byte(`package mypkg
3420
3421 type Stringer interface {
3422 str() string
3423 }
3424
3425 type Num struct {
3426 val int32
3427 }
3428
3429 func (n Num) str() string {
3430 return "num"
3431 }
3432
3433 func test() int32 {
3434 var s Stringer
3435 s = Num{val: 42}
3436 name := s.str()
3437 return int32(len(name))
3438 }
3439 `)
3440 h108 := compileToIR(
3441 uintptr(unsafe.Pointer(&src108[0])), int32(len(src108)),
3442 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3443 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3444 )
3445 ir108 := getIR(h108)
3446 fmt.Println("=== IR for iface var assign ===")
3447 fmt.Println(ir108)
3448
3449 llvmVerify("iface var assign", ir108)
3450 assert("iface assign has typeid", strings.Contains(ir108, "typeid"))
3451 assert("iface assign no parse error", !strings.Contains(ir108, "parse error"))
3452
3453 irFree(h108)
3454
3455 // Test 109: string(buf) conversion from []byte
3456 src109 := []byte(`package mypkg
3457
3458 func test() int32 {
3459 buf := []byte{72, 105}
3460 s := string(buf)
3461 return int32(len(s))
3462 }
3463 `)
3464 h109 := compileToIR(
3465 uintptr(unsafe.Pointer(&src109[0])), int32(len(src109)),
3466 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3467 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3468 )
3469 ir109 := getIR(h109)
3470 fmt.Println("=== IR for string(buf) ===")
3471 fmt.Println(ir109)
3472
3473 llvmVerify("string(buf)", ir109)
3474 assert("string buf no parse error", !strings.Contains(ir109, "parse error"))
3475
3476 irFree(h109)
3477
3478 // Test 110: byte(expr) conversion + char literal
3479 src110 := []byte(`package mypkg
3480
3481 func test() int32 {
3482 n := int32(5)
3483 b := byte('0' + n)
3484 return int32(b)
3485 }
3486 `)
3487 h110 := compileToIR(
3488 uintptr(unsafe.Pointer(&src110[0])), int32(len(src110)),
3489 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3490 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3491 )
3492 ir110 := getIR(h110)
3493 fmt.Println("=== IR for byte conversion ===")
3494 fmt.Println(ir110)
3495
3496 llvmVerify("byte conversion", ir110)
3497 assert("byte conv no parse error", !strings.Contains(ir110, "parse error"))
3498
3499 irFree(h110)
3500
3501 // Test 111: Slice append in loop (builder pattern from ir_emit)
3502 src111 := []byte(`package mypkg
3503
3504 type Writer struct {
3505 buf []byte
3506 }
3507
3508 func (w *Writer) write(s string) {
3509 w.buf = append(w.buf, s...)
3510 }
3511
3512 func (w *Writer) result() string {
3513 return string(w.buf)
3514 }
3515
3516 func test() int32 {
3517 w := Writer{buf: make([]byte, 0)}
3518 w.write("he")
3519 w.write("llo")
3520 s := w.result()
3521 return int32(len(s))
3522 }
3523 `)
3524 h111 := compileToIR(
3525 uintptr(unsafe.Pointer(&src111[0])), int32(len(src111)),
3526 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3527 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3528 )
3529 ir111 := getIR(h111)
3530 fmt.Println("=== IR for writer pattern ===")
3531 fmt.Println(ir111)
3532
3533 llvmVerify("writer pattern", ir111)
3534 assert("writer has sliceAppend", strings.Contains(ir111, "sliceAppend"))
3535 assert("writer no parse error", !strings.Contains(ir111, "parse error"))
3536
3537 irFree(h111)
3538
3539 // Test 112: Map with string values and range iteration
3540 src112 := []byte(`package mypkg
3541
3542 func test() int32 {
3543 m := map[string]string{"a": "alpha", "b": "beta"}
3544 total := int32(0)
3545 for _, v := range m {
3546 total = total + int32(len(v))
3547 }
3548 return total
3549 }
3550 `)
3551 h112 := compileToIR(
3552 uintptr(unsafe.Pointer(&src112[0])), int32(len(src112)),
3553 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3554 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3555 )
3556 ir112 := getIR(h112)
3557 fmt.Println("=== IR for map string range ===")
3558 fmt.Println(ir112)
3559
3560 llvmVerify("map string range", ir112)
3561 assert("map str range no parse error", !strings.Contains(ir112, "parse error"))
3562
3563 irFree(h112)
3564
3565 // Test 113: Nested if with type assertion
3566 src113 := []byte(`package mypkg
3567
3568 type Animal interface {
3569 sound() string
3570 }
3571
3572 type Dog struct{}
3573
3574 func (d Dog) sound() string { return "woof" }
3575
3576 type Cat struct{}
3577
3578 func (c Cat) sound() string { return "meow" }
3579
3580 func describe(a Animal) int32 {
3581 if d, ok := a.(Dog); ok {
3582 s := d.sound()
3583 return int32(len(s))
3584 }
3585 if c, ok := a.(Cat); ok {
3586 s := c.sound()
3587 return int32(len(s))
3588 }
3589 return 0
3590 }
3591
3592 func test() int32 {
3593 return describe(Dog{}) + describe(Cat{})
3594 }
3595 `)
3596 h113 := compileToIR(
3597 uintptr(unsafe.Pointer(&src113[0])), int32(len(src113)),
3598 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3599 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3600 )
3601 ir113 := getIR(h113)
3602 fmt.Println("=== IR for if type assertion ===")
3603 fmt.Println(ir113)
3604
3605 llvmVerify("if type assertion", ir113)
3606 assert("if type assert no parse error", !strings.Contains(ir113, "parse error"))
3607
3608 irFree(h113)
3609
3610 // Test 114: Large switch on int constant (simulates SSA op dispatch)
3611 src114 := []byte(`package mypkg
3612
3613 const (
3614 OpAdd = iota
3615 OpSub
3616 OpMul
3617 OpDiv
3618 OpEql
3619 OpNeq
3620 OpLss
3621 OpGtr
3622 )
3623
3624 func opName(op int32) string {
3625 switch op {
3626 case OpAdd:
3627 return "add"
3628 case OpSub:
3629 return "sub"
3630 case OpMul:
3631 return "mul"
3632 case OpDiv:
3633 return "div"
3634 case OpEql:
3635 return "eq"
3636 case OpNeq:
3637 return "ne"
3638 case OpLss:
3639 return "lt"
3640 case OpGtr:
3641 return "gt"
3642 default:
3643 return "?"
3644 }
3645 }
3646
3647 func test() int32 {
3648 s1 := opName(OpAdd)
3649 s2 := opName(OpDiv)
3650 return int32(len(s1) + len(s2))
3651 }
3652 `)
3653 h114 := compileToIR(
3654 uintptr(unsafe.Pointer(&src114[0])), int32(len(src114)),
3655 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3656 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3657 )
3658 ir114 := getIR(h114)
3659 fmt.Println("=== IR for large iota switch ===")
3660 fmt.Println(ir114)
3661
3662 llvmVerify("large iota switch", ir114)
3663 assert("large switch has icmp", strings.Contains(ir114, "icmp eq"))
3664 assert("large switch no parse error", !strings.Contains(ir114, "parse error"))
3665
3666 irFree(h114)
3667
3668 // Test 115: Nested type switch (primary dispatch pattern in ir_emit.mx)
3669 src115 := []byte(`package mypkg
3670
3671 type Node interface {
3672 nodeType() int32
3673 }
3674
3675 type Lit struct {
3676 val int32
3677 }
3678 func (l Lit) nodeType() int32 { return 1 }
3679
3680 type BinOp struct {
3681 op int32
3682 x Node
3683 y Node
3684 }
3685 func (b BinOp) nodeType() int32 { return 2 }
3686
3687 type UnOp struct {
3688 op int32
3689 x Node
3690 }
3691 func (u UnOp) nodeType() int32 { return 3 }
3692
3693 func eval(n Node) int32 {
3694 switch v := n.(type) {
3695 case Lit:
3696 return v.val
3697 case BinOp:
3698 lv := eval(v.x)
3699 rv := eval(v.y)
3700 switch v.op {
3701 case 1:
3702 return lv + rv
3703 case 2:
3704 return lv - rv
3705 default:
3706 return 0
3707 }
3708 case UnOp:
3709 inner := eval(v.x)
3710 if v.op == 1 {
3711 return 0 - inner
3712 }
3713 return inner
3714 }
3715 return 0
3716 }
3717
3718 func test() int32 {
3719 a := Lit{val: 10}
3720 b := Lit{val: 3}
3721 sum := BinOp{op: 1, x: a, y: b}
3722 return eval(sum)
3723 }
3724 `)
3725 h115 := compileToIR(
3726 uintptr(unsafe.Pointer(&src115[0])), int32(len(src115)),
3727 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3728 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3729 )
3730 ir115 := getIR(h115)
3731 fmt.Println("=== IR for nested type switch ===")
3732 fmt.Println(ir115)
3733
3734 llvmVerify("nested type switch", ir115)
3735 assert("nested tswitch has eval", strings.Contains(ir115, "@mypkg.eval"))
3736 assert("nested tswitch no parse error", !strings.Contains(ir115, "parse error"))
3737
3738 irFree(h115)
3739
3740 // Test 116: String concatenation via | operator (Moxie-specific)
3741 src116 := []byte(`package mypkg
3742
3743 func join(a string, b string) string {
3744 return a | b
3745 }
3746
3747 func test() int32 {
3748 s := join("hel", "lo")
3749 return int32(len(s))
3750 }
3751 `)
3752 h116 := compileToIR(
3753 uintptr(unsafe.Pointer(&src116[0])), int32(len(src116)),
3754 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3755 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3756 )
3757 ir116 := getIR(h116)
3758 fmt.Println("=== IR for string concat ===")
3759 fmt.Println(ir116)
3760
3761 llvmVerify("string concat", ir116)
3762 assert("str concat has sliceAppend", strings.Contains(ir116, "sliceAppend"))
3763 assert("str concat no parse error", !strings.Contains(ir116, "parse error"))
3764
3765 irFree(h116)
3766
3767 // Test 117: Multiple return values with named usage
3768 src117 := []byte(`package mypkg
3769
3770 func divmod(a int32, b int32) (int32, int32) {
3771 return a / b, a % b
3772 }
3773
3774 func test() int32 {
3775 q, r := divmod(17, 5)
3776 return q*10 + r
3777 }
3778 `)
3779 h117 := compileToIR(
3780 uintptr(unsafe.Pointer(&src117[0])), int32(len(src117)),
3781 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3782 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3783 )
3784 ir117 := getIR(h117)
3785 fmt.Println("=== IR for multi-return ===")
3786 fmt.Println(ir117)
3787
3788 llvmVerify("multi-return", ir117)
3789 assert("multi-return has extractvalue", strings.Contains(ir117, "extractvalue"))
3790 assert("multi-return no parse error", !strings.Contains(ir117, "parse error"))
3791
3792 irFree(h117)
3793
3794 // Test 118: For-range over string (byte iteration - Moxie string=[]byte)
3795 src118 := []byte(`package mypkg
3796
3797 func countUpper(s string) int32 {
3798 n := int32(0)
3799 for _, c := range s {
3800 if int32(c) >= 65 && int32(c) <= 90 {
3801 n = n + 1
3802 }
3803 }
3804 return n
3805 }
3806
3807 func test() int32 {
3808 return countUpper("Hello World")
3809 }
3810 `)
3811 h118 := compileToIR(
3812 uintptr(unsafe.Pointer(&src118[0])), int32(len(src118)),
3813 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3814 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3815 )
3816 ir118 := getIR(h118)
3817 fmt.Println("=== IR for range over string ===")
3818 fmt.Println(ir118)
3819
3820 llvmVerify("range over string", ir118)
3821 assert("range string no parse error", !strings.Contains(ir118, "parse error"))
3822
3823 irFree(h118)
3824
3825 // Test 119: Nested struct field write through pointer receiver
3826 src119 := []byte(`package mypkg
3827
3828 type Inner struct {
3829 val int32
3830 }
3831
3832 type Outer struct {
3833 inner Inner
3834 count int32
3835 }
3836
3837 func (o *Outer) setVal(v int32) {
3838 o.inner.val = v
3839 o.count = o.count + 1
3840 }
3841
3842 func (o *Outer) getVal() int32 {
3843 return o.inner.val
3844 }
3845
3846 func test() int32 {
3847 o := Outer{inner: Inner{val: 0}, count: 0}
3848 o.setVal(42)
3849 return o.getVal() + o.count
3850 }
3851 `)
3852 h119 := compileToIR(
3853 uintptr(unsafe.Pointer(&src119[0])), int32(len(src119)),
3854 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3855 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3856 )
3857 ir119 := getIR(h119)
3858 fmt.Println("=== IR for nested struct write ===")
3859 fmt.Println(ir119)
3860
3861 llvmVerify("nested struct write", ir119)
3862 assert("nested struct has getelementptr", strings.Contains(ir119, "getelementptr"))
3863 assert("nested struct no parse error", !strings.Contains(ir119, "parse error"))
3864
3865 irFree(h119)
3866
3867 // Test 120: Global variable with simple init and function-level map
3868 src120 := []byte(`package mypkg
3869
3870 var globalCount int32 = 10
3871
3872 func lookup(s string) int32 {
3873 m := map[string]int32{"if": 1, "for": 3}
3874 v, ok := m[s]
3875 if ok {
3876 return v + globalCount
3877 }
3878 return 0
3879 }
3880
3881 func test() int32 {
3882 return lookup("if") + lookup("for")
3883 }
3884 `)
3885 h120 := compileToIR(
3886 uintptr(unsafe.Pointer(&src120[0])), int32(len(src120)),
3887 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3888 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3889 )
3890 ir120 := getIR(h120)
3891 fmt.Println("=== IR for global var + local map ===")
3892 fmt.Println(ir120)
3893
3894 llvmVerify("global var + local map", ir120)
3895 assert("global var has globalCount", strings.Contains(ir120, "@mypkg.globalCount"))
3896 assert("global var no parse error", !strings.Contains(ir120, "parse error"))
3897
3898 irFree(h120)
3899
3900 // Test 121: Recursive data structure (linked list - forward ref types)
3901 src121 := []byte(`package mypkg
3902
3903 type ListNode struct {
3904 val int32
3905 next *ListNode
3906 }
3907
3908 func sum(n *ListNode) int32 {
3909 total := int32(0)
3910 cur := n
3911 for cur != nil {
3912 total = total + cur.val
3913 cur = cur.next
3914 }
3915 return total
3916 }
3917
3918 func test() int32 {
3919 c := ListNode{val: 3, next: nil}
3920 b := ListNode{val: 2, next: &c}
3921 a := ListNode{val: 1, next: &b}
3922 return sum(&a)
3923 }
3924 `)
3925 h121 := compileToIR(
3926 uintptr(unsafe.Pointer(&src121[0])), int32(len(src121)),
3927 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3928 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3929 )
3930 ir121 := getIR(h121)
3931 fmt.Println("=== IR for linked list ===")
3932 fmt.Println(ir121)
3933
3934 llvmVerify("linked list", ir121)
3935 assert("linked list has icmp ne ptr", strings.Contains(ir121, "icmp ne ptr"))
3936 assert("linked list no parse error", !strings.Contains(ir121, "parse error"))
3937
3938 irFree(h121)
3939
3940 // Test 122: Slice of interfaces (heterogeneous collection)
3941 src122 := []byte(`package mypkg
3942
3943 type Sizer interface {
3944 size() int32
3945 }
3946
3947 type Small struct{}
3948 func (s Small) size() int32 { return 1 }
3949
3950 type Big struct{ n int32 }
3951 func (b Big) size() int32 { return b.n }
3952
3953 func totalSize(items []Sizer) int32 {
3954 total := int32(0)
3955 for _, item := range items {
3956 total = total + item.size()
3957 }
3958 return total
3959 }
3960
3961 func test() int32 {
3962 items := []Sizer{Small{}, Big{n: 5}, Small{}, Big{n: 10}}
3963 return totalSize(items)
3964 }
3965 `)
3966 h122 := compileToIR(
3967 uintptr(unsafe.Pointer(&src122[0])), int32(len(src122)),
3968 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3969 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3970 )
3971 ir122 := getIR(h122)
3972 fmt.Println("=== IR for interface slice ===")
3973 fmt.Println(ir122)
3974
3975 llvmVerify("interface slice", ir122)
3976 assert("iface slice no parse error", !strings.Contains(ir122, "parse error"))
3977
3978 irFree(h122)
3979
3980 // Test 123: Nested function calls with method chaining pattern
3981 src123 := []byte(`package mypkg
3982
3983 type Builder struct {
3984 n int32
3985 }
3986
3987 func newBuilder() *Builder {
3988 b := Builder{n: 0}
3989 return &b
3990 }
3991
3992 func (b *Builder) add(v int32) *Builder {
3993 b.n = b.n + v
3994 return b
3995 }
3996
3997 func (b *Builder) result() int32 {
3998 return b.n
3999 }
4000
4001 func test() int32 {
4002 return newBuilder().add(10).add(20).add(3).result()
4003 }
4004 `)
4005 h123 := compileToIR(
4006 uintptr(unsafe.Pointer(&src123[0])), int32(len(src123)),
4007 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4008 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4009 )
4010 ir123 := getIR(h123)
4011 fmt.Println("=== IR for method chaining ===")
4012 fmt.Println(ir123)
4013
4014 llvmVerify("method chaining", ir123)
4015 assert("chain has newBuilder", strings.Contains(ir123, "@mypkg.newBuilder"))
4016 assert("chain no parse error", !strings.Contains(ir123, "parse error"))
4017
4018 irFree(h123)
4019
4020 // Test 124: Local slice lookup with bounds check
4021 src124 := []byte(`package mypkg
4022
4023 func opName(i int32) string {
4024 names := []string{"add", "sub", "mul", "div", "mod"}
4025 if i >= 0 && i < int32(len(names)) {
4026 return names[i]
4027 }
4028 return "?"
4029 }
4030
4031 func test() int32 {
4032 s := opName(2)
4033 return int32(len(s))
4034 }
4035 `)
4036 h124 := compileToIR(
4037 uintptr(unsafe.Pointer(&src124[0])), int32(len(src124)),
4038 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4039 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4040 )
4041 ir124 := getIR(h124)
4042 fmt.Println("=== IR for local slice lookup ===")
4043 fmt.Println(ir124)
4044
4045 llvmVerify("local slice lookup", ir124)
4046 assert("local slice no parse error", !strings.Contains(ir124, "parse error"))
4047
4048 irFree(h124)
4049
4050 // Test 125: Multiple `:=` with same name in sibling if-blocks (scoping)
4051 src125 := []byte(`package mypkg
4052
4053 func classify(n int32) int32 {
4054 if n > 100 {
4055 r := n - 100
4056 return r
4057 }
4058 if n > 50 {
4059 r := n - 50
4060 return r * 2
4061 }
4062 if n > 0 {
4063 r := n
4064 return r * 3
4065 }
4066 return 0
4067 }
4068
4069 func test() int32 {
4070 return classify(120) + classify(75)
4071 }
4072 `)
4073 h125 := compileToIR(
4074 uintptr(unsafe.Pointer(&src125[0])), int32(len(src125)),
4075 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4076 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4077 )
4078 ir125 := getIR(h125)
4079 fmt.Println("=== IR for variable shadowing ===")
4080 fmt.Println(ir125)
4081
4082 llvmVerify("variable shadowing", ir125)
4083 assert("shadowing no parse error", !strings.Contains(ir125, "parse error"))
4084
4085 irFree(h125)
4086
4087 // Test 126: Multiple interface implementations with method dispatch
4088 src126 := []byte(`package mypkg
4089
4090 type Formatter interface {
4091 format() string
4092 }
4093
4094 type IntFmt struct{ val int32 }
4095 func (f IntFmt) format() string {
4096 if f.val > 0 {
4097 return "positive"
4098 }
4099 return "non-positive"
4100 }
4101
4102 type StrFmt struct{ val string }
4103 func (f StrFmt) format() string {
4104 return f.val
4105 }
4106
4107 type NilFmt struct{}
4108 func (f NilFmt) format() string {
4109 return "nil"
4110 }
4111
4112 func formatLen(f Formatter) int32 {
4113 s := f.format()
4114 return int32(len(s))
4115 }
4116
4117 func test() int32 {
4118 a := formatLen(IntFmt{val: 5})
4119 b := formatLen(StrFmt{val: "hello"})
4120 c := formatLen(NilFmt{})
4121 return a + b + c
4122 }
4123 `)
4124 h126 := compileToIR(
4125 uintptr(unsafe.Pointer(&src126[0])), int32(len(src126)),
4126 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4127 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4128 )
4129 ir126 := getIR(h126)
4130 fmt.Println("=== IR for multi-impl dispatch ===")
4131 fmt.Println(ir126)
4132
4133 llvmVerify("multi-impl dispatch", ir126)
4134 assert("multi-impl has typeid", strings.Contains(ir126, "typeid"))
4135 assert("multi-impl no parse error", !strings.Contains(ir126, "parse error"))
4136
4137 irFree(h126)
4138
4139 // Test 127: Nested composite literal (struct containing struct containing slice)
4140 src127 := []byte(`package mypkg
4141
4142 type Pos struct {
4143 line int32
4144 col int32
4145 }
4146
4147 type Token struct {
4148 pos Pos
4149 kind int32
4150 text string
4151 }
4152
4153 func tokenLen(t Token) int32 {
4154 return int32(len(t.text)) + t.pos.line
4155 }
4156
4157 func test() int32 {
4158 t := Token{
4159 pos: Pos{line: 1, col: 5},
4160 kind: 42,
4161 text: "hello",
4162 }
4163 return tokenLen(t)
4164 }
4165 `)
4166 h127 := compileToIR(
4167 uintptr(unsafe.Pointer(&src127[0])), int32(len(src127)),
4168 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4169 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4170 )
4171 ir127 := getIR(h127)
4172 fmt.Println("=== IR for nested struct literal ===")
4173 fmt.Println(ir127)
4174
4175 llvmVerify("nested struct literal", ir127)
4176 assert("nested struct lit has gep", strings.Contains(ir127, "getelementptr"))
4177 assert("nested struct lit no parse error", !strings.Contains(ir127, "parse error"))
4178
4179 irFree(h127)
4180
4181 // Test 128: Recursive function with multiple base cases
4182 src128 := []byte(`package mypkg
4183
4184 func fib(n int32) int32 {
4185 if n <= 0 {
4186 return 0
4187 }
4188 if n == 1 {
4189 return 1
4190 }
4191 return fib(n-1) + fib(n-2)
4192 }
4193
4194 func test() int32 {
4195 return fib(7)
4196 }
4197 `)
4198 h128 := compileToIR(
4199 uintptr(unsafe.Pointer(&src128[0])), int32(len(src128)),
4200 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4201 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4202 )
4203 ir128 := getIR(h128)
4204 fmt.Println("=== IR for fibonacci ===")
4205 fmt.Println(ir128)
4206
4207 llvmVerify("fibonacci", ir128)
4208 assert("fib has recursive call", strings.Contains(ir128, "@mypkg.fib"))
4209 assert("fib no parse error", !strings.Contains(ir128, "parse error"))
4210
4211 irFree(h128)
4212
4213 // Test 129: Slice of structs with append and field access in loop
4214 src129 := []byte(`package mypkg
4215
4216 type Entry struct {
4217 key string
4218 value int32
4219 }
4220
4221 func totalValue(entries []Entry) int32 {
4222 total := int32(0)
4223 for _, e := range entries {
4224 total = total + e.value
4225 }
4226 return total
4227 }
4228
4229 func test() int32 {
4230 entries := []Entry{
4231 Entry{key: "a", value: 10},
4232 Entry{key: "b", value: 20},
4233 Entry{key: "c", value: 30},
4234 }
4235 return totalValue(entries)
4236 }
4237 `)
4238 h129 := compileToIR(
4239 uintptr(unsafe.Pointer(&src129[0])), int32(len(src129)),
4240 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4241 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4242 )
4243 ir129 := getIR(h129)
4244 fmt.Println("=== IR for struct slice ===")
4245 fmt.Println(ir129)
4246
4247 llvmVerify("struct slice", ir129)
4248 assert("struct slice no parse error", !strings.Contains(ir129, "parse error"))
4249
4250 irFree(h129)
4251
4252 // Test 130: Type switch with mixed types (pattern from ir_emit.mx dispatch)
4253 src130 := []byte(`package mypkg
4254
4255 type Expr interface {
4256 eval() int32
4257 }
4258
4259 type Const struct{ val int32 }
4260 func (c Const) eval() int32 { return c.val }
4261
4262 type Add struct{ x Expr; y Expr }
4263 func (a Add) eval() int32 { return a.x.eval() + a.y.eval() }
4264
4265 type Neg struct{ x Expr }
4266 func (n Neg) eval() int32 { return 0 - n.x.eval() }
4267
4268 func describe(e Expr) int32 {
4269 switch v := e.(type) {
4270 case Const:
4271 return v.val
4272 case Add:
4273 return v.eval()
4274 case Neg:
4275 return v.eval()
4276 }
4277 return 0
4278 }
4279
4280 func test() int32 {
4281 c1 := Const{val: 5}
4282 c2 := Const{val: 3}
4283 sum := Add{x: c1, y: c2}
4284 neg := Neg{x: c1}
4285 return describe(sum) + describe(neg)
4286 }
4287 `)
4288 h130 := compileToIR(
4289 uintptr(unsafe.Pointer(&src130[0])), int32(len(src130)),
4290 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4291 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4292 )
4293 ir130 := getIR(h130)
4294 fmt.Println("=== IR for expr eval dispatch ===")
4295 fmt.Println(ir130)
4296
4297 llvmVerify("expr eval dispatch", ir130)
4298 assert("expr eval has typeid", strings.Contains(ir130, "typeid"))
4299 assert("expr eval no parse error", !strings.Contains(ir130, "parse error"))
4300
4301 irFree(h130)
4302
4303 // Test 131: Cross-package function call
4304 regPkg("mathutil", "mathutil")
4305 regFn("mathutil", "Double", "int32->int32")
4306 regFn("mathutil", "Add", "int32,int32->int32")
4307
4308 src131 := []byte(`package mypkg
4309
4310 import "mathutil"
4311
4312 func compute(x int32) int32 {
4313 return mathutil.Add(mathutil.Double(x), 10)
4314 }
4315 `)
4316 name131 := []byte("mypkg")
4317 h131 := compileToIR(
4318 uintptr(unsafe.Pointer(&src131[0])), int32(len(src131)),
4319 uintptr(unsafe.Pointer(&name131[0])), int32(len(name131)),
4320 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4321 )
4322 ir131 := getIR(h131)
4323 fmt.Println("=== IR for cross-package call ===")
4324 fmt.Println(ir131)
4325
4326 llvmVerify("cross-package call", ir131)
4327 assert("cross-pkg has declare @mathutil.Double", strings.Contains(ir131, "declare") && strings.Contains(ir131, "@mathutil.Double"))
4328 assert("cross-pkg has declare @mathutil.Add", strings.Contains(ir131, "@mathutil.Add"))
4329 assert("cross-pkg calls Double", strings.Contains(ir131, "call i32 @mathutil.Double("))
4330 assert("cross-pkg calls Add", strings.Contains(ir131, "call i32 @mathutil.Add("))
4331 assert("cross-pkg no parse error", !strings.Contains(ir131, "parse error"))
4332
4333 irFree(h131)
4334 clearImports()
4335
4336 // Test 132: Cross-package variable access
4337 regPkg("config", "config")
4338 regVar("config", "MaxRetries", "int32")
4339 regFn("config", "GetTimeout", "->int32")
4340
4341 src132 := []byte(`package mypkg
4342
4343 import "config"
4344
4345 func retries() int32 {
4346 return config.MaxRetries
4347 }
4348
4349 func timeout() int32 {
4350 return config.GetTimeout()
4351 }
4352 `)
4353 name132 := []byte("mypkg")
4354 h132 := compileToIR(
4355 uintptr(unsafe.Pointer(&src132[0])), int32(len(src132)),
4356 uintptr(unsafe.Pointer(&name132[0])), int32(len(name132)),
4357 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4358 )
4359 ir132 := getIR(h132)
4360 fmt.Println("=== IR for cross-package variable ===")
4361 fmt.Println(ir132)
4362
4363 llvmVerify("cross-package variable", ir132)
4364 assert("cross-pkg-var has @config.MaxRetries global", strings.Contains(ir132, "@config.MaxRetries"))
4365 assert("cross-pkg-var loads MaxRetries", strings.Contains(ir132, "load i32, ptr @config.MaxRetries"))
4366 assert("cross-pkg-var calls GetTimeout", strings.Contains(ir132, "call i32 @config.GetTimeout("))
4367 assert("cross-pkg-var no parse error", !strings.Contains(ir132, "parse error"))
4368
4369 irFree(h132)
4370 clearImports()
4371
4372 // Test 133: Aliased import
4373 regPkg("long/path/util", "util")
4374 regFn("long/path/util", "Helper", "int32->int32")
4375
4376 src133 := []byte(`package mypkg
4377
4378 import u "long/path/util"
4379
4380 func wrapped(x int32) int32 {
4381 return u.Helper(x)
4382 }
4383 `)
4384 name133 := []byte("mypkg")
4385 h133 := compileToIR(
4386 uintptr(unsafe.Pointer(&src133[0])), int32(len(src133)),
4387 uintptr(unsafe.Pointer(&name133[0])), int32(len(name133)),
4388 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4389 )
4390 ir133 := getIR(h133)
4391 fmt.Println("=== IR for aliased import ===")
4392 fmt.Println(ir133)
4393
4394 llvmVerify("aliased import", ir133)
4395 assert("aliased import calls @long/path/util.Helper", strings.Contains(ir133, `@"long/path/util.Helper"`))
4396 assert("aliased import has declare", strings.Contains(ir133, "declare"))
4397 assert("aliased import no parse error", !strings.Contains(ir133, "parse error"))
4398
4399 irFree(h133)
4400 clearImports()
4401
4402 // Test 134: Cross-package multi-return function
4403 regPkg("parser", "parser")
4404 regFn("parser", "Parse", "[]byte->int32,bool")
4405
4406 src134 := []byte(`package mypkg
4407
4408 import "parser"
4409
4410 func tryParse(data []byte) int32 {
4411 n, ok := parser.Parse(data)
4412 if ok {
4413 return n
4414 }
4415 return -1
4416 }
4417 `)
4418 name134 := []byte("mypkg")
4419 h134 := compileToIR(
4420 uintptr(unsafe.Pointer(&src134[0])), int32(len(src134)),
4421 uintptr(unsafe.Pointer(&name134[0])), int32(len(name134)),
4422 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4423 )
4424 ir134 := getIR(h134)
4425 fmt.Println("=== IR for cross-pkg multi-return ===")
4426 fmt.Println(ir134)
4427
4428 llvmVerify("cross-pkg multi-return", ir134)
4429 assert("cross-pkg multi-ret calls Parse", strings.Contains(ir134, "call {i32, i1} @parser.Parse("))
4430 assert("cross-pkg multi-ret extracts value", strings.Contains(ir134, "extractvalue"))
4431 assert("cross-pkg multi-ret no parse error", !strings.Contains(ir134, "parse error"))
4432
4433 irFree(h134)
4434 clearImports()
4435
4436 // Test 135: Cross-package slice-returning function
4437 regPkg("codec", "codec")
4438 regFn("codec", "Encode", "int32->[]byte")
4439
4440 src135 := []byte(`package mypkg
4441
4442 import "codec"
4443
4444 func encodeVal(v int32) []byte {
4445 return codec.Encode(v)
4446 }
4447 `)
4448 name135 := []byte("mypkg")
4449 h135 := compileToIR(
4450 uintptr(unsafe.Pointer(&src135[0])), int32(len(src135)),
4451 uintptr(unsafe.Pointer(&name135[0])), int32(len(name135)),
4452 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4453 )
4454 ir135 := getIR(h135)
4455 fmt.Println("=== IR for cross-pkg slice return ===")
4456 fmt.Println(ir135)
4457
4458 llvmVerify("cross-pkg slice return", ir135)
4459 assert("cross-pkg slice calls Encode", strings.Contains(ir135, "call {ptr, i64, i64} @codec.Encode("))
4460 assert("cross-pkg slice has declare", strings.Contains(ir135, "declare"))
4461 assert("cross-pkg slice no parse error", !strings.Contains(ir135, "parse error"))
4462
4463 irFree(h135)
4464 clearImports()
4465
4466 // Test 136: Cross-package function as argument to local function
4467 regPkg("strings", "strings")
4468 regFn("strings", "Contains", "string,string->bool")
4469 regFn("strings", "HasPrefix", "string,string->bool")
4470
4471 src136 := []byte(`package mypkg
4472
4473 import "strings"
4474
4475 func check(s string) bool {
4476 if strings.HasPrefix(s, "test") {
4477 return strings.Contains(s, "pass")
4478 }
4479 return false
4480 }
4481 `)
4482 name136 := []byte("mypkg")
4483 h136 := compileToIR(
4484 uintptr(unsafe.Pointer(&src136[0])), int32(len(src136)),
4485 uintptr(unsafe.Pointer(&name136[0])), int32(len(name136)),
4486 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4487 )
4488 ir136 := getIR(h136)
4489 fmt.Println("=== IR for cross-pkg chained calls ===")
4490 fmt.Println(ir136)
4491
4492 llvmVerify("cross-pkg chained calls", ir136)
4493 assert("cross-pkg chain calls HasPrefix", strings.Contains(ir136, "@strings.HasPrefix"))
4494 assert("cross-pkg chain calls Contains", strings.Contains(ir136, "@strings.Contains"))
4495 assert("cross-pkg chain both declared", strings.Count(ir136, "declare") >= 2)
4496 assert("cross-pkg chain no parse error", !strings.Contains(ir136, "parse error"))
4497
4498 irFree(h136)
4499 clearImports()
4500
4501 // Test 137: Cross-package void function (no return value)
4502 regPkg("log", "log")
4503 regFn("log", "Print", "string")
4504
4505 src137 := []byte(`package mypkg
4506
4507 import "log"
4508
4509 func logMsg(msg string) {
4510 log.Print(msg)
4511 }
4512 `)
4513 name137 := []byte("mypkg")
4514 h137 := compileToIR(
4515 uintptr(unsafe.Pointer(&src137[0])), int32(len(src137)),
4516 uintptr(unsafe.Pointer(&name137[0])), int32(len(name137)),
4517 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4518 )
4519 ir137 := getIR(h137)
4520 fmt.Println("=== IR for cross-pkg void call ===")
4521 fmt.Println(ir137)
4522
4523 llvmVerify("cross-pkg void call", ir137)
4524 assert("cross-pkg void calls Print", strings.Contains(ir137, "call void @log.Print("))
4525 assert("cross-pkg void has declare", strings.Contains(ir137, "declare void @log.Print("))
4526 assert("cross-pkg void no parse error", !strings.Contains(ir137, "parse error"))
4527
4528 irFree(h137)
4529 clearImports()
4530
4531 // Test 138: Multiple imports in one file
4532 regPkg("bytes", "bytes")
4533 regFn("bytes", "NewReader", "[]byte->*int32")
4534 regPkg("strconv", "strconv")
4535 regFn("strconv", "Itoa", "int32->string")
4536
4537 src138 := []byte(`package mypkg
4538
4539 import (
4540 "bytes"
4541 "strconv"
4542 )
4543
4544 func format(n int32) []byte {
4545 s := strconv.Itoa(n)
4546 return s
4547 }
4548
4549 func reader(data []byte) *int32 {
4550 return bytes.NewReader(data)
4551 }
4552 `)
4553 name138 := []byte("mypkg")
4554 h138 := compileToIR(
4555 uintptr(unsafe.Pointer(&src138[0])), int32(len(src138)),
4556 uintptr(unsafe.Pointer(&name138[0])), int32(len(name138)),
4557 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4558 )
4559 ir138 := getIR(h138)
4560 fmt.Println("=== IR for multi-import ===")
4561 fmt.Println(ir138)
4562
4563 llvmVerify("multi-import", ir138)
4564 assert("multi-import calls Itoa", strings.Contains(ir138, "@strconv.Itoa"))
4565 assert("multi-import calls NewReader", strings.Contains(ir138, "@bytes.NewReader"))
4566 assert("multi-import no parse error", !strings.Contains(ir138, "parse error"))
4567
4568 irFree(h138)
4569 clearImports()
4570
4571 // Test 139: Named type with methods and switch - pattern from ssa_types.mx
4572 src139 := []byte(`package mypkg
4573
4574 type Op int32
4575
4576 const (
4577 OpAdd Op = iota
4578 OpSub
4579 OpMul
4580 )
4581
4582 func (op Op) String() string {
4583 switch op {
4584 case OpAdd:
4585 return "+"
4586 case OpSub:
4587 return "-"
4588 case OpMul:
4589 return "*"
4590 }
4591 return "?"
4592 }
4593
4594 func describe(op Op) string {
4595 return op.String()
4596 }
4597 `)
4598 name139 := []byte("mypkg")
4599 h139 := compileToIR(
4600 uintptr(unsafe.Pointer(&src139[0])), int32(len(src139)),
4601 uintptr(unsafe.Pointer(&name139[0])), int32(len(name139)),
4602 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4603 )
4604 ir139 := getIR(h139)
4605 fmt.Println("=== IR for named type method ===")
4606 fmt.Println(ir139)
4607
4608 llvmVerify("named type method", ir139)
4609 assert("named-type has Op.String method", strings.Contains(ir139, "@mypkg.Op.String"))
4610 assert("named-type has switch comparisons", strings.Contains(ir139, "icmp eq i32"))
4611 assert("named-type describe calls String", strings.Contains(ir139, "call"))
4612 assert("named-type no parse error", !strings.Contains(ir139, "parse error"))
4613
4614 irFree(h139)
4615
4616 // Test 140: Struct with method returning pointer to self - pattern from SSA builder
4617 src140 := []byte(`package mypkg
4618
4619 type Builder struct {
4620 buf []byte
4621 count int32
4622 }
4623
4624 func (b *Builder) Write(data []byte) *Builder {
4625 b.buf = append(b.buf, data...)
4626 b.count = b.count + 1
4627 return b
4628 }
4629
4630 func (b *Builder) Len() int32 {
4631 return int32(len(b.buf))
4632 }
4633
4634 func chain() int32 {
4635 b := &Builder{buf: []byte{:0:64}}
4636 b.Write([]byte("hello")).Write([]byte(" world"))
4637 return b.Len()
4638 }
4639 `)
4640 name140 := []byte("mypkg")
4641 h140 := compileToIR(
4642 uintptr(unsafe.Pointer(&src140[0])), int32(len(src140)),
4643 uintptr(unsafe.Pointer(&name140[0])), int32(len(name140)),
4644 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4645 )
4646 ir140 := getIR(h140)
4647 fmt.Println("=== IR for struct method chain ===")
4648 fmt.Println(ir140)
4649
4650 llvmVerify("struct method chain", ir140)
4651 assert("method-chain has Write method", strings.Contains(ir140, "@mypkg.Builder.Write"))
4652 assert("method-chain has Len method", strings.Contains(ir140, "@mypkg.Builder.Len"))
4653 assert("method-chain chain calls Write twice", strings.Count(ir140, "call ptr @mypkg.Write") >= 2 || strings.Count(ir140, "call") >= 3)
4654 assert("method-chain no parse error", !strings.Contains(ir140, "parse error"))
4655
4656 irFree(h140)
4657
4658 // Test 141: Cross-package function result used in local map
4659 regPkg("strconv", "strconv")
4660 regFn("strconv", "Itoa", "int32->string")
4661
4662 src141 := []byte(`package mypkg
4663
4664 import "strconv"
4665
4666 func buildTable(n int32) map[int32]string {
4667 m := map[int32]string{}
4668 var i int32
4669 for i = 0; i < n; i++ {
4670 m[i] = strconv.Itoa(i)
4671 }
4672 return m
4673 }
4674 `)
4675 name141 := []byte("mypkg")
4676 h141 := compileToIR(
4677 uintptr(unsafe.Pointer(&src141[0])), int32(len(src141)),
4678 uintptr(unsafe.Pointer(&name141[0])), int32(len(name141)),
4679 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4680 )
4681 ir141 := getIR(h141)
4682 fmt.Println("=== IR for cross-pkg in map ===")
4683 fmt.Println(ir141)
4684
4685 llvmVerify("cross-pkg in map", ir141)
4686 assert("cross-pkg-map calls Itoa", strings.Contains(ir141, "@strconv.Itoa"))
4687 assert("cross-pkg-map has hashmapBinarySet", strings.Contains(ir141, "runtime.hashmapBinarySet"))
4688 assert("cross-pkg-map no parse error", !strings.Contains(ir141, "parse error"))
4689
4690 irFree(h141)
4691 clearImports()
4692
4693 // Test 142: Cross-package function result stored in struct field
4694 regPkg("codec", "codec")
4695 regFn("codec", "Encode", "int32->[]byte")
4696
4697 src142 := []byte(`package mypkg
4698
4699 import "codec"
4700
4701 type Packet struct {
4702 data []byte
4703 seq int32
4704 }
4705
4706 func newPacket(seq int32) Packet {
4707 return Packet{
4708 data: codec.Encode(seq),
4709 seq: seq,
4710 }
4711 }
4712 `)
4713 name142 := []byte("mypkg")
4714 h142 := compileToIR(
4715 uintptr(unsafe.Pointer(&src142[0])), int32(len(src142)),
4716 uintptr(unsafe.Pointer(&name142[0])), int32(len(name142)),
4717 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4718 )
4719 ir142 := getIR(h142)
4720 fmt.Println("=== IR for cross-pkg in struct ===")
4721 fmt.Println(ir142)
4722
4723 llvmVerify("cross-pkg in struct", ir142)
4724 assert("cross-pkg-struct calls Encode", strings.Contains(ir142, "@codec.Encode"))
4725 assert("cross-pkg-struct has struct GEP", strings.Contains(ir142, "getelementptr"))
4726 assert("cross-pkg-struct no parse error", !strings.Contains(ir142, "parse error"))
4727
4728 irFree(h142)
4729 clearImports()
4730
4731 // Test 143: Cross-package function in conditional expression
4732 regPkg("strings", "strings")
4733 regFn("strings", "HasPrefix", "string,string->bool")
4734 regFn("strings", "TrimPrefix", "string,string->string")
4735
4736 src143 := []byte(`package mypkg
4737
4738 import "strings"
4739
4740 func clean(s string) string {
4741 if strings.HasPrefix(s, "//") {
4742 return strings.TrimPrefix(s, "//")
4743 }
4744 return s
4745 }
4746 `)
4747 name143 := []byte("mypkg")
4748 h143 := compileToIR(
4749 uintptr(unsafe.Pointer(&src143[0])), int32(len(src143)),
4750 uintptr(unsafe.Pointer(&name143[0])), int32(len(name143)),
4751 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4752 )
4753 ir143 := getIR(h143)
4754 fmt.Println("=== IR for cross-pkg conditional ===")
4755 fmt.Println(ir143)
4756
4757 llvmVerify("cross-pkg conditional", ir143)
4758 assert("cross-pkg-cond calls HasPrefix", strings.Contains(ir143, "@strings.HasPrefix"))
4759 assert("cross-pkg-cond calls TrimPrefix", strings.Contains(ir143, "@strings.TrimPrefix"))
4760 assert("cross-pkg-cond has branch", strings.Contains(ir143, "br i1"))
4761 assert("cross-pkg-cond no parse error", !strings.Contains(ir143, "parse error"))
4762
4763 irFree(h143)
4764 clearImports()
4765
4766 // Test 144: Cross-package variable write (store to external global)
4767 regPkg("state", "state")
4768 regVar("state", "Counter", "int32")
4769 regVar("state", "Name", "string")
4770
4771 src144 := []byte(`package mypkg
4772
4773 import "state"
4774
4775 func increment() {
4776 state.Counter = state.Counter + 1
4777 }
4778
4779 func setName(s string) {
4780 state.Name = s
4781 }
4782 `)
4783 name144 := []byte("mypkg")
4784 h144 := compileToIR(
4785 uintptr(unsafe.Pointer(&src144[0])), int32(len(src144)),
4786 uintptr(unsafe.Pointer(&name144[0])), int32(len(name144)),
4787 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4788 )
4789 ir144 := getIR(h144)
4790 fmt.Println("=== IR for cross-pkg variable write ===")
4791 fmt.Println(ir144)
4792
4793 llvmVerify("cross-pkg variable write", ir144)
4794 assert("cross-pkg-write loads Counter", strings.Contains(ir144, "load i32, ptr @state.Counter"))
4795 assert("cross-pkg-write stores Counter", strings.Contains(ir144, "store i32") && strings.Contains(ir144, "@state.Counter"))
4796 assert("cross-pkg-write stores Name", strings.Contains(ir144, "store {ptr, i64, i64}") && strings.Contains(ir144, "@state.Name"))
4797 assert("cross-pkg-write has external globals", strings.Contains(ir144, "external global"))
4798 assert("cross-pkg-write no parse error", !strings.Contains(ir144, "parse error"))
4799
4800 irFree(h144)
4801 clearImports()
4802
4803 // Test 145: String escape pattern from ir_emit.mx (string indexing, bit shift, hex table)
4804 src145 := []byte(`package mypkg
4805
4806 func escape(s string) []byte {
4807 var buf []byte
4808 for i := 0; i < len(s); i++ {
4809 c := s[i]
4810 if c >= 32 && c < 127 {
4811 buf = append(buf, c)
4812 } else {
4813 buf = append(buf, '\\')
4814 buf = append(buf, "0123456789ABCDEF"[c>>4])
4815 buf = append(buf, "0123456789ABCDEF"[c&0xf])
4816 }
4817 }
4818 return buf
4819 }
4820 `)
4821 name145 := []byte("mypkg")
4822 h145 := compileToIR(
4823 uintptr(unsafe.Pointer(&src145[0])), int32(len(src145)),
4824 uintptr(unsafe.Pointer(&name145[0])), int32(len(name145)),
4825 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4826 )
4827 ir145 := getIR(h145)
4828 fmt.Println("=== IR for string escape ===")
4829 fmt.Println(ir145)
4830
4831 llvmVerify("string escape", ir145)
4832 assert("escape has shr (>>4)", strings.Contains(ir145, "lshr") || strings.Contains(ir145, "ashr"))
4833 assert("escape has and (&0xf)", strings.Contains(ir145, "and"))
4834 assert("escape has string index GEP", strings.Contains(ir145, "getelementptr"))
4835 assert("escape no parse error", !strings.Contains(ir145, "parse error"))
4836
4837 irFree(h145)
4838
4839 // Test 146: String builder pattern from ir_emit.mx (append bytes, return string)
4840 src146 := []byte(`package mypkg
4841
4842 func build(parts []string) string {
4843 var buf []byte
4844 for i := 0; i < len(parts); i++ {
4845 if i > 0 {
4846 buf = append(buf, ',')
4847 }
4848 buf = append(buf, parts[i]...)
4849 }
4850 return string(buf)
4851 }
4852 `)
4853 name146 := []byte("mypkg")
4854 h146 := compileToIR(
4855 uintptr(unsafe.Pointer(&src146[0])), int32(len(src146)),
4856 uintptr(unsafe.Pointer(&name146[0])), int32(len(name146)),
4857 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4858 )
4859 ir146 := getIR(h146)
4860 fmt.Println("=== IR for string builder ===")
4861 fmt.Println(ir146)
4862
4863 llvmVerify("string builder", ir146)
4864 assert("builder has sliceAppend", strings.Contains(ir146, "sliceAppend"))
4865 assert("builder has loop", strings.Contains(ir146, "br i1"))
4866 assert("builder no parse error", !strings.Contains(ir146, "parse error"))
4867
4868 irFree(h146)
4869
4870 // Test 147: Multiple return with cross-package call in one return value
4871 regPkg("conv", "conv")
4872 regFn("conv", "Parse", "string->int32,bool")
4873
4874 src147 := []byte(`package mypkg
4875
4876 import "conv"
4877
4878 func tryGet(s string) (int32, string) {
4879 n, ok := conv.Parse(s)
4880 if !ok {
4881 return 0, "error"
4882 }
4883 return n, "ok"
4884 }
4885 `)
4886 name147 := []byte("mypkg")
4887 h147 := compileToIR(
4888 uintptr(unsafe.Pointer(&src147[0])), int32(len(src147)),
4889 uintptr(unsafe.Pointer(&name147[0])), int32(len(name147)),
4890 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4891 )
4892 ir147 := getIR(h147)
4893 fmt.Println("=== IR for multi-ret cross-pkg ===")
4894 fmt.Println(ir147)
4895
4896 llvmVerify("multi-ret cross-pkg", ir147)
4897 assert("multi-ret calls Parse", strings.Contains(ir147, "@conv.Parse"))
4898 assert("multi-ret extracts bool", strings.Contains(ir147, "extractvalue"))
4899 assert("multi-ret returns tuple", strings.Contains(ir147, "ret {i32, {ptr, i64, i64}}"))
4900 assert("multi-ret no parse error", !strings.Contains(ir147, "parse error"))
4901
4902 irFree(h147)
4903 clearImports()
4904
4905 // Test 148: Realistic emitter pattern - struct with map fields, methods, string building
4906 src148 := []byte(`package mypkg
4907
4908 type Emitter struct {
4909 buf []byte
4910 names map[string]int32
4911 next int32
4912 }
4913
4914 func newEmitter() *Emitter {
4915 return &Emitter{
4916 buf: []byte{:0:1024},
4917 names: map[string]int32{},
4918 }
4919 }
4920
4921 func (e *Emitter) w(s string) {
4922 e.buf = append(e.buf, s...)
4923 }
4924
4925 func (e *Emitter) nextName() string {
4926 e.next = e.next + 1
4927 return "t"
4928 }
4929
4930 func (e *Emitter) lookup(name string) int32 {
4931 if n, ok := e.names[name]; ok {
4932 return n
4933 }
4934 n := e.next
4935 e.next = e.next + 1
4936 e.names[name] = n
4937 return n
4938 }
4939
4940 func (e *Emitter) emit() string {
4941 e.w("define void @main() {\n")
4942 e.w("entry:\n")
4943 e.w(" ret void\n")
4944 e.w("}\n")
4945 return string(e.buf)
4946 }
4947
4948 func run() string {
4949 e := newEmitter()
4950 e.lookup("x")
4951 e.lookup("y")
4952 return e.emit()
4953 }
4954 `)
4955 name148 := []byte("mypkg")
4956 h148 := compileToIR(
4957 uintptr(unsafe.Pointer(&src148[0])), int32(len(src148)),
4958 uintptr(unsafe.Pointer(&name148[0])), int32(len(name148)),
4959 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4960 )
4961 ir148 := getIR(h148)
4962 fmt.Println("=== IR for emitter pattern ===")
4963 fmt.Println(ir148)
4964
4965 llvmVerify("emitter pattern", ir148)
4966 assert("emitter has Emitter.w method", strings.Contains(ir148, "@mypkg.Emitter.w"))
4967 assert("emitter has Emitter.lookup method", strings.Contains(ir148, "@mypkg.Emitter.lookup"))
4968 assert("emitter has Emitter.emit method", strings.Contains(ir148, "@mypkg.Emitter.emit"))
4969 assert("emitter has map operations", strings.Contains(ir148, "hashmap"))
4970 assert("emitter has newEmitter", strings.Contains(ir148, "@mypkg.newEmitter"))
4971 assert("emitter no parse error", !strings.Contains(ir148, "parse error"))
4972
4973 irFree(h148)
4974
4975 // Test 149: Interface dispatch with method set - pattern from SSA instruction emit
4976 src149 := []byte(`package mypkg
4977
4978 type Instruction interface {
4979 String() string
4980 }
4981
4982 type Add struct {
4983 left int32
4984 right int32
4985 }
4986
4987 type Ret struct {
4988 val int32
4989 }
4990
4991 func (a *Add) String() string {
4992 return "add"
4993 }
4994
4995 func (r *Ret) String() string {
4996 return "ret"
4997 }
4998
4999 func emit(instr Instruction) string {
5000 return instr.String()
5001 }
5002
5003 func test() string {
5004 a := &Add{left: 1, right: 2}
5005 r := &Ret{val: 42}
5006 s1 := emit(a)
5007 s2 := emit(r)
5008 return s1 | s2
5009 }
5010 `)
5011 name149 := []byte("mypkg")
5012 h149 := compileToIR(
5013 uintptr(unsafe.Pointer(&src149[0])), int32(len(src149)),
5014 uintptr(unsafe.Pointer(&name149[0])), int32(len(name149)),
5015 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5016 )
5017 ir149 := getIR(h149)
5018 fmt.Println("=== IR for interface dispatch ===")
5019 fmt.Println(ir149)
5020
5021 llvmVerify("interface dispatch", ir149)
5022 assert("iface-dispatch has Add.String", strings.Contains(ir149, "Add.String"))
5023 assert("iface-dispatch has Ret.String", strings.Contains(ir149, "Ret.String"))
5024 assert("iface-dispatch has typeid", strings.Contains(ir149, "typeid"))
5025 assert("iface-dispatch has emit function", strings.Contains(ir149, "@mypkg.emit"))
5026 assert("iface-dispatch no parse error", !strings.Contains(ir149, "parse error"))
5027
5028 irFree(h149)
5029
5030 // Test 150: Switch on type with fallthrough to handler - mirrors emitInstr dispatch
5031 src150 := []byte(`package mypkg
5032
5033 type Node interface {
5034 nodeTag()
5035 }
5036
5037 type Lit struct {
5038 val int32
5039 }
5040
5041 type Bin struct {
5042 op int32
5043 left Node
5044 right Node
5045 }
5046
5047 func (l *Lit) nodeTag() {}
5048 func (b *Bin) nodeTag() {}
5049
5050 func eval(n Node) int32 {
5051 switch v := n.(type) {
5052 case *Lit:
5053 return v.val
5054 case *Bin:
5055 l := eval(v.left)
5056 r := eval(v.right)
5057 if v.op == 0 {
5058 return l + r
5059 }
5060 return l - r
5061 }
5062 return 0
5063 }
5064 `)
5065 name150 := []byte("mypkg")
5066 h150 := compileToIR(
5067 uintptr(unsafe.Pointer(&src150[0])), int32(len(src150)),
5068 uintptr(unsafe.Pointer(&name150[0])), int32(len(name150)),
5069 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5070 )
5071 ir150 := getIR(h150)
5072 fmt.Println("=== IR for type switch dispatch ===")
5073 fmt.Println(ir150)
5074
5075 llvmVerify("type switch dispatch", ir150)
5076 assert("type-switch has eval function", strings.Contains(ir150, "@mypkg.eval"))
5077 assert("type-switch has typeid comparisons", strings.Contains(ir150, "icmp eq ptr"))
5078 assert("type-switch recursive call", strings.Count(ir150, "call i32 @mypkg.eval") >= 2)
5079 assert("type-switch no parse error", !strings.Contains(ir150, "parse error"))
5080
5081 irFree(h150)
5082
5083 // Test 151: Verify pointer type switch gets DISTINCT typeids (regression test)
5084 src151 := []byte(`package mypkg
5085
5086 type Animal interface {
5087 Sound() string
5088 }
5089
5090 type Dog struct {
5091 name string
5092 }
5093
5094 type Cat struct {
5095 name string
5096 }
5097
5098 type Bird struct {
5099 name string
5100 }
5101
5102 func (d *Dog) Sound() string { return "woof" }
5103 func (c *Cat) Sound() string { return "meow" }
5104 func (b *Bird) Sound() string { return "tweet" }
5105
5106 func classify(a Animal) int32 {
5107 switch a.(type) {
5108 case *Dog:
5109 return 1
5110 case *Cat:
5111 return 2
5112 case *Bird:
5113 return 3
5114 }
5115 return 0
5116 }
5117 `)
5118 name151 := []byte("mypkg")
5119 h151 := compileToIR(
5120 uintptr(unsafe.Pointer(&src151[0])), int32(len(src151)),
5121 uintptr(unsafe.Pointer(&name151[0])), int32(len(name151)),
5122 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5123 )
5124 ir151 := getIR(h151)
5125 fmt.Println("=== IR for pointer typeids ===")
5126 fmt.Println(ir151)
5127
5128 llvmVerify("pointer typeids", ir151)
5129 assert("ptr-typeid has distinct Dog typeid", strings.Contains(ir151, "typeid.ptr.Dog"))
5130 assert("ptr-typeid has distinct Cat typeid", strings.Contains(ir151, "typeid.ptr.Cat"))
5131 assert("ptr-typeid has distinct Bird typeid", strings.Contains(ir151, "typeid.ptr.Bird"))
5132 assert("ptr-typeid Dog != Cat != Bird", strings.Count(ir151, "typeid.ptr.Dog") >= 2 && strings.Count(ir151, "typeid.ptr.Cat") >= 2 && strings.Count(ir151, "typeid.ptr.Bird") >= 2)
5133 assert("ptr-typeid no parse error", !strings.Contains(ir151, "parse error"))
5134
5135 irFree(h151)
5136
5137 // Test 152: Real bootstrap code - irItoa (modulo, division, byte conversion)
5138 src152 := []byte(`package mypkg
5139
5140 func itoa(n int32) string {
5141 if n == 0 {
5142 return "0"
5143 }
5144 buf := []byte{:0:20}
5145 for n > 0 {
5146 buf = append(buf, byte('0' + n % 10))
5147 n = n / 10
5148 }
5149 return string(buf)
5150 }
5151 `)
5152 name152 := []byte("mypkg")
5153 h152 := compileToIR(
5154 uintptr(unsafe.Pointer(&src152[0])), int32(len(src152)),
5155 uintptr(unsafe.Pointer(&name152[0])), int32(len(name152)),
5156 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5157 )
5158 ir152 := getIR(h152)
5159 fmt.Println("=== IR for irItoa ===")
5160 fmt.Println(ir152)
5161
5162 llvmVerify("irItoa", ir152)
5163 assert("itoa has srem (modulo)", strings.Contains(ir152, "srem"))
5164 assert("itoa has sdiv (division)", strings.Contains(ir152, "sdiv"))
5165 assert("itoa no parse error", !strings.Contains(ir152, "parse error"))
5166
5167 irFree(h152)
5168
5169 // Test 153: Real bootstrap code - irEscapeString (string indexing, bit ops)
5170 src153 := []byte(`package mypkg
5171
5172 func escapeStr(s string) string {
5173 var buf []byte
5174 for i := 0; i < len(s); i++ {
5175 c := s[i]
5176 if c >= 32 && c < 127 && c != '\\' && c != '"' {
5177 buf = append(buf, c)
5178 } else {
5179 buf = append(buf, '\\')
5180 buf = append(buf, "0123456789ABCDEF"[c>>4])
5181 buf = append(buf, "0123456789ABCDEF"[c&0xf])
5182 }
5183 }
5184 return string(buf)
5185 }
5186 `)
5187 name153 := []byte("mypkg")
5188 h153 := compileToIR(
5189 uintptr(unsafe.Pointer(&src153[0])), int32(len(src153)),
5190 uintptr(unsafe.Pointer(&name153[0])), int32(len(name153)),
5191 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5192 )
5193 ir153 := getIR(h153)
5194 fmt.Println("=== IR for escapeStr ===")
5195 fmt.Println(ir153)
5196
5197 llvmVerify("escapeStr", ir153)
5198 assert("escape has lshr (>>4)", strings.Contains(ir153, "lshr") || strings.Contains(ir153, "ashr"))
5199 assert("escape has and (&0xf)", strings.Contains(ir153, "and i"))
5200 assert("escape no parse error", !strings.Contains(ir153, "parse error"))
5201
5202 irFree(h153)
5203
5204 // Test 154: Full IRWriter pattern (restored after bisection shows individual parts pass)
5205 src154 := []byte(`package mypkg
5206
5207 type IRWriter struct {
5208 buf []byte
5209 lines []string
5210 seen map[string]int32
5211 }
5212
5213 func (w *IRWriter) emit(s string) {
5214 w.buf = append(w.buf, s...)
5215 }
5216
5217 func (w *IRWriter) newline() {
5218 w.lines = append(w.lines, string(w.buf))
5219 w.buf = w.buf[:0]
5220 }
5221
5222 func (w *IRWriter) writeLine(s string) {
5223 w.emit(s)
5224 w.newline()
5225 }
5226
5227 func itoa154(n int32) string {
5228 if n == 0 {
5229 return "0"
5230 }
5231 neg := n < 0
5232 if neg {
5233 n = -n
5234 }
5235 buf := []byte{:0:20}
5236 for n > 0 {
5237 buf = append(buf, byte('0' + n % 10))
5238 n = n / 10
5239 }
5240 if neg {
5241 buf = append(buf, '-')
5242 }
5243 i := 0
5244 j := int32(len(buf)) - 1
5245 for i < j {
5246 buf[i], buf[j] = buf[j], buf[i]
5247 i = i + 1
5248 j = j - 1
5249 }
5250 return string(buf)
5251 }
5252
5253 func (w *IRWriter) writeInt(n int32) {
5254 w.emit(itoa154(n))
5255 }
5256
5257 func (w *IRWriter) emitDecl(name string, idx int32) {
5258 w.emit("define ")
5259 w.emit(name)
5260 w.emit("(")
5261 w.emit(itoa154(idx))
5262 w.emit(")")
5263 w.newline()
5264 }
5265
5266 func (w *IRWriter) track(key string) {
5267 w.seen[key] = w.seen[key] + 1
5268 }
5269
5270 func (w *IRWriter) count() int32 {
5271 return int32(len(w.lines))
5272 }
5273 `)
5274 name154 := []byte("mypkg")
5275 h154 := compileToIR(
5276 uintptr(unsafe.Pointer(&src154[0])), int32(len(src154)),
5277 uintptr(unsafe.Pointer(&name154[0])), int32(len(name154)),
5278 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5279 )
5280 ir154 := getIR(h154)
5281 fmt.Println("=== IR for Writer+itoa ===")
5282 fmt.Println(ir154)
5283
5284 llvmVerify("IRWriter", ir154)
5285 assert("irwriter has emit method", strings.Contains(ir154, "@mypkg.IRWriter.emit"))
5286 assert("irwriter has writeInt method", strings.Contains(ir154, "@mypkg.IRWriter.writeInt"))
5287 assert("irwriter has emitDecl method", strings.Contains(ir154, "@mypkg.IRWriter.emitDecl"))
5288 assert("irwriter has track method", strings.Contains(ir154, "@mypkg.IRWriter.track"))
5289 assert("itoa154 has srem", strings.Contains(ir154, "srem"))
5290 assert("irwriter no parse error", !strings.Contains(ir154, "parse error"))
5291
5292 irFree(h154)
5293
5294 // Test 155: Real bootstrap pattern - SSA instruction switch dispatch
5295 src155 := []byte(`package mypkg
5296
5297 type Value interface {
5298 valTag()
5299 }
5300
5301 type Const struct {
5302 val int32
5303 }
5304
5305 type Param struct {
5306 name string
5307 idx int32
5308 }
5309
5310 type BinOp struct {
5311 op int32
5312 x Value
5313 y Value
5314 }
5315
5316 func (c *Const) valTag() {}
5317 func (p *Param) valTag() {}
5318 func (b *BinOp) valTag() {}
5319
5320 func operand(v Value) string {
5321 switch v := v.(type) {
5322 case *Const:
5323 return itoa155(v.val)
5324 case *Param:
5325 return "%" | v.name
5326 case *BinOp:
5327 x := operand(v.x)
5328 y := operand(v.y)
5329 switch v.op {
5330 case 0:
5331 return x | " + " | y
5332 case 1:
5333 return x | " - " | y
5334 case 2:
5335 return x | " * " | y
5336 }
5337 return x | " ? " | y
5338 }
5339 return "undef"
5340 }
5341
5342 func itoa155(n int32) string {
5343 if n == 0 {
5344 return "0"
5345 }
5346 buf := []byte{:0:10}
5347 for n > 0 {
5348 buf = append(buf, byte('0' + n % 10))
5349 n = n / 10
5350 }
5351 return string(buf)
5352 }
5353 `)
5354 name155 := []byte("mypkg")
5355 h155 := compileToIR(
5356 uintptr(unsafe.Pointer(&src155[0])), int32(len(src155)),
5357 uintptr(unsafe.Pointer(&name155[0])), int32(len(name155)),
5358 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5359 )
5360 ir155 := getIR(h155)
5361 fmt.Println("=== IR for SSA operand dispatch ===")
5362 fmt.Println(ir155)
5363
5364 llvmVerify("SSA operand dispatch", ir155)
5365 assert("ssa-dispatch has operand", strings.Contains(ir155, "@mypkg.operand"))
5366 assert("ssa-dispatch has typeid Const", strings.Contains(ir155, "typeid.ptr.Const"))
5367 assert("ssa-dispatch has typeid Param", strings.Contains(ir155, "typeid.ptr.Param"))
5368 assert("ssa-dispatch has typeid BinOp", strings.Contains(ir155, "typeid.ptr.BinOp"))
5369 assert("ssa-dispatch recursive operand calls", strings.Count(ir155, "call {ptr, i64, i64} @mypkg.operand") >= 2)
5370 assert("ssa-dispatch has nested switch", strings.Contains(ir155, "icmp eq i32"))
5371 assert("ssa-dispatch no parse error", !strings.Contains(ir155, "parse error"))
5372
5373 irFree(h155)
5374
5375 // Test 156: Nil interface comparison
5376 src156 := []byte(`package mypkg
5377
5378 type Stringer interface {
5379 String() string
5380 }
5381
5382 func isNil(s Stringer) bool {
5383 return s == nil
5384 }
5385
5386 func isNotNil(s Stringer) bool {
5387 return s != nil
5388 }
5389 `)
5390 name156 := []byte("mypkg")
5391 h156 := compileToIR(
5392 uintptr(unsafe.Pointer(&src156[0])), int32(len(src156)),
5393 uintptr(unsafe.Pointer(&name156[0])), int32(len(name156)),
5394 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5395 )
5396 ir156 := getIR(h156)
5397 fmt.Println("=== IR for nil interface ===")
5398 fmt.Println(ir156)
5399
5400 llvmVerify("nil interface", ir156)
5401 assert("nil-iface has isNil", strings.Contains(ir156, "@mypkg.isNil"))
5402 assert("nil-iface has isNotNil", strings.Contains(ir156, "@mypkg.isNotNil"))
5403 assert("nil-iface no parse error", !strings.Contains(ir156, "parse error"))
5404
5405 irFree(h156)
5406
5407 // Test 157: Nil slice comparison
5408 src157 := []byte(`package mypkg
5409
5410 func sliceIsNil(s []int32) bool {
5411 return s == nil
5412 }
5413
5414 func sliceNotNil(s []int32) bool {
5415 return s != nil
5416 }
5417 `)
5418 name157 := []byte("mypkg")
5419 h157 := compileToIR(
5420 uintptr(unsafe.Pointer(&src157[0])), int32(len(src157)),
5421 uintptr(unsafe.Pointer(&name157[0])), int32(len(name157)),
5422 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5423 )
5424 ir157 := getIR(h157)
5425 fmt.Println("=== IR for nil slice ===")
5426 fmt.Println(ir157)
5427
5428 llvmVerify("nil slice", ir157)
5429 assert("nil-slice has sliceIsNil", strings.Contains(ir157, "@mypkg.sliceIsNil"))
5430 assert("nil-slice has sliceNotNil", strings.Contains(ir157, "@mypkg.sliceNotNil"))
5431 assert("nil-slice no parse error", !strings.Contains(ir157, "parse error"))
5432
5433 irFree(h157)
5434
5435 // Test 158: Nested method calls with string concat (emitter pattern)
5436 src158 := []byte(`package mypkg
5437
5438 type Buf struct {
5439 data []byte
5440 }
5441
5442 func (b *Buf) write(s string) {
5443 b.data = append(b.data, s...)
5444 }
5445
5446 func (b *Buf) writeQuoted(s string) {
5447 b.write("\"")
5448 b.write(s)
5449 b.write("\"")
5450 }
5451
5452 func (b *Buf) writeKV(k string, v string) {
5453 b.write(k)
5454 b.write(": ")
5455 b.writeQuoted(v)
5456 b.write("\n")
5457 }
5458
5459 func (b *Buf) result() string {
5460 return string(b.data)
5461 }
5462 `)
5463 name158 := []byte("mypkg")
5464 h158 := compileToIR(
5465 uintptr(unsafe.Pointer(&src158[0])), int32(len(src158)),
5466 uintptr(unsafe.Pointer(&name158[0])), int32(len(name158)),
5467 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5468 )
5469 ir158 := getIR(h158)
5470 fmt.Println("=== IR for Buf methods ===")
5471 fmt.Println(ir158)
5472
5473 llvmVerify("Buf methods", ir158)
5474 assert("buf has write", strings.Contains(ir158, "@mypkg.Buf.write"))
5475 assert("buf has writeQuoted", strings.Contains(ir158, "@mypkg.Buf.writeQuoted"))
5476 assert("buf has writeKV", strings.Contains(ir158, "@mypkg.Buf.writeKV"))
5477 assert("buf has result", strings.Contains(ir158, "@mypkg.Buf.result"))
5478 assert("buf no parse error", !strings.Contains(ir158, "parse error"))
5479
5480 irFree(h158)
5481
5482 // Test 159: Struct with interface field + factory function + method dispatch
5483 src159 := []byte(`package mypkg
5484
5485 type Node interface {
5486 nodeTag()
5487 }
5488
5489 type Literal struct {
5490 val int32
5491 }
5492
5493 type Binary struct {
5494 op int32
5495 left Node
5496 right Node
5497 }
5498
5499 func (l *Literal) nodeTag() {}
5500 func (b *Binary) nodeTag() {}
5501
5502 func newLit(v int32) *Literal {
5503 return &Literal{val: v}
5504 }
5505
5506 func newBin(op int32, l Node, r Node) *Binary {
5507 return &Binary{op: op, left: l, right: r}
5508 }
5509
5510 func depth(n Node) int32 {
5511 switch n := n.(type) {
5512 case *Literal:
5513 return 1
5514 case *Binary:
5515 ld := depth(n.left)
5516 rd := depth(n.right)
5517 if ld > rd {
5518 return ld + 1
5519 }
5520 return rd + 1
5521 }
5522 return 0
5523 }
5524 `)
5525 name159 := []byte("mypkg")
5526 h159 := compileToIR(
5527 uintptr(unsafe.Pointer(&src159[0])), int32(len(src159)),
5528 uintptr(unsafe.Pointer(&name159[0])), int32(len(name159)),
5529 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5530 )
5531 ir159 := getIR(h159)
5532 fmt.Println("=== IR for Node tree ===")
5533 fmt.Println(ir159)
5534
5535 llvmVerify("Node tree", ir159)
5536 assert("node has newLit", strings.Contains(ir159, "@mypkg.newLit"))
5537 assert("node has newBin", strings.Contains(ir159, "@mypkg.newBin"))
5538 assert("node has depth", strings.Contains(ir159, "@mypkg.depth"))
5539 assert("node depth recursive", strings.Count(ir159, "call i32 @mypkg.depth") >= 2)
5540 assert("node distinct typeids", strings.Contains(ir159, "typeid.ptr.Literal") && strings.Contains(ir159, "typeid.ptr.Binary"))
5541 assert("node no parse error", !strings.Contains(ir159, "parse error"))
5542
5543 irFree(h159)
5544
5545 // Test 160: Large struct with many fields (emitter-scale struct)
5546 src160 := []byte(`package mypkg
5547
5548 type Emitter struct {
5549 pkg string
5550 triple string
5551 buf []byte
5552 decls []string
5553 globals map[string]string
5554 types map[string]int32
5555 tempCount int32
5556 indent int32
5557 }
5558
5559 func newEmitter(pkg string, triple string) *Emitter {
5560 return &Emitter{
5561 pkg: pkg,
5562 triple: triple,
5563 globals: map[string]string{},
5564 types: map[string]int32{},
5565 }
5566 }
5567
5568 func (e *Emitter) nextTemp() string {
5569 e.tempCount = e.tempCount + 1
5570 return "%t" | itoa160(e.tempCount)
5571 }
5572
5573 func (e *Emitter) addDecl(s string) {
5574 e.decls = append(e.decls, s)
5575 }
5576
5577 func (e *Emitter) setGlobal(name string, val string) {
5578 e.globals[name] = val
5579 }
5580
5581 func (e *Emitter) hasType(name string) bool {
5582 _, ok := e.types[name]
5583 return ok
5584 }
5585
5586 func itoa160(n int32) string {
5587 if n == 0 {
5588 return "0"
5589 }
5590 buf := []byte{:0:10}
5591 for n > 0 {
5592 buf = append(buf, byte('0' + n % 10))
5593 n = n / 10
5594 }
5595 return string(buf)
5596 }
5597 `)
5598 name160 := []byte("mypkg")
5599 h160 := compileToIR(
5600 uintptr(unsafe.Pointer(&src160[0])), int32(len(src160)),
5601 uintptr(unsafe.Pointer(&name160[0])), int32(len(name160)),
5602 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5603 )
5604 ir160 := getIR(h160)
5605 fmt.Println("=== IR for Emitter struct ===")
5606 fmt.Println(ir160)
5607
5608 llvmVerify("Emitter struct", ir160)
5609 assert("emitter has newEmitter", strings.Contains(ir160, "@mypkg.newEmitter"))
5610 assert("emitter has nextTemp", strings.Contains(ir160, "@mypkg.Emitter.nextTemp"))
5611 assert("emitter has addDecl", strings.Contains(ir160, "@mypkg.Emitter.addDecl"))
5612 assert("emitter has setGlobal", strings.Contains(ir160, "@mypkg.Emitter.setGlobal"))
5613 assert("emitter has hasType", strings.Contains(ir160, "@mypkg.Emitter.hasType"))
5614 assert("emitter no parse error", !strings.Contains(ir160, "parse error"))
5615
5616 irFree(h160)
5617
5618 // Test 161: Closure-like pattern (function variable in struct)
5619 src161 := []byte(`package mypkg
5620
5621 type Handler struct {
5622 name string
5623 fn func(string) string
5624 }
5625
5626 func identity(s string) string {
5627 return s
5628 }
5629
5630 func upper(s string) string {
5631 return s
5632 }
5633
5634 func newHandler(name string) *Handler {
5635 return &Handler{name: name, fn: identity}
5636 }
5637
5638 func (h *Handler) setFn(f func(string) string) {
5639 h.fn = f
5640 }
5641
5642 func (h *Handler) run(input string) string {
5643 return h.fn(input)
5644 }
5645 `)
5646 name161 := []byte("mypkg")
5647 h161 := compileToIR(
5648 uintptr(unsafe.Pointer(&src161[0])), int32(len(src161)),
5649 uintptr(unsafe.Pointer(&name161[0])), int32(len(name161)),
5650 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5651 )
5652 ir161 := getIR(h161)
5653 fmt.Println("=== IR for func var ===")
5654 fmt.Println(ir161)
5655
5656 llvmVerify("func var", ir161)
5657 assert("funcvar has newHandler", strings.Contains(ir161, "@mypkg.newHandler"))
5658 assert("funcvar has run method", strings.Contains(ir161, "@mypkg.Handler.run"))
5659 assert("funcvar no parse error", !strings.Contains(ir161, "parse error"))
5660
5661 irFree(h161)
5662
5663 // Test 162: Map iteration (range over map)
5664 src162 := []byte(`package mypkg
5665
5666 func sumMap(m map[string]int32) int32 {
5667 total := int32(0)
5668 for _, v := range m {
5669 total = total + v
5670 }
5671 return total
5672 }
5673
5674 func keys(m map[string]int32) []string {
5675 var result []string
5676 for k := range m {
5677 result = append(result, k)
5678 }
5679 return result
5680 }
5681 `)
5682 name162 := []byte("mypkg")
5683 h162 := compileToIR(
5684 uintptr(unsafe.Pointer(&src162[0])), int32(len(src162)),
5685 uintptr(unsafe.Pointer(&name162[0])), int32(len(name162)),
5686 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5687 )
5688 ir162 := getIR(h162)
5689 fmt.Println("=== IR for map iteration ===")
5690 fmt.Println(ir162)
5691
5692 llvmVerify("map iteration", ir162)
5693 assert("mapiter has sumMap", strings.Contains(ir162, "@mypkg.sumMap"))
5694 assert("mapiter has keys", strings.Contains(ir162, "@mypkg.keys"))
5695 assert("mapiter uses hashmapNext", strings.Contains(ir162, "hashmapNext") || strings.Contains(ir162, "hashmapBinaryNext"))
5696 assert("mapiter no parse error", !strings.Contains(ir162, "parse error"))
5697
5698 irFree(h162)
5699
5700 // Test 163: Multi-level type switch with method calls (ir_emit pattern)
5701 src163 := []byte(`package mypkg
5702
5703 type Type interface {
5704 typeTag()
5705 }
5706
5707 type BasicType struct {
5708 kind int32
5709 }
5710
5711 type SliceType struct {
5712 elem Type
5713 }
5714
5715 type PointerType struct {
5716 elem Type
5717 }
5718
5719 type StructType struct {
5720 fields []Type
5721 }
5722
5723 func (b *BasicType) typeTag() {}
5724 func (s *SliceType) typeTag() {}
5725 func (p *PointerType) typeTag() {}
5726 func (s *StructType) typeTag() {}
5727
5728 func typeSize(t Type) int32 {
5729 switch t := t.(type) {
5730 case *BasicType:
5731 switch t.kind {
5732 case 0:
5733 return 1
5734 case 1:
5735 return 4
5736 case 2:
5737 return 8
5738 }
5739 return 0
5740 case *SliceType:
5741 return 24
5742 case *PointerType:
5743 return 8
5744 case *StructType:
5745 total := int32(0)
5746 for _, f := range t.fields {
5747 total = total + typeSize(f)
5748 }
5749 return total
5750 }
5751 return 0
5752 }
5753
5754 func typeName(t Type) string {
5755 switch t := t.(type) {
5756 case *BasicType:
5757 switch t.kind {
5758 case 0:
5759 return "i8"
5760 case 1:
5761 return "i32"
5762 case 2:
5763 return "i64"
5764 }
5765 return "void"
5766 case *SliceType:
5767 return "[]" | typeName(t.elem)
5768 case *PointerType:
5769 return "*" | typeName(t.elem)
5770 case *StructType:
5771 return "struct"
5772 }
5773 return "unknown"
5774 }
5775 `)
5776 name163 := []byte("mypkg")
5777 h163 := compileToIR(
5778 uintptr(unsafe.Pointer(&src163[0])), int32(len(src163)),
5779 uintptr(unsafe.Pointer(&name163[0])), int32(len(name163)),
5780 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5781 )
5782 ir163 := getIR(h163)
5783 fmt.Println("=== IR for type system ===")
5784 fmt.Println(ir163)
5785
5786 llvmVerify("type system", ir163)
5787 assert("typesys has typeSize", strings.Contains(ir163, "@mypkg.typeSize"))
5788 assert("typesys has typeName", strings.Contains(ir163, "@mypkg.typeName"))
5789 assert("typesys has 4 distinct typeids",
5790 strings.Contains(ir163, "typeid.ptr.BasicType") &&
5791 strings.Contains(ir163, "typeid.ptr.SliceType") &&
5792 strings.Contains(ir163, "typeid.ptr.PointerType") &&
5793 strings.Contains(ir163, "typeid.ptr.StructType"))
5794 assert("typesys typeSize recursive", strings.Count(ir163, "call i32 @mypkg.typeSize") >= 1)
5795 assert("typesys typeName recursive", strings.Count(ir163, "call {ptr, i64, i64} @mypkg.typeName") >= 1)
5796 assert("typesys no parse error", !strings.Contains(ir163, "parse error"))
5797
5798 irFree(h163)
5799
5800 // Test 164: String building with map lookup (ir_emit core pattern)
5801 src164 := []byte(`package mypkg
5802
5803 type IRGen struct {
5804 regs map[string]string
5805 buf []byte
5806 n int32
5807 }
5808
5809 func (g *IRGen) fresh(prefix string) string {
5810 g.n = g.n + 1
5811 return prefix | itoa164(g.n)
5812 }
5813
5814 func (g *IRGen) emit(s string) {
5815 g.buf = append(g.buf, s...)
5816 }
5817
5818 func (g *IRGen) emitLine(parts []string) {
5819 for i := 0; i < len(parts); i++ {
5820 g.emit(parts[i])
5821 }
5822 g.emit("\n")
5823 }
5824
5825 func (g *IRGen) setReg(name string, val string) {
5826 g.regs[name] = val
5827 }
5828
5829 func (g *IRGen) getReg(name string) string {
5830 v, ok := g.regs[name]
5831 if !ok {
5832 return "undef"
5833 }
5834 return v
5835 }
5836
5837 func itoa164(n int32) string {
5838 if n == 0 {
5839 return "0"
5840 }
5841 buf := []byte{:0:10}
5842 for n > 0 {
5843 buf = append(buf, byte('0' + n % 10))
5844 n = n / 10
5845 }
5846 i := 0
5847 j := int32(len(buf)) - 1
5848 for i < j {
5849 buf[i], buf[j] = buf[j], buf[i]
5850 i = i + 1
5851 j = j - 1
5852 }
5853 return string(buf)
5854 }
5855 `)
5856 name164 := []byte("mypkg")
5857 h164 := compileToIR(
5858 uintptr(unsafe.Pointer(&src164[0])), int32(len(src164)),
5859 uintptr(unsafe.Pointer(&name164[0])), int32(len(name164)),
5860 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5861 )
5862 ir164 := getIR(h164)
5863 fmt.Println("=== IR for IRGen ===")
5864 fmt.Println(ir164)
5865
5866 llvmVerify("IRGen", ir164)
5867 assert("irgen has fresh", strings.Contains(ir164, "@mypkg.IRGen.fresh"))
5868 assert("irgen has emit", strings.Contains(ir164, "@mypkg.IRGen.emit"))
5869 assert("irgen has emitLine", strings.Contains(ir164, "@mypkg.IRGen.emitLine"))
5870 assert("irgen has getReg with ok check", strings.Contains(ir164, "@mypkg.IRGen.getReg"))
5871 assert("irgen no parse error", !strings.Contains(ir164, "parse error"))
5872
5873 irFree(h164)
5874
5875 // Test 165: Cross-package calls inside type switch (compile pattern)
5876 clearImports()
5877 regPkg("ext/types", "types")
5878 regFn("ext/types", "BasicSize", "int32->int32")
5879 regFn("ext/types", "SliceSize", "->int32")
5880 src165 := []byte(`package mypkg
5881
5882 import "ext/types"
5883
5884 type Typ interface {
5885 tag()
5886 }
5887
5888 type Basic165 struct {
5889 kind int32
5890 }
5891
5892 type Slice165 struct {
5893 elem Typ
5894 }
5895
5896 func (b *Basic165) tag() {}
5897 func (s *Slice165) tag() {}
5898
5899 func size(t Typ) int32 {
5900 switch t := t.(type) {
5901 case *Basic165:
5902 return types.BasicSize(t.kind)
5903 case *Slice165:
5904 return types.SliceSize()
5905 }
5906 return 0
5907 }
5908 `)
5909 name165 := []byte("mypkg")
5910 h165 := compileToIR(
5911 uintptr(unsafe.Pointer(&src165[0])), int32(len(src165)),
5912 uintptr(unsafe.Pointer(&name165[0])), int32(len(name165)),
5913 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5914 )
5915 ir165 := getIR(h165)
5916 fmt.Println("=== IR for cross-pkg type switch ===")
5917 fmt.Println(ir165)
5918
5919 llvmVerify("cross-pkg type switch", ir165)
5920 assert("xpkg-tswitch has size func", strings.Contains(ir165, "@mypkg.size"))
5921 assert("xpkg-tswitch calls BasicSize", strings.Contains(ir165, "BasicSize"))
5922 assert("xpkg-tswitch calls SliceSize", strings.Contains(ir165, "SliceSize"))
5923 assert("xpkg-tswitch no parse error", !strings.Contains(ir165, "parse error"))
5924
5925 irFree(h165)
5926 clearImports()
5927
5928 // Test 166: Multiple return values from method
5929 src166 := []byte(`package mypkg
5930
5931 type Scanner struct {
5932 src []byte
5933 pos int32
5934 }
5935
5936 func (s *Scanner) peek() (byte, bool) {
5937 if int32(s.pos) >= int32(len(s.src)) {
5938 return 0, false
5939 }
5940 return s.src[s.pos], true
5941 }
5942
5943 func (s *Scanner) advance() byte {
5944 ch, ok := s.peek()
5945 if !ok {
5946 return 0
5947 }
5948 s.pos = s.pos + 1
5949 return ch
5950 }
5951
5952 func (s *Scanner) skipWhile(ch byte) {
5953 for {
5954 c, ok := s.peek()
5955 if !ok || c != ch {
5956 return
5957 }
5958 s.pos = s.pos + 1
5959 }
5960 }
5961 `)
5962 name166 := []byte("mypkg")
5963 h166 := compileToIR(
5964 uintptr(unsafe.Pointer(&src166[0])), int32(len(src166)),
5965 uintptr(unsafe.Pointer(&name166[0])), int32(len(name166)),
5966 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5967 )
5968 ir166 := getIR(h166)
5969 fmt.Println("=== IR for Scanner ===")
5970 fmt.Println(ir166)
5971
5972 llvmVerify("Scanner", ir166)
5973 assert("scanner has peek", strings.Contains(ir166, "@mypkg.Scanner.peek"))
5974 assert("scanner has advance", strings.Contains(ir166, "@mypkg.Scanner.advance"))
5975 assert("scanner has skipWhile", strings.Contains(ir166, "@mypkg.Scanner.skipWhile"))
5976 assert("scanner peek returns tuple", strings.Contains(ir166, "{i8, i1}"))
5977 assert("scanner advance calls peek", strings.Contains(ir166, "call {i8, i1} @mypkg.Scanner.peek"))
5978 assert("scanner no parse error", !strings.Contains(ir166, "parse error"))
5979
5980 irFree(h166)
5981
5982 // Test 167: Repeated short method calls (w() pattern from ir_emit)
5983 src167 := []byte(`package mypkg
5984
5985 type Builder struct {
5986 buf []byte
5987 }
5988
5989 func (b *Builder) w(s string) {
5990 b.buf = append(b.buf, s...)
5991 }
5992
5993 func (b *Builder) emitAdd(dst string, ty string, lhs string, rhs string) {
5994 b.w(" ")
5995 b.w(dst)
5996 b.w(" = add ")
5997 b.w(ty)
5998 b.w(" ")
5999 b.w(lhs)
6000 b.w(", ")
6001 b.w(rhs)
6002 b.w("\n")
6003 }
6004
6005 func (b *Builder) emitStore(ty string, val string, ptr string) {
6006 b.w(" store ")
6007 b.w(ty)
6008 b.w(" ")
6009 b.w(val)
6010 b.w(", ptr ")
6011 b.w(ptr)
6012 b.w("\n")
6013 }
6014
6015 func (b *Builder) emitRet(ty string, val string) {
6016 b.w(" ret ")
6017 b.w(ty)
6018 b.w(" ")
6019 b.w(val)
6020 b.w("\n")
6021 }
6022
6023 func (b *Builder) result() string {
6024 return string(b.buf)
6025 }
6026 `)
6027 name167 := []byte("mypkg")
6028 h167 := compileToIR(
6029 uintptr(unsafe.Pointer(&src167[0])), int32(len(src167)),
6030 uintptr(unsafe.Pointer(&name167[0])), int32(len(name167)),
6031 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6032 )
6033 ir167 := getIR(h167)
6034 fmt.Println("=== IR for Builder w() ===")
6035 fmt.Println(ir167)
6036
6037 llvmVerify("Builder w()", ir167)
6038 assert("builder has w method", strings.Contains(ir167, "@mypkg.Builder.w"))
6039 assert("builder has emitAdd", strings.Contains(ir167, "@mypkg.Builder.emitAdd"))
6040 assert("builder has emitStore", strings.Contains(ir167, "@mypkg.Builder.emitStore"))
6041 assert("builder has emitRet", strings.Contains(ir167, "@mypkg.Builder.emitRet"))
6042 assert("builder emitAdd calls w many times", strings.Count(ir167, "call void @mypkg.Builder.w") >= 10)
6043 assert("builder no parse error", !strings.Contains(ir167, "parse error"))
6044
6045 irFree(h167)
6046
6047 // Test 168: Nested struct access + interface field (SSA node pattern)
6048 src168 := []byte(`package mypkg
6049
6050 type Pos struct {
6051 line int32
6052 col int32
6053 }
6054
6055 type Token struct {
6056 kind int32
6057 pos Pos
6058 text string
6059 }
6060
6061 type ASTNode interface {
6062 astTag()
6063 }
6064
6065 type ExprStmt struct {
6066 pos Pos
6067 expr ASTNode
6068 }
6069
6070 type ReturnStmt struct {
6071 pos Pos
6072 result ASTNode
6073 }
6074
6075 func (e *ExprStmt) astTag() {}
6076 func (r *ReturnStmt) astTag() {}
6077
6078 func stmtLine(n ASTNode) int32 {
6079 switch n := n.(type) {
6080 case *ExprStmt:
6081 return n.pos.line
6082 case *ReturnStmt:
6083 return n.pos.line
6084 }
6085 return 0
6086 }
6087
6088 func stmtCol(n ASTNode) int32 {
6089 switch n := n.(type) {
6090 case *ExprStmt:
6091 return n.pos.col
6092 case *ReturnStmt:
6093 return n.pos.col
6094 }
6095 return 0
6096 }
6097 `)
6098 name168 := []byte("mypkg")
6099 h168 := compileToIR(
6100 uintptr(unsafe.Pointer(&src168[0])), int32(len(src168)),
6101 uintptr(unsafe.Pointer(&name168[0])), int32(len(name168)),
6102 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6103 )
6104 ir168 := getIR(h168)
6105 fmt.Println("=== IR for AST nodes ===")
6106 fmt.Println(ir168)
6107
6108 llvmVerify("AST nodes", ir168)
6109 assert("ast has stmtLine", strings.Contains(ir168, "@mypkg.stmtLine"))
6110 assert("ast has stmtCol", strings.Contains(ir168, "@mypkg.stmtCol"))
6111 assert("ast nested field getelementptr", strings.Count(ir168, "getelementptr") >= 4)
6112 assert("ast no parse error", !strings.Contains(ir168, "parse error"))
6113
6114 irFree(h168)
6115
6116 // Test 169: Struct embedding - basic field access through embedded struct
6117 src169 := []byte(`package mypkg
6118
6119 type base struct {
6120 name string
6121 val int32
6122 }
6123
6124 func (b *base) Name() string { return b.name }
6125 func (b *base) Val() int32 { return b.val }
6126
6127 type Derived struct {
6128 base
6129 extra int32
6130 }
6131
6132 func newDerived(name string, val int32, extra int32) *Derived {
6133 return &Derived{base: base{name: name, val: val}, extra: extra}
6134 }
6135
6136 func getName(d *Derived) string {
6137 return d.Name()
6138 }
6139
6140 func getVal(d *Derived) int32 {
6141 return d.Val()
6142 }
6143 `)
6144 name169 := []byte("mypkg")
6145 h169 := compileToIR(
6146 uintptr(unsafe.Pointer(&src169[0])), int32(len(src169)),
6147 uintptr(unsafe.Pointer(&name169[0])), int32(len(name169)),
6148 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6149 )
6150 ir169 := getIR(h169)
6151 fmt.Println("=== IR for struct embedding ===")
6152 fmt.Println(ir169)
6153
6154 if ir169 == "" || strings.Contains(ir169, "parse error") {
6155 fmt.Println("NOTE: struct embedding may not be supported yet")
6156 assert("embedding produces IR", ir169 != "")
6157 } else {
6158 llvmVerify("struct embedding", ir169)
6159 assert("embed has newDerived", strings.Contains(ir169, "@mypkg.newDerived"))
6160 assert("embed has getName", strings.Contains(ir169, "@mypkg.getName"))
6161 assert("embed has base.Name method", strings.Contains(ir169, "@mypkg.base.Name"))
6162 assert("embed no parse error", !strings.Contains(ir169, "parse error"))
6163 }
6164
6165 irFree(h169)
6166
6167 // Test 170: Embedded field direct access (d.name -> base.name)
6168 src170 := []byte(`package mypkg
6169
6170 type inner struct {
6171 x int32
6172 y int32
6173 }
6174
6175 type Outer struct {
6176 inner
6177 z int32
6178 }
6179
6180 func sumOuter(o *Outer) int32 {
6181 return o.x + o.y + o.z
6182 }
6183
6184 func setX(o *Outer, v int32) {
6185 o.x = v
6186 }
6187 `)
6188 name170 := []byte("mypkg")
6189 h170 := compileToIR(
6190 uintptr(unsafe.Pointer(&src170[0])), int32(len(src170)),
6191 uintptr(unsafe.Pointer(&name170[0])), int32(len(name170)),
6192 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6193 )
6194 ir170 := getIR(h170)
6195 fmt.Println("=== IR for embedded field access ===")
6196 fmt.Println(ir170)
6197
6198 llvmVerify("embedded field access", ir170)
6199 assert("embed-field has sumOuter", strings.Contains(ir170, "@mypkg.sumOuter"))
6200 assert("embed-field has setX", strings.Contains(ir170, "@mypkg.setX"))
6201 assert("embed-field accesses nested field (two GEPs)", strings.Count(ir170, "getelementptr") >= 4)
6202 assert("embed-field no parse error", !strings.Contains(ir170, "parse error"))
6203
6204 irFree(h170)
6205
6206 // Test 171: Interface satisfaction via embedded methods (tc_object pattern)
6207 src171 := []byte(`package mypkg
6208
6209 type Named interface {
6210 GetName() string
6211 GetKind() int32
6212 }
6213
6214 type baseObj struct {
6215 name string
6216 kind int32
6217 }
6218
6219 func (b *baseObj) GetName() string { return b.name }
6220 func (b *baseObj) GetKind() int32 { return b.kind }
6221
6222 type TypeObj struct {
6223 baseObj
6224 extra bool
6225 }
6226
6227 type FuncObj struct {
6228 baseObj
6229 sig string
6230 }
6231
6232 func classify(n Named) string {
6233 switch n.(type) {
6234 case *TypeObj:
6235 return "type"
6236 case *FuncObj:
6237 return "func"
6238 }
6239 return "unknown"
6240 }
6241
6242 func describe(n Named) string {
6243 return n.GetName() | ":" | itoa171(n.GetKind())
6244 }
6245
6246 func itoa171(n int32) string {
6247 if n == 0 {
6248 return "0"
6249 }
6250 buf := []byte{:0:10}
6251 for n > 0 {
6252 buf = append(buf, byte('0' + n % 10))
6253 n = n / 10
6254 }
6255 return string(buf)
6256 }
6257 `)
6258 name171 := []byte("mypkg")
6259 h171 := compileToIR(
6260 uintptr(unsafe.Pointer(&src171[0])), int32(len(src171)),
6261 uintptr(unsafe.Pointer(&name171[0])), int32(len(name171)),
6262 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6263 )
6264 ir171 := getIR(h171)
6265 fmt.Println("=== IR for interface via embedding ===")
6266 fmt.Println(ir171)
6267
6268 llvmVerify("interface via embedding", ir171)
6269 assert("iface-embed has classify", strings.Contains(ir171, "@mypkg.classify"))
6270 assert("iface-embed has describe", strings.Contains(ir171, "@mypkg.describe"))
6271 assert("iface-embed has TypeObj typeid", strings.Contains(ir171, "typeid.ptr.TypeObj"))
6272 assert("iface-embed has FuncObj typeid", strings.Contains(ir171, "typeid.ptr.FuncObj"))
6273 assert("iface-embed no parse error", !strings.Contains(ir171, "parse error"))
6274
6275 irFree(h171)
6276
6277 // Test 172: Map with interface values + nil return (tc_scope pattern)
6278 src172 := []byte(`package mypkg
6279
6280 type Entry interface {
6281 Key() string
6282 }
6283
6284 type StrEntry struct {
6285 key string
6286 val string
6287 }
6288
6289 func (e *StrEntry) Key() string { return e.key }
6290
6291 type Table struct {
6292 elems map[string]Entry
6293 }
6294
6295 func newTable() *Table {
6296 return &Table{elems: map[string]Entry{}}
6297 }
6298
6299 func (t *Table) get(name string) Entry {
6300 return t.elems[name]
6301 }
6302
6303 func (t *Table) set(e Entry) {
6304 t.elems[e.Key()] = e
6305 }
6306
6307 func (t *Table) has(name string) bool {
6308 _, ok := t.elems[name]
6309 return ok
6310 }
6311 `)
6312 name172 := []byte("mypkg")
6313 h172 := compileToIR(
6314 uintptr(unsafe.Pointer(&src172[0])), int32(len(src172)),
6315 uintptr(unsafe.Pointer(&name172[0])), int32(len(name172)),
6316 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6317 )
6318 ir172 := getIR(h172)
6319 fmt.Println("=== IR for map[string]interface ===")
6320 fmt.Println(ir172)
6321
6322 llvmVerify("map[string]interface", ir172)
6323 assert("map-iface has newTable", strings.Contains(ir172, "@mypkg.newTable"))
6324 assert("map-iface has get method", strings.Contains(ir172, "@mypkg.Table.get"))
6325 assert("map-iface has set method", strings.Contains(ir172, "@mypkg.Table.set"))
6326 assert("map-iface has has method", strings.Contains(ir172, "@mypkg.Table.has"))
6327 assert("map-iface no parse error", !strings.Contains(ir172, "parse error"))
6328
6329 irFree(h172)
6330
6331 // Test 173: Pointer chain walking with nil check (tc_scope.LookupParent pattern)
6332 src173 := []byte(`package mypkg
6333
6334 type Chain struct {
6335 parent *Chain
6336 name string
6337 val int32
6338 }
6339
6340 func walk(c *Chain, target string) int32 {
6341 for s := c; s != nil; s = s.parent {
6342 if s.name == target {
6343 return s.val
6344 }
6345 }
6346 return -1
6347 }
6348
6349 func depth(c *Chain) int32 {
6350 n := int32(0)
6351 for s := c; s != nil; s = s.parent {
6352 n = n + 1
6353 }
6354 return n
6355 }
6356 `)
6357 name173 := []byte("mypkg")
6358 h173 := compileToIR(
6359 uintptr(unsafe.Pointer(&src173[0])), int32(len(src173)),
6360 uintptr(unsafe.Pointer(&name173[0])), int32(len(name173)),
6361 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6362 )
6363 ir173 := getIR(h173)
6364 fmt.Println("=== IR for pointer chain walk ===")
6365 fmt.Println(ir173)
6366
6367 llvmVerify("pointer chain walk", ir173)
6368 assert("chain has walk", strings.Contains(ir173, "@mypkg.walk"))
6369 assert("chain has depth", strings.Contains(ir173, "@mypkg.depth"))
6370 assert("chain has null comparison", strings.Contains(ir173, "icmp") && strings.Contains(ir173, "null"))
6371 assert("chain no parse error", !strings.Contains(ir173, "parse error"))
6372
6373 irFree(h173)
6374
6375 // Test 174: Full tc_scope pattern with concrete types
6376 src174 := []byte(`package mypkg
6377
6378 type Object interface {
6379 Name() string
6380 }
6381
6382 type SimpleObj struct {
6383 name string
6384 }
6385
6386 func (o *SimpleObj) Name() string { return o.name }
6387
6388 type Scope struct {
6389 parent *Scope
6390 elems map[string]Object
6391 }
6392
6393 func NewScope(parent *Scope) *Scope {
6394 return &Scope{parent: parent, elems: map[string]Object{}}
6395 }
6396
6397 func (s *Scope) Parent() *Scope { return s.parent }
6398 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
6399
6400 func (s *Scope) Lookup(name string) Object {
6401 return s.elems[name]
6402 }
6403
6404 func (s *Scope) LookupParent(name string) (*Scope, Object) {
6405 for sc := s; sc != nil; sc = sc.parent {
6406 if obj, ok := sc.elems[name]; ok {
6407 return sc, obj
6408 }
6409 }
6410 return nil, nil
6411 }
6412
6413 func (s *Scope) Insert(obj Object) Object {
6414 name := obj.Name()
6415 if alt, ok := s.elems[name]; ok {
6416 return alt
6417 }
6418 s.elems[name] = obj
6419 return nil
6420 }
6421
6422 func (s *Scope) Names() []string {
6423 names := []string{:0:len(s.elems)}
6424 for n := range s.elems {
6425 names = append(names, n)
6426 }
6427 return names
6428 }
6429 `)
6430 name174 := []byte("mypkg")
6431 h174 := compileToIR(
6432 uintptr(unsafe.Pointer(&src174[0])), int32(len(src174)),
6433 uintptr(unsafe.Pointer(&name174[0])), int32(len(name174)),
6434 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6435 )
6436 ir174 := getIR(h174)
6437 fmt.Println("=== IR for Scope ===")
6438 fmt.Println(ir174)
6439
6440 if ir174 == "" {
6441 assert("scope produces IR", false)
6442 } else {
6443 llvmVerify("Scope", ir174)
6444 assert("scope has NewScope", strings.Contains(ir174, "@mypkg.NewScope"))
6445 assert("scope has Lookup", strings.Contains(ir174, "@mypkg.Scope.Lookup"))
6446 assert("scope has LookupParent", strings.Contains(ir174, "@mypkg.Scope.LookupParent"))
6447 assert("scope has Insert", strings.Contains(ir174, "@mypkg.Scope.Insert"))
6448 assert("scope has Names", strings.Contains(ir174, "@mypkg.Scope.Names"))
6449 assert("scope Insert calls Name via invoke", strings.Contains(ir174, "call {ptr, i64, i64} @mypkg.SimpleObj.Name"))
6450 assert("scope no parse error", !strings.Contains(ir174, "parse error"))
6451 }
6452
6453 irFree(h174)
6454
6455 // Test 175: tc_object pattern - Object hierarchy with embedding
6456 src175 := []byte(`package mypkg
6457
6458 type Type interface {
6459 typeTag()
6460 }
6461
6462 type BasicType175 struct {
6463 kind int32
6464 }
6465
6466 func (b *BasicType175) typeTag() {}
6467
6468 type Pkg175 struct {
6469 path string
6470 name string
6471 }
6472
6473 type Object interface {
6474 Name() string
6475 ObjType() Type
6476 ObjPkg() *Pkg175
6477 Exported() bool
6478 }
6479
6480 type object175 struct {
6481 pkg *Pkg175
6482 name string
6483 typ Type
6484 }
6485
6486 func (o *object175) Name() string { return o.name }
6487 func (o *object175) ObjType() Type { return o.typ }
6488 func (o *object175) ObjPkg() *Pkg175 { return o.pkg }
6489 func (o *object175) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
6490
6491 type TypeName175 struct {
6492 object175
6493 }
6494
6495 func NewTypeName175(pkg *Pkg175, name string, typ Type) *TypeName175 {
6496 return &TypeName175{object175{pkg: pkg, name: name, typ: typ}}
6497 }
6498
6499 func (o *TypeName175) String() string { return "type " | o.name }
6500
6501 type FuncObj175 struct {
6502 object175
6503 ptrRecv bool
6504 }
6505
6506 func NewFuncObj175(pkg *Pkg175, name string) *FuncObj175 {
6507 return &FuncObj175{object175: object175{pkg: pkg, name: name}}
6508 }
6509
6510 func (o *FuncObj175) HasPtrRecv() bool { return o.ptrRecv }
6511 func (o *FuncObj175) String() string { return "func " | o.name }
6512
6513 func classify175(obj Object) string {
6514 switch obj.(type) {
6515 case *TypeName175:
6516 return "type"
6517 case *FuncObj175:
6518 return "func"
6519 }
6520 return "unknown"
6521 }
6522 `)
6523 name175 := []byte("mypkg")
6524 h175 := compileToIR(
6525 uintptr(unsafe.Pointer(&src175[0])), int32(len(src175)),
6526 uintptr(unsafe.Pointer(&name175[0])), int32(len(name175)),
6527 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6528 )
6529 ir175 := getIR(h175)
6530 fmt.Println("=== IR for tc_object ===")
6531 fmt.Println(ir175)
6532
6533 if ir175 == "" {
6534 assert("tc_object produces IR", false)
6535 } else {
6536 llvmVerify("tc_object", ir175)
6537 assert("obj has NewTypeName175", strings.Contains(ir175, "@mypkg.NewTypeName175"))
6538 assert("obj has NewFuncObj175", strings.Contains(ir175, "@mypkg.NewFuncObj175"))
6539 assert("obj has classify175", strings.Contains(ir175, "@mypkg.classify175"))
6540 assert("obj has Exported method", strings.Contains(ir175, "@mypkg.object175.Exported"))
6541 assert("obj TypeName175 typeid", strings.Contains(ir175, "typeid.ptr.TypeName175"))
6542 assert("obj FuncObj175 typeid", strings.Contains(ir175, "typeid.ptr.FuncObj175"))
6543 assert("obj no parse error", !strings.Contains(ir175, "parse error"))
6544 }
6545
6546 irFree(h175)
6547
6548 // Test 176: Combined Scope + Object pattern (tc_scope + tc_object together)
6549 src176 := []byte(`package mypkg
6550
6551 type Type176 interface {
6552 typeTag()
6553 }
6554
6555 type Object176 interface {
6556 Name() string
6557 }
6558
6559 type obj176 struct {
6560 name string
6561 }
6562
6563 func (o *obj176) Name() string { return o.name }
6564
6565 type VarObj176 struct {
6566 obj176
6567 typ Type176
6568 }
6569
6570 type ConstObj176 struct {
6571 obj176
6572 val int32
6573 }
6574
6575 type Scope176 struct {
6576 parent *Scope176
6577 elems map[string]Object176
6578 }
6579
6580 func NewScope176(parent *Scope176) *Scope176 {
6581 return &Scope176{parent: parent, elems: map[string]Object176{}}
6582 }
6583
6584 func (s *Scope176) Insert(obj Object176) Object176 {
6585 name := obj.Name()
6586 if alt, ok := s.elems[name]; ok {
6587 return alt
6588 }
6589 s.elems[name] = obj
6590 return nil
6591 }
6592
6593 func (s *Scope176) Lookup(name string) Object176 {
6594 return s.elems[name]
6595 }
6596
6597 func (s *Scope176) LookupParent(name string) (*Scope176, Object176) {
6598 for sc := s; sc != nil; sc = sc.parent {
6599 if obj, ok := sc.elems[name]; ok {
6600 return sc, obj
6601 }
6602 }
6603 return nil, nil
6604 }
6605
6606 func (s *Scope176) Len() int32 {
6607 return int32(len(s.elems))
6608 }
6609
6610 func classifyObj176(obj Object176) string {
6611 switch obj.(type) {
6612 case *VarObj176:
6613 return "var"
6614 case *ConstObj176:
6615 return "const"
6616 }
6617 return "unknown"
6618 }
6619 `)
6620 name176 := []byte("mypkg")
6621 h176 := compileToIR(
6622 uintptr(unsafe.Pointer(&src176[0])), int32(len(src176)),
6623 uintptr(unsafe.Pointer(&name176[0])), int32(len(name176)),
6624 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6625 )
6626 ir176 := getIR(h176)
6627 fmt.Println("=== IR for scope+object ===")
6628 fmt.Println(ir176)
6629
6630 if ir176 == "" {
6631 assert("scope+object produces IR", false)
6632 } else {
6633 llvmVerify("scope+object", ir176)
6634 assert("so has NewScope176", strings.Contains(ir176, "@mypkg.NewScope176"))
6635 assert("so has Insert", strings.Contains(ir176, "@mypkg.Scope176.Insert"))
6636 assert("so has LookupParent", strings.Contains(ir176, "@mypkg.Scope176.LookupParent"))
6637 assert("so has classifyObj176", strings.Contains(ir176, "@mypkg.classifyObj176"))
6638 assert("so has hashmapLen", strings.Contains(ir176, "hashmapLen"))
6639 assert("so VarObj176 typeid", strings.Contains(ir176, "typeid.ptr.VarObj176"))
6640 assert("so ConstObj176 typeid", strings.Contains(ir176, "typeid.ptr.ConstObj176"))
6641 assert("so no parse error", !strings.Contains(ir176, "parse error"))
6642 }
6643
6644 irFree(h176)
6645
6646 // Test 177: Scanner pattern (tc_scanner core loop)
6647 src177 := []byte(`package mypkg
6648
6649 type Scanner177 struct {
6650 src []byte
6651 pos int32
6652 line int32
6653 col int32
6654 }
6655
6656 func NewScanner177(src []byte) *Scanner177 {
6657 return &Scanner177{src: src, line: 1, col: 1}
6658 }
6659
6660 func (s *Scanner177) peek() byte {
6661 if s.pos >= int32(len(s.src)) {
6662 return 0
6663 }
6664 return s.src[s.pos]
6665 }
6666
6667 func (s *Scanner177) next() byte {
6668 ch := s.peek()
6669 if ch == 0 {
6670 return 0
6671 }
6672 s.pos = s.pos + 1
6673 if ch == '\n' {
6674 s.line = s.line + 1
6675 s.col = 1
6676 } else {
6677 s.col = s.col + 1
6678 }
6679 return ch
6680 }
6681
6682 func (s *Scanner177) skipSpace() {
6683 for {
6684 ch := s.peek()
6685 if ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' {
6686 return
6687 }
6688 s.next()
6689 }
6690 }
6691
6692 func (s *Scanner177) readIdent() string {
6693 start := s.pos
6694 for {
6695 ch := s.peek()
6696 if (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && ch != '_' {
6697 break
6698 }
6699 s.pos = s.pos + 1
6700 }
6701 return string(s.src[start:s.pos])
6702 }
6703
6704 func (s *Scanner177) atEnd() bool {
6705 return s.pos >= int32(len(s.src))
6706 }
6707 `)
6708 name177 := []byte("mypkg")
6709 h177 := compileToIR(
6710 uintptr(unsafe.Pointer(&src177[0])), int32(len(src177)),
6711 uintptr(unsafe.Pointer(&name177[0])), int32(len(name177)),
6712 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6713 )
6714 ir177 := getIR(h177)
6715 fmt.Println("=== IR for scanner ===")
6716 fmt.Println(ir177)
6717
6718 if ir177 == "" {
6719 assert("scanner produces IR", false)
6720 } else {
6721 llvmVerify("scanner", ir177)
6722 assert("scan has NewScanner177", strings.Contains(ir177, "@mypkg.NewScanner177"))
6723 assert("scan has peek", strings.Contains(ir177, "@mypkg.Scanner177.peek"))
6724 assert("scan has next", strings.Contains(ir177, "@mypkg.Scanner177.next"))
6725 assert("scan has skipSpace", strings.Contains(ir177, "@mypkg.Scanner177.skipSpace"))
6726 assert("scan has readIdent", strings.Contains(ir177, "@mypkg.Scanner177.readIdent"))
6727 assert("scan next calls peek", strings.Contains(ir177, "call i8 @mypkg.Scanner177.peek"))
6728 assert("scan no parse error", !strings.Contains(ir177, "parse error"))
6729 }
6730
6731 irFree(h177)
6732
6733 // Test 178: tc_types core pattern - Type interface hierarchy
6734 src178 := []byte(`package mypkg
6735
6736 type Type interface {
6737 Underlying() Type
6738 String() string
6739 }
6740
6741 type BasicKind int32
6742
6743 const (
6744 Invalid BasicKind = iota
6745 Bool178
6746 Int8Kind
6747 Int32Kind
6748 Int64Kind
6749 StringKind
6750 )
6751
6752 type BasicInfo int32
6753
6754 const (
6755 IsBoolean BasicInfo = 1 << iota
6756 IsInteger
6757 IsUnsigned
6758 IsFloat
6759 IsString178
6760 )
6761
6762 type Basic178 struct {
6763 kind BasicKind
6764 info BasicInfo
6765 name string
6766 }
6767
6768 func (t *Basic178) Kind() BasicKind { return t.kind }
6769 func (t *Basic178) Info() BasicInfo { return t.info }
6770 func (t *Basic178) Name() string { return t.name }
6771 func (t *Basic178) Underlying() Type { return t }
6772 func (t *Basic178) String() string { return t.name }
6773
6774 type Slice178 struct {
6775 elem Type
6776 }
6777
6778 func NewSlice178(elem Type) *Slice178 { return &Slice178{elem: elem} }
6779 func (t *Slice178) Elem() Type { return t.elem }
6780 func (t *Slice178) Underlying() Type { return t }
6781 func (t *Slice178) String() string { return "[]" | t.elem.String() }
6782
6783 type Pointer178 struct {
6784 base Type
6785 }
6786
6787 func NewPointer178(base Type) *Pointer178 { return &Pointer178{base: base} }
6788 func (t *Pointer178) Elem() Type { return t.base }
6789 func (t *Pointer178) Underlying() Type { return t }
6790 func (t *Pointer178) String() string { return "*" | t.base.String() }
6791
6792 type Map178 struct {
6793 key Type
6794 elem Type
6795 }
6796
6797 func NewMap178(key Type, elem Type) *Map178 { return &Map178{key: key, elem: elem} }
6798 func (t *Map178) Key() Type { return t.key }
6799 func (t *Map178) Elem() Type { return t.elem }
6800 func (t *Map178) Underlying() Type { return t }
6801
6802 func isInteger(t Type) bool {
6803 if b, ok := t.(*Basic178); ok {
6804 return b.info & IsInteger != 0
6805 }
6806 return false
6807 }
6808
6809 func elemType(t Type) Type {
6810 switch t := t.(type) {
6811 case *Slice178:
6812 return t.elem
6813 case *Pointer178:
6814 return t.base
6815 case *Map178:
6816 return t.elem
6817 }
6818 return nil
6819 }
6820 `)
6821 name178 := []byte("mypkg")
6822 h178 := compileToIR(
6823 uintptr(unsafe.Pointer(&src178[0])), int32(len(src178)),
6824 uintptr(unsafe.Pointer(&name178[0])), int32(len(name178)),
6825 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6826 )
6827 ir178 := getIR(h178)
6828 fmt.Println("=== IR for type system ===")
6829 fmt.Println(ir178)
6830
6831 if ir178 == "" {
6832 assert("type system produces IR", false)
6833 } else {
6834 llvmVerify("type system", ir178)
6835 assert("ts has Basic178 methods", strings.Contains(ir178, "@mypkg.Basic178.String"))
6836 assert("ts has Slice178.String", strings.Contains(ir178, "@mypkg.Slice178.String"))
6837 assert("ts has Pointer178.String", strings.Contains(ir178, "@mypkg.Pointer178.String"))
6838 assert("ts has isInteger", strings.Contains(ir178, "@mypkg.isInteger"))
6839 assert("ts has elemType", strings.Contains(ir178, "@mypkg.elemType"))
6840 assert("ts bitmask and", strings.Contains(ir178, "and i32"))
6841 assert("ts has Slice178 typeid", strings.Contains(ir178, "typeid.ptr.Slice178"))
6842 assert("ts has Pointer178 typeid", strings.Contains(ir178, "typeid.ptr.Pointer178"))
6843 assert("ts has Map178 typeid", strings.Contains(ir178, "typeid.ptr.Map178"))
6844 assert("ts Slice.String calls elem.String", strings.Contains(ir178, "call {ptr, i64, i64}") || strings.Contains(ir178, "invoke"))
6845 assert("ts no parse error", !strings.Contains(ir178, "parse error"))
6846 }
6847
6848 irFree(h178)
6849
6850 // Test 179: Named type with methods + Underlying (key tc_types pattern)
6851 src179 := []byte(`package mypkg
6852
6853 type Type179 interface {
6854 Underlying() Type179
6855 }
6856
6857 type Named179 struct {
6858 obj *TypeObj179
6859 underlying Type179
6860 methods []*FuncObj179
6861 }
6862
6863 type TypeObj179 struct {
6864 name string
6865 }
6866
6867 type FuncObj179 struct {
6868 name string
6869 }
6870
6871 func NewNamed179(obj *TypeObj179, underlying Type179) *Named179 {
6872 return &Named179{obj: obj, underlying: underlying}
6873 }
6874
6875 func (t *Named179) Obj() *TypeObj179 { return t.obj }
6876 func (t *Named179) Underlying() Type179 { return t.underlying }
6877 func (t *Named179) NumMethods() int32 { return int32(len(t.methods)) }
6878 func (t *Named179) Method(i int32) *FuncObj179 { return t.methods[i] }
6879 func (t *Named179) AddMethod(m *FuncObj179) {
6880 t.methods = append(t.methods, m)
6881 }
6882
6883 func (t *Named179) SetUnderlying(u Type179) {
6884 t.underlying = u
6885 }
6886
6887 type Struct179 struct {
6888 fields []*Field179
6889 }
6890
6891 type Field179 struct {
6892 name string
6893 typ Type179
6894 anon bool
6895 }
6896
6897 func (t *Struct179) Underlying() Type179 { return t }
6898 func (t *Struct179) NumFields() int32 { return int32(len(t.fields)) }
6899 func (t *Struct179) Field(i int32) *Field179 { return t.fields[i] }
6900
6901 func underlyingType(t Type179) Type179 {
6902 if n, ok := t.(*Named179); ok {
6903 return n.underlying
6904 }
6905 return t
6906 }
6907 `)
6908 name179 := []byte("mypkg")
6909 h179 := compileToIR(
6910 uintptr(unsafe.Pointer(&src179[0])), int32(len(src179)),
6911 uintptr(unsafe.Pointer(&name179[0])), int32(len(name179)),
6912 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6913 )
6914 ir179 := getIR(h179)
6915 fmt.Println("=== IR for Named type ===")
6916 fmt.Println(ir179)
6917
6918 if ir179 == "" {
6919 assert("named type produces IR", false)
6920 } else {
6921 llvmVerify("Named type", ir179)
6922 assert("named has NewNamed179", strings.Contains(ir179, "@mypkg.NewNamed179"))
6923 assert("named has AddMethod", strings.Contains(ir179, "@mypkg.Named179.AddMethod"))
6924 assert("named has SetUnderlying", strings.Contains(ir179, "@mypkg.Named179.SetUnderlying"))
6925 assert("named has underlyingType", strings.Contains(ir179, "@mypkg.underlyingType"))
6926 assert("named has Named179 typeid", strings.Contains(ir179, "typeid.ptr.Named179"))
6927 assert("named no parse error", !strings.Contains(ir179, "parse error"))
6928 }
6929
6930 irFree(h179)
6931
6932 // Test 180: Signature/Tuple pattern + nil field access
6933 src180 := []byte(`package mypkg
6934
6935 type Type180 interface {
6936 Underlying() Type180
6937 }
6938
6939 type Var180 struct {
6940 name string
6941 typ Type180
6942 }
6943
6944 type Tuple180 struct {
6945 vars []*Var180
6946 }
6947
6948 func NewTuple180(vars []*Var180) *Tuple180 { return &Tuple180{vars: vars} }
6949 func (t *Tuple180) Len() int32 { return int32(len(t.vars)) }
6950 func (t *Tuple180) At(i int32) *Var180 { return t.vars[i] }
6951
6952 type Signature180 struct {
6953 recv *Var180
6954 params *Tuple180
6955 results *Tuple180
6956 variadic bool
6957 }
6958
6959 func NewSig180(recv *Var180, params *Tuple180, results *Tuple180) *Signature180 {
6960 return &Signature180{recv: recv, params: params, results: results}
6961 }
6962
6963 func (s *Signature180) Recv() *Var180 { return s.recv }
6964 func (s *Signature180) Params() *Tuple180 { return s.params }
6965 func (s *Signature180) Results() *Tuple180 { return s.results }
6966 func (s *Signature180) Variadic() bool { return s.variadic }
6967 func (s *Signature180) Underlying() Type180 { return s }
6968
6969 func numParams(s *Signature180) int32 {
6970 if s.params == nil {
6971 return 0
6972 }
6973 return s.params.Len()
6974 }
6975
6976 func numResults(s *Signature180) int32 {
6977 if s.results == nil {
6978 return 0
6979 }
6980 return s.results.Len()
6981 }
6982
6983 func hasReceiver(s *Signature180) bool {
6984 return s.recv != nil
6985 }
6986
6987 func paramName(s *Signature180, i int32) string {
6988 if s.params == nil || i >= s.params.Len() {
6989 return ""
6990 }
6991 return s.params.At(i).name
6992 }
6993 `)
6994 name180 := []byte("mypkg")
6995 h180 := compileToIR(
6996 uintptr(unsafe.Pointer(&src180[0])), int32(len(src180)),
6997 uintptr(unsafe.Pointer(&name180[0])), int32(len(name180)),
6998 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6999 )
7000 ir180 := getIR(h180)
7001 fmt.Println("=== IR for Signature ===")
7002 fmt.Println(ir180)
7003
7004 if ir180 == "" {
7005 assert("signature produces IR", false)
7006 } else {
7007 llvmVerify("Signature", ir180)
7008 assert("sig has NewSig180", strings.Contains(ir180, "@mypkg.NewSig180"))
7009 assert("sig has numParams", strings.Contains(ir180, "@mypkg.numParams"))
7010 assert("sig has numResults", strings.Contains(ir180, "@mypkg.numResults"))
7011 assert("sig has hasReceiver", strings.Contains(ir180, "@mypkg.hasReceiver"))
7012 assert("sig has paramName", strings.Contains(ir180, "@mypkg.paramName"))
7013 assert("sig nil check on params", strings.Contains(ir180, "icmp") && strings.Contains(ir180, "null"))
7014 assert("sig no parse error", !strings.Contains(ir180, "parse error"))
7015 }
7016
7017 irFree(h180)
7018
7019 // Test 181: SSA instruction hierarchy (the pattern from ssa_types.mx)
7020 src181 := []byte(`package mypkg
7021
7022 type SSAType181 interface {
7023 Underlying() SSAType181
7024 }
7025
7026 type SSAValue181 interface {
7027 SSAType() SSAType181
7028 Name181() string
7029 }
7030
7031 type ssaNode181 struct {
7032 name string
7033 typ SSAType181
7034 }
7035
7036 func (n *ssaNode181) SSAType() SSAType181 { return n.typ }
7037 func (n *ssaNode181) Name181() string { return n.name }
7038
7039 type SSAConst181 struct {
7040 ssaNode181
7041 val int64
7042 }
7043
7044 type SSAAlloc181 struct {
7045 ssaNode181
7046 heap bool
7047 }
7048
7049 type SSABinOp181 struct {
7050 ssaNode181
7051 op int32
7052 x SSAValue181
7053 y SSAValue181
7054 }
7055
7056 type SSACall181 struct {
7057 ssaNode181
7058 fn string
7059 args []SSAValue181
7060 }
7061
7062 func isConst(v SSAValue181) bool {
7063 _, ok := v.(*SSAConst181)
7064 return ok
7065 }
7066
7067 func operandName(v SSAValue181) string {
7068 if v == nil {
7069 return "undef"
7070 }
7071 if c, ok := v.(*SSAConst181); ok {
7072 return itoa181(int32(c.val))
7073 }
7074 return "%" | v.Name181()
7075 }
7076
7077 func itoa181(n int32) string {
7078 if n == 0 {
7079 return "0"
7080 }
7081 buf := []byte{:0:10}
7082 for n > 0 {
7083 buf = append(buf, byte('0' + n % 10))
7084 n = n / 10
7085 }
7086 return string(buf)
7087 }
7088
7089 func countArgs(c *SSACall181) int32 {
7090 return int32(len(c.args))
7091 }
7092 `)
7093 name181 := []byte("mypkg")
7094 h181 := compileToIR(
7095 uintptr(unsafe.Pointer(&src181[0])), int32(len(src181)),
7096 uintptr(unsafe.Pointer(&name181[0])), int32(len(name181)),
7097 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7098 )
7099 ir181 := getIR(h181)
7100 fmt.Println("=== IR for SSA types ===")
7101 fmt.Println(ir181)
7102
7103 if ir181 == "" {
7104 assert("ssa types produces IR", false)
7105 } else {
7106 llvmVerify("SSA types", ir181)
7107 assert("ssa has isConst", strings.Contains(ir181, "@mypkg.isConst"))
7108 assert("ssa has operandName", strings.Contains(ir181, "@mypkg.operandName"))
7109 assert("ssa has countArgs", strings.Contains(ir181, "@mypkg.countArgs"))
7110 assert("ssa SSAConst181 typeid", strings.Contains(ir181, "typeid.ptr.SSAConst181"))
7111 assert("ssa promotes Name181 via embed", strings.Contains(ir181, "ssaNode181.Name181") || strings.Contains(ir181, "SSAConst181.Name181"))
7112 assert("ssa no parse error", !strings.Contains(ir181, "parse error"))
7113 }
7114
7115 irFree(h181)
7116
7117 // Test 182: Self-compilation pattern - mini IR emitter compiling mini IR emitter
7118 src182 := []byte(`package mypkg
7119
7120 type Type182 interface {
7121 Underlying() Type182
7122 String() string
7123 }
7124
7125 type Basic182 struct {
7126 kind int32
7127 name string
7128 }
7129
7130 func (t *Basic182) Underlying() Type182 { return t }
7131 func (t *Basic182) String() string { return t.name }
7132
7133 type Slice182 struct {
7134 elem Type182
7135 }
7136
7137 func (t *Slice182) Underlying() Type182 { return t }
7138 func (t *Slice182) String() string { return "[]" | t.elem.String() }
7139
7140 type Pointer182 struct {
7141 base Type182
7142 }
7143
7144 func (t *Pointer182) Underlying() Type182 { return t }
7145 func (t *Pointer182) String() string { return "*" | t.base.String() }
7146
7147 type SSAValue182 interface {
7148 ValType() Type182
7149 ValName() string
7150 }
7151
7152 type ssaBase182 struct {
7153 name string
7154 typ Type182
7155 }
7156
7157 func (n *ssaBase182) ValType() Type182 { return n.typ }
7158 func (n *ssaBase182) ValName() string { return n.name }
7159
7160 type SSAConst182 struct {
7161 ssaBase182
7162 val int64
7163 }
7164
7165 type SSABinOp182 struct {
7166 ssaBase182
7167 op int32
7168 x SSAValue182
7169 y SSAValue182
7170 }
7171
7172 type SSAFieldAddr182 struct {
7173 ssaBase182
7174 x SSAValue182
7175 field int32
7176 }
7177
7178 type Emitter182 struct {
7179 buf []byte
7180 decls map[string]bool
7181 tempCount int32
7182 pkg string
7183 }
7184
7185 func NewEmitter182(pkg string) *Emitter182 {
7186 return &Emitter182{pkg: pkg, decls: map[string]bool{}}
7187 }
7188
7189 func (e *Emitter182) w(s string) {
7190 e.buf = append(e.buf, s...)
7191 }
7192
7193 func (e *Emitter182) nextTemp() string {
7194 e.tempCount = e.tempCount + 1
7195 return "%t" | itoa182(e.tempCount)
7196 }
7197
7198 func (e *Emitter182) llvmType(t Type182) string {
7199 switch t.(type) {
7200 case *Basic182:
7201 b := t.(*Basic182)
7202 switch b.kind {
7203 case 0:
7204 return "i32"
7205 case 1:
7206 return "i64"
7207 case 2:
7208 return "{ptr, i64, i64}"
7209 }
7210 return "i32"
7211 case *Slice182:
7212 return "{ptr, i64, i64}"
7213 case *Pointer182:
7214 return "ptr"
7215 }
7216 return "i32"
7217 }
7218
7219 func (e *Emitter182) operand(v SSAValue182) string {
7220 if v == nil {
7221 return "zeroinitializer"
7222 }
7223 if c, ok := v.(*SSAConst182); ok {
7224 return itoa182(int32(c.val))
7225 }
7226 return "%" | v.ValName()
7227 }
7228
7229 func (e *Emitter182) emitBinOp(b *SSABinOp182) {
7230 reg := e.nextTemp()
7231 lt := e.llvmType(b.x.ValType())
7232 lv := e.operand(b.x)
7233 rv := e.operand(b.y)
7234 e.w(" ")
7235 e.w(reg)
7236 e.w(" = add ")
7237 e.w(lt)
7238 e.w(" ")
7239 e.w(lv)
7240 e.w(", ")
7241 e.w(rv)
7242 e.w("\n")
7243 }
7244
7245 func (e *Emitter182) result() string {
7246 return string(e.buf)
7247 }
7248
7249 func itoa182(n int32) string {
7250 if n == 0 {
7251 return "0"
7252 }
7253 buf := []byte{:0:10}
7254 for n > 0 {
7255 buf = append(buf, byte('0' + n % 10))
7256 n = n / 10
7257 }
7258 i := 0
7259 j := int32(len(buf)) - 1
7260 for i < j {
7261 buf[i], buf[j] = buf[j], buf[i]
7262 i = i + 1
7263 j = j - 1
7264 }
7265 return string(buf)
7266 }
7267 `)
7268 name182 := []byte("mypkg")
7269 h182 := compileToIR(
7270 uintptr(unsafe.Pointer(&src182[0])), int32(len(src182)),
7271 uintptr(unsafe.Pointer(&name182[0])), int32(len(name182)),
7272 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7273 )
7274 ir182 := getIR(h182)
7275 fmt.Println("=== IR for self-compile pattern ===")
7276 fmt.Println(ir182)
7277
7278 if ir182 == "" {
7279 assert("self-compile produces IR", false)
7280 } else {
7281 llvmVerify("self-compile", ir182)
7282 assert("sc has NewEmitter182", strings.Contains(ir182, "@mypkg.NewEmitter182"))
7283 assert("sc has emitBinOp", strings.Contains(ir182, "@mypkg.Emitter182.emitBinOp"))
7284 assert("sc has llvmType", strings.Contains(ir182, "@mypkg.Emitter182.llvmType"))
7285 assert("sc has operand", strings.Contains(ir182, "@mypkg.Emitter182.operand"))
7286 assert("sc has nextTemp", strings.Contains(ir182, "@mypkg.Emitter182.nextTemp"))
7287 assert("sc Basic182 typeid", strings.Contains(ir182, "typeid.ptr.Basic182"))
7288 assert("sc Slice182 typeid", strings.Contains(ir182, "typeid.ptr.Slice182"))
7289 assert("sc Pointer182 typeid", strings.Contains(ir182, "typeid.ptr.Pointer182"))
7290 assert("sc SSAConst182 typeid", strings.Contains(ir182, "typeid.ptr.SSAConst182"))
7291 assert("sc no parse error", !strings.Contains(ir182, "parse error"))
7292 }
7293
7294 irFree(h182)
7295
7296 // Test 183: Real bootstrap files - tc_package + tc_scope + Object (concatenated)
7297 src183 := []byte(`package main
7298
7299 type Type interface {
7300 Underlying() Type
7301 String() string
7302 }
7303
7304 type Object interface {
7305 Name() string
7306 Type() Type
7307 Pkg() *TCPackage
7308 Exported() bool
7309 }
7310
7311 type object struct {
7312 pkg *TCPackage
7313 name string
7314 typ Type
7315 }
7316
7317 func (o *object) Name() string { return o.name }
7318 func (o *object) Type() Type { return o.typ }
7319 func (o *object) Pkg() *TCPackage { return o.pkg }
7320 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
7321
7322 type TypeName struct {
7323 object
7324 }
7325
7326 func NewTypeName(pkg *TCPackage, name string, typ Type) *TypeName {
7327 return &TypeName{object{pkg: pkg, name: name, typ: typ}}
7328 }
7329
7330 type TCVar struct {
7331 pkg *TCPackage
7332 name string
7333 typ Type
7334 anonymous bool
7335 }
7336
7337 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
7338 return &TCVar{pkg: pkg, name: name, typ: typ, anonymous: anonymous}
7339 }
7340
7341 func (v *TCVar) Name() string { return v.name }
7342 func (v *TCVar) Type() Type { return v.typ }
7343 func (v *TCVar) Pkg() *TCPackage { return v.pkg }
7344 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
7345 func (v *TCVar) Anonymous() bool { return v.anonymous }
7346
7347 type TCPackage struct {
7348 path string
7349 name string
7350 scope *Scope
7351 imports []*TCPackage
7352 complete bool
7353 }
7354
7355 func NewTCPackage(path string, name string) *TCPackage {
7356 return &TCPackage{
7357 path: path,
7358 name: name,
7359 scope: NewScope(nil),
7360 }
7361 }
7362
7363 func (p *TCPackage) Path() string { return p.path }
7364 func (p *TCPackage) Name() string { return p.name }
7365 func (p *TCPackage) Scope() *Scope { return p.scope }
7366 func (p *TCPackage) Complete() bool { return p.complete }
7367 func (p *TCPackage) MarkComplete() { p.complete = true }
7368 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
7369 func (p *TCPackage) Imports() []*TCPackage { return p.imports }
7370 func (p *TCPackage) SetImports(imps []*TCPackage) { p.imports = imps }
7371
7372 type Scope struct {
7373 parent *Scope
7374 children []*Scope
7375 elems map[string]Object
7376 }
7377
7378 func NewScope(parent *Scope) *Scope {
7379 return &Scope{parent: parent, elems: map[string]Object{}}
7380 }
7381
7382 func (s *Scope) Parent() *Scope { return s.parent }
7383 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
7384
7385 func (s *Scope) Lookup(name string) Object {
7386 return s.elems[name]
7387 }
7388
7389 func (s *Scope) LookupParent(name string) (*Scope, Object) {
7390 for sc := s; sc != nil; sc = sc.parent {
7391 if obj, ok := sc.elems[name]; ok {
7392 return sc, obj
7393 }
7394 }
7395 return nil, nil
7396 }
7397
7398 func (s *Scope) Insert(obj Object) Object {
7399 name := obj.Name()
7400 if alt, ok := s.elems[name]; ok {
7401 return alt
7402 }
7403 s.elems[name] = obj
7404 return nil
7405 }
7406
7407 func (s *Scope) Names() []string {
7408 names := []string{:0:len(s.elems)}
7409 for n := range s.elems {
7410 names = append(names, n)
7411 }
7412 return names
7413 }
7414 `)
7415 name183 := []byte("main")
7416 h183 := compileToIR(
7417 uintptr(unsafe.Pointer(&src183[0])), int32(len(src183)),
7418 uintptr(unsafe.Pointer(&name183[0])), int32(len(name183)),
7419 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7420 )
7421 ir183 := getIR(h183)
7422 fmt.Println("=== IR for real bootstrap concat ===")
7423 if len(ir183) > 200 {
7424 fmt.Println(ir183[:200])
7425 fmt.Println("... [truncated, total", len(ir183), "bytes]")
7426 } else {
7427 fmt.Println(ir183)
7428 }
7429
7430 if ir183 == "" {
7431 assert("bootstrap concat produces IR", false)
7432 } else {
7433 llvmVerify("bootstrap concat", ir183)
7434 assert("bc has NewTCPackage", strings.Contains(ir183, "@main.NewTCPackage"))
7435 assert("bc has NewScope", strings.Contains(ir183, "@main.NewScope"))
7436 assert("bc has Scope.Insert", strings.Contains(ir183, "@main.Scope.Insert"))
7437 assert("bc has Scope.LookupParent", strings.Contains(ir183, "@main.Scope.LookupParent"))
7438 assert("bc has Scope.Names", strings.Contains(ir183, "@main.Scope.Names"))
7439 assert("bc has object.Exported", strings.Contains(ir183, "@main.object.Exported"))
7440 assert("bc has NewTypeName", strings.Contains(ir183, "@main.NewTypeName"))
7441 assert("bc has TCPackage.String", strings.Contains(ir183, "@main.TCPackage.String"))
7442 assert("bc has hashmapLen", strings.Contains(ir183, "hashmapLen"))
7443 assert("bc no parse error", !strings.Contains(ir183, "parse error"))
7444 }
7445
7446 irFree(h183)
7447
7448 // Test 184: copy builtin
7449 test(184, `package main
7450 func copyBytes(dst []byte, src []byte) int32 {
7451 return int32(copy(dst, src))
7452 }
7453 func main() {
7454 a := []byte{:10}
7455 b := []byte("hello")
7456 n := copyBytes(a, b)
7457 _ = n
7458 }
7459 `, func(ir string) {
7460 assert("184: copy call", strings.Contains(ir, "sliceCopy"))
7461 })
7462
7463 // Test 185: panic builtin
7464 test(185, `package main
7465 func mustNotBeNil(p *int32) {
7466 if p == nil {
7467 panic("nil pointer")
7468 }
7469 }
7470 func main() {
7471 var x int32
7472 mustNotBeNil(&x)
7473 }
7474 `, func(ir string) {
7475 assert("185: panic call", strings.Contains(ir, "_panic"))
7476 })
7477
7478 // Test 186: named returns
7479 test(186, `package main
7480 func divide(a int32, b int32) (q int32, r int32) {
7481 q = a / b
7482 r = a - q*b
7483 return
7484 }
7485 func main() {
7486 q, r := divide(17, 5)
7487 _ = q
7488 _ = r
7489 }
7490 `, func(ir string) {
7491 assert("186: divide defined", strings.Contains(ir, "@main.divide"))
7492 })
7493
7494 // Test 187: function values as struct fields
7495 test(187, `package main
7496 type Handler struct {
7497 onEvent func(int32) bool
7498 name string
7499 }
7500 func process(h *Handler, val int32) bool {
7501 if h.onEvent != nil {
7502 return h.onEvent(val)
7503 }
7504 return false
7505 }
7506 func main() {
7507 h := &Handler{
7508 onEvent: func(v int32) bool { return v > 0 },
7509 name: "test",
7510 }
7511 result := process(h, 42)
7512 _ = result
7513 }
7514 `, func(ir string) {
7515 assert("187: process defined", strings.Contains(ir, "@main.process"))
7516 })
7517
7518 // Test 188: goto statement
7519 test(188, `package main
7520 func search(data []byte, target byte) int32 {
7521 var i int32
7522 loop:
7523 if i >= int32(len(data)) {
7524 return -1
7525 }
7526 if data[i] == target {
7527 return i
7528 }
7529 i++
7530 goto loop
7531 }
7532 func main() {
7533 data := []byte("hello")
7534 idx := search(data, 'l')
7535 _ = idx
7536 }
7537 `, func(ir string) {
7538 assert("188: search defined", strings.Contains(ir, "@main.search"))
7539 })
7540
7541 // Test 189: multiple assignment
7542 test(189, `package main
7543 func swap(a int32, b int32) (int32, int32) {
7544 return b, a
7545 }
7546 func main() {
7547 x, y := swap(1, 2)
7548 _ = x
7549 _ = y
7550 }
7551 `, func(ir string) {
7552 assert("189: swap defined", strings.Contains(ir, "@main.swap"))
7553 })
7554
7555 // Test 190: rune type and comparisons
7556 test(190, `package main
7557 func isDigit(ch rune) bool {
7558 return ch >= '0' && ch <= '9'
7559 }
7560 func isLetter(ch rune) bool {
7561 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
7562 }
7563 func main() {
7564 d := isDigit('5')
7565 l := isLetter('x')
7566 _ = d
7567 _ = l
7568 }
7569 `, func(ir string) {
7570 assert("190: isDigit defined", strings.Contains(ir, "@main.isDigit"))
7571 assert("190: isLetter defined", strings.Contains(ir, "@main.isLetter"))
7572 })
7573
7574 // Test 191: function value nil check and call through variable
7575 test(191, `package main
7576 type Callback func(string)
7577 func invoke(cb Callback, msg string) {
7578 if cb != nil {
7579 cb(msg)
7580 }
7581 }
7582 func main() {
7583 var cb Callback
7584 invoke(cb, "test")
7585 }
7586 `, func(ir string) {
7587 assert("191: invoke defined", strings.Contains(ir, "@main.invoke"))
7588 })
7589
7590 // Test 192: struct value return (non-pointer)
7591 test(192, `package main
7592 type Point struct {
7593 x int32
7594 y int32
7595 }
7596 func makePoint(x int32, y int32) Point {
7597 return Point{x, y}
7598 }
7599 func addPoints(a Point, b Point) Point {
7600 return Point{a.x + b.x, a.y + b.y}
7601 }
7602 func main() {
7603 p1 := makePoint(1, 2)
7604 p2 := makePoint(3, 4)
7605 p3 := addPoints(p1, p2)
7606 _ = p3
7607 }
7608 `, func(ir string) {
7609 assert("192: makePoint defined", strings.Contains(ir, "@main.makePoint"))
7610 assert("192: addPoints defined", strings.Contains(ir, "@main.addPoints"))
7611 })
7612
7613 // Test 193: Source-like pattern (nextch with goto, byte indexing, rune)
7614 test(193, `package main
7615 const sentinel = 128
7616 type Source struct {
7617 buf []byte
7618 b int32
7619 r int32
7620 e int32
7621 line uint32
7622 col uint32
7623 ch rune
7624 chw int32
7625 }
7626 func (s *Source) start() { s.b = s.r - s.chw }
7627 func (s *Source) stop() { s.b = -1 }
7628 func (s *Source) segment() []byte { return s.buf[s.b : s.r-s.chw] }
7629 func (s *Source) nextch() {
7630 s.col += uint32(s.chw)
7631 if s.ch == '\n' {
7632 s.line++
7633 s.col = 0
7634 }
7635 if s.ch = rune(s.buf[s.r]); s.ch < sentinel {
7636 s.r++
7637 s.chw = 1
7638 if s.ch == 0 {
7639 return
7640 }
7641 return
7642 }
7643 s.ch = -1
7644 s.chw = 0
7645 }
7646 func main() {
7647 s := &Source{buf: []byte("hello\nworld"), r: 0, e: 11, ch: ' ', b: -1}
7648 s.nextch()
7649 }
7650 `, func(ir string) {
7651 assert("193: nextch defined", strings.Contains(ir, "@main.Source.nextch"))
7652 assert("193: segment defined", strings.Contains(ir, "@main.Source.segment"))
7653 })
7654
7655 // Test 194: Token-like const enum with type conversion
7656 test(194, `package main
7657 type Token uint32
7658 const (
7659 _ Token = iota
7660 EOF
7661 NameType
7662 Literal
7663 OperatorType
7664 AssignOp
7665 Lparen
7666 Rparen
7667 Comma
7668 Semi
7669 tokenCount
7670 )
7671 const _ uint64 = 1 << (tokenCount - 1)
7672 func contains(tokset uint64, tok Token) bool {
7673 return tokset&(1<<tok) != 0
7674 }
7675 type LitKind uint8
7676 const (
7677 IntLit LitKind = iota
7678 FloatLit
7679 StringLit
7680 )
7681 func main() {
7682 b := contains(1<<EOF|1<<NameType, EOF)
7683 _ = b
7684 }
7685 `, func(ir string) {
7686 assert("194: contains defined", strings.Contains(ir, "@main.contains"))
7687 })
7688
7689 // Test 195: Pos-like value receiver with nested struct access
7690 test(195, `package main
7691 type PosBase struct {
7692 filename string
7693 line uint32
7694 col uint32
7695 }
7696 type Pos struct {
7697 base *PosBase
7698 line uint32
7699 col uint32
7700 }
7701 func MakePos(base *PosBase, line uint32, col uint32) Pos {
7702 return Pos{base, line, col}
7703 }
7704 func (pos Pos) IsKnown() bool { return pos.line > 0 }
7705 func (pos Pos) Base() *PosBase { return pos.base }
7706 func (pos Pos) Line() uint32 { return pos.line }
7707 func (pos Pos) Col() uint32 { return pos.col }
7708 func (pos Pos) Filename() string {
7709 if pos.base == nil {
7710 return ""
7711 }
7712 return pos.base.filename
7713 }
7714 func main() {
7715 base := &PosBase{filename: "test.mx", line: 1, col: 1}
7716 p := MakePos(base, 10, 5)
7717 known := p.IsKnown()
7718 name := p.Filename()
7719 _ = known
7720 _ = name
7721 }
7722 `, func(ir string) {
7723 assert("195: MakePos defined", strings.Contains(ir, "@main.MakePos"))
7724 assert("195: Filename defined", strings.Contains(ir, "@main.Pos.Filename"))
7725 })
7726
7727 // Test 196: Scanner-like pattern with for loop and byte comparisons
7728 test(196, `package main
7729 type Scanner struct {
7730 src []byte
7731 pos int32
7732 ch byte
7733 }
7734 func (s *Scanner) setup(src []byte) {
7735 s.src = src
7736 s.pos = 0
7737 if len(src) > 0 {
7738 s.ch = src[0]
7739 }
7740 }
7741 func (s *Scanner) next() {
7742 s.pos++
7743 if s.pos < int32(len(s.src)) {
7744 s.ch = s.src[s.pos]
7745 } else {
7746 s.ch = 0
7747 }
7748 }
7749 func (s *Scanner) skipSpace() {
7750 for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' || s.ch == '\r' {
7751 s.next()
7752 }
7753 }
7754 func (s *Scanner) readIdent() string {
7755 start := s.pos
7756 for s.ch >= 'a' && s.ch <= 'z' || s.ch >= 'A' && s.ch <= 'Z' || s.ch == '_' || s.ch >= '0' && s.ch <= '9' {
7757 s.next()
7758 }
7759 return string(s.src[start:s.pos])
7760 }
7761 func main() {
7762 sc := &Scanner{}
7763 sc.setup([]byte(" hello world"))
7764 sc.skipSpace()
7765 word := sc.readIdent()
7766 _ = word
7767 }
7768 `, func(ir string) {
7769 assert("196: setup defined", strings.Contains(ir, "@main.Scanner.setup"))
7770 assert("196: skipSpace defined", strings.Contains(ir, "@main.Scanner.skipSpace"))
7771 assert("196: readIdent defined", strings.Contains(ir, "@main.Scanner.readIdent"))
7772 })
7773
7774 // Test 197: Node hierarchy with interface and type switch
7775 test(197, `package main
7776 type Node interface {
7777 nodeTag()
7778 }
7779 type Expr interface {
7780 Node
7781 exprTag()
7782 }
7783 type Name struct {
7784 Value string
7785 }
7786 func (n *Name) nodeTag() {}
7787 func (n *Name) exprTag() {}
7788 type BasicLit struct {
7789 Value string
7790 Kind int32
7791 }
7792 func (b *BasicLit) nodeTag() {}
7793 func (b *BasicLit) exprTag() {}
7794 type BinaryExpr struct {
7795 X Expr
7796 Op int32
7797 Y Expr
7798 }
7799 func (b *BinaryExpr) nodeTag() {}
7800 func (b *BinaryExpr) exprTag() {}
7801 func exprName(e Expr) string {
7802 switch x := e.(type) {
7803 case *Name:
7804 return x.Value
7805 case *BasicLit:
7806 return x.Value
7807 case *BinaryExpr:
7808 return "binary"
7809 }
7810 return ""
7811 }
7812 func main() {
7813 n := &Name{Value: "foo"}
7814 var e Expr = n
7815 result := exprName(e)
7816 _ = result
7817 }
7818 `, func(ir string) {
7819 assert("197: exprName defined", strings.Contains(ir, "@main.exprName"))
7820 assert("197: has type switch", strings.Contains(ir, "icmp eq ptr"))
7821 })
7822
7823 // Test 198: Linked list pattern (self-referential struct)
7824 test(198, `package main
7825 type ListNode struct {
7826 value int32
7827 next *ListNode
7828 }
7829 func push(head *ListNode, val int32) *ListNode {
7830 return &ListNode{value: val, next: head}
7831 }
7832 func length(head *ListNode) int32 {
7833 n := int32(0)
7834 for p := head; p != nil; p = p.next {
7835 n++
7836 }
7837 return n
7838 }
7839 func sum(head *ListNode) int32 {
7840 s := int32(0)
7841 for p := head; p != nil; p = p.next {
7842 s += p.value
7843 }
7844 return s
7845 }
7846 func main() {
7847 var head *ListNode
7848 head = push(head, 1)
7849 head = push(head, 2)
7850 head = push(head, 3)
7851 n := length(head)
7852 s := sum(head)
7853 _ = n
7854 _ = s
7855 }
7856 `, func(ir string) {
7857 assert("198: push defined", strings.Contains(ir, "@main.push"))
7858 assert("198: length defined", strings.Contains(ir, "@main.length"))
7859 assert("198: sum defined", strings.Contains(ir, "@main.sum"))
7860 })
7861
7862 // Test 199: Slice of structs with append
7863 test(199, `package main
7864 type Entry struct {
7865 name string
7866 value int32
7867 }
7868 func addEntry(entries []Entry, name string, val int32) []Entry {
7869 return append(entries, Entry{name: name, value: val})
7870 }
7871 func findEntry(entries []Entry, name string) int32 {
7872 for i := int32(0); i < int32(len(entries)); i++ {
7873 if entries[i].name == name {
7874 return entries[i].value
7875 }
7876 }
7877 return -1
7878 }
7879 func main() {
7880 var entries []Entry
7881 entries = addEntry(entries, "x", 10)
7882 entries = addEntry(entries, "y", 20)
7883 v := findEntry(entries, "x")
7884 _ = v
7885 }
7886 `, func(ir string) {
7887 assert("199: addEntry defined", strings.Contains(ir, "@main.addEntry"))
7888 assert("199: findEntry defined", strings.Contains(ir, "@main.findEntry"))
7889 })
7890
7891 // Test 200: bytes.Buffer-like pattern (write methods, grow)
7892 test(200, `package main
7893 type Buffer struct {
7894 buf []byte
7895 }
7896 func (b *Buffer) Len() int32 { return int32(len(b.buf)) }
7897 func (b *Buffer) Bytes() []byte { return b.buf }
7898 func (b *Buffer) String() string { return string(b.buf) }
7899 func (b *Buffer) Reset() { b.buf = b.buf[:0] }
7900 func (b *Buffer) WriteByte(c byte) {
7901 b.buf = append(b.buf, c)
7902 }
7903 func (b *Buffer) WriteString(s string) {
7904 b.buf = append(b.buf, s...)
7905 }
7906 func (b *Buffer) Write(p []byte) int32 {
7907 b.buf = append(b.buf, p...)
7908 return int32(len(p))
7909 }
7910 func main() {
7911 var buf Buffer
7912 buf.WriteByte('(')
7913 buf.WriteString("hello")
7914 buf.WriteByte(')')
7915 s := buf.String()
7916 _ = s
7917 }
7918 `, func(ir string) {
7919 assert("200: WriteByte defined", strings.Contains(ir, "@main.Buffer.WriteByte"))
7920 assert("200: WriteString defined", strings.Contains(ir, "@main.Buffer.WriteString"))
7921 assert("200: String defined", strings.Contains(ir, "@main.Buffer.String"))
7922 })
7923
7924 // Test 201: Checker-like pattern with Info struct and map lookups
7925 test(201, `package main
7926 type Node interface{ nodeTag() }
7927 type Expr interface {
7928 Node
7929 exprTag()
7930 }
7931 type Name struct { Value string }
7932 func (n *Name) nodeTag() {}
7933 func (n *Name) exprTag() {}
7934 type TypeAndValue struct {
7935 Type int32
7936 mode int32
7937 }
7938 func (tv TypeAndValue) IsValue() bool { return tv.mode == 1 || tv.mode == 2 }
7939 func (tv TypeAndValue) IsConst() bool { return tv.mode == 3 }
7940 type Info struct {
7941 Types map[Expr]TypeAndValue
7942 Defs map[*Name]int32
7943 }
7944 func NewInfo() *Info {
7945 return &Info{
7946 Types: map[Expr]TypeAndValue{},
7947 Defs: map[*Name]int32{},
7948 }
7949 }
7950 func (info *Info) TypeOf(e Expr) int32 {
7951 if tv, ok := info.Types[e]; ok {
7952 return tv.Type
7953 }
7954 return 0
7955 }
7956 func main() {
7957 info := NewInfo()
7958 n := &Name{Value: "x"}
7959 info.Types[n] = TypeAndValue{Type: 42, mode: 1}
7960 t := info.TypeOf(n)
7961 _ = t
7962 }
7963 `, func(ir string) {
7964 assert("201: NewInfo defined", strings.Contains(ir, "@main.NewInfo"))
7965 assert("201: TypeOf defined", strings.Contains(ir, "@main.Info.TypeOf"))
7966 })
7967
7968 // Test 202: Multi-level pointer chain (a->b->c field access)
7969 test(202, `package main
7970 type Inner struct {
7971 value int32
7972 }
7973 type Middle struct {
7974 inner *Inner
7975 name string
7976 }
7977 type Outer struct {
7978 mid *Middle
7979 tag int32
7980 }
7981 func getValue(o *Outer) int32 {
7982 return o.mid.inner.value
7983 }
7984 func getName(o *Outer) string {
7985 return o.mid.name
7986 }
7987 func main() {
7988 i := &Inner{value: 42}
7989 m := &Middle{inner: i, name: "hello"}
7990 o := &Outer{mid: m, tag: 1}
7991 v := getValue(o)
7992 n := getName(o)
7993 _ = v
7994 _ = n
7995 }
7996 `, func(ir string) {
7997 assert("202: getValue defined", strings.Contains(ir, "@main.getValue"))
7998 assert("202: getName defined", strings.Contains(ir, "@main.getName"))
7999 })
8000
8001 // Test 203: String comparison in if/else chain
8002 test(203, `package main
8003 func classify(s string) int32 {
8004 if s == "int" {
8005 return 1
8006 } else if s == "string" {
8007 return 2
8008 } else if s == "bool" {
8009 return 3
8010 }
8011 return 0
8012 }
8013 func main() {
8014 c := classify("int")
8015 _ = c
8016 }
8017 `, func(ir string) {
8018 assert("203: classify defined", strings.Contains(ir, "@main.classify"))
8019 })
8020
8021 // Test 204: Variadic-like append pattern
8022 test(204, `package main
8023 func joinStrings(sep string, parts []string) string {
8024 if len(parts) == 0 {
8025 return ""
8026 }
8027 result := parts[0]
8028 for i := int32(1); i < int32(len(parts)); i++ {
8029 result = result | sep | parts[i]
8030 }
8031 return result
8032 }
8033 func main() {
8034 parts := []string{"a", "b", "c"}
8035 s := joinStrings(", ", parts)
8036 _ = s
8037 }
8038 `, func(ir string) {
8039 assert("204: joinStrings defined", strings.Contains(ir, "@main.joinStrings"))
8040 })
8041
8042 // Test 205: Alloc with field initialization in loop
8043 test(205, `package main
8044 type Node struct {
8045 key string
8046 value int32
8047 next *Node
8048 }
8049 func buildList(keys []string) *Node {
8050 var head *Node
8051 for i := int32(len(keys)) - 1; i >= 0; i-- {
8052 n := &Node{key: keys[i], value: i, next: head}
8053 head = n
8054 }
8055 return head
8056 }
8057 func main() {
8058 keys := []string{"a", "b", "c"}
8059 list := buildList(keys)
8060 _ = list
8061 }
8062 `, func(ir string) {
8063 assert("205: buildList defined", strings.Contains(ir, "@main.buildList"))
8064 })
8065
8066 // Test 206: Token types with const enums (no globals)
8067 test(206, `package main
8068 type Token uint32
8069 const (
8070 _ Token = iota
8071 EOF
8072 NameType
8073 Literal
8074 tokenCount
8075 )
8076 const _ uint64 = 1 << (tokenCount - 1)
8077 func contains(tokset uint64, tok Token) bool {
8078 return tokset&(1<<tok) != 0
8079 }
8080 func main() {
8081 b := contains(1<<EOF|1<<NameType, Literal)
8082 _ = b
8083 }
8084 `, func(ir string) {
8085 assert("206: contains defined", strings.Contains(ir, "@main.contains"))
8086 })
8087
8088 // Test 207: Full tc_types-like pattern (Type interface, Named types, methods)
8089 test(207, `package main
8090 type Type interface {
8091 Underlying() Type
8092 String() string
8093 }
8094 type BasicInfo int32
8095 const (
8096 IsBoolean BasicInfo = 1 << iota
8097 IsInteger
8098 IsUnsigned
8099 IsFloat
8100 IsString
8101 IsUntyped
8102 )
8103 type BasicKind int32
8104 type Basic struct {
8105 kind BasicKind
8106 info BasicInfo
8107 name string
8108 }
8109 func (b *Basic) Underlying() Type { return b }
8110 func (b *Basic) String() string { return b.name }
8111 func (b *Basic) Kind() BasicKind { return b.kind }
8112 func (b *Basic) Info() BasicInfo { return b.info }
8113 func (b *Basic) Name() string { return b.name }
8114 type Slice struct {
8115 elem Type
8116 }
8117 func (s *Slice) Underlying() Type { return s }
8118 func (s *Slice) String() string { return "[]" | s.elem.String() }
8119 func (s *Slice) Elem() Type { return s.elem }
8120 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
8121 type Pointer struct {
8122 base Type
8123 }
8124 func (p *Pointer) Underlying() Type { return p }
8125 func (p *Pointer) String() string { return "*" | p.base.String() }
8126 func (p *Pointer) Elem() Type { return p.base }
8127 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
8128 type Named struct {
8129 name string
8130 under Type
8131 methods []*Func
8132 }
8133 func (n *Named) Underlying() Type { return n.under }
8134 func (n *Named) String() string { return n.name }
8135 func (n *Named) NumMethods() int32 { return int32(len(n.methods)) }
8136 func (n *Named) Method(i int32) *Func { return n.methods[i] }
8137 func (n *Named) AddMethod(m *Func) { n.methods = append(n.methods, m) }
8138 type Func struct {
8139 name string
8140 typ Type
8141 }
8142 func (f *Func) Name() string { return f.name }
8143 func (f *Func) Type() Type { return f.typ }
8144 func main() {
8145 intType := &Basic{kind: 2, info: IsInteger, name: "int"}
8146 sliceType := NewSlice(intType)
8147 ptrType := NewPointer(intType)
8148 named := &Named{name: "MyInt", under: intType}
8149 named.AddMethod(&Func{name: "String", typ: intType})
8150 s1 := intType.String()
8151 s2 := sliceType.String()
8152 s3 := ptrType.String()
8153 n := named.NumMethods()
8154 _ = s1
8155 _ = s2
8156 _ = s3
8157 _ = n
8158 }
8159 `, func(ir string) {
8160 assert("207: Basic.String defined", strings.Contains(ir, "@main.Basic.String"))
8161 assert("207: Slice.String defined", strings.Contains(ir, "@main.Slice.String"))
8162 assert("207: Pointer.String defined", strings.Contains(ir, "@main.Pointer.String"))
8163 assert("207: Named.AddMethod defined", strings.Contains(ir, "@main.Named.AddMethod"))
8164 })
8165
8166 // Test 208: Checker-like pattern with type resolution
8167 test(208, `package main
8168 type Type interface {
8169 Underlying() Type
8170 }
8171 type Basic208 struct {
8172 kind int32
8173 name string
8174 }
8175 func (b *Basic208) Underlying() Type { return b }
8176 type Pointer208 struct {
8177 base Type
8178 }
8179 func (p *Pointer208) Underlying() Type { return p }
8180 func (p *Pointer208) Elem() Type { return p.base }
8181 type Checker struct {
8182 pkg string
8183 types map[string]Type
8184 }
8185 func NewChecker(pkg string) *Checker {
8186 return &Checker{pkg: pkg, types: map[string]Type{}}
8187 }
8188 func (c *Checker) Define(name string, t Type) {
8189 c.types[name] = t
8190 }
8191 func (c *Checker) Resolve(name string) Type {
8192 t, ok := c.types[name]
8193 if ok {
8194 return t
8195 }
8196 return nil
8197 }
8198 func (c *Checker) IsPointer(t Type) bool {
8199 _, ok := t.(*Pointer208)
8200 return ok
8201 }
8202 func main() {
8203 c := NewChecker("main")
8204 intT := &Basic208{kind: 1, name: "int"}
8205 c.Define("int", intT)
8206 c.Define("*int", &Pointer208{base: intT})
8207 t := c.Resolve("int")
8208 ip := c.IsPointer(t)
8209 _ = ip
8210 }
8211 `, func(ir string) {
8212 assert("208: NewChecker defined", strings.Contains(ir, "@main.NewChecker"))
8213 assert("208: Resolve defined", strings.Contains(ir, "@main.Checker.Resolve"))
8214 assert("208: IsPointer defined", strings.Contains(ir, "@main.Checker.IsPointer"))
8215 })
8216
8217 // Test 209: Full scanner pattern with rune processing
8218 test(209, `package main
8219 type Scanner struct {
8220 src []byte
8221 pos int32
8222 ch rune
8223 chw int32
8224 }
8225 func (s *Scanner) peek() rune {
8226 if s.pos >= int32(len(s.src)) {
8227 return -1
8228 }
8229 return rune(s.src[s.pos])
8230 }
8231 func (s *Scanner) next() {
8232 if s.pos >= int32(len(s.src)) {
8233 s.ch = -1
8234 s.chw = 0
8235 return
8236 }
8237 s.ch = rune(s.src[s.pos])
8238 s.chw = 1
8239 s.pos++
8240 }
8241 func (s *Scanner) skipSpace() {
8242 for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' || s.ch == '\r' {
8243 s.next()
8244 }
8245 }
8246 func isLetter(ch rune) bool {
8247 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'
8248 }
8249 func isDigit(ch rune) bool {
8250 return ch >= '0' && ch <= '9'
8251 }
8252 func (s *Scanner) scanIdent() string {
8253 start := s.pos - s.chw
8254 for isLetter(s.ch) || isDigit(s.ch) {
8255 s.next()
8256 }
8257 return string(s.src[start : s.pos-s.chw])
8258 }
8259 func (s *Scanner) scanNumber() string {
8260 start := s.pos - s.chw
8261 for isDigit(s.ch) {
8262 s.next()
8263 }
8264 return string(s.src[start : s.pos-s.chw])
8265 }
8266 func (s *Scanner) scanString() string {
8267 start := s.pos
8268 for s.ch != '"' && s.ch >= 0 {
8269 s.next()
8270 }
8271 val := string(s.src[start : s.pos-s.chw])
8272 if s.ch == '"' {
8273 s.next()
8274 }
8275 return val
8276 }
8277 type TokenKind int32
8278 const (
8279 TokEOF TokenKind = iota
8280 TokIdent
8281 TokNumber
8282 TokString
8283 TokPunct
8284 )
8285 type ScanToken struct {
8286 kind TokenKind
8287 value string
8288 }
8289 func (s *Scanner) scan() ScanToken {
8290 s.skipSpace()
8291 if s.ch < 0 {
8292 return ScanToken{kind: TokEOF}
8293 }
8294 if isLetter(s.ch) {
8295 return ScanToken{kind: TokIdent, value: s.scanIdent()}
8296 }
8297 if isDigit(s.ch) {
8298 return ScanToken{kind: TokNumber, value: s.scanNumber()}
8299 }
8300 if s.ch == '"' {
8301 s.next()
8302 return ScanToken{kind: TokString, value: s.scanString()}
8303 }
8304 ch := string([]byte{byte(s.ch)})
8305 s.next()
8306 return ScanToken{kind: TokPunct, value: ch}
8307 }
8308 func main() {
8309 sc := &Scanner{src: []byte("hello 42 \"world\""), ch: ' '}
8310 sc.next()
8311 t1 := sc.scan()
8312 t2 := sc.scan()
8313 t3 := sc.scan()
8314 _ = t1
8315 _ = t2
8316 _ = t3
8317 }
8318 `, func(ir string) {
8319 assert("209: scan defined", strings.Contains(ir, "@main.Scanner.scan"))
8320 assert("209: scanIdent defined", strings.Contains(ir, "@main.Scanner.scanIdent"))
8321 assert("209: scanString defined", strings.Contains(ir, "@main.Scanner.scanString"))
8322 })
8323
8324 // Test 210a: Incremental - many types to reproduce void field bug
8325 test(2100, `package main
8326 type Type interface {
8327 Underlying() Type
8328 String() string
8329 }
8330 type BasicInfo int32
8331 type BasicKind int32
8332 type Basic struct {
8333 kind BasicKind
8334 info BasicInfo
8335 name string
8336 }
8337 func (b *Basic) Underlying() Type { return b }
8338 func (b *Basic) String() string { return b.name }
8339 type Slice struct{ elem Type }
8340 func (s *Slice) Underlying() Type { return s }
8341 func (s *Slice) String() string { return "[]" | s.elem.String() }
8342 func (s *Slice) Elem() Type { return s.elem }
8343 type Pointer struct{ base Type }
8344 func (p *Pointer) Underlying() Type { return p }
8345 func (p *Pointer) String() string { return "*" | p.base.String() }
8346 func (p *Pointer) Elem() Type { return p.base }
8347 type TCMap struct {
8348 key Type
8349 elem Type
8350 }
8351 func (m *TCMap) Underlying() Type { return m }
8352 func (m *TCMap) String() string { return "map" }
8353 type TCInterface struct {
8354 methods []string
8355 }
8356 func (t *TCInterface) Underlying() Type { return t }
8357 func (t *TCInterface) String() string { return "interface" }
8358 type Signature struct {
8359 recv *TCVar
8360 params *Tuple
8361 results *Tuple
8362 }
8363 func (s *Signature) Underlying() Type { return s }
8364 func (s *Signature) String() string { return "func" }
8365 type Named struct {
8366 name string
8367 under Type
8368 methods []*TCFunc
8369 }
8370 func (n *Named) Underlying() Type { return n.under }
8371 func (n *Named) String() string { return n.name }
8372 type Tuple struct{ vars []*TCVar }
8373 type Object interface {
8374 Name() string
8375 Type() Type
8376 Exported() bool
8377 }
8378 type object struct {
8379 name string
8380 typ Type
8381 }
8382 func (o *object) Name() string { return o.name }
8383 func (o *object) Type() Type { return o.typ }
8384 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
8385 type TypeName struct{ object }
8386 func NewTypeName(name string, typ Type) *TypeName {
8387 return &TypeName{object{name: name, typ: typ}}
8388 }
8389 type TCVar struct {
8390 name string
8391 typ Type
8392 }
8393 func (v *TCVar) Name() string { return v.name }
8394 func (v *TCVar) Type() Type { return v.typ }
8395 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
8396 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
8397 return &TCVar{name: name, typ: typ}
8398 }
8399 type TCFunc struct {
8400 object
8401 sig *Signature
8402 }
8403 type TCPackage struct {
8404 path string
8405 name string
8406 scope *Scope
8407 }
8408 func NewTCPackage(path string, name string) *TCPackage {
8409 return &TCPackage{path: path, name: name, scope: NewScope(nil)}
8410 }
8411 type Scope struct {
8412 parent *Scope
8413 elems map[string]Object
8414 }
8415 func NewScope(parent *Scope) *Scope {
8416 return &Scope{parent: parent, elems: map[string]Object{}}
8417 }
8418 func (s *Scope) Lookup(name string) Object {
8419 return s.elems[name]
8420 }
8421 func (s *Scope) Insert(obj Object) Object {
8422 nm := obj.Name()
8423 if alt, ok := s.elems[nm]; ok {
8424 return alt
8425 }
8426 s.elems[nm] = obj
8427 return nil
8428 }
8429 func (s *Scope) LookupParent(name string) (*Scope, Object) {
8430 for sc := s; sc != nil; sc = sc.parent {
8431 if obj, ok := sc.elems[name]; ok {
8432 return sc, obj
8433 }
8434 }
8435 return nil, nil
8436 }
8437 func (s *Scope) Names() []string {
8438 names := []string{:0:len(s.elems)}
8439 for n := range s.elems {
8440 names = append(names, n)
8441 }
8442 return names
8443 }
8444 func (p *TCPackage) Path() string { return p.path }
8445 func (p *TCPackage) Name() string { return p.name }
8446 func (p *TCPackage) Scope() *Scope { return p.scope }
8447 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
8448 type exprMode uint8
8449 const (
8450 modeInvalid exprMode = iota
8451 modeValue
8452 modeVar
8453 modeConst
8454 )
8455 type TypeAndValue struct {
8456 Typ Type
8457 mode exprMode
8458 }
8459 func (tv TypeAndValue) IsValue() bool { return tv.mode == modeValue || tv.mode == modeVar }
8460 func main() {
8461 b := &Basic{kind: 2, info: 2, name: "int"}
8462 pkg := NewTCPackage("main", "main")
8463 tn := NewTypeName("MyType", b)
8464 pkg.Scope().Insert(tn)
8465 f := NewTCField(pkg, "x", b, false)
8466 _ = f
8467 }
8468 `, func(ir string) {
8469 assert("210a: NewTypeName no void", !strings.Contains(ir, "void %typ"))
8470 assert("210a: NewTCField no void", !strings.Contains(ir, "void %typ"))
8471 })
8472
8473 // Test 210: Large concat - tc_types + tc_scope + tc_object + tc_info patterns
8474 src210 := []byte(`package main
8475 type Type interface {
8476 Underlying() Type
8477 String() string
8478 }
8479 type BasicInfo int32
8480 const (
8481 IsBoolean BasicInfo = 1 << iota
8482 IsInteger
8483 IsUnsigned
8484 IsFloat
8485 IsString210
8486 IsUntyped
8487 )
8488 type BasicKind int32
8489 type Basic struct {
8490 kind BasicKind
8491 info BasicInfo
8492 name string
8493 }
8494 func (b *Basic) Underlying() Type { return b }
8495 func (b *Basic) String() string { return b.name }
8496 func (b *Basic) Kind() BasicKind { return b.kind }
8497 func (b *Basic) Info() BasicInfo { return b.info }
8498 type Slice struct{ elem Type }
8499 func (s *Slice) Underlying() Type { return s }
8500 func (s *Slice) String() string { return "[]" | s.elem.String() }
8501 func (s *Slice) Elem() Type { return s.elem }
8502 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
8503 type Pointer struct{ base Type }
8504 func (p *Pointer) Underlying() Type { return p }
8505 func (p *Pointer) String() string { return "*" | p.base.String() }
8506 func (p *Pointer) Elem() Type { return p.base }
8507 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
8508 type TCMap struct {
8509 key Type
8510 elem Type
8511 }
8512 func (m *TCMap) Underlying() Type { return m }
8513 func (m *TCMap) String() string { return "map" }
8514 func (m *TCMap) Key() Type { return m.key }
8515 func (m *TCMap) Elem() Type { return m.elem }
8516 type TCInterface struct {
8517 methods []string
8518 }
8519 func (t *TCInterface) Underlying() Type { return t }
8520 func (t *TCInterface) String() string { return "interface" }
8521 func (t *TCInterface) NumMethods() int32 { return int32(len(t.methods)) }
8522 type Signature struct {
8523 recv *TCVar
8524 params *Tuple
8525 results *Tuple
8526 }
8527 func NewSignature(recv *TCVar, params *Tuple, results *Tuple) *Signature {
8528 return &Signature{recv: recv, params: params, results: results}
8529 }
8530 func (s *Signature) Underlying() Type { return s }
8531 func (s *Signature) String() string { return "func" }
8532 func (s *Signature) Recv() *TCVar { return s.recv }
8533 func (s *Signature) Params() *Tuple { return s.params }
8534 func (s *Signature) Results() *Tuple { return s.results }
8535 type Named struct {
8536 name string
8537 under Type
8538 methods []*TCFunc
8539 }
8540 func (n *Named) Underlying() Type { return n.under }
8541 func (n *Named) String() string { return n.name }
8542 func (n *Named) NumMethods() int32 { return int32(len(n.methods)) }
8543 func (n *Named) Method(i int32) *TCFunc { return n.methods[i] }
8544 func (n *Named) AddMethod(m *TCFunc) { n.methods = append(n.methods, m) }
8545 type Tuple struct{ vars []*TCVar }
8546 func NewTuple(vars []*TCVar) *Tuple { return &Tuple{vars: vars} }
8547 func (t *Tuple) Len() int32 { return int32(len(t.vars)) }
8548 func (t *Tuple) At(i int32) *TCVar { return t.vars[i] }
8549 type Object interface {
8550 Name() string
8551 Type() Type
8552 Pkg() *TCPackage
8553 Exported() bool
8554 }
8555 type object struct {
8556 pkg *TCPackage
8557 name string
8558 typ Type
8559 }
8560 func (o *object) Name() string { return o.name }
8561 func (o *object) Type() Type { return o.typ }
8562 func (o *object) Pkg() *TCPackage { return o.pkg }
8563 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
8564 type TypeName struct{ object }
8565 func NewTypeName(pkg *TCPackage, name string, typ Type) *TypeName {
8566 return &TypeName{object{pkg: pkg, name: name, typ: typ}}
8567 }
8568 type TCVar struct {
8569 pkg *TCPackage
8570 name string
8571 typ Type
8572 anonymous bool
8573 }
8574 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
8575 return &TCVar{pkg: pkg, name: name, typ: typ, anonymous: anonymous}
8576 }
8577 func (v *TCVar) Name() string { return v.name }
8578 func (v *TCVar) Type() Type { return v.typ }
8579 func (v *TCVar) Pkg() *TCPackage { return v.pkg }
8580 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
8581 func (v *TCVar) Anonymous() bool { return v.anonymous }
8582 type TCFunc struct {
8583 object
8584 sig *Signature
8585 }
8586 func (f *TCFunc) Signature() *Signature { return f.sig }
8587 type TCPackage struct {
8588 path string
8589 name string
8590 scope *Scope
8591 imports []*TCPackage
8592 complete bool
8593 }
8594 func NewTCPackage(path string, name string) *TCPackage {
8595 return &TCPackage{
8596 path: path,
8597 name: name,
8598 scope: NewScope(nil),
8599 }
8600 }
8601 func (p *TCPackage) Path() string { return p.path }
8602 func (p *TCPackage) Name() string { return p.name }
8603 func (p *TCPackage) Scope() *Scope { return p.scope }
8604 func (p *TCPackage) Complete() bool { return p.complete }
8605 func (p *TCPackage) MarkComplete() { p.complete = true }
8606 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
8607 func (p *TCPackage) Imports() []*TCPackage { return p.imports }
8608 type Scope struct {
8609 parent *Scope
8610 children []*Scope
8611 elems map[string]Object
8612 }
8613 func NewScope(parent *Scope) *Scope {
8614 return &Scope{parent: parent, elems: map[string]Object{}}
8615 }
8616 func (s *Scope) Parent() *Scope { return s.parent }
8617 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
8618 func (s *Scope) Lookup(name string) Object {
8619 return s.elems[name]
8620 }
8621 func (s *Scope) LookupParent(name string) (*Scope, Object) {
8622 for sc := s; sc != nil; sc = sc.parent {
8623 if obj, ok := sc.elems[name]; ok {
8624 return sc, obj
8625 }
8626 }
8627 return nil, nil
8628 }
8629 func (s *Scope) Insert(obj Object) Object {
8630 name := obj.Name()
8631 if alt, ok := s.elems[name]; ok {
8632 return alt
8633 }
8634 s.elems[name] = obj
8635 return nil
8636 }
8637 func (s *Scope) Names() []string {
8638 names := []string{:0:len(s.elems)}
8639 for n := range s.elems {
8640 names = append(names, n)
8641 }
8642 return names
8643 }
8644 type exprMode uint8
8645 const (
8646 modeInvalid exprMode = iota
8647 modeValue
8648 modeVar
8649 modeConst
8650 modeType
8651 )
8652 type TypeAndValue struct {
8653 Typ Type
8654 mode exprMode
8655 }
8656 func (tv TypeAndValue) IsValue() bool { return tv.mode == modeValue || tv.mode == modeVar }
8657 func (tv TypeAndValue) IsConst() bool { return tv.mode == modeConst }
8658 func main() {
8659 intT := &Basic{kind: 2, info: IsInteger, name: "int"}
8660 strT := &Basic{kind: 17, info: IsString210, name: "string"}
8661 sliceInt := NewSlice(intT)
8662 ptrInt := NewPointer(intT)
8663 pkg := NewTCPackage("main", "main")
8664 scope := pkg.Scope()
8665 tn := NewTypeName(pkg, "MyType", intT)
8666 scope.Insert(tn)
8667 field := NewTCField(pkg, "x", intT, false)
8668 sig := NewSignature(nil, NewTuple([]*TCVar{field}), NewTuple([]*TCVar{NewTCField(nil, "", strT, false)}))
8669 named := &Named{name: "MyStruct", under: intT}
8670 named.AddMethod(&TCFunc{object: object{pkg: pkg, name: "String", typ: sig}, sig: sig})
8671 _, obj := scope.LookupParent("MyType")
8672 if obj != nil {
8673 n := obj.Name()
8674 _ = n
8675 }
8676 s1 := sliceInt.String()
8677 s2 := ptrInt.String()
8678 nm := named.NumMethods()
8679 m0 := named.Method(0)
8680 ms := m0.Signature()
8681 _ = s1
8682 _ = s2
8683 _ = nm
8684 _ = ms
8685 tv := TypeAndValue{Typ: intT, mode: modeValue}
8686 isVal := tv.IsValue()
8687 _ = isVal
8688 }
8689 `)
8690 name210 := []byte("main")
8691 h210 := compileToIR(
8692 uintptr(unsafe.Pointer(&src210[0])), int32(len(src210)),
8693 uintptr(unsafe.Pointer(&name210[0])), int32(len(name210)),
8694 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
8695 )
8696 ir210 := getIR(h210)
8697 if ir210 == "" {
8698 assert("210: full type system concat produces IR", false)
8699 } else {
8700 assert("210: has NewTCPackage", strings.Contains(ir210, "@main.NewTCPackage"))
8701 assert("210: has Scope.LookupParent", strings.Contains(ir210, "@main.Scope.LookupParent"))
8702 assert("210: has TypeAndValue.IsValue", strings.Contains(ir210, "@main.TypeAndValue.IsValue"))
8703 assert("210: no parse error", !strings.Contains(ir210, "parse error"))
8704 voidFieldCount := strings.Count(ir210, "void %typ")
8705 fmt.Println("=== Full type system concat ===")
8706 fmt.Printf("IR size: %d bytes, functions: ~%d, void fields: %d (known issue)\n", len(ir210),
8707 strings.Count(ir210, "\ndefine "), voidFieldCount)
8708 }
8709 irFree(h210)
8710
8711 // Test 211: Variadic function - definition + call
8712 test(211, `package main
8713
8714 func sum(nums ...int32) int32 {
8715 total := int32(0)
8716 for _, n := range nums {
8717 total = total + n
8718 }
8719 return total
8720 }
8721
8722 func main() {
8723 s := sum(1, 2, 3)
8724 _ = s
8725 }
8726 `, func(ir string) {
8727 assert("211: has sum", strings.Contains(ir, "@main.sum"))
8728 assert("211: sum takes slice", strings.Contains(ir, "define i32 @main.sum({ptr, i64, i64} %nums"))
8729 assert("211: makeslice len 3", strings.Contains(ir, "sext i32 3 to i64"))
8730 assert("211: call passes slice", strings.Contains(ir, "call i32 @main.sum({ptr, i64, i64}"))
8731 })
8732
8733 // Test 213: Variadic call with zero args
8734 test(213, `package main
8735
8736 func sum(nums ...int32) int32 {
8737 return int32(0)
8738 }
8739
8740 func main() {
8741 s := sum()
8742 _ = s
8743 }
8744 `, func(ir string) {
8745 assert("213: has sum", strings.Contains(ir, "@main.sum"))
8746 assert("213: nil slice arg", strings.Contains(ir, "call i32 @main.sum({ptr, i64, i64} zeroinitializer"))
8747 })
8748
8749 // Test 214: Variadic with fixed args
8750 test(214, `package main
8751
8752 func printf(format string, args ...int32) int32 {
8753 return int32(0)
8754 }
8755
8756 func main() {
8757 s := printf("hello", 1, 2)
8758 _ = s
8759 }
8760 `, func(ir string) {
8761 assert("214: has printf", strings.Contains(ir, "@main.printf"))
8762 assert("214: takes string then slice", strings.Contains(ir, "define i32 @main.printf({ptr, i64, i64} %format, {ptr, i64, i64} %args"))
8763 })
8764
8765 // Test 215: String building with | operator, method chains
8766 test(215, `package main
8767
8768 type Builder struct {
8769 buf []byte
8770 }
8771
8772 func (b *Builder) write(s string) {
8773 b.buf = b.buf | []byte(s)
8774 }
8775
8776 func (b *Builder) writeInt(n int32) {
8777 if n == 0 {
8778 b.buf = append(b.buf, byte('0'))
8779 return
8780 }
8781 tmp := []byte{:0:10}
8782 for n > 0 {
8783 tmp = append(tmp, byte('0' + n % 10))
8784 n = n / 10
8785 }
8786 for i := len(tmp) - 1; i >= 0; i = i - 1 {
8787 b.buf = append(b.buf, tmp[i])
8788 }
8789 }
8790
8791 func (b *Builder) String() string {
8792 return string(b.buf)
8793 }
8794
8795 func main() {
8796 b := &Builder{buf: []byte{:0:64}}
8797 b.write("hello")
8798 b.write(" ")
8799 b.write("world")
8800 b.writeInt(42)
8801 s := b.String()
8802 _ = s
8803 }
8804 `, func(ir string) {
8805 assert("215: has Builder.write", strings.Contains(ir, "@main.Builder.write"))
8806 assert("215: has Builder.writeInt", strings.Contains(ir, "@main.Builder.writeInt"))
8807 assert("215: has Builder.String", strings.Contains(ir, "@main.Builder.String"))
8808 assert("215: uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
8809 })
8810
8811 // Test 216: Type switch with multiple cases
8812 test(216, `package main
8813
8814 type Node interface {
8815 Kind() int32
8816 }
8817
8818 type Literal struct {
8819 val int32
8820 }
8821 func (l *Literal) Kind() int32 { return 1 }
8822
8823 type BinOp struct {
8824 op int32
8825 lhs Node
8826 rhs Node
8827 }
8828 func (b *BinOp) Kind() int32 { return 2 }
8829
8830 type UnaryOp struct {
8831 op int32
8832 operand Node
8833 }
8834 func (u *UnaryOp) Kind() int32 { return 3 }
8835
8836 func eval(n Node) int32 {
8837 switch v := n.(type) {
8838 case *Literal:
8839 return v.val
8840 case *BinOp:
8841 l := eval(v.lhs)
8842 r := eval(v.rhs)
8843 if v.op == 1 {
8844 return l + r
8845 }
8846 return l - r
8847 case *UnaryOp:
8848 x := eval(v.operand)
8849 return -x
8850 }
8851 return 0
8852 }
8853
8854 func main() {
8855 a := &Literal{val: 10}
8856 b := &Literal{val: 3}
8857 sum := &BinOp{op: 1, lhs: a, rhs: b}
8858 neg := &UnaryOp{op: 1, operand: a}
8859 r1 := eval(sum)
8860 r2 := eval(neg)
8861 _ = r1
8862 _ = r2
8863 }
8864 `, func(ir string) {
8865 assert("216: has eval", strings.Contains(ir, "@main.eval"))
8866 assert("216: type switch has typeid", strings.Contains(ir, "typeid"))
8867 assert("216: recursive call", strings.Count(ir, "call i32 @main.eval") >= 2)
8868 })
8869
8870 // Test 217: Map with string keys, comma-ok lookup, delete
8871 test(217, `package main
8872
8873 func lookup(m map[string]int32, key string) (int32, bool) {
8874 v, ok := m[key]
8875 return v, ok
8876 }
8877
8878 func main() {
8879 m := map[string]int32{}
8880 m["hello"] = 1
8881 m["world"] = 2
8882 v, ok := lookup(m, "hello")
8883 _ = v
8884 _ = ok
8885 delete(m, "world")
8886 n := len(m)
8887 _ = n
8888 }
8889 `, func(ir string) {
8890 assert("217: has lookup", strings.Contains(ir, "@main.lookup"))
8891 assert("217: map make", strings.Contains(ir, "hashmapMake"))
8892 assert("217: map update", strings.Contains(ir, "hashmapContentSet"))
8893 assert("217: map delete", strings.Contains(ir, "hashmapDelete") || strings.Contains(ir, "hashmapBinaryDelete"))
8894 })
8895
8896 // Test 218: Function value as variable, call through variable
8897 test(218, `package main
8898
8899 type Transformer func(int32) int32
8900
8901 func apply(f Transformer, x int32) int32 {
8902 return f(x)
8903 }
8904
8905 func double(x int32) int32 {
8906 return x + x
8907 }
8908
8909 func main() {
8910 var f Transformer
8911 f = double
8912 r := apply(f, 5)
8913 _ = r
8914 }
8915 `, func(ir string) {
8916 assert("218: has apply", strings.Contains(ir, "@main.apply"))
8917 assert("218: has double", strings.Contains(ir, "@main.double"))
8918 assert("218: indirect call", strings.Contains(ir, "call i32 %"))
8919 })
8920
8921 // Test 219: Multi-value return with type assertion comma-ok
8922 test(219, `package main
8923
8924 type Value interface {
8925 String() string
8926 }
8927
8928 type IntVal struct {
8929 v int32
8930 }
8931 func (i *IntVal) String() string { return "int" }
8932
8933 func asInt(v Value) (*IntVal, bool) {
8934 i, ok := v.(*IntVal)
8935 return i, ok
8936 }
8937
8938 func main() {
8939 var v Value
8940 v = &IntVal{v: 42}
8941 i, ok := asInt(v)
8942 _ = i
8943 _ = ok
8944 }
8945 `, func(ir string) {
8946 assert("219: has asInt", strings.Contains(ir, "@main.asInt"))
8947 assert("219: type assert", strings.Contains(ir, "typeid") || strings.Contains(ir, "icmp"))
8948 })
8949
8950 // Test 220: Const block with iota, string concat in method
8951 test(220, `package main
8952
8953 const (
8954 KindA = iota
8955 KindB
8956 KindC
8957 )
8958
8959 type Item struct {
8960 kind int32
8961 name string
8962 }
8963
8964 func (it *Item) Label() string {
8965 prefix := "item:"
8966 return prefix | it.name
8967 }
8968
8969 func kindName(k int32) string {
8970 switch k {
8971 case KindA:
8972 return "A"
8973 case KindB:
8974 return "B"
8975 case KindC:
8976 return "C"
8977 }
8978 return "?"
8979 }
8980
8981 func main() {
8982 it := &Item{kind: KindB, name: "test"}
8983 s := it.Label()
8984 n := kindName(KindC)
8985 _ = s
8986 _ = n
8987 }
8988 `, func(ir string) {
8989 assert("220: has Item.Label", strings.Contains(ir, "@main.Item.Label"))
8990 assert("220: has kindName", strings.Contains(ir, "@main.kindName"))
8991 assert("220: string concat uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
8992 assert("220: switch has icmp", strings.Contains(ir, "icmp eq"))
8993 })
8994
8995 // Test 221: Mini IR emitter - exercises self-compilation patterns
8996 test221src := []byte(`package main
8997
8998 type Type interface {
8999 Kind() int32
9000 LLVMType() string
9001 }
9002
9003 type BasicType struct {
9004 kind int32
9005 name string
9006 llvm string
9007 }
9008 func (b *BasicType) Kind() int32 { return b.kind }
9009 func (b *BasicType) LLVMType() string { return b.llvm }
9010
9011 type PtrType struct {
9012 elem Type
9013 }
9014 func (p *PtrType) Kind() int32 { return 4 }
9015 func (p *PtrType) LLVMType() string { return "ptr" }
9016
9017 type SliceType struct {
9018 elem Type
9019 }
9020 func (s *SliceType) Kind() int32 { return 5 }
9021 func (s *SliceType) LLVMType() string { return "{ptr, i64, i64}" }
9022
9023 type FuncSig struct {
9024 params []Type
9025 results []Type
9026 }
9027 func (f *FuncSig) Kind() int32 { return 6 }
9028 func (f *FuncSig) LLVMType() string { return "ptr" }
9029
9030 type Emitter struct {
9031 buf []byte
9032 nextReg int32
9033 types map[string]Type
9034 }
9035
9036 func NewEmitter() *Emitter {
9037 e := &Emitter{
9038 buf: []byte{:0:256},
9039 types: map[string]Type{},
9040 }
9041 e.types["int32"] = &BasicType{kind: 1, name: "int32", llvm: "i32"}
9042 e.types["string"] = &BasicType{kind: 14, name: "string", llvm: "{ptr, i64, i64}"}
9043 return e
9044 }
9045
9046 func (e *Emitter) w(s string) {
9047 e.buf = e.buf | []byte(s)
9048 }
9049
9050 func (e *Emitter) nextName() string {
9051 e.nextReg = e.nextReg + 1
9052 return "%t" | itoa(e.nextReg)
9053 }
9054
9055 func itoa(n int32) string {
9056 if n == 0 { return "0" }
9057 buf := []byte{:0:10}
9058 for n > 0 {
9059 buf = append(buf, byte('0' + n % 10))
9060 n = n / 10
9061 }
9062 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
9063 buf[i], buf[j] = buf[j], buf[i]
9064 }
9065 return string(buf)
9066 }
9067
9068 func (e *Emitter) emitType(t Type) string {
9069 switch v := t.(type) {
9070 case *BasicType:
9071 return v.llvm
9072 case *PtrType:
9073 return "ptr"
9074 case *SliceType:
9075 return "{ptr, i64, i64}"
9076 case *FuncSig:
9077 return e.emitFuncType(v)
9078 }
9079 return "void"
9080 }
9081
9082 func (e *Emitter) emitFuncType(f *FuncSig) string {
9083 result := "void"
9084 if len(f.results) > 0 {
9085 result = e.emitType(f.results[0])
9086 }
9087 s := result | " ("
9088 for i, p := range f.params {
9089 if i > 0 {
9090 s = s | ", "
9091 }
9092 s = s | e.emitType(p)
9093 }
9094 s = s | ")"
9095 return s
9096 }
9097
9098 func (e *Emitter) emitAlloc(t Type) string {
9099 name := e.nextName()
9100 e.w(" " | name | " = alloca " | e.emitType(t) | "\n")
9101 return name
9102 }
9103
9104 func (e *Emitter) emitStore(addr string, val string, t Type) {
9105 e.w(" store " | e.emitType(t) | " " | val | ", ptr " | addr | "\n")
9106 }
9107
9108 func (e *Emitter) emitLoad(addr string, t Type) string {
9109 name := e.nextName()
9110 e.w(" " | name | " = load " | e.emitType(t) | ", ptr " | addr | "\n")
9111 return name
9112 }
9113
9114 func (e *Emitter) lookupType(name string) (Type, bool) {
9115 t, ok := e.types[name]
9116 return t, ok
9117 }
9118
9119 func (e *Emitter) Result() string {
9120 return string(e.buf)
9121 }
9122
9123 func main() {
9124 em := NewEmitter()
9125 intT, _ := em.lookupType("int32")
9126 strT, _ := em.lookupType("string")
9127
9128 sig := &FuncSig{
9129 params: []Type{intT, strT},
9130 results: []Type{intT},
9131 }
9132
9133 em.w("define " | em.emitFuncType(sig) | " @main.add(")
9134 em.w(em.emitType(intT) | " %a, ")
9135 em.w(em.emitType(strT) | " %b) {\n")
9136 em.w("entry:\n")
9137 a1 := em.emitAlloc(intT)
9138 em.emitStore(a1, "%a", intT)
9139 v1 := em.emitLoad(a1, intT)
9140 _ = v1
9141 em.w(" ret " | em.emitType(intT) | " " | v1 | "\n")
9142 em.w("}\n")
9143
9144 ir := em.Result()
9145 _ = ir
9146 }
9147 `)
9148 name221 := []byte("main")
9149 h221 := compileToIR(
9150 uintptr(unsafe.Pointer(&test221src[0])), int32(len(test221src)),
9151 uintptr(unsafe.Pointer(&name221[0])), int32(len(name221)),
9152 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
9153 )
9154 ir221 := getIR(h221)
9155 if ir221 == "" {
9156 assert("221: mini emitter produces IR", false)
9157 } else {
9158 voidCount := strings.Count(ir221, "void %")
9159 funcCount := strings.Count(ir221, "\ndefine ")
9160 lineCount := strings.Count(string(test221src), "\n")
9161 fmt.Printf("=== Mini emitter test (221) ===\n")
9162 fmt.Printf("Source: %d lines, %d bytes | IR: %d bytes, %d functions, void fields: %d\n",
9163 lineCount, len(test221src), len(ir221), funcCount, voidCount)
9164 assert("221: produces IR", len(ir221) > 1000)
9165 assert("221: zero void fields", voidCount == 0)
9166 assert("221: has NewEmitter", strings.Contains(ir221, "@main.NewEmitter"))
9167 assert("221: has emitType", strings.Contains(ir221, "@main.Emitter.emitType"))
9168 assert("221: has emitFuncType", strings.Contains(ir221, "@main.Emitter.emitFuncType"))
9169 assert("221: has itoa", strings.Contains(ir221, "@main.itoa"))
9170 assert("221: has lookupType", strings.Contains(ir221, "@main.Emitter.lookupType"))
9171 assert("221: type switch typeid", strings.Contains(ir221, "typeid"))
9172 assert("221: uses sliceAppend", strings.Contains(ir221, "@runtime.sliceAppend"))
9173 assert("221: uses hashmapMake", strings.Contains(ir221, "@runtime.hashmapMake"))
9174 llvmVerify("221: mini emitter", ir221)
9175 }
9176 irFree(h221)
9177
9178 // Test 222: Scope/Object hierarchy - mirrors tc_scope.mx, tc_object.mx patterns
9179 test(222, `package main
9180
9181 type Object interface {
9182 Name() string
9183 Type() Type
9184 }
9185
9186 type Type interface {
9187 Underlying() Type
9188 String() string
9189 }
9190
9191 type Scope struct {
9192 parent *Scope
9193 entries map[string]Object
9194 }
9195
9196 func NewScope(parent *Scope) *Scope {
9197 return &Scope{parent: parent, entries: map[string]Object{}}
9198 }
9199
9200 func (s *Scope) Insert(obj Object) Object {
9201 name := obj.Name()
9202 old, ok := s.entries[name]
9203 if ok {
9204 return old
9205 }
9206 s.entries[name] = obj
9207 return nil
9208 }
9209
9210 func (s *Scope) Lookup(name string) Object {
9211 obj, ok := s.entries[name]
9212 if ok {
9213 return obj
9214 }
9215 if s.parent != nil {
9216 return s.parent.Lookup(name)
9217 }
9218 return nil
9219 }
9220
9221 func (s *Scope) Len() int32 {
9222 return int32(len(s.entries))
9223 }
9224
9225 type BasicType struct {
9226 kind int32
9227 name string
9228 }
9229 func (b *BasicType) Underlying() Type { return b }
9230 func (b *BasicType) String() string { return b.name }
9231
9232 type PointerType struct {
9233 base Type
9234 }
9235 func (p *PointerType) Underlying() Type { return p }
9236 func (p *PointerType) String() string { return "*" | p.base.String() }
9237
9238 type TypeName struct {
9239 name string
9240 typ Type
9241 }
9242 func (t *TypeName) Name() string { return t.name }
9243 func (t *TypeName) Type() Type { return t.typ }
9244
9245 type Var struct {
9246 name string
9247 typ Type
9248 }
9249 func (v *Var) Name() string { return v.name }
9250 func (v *Var) Type() Type { return v.typ }
9251
9252 type Func struct {
9253 name string
9254 typ Type
9255 }
9256 func (f *Func) Name() string { return f.name }
9257 func (f *Func) Type() Type { return f.typ }
9258
9259 type Checker struct {
9260 pkg *Package
9261 scope *Scope
9262 }
9263
9264 type Package struct {
9265 name string
9266 scope *Scope
9267 }
9268
9269 func NewChecker(pkg *Package) *Checker {
9270 return &Checker{pkg: pkg, scope: pkg.scope}
9271 }
9272
9273 func (c *Checker) lookup(name string) Object {
9274 return c.scope.Lookup(name)
9275 }
9276
9277 func (c *Checker) resolveTypeName(name string) Type {
9278 obj := c.lookup(name)
9279 if obj == nil {
9280 return nil
9281 }
9282 tn, ok := obj.(*TypeName)
9283 if !ok {
9284 return nil
9285 }
9286 return tn.typ
9287 }
9288
9289 func main() {
9290 universe := NewScope(nil)
9291 intT := &BasicType{kind: 2, name: "int32"}
9292 strT := &BasicType{kind: 14, name: "string"}
9293 boolT := &BasicType{kind: 1, name: "bool"}
9294
9295 universe.Insert(&TypeName{name: "int32", typ: intT})
9296 universe.Insert(&TypeName{name: "string", typ: strT})
9297 universe.Insert(&TypeName{name: "bool", typ: boolT})
9298
9299 pkgScope := NewScope(universe)
9300 pkg := &Package{name: "main", scope: pkgScope}
9301
9302 ptrInt := &PointerType{base: intT}
9303 pkgScope.Insert(&TypeName{name: "PtrInt", typ: ptrInt})
9304 pkgScope.Insert(&Var{name: "x", typ: intT})
9305 pkgScope.Insert(&Func{name: "foo", typ: nil})
9306
9307 chk := NewChecker(pkg)
9308
9309 t1 := chk.resolveTypeName("int32")
9310 t2 := chk.resolveTypeName("PtrInt")
9311 t3 := chk.resolveTypeName("missing")
9312 _ = t1
9313 _ = t2
9314 _ = t3
9315
9316 n := pkgScope.Len()
9317 _ = n
9318
9319 s1 := intT.String()
9320 s2 := ptrInt.String()
9321 _ = s1
9322 _ = s2
9323 }
9324 `, func(ir string) {
9325 assert("222: has NewScope", strings.Contains(ir, "@main.NewScope"))
9326 assert("222: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
9327 assert("222: has Scope.Insert", strings.Contains(ir, "@main.Scope.Insert"))
9328 assert("222: has NewChecker", strings.Contains(ir, "@main.NewChecker"))
9329 assert("222: has resolveTypeName", strings.Contains(ir, "@main.Checker.resolveTypeName"))
9330 assert("222: recursive lookup", strings.Contains(ir, "call {ptr, ptr} @main.Scope.Lookup"))
9331 assert("222: type assert typeid", strings.Contains(ir, "typeid"))
9332 assert("222: map operations", strings.Contains(ir, "hashmapMake"))
9333 })
9334
9335 // Test 223: Multi-value assign (tuple swap), array literal, byte operations
9336 test(223, `package main
9337
9338 func swap(a []int32) {
9339 if len(a) >= 2 {
9340 a[0], a[1] = a[1], a[0]
9341 }
9342 }
9343
9344 func reverseBytes(s string) string {
9345 b := []byte(s)
9346 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
9347 b[i], b[j] = b[j], b[i]
9348 }
9349 return string(b)
9350 }
9351
9352 func countChar(s string, c byte) int32 {
9353 n := int32(0)
9354 for i := 0; i < len(s); i = i + 1 {
9355 if s[i] == c {
9356 n = n + 1
9357 }
9358 }
9359 return n
9360 }
9361
9362 func main() {
9363 a := []int32{10, 20, 30}
9364 swap(a)
9365 s := reverseBytes("hello")
9366 n := countChar("banana", byte('a'))
9367 _ = s
9368 _ = n
9369 }
9370 `, func(ir string) {
9371 assert("223: has swap", strings.Contains(ir, "@main.swap"))
9372 assert("223: has reverseBytes", strings.Contains(ir, "@main.reverseBytes"))
9373 assert("223: has countChar", strings.Contains(ir, "@main.countChar"))
9374 })
9375
9376 // Test 224: Nested method calls, chained returns, early returns in switch
9377 test(224, `package main
9378
9379 type Node interface {
9380 Emit(buf *Buffer)
9381 }
9382
9383 type Buffer struct {
9384 data []byte
9385 }
9386
9387 func NewBuffer() *Buffer {
9388 return &Buffer{data: []byte{:0:64}}
9389 }
9390
9391 func (b *Buffer) Write(s string) {
9392 b.data = b.data | []byte(s)
9393 }
9394
9395 func (b *Buffer) WriteByte(c byte) {
9396 b.data = append(b.data, c)
9397 }
9398
9399 func (b *Buffer) String() string {
9400 return string(b.data)
9401 }
9402
9403 func (b *Buffer) Len() int32 {
9404 return int32(len(b.data))
9405 }
9406
9407 type IntNode struct {
9408 val int32
9409 }
9410
9411 func (n *IntNode) Emit(buf *Buffer) {
9412 if n.val == 0 {
9413 buf.Write("0")
9414 return
9415 }
9416 v := n.val
9417 tmp := []byte{:0:10}
9418 for v > 0 {
9419 tmp = append(tmp, byte('0' + v % 10))
9420 v = v / 10
9421 }
9422 for i, j := 0, len(tmp)-1; i < j; i, j = i+1, j-1 {
9423 tmp[i], tmp[j] = tmp[j], tmp[i]
9424 }
9425 buf.Write(string(tmp))
9426 }
9427
9428 type StrNode struct {
9429 val string
9430 }
9431
9432 func (n *StrNode) Emit(buf *Buffer) {
9433 buf.WriteByte(byte('"'))
9434 buf.Write(n.val)
9435 buf.WriteByte(byte('"'))
9436 }
9437
9438 type BinNode struct {
9439 op string
9440 lhs Node
9441 rhs Node
9442 }
9443
9444 func (n *BinNode) Emit(buf *Buffer) {
9445 buf.WriteByte(byte('('))
9446 n.lhs.Emit(buf)
9447 buf.Write(" " | n.op | " ")
9448 n.rhs.Emit(buf)
9449 buf.WriteByte(byte(')'))
9450 }
9451
9452 func main() {
9453 buf := NewBuffer()
9454 expr := &BinNode{
9455 op: "+",
9456 lhs: &IntNode{val: 42},
9457 rhs: &BinNode{
9458 op: "*",
9459 lhs: &IntNode{val: 3},
9460 rhs: &StrNode{val: "x"},
9461 },
9462 }
9463 expr.Emit(buf)
9464 result := buf.String()
9465 n := buf.Len()
9466 _ = result
9467 _ = n
9468 }
9469 `, func(ir string) {
9470 assert("224: has Buffer.Write", strings.Contains(ir, "@main.Buffer.Write"))
9471 assert("224: has IntNode.Emit", strings.Contains(ir, "@main.IntNode.Emit"))
9472 assert("224: has BinNode.Emit", strings.Contains(ir, "@main.BinNode.Emit"))
9473 assert("224: interface dispatch", strings.Contains(ir, "typeid"))
9474 assert("224: uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
9475 })
9476
9477 // Test 225: Byte indexing, tagless switch
9478 test(225, `package main
9479
9480 func isExported(name string) bool {
9481 if len(name) == 0 {
9482 return false
9483 }
9484 c := name[0]
9485 if c >= 65 && c <= 90 {
9486 return true
9487 }
9488 return false
9489 }
9490
9491 func classify(x int32) string {
9492 switch {
9493 case x < 0:
9494 return "negative"
9495 case x == 0:
9496 return "zero"
9497 case x > 100:
9498 return "large"
9499 }
9500 return "small"
9501 }
9502
9503 func main() {
9504 e1 := isExported("Hello")
9505 e2 := isExported("hello")
9506 _ = e1
9507 _ = e2
9508 c1 := classify(-1)
9509 c2 := classify(0)
9510 c3 := classify(200)
9511 c4 := classify(50)
9512 _ = c1
9513 _ = c2
9514 _ = c3
9515 _ = c4
9516 }
9517 `, func(ir string) {
9518 assert("225: has isExported", strings.Contains(ir, "@main.isExported"))
9519 assert("225: has classify", strings.Contains(ir, "@main.classify"))
9520 })
9521
9522 // Test 226: Named return values, multi-return with named results
9523 test(226, `package main
9524
9525 func divide(a int32, b int32) (q int32, r int32) {
9526 if b == 0 {
9527 return 0, 0
9528 }
9529 q = a / b
9530 r = a - q*b
9531 return q, r
9532 }
9533
9534 func main() {
9535 q, r := divide(17, 5)
9536 _ = q
9537 _ = r
9538 }
9539 `, func(ir string) {
9540 assert("226: has divide", strings.Contains(ir, "@main.divide"))
9541 assert("226: divide returns tuple", strings.Contains(ir, "define {i32, i32} @main.divide"))
9542 })
9543
9544 // Test 227: For-range over map, delete from map
9545 test(227, `package main
9546
9547 func countEntries(m map[string]int32) int32 {
9548 n := int32(0)
9549 for range m {
9550 n = n + 1
9551 }
9552 return n
9553 }
9554
9555 func removeKey(m map[string]int32, key string) {
9556 delete(m, key)
9557 }
9558
9559 func main() {
9560 m := map[string]int32{"a": 1, "b": 2, "c": 3}
9561 n := countEntries(m)
9562 _ = n
9563 removeKey(m, "b")
9564 }
9565 `, func(ir string) {
9566 assert("227: has countEntries", strings.Contains(ir, "@main.countEntries"))
9567 assert("227: has removeKey", strings.Contains(ir, "@main.removeKey"))
9568 assert("227: hashmapNext for range", strings.Contains(ir, "hashmapNext"))
9569 assert("227: hashmapBinaryDelete", strings.Contains(ir, "hashmapBinaryDelete"))
9570 })
9571
9572 // Test 228: Multi-level struct embedding, promoted methods
9573 test(228, `package main
9574
9575 type base struct {
9576 name string
9577 }
9578
9579 func (b *base) Name() string { return b.name }
9580
9581 type TypeName struct {
9582 base
9583 typ int32
9584 }
9585
9586 func NewTypeName(name string, typ int32) *TypeName {
9587 return &TypeName{base: base{name: name}, typ: typ}
9588 }
9589
9590 func main() {
9591 tn := NewTypeName("int", 1)
9592 n := tn.Name()
9593 _ = n
9594 }
9595 `, func(ir string) {
9596 assert("228: has NewTypeName", strings.Contains(ir, "@main.NewTypeName"))
9597 assert("228: has base.Name", strings.Contains(ir, "@main.base.Name"))
9598 assert("228: promoted method call", strings.Contains(ir, "call") && strings.Contains(ir, "base.Name"))
9599 })
9600
9601 // Test 229: Simple append with spread
9602 test(229, `package main
9603
9604 func join(a []byte, b []byte) []byte {
9605 return append(a, b...)
9606 }
9607
9608 func main() {
9609 x := []byte("abc")
9610 y := []byte("def")
9611 z := join(x, y)
9612 _ = z
9613 }
9614 `, func(ir string) {
9615 assert("229: has join", strings.Contains(ir, "@main.join"))
9616 assert("229: sliceAppend for spread", strings.Contains(ir, "sliceAppend"))
9617 })
9618
9619 // Test 230: []byte(nil) conversion + spread append (self-compile pattern)
9620 test(230, `package main
9621
9622 func copyBytes(s []byte) []byte {
9623 return append([]byte(nil), s...)
9624 }
9625
9626 func main() {
9627 x := []byte("test")
9628 y := copyBytes(x)
9629 _ = y
9630 }
9631 `, func(ir string) {
9632 assert("230: has copyBytes", strings.Contains(ir, "@main.copyBytes"))
9633 })
9634
9635 // Test 231: String copy via append+spread (common bootstrap pattern)
9636 test(231, `package main
9637
9638 func copyString(s string) string {
9639 return string(append([]byte(nil), s...))
9640 }
9641
9642 func main() {
9643 s := copyString("hello")
9644 _ = s
9645 }
9646 `, func(ir string) {
9647 assert("231: has copyString", strings.Contains(ir, "@main.copyString"))
9648 })
9649
9650 // Test 232: Closures and function values
9651 test(232, `package main
9652
9653 func apply(f func(int32) int32, x int32) int32 {
9654 return f(x)
9655 }
9656
9657 func main() {
9658 double := func(x int32) int32 { return x * 2 }
9659 r := apply(double, 5)
9660 _ = r
9661 }
9662 `, func(ir string) {
9663 assert("232: has apply", strings.Contains(ir, "@main.apply"))
9664 })
9665
9666 // Test 233: Closure with capture (makeAdder pattern)
9667 test(233, `package main
9668
9669 func makeAdder(n int32) func(int32) int32 {
9670 return func(x int32) int32 {
9671 return x + n
9672 }
9673 }
9674
9675 func main() {
9676 add3 := makeAdder(3)
9677 r := add3(10)
9678 _ = r
9679 }
9680 `, func(ir string) {
9681 assert("233: has makeAdder", strings.Contains(ir, "@main.makeAdder"))
9682 })
9683
9684 // Test 234: Named return values with bare return
9685 test(234, `package main
9686
9687 func divide(a int32, b int32) (q int32, r int32) {
9688 if b == 0 {
9689 return
9690 }
9691 q = a / b
9692 r = a - q*b
9693 return
9694 }
9695
9696 func main() {
9697 q, r := divide(17, 5)
9698 _ = q
9699 _ = r
9700 q2, r2 := divide(5, 0)
9701 _ = q2
9702 _ = r2
9703 }
9704 `, func(ir string) {
9705 assert("234: has divide", strings.Contains(ir, "@main.divide"))
9706 assert("234: returns tuple", strings.Contains(ir, "define {i32, i32} @main.divide"))
9707 })
9708
9709 test(235, `package main
9710
9711 type Color int32
9712 const (
9713 Red Color = iota
9714 Green
9715 Blue
9716 )
9717
9718 func colorName(c Color) string {
9719 switch c {
9720 case Red:
9721 return "red"
9722 case Green:
9723 return "green"
9724 case Blue:
9725 return "blue"
9726 }
9727 return "unknown"
9728 }
9729
9730 func main() {
9731 n := colorName(Green)
9732 _ = n
9733 }
9734 `, func(ir string) {
9735 assert("235: has colorName", strings.Contains(ir, "@main.colorName"))
9736 assert("235: Red=0 in switch", strings.Contains(ir, "icmp eq i32 %t2, 0"))
9737 assert("235: Green=1 in switch", strings.Contains(ir, "icmp eq i32 %t2, 1"))
9738 assert("235: Blue=2 in switch", strings.Contains(ir, "icmp eq i32 %t2, 2"))
9739 })
9740
9741 test(236, `package main
9742
9743 type Op int32
9744 const (
9745 _ Op = iota
9746 Add
9747 Sub
9748 Mul
9749 Div
9750 )
9751
9752 func priority(op Op) int32 {
9753 switch op {
9754 case Add, Sub:
9755 return 1
9756 case Mul, Div:
9757 return 2
9758 }
9759 return 0
9760 }
9761
9762 func main() {
9763 p := priority(Mul)
9764 _ = p
9765 }
9766 `, func(ir string) {
9767 assert("236: has priority", strings.Contains(ir, "@main.priority"))
9768 assert("236: Add=1 (skip blank)", strings.Contains(ir, "i32 1") || strings.Contains(ir, "i32 2"))
9769 })
9770
9771 test(237, `package main
9772
9773 const (
9774 FlagA int32 = 1 << iota
9775 FlagB
9776 FlagC
9777 FlagD
9778 )
9779
9780 func hasFlag(flags int32, f int32) bool {
9781 return flags & f != 0
9782 }
9783
9784 func main() {
9785 flags := FlagA | FlagC
9786 a := hasFlag(flags, FlagA)
9787 b := hasFlag(flags, FlagB)
9788 _ = a
9789 _ = b
9790 }
9791 `, func(ir string) {
9792 assert("237: has hasFlag", strings.Contains(ir, "@main.hasFlag"))
9793 assert("237: has FlagA=1", strings.Contains(ir, "i32 1"))
9794 assert("237: has or op", strings.Contains(ir, " or "))
9795 assert("237: has and op", strings.Contains(ir, " and "))
9796 })
9797
9798 test(238, `package main
9799
9800 func greet(name string) string {
9801 return "hello, " | name | "!"
9802 }
9803
9804 func bits(a int32, b int32) int32 {
9805 return (a | b) & 0xFF
9806 }
9807
9808 func main() {
9809 s := greet("world")
9810 _ = s
9811 r := bits(3, 12)
9812 _ = r
9813 }
9814 `, func(ir string) {
9815 assert("238: has greet", strings.Contains(ir, "@main.greet"))
9816 assert("238: has bits", strings.Contains(ir, "@main.bits"))
9817 assert("238: string concat via sliceAppend", strings.Contains(ir, "runtime.sliceAppend"))
9818 assert("238: bitwise or in bits", strings.Contains(ir, " or "))
9819 assert("238: bitwise and in bits", strings.Contains(ir, " and "))
9820 })
9821
9822 test(239, `package main
9823
9824 type Pos struct {
9825 line int32
9826 col int32
9827 }
9828
9829 type Node struct {
9830 pos Pos
9831 kind int32
9832 }
9833
9834 func makeNode(line int32, col int32, kind int32) *Node {
9835 return &Node{pos: Pos{line: line, col: col}, kind: kind}
9836 }
9837
9838 func getLine(n *Node) int32 {
9839 return n.pos.line
9840 }
9841
9842 func main() {
9843 n := makeNode(10, 5, 1)
9844 l := getLine(n)
9845 _ = l
9846 }
9847 `, func(ir string) {
9848 assert("239: has makeNode", strings.Contains(ir, "@main.makeNode"))
9849 assert("239: has getLine", strings.Contains(ir, "@main.getLine"))
9850 assert("239: nested struct access", strings.Contains(ir, "getelementptr"))
9851 })
9852
9853 test(240, `package main
9854
9855 type Builder struct {
9856 buf []byte
9857 }
9858
9859 func (b *Builder) writeByte(c byte) {
9860 b.buf = append(b.buf, c)
9861 }
9862
9863 func (b *Builder) writeString(s string) {
9864 b.buf = append(b.buf, s...)
9865 }
9866
9867 func (b *Builder) String() string {
9868 return string(b.buf)
9869 }
9870
9871 func main() {
9872 b := &Builder{}
9873 b.writeByte('H')
9874 b.writeString("ello")
9875 s := b.String()
9876 _ = s
9877 }
9878 `, func(ir string) {
9879 assert("240: has Builder.writeByte", strings.Contains(ir, "@main.Builder.writeByte"))
9880 assert("240: has Builder.writeString", strings.Contains(ir, "@main.Builder.writeString"))
9881 assert("240: has Builder.String", strings.Contains(ir, "@main.Builder.String"))
9882 assert("240: append call", strings.Contains(ir, "runtime.sliceAppend"))
9883 })
9884
9885 test(241, `package main
9886
9887 var counter int32
9888
9889 func inc() int32 {
9890 counter++
9891 return counter
9892 }
9893
9894 func dec() int32 {
9895 counter--
9896 return counter
9897 }
9898
9899 func main() {
9900 a := inc()
9901 b := inc()
9902 c := dec()
9903 _ = a
9904 _ = b
9905 _ = c
9906 }
9907 `, func(ir string) {
9908 assert("241: has inc", strings.Contains(ir, "@main.inc"))
9909 assert("241: has dec", strings.Contains(ir, "@main.dec"))
9910 assert("241: has global counter", strings.Contains(ir, "@main.counter"))
9911 })
9912
9913 test(242, `package main
9914
9915 type Token int32
9916 const (
9917 EOF Token = iota
9918 Ident
9919 Number
9920 Plus
9921 Minus
9922 Star
9923 Slash
9924 Lparen
9925 Rparen
9926 )
9927
9928 func isOperator(t Token) bool {
9929 switch t {
9930 case Plus, Minus, Star, Slash:
9931 return true
9932 }
9933 return false
9934 }
9935
9936 func precedence(t Token) int32 {
9937 switch t {
9938 case Plus, Minus:
9939 return 1
9940 case Star, Slash:
9941 return 2
9942 }
9943 return 0
9944 }
9945
9946 func main() {
9947 t := Star
9948 op := isOperator(t)
9949 p := precedence(t)
9950 _ = op
9951 _ = p
9952 }
9953 `, func(ir string) {
9954 assert("242: has isOperator", strings.Contains(ir, "@main.isOperator"))
9955 assert("242: has precedence", strings.Contains(ir, "@main.precedence"))
9956 assert("242: multi-case switch", strings.Contains(ir, "icmp eq"))
9957 })
9958
9959 test(243, `package main
9960
9961 type Pair struct {
9962 key string
9963 value int32
9964 }
9965
9966 func lookup(pairs []Pair, key string) (int32, bool) {
9967 for i := 0; i < len(pairs); i++ {
9968 if pairs[i].key == key {
9969 return pairs[i].value, true
9970 }
9971 }
9972 return 0, false
9973 }
9974
9975 func main() {
9976 pairs := []Pair{
9977 {key: "a", value: 1},
9978 {key: "b", value: 2},
9979 {key: "c", value: 3},
9980 }
9981 v, ok := lookup(pairs, "b")
9982 _ = v
9983 _ = ok
9984 }
9985 `, func(ir string) {
9986 assert("243: has lookup", strings.Contains(ir, "@main.lookup"))
9987 assert("243: returns tuple", strings.Contains(ir, "{i32, i1}"))
9988 assert("243: slice indexing", strings.Contains(ir, "getelementptr"))
9989 })
9990
9991 test(244, `package main
9992
9993 type Writer interface {
9994 Write(data []byte) int32
9995 }
9996
9997 type Buffer struct {
9998 data []byte
9999 }
10000
10001 func (b *Buffer) Write(data []byte) int32 {
10002 b.data = append(b.data, data...)
10003 return int32(len(data))
10004 }
10005
10006 func (b *Buffer) Len() int32 {
10007 return int32(len(b.data))
10008 }
10009
10010 func writeAll(w Writer, chunks []string) int32 {
10011 total := int32(0)
10012 for i := 0; i < len(chunks); i++ {
10013 n := w.Write([]byte(chunks[i]))
10014 total = total + n
10015 }
10016 return total
10017 }
10018
10019 func main() {
10020 buf := &Buffer{}
10021 chunks := []string{"hello", " ", "world"}
10022 n := writeAll(buf, chunks)
10023 _ = n
10024 l := buf.Len()
10025 _ = l
10026 }
10027 `, func(ir string) {
10028 assert("244: has Buffer.Write", strings.Contains(ir, "@main.Buffer.Write"))
10029 assert("244: has writeAll", strings.Contains(ir, "@main.writeAll"))
10030 assert("244: interface method call", strings.Contains(ir, "call"))
10031 assert("244: has Buffer.Len", strings.Contains(ir, "@main.Buffer.Len"))
10032 })
10033
10034 test(245, `package main
10035
10036 type SSAOp int32
10037 const (
10038 OpAdd SSAOp = iota + 1
10039 OpSub
10040 OpMul
10041 OpOr
10042 OpAnd
10043 )
10044
10045 type SSABinOp struct {
10046 Op SSAOp
10047 X int32
10048 Y int32
10049 }
10050
10051 func eval(b *SSABinOp) int32 {
10052 switch b.Op {
10053 case OpAdd:
10054 return b.X + b.Y
10055 case OpSub:
10056 return b.X - b.Y
10057 case OpMul:
10058 return b.X * b.Y
10059 case OpOr:
10060 return b.X | b.Y
10061 case OpAnd:
10062 return b.X & b.Y
10063 }
10064 return 0
10065 }
10066
10067 func main() {
10068 b := &SSABinOp{Op: OpOr, X: 5, Y: 3}
10069 r := eval(b)
10070 _ = r
10071 }
10072 `, func(ir string) {
10073 assert("245: has eval", strings.Contains(ir, "@main.eval"))
10074 assert("245: switch on field", strings.Contains(ir, "icmp eq"))
10075 assert("245: iota+1 offset", strings.Contains(ir, "i32 4"))
10076 })
10077
10078 test(246, `package main
10079
10080 type Scope struct {
10081 parent *Scope
10082 elems map[string]int32
10083 }
10084
10085 func NewScope(parent *Scope) *Scope {
10086 return &Scope{parent: parent, elems: map[string]int32{}}
10087 }
10088
10089 func (s *Scope) Insert(name string, val int32) {
10090 s.elems[name] = val
10091 }
10092
10093 func (s *Scope) Lookup(name string) (int32, bool) {
10094 v, ok := s.elems[name]
10095 if ok {
10096 return v, true
10097 }
10098 if s.parent != nil {
10099 return s.parent.Lookup(name)
10100 }
10101 return 0, false
10102 }
10103
10104 func main() {
10105 outer := NewScope(nil)
10106 outer.Insert("x", 42)
10107 inner := NewScope(outer)
10108 inner.Insert("y", 7)
10109 v1, _ := inner.Lookup("x")
10110 v2, _ := inner.Lookup("y")
10111 _ = v1
10112 _ = v2
10113 }
10114 `, func(ir string) {
10115 assert("246: has NewScope", strings.Contains(ir, "@main.NewScope"))
10116 assert("246: has Scope.Insert", strings.Contains(ir, "@main.Scope.Insert"))
10117 assert("246: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
10118 assert("246: recursive method call", strings.Contains(ir, "call {i32, i1} @main.Scope.Lookup"))
10119 })
10120
10121 test(247, `package main
10122
10123 type Entry struct {
10124 name string
10125 typ int32
10126 }
10127
10128 type Registry struct {
10129 entries []Entry
10130 }
10131
10132 func (r *Registry) add(name string, typ int32) {
10133 r.entries = append(r.entries, Entry{name: name, typ: typ})
10134 }
10135
10136 func (r *Registry) find(name string) int32 {
10137 for i := 0; i < len(r.entries); i++ {
10138 if r.entries[i].name == name {
10139 return r.entries[i].typ
10140 }
10141 }
10142 return -1
10143 }
10144
10145 func main() {
10146 r := &Registry{}
10147 r.add("int", 1)
10148 r.add("string", 2)
10149 r.add("bool", 3)
10150 t := r.find("string")
10151 _ = t
10152 }
10153 `, func(ir string) {
10154 assert("247: has Registry.add", strings.Contains(ir, "@main.Registry.add"))
10155 assert("247: has Registry.find", strings.Contains(ir, "@main.Registry.find"))
10156 assert("247: append struct to slice", strings.Contains(ir, "runtime.sliceAppend"))
10157 })
10158
10159 test(248, `package main
10160
10161 func prefixMatch(s string, prefix string) bool {
10162 if len(s) < len(prefix) {
10163 return false
10164 }
10165 return s[:len(prefix)] == prefix
10166 }
10167
10168 func trimPrefix(s string, prefix string) string {
10169 if prefixMatch(s, prefix) {
10170 return s[len(prefix):]
10171 }
10172 return s
10173 }
10174
10175 func main() {
10176 r := prefixMatch("hello world", "hello")
10177 _ = r
10178 t := trimPrefix("hello world", "hello")
10179 _ = t
10180 }
10181 `, func(ir string) {
10182 assert("248: has prefixMatch", strings.Contains(ir, "@main.prefixMatch"))
10183 assert("248: has trimPrefix", strings.Contains(ir, "@main.trimPrefix"))
10184 assert("248: string compare", strings.Contains(ir, "runtime.stringEqual"))
10185 assert("248: slice sub-expr", strings.Contains(ir, "extractvalue"))
10186 })
10187
10188 test(249, `package main
10189
10190 type Emitter struct {
10191 buf []byte
10192 indent int32
10193 }
10194
10195 func newEmitter() *Emitter {
10196 return &Emitter{buf: []byte{:0:1024}, indent: 0}
10197 }
10198
10199 func (e *Emitter) w(s string) {
10200 e.buf = append(e.buf, s...)
10201 }
10202
10203 func (e *Emitter) nl() {
10204 e.buf = append(e.buf, '\n')
10205 for i := int32(0); i < e.indent; i++ {
10206 e.buf = append(e.buf, ' ')
10207 e.buf = append(e.buf, ' ')
10208 }
10209 }
10210
10211 func (e *Emitter) enter() {
10212 e.indent++
10213 }
10214
10215 func (e *Emitter) leave() {
10216 if e.indent > 0 {
10217 e.indent--
10218 }
10219 }
10220
10221 func (e *Emitter) String() string {
10222 return string(e.buf)
10223 }
10224
10225 func main() {
10226 em := newEmitter()
10227 em.w("func main() {")
10228 em.enter()
10229 em.nl()
10230 em.w("x := 1")
10231 em.leave()
10232 em.nl()
10233 em.w("}")
10234 s := em.String()
10235 _ = s
10236 }
10237 `, func(ir string) {
10238 assert("249: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
10239 assert("249: has Emitter.nl", strings.Contains(ir, "@main.Emitter.nl"))
10240 assert("249: has Emitter.enter", strings.Contains(ir, "@main.Emitter.enter"))
10241 assert("249: has newEmitter", strings.Contains(ir, "@main.newEmitter"))
10242 assert("249: append byte", strings.Contains(ir, "runtime.sliceAppend"))
10243 })
10244
10245 test(250, `package main
10246
10247 func itoa(n int32) string {
10248 if n == 0 {
10249 return "0"
10250 }
10251 neg := n < 0
10252 if neg {
10253 n = -n
10254 }
10255 buf := []byte{:0:20}
10256 for n > 0 {
10257 buf = append(buf, byte('0' + n % 10))
10258 n = n / 10
10259 }
10260 if neg {
10261 buf = append(buf, '-')
10262 }
10263 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
10264 buf[i], buf[j] = buf[j], buf[i]
10265 }
10266 return string(buf)
10267 }
10268
10269 func main() {
10270 s1 := itoa(0)
10271 s2 := itoa(42)
10272 s3 := itoa(-123)
10273 _ = s1
10274 _ = s2
10275 _ = s3
10276 }
10277 `, func(ir string) {
10278 assert("250: has itoa", strings.Contains(ir, "@main.itoa"))
10279 assert("250: modulo op", strings.Contains(ir, "srem"))
10280 assert("250: division", strings.Contains(ir, "sdiv"))
10281 assert("250: reverse loop", strings.Contains(ir, "icmp slt"))
10282 })
10283
10284 test(251, `package main
10285
10286 type Object interface {
10287 Name() string
10288 }
10289
10290 type Var struct {
10291 name string
10292 typ string
10293 }
10294
10295 func (v *Var) Name() string { return v.name }
10296
10297 type Func struct {
10298 name string
10299 sig string
10300 }
10301
10302 func (f *Func) Name() string { return f.name }
10303
10304 func describe(o Object) string {
10305 switch o := o.(type) {
10306 case *Var:
10307 return "var " | o.name | " " | o.typ
10308 case *Func:
10309 return "func " | o.name | o.sig
10310 }
10311 return "unknown"
10312 }
10313
10314 func main() {
10315 var objs []Object
10316 objs = append(objs, &Var{name: "x", typ: "int"})
10317 objs = append(objs, &Func{name: "foo", sig: "()"})
10318 for i := 0; i < len(objs); i++ {
10319 d := describe(objs[i])
10320 _ = d
10321 }
10322 }
10323 `, func(ir string) {
10324 assert("251: has describe", strings.Contains(ir, "@main.describe"))
10325 assert("251: has Var.Name", strings.Contains(ir, "@main.Var.Name"))
10326 assert("251: has Func.Name", strings.Contains(ir, "@main.Func.Name"))
10327 assert("251: type switch typeid", strings.Contains(ir, "typeid"))
10328 assert("251: string concat", strings.Contains(ir, "runtime.sliceAppend"))
10329 })
10330
10331 test(252, `package main
10332
10333 type Node struct {
10334 kind int32
10335 children []*Node
10336 value string
10337 }
10338
10339 func newLeaf(val string) *Node {
10340 return &Node{kind: 1, value: val}
10341 }
10342
10343 func newBranch(children []*Node) *Node {
10344 return &Node{kind: 2, children: children}
10345 }
10346
10347 func countLeaves(n *Node) int32 {
10348 if n.kind == 1 {
10349 return 1
10350 }
10351 total := int32(0)
10352 for i := 0; i < len(n.children); i++ {
10353 total = total + countLeaves(n.children[i])
10354 }
10355 return total
10356 }
10357
10358 func main() {
10359 a := newLeaf("x")
10360 b := newLeaf("y")
10361 c := newLeaf("z")
10362 branch := newBranch([]*Node{a, b, c})
10363 n := countLeaves(branch)
10364 _ = n
10365 }
10366 `, func(ir string) {
10367 assert("252: has countLeaves", strings.Contains(ir, "@main.countLeaves"))
10368 assert("252: recursive call", strings.Contains(ir, "call i32 @main.countLeaves"))
10369 assert("252: has newBranch", strings.Contains(ir, "@main.newBranch"))
10370 assert("252: slice of ptr indexing", strings.Contains(ir, "getelementptr"))
10371 })
10372
10373 test(253, `package main
10374
10375 type Checker struct {
10376 errors []string
10377 pkg string
10378 }
10379
10380 func (c *Checker) errorf(msg string) {
10381 c.errors = append(c.errors, c.pkg | ": " | msg)
10382 }
10383
10384 func (c *Checker) hasErrors() bool {
10385 return len(c.errors) > 0
10386 }
10387
10388 func (c *Checker) check(name string, typ string) {
10389 if typ == "" {
10390 c.errorf("undefined type for " | name)
10391 return
10392 }
10393 if name == "" {
10394 c.errorf("empty name")
10395 }
10396 }
10397
10398 func main() {
10399 c := &Checker{pkg: "main"}
10400 c.check("x", "int")
10401 c.check("y", "")
10402 has := c.hasErrors()
10403 _ = has
10404 }
10405 `, func(ir string) {
10406 assert("253: has Checker.errorf", strings.Contains(ir, "@main.Checker.errorf"))
10407 assert("253: has Checker.check", strings.Contains(ir, "@main.Checker.check"))
10408 assert("253: has Checker.hasErrors", strings.Contains(ir, "@main.Checker.hasErrors"))
10409 assert("253: string concat in errorf", strings.Contains(ir, "runtime.sliceAppend"))
10410 assert("253: string equal for empty check", strings.Contains(ir, "runtime.stringEqual"))
10411 })
10412
10413 test(254, `package main
10414
10415 type Type interface {
10416 Underlying() Type
10417 String() string
10418 }
10419
10420 type Basic struct {
10421 name string
10422 kind int32
10423 }
10424
10425 func (b *Basic) Underlying() Type { return b }
10426 func (b *Basic) String() string { return b.name }
10427
10428 type Pointer struct {
10429 base Type
10430 }
10431
10432 func (p *Pointer) Underlying() Type { return p }
10433 func (p *Pointer) String() string { return "*" | p.base.String() }
10434 func (p *Pointer) Elem() Type { return p.base }
10435
10436 type Named struct {
10437 name string
10438 underlying Type
10439 }
10440
10441 func (n *Named) Underlying() Type {
10442 if n.underlying != nil {
10443 return n.underlying.Underlying()
10444 }
10445 return n
10446 }
10447
10448 func (n *Named) String() string { return n.name }
10449
10450 func NewPointer(base Type) *Pointer { return &Pointer{base: base} }
10451 func NewNamed(name string, underlying Type) *Named {
10452 return &Named{name: name, underlying: underlying}
10453 }
10454
10455 func isPointer(t Type) bool {
10456 _, ok := t.Underlying().(*Pointer)
10457 return ok
10458 }
10459
10460 func baseType(t Type) Type {
10461 if p, ok := t.Underlying().(*Pointer); ok {
10462 return p.Elem()
10463 }
10464 return t
10465 }
10466
10467 func main() {
10468 intT := &Basic{name: "int", kind: 1}
10469 ptrInt := NewPointer(intT)
10470 named := NewNamed("MyInt", intT)
10471 ptrNamed := NewPointer(named)
10472
10473 s1 := ptrInt.String()
10474 s2 := named.String()
10475 ip := isPointer(ptrNamed)
10476 bt := baseType(ptrNamed)
10477 _ = s1
10478 _ = s2
10479 _ = ip
10480 _ = bt
10481 }
10482 `, func(ir string) {
10483 assert("254: has Pointer.String", strings.Contains(ir, "@main.Pointer.String"))
10484 assert("254: has Named.Underlying", strings.Contains(ir, "@main.Named.Underlying"))
10485 assert("254: has isPointer", strings.Contains(ir, "@main.isPointer"))
10486 assert("254: has baseType", strings.Contains(ir, "@main.baseType"))
10487 assert("254: interface method dispatch", strings.Contains(ir, "typeid"))
10488 })
10489
10490 test(255, `package main
10491
10492 type Instruction interface {
10493 Operands() int32
10494 }
10495
10496 type BinOp struct {
10497 op string
10498 x int32
10499 y int32
10500 }
10501
10502 func (b *BinOp) Operands() int32 { return 2 }
10503
10504 type UnOp struct {
10505 op string
10506 x int32
10507 }
10508
10509 func (u *UnOp) Operands() int32 { return 1 }
10510
10511 type Block struct {
10512 instrs []Instruction
10513 }
10514
10515 func (bl *Block) add(i Instruction) {
10516 bl.instrs = append(bl.instrs, i)
10517 }
10518
10519 func (bl *Block) count() int32 {
10520 total := int32(0)
10521 for i := 0; i < len(bl.instrs); i++ {
10522 total = total + bl.instrs[i].Operands()
10523 }
10524 return total
10525 }
10526
10527 func main() {
10528 bl := &Block{}
10529 bl.add(&BinOp{op: "add", x: 1, y: 2})
10530 bl.add(&UnOp{op: "neg", x: 3})
10531 bl.add(&BinOp{op: "mul", x: 4, y: 5})
10532 c := bl.count()
10533 _ = c
10534 }
10535 `, func(ir string) {
10536 assert("255: has Block.add", strings.Contains(ir, "@main.Block.add"))
10537 assert("255: has Block.count", strings.Contains(ir, "@main.Block.count"))
10538 assert("255: has BinOp.Operands", strings.Contains(ir, "@main.BinOp.Operands"))
10539 assert("255: interface dispatch in count", strings.Contains(ir, "typeid"))
10540 })
10541
10542 test(256, `package main
10543
10544 func reverse(s string) string {
10545 b := []byte(s)
10546 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
10547 b[i], b[j] = b[j], b[i]
10548 }
10549 return string(b)
10550 }
10551
10552 func contains(s string, sub string) bool {
10553 if len(sub) == 0 {
10554 return true
10555 }
10556 if len(sub) > len(s) {
10557 return false
10558 }
10559 for i := 0; i <= len(s)-len(sub); i++ {
10560 if s[i:i+len(sub)] == sub {
10561 return true
10562 }
10563 }
10564 return false
10565 }
10566
10567 func main() {
10568 r := reverse("hello")
10569 _ = r
10570 c := contains("hello world", "world")
10571 _ = c
10572 }
10573 `, func(ir string) {
10574 assert("256: has reverse", strings.Contains(ir, "@main.reverse"))
10575 assert("256: has contains", strings.Contains(ir, "@main.contains"))
10576 assert("256: string equal", strings.Contains(ir, "runtime.stringEqual"))
10577 assert("256: byte swap", strings.Contains(ir, "getelementptr"))
10578 })
10579
10580 test(257, `package main
10581
10582 type Gen struct {
10583 counter int32
10584 prefix string
10585 }
10586
10587 func (g *Gen) emit() string {
10588 p := func(tag string) string {
10589 g.counter++
10590 return g.prefix | tag | itoa257(g.counter)
10591 }
10592 a := p("a")
10593 b := p("b")
10594 c := p("a")
10595 return a | " " | b | " " | c
10596 }
10597
10598 func itoa257(n int32) string {
10599 if n == 0 { return "0" }
10600 buf := []byte{:0:10}
10601 for n > 0 {
10602 buf = append(buf, byte('0' + n % 10))
10603 n = n / 10
10604 }
10605 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
10606 buf[i], buf[j] = buf[j], buf[i]
10607 }
10608 return string(buf)
10609 }
10610
10611 func main() {
10612 g := &Gen{prefix: "%t"}
10613 result := g.emit()
10614 _ = result
10615 }
10616 `, func(ir string) {
10617 assert("257: has Gen.emit", strings.Contains(ir, "@main.Gen.emit"))
10618 assert("257: closure function", strings.Contains(ir, "@main.Gen.emit$1"))
10619 })
10620
10621 test(258, `package main
10622
10623 type MapEntry struct {
10624 key string
10625 val int32
10626 }
10627
10628 func sortEntries(entries []MapEntry) {
10629 for i := 1; i < len(entries); i++ {
10630 for j := i; j > 0; j-- {
10631 if entries[j].key < entries[j-1].key {
10632 entries[j], entries[j-1] = entries[j-1], entries[j]
10633 }
10634 }
10635 }
10636 }
10637
10638 func main() {
10639 entries := []MapEntry{
10640 {key: "c", val: 3},
10641 {key: "a", val: 1},
10642 {key: "b", val: 2},
10643 }
10644 sortEntries(entries)
10645 }
10646 `, func(ir string) {
10647 assert("258: has sortEntries", strings.Contains(ir, "@main.sortEntries"))
10648 assert("258: string less-than", strings.Contains(ir, "runtime.stringLess"))
10649 assert("258: swap pattern", strings.Contains(ir, "getelementptr"))
10650 })
10651
10652 test(259, `package main
10653
10654 type Scope struct {
10655 parent *Scope
10656 names map[string]bool
10657 }
10658
10659 func (s *Scope) define(name string) {
10660 s.names[name] = true
10661 }
10662
10663 func (s *Scope) isDefined(name string) bool {
10664 if s.names[name] {
10665 return true
10666 }
10667 if s.parent != nil {
10668 return s.parent.isDefined(name)
10669 }
10670 return false
10671 }
10672
10673 func (s *Scope) allNames() []string {
10674 var result []string
10675 for k, _ := range s.names {
10676 result = append(result, k)
10677 }
10678 return result
10679 }
10680
10681 func main() {
10682 outer := &Scope{names: map[string]bool{}}
10683 outer.define("x")
10684 outer.define("y")
10685 inner := &Scope{parent: outer, names: map[string]bool{}}
10686 inner.define("z")
10687 d := inner.isDefined("x")
10688 names := inner.allNames()
10689 _ = d
10690 _ = names
10691 }
10692 `, func(ir string) {
10693 assert("259: has Scope.define", strings.Contains(ir, "@main.Scope.define"))
10694 assert("259: has Scope.isDefined", strings.Contains(ir, "@main.Scope.isDefined"))
10695 assert("259: has Scope.allNames", strings.Contains(ir, "@main.Scope.allNames"))
10696 assert("259: recursive method", strings.Contains(ir, "call i1 @main.Scope.isDefined"))
10697 assert("259: for-range map", strings.Contains(ir, "hashmapNext"))
10698 })
10699
10700 test(260, `package main
10701
10702 type SSAOp int32
10703 const (
10704 OpIllegal SSAOp = iota
10705 OpAdd
10706 OpSub
10707 OpMul
10708 OpOr
10709 OpAnd
10710 )
10711
10712 type SSAValue interface {
10713 Name() string
10714 Type() string
10715 }
10716
10717 type SSAConst struct {
10718 name string
10719 typ string
10720 val int32
10721 }
10722
10723 func (c *SSAConst) Name() string { return c.name }
10724 func (c *SSAConst) Type() string { return c.typ }
10725
10726 type SSABinOp struct {
10727 name string
10728 typ string
10729 Op SSAOp
10730 X SSAValue
10731 Y SSAValue
10732 }
10733
10734 func (b *SSABinOp) Name() string { return b.name }
10735 func (b *SSABinOp) Type() string { return b.typ }
10736
10737 type Emitter struct {
10738 buf []byte
10739 regs int32
10740 }
10741
10742 func (e *Emitter) w(s string) {
10743 e.buf = append(e.buf, s...)
10744 }
10745
10746 func (e *Emitter) nextReg() string {
10747 e.regs++
10748 return "%t" | itoa260(e.regs)
10749 }
10750
10751 func (e *Emitter) emitBinOp(b *SSABinOp) {
10752 reg := b.Name()
10753 lv := b.X.Name()
10754 rv := b.Y.Name()
10755 op := ""
10756 switch b.Op {
10757 case OpAdd:
10758 op = "add"
10759 case OpSub:
10760 op = "sub"
10761 case OpMul:
10762 op = "mul"
10763 case OpOr:
10764 op = "or"
10765 case OpAnd:
10766 op = "and"
10767 }
10768 e.w(" ") ; e.w(reg) ; e.w(" = ") ; e.w(op) ; e.w(" ")
10769 e.w(b.Type()) ; e.w(" ") ; e.w(lv) ; e.w(", ") ; e.w(rv) ; e.w("\n")
10770 }
10771
10772 func (e *Emitter) emit(instrs []SSAValue) string {
10773 for i := 0; i < len(instrs); i++ {
10774 switch v := instrs[i].(type) {
10775 case *SSABinOp:
10776 e.emitBinOp(v)
10777 }
10778 }
10779 return string(e.buf)
10780 }
10781
10782 func itoa260(n int32) string {
10783 if n == 0 { return "0" }
10784 buf := []byte{:0:10}
10785 for n > 0 {
10786 buf = append(buf, byte('0' + n % 10))
10787 n = n / 10
10788 }
10789 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
10790 buf[i], buf[j] = buf[j], buf[i]
10791 }
10792 return string(buf)
10793 }
10794
10795 func main() {
10796 c1 := &SSAConst{name: "%c1", typ: "i32", val: 5}
10797 c2 := &SSAConst{name: "%c2", typ: "i32", val: 3}
10798 add := &SSABinOp{name: "%t1", typ: "i32", Op: OpAdd, X: c1, Y: c2}
10799 c3 := &SSAConst{name: "%c3", typ: "i32", val: 7}
10800 mul := &SSABinOp{name: "%t2", typ: "i32", Op: OpMul, X: add, Y: c3}
10801
10802 em := &Emitter{}
10803 var instrs []SSAValue
10804 instrs = append(instrs, add)
10805 instrs = append(instrs, mul)
10806 result := em.emit(instrs)
10807 _ = result
10808 }
10809 `, func(ir string) {
10810 assert("260: has Emitter.emit", strings.Contains(ir, "@main.Emitter.emit"))
10811 assert("260: has Emitter.emitBinOp", strings.Contains(ir, "@main.Emitter.emitBinOp"))
10812 assert("260: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
10813 assert("260: SSAValue interface dispatch", strings.Contains(ir, "typeid"))
10814 assert("260: type switch on SSAValue", strings.Contains(ir, "typeid.ptr.SSABinOp"))
10815 assert("260: append interface coercion", strings.Contains(ir, "typeid.ptr.SSAConst") || strings.Contains(ir, "insertvalue {ptr, ptr}"))
10816 })
10817
10818 test(261, `package main
10819
10820 type TokenKind int32
10821
10822 const (
10823 TokEOF TokenKind = iota
10824 TokIdent
10825 TokNumber
10826 TokPlus
10827 TokMinus
10828 TokStar
10829 )
10830
10831 func (k TokenKind) String() string {
10832 switch k {
10833 case TokEOF:
10834 return "EOF"
10835 case TokIdent:
10836 return "IDENT"
10837 case TokNumber:
10838 return "NUMBER"
10839 case TokPlus:
10840 return "+"
10841 case TokMinus:
10842 return "-"
10843 case TokStar:
10844 return "*"
10845 }
10846 return "?"
10847 }
10848
10849 func (k TokenKind) IsOperator() bool {
10850 return k >= TokPlus && k <= TokStar
10851 }
10852
10853 type Token struct {
10854 kind TokenKind
10855 lit string
10856 }
10857
10858 func (t *Token) String() string {
10859 if t.lit != "" {
10860 return t.kind.String() | "(" | t.lit | ")"
10861 }
10862 return t.kind.String()
10863 }
10864
10865 func main() {
10866 t := &Token{kind: TokIdent, lit: "foo"}
10867 s := t.String()
10868 _ = s
10869 op := TokPlus.IsOperator()
10870 _ = op
10871 name := TokIdent.String()
10872 _ = name
10873 }
10874 `, func(ir string) {
10875 assert("261: method on named int", strings.Contains(ir, "@main.TokenKind.String"))
10876 assert("261: TokenKind.IsOperator", strings.Contains(ir, "@main.TokenKind.IsOperator"))
10877 assert("261: Token.String calls kind.String", strings.Contains(ir, "call {ptr, i64, i64} @main.TokenKind.String"))
10878 assert("261: value receiver method", strings.Contains(ir, "define {ptr, i64, i64} @main.TokenKind.String(i32 %k"))
10879 })
10880
10881 test(262, `package main
10882
10883 type Info int32
10884 const (
10885 IsInteger Info = 1 << iota
10886 IsFloat
10887 IsUnsigned
10888 IsString
10889 IsUntyped
10890 )
10891
10892 func (i Info) Has(flag Info) bool {
10893 return i & flag != 0
10894 }
10895
10896 type BasicKind int32
10897 const (
10898 Int32Kind BasicKind = iota
10899 Uint32Kind
10900 Float64Kind
10901 StringKind
10902 )
10903
10904 type Basic struct {
10905 kind BasicKind
10906 info Info
10907 name string
10908 }
10909
10910 var basics = [4]*Basic{
10911 &Basic{kind: Int32Kind, info: IsInteger, name: "int32"},
10912 &Basic{kind: Uint32Kind, info: IsInteger | IsUnsigned, name: "uint32"},
10913 &Basic{kind: Float64Kind, info: IsFloat, name: "float64"},
10914 &Basic{kind: StringKind, info: IsString, name: "string"},
10915 }
10916
10917 func lookupBasic(kind BasicKind) *Basic {
10918 if int32(kind) >= 0 && int32(kind) < 4 {
10919 return basics[int32(kind)]
10920 }
10921 return nil
10922 }
10923
10924 func main() {
10925 b := lookupBasic(Uint32Kind)
10926 isInt := b.info.Has(IsInteger)
10927 isUns := b.info.Has(IsUnsigned)
10928 isFlt := b.info.Has(IsFloat)
10929 _ = isInt
10930 _ = isUns
10931 _ = isFlt
10932 }
10933 `, func(ir string) {
10934 assert("262: has Info.Has", strings.Contains(ir, "@main.Info.Has"))
10935 assert("262: has lookupBasic", strings.Contains(ir, "@main.lookupBasic"))
10936 assert("262: array global", strings.Contains(ir, "@main.basics"))
10937 assert("262: bitwise and in Has", strings.Contains(ir, " and "))
10938 assert("262: const flags passed to Has", strings.Contains(ir, "i32 1") && strings.Contains(ir, "i32 4"))
10939 })
10940
10941 test(263, `package main
10942
10943 type Member interface {
10944 MemberName() string
10945 }
10946
10947 type Function struct {
10948 name string
10949 params []string
10950 }
10951
10952 func (f *Function) MemberName() string { return f.name }
10953
10954 type Global struct {
10955 name string
10956 typ string
10957 }
10958
10959 func (g *Global) MemberName() string { return g.name }
10960
10961 type Package struct {
10962 members map[string]Member
10963 }
10964
10965 func NewPackage() *Package {
10966 return &Package{members: map[string]Member{}}
10967 }
10968
10969 func (p *Package) addFunc(name string, params []string) {
10970 p.members[name] = &Function{name: name, params: params}
10971 }
10972
10973 func (p *Package) addGlobal(name string, typ string) {
10974 p.members[name] = &Global{name: name, typ: typ}
10975 }
10976
10977 func (p *Package) lookup(name string) Member {
10978 m, ok := p.members[name]
10979 if ok {
10980 return m
10981 }
10982 return nil
10983 }
10984
10985 func (p *Package) sortedNames() []string {
10986 var names []string
10987 for k, _ := range p.members {
10988 names = append(names, k)
10989 }
10990 for i := 1; i < len(names); i++ {
10991 for j := i; j > 0 && names[j] < names[j-1]; j-- {
10992 names[j], names[j-1] = names[j-1], names[j]
10993 }
10994 }
10995 return names
10996 }
10997
10998 func main() {
10999 pkg := NewPackage()
11000 pkg.addFunc("main", nil)
11001 pkg.addFunc("helper", []string{"x", "y"})
11002 pkg.addGlobal("counter", "int32")
11003 m := pkg.lookup("helper")
11004 _ = m
11005 names := pkg.sortedNames()
11006 _ = names
11007 }
11008 `, func(ir string) {
11009 assert("263: has Package.addFunc", strings.Contains(ir, "@main.Package.addFunc"))
11010 assert("263: has Package.lookup", strings.Contains(ir, "@main.Package.lookup"))
11011 assert("263: has Package.sortedNames", strings.Contains(ir, "@main.Package.sortedNames"))
11012 assert("263: map interface store", strings.Contains(ir, "hashmapContentSet"))
11013 assert("263: for-range map", strings.Contains(ir, "hashmapNext"))
11014 assert("263: insertion sort", strings.Contains(ir, "stringLess"))
11015 })
11016
11017 test(264, `package main
11018
11019 type SSAOp int32
11020 const (
11021 OpIllegal SSAOp = iota
11022 OpAdd
11023 OpSub
11024 OpMul
11025 OpQuo
11026 OpRem
11027 OpAnd
11028 OpOr
11029 OpXor
11030 OpShl
11031 OpShr
11032 )
11033
11034 func (op SSAOp) String() string {
11035 switch op {
11036 case OpAdd: return "+"
11037 case OpSub: return "-"
11038 case OpMul: return "*"
11039 case OpQuo: return "/"
11040 case OpRem: return "%"
11041 case OpAnd: return "&"
11042 case OpOr: return "|"
11043 case OpXor: return "^"
11044 case OpShl: return "<<"
11045 case OpShr: return ">>"
11046 }
11047 return "?"
11048 }
11049
11050 type Type interface {
11051 Underlying() Type
11052 String() string
11053 }
11054
11055 type Basic struct {
11056 kind int32
11057 info int32
11058 name string
11059 }
11060
11061 func (b *Basic) Underlying() Type { return b }
11062 func (b *Basic) String() string { return b.name }
11063
11064 type Pointer struct {
11065 base Type
11066 }
11067
11068 func (p *Pointer) Underlying() Type { return p }
11069 func (p *Pointer) String() string { return "*" | p.base.String() }
11070 func (p *Pointer) Elem() Type { return p.base }
11071
11072 type Slice struct {
11073 elem Type
11074 }
11075
11076 func (s *Slice) Underlying() Type { return s }
11077 func (s *Slice) String() string { return "[]" | s.elem.String() }
11078 func (s *Slice) Elem() Type { return s.elem }
11079
11080 type Scope struct {
11081 parent *Scope
11082 elems map[string]Type
11083 }
11084
11085 func NewScope(parent *Scope) *Scope {
11086 return &Scope{parent: parent, elems: map[string]Type{}}
11087 }
11088
11089 func (s *Scope) Insert(name string, t Type) {
11090 s.elems[name] = t
11091 }
11092
11093 func (s *Scope) Lookup(name string) Type {
11094 t, ok := s.elems[name]
11095 if ok {
11096 return t
11097 }
11098 if s.parent != nil {
11099 return s.parent.Lookup(name)
11100 }
11101 return nil
11102 }
11103
11104 type SSAValue interface {
11105 SSAName() string
11106 SSAType() Type
11107 }
11108
11109 type SSAConst struct {
11110 name string
11111 typ Type
11112 val int32
11113 }
11114
11115 func (c *SSAConst) SSAName() string { return c.name }
11116 func (c *SSAConst) SSAType() Type { return c.typ }
11117
11118 type SSABinOp struct {
11119 name string
11120 typ Type
11121 Op SSAOp
11122 X SSAValue
11123 Y SSAValue
11124 }
11125
11126 func (b *SSABinOp) SSAName() string { return b.name }
11127 func (b *SSABinOp) SSAType() Type { return b.typ }
11128
11129 type Emitter struct {
11130 buf []byte
11131 nextReg int32
11132 scope *Scope
11133 }
11134
11135 func NewEmitter() *Emitter {
11136 s := NewScope(nil)
11137 s.Insert("int32", &Basic{kind: 0, info: 1, name: "int32"})
11138 s.Insert("string", &Basic{kind: 1, info: 8, name: "string"})
11139 s.Insert("bool", &Basic{kind: 2, info: 0, name: "bool"})
11140 return &Emitter{buf: []byte{:0:4096}, scope: s}
11141 }
11142
11143 func (e *Emitter) w(s string) {
11144 e.buf = append(e.buf, s...)
11145 }
11146
11147 func (e *Emitter) reg() string {
11148 e.nextReg++
11149 return "%t" | itoa264(e.nextReg)
11150 }
11151
11152 func (e *Emitter) llvmType(t Type) string {
11153 if t == nil {
11154 return "void"
11155 }
11156 switch t := t.Underlying().(type) {
11157 case *Basic:
11158 if t.name == "int32" {
11159 return "i32"
11160 }
11161 if t.name == "bool" {
11162 return "i1"
11163 }
11164 if t.name == "string" {
11165 return "{ptr, i64, i64}"
11166 }
11167 case *Pointer:
11168 return "ptr"
11169 case *Slice:
11170 return "{ptr, i64, i64}"
11171 }
11172 return "void"
11173 }
11174
11175 func (e *Emitter) emitBinOp(b *SSABinOp) string {
11176 reg := e.reg()
11177 lt := e.llvmType(b.X.SSAType())
11178 lv := b.X.SSAName()
11179 rv := b.Y.SSAName()
11180 op := ""
11181 switch b.Op {
11182 case OpAdd: op = "add"
11183 case OpSub: op = "sub"
11184 case OpMul: op = "mul"
11185 case OpOr: op = "or"
11186 case OpAnd: op = "and"
11187 }
11188 if op == "" {
11189 return reg
11190 }
11191 e.w(" ") ; e.w(reg) ; e.w(" = ") ; e.w(op) ; e.w(" ")
11192 e.w(lt) ; e.w(" ") ; e.w(lv) ; e.w(", ") ; e.w(rv) ; e.w("\n")
11193 return reg
11194 }
11195
11196 func (e *Emitter) String() string {
11197 return string(e.buf)
11198 }
11199
11200 func itoa264(n int32) string {
11201 if n == 0 { return "0" }
11202 buf := []byte{:0:10}
11203 for n > 0 {
11204 buf = append(buf, byte('0' + n % 10))
11205 n = n / 10
11206 }
11207 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
11208 buf[i], buf[j] = buf[j], buf[i]
11209 }
11210 return string(buf)
11211 }
11212
11213 func main() {
11214 em := NewEmitter()
11215 int32Type := em.scope.Lookup("int32")
11216
11217 c1 := &SSAConst{name: "1", typ: int32Type, val: 1}
11218 c2 := &SSAConst{name: "2", typ: int32Type, val: 2}
11219 add := &SSABinOp{name: "%t1", typ: int32Type, Op: OpAdd, X: c1, Y: c2}
11220 c3 := &SSAConst{name: "3", typ: int32Type, val: 3}
11221 mul := &SSABinOp{name: "%t2", typ: int32Type, Op: OpMul, X: add, Y: c3}
11222 c4 := &SSAConst{name: "7", typ: int32Type, val: 7}
11223 bor := &SSABinOp{name: "%t3", typ: int32Type, Op: OpOr, X: mul, Y: c4}
11224
11225 em.emitBinOp(add)
11226 em.emitBinOp(mul)
11227 em.emitBinOp(bor)
11228
11229 result := em.String()
11230 _ = result
11231
11232 lt := em.llvmType(&Pointer{base: int32Type})
11233 _ = lt
11234 st := em.llvmType(&Slice{elem: int32Type})
11235 _ = st
11236 }
11237 `, func(ir string) {
11238 assert("264: has Emitter.emitBinOp", strings.Contains(ir, "@main.Emitter.emitBinOp"))
11239 assert("264: has Emitter.llvmType", strings.Contains(ir, "@main.Emitter.llvmType"))
11240 assert("264: SSAOp.String method on named int", strings.Contains(ir, "@main.SSAOp.String"))
11241 assert("264: Scope.Lookup recursive", strings.Contains(ir, "call {ptr, ptr} @main.Scope.Lookup"))
11242 assert("264: type switch in llvmType", strings.Contains(ir, "typeid"))
11243 assert("264: interface dispatch SSAConst", strings.Contains(ir, "typeid.SSAConst") || strings.Contains(ir, "typeid.ptr.SSAConst"))
11244 assert("264: string concat via |", strings.Contains(ir, "runtime.sliceAppend"))
11245 assert("264: scope map lookup", strings.Contains(ir, "hashmapContentGet"))
11246 })
11247
11248 test(265, `package main
11249
11250 type Instruction interface {
11251 Block() *BasicBlock
11252 InstrString() string
11253 }
11254
11255 type Value interface {
11256 Name() string
11257 Type() string
11258 }
11259
11260 type instrBase struct {
11261 block *BasicBlock
11262 }
11263
11264 func (a *instrBase) Block() *BasicBlock { return a.block }
11265
11266 type register struct {
11267 instrBase
11268 name string
11269 typ string
11270 }
11271
11272 func (r *register) Name() string { return r.name }
11273 func (r *register) Type() string { return r.typ }
11274
11275 type BinOp struct {
11276 register
11277 Op string
11278 X Value
11279 Y Value
11280 }
11281
11282 func (b *BinOp) InstrString() string {
11283 return b.Op | " " | b.X.Name() | " " | b.Y.Name()
11284 }
11285
11286 type Store struct {
11287 instrBase
11288 Addr Value
11289 Val Value
11290 }
11291
11292 func (s *Store) InstrString() string {
11293 return "store " | s.Val.Name() | " -> " | s.Addr.Name()
11294 }
11295
11296 type BasicBlock struct {
11297 index int32
11298 name string
11299 instrs []Instruction
11300 }
11301
11302 func (bl *BasicBlock) emit(i Instruction) {
11303 bl.instrs = append(bl.instrs, i)
11304 }
11305
11306 type Const struct {
11307 name string
11308 typ string
11309 val int32
11310 }
11311
11312 func (c *Const) Name() string { return c.name }
11313 func (c *Const) Type() string { return c.typ }
11314
11315 func main() {
11316 bl := &BasicBlock{index: 0, name: "entry"}
11317 c1 := &Const{name: "%c1", typ: "i32", val: 1}
11318 c2 := &Const{name: "%c2", typ: "i32", val: 2}
11319
11320 add := &BinOp{
11321 register: register{instrBase: instrBase{block: bl}, name: "%t1", typ: "i32"},
11322 Op: "add", X: c1, Y: c2,
11323 }
11324 bl.emit(add)
11325
11326 store := &Store{
11327 instrBase: instrBase{block: bl},
11328 Addr: c1, Val: add,
11329 }
11330 bl.emit(store)
11331
11332 s1 := add.InstrString()
11333 s2 := store.InstrString()
11334 _ = s1
11335 _ = s2
11336
11337 n := add.Name()
11338 t := add.Type()
11339 b := add.Block()
11340 _ = n
11341 _ = t
11342 _ = b
11343 }
11344 `, func(ir string) {
11345 assert("265: has BinOp.InstrString", strings.Contains(ir, "@main.BinOp.InstrString"))
11346 assert("265: has Store.InstrString", strings.Contains(ir, "@main.Store.InstrString"))
11347 assert("265: multi-level embed register.Name", strings.Contains(ir, "@main.register.Name"))
11348 assert("265: deep embed instrBase.Block", strings.Contains(ir, "@main.instrBase.Block"))
11349 assert("265: interface append with boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11350 assert("265: promoted field access", strings.Contains(ir, "getelementptr"))
11351 })
11352
11353 // Test 266: comma-ok type assertions
11354 test(266, `package main
11355
11356 type Node interface {
11357 Kind() string
11358 }
11359
11360 type Ident struct {
11361 name string
11362 }
11363 func (i *Ident) Kind() string { return "ident" }
11364
11365 type Literal struct {
11366 val int32
11367 }
11368 func (l *Literal) Kind() string { return "literal" }
11369
11370 func classify(n Node) string {
11371 if id, ok := n.(*Ident); ok {
11372 return id.name
11373 }
11374 if lit, ok := n.(*Literal); ok {
11375 _ = lit.val
11376 return "lit"
11377 }
11378 return "unknown"
11379 }
11380
11381 func main() {
11382 var n Node
11383 n = &Ident{name: "foo"}
11384 s1 := classify(n)
11385 _ = s1
11386
11387 n = &Literal{val: 42}
11388 s2 := classify(n)
11389 _ = s2
11390 }
11391 `, func(ir string) {
11392 assert("266: has classify", strings.Contains(ir, "@main.classify"))
11393 assert("266: typeid for assertions", strings.Contains(ir, "typeid"))
11394 assert("266: icmp for type check", strings.Contains(ir, "icmp eq ptr"))
11395 })
11396
11397 // Test 267: for-range map with key and value
11398 test(267, `package main
11399
11400 type Entry struct {
11401 name string
11402 val int32
11403 }
11404
11405 func sumMap(m map[string]int32) int32 {
11406 total := int32(0)
11407 for _, v := range m {
11408 total = total + v
11409 }
11410 return total
11411 }
11412
11413 func collectKeys(m map[string]*Entry) []string {
11414 var keys []string
11415 for k := range m {
11416 keys = append(keys, k)
11417 }
11418 return keys
11419 }
11420
11421 func main() {
11422 m := map[string]int32{}
11423 m["a"] = 1
11424 m["b"] = 2
11425 s := sumMap(m)
11426 _ = s
11427
11428 entries := map[string]*Entry{}
11429 entries["x"] = &Entry{name: "x", val: 10}
11430 keys := collectKeys(entries)
11431 _ = keys
11432 }
11433 `, func(ir string) {
11434 assert("267: has sumMap", strings.Contains(ir, "@main.sumMap"))
11435 assert("267: has collectKeys", strings.Contains(ir, "@main.collectKeys"))
11436 assert("267: hashmapNext for range", strings.Contains(ir, "hashmapNext"))
11437 })
11438
11439 // Test 268: closure capturing struct pointer, called multiple times
11440 test(268, `package main
11441
11442 type Builder struct {
11443 buf []byte
11444 indent int32
11445 }
11446
11447 func (b *Builder) build() string {
11448 p := func(s string) {
11449 b.buf = append(b.buf, s...)
11450 }
11451 nl := func() {
11452 b.buf = append(b.buf, '\n')
11453 }
11454 p("func main() {")
11455 nl()
11456 p(" return")
11457 nl()
11458 p("}")
11459 nl()
11460 return string(b.buf)
11461 }
11462
11463 func main() {
11464 b := &Builder{}
11465 result := b.build()
11466 _ = result
11467 }
11468 `, func(ir string) {
11469 assert("268: has Builder.build", strings.Contains(ir, "@main.Builder.build"))
11470 assert("268: closure captures", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11471 assert("268: sliceAppend for buf", strings.Contains(ir, "sliceAppend"))
11472 })
11473
11474 // Test 269: multiple comma-ok assertions in sequence with branching
11475 test(269, `package main
11476
11477 type Type interface {
11478 Underlying() Type
11479 }
11480
11481 type Basic struct {
11482 kind int32
11483 }
11484 func (b *Basic) Underlying() Type { return b }
11485
11486 type Pointer struct {
11487 elem Type
11488 }
11489 func (p *Pointer) Underlying() Type { return p }
11490 func (p *Pointer) Elem() Type { return p.elem }
11491
11492 type Named struct {
11493 name string
11494 underlying Type
11495 }
11496 func (n *Named) Underlying() Type { return n.underlying }
11497
11498 func resolve(t Type) Type {
11499 if p, ok := t.(*Pointer); ok {
11500 return p.Elem()
11501 }
11502 if n, ok := t.(*Named); ok {
11503 return n.Underlying()
11504 }
11505 return t
11506 }
11507
11508 func isPointerTo(t Type, kind int32) bool {
11509 p, ok := t.(*Pointer)
11510 if !ok {
11511 return false
11512 }
11513 b, ok2 := p.Elem().(*Basic)
11514 if !ok2 {
11515 return false
11516 }
11517 return b.kind == kind
11518 }
11519
11520 func main() {
11521 intType := &Basic{kind: 1}
11522 ptrInt := &Pointer{elem: intType}
11523 named := &Named{name: "myint", underlying: intType}
11524
11525 r1 := resolve(ptrInt)
11526 _ = r1
11527 r2 := resolve(named)
11528 _ = r2
11529 r3 := resolve(intType)
11530 _ = r3
11531
11532 yes := isPointerTo(ptrInt, 1)
11533 no := isPointerTo(intType, 1)
11534 _ = yes
11535 _ = no
11536 }
11537 `, func(ir string) {
11538 assert("269: has resolve", strings.Contains(ir, "@main.resolve"))
11539 assert("269: has isPointerTo", strings.Contains(ir, "@main.isPointerTo"))
11540 assert("269: multiple type assertions", strings.Count(ir, "icmp eq ptr") >= 3)
11541 })
11542
11543 // Test 270: string([]byte) and []byte(string) conversions with itoa pattern
11544 test(270, `package main
11545
11546 func itoa(n int32) string {
11547 if n == 0 {
11548 return "0"
11549 }
11550 neg := false
11551 if n < 0 {
11552 neg = true
11553 n = -n
11554 }
11555 var buf [20]byte
11556 i := int32(19)
11557 for n > 0 {
11558 buf[i] = byte(n%10) + '0'
11559 n = n / 10
11560 i = i - 1
11561 }
11562 if neg {
11563 buf[i] = '-'
11564 i = i - 1
11565 }
11566 return string(buf[i+1:])
11567 }
11568
11569 func concat(parts []string) string {
11570 var buf []byte
11571 for _, p := range parts {
11572 buf = append(buf, p...)
11573 }
11574 return string(buf)
11575 }
11576
11577 func main() {
11578 s1 := itoa(42)
11579 s2 := itoa(-7)
11580 s3 := itoa(0)
11581 _ = s1
11582 _ = s2
11583 _ = s3
11584
11585 parts := []string{"hello", " ", "world"}
11586 joined := concat(parts)
11587 _ = joined
11588 }
11589 `, func(ir string) {
11590 assert("270: has itoa", strings.Contains(ir, "@main.itoa"))
11591 assert("270: has concat", strings.Contains(ir, "@main.concat"))
11592 assert("270: array alloca for buf", strings.Contains(ir, "alloca [20 x i8]"))
11593 assert("270: sliceAppend for concat", strings.Contains(ir, "sliceAppend"))
11594 })
11595
11596 // Test 271: for-range over map with both key and value, building output
11597 test(271, `package main
11598
11599 type Member interface {
11600 Name() string
11601 }
11602
11603 type Func struct {
11604 name string
11605 }
11606 func (f *Func) Name() string { return f.name }
11607
11608 type Global struct {
11609 name string
11610 typ string
11611 }
11612 func (g *Global) Name() string { return g.name }
11613
11614 type Package struct {
11615 members map[string]Member
11616 }
11617
11618 func (p *Package) addFunc(name string) {
11619 p.members[name] = &Func{name: name}
11620 }
11621
11622 func (p *Package) addGlobal(name string, typ string) {
11623 p.members[name] = &Global{name: name, typ: typ}
11624 }
11625
11626 func (p *Package) allNames() []string {
11627 var names []string
11628 for k, m := range p.members {
11629 _ = m
11630 names = append(names, k)
11631 }
11632 return names
11633 }
11634
11635 func (p *Package) findFuncs() []*Func {
11636 var funcs []*Func
11637 for _, m := range p.members {
11638 if f, ok := m.(*Func); ok {
11639 funcs = append(funcs, f)
11640 }
11641 }
11642 return funcs
11643 }
11644
11645 func main() {
11646 p := &Package{members: map[string]Member{}}
11647 p.addFunc("main")
11648 p.addFunc("init")
11649 p.addGlobal("x", "i32")
11650
11651 names := p.allNames()
11652 _ = names
11653
11654 funcs := p.findFuncs()
11655 _ = funcs
11656 }
11657 `, func(ir string) {
11658 assert("271: has allNames", strings.Contains(ir, "@main.Package.allNames"))
11659 assert("271: has findFuncs", strings.Contains(ir, "@main.Package.findFuncs"))
11660 assert("271: range map hashmapNext", strings.Contains(ir, "hashmapNext"))
11661 assert("271: type assertion in range body", strings.Contains(ir, "icmp eq ptr"))
11662 })
11663
11664 // Test 272: nested closure calls - p("text") pattern from ir_emit.mx
11665 test(272, `package main
11666
11667 type Emitter struct {
11668 buf []byte
11669 nextReg int32
11670 }
11671
11672 func (e *Emitter) emit() string {
11673 p := func(prefix string) string {
11674 e.nextReg = e.nextReg + 1
11675 return "%" | prefix | itoa272(e.nextReg)
11676 }
11677 var out []byte
11678 r1 := p("t")
11679 out = append(out, r1...)
11680 out = append(out, ' ')
11681 r2 := p("t")
11682 out = append(out, r2...)
11683 out = append(out, ' ')
11684 r3 := p("mi")
11685 out = append(out, r3...)
11686 return string(out)
11687 }
11688
11689 func itoa272(n int32) string {
11690 if n == 0 { return "0" }
11691 var buf [10]byte
11692 i := int32(9)
11693 for n > 0 {
11694 buf[i] = byte(n%10) + '0'
11695 n = n / 10
11696 i = i - 1
11697 }
11698 return string(buf[i+1:])
11699 }
11700
11701 func main() {
11702 e := &Emitter{}
11703 result := e.emit()
11704 _ = result
11705 }
11706 `, func(ir string) {
11707 assert("272: has Emitter.emit", strings.Contains(ir, "@main.Emitter.emit"))
11708 assert("272: closure with capture", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11709 assert("272: string concat via or", strings.Contains(ir, "sliceAppend"))
11710 })
11711
11712 // Test 273: chained method calls with intermediate results
11713 test(273, `package main
11714
11715 type Scope struct {
11716 parent *Scope
11717 names map[string]int32
11718 }
11719
11720 func (s *Scope) Lookup(name string) int32 {
11721 if s.names != nil {
11722 v, ok := s.names[name]
11723 if ok {
11724 return v
11725 }
11726 }
11727 if s.parent != nil {
11728 return s.parent.Lookup(name)
11729 }
11730 return -1
11731 }
11732
11733 func (s *Scope) LookupParent(name string) (*Scope, int32) {
11734 if s.names != nil {
11735 v, ok := s.names[name]
11736 if ok {
11737 return s, v
11738 }
11739 }
11740 if s.parent != nil {
11741 return s.parent.LookupParent(name)
11742 }
11743 return nil, -1
11744 }
11745
11746 func main() {
11747 inner := &Scope{
11748 names: map[string]int32{"x": 1},
11749 }
11750 outer := &Scope{
11751 names: map[string]int32{"y": 2},
11752 }
11753 inner.parent = outer
11754
11755 v1 := inner.Lookup("x")
11756 v2 := inner.Lookup("y")
11757 v3 := inner.Lookup("z")
11758 _ = v1
11759 _ = v2
11760 _ = v3
11761
11762 s, v := inner.LookupParent("y")
11763 _ = s
11764 _ = v
11765 }
11766 `, func(ir string) {
11767 assert("273: has Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
11768 assert("273: has LookupParent", strings.Contains(ir, "@main.Scope.LookupParent"))
11769 assert("273: recursive call", strings.Count(ir, "call") >= 2)
11770 assert("273: multi-return", strings.Contains(ir, "extractvalue"))
11771 })
11772
11773 // Test 274: map[string]bool and delete pattern
11774 test(274, `package main
11775
11776 func main() {
11777 seen := map[string]bool{}
11778 names := []string{"a", "b", "a", "c", "b"}
11779 var unique []string
11780 for _, n := range names {
11781 if !seen[n] {
11782 seen[n] = true
11783 unique = append(unique, n)
11784 }
11785 }
11786 _ = unique
11787
11788 delete(seen, "a")
11789 has := seen["a"]
11790 _ = has
11791 }
11792 `, func(ir string) {
11793 assert("274: hashmapContentSet for map assign", strings.Contains(ir, "hashmapContentSet"))
11794 assert("274: hashmapContentGet for map lookup", strings.Contains(ir, "hashmapContentGet"))
11795 assert("274: hashmapBinaryDelete for delete", strings.Contains(ir, "hashmapBinaryDelete"))
11796 })
11797
11798 // Test 275: interface dispatch with multiple implementors and return values
11799 test(275, `package main
11800
11801 type SSAValue interface {
11802 SSAName() string
11803 SSAType() string
11804 }
11805
11806 type SSAConst struct {
11807 name string
11808 typ string
11809 val int32
11810 }
11811 func (c *SSAConst) SSAName() string { return c.name }
11812 func (c *SSAConst) SSAType() string { return c.typ }
11813
11814 type SSABinOp struct {
11815 name string
11816 typ string
11817 op string
11818 x SSAValue
11819 y SSAValue
11820 }
11821 func (b *SSABinOp) SSAName() string { return b.name }
11822 func (b *SSABinOp) SSAType() string { return b.typ }
11823
11824 func operand(v SSAValue) string {
11825 return v.SSAName()
11826 }
11827
11828 func emitBinOp(b *SSABinOp) string {
11829 return b.SSAName() | " = " | b.op | " " | b.SSAType() | " " | operand(b.x) | ", " | operand(b.y)
11830 }
11831
11832 func main() {
11833 c1 := &SSAConst{name: "%c1", typ: "i32", val: 1}
11834 c2 := &SSAConst{name: "%c2", typ: "i32", val: 2}
11835 add := &SSABinOp{name: "%t1", typ: "i32", op: "add", x: c1, y: c2}
11836 result := emitBinOp(add)
11837 _ = result
11838
11839 name := operand(c1)
11840 _ = name
11841 }
11842 `, func(ir string) {
11843 assert("275: has operand", strings.Contains(ir, "@main.operand"))
11844 assert("275: has emitBinOp", strings.Contains(ir, "@main.emitBinOp"))
11845 assert("275: interface dispatch", strings.Contains(ir, "icmp eq ptr") || strings.Contains(ir, "SSAName"))
11846 })
11847
11848 // Test 276: struct with map field, range with both key and value used
11849 test(276, `package main
11850
11851 type Scope struct {
11852 parent *Scope
11853 objects map[string]*Object
11854 }
11855
11856 type Object struct {
11857 name string
11858 kind int32
11859 }
11860
11861 func NewScope(parent *Scope) *Scope {
11862 return &Scope{parent: parent, objects: map[string]*Object{}}
11863 }
11864
11865 func (s *Scope) Insert(obj *Object) {
11866 s.objects[obj.name] = obj
11867 }
11868
11869 func (s *Scope) Lookup(name string) *Object {
11870 if s.objects != nil {
11871 obj, ok := s.objects[name]
11872 if ok {
11873 return obj
11874 }
11875 }
11876 if s.parent != nil {
11877 return s.parent.Lookup(name)
11878 }
11879 return nil
11880 }
11881
11882 func (s *Scope) NumObjects() int32 {
11883 n := int32(0)
11884 for _, obj := range s.objects {
11885 _ = obj
11886 n = n + 1
11887 }
11888 return n
11889 }
11890
11891 func main() {
11892 outer := NewScope(nil)
11893 outer.Insert(&Object{name: "int", kind: 1})
11894 outer.Insert(&Object{name: "string", kind: 2})
11895
11896 inner := NewScope(outer)
11897 inner.Insert(&Object{name: "x", kind: 3})
11898
11899 o1 := inner.Lookup("x")
11900 o2 := inner.Lookup("int")
11901 o3 := inner.Lookup("missing")
11902 _ = o1
11903 _ = o2
11904 _ = o3
11905
11906 n := outer.NumObjects()
11907 _ = n
11908 }
11909 `, func(ir string) {
11910 assert("276: has NewScope", strings.Contains(ir, "@main.NewScope"))
11911 assert("276: has Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
11912 assert("276: has NumObjects", strings.Contains(ir, "@main.Scope.NumObjects"))
11913 assert("276: map operations", strings.Contains(ir, "hashmapContentGet"))
11914 })
11915
11916 // Test 277: type switch with nil check and multiple concrete types
11917 test(277, `package main
11918
11919 type Expr interface {
11920 exprNode()
11921 }
11922
11923 type Ident struct {
11924 name string
11925 }
11926 func (i *Ident) exprNode() {}
11927
11928 type Call struct {
11929 fn Expr
11930 args []Expr
11931 }
11932 func (c *Call) exprNode() {}
11933
11934 type Literal struct {
11935 val int32
11936 }
11937 func (l *Literal) exprNode() {}
11938
11939 func describe(e Expr) string {
11940 if e == nil {
11941 return "nil"
11942 }
11943 switch x := e.(type) {
11944 case *Ident:
11945 return "ident:" | x.name
11946 case *Call:
11947 return "call"
11948 case *Literal:
11949 _ = x.val
11950 return "literal"
11951 }
11952 return "unknown"
11953 }
11954
11955 func main() {
11956 i := &Ident{name: "foo"}
11957 l := &Literal{val: 42}
11958 c := &Call{fn: i, args: []Expr{l}}
11959
11960 s1 := describe(i)
11961 s2 := describe(l)
11962 s3 := describe(c)
11963 s4 := describe(nil)
11964 _ = s1
11965 _ = s2
11966 _ = s3
11967 _ = s4
11968 }
11969 `, func(ir string) {
11970 assert("277: has describe", strings.Contains(ir, "@main.describe"))
11971 assert("277: nil check", strings.Contains(ir, "icmp eq") || strings.Contains(ir, "null"))
11972 assert("277: type switch branches", strings.Contains(ir, "typeid"))
11973 })
11974
11975 // Test 278: func literal returning value, multiple closures in same func
11976 test(278, `package main
11977
11978 type Writer struct {
11979 buf []byte
11980 }
11981
11982 func (w *Writer) emit(prefix string, n int32) string {
11983 p := func(s string) {
11984 w.buf = append(w.buf, s...)
11985 }
11986 num := func(v int32) string {
11987 if v == 0 { return "0" }
11988 var b [10]byte
11989 i := int32(9)
11990 for v > 0 {
11991 b[i] = byte(v%10) + '0'
11992 v = v / 10
11993 i = i - 1
11994 }
11995 return string(b[i+1:])
11996 }
11997 p(prefix)
11998 s := num(n)
11999 p(s)
12000 return string(w.buf)
12001 }
12002
12003 func main() {
12004 w := &Writer{}
12005 result := w.emit("count=", 42)
12006 _ = result
12007 }
12008 `, func(ir string) {
12009 assert("278: has Writer.emit", strings.Contains(ir, "@main.Writer.emit"))
12010 assert("278: two closures", strings.Count(ir, "insertvalue {ptr, ptr}") >= 2)
12011 assert("278: array subslice in closure", strings.Contains(ir, "alloca [10 x i8]"))
12012 })
12013
12014 // Test 279: method on result of method call (chained dispatch)
12015 test(279, `package main
12016
12017 type Token struct {
12018 kind int32
12019 text string
12020 }
12021
12022 type Scanner struct {
12023 src []byte
12024 pos int32
12025 }
12026
12027 func (s *Scanner) peek() byte {
12028 if int32(len(s.src)) <= s.pos {
12029 return 0
12030 }
12031 return s.src[s.pos]
12032 }
12033
12034 func (s *Scanner) next() *Token {
12035 ch := s.peek()
12036 if ch == 0 {
12037 return &Token{kind: 0, text: ""}
12038 }
12039 s.pos = s.pos + 1
12040 return &Token{kind: int32(ch), text: string(s.src[s.pos-1:s.pos])}
12041 }
12042
12043 func main() {
12044 s := &Scanner{src: []byte("abc"), pos: 0}
12045 t1 := s.next()
12046 t2 := s.next()
12047 _ = t1.text
12048 _ = t2.kind
12049 }
12050 `, func(ir string) {
12051 assert("279: has Scanner.peek", strings.Contains(ir, "@main.Scanner.peek"))
12052 assert("279: has Scanner.next", strings.Contains(ir, "@main.Scanner.next"))
12053 assert("279: field access on result", strings.Contains(ir, "getelementptr"))
12054 })
12055
12056 // Test 280: interface slice iteration with type assertion
12057 test(280, `package main
12058
12059 type Instruction interface {
12060 String() string
12061 }
12062
12063 type Add struct {
12064 dst string
12065 x string
12066 y string
12067 }
12068 func (a *Add) String() string { return a.dst | " = add " | a.x | " " | a.y }
12069
12070 type Ret struct {
12071 val string
12072 }
12073 func (r *Ret) String() string { return "ret " | r.val }
12074
12075 func printAll(instrs []Instruction) string {
12076 var out []byte
12077 for _, instr := range instrs {
12078 s := instr.String()
12079 out = append(out, s...)
12080 out = append(out, '\n')
12081 }
12082 return string(out)
12083 }
12084
12085 func countAdds(instrs []Instruction) int32 {
12086 n := int32(0)
12087 for _, instr := range instrs {
12088 if _, ok := instr.(*Add); ok {
12089 n = n + 1
12090 }
12091 }
12092 return n
12093 }
12094
12095 func main() {
12096 instrs := []Instruction{
12097 &Add{dst: "%1", x: "%a", y: "%b"},
12098 &Add{dst: "%2", x: "%1", y: "%c"},
12099 &Ret{val: "%2"},
12100 }
12101 s := printAll(instrs)
12102 _ = s
12103 n := countAdds(instrs)
12104 _ = n
12105 }
12106 `, func(ir string) {
12107 assert("280: has printAll", strings.Contains(ir, "@main.printAll"))
12108 assert("280: has countAdds", strings.Contains(ir, "@main.countAdds"))
12109 assert("280: interface invoke String", strings.Contains(ir, "icmp eq ptr"))
12110 assert("280: slice of interfaces", strings.Contains(ir, "insertvalue {ptr, ptr}"))
12111 })
12112
12113 // Test 281: nested struct literal with embedded field init
12114 test(281, `package main
12115
12116 type Pos struct {
12117 line int32
12118 col int32
12119 }
12120
12121 type Name struct {
12122 Value string
12123 pos Pos
12124 }
12125
12126 type Field struct {
12127 Name *Name
12128 Type *Name
12129 Exported bool
12130 }
12131
12132 type StructType struct {
12133 fields []*Field
12134 }
12135
12136 func (s *StructType) NumFields() int32 { return int32(len(s.fields)) }
12137
12138 func main() {
12139 st := &StructType{
12140 fields: []*Field{
12141 {Name: &Name{Value: "x", pos: Pos{line: 1, col: 5}}, Type: &Name{Value: "int32"}, Exported: false},
12142 {Name: &Name{Value: "Y", pos: Pos{line: 2, col: 5}}, Type: &Name{Value: "string"}, Exported: true},
12143 },
12144 }
12145 n := st.NumFields()
12146 _ = n
12147 f0 := st.fields[0]
12148 _ = f0.Name.Value
12149 }
12150 `, func(ir string) {
12151 assert("281: has NumFields", strings.Contains(ir, "@main.StructType.NumFields"))
12152 assert("281: nested struct alloc", strings.Contains(ir, "runtime.alloc"))
12153 assert("281: field access chain", strings.Contains(ir, "getelementptr"))
12154 })
12155
12156 // Test 282: byte to int32 conversion and int32 to byte
12157 test(282, `package main
12158
12159 func isLetter(ch byte) bool {
12160 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'
12161 }
12162
12163 func isDigit(ch byte) bool {
12164 return ch >= '0' && ch <= '9'
12165 }
12166
12167 func scanIdent(src []byte, pos int32) (string, int32) {
12168 start := pos
12169 for int32(len(src)) > pos && (isLetter(src[pos]) || isDigit(src[pos])) {
12170 pos = pos + 1
12171 }
12172 return string(src[start:pos]), pos
12173 }
12174
12175 func main() {
12176 src := []byte("hello123 world")
12177 name, end := scanIdent(src, 0)
12178 _ = name
12179 _ = end
12180
12181 b1 := isLetter('x')
12182 b2 := isDigit('5')
12183 b3 := isLetter('9')
12184 _ = b1
12185 _ = b2
12186 _ = b3
12187 }
12188 `, func(ir string) {
12189 assert("282: has isLetter", strings.Contains(ir, "@main.isLetter"))
12190 assert("282: has scanIdent", strings.Contains(ir, "@main.scanIdent"))
12191 assert("282: byte comparison", strings.Contains(ir, "icmp"))
12192 assert("282: multi-return", strings.Contains(ir, "insertvalue"))
12193 })
12194
12195 // Test 283: nil comparison with interface and pointer
12196 test(283, `package main
12197
12198 type Node interface {
12199 Kind() string
12200 }
12201
12202 type Leaf struct {
12203 val int32
12204 }
12205 func (l *Leaf) Kind() string { return "leaf" }
12206
12207 func checkNil(n Node) bool {
12208 return n == nil
12209 }
12210
12211 func checkPtrNil(l *Leaf) bool {
12212 return l == nil
12213 }
12214
12215 func safeKind(n Node) string {
12216 if n == nil {
12217 return "nil"
12218 }
12219 return n.Kind()
12220 }
12221
12222 func main() {
12223 var n Node
12224 b1 := checkNil(n)
12225 _ = b1
12226
12227 l := &Leaf{val: 1}
12228 n = l
12229 b2 := checkNil(n)
12230 _ = b2
12231
12232 b3 := checkPtrNil(nil)
12233 b4 := checkPtrNil(l)
12234 _ = b3
12235 _ = b4
12236
12237 s := safeKind(nil)
12238 _ = s
12239 }
12240 `, func(ir string) {
12241 assert("283: has checkNil", strings.Contains(ir, "@main.checkNil"))
12242 assert("283: has safeKind", strings.Contains(ir, "@main.safeKind"))
12243 assert("283: nil comparison", strings.Contains(ir, "icmp"))
12244 })
12245
12246 // Test 284: switch on string value
12247 test(284, `package main
12248
12249 func tokenKind(s string) int32 {
12250 switch s {
12251 case "func":
12252 return 1
12253 case "var":
12254 return 2
12255 case "type":
12256 return 3
12257 case "return":
12258 return 4
12259 }
12260 return 0
12261 }
12262
12263 func main() {
12264 k1 := tokenKind("func")
12265 k2 := tokenKind("var")
12266 k3 := tokenKind("other")
12267 _ = k1
12268 _ = k2
12269 _ = k3
12270 }
12271 `, func(ir string) {
12272 assert("284: has tokenKind", strings.Contains(ir, "@main.tokenKind"))
12273 assert("284: string compare calls", strings.Contains(ir, "stringEqual") || strings.Contains(ir, "icmp"))
12274 })
12275
12276 // Test 285: for-range with index only (map key iteration)
12277 test(285, `package main
12278
12279 func keys(m map[string]int32) []string {
12280 var result []string
12281 for k := range m {
12282 result = append(result, k)
12283 }
12284 return result
12285 }
12286
12287 func sumValues(m map[string]int32) int32 {
12288 total := int32(0)
12289 for _, v := range m {
12290 total = total + v
12291 }
12292 return total
12293 }
12294
12295 func main() {
12296 m := map[string]int32{"a": 1, "b": 2, "c": 3}
12297 ks := keys(m)
12298 _ = ks
12299 s := sumValues(m)
12300 _ = s
12301 }
12302 `, func(ir string) {
12303 assert("285: has keys", strings.Contains(ir, "@main.keys"))
12304 assert("285: has sumValues", strings.Contains(ir, "@main.sumValues"))
12305 assert("285: map iteration", strings.Contains(ir, "hashmapNext"))
12306 })
12307
12308 // Test 286: SSA builder pattern - func builder with emit method and block management
12309 test(286, `package main
12310
12311 type Instruction interface {
12312 String() string
12313 }
12314
12315 type Block struct {
12316 instrs []Instruction
12317 name string
12318 }
12319
12320 type Add struct {
12321 dst string
12322 src string
12323 }
12324 func (a *Add) String() string { return a.dst | " = add " | a.src }
12325
12326 type Ret struct{}
12327 func (r *Ret) String() string { return "ret" }
12328
12329 type FuncBuilder struct {
12330 blocks []*Block
12331 cur *Block
12332 nextN int32
12333 }
12334
12335 func (fb *FuncBuilder) newBlock(name string) *Block {
12336 b := &Block{name: name}
12337 fb.blocks = append(fb.blocks, b)
12338 return b
12339 }
12340
12341 func (fb *FuncBuilder) emit(i Instruction) {
12342 fb.cur.instrs = append(fb.cur.instrs, i)
12343 }
12344
12345 func (fb *FuncBuilder) nextName() string {
12346 fb.nextN = fb.nextN + 1
12347 return "%t" | itoa286(fb.nextN)
12348 }
12349
12350 func itoa286(n int32) string {
12351 if n == 0 { return "0" }
12352 var buf [10]byte
12353 i := int32(9)
12354 for n > 0 {
12355 buf[i] = byte(n%10) + '0'
12356 n = n / 10
12357 i = i - 1
12358 }
12359 return string(buf[i+1:])
12360 }
12361
12362 func main() {
12363 fb := &FuncBuilder{}
12364 entry := fb.newBlock("entry")
12365 fb.cur = entry
12366 n1 := fb.nextName()
12367 n2 := fb.nextName()
12368 fb.emit(&Add{dst: n1, src: "%arg0"})
12369 fb.emit(&Add{dst: n2, src: n1})
12370 fb.emit(&Ret{})
12371 total := int32(0)
12372 for _, b := range fb.blocks {
12373 total = total + int32(len(b.instrs))
12374 }
12375 _ = total
12376 }
12377 `, func(ir string) {
12378 assert("286: has FuncBuilder.emit", strings.Contains(ir, "@main.FuncBuilder.emit"))
12379 assert("286: has FuncBuilder.nextName", strings.Contains(ir, "@main.FuncBuilder.nextName"))
12380 assert("286: has FuncBuilder.newBlock", strings.Contains(ir, "@main.FuncBuilder.newBlock"))
12381 assert("286: interface boxing in emit", strings.Contains(ir, "insertvalue {ptr, ptr}"))
12382 })
12383
12384 // Test 287: type resolution pattern - resolve through Named and Pointer layers
12385 test(287, `package main
12386
12387 type Type interface {
12388 Underlying() Type
12389 }
12390
12391 type Basic struct {
12392 kind int32
12393 name string
12394 }
12395 func (b *Basic) Underlying() Type { return b }
12396
12397 type Pointer struct {
12398 base Type
12399 }
12400 func (p *Pointer) Underlying() Type { return p }
12401 func (p *Pointer) Elem() Type { return p.base }
12402
12403 type Named struct {
12404 obj *TypeName
12405 underlying Type
12406 }
12407 func (n *Named) Underlying() Type {
12408 if n.underlying != nil {
12409 return n.underlying
12410 }
12411 return n
12412 }
12413 func (n *Named) Obj() *TypeName { return n.obj }
12414
12415 type TypeName struct {
12416 name string
12417 typ Type
12418 }
12419 func (tn *TypeName) Name() string { return tn.name }
12420 func (tn *TypeName) Type() Type { return tn.typ }
12421
12422 type Slice struct {
12423 elem Type
12424 }
12425 func (s *Slice) Underlying() Type { return s }
12426 func (s *Slice) Elem() Type { return s.elem }
12427
12428 func llvmType(t Type) string {
12429 if t == nil {
12430 return "void"
12431 }
12432 switch u := t.Underlying().(type) {
12433 case *Basic:
12434 switch u.kind {
12435 case 1: return "i32"
12436 case 2: return "i64"
12437 case 3: return "{ptr, i64, i64}"
12438 }
12439 case *Pointer:
12440 return "ptr"
12441 case *Slice:
12442 return "{ptr, i64, i64}"
12443 }
12444 return "void"
12445 }
12446
12447 func isPointer(t Type) bool {
12448 _, ok := t.Underlying().(*Pointer)
12449 return ok
12450 }
12451
12452 func main() {
12453 intType := &Basic{kind: 1, name: "int32"}
12454 strType := &Basic{kind: 3, name: "string"}
12455 ptrInt := &Pointer{base: intType}
12456 tn := &TypeName{name: "MyInt"}
12457 named := &Named{obj: tn, underlying: intType}
12458 tn.typ = named
12459 sliceStr := &Slice{elem: strType}
12460
12461 s1 := llvmType(intType)
12462 s2 := llvmType(ptrInt)
12463 s3 := llvmType(named)
12464 s4 := llvmType(sliceStr)
12465 s5 := llvmType(nil)
12466 _ = s1
12467 _ = s2
12468 _ = s3
12469 _ = s4
12470 _ = s5
12471
12472 b1 := isPointer(ptrInt)
12473 b2 := isPointer(intType)
12474 _ = b1
12475 _ = b2
12476 }
12477 `, func(ir string) {
12478 assert("287: has llvmType", strings.Contains(ir, "@main.llvmType"))
12479 assert("287: has isPointer", strings.Contains(ir, "@main.isPointer"))
12480 assert("287: type switch dispatch", strings.Contains(ir, "icmp eq ptr"))
12481 assert("287: nested switch", strings.Contains(ir, "icmp eq i32"))
12482 })
12483
12484 // Test 288: emitter pattern - write() calls with string concat building IR output
12485 test(288, `package main
12486
12487 type Emitter struct {
12488 buf []byte
12489 nextReg int32
12490 }
12491
12492 func (e *Emitter) w(s string) {
12493 e.buf = append(e.buf, s...)
12494 }
12495
12496 func (e *Emitter) regName() string {
12497 e.nextReg = e.nextReg + 1
12498 return "%t" | itoa288(e.nextReg)
12499 }
12500
12501 func (e *Emitter) emitAdd(dst string, lhs string, rhs string) {
12502 e.w(" ")
12503 e.w(dst)
12504 e.w(" = add i32 ")
12505 e.w(lhs)
12506 e.w(", ")
12507 e.w(rhs)
12508 e.w("\n")
12509 }
12510
12511 func (e *Emitter) emitRet(val string) {
12512 e.w(" ret i32 ")
12513 e.w(val)
12514 e.w("\n")
12515 }
12516
12517 func itoa288(n int32) string {
12518 if n == 0 { return "0" }
12519 var buf [10]byte
12520 i := int32(9)
12521 for n > 0 {
12522 buf[i] = byte(n%10) + '0'
12523 n = n / 10
12524 i = i - 1
12525 }
12526 return string(buf[i+1:])
12527 }
12528
12529 func main() {
12530 e := &Emitter{}
12531 r1 := e.regName()
12532 r2 := e.regName()
12533 e.emitAdd(r1, "%arg0", "%arg1")
12534 e.emitAdd(r2, r1, "%arg2")
12535 e.emitRet(r2)
12536 result := string(e.buf)
12537 _ = result
12538 }
12539 `, func(ir string) {
12540 assert("288: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
12541 assert("288: has Emitter.regName", strings.Contains(ir, "@main.Emitter.regName"))
12542 assert("288: has Emitter.emitAdd", strings.Contains(ir, "@main.Emitter.emitAdd"))
12543 assert("288: sliceAppend for buf", strings.Contains(ir, "sliceAppend"))
12544 })
12545
12546 // Test 289: SSA const pattern - nil type, typed nil, constant values
12547 test(289, `package main
12548
12549 type Type interface {
12550 String() string
12551 }
12552
12553 type Basic struct {
12554 name string
12555 }
12556 func (b *Basic) String() string { return b.name }
12557
12558 type Const struct {
12559 typ Type
12560 val int32
12561 }
12562
12563 func (c *Const) SSAType() Type { return c.typ }
12564
12565 func operand289(c *Const) string {
12566 if c.typ == nil {
12567 return "null"
12568 }
12569 if c.val == 0 {
12570 return "zeroinitializer"
12571 }
12572 return itoa289(c.val)
12573 }
12574
12575 func itoa289(n int32) string {
12576 if n < 0 {
12577 return "-" | itoa289(-n)
12578 }
12579 if n == 0 { return "0" }
12580 var buf [10]byte
12581 i := int32(9)
12582 for n > 0 {
12583 buf[i] = byte(n%10) + '0'
12584 n = n / 10
12585 i = i - 1
12586 }
12587 return string(buf[i+1:])
12588 }
12589
12590 func main() {
12591 intType := &Basic{name: "i32"}
12592 c1 := &Const{typ: intType, val: 42}
12593 c2 := &Const{typ: intType, val: 0}
12594 c3 := &Const{typ: nil, val: 0}
12595
12596 s1 := operand289(c1)
12597 s2 := operand289(c2)
12598 s3 := operand289(c3)
12599 _ = s1
12600 _ = s2
12601 _ = s3
12602
12603 t := c1.SSAType()
12604 _ = t
12605 }
12606 `, func(ir string) {
12607 assert("289: has operand289", strings.Contains(ir, "@main.operand289"))
12608 assert("289: has itoa289", strings.Contains(ir, "@main.itoa289"))
12609 assert("289: recursive call for negative", strings.Count(ir, "call") >= 2)
12610 })
12611
12612 // Test 290: 300-line stress test - mini compiler pipeline
12613 test(290, `package main
12614
12615 type Token struct {
12616 kind int32
12617 text string
12618 pos int32
12619 }
12620
12621 type Expr interface {
12622 exprNode()
12623 }
12624
12625 type NameExpr struct {
12626 name string
12627 }
12628 func (n *NameExpr) exprNode() {}
12629
12630 type BinExpr struct {
12631 op string
12632 x Expr
12633 y Expr
12634 }
12635 func (b *BinExpr) exprNode() {}
12636
12637 type CallExpr struct {
12638 fn Expr
12639 args []Expr
12640 }
12641 func (c *CallExpr) exprNode() {}
12642
12643 type LitExpr struct {
12644 val int32
12645 }
12646 func (l *LitExpr) exprNode() {}
12647
12648 type Stmt interface {
12649 stmtNode()
12650 }
12651
12652 type ReturnStmt struct {
12653 val Expr
12654 }
12655 func (r *ReturnStmt) stmtNode() {}
12656
12657 type AssignStmt struct {
12658 name string
12659 val Expr
12660 }
12661 func (a *AssignStmt) stmtNode() {}
12662
12663 type SSAValue interface {
12664 Name() string
12665 Type() string
12666 }
12667
12668 type SSAReg struct {
12669 name string
12670 typ string
12671 }
12672 func (r *SSAReg) Name() string { return r.name }
12673 func (r *SSAReg) Type() string { return r.typ }
12674
12675 type SSAConst struct {
12676 name string
12677 typ string
12678 val int32
12679 }
12680 func (c *SSAConst) Name() string { return c.name }
12681 func (c *SSAConst) Type() string { return c.typ }
12682
12683 type SSAInstr interface {
12684 InstrString() string
12685 }
12686
12687 type SSABinOp struct {
12688 dst SSAValue
12689 op string
12690 x SSAValue
12691 y SSAValue
12692 }
12693 func (b *SSABinOp) InstrString() string {
12694 return b.dst.Name() | " = " | b.op | " " | b.dst.Type() | " " | b.x.Name() | ", " | b.y.Name()
12695 }
12696
12697 type SSARet struct {
12698 val SSAValue
12699 }
12700 func (r *SSARet) InstrString() string {
12701 if r.val == nil {
12702 return "ret void"
12703 }
12704 return "ret " | r.val.Type() | " " | r.val.Name()
12705 }
12706
12707 type SSABlock struct {
12708 name string
12709 instrs []SSAInstr
12710 }
12711
12712 func (b *SSABlock) emit(i SSAInstr) {
12713 b.instrs = append(b.instrs, i)
12714 }
12715
12716 type Builder struct {
12717 blocks []*SSABlock
12718 cur *SSABlock
12719 nextID int32
12720 env map[string]SSAValue
12721 }
12722
12723 func NewBuilder() *Builder {
12724 b := &Builder{env: map[string]SSAValue{}}
12725 entry := &SSABlock{name: "entry"}
12726 b.blocks = append(b.blocks, entry)
12727 b.cur = entry
12728 return b
12729 }
12730
12731 func (b *Builder) fresh() string {
12732 b.nextID = b.nextID + 1
12733 return "%t" | itoa290(b.nextID)
12734 }
12735
12736 func (b *Builder) buildExpr(e Expr) SSAValue {
12737 switch x := e.(type) {
12738 case *LitExpr:
12739 return &SSAConst{name: itoa290(x.val), typ: "i32", val: x.val}
12740 case *NameExpr:
12741 v, ok := b.env[x.name]
12742 if ok {
12743 return v
12744 }
12745 return &SSAReg{name: "%" | x.name, typ: "i32"}
12746 case *BinExpr:
12747 lhs := b.buildExpr(x.x)
12748 rhs := b.buildExpr(x.y)
12749 dst := &SSAReg{name: b.fresh(), typ: "i32"}
12750 b.cur.emit(&SSABinOp{dst: dst, op: x.op, x: lhs, y: rhs})
12751 return dst
12752 case *CallExpr:
12753 dst := &SSAReg{name: b.fresh(), typ: "i32"}
12754 return dst
12755 }
12756 return nil
12757 }
12758
12759 func (b *Builder) buildStmt(s Stmt) {
12760 switch x := s.(type) {
12761 case *AssignStmt:
12762 v := b.buildExpr(x.val)
12763 if v != nil {
12764 b.env[x.name] = v
12765 }
12766 case *ReturnStmt:
12767 v := b.buildExpr(x.val)
12768 b.cur.emit(&SSARet{val: v})
12769 }
12770 }
12771
12772 func (b *Builder) render() string {
12773 var out []byte
12774 for _, bl := range b.blocks {
12775 out = append(out, bl.name...)
12776 out = append(out, ':')
12777 out = append(out, '\n')
12778 for _, instr := range bl.instrs {
12779 out = append(out, ' ')
12780 out = append(out, ' ')
12781 s := instr.InstrString()
12782 out = append(out, s...)
12783 out = append(out, '\n')
12784 }
12785 }
12786 return string(out)
12787 }
12788
12789 func itoa290(n int32) string {
12790 if n == 0 { return "0" }
12791 neg := false
12792 if n < 0 {
12793 neg = true
12794 n = -n
12795 }
12796 var buf [10]byte
12797 i := int32(9)
12798 for n > 0 {
12799 buf[i] = byte(n%10) + '0'
12800 n = n / 10
12801 i = i - 1
12802 }
12803 if neg {
12804 buf[i] = '-'
12805 i = i - 1
12806 }
12807 return string(buf[i+1:])
12808 }
12809
12810 func main() {
12811 b := NewBuilder()
12812
12813 stmts := []Stmt{
12814 &AssignStmt{name: "sum", val: &BinExpr{op: "add", x: &LitExpr{val: 1}, y: &LitExpr{val: 2}}},
12815 &AssignStmt{name: "prod", val: &BinExpr{op: "mul", x: &NameExpr{name: "sum"}, y: &LitExpr{val: 3}}},
12816 &ReturnStmt{val: &NameExpr{name: "prod"}},
12817 }
12818 for _, s := range stmts {
12819 b.buildStmt(s)
12820 }
12821 result := b.render()
12822 _ = result
12823
12824 n := int32(0)
12825 for _, bl := range b.blocks {
12826 n = n + int32(len(bl.instrs))
12827 }
12828 _ = n
12829 }
12830 `, func(ir string) {
12831 assert("290: has NewBuilder", strings.Contains(ir, "@main.NewBuilder"))
12832 assert("290: has Builder.buildExpr", strings.Contains(ir, "@main.Builder.buildExpr"))
12833 assert("290: has Builder.buildStmt", strings.Contains(ir, "@main.Builder.buildStmt"))
12834 assert("290: has Builder.render", strings.Contains(ir, "@main.Builder.render"))
12835 assert("290: type switches in buildExpr", strings.Contains(ir, "typeid"))
12836 assert("290: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
12837 assert("290: map operations", strings.Contains(ir, "hashmapContent"))
12838 assert("290: interface slice boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
12839 })
12840
12841 // Test 291: tagless switch (switch { case cond: }) and if-init
12842 test(291, `package main
12843
12844 func classify(n int32) string {
12845 switch {
12846 case n < 0:
12847 return "negative"
12848 case n == 0:
12849 return "zero"
12850 case n < 10:
12851 return "small"
12852 case n < 100:
12853 return "medium"
12854 }
12855 return "large"
12856 }
12857
12858 func safeLookup(m map[string]int32, key string) int32 {
12859 if v, ok := m[key]; ok {
12860 return v
12861 }
12862 return -1
12863 }
12864
12865 func main() {
12866 s1 := classify(-5)
12867 s2 := classify(0)
12868 s3 := classify(7)
12869 s4 := classify(50)
12870 s5 := classify(200)
12871 _ = s1
12872 _ = s2
12873 _ = s3
12874 _ = s4
12875 _ = s5
12876
12877 m := map[string]int32{"x": 42}
12878 v1 := safeLookup(m, "x")
12879 v2 := safeLookup(m, "missing")
12880 _ = v1
12881 _ = v2
12882 }
12883 `, func(ir string) {
12884 assert("291: has classify", strings.Contains(ir, "@main.classify"))
12885 assert("291: has safeLookup", strings.Contains(ir, "@main.safeLookup"))
12886 assert("291: branch for cases", strings.Contains(ir, "br i1"))
12887 })
12888
12889 // Test 292: string indexing, byte comparison, break/continue
12890 test(292, `package main
12891
12892 func indexOf(s string, ch byte) int32 {
12893 for i := int32(0); i < int32(len(s)); i = i + 1 {
12894 if s[i] == ch {
12895 return i
12896 }
12897 }
12898 return -1
12899 }
12900
12901 func countChar(s string, ch byte) int32 {
12902 n := int32(0)
12903 for i := int32(0); i < int32(len(s)); i = i + 1 {
12904 if s[i] != ch {
12905 continue
12906 }
12907 n = n + 1
12908 }
12909 return n
12910 }
12911
12912 func skipSpaces(s string, pos int32) int32 {
12913 for pos < int32(len(s)) {
12914 if s[pos] != ' ' && s[pos] != '\t' {
12915 break
12916 }
12917 pos = pos + 1
12918 }
12919 return pos
12920 }
12921
12922 func main() {
12923 i1 := indexOf("hello", 'l')
12924 i2 := indexOf("hello", 'z')
12925 _ = i1
12926 _ = i2
12927
12928 c := countChar("abracadabra", 'a')
12929 _ = c
12930
12931 p := skipSpaces(" hello", 0)
12932 _ = p
12933 }
12934 `, func(ir string) {
12935 assert("292: has indexOf", strings.Contains(ir, "@main.indexOf"))
12936 assert("292: has countChar", strings.Contains(ir, "@main.countChar"))
12937 assert("292: has skipSpaces", strings.Contains(ir, "@main.skipSpaces"))
12938 assert("292: string index gep", strings.Contains(ir, "getelementptr"))
12939 })
12940
12941 // Test 293: nested function calls as arguments f(g(x))
12942 test(293, `package main
12943
12944 type Type interface {
12945 Underlying() Type
12946 }
12947
12948 type Basic struct {
12949 kind int32
12950 }
12951 func (b *Basic) Underlying() Type { return b }
12952
12953 type Pointer struct {
12954 base Type
12955 }
12956 func (p *Pointer) Underlying() Type { return p }
12957 func (p *Pointer) Elem() Type { return p.base }
12958
12959 func NewPointer(base Type) *Pointer {
12960 return &Pointer{base: base}
12961 }
12962
12963 func llvmType(t Type) string {
12964 if t == nil { return "void" }
12965 switch u := t.Underlying().(type) {
12966 case *Basic:
12967 if u.kind == 1 { return "i32" }
12968 if u.kind == 2 { return "i64" }
12969 return "i8"
12970 case *Pointer:
12971 return "ptr"
12972 }
12973 return "void"
12974 }
12975
12976 func ptrType(t Type) string {
12977 return llvmType(NewPointer(t))
12978 }
12979
12980 func main() {
12981 intT := &Basic{kind: 1}
12982 s1 := ptrType(intT)
12983 _ = s1
12984 s2 := llvmType(NewPointer(NewPointer(intT)))
12985 _ = s2
12986 }
12987 `, func(ir string) {
12988 assert("293: has NewPointer", strings.Contains(ir, "@main.NewPointer"))
12989 assert("293: has ptrType", strings.Contains(ir, "@main.ptrType"))
12990 assert("293: nested calls", strings.Count(ir, "call") >= 3)
12991 })
12992
12993 // Test 294: type switch with default, fallthrough to default
12994 test(294, `package main
12995
12996 type Node interface {
12997 nodeKind() int32
12998 }
12999
13000 type IntNode struct {
13001 val int32
13002 }
13003 func (n *IntNode) nodeKind() int32 { return 1 }
13004
13005 type StrNode struct {
13006 val string
13007 }
13008 func (n *StrNode) nodeKind() int32 { return 2 }
13009
13010 type ListNode struct {
13011 items []Node
13012 }
13013 func (n *ListNode) nodeKind() int32 { return 3 }
13014
13015 func describe(n Node) string {
13016 switch x := n.(type) {
13017 case *IntNode:
13018 _ = x.val
13019 return "int"
13020 case *StrNode:
13021 return "str:" | x.val
13022 case *ListNode:
13023 _ = len(x.items)
13024 return "list"
13025 default:
13026 return "unknown"
13027 }
13028 }
13029
13030 func main() {
13031 nodes := []Node{
13032 &IntNode{val: 42},
13033 &StrNode{val: "hello"},
13034 &ListNode{items: []Node{&IntNode{val: 1}}},
13035 }
13036 var results []string
13037 for _, n := range nodes {
13038 s := describe(n)
13039 results = append(results, s)
13040 }
13041 _ = results
13042 }
13043 `, func(ir string) {
13044 assert("294: has describe", strings.Contains(ir, "@main.describe"))
13045 assert("294: type switch with 3 cases", strings.Count(ir, "typeid") >= 3)
13046 assert("294: default case", strings.Contains(ir, "br label") || strings.Contains(ir, "unreachable"))
13047 })
13048
13049 // Test 295: map[string]interface{} pattern (map with interface values)
13050 test(295, `package main
13051
13052 type Value interface {
13053 String() string
13054 }
13055
13056 type IntVal struct {
13057 v int32
13058 }
13059 func (i *IntVal) String() string { return "int" }
13060
13061 type StrVal struct {
13062 v string
13063 }
13064 func (s *StrVal) String() string { return s.v }
13065
13066 func buildEnv() map[string]Value {
13067 env := map[string]Value{}
13068 env["x"] = &IntVal{v: 1}
13069 env["name"] = &StrVal{v: "hello"}
13070 return env
13071 }
13072
13073 func lookupString(env map[string]Value, key string) string {
13074 v, ok := env[key]
13075 if !ok {
13076 return ""
13077 }
13078 return v.String()
13079 }
13080
13081 func main() {
13082 env := buildEnv()
13083 s1 := lookupString(env, "x")
13084 s2 := lookupString(env, "name")
13085 s3 := lookupString(env, "missing")
13086 _ = s1
13087 _ = s2
13088 _ = s3
13089 }
13090 `, func(ir string) {
13091 assert("295: has buildEnv", strings.Contains(ir, "@main.buildEnv"))
13092 assert("295: has lookupString", strings.Contains(ir, "@main.lookupString"))
13093 assert("295: map with interface values", strings.Contains(ir, "hashmapContent"))
13094 assert("295: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13095 })
13096
13097 // Test 296: full SSA type hierarchy - replicates ssa_types.mx patterns
13098 test(296, `package main
13099
13100 type Type interface {
13101 Underlying() Type
13102 String() string
13103 }
13104
13105 type Basic struct {
13106 kind int32
13107 name string
13108 }
13109 func (b *Basic) Underlying() Type { return b }
13110 func (b *Basic) String() string { return b.name }
13111
13112 type Pointer struct {
13113 base Type
13114 }
13115 func (p *Pointer) Underlying() Type { return p }
13116 func (p *Pointer) String() string { return "*" | p.base.String() }
13117 func (p *Pointer) Elem() Type { return p.base }
13118
13119 type Slice struct {
13120 elem Type
13121 }
13122 func (s *Slice) Underlying() Type { return s }
13123 func (s *Slice) String() string { return "[]" | s.elem.String() }
13124 func (s *Slice) Elem() Type { return s.elem }
13125
13126 type SSAValue interface {
13127 SSAName() string
13128 SSAType() Type
13129 }
13130
13131 type SSAInstruction interface {
13132 InstrBlock() *SSABasicBlock
13133 InstrString() string
13134 setBlock(*SSABasicBlock)
13135 }
13136
13137 type SSAMember interface {
13138 MemberName() string
13139 MemberType() Type
13140 }
13141
13142 type SSABasicBlock struct {
13143 Index int32
13144 parent *SSAFunction
13145 Instrs []SSAInstruction
13146 }
13147
13148 type SSAFunction struct {
13149 name string
13150 Blocks []*SSABasicBlock
13151 Params []*SSAParameter
13152 }
13153 func (f *SSAFunction) MemberName() string { return f.name }
13154 func (f *SSAFunction) MemberType() Type { return nil }
13155 func (f *SSAFunction) SSAName() string { return f.name }
13156 func (f *SSAFunction) SSAType() Type { return nil }
13157
13158 type SSAGlobal struct {
13159 name string
13160 typ Type
13161 }
13162 func (g *SSAGlobal) MemberName() string { return g.name }
13163 func (g *SSAGlobal) MemberType() Type { return g.typ }
13164 func (g *SSAGlobal) SSAName() string { return g.name }
13165 func (g *SSAGlobal) SSAType() Type { return g.typ }
13166
13167 type SSAParameter struct {
13168 name string
13169 typ Type
13170 parent *SSAFunction
13171 }
13172 func (p *SSAParameter) SSAName() string { return p.name }
13173 func (p *SSAParameter) SSAType() Type { return p.typ }
13174
13175 type ssaInstr struct {
13176 block *SSABasicBlock
13177 }
13178 func (a *ssaInstr) InstrBlock() *SSABasicBlock { return a.block }
13179 func (a *ssaInstr) setBlock(b *SSABasicBlock) { a.block = b }
13180
13181 type ssaRegister struct {
13182 ssaInstr
13183 name string
13184 typ Type
13185 }
13186 func (r *ssaRegister) SSAName() string { return r.name }
13187 func (r *ssaRegister) SSAType() Type { return r.typ }
13188
13189 type SSAConst struct {
13190 name string
13191 typ Type
13192 val int32
13193 }
13194 func (c *SSAConst) SSAName() string { return c.name }
13195 func (c *SSAConst) SSAType() Type { return c.typ }
13196
13197 type SSABinOp struct {
13198 ssaRegister
13199 Op string
13200 X SSAValue
13201 Y SSAValue
13202 }
13203 func (b *SSABinOp) InstrString() string {
13204 return b.name | " = " | b.Op | " " | b.X.SSAName() | " " | b.Y.SSAName()
13205 }
13206
13207 type SSACall struct {
13208 ssaRegister
13209 Fn SSAValue
13210 Args []SSAValue
13211 }
13212 func (c *SSACall) InstrString() string { return c.name | " = call " | c.Fn.SSAName() }
13213
13214 type SSAStore struct {
13215 ssaInstr
13216 Addr SSAValue
13217 Val SSAValue
13218 }
13219 func (s *SSAStore) InstrString() string { return "store " | s.Val.SSAName() | " -> " | s.Addr.SSAName() }
13220
13221 type SSARet struct {
13222 ssaInstr
13223 Val SSAValue
13224 }
13225 func (r *SSARet) InstrString() string {
13226 if r.Val == nil { return "ret void" }
13227 return "ret " | r.Val.SSAName()
13228 }
13229
13230 type SSAAlloc struct {
13231 ssaRegister
13232 Heap bool
13233 }
13234 func (a *SSAAlloc) InstrString() string {
13235 if a.Heap { return "new " | a.typ.String() }
13236 return "local " | a.typ.String()
13237 }
13238
13239 func NewBasicBlock(f *SSAFunction) *SSABasicBlock {
13240 b := &SSABasicBlock{Index: int32(len(f.Blocks)), parent: f}
13241 f.Blocks = append(f.Blocks, b)
13242 return b
13243 }
13244
13245 func emit(b *SSABasicBlock, i SSAInstruction) {
13246 i.setBlock(b)
13247 b.Instrs = append(b.Instrs, i)
13248 }
13249
13250 type Package struct {
13251 Members map[string]SSAMember
13252 }
13253
13254 func (p *Package) Func(name string) *SSAFunction {
13255 m := p.Members[name]
13256 if m == nil { return nil }
13257 fn, _ := m.(*SSAFunction)
13258 return fn
13259 }
13260
13261 func renderBlock(b *SSABasicBlock) string {
13262 var out []byte
13263 for _, instr := range b.Instrs {
13264 out = append(out, ' ')
13265 out = append(out, ' ')
13266 s := instr.InstrString()
13267 out = append(out, s...)
13268 out = append(out, '\n')
13269 }
13270 return string(out)
13271 }
13272
13273 func main() {
13274 intType := &Basic{kind: 1, name: "i32"}
13275 ptrType := &Pointer{base: intType}
13276
13277 pkg := &Package{Members: map[string]SSAMember{}}
13278
13279 fn := &SSAFunction{name: "main"}
13280 pkg.Members["main"] = fn
13281
13282 g := &SSAGlobal{name: "counter", typ: intType}
13283 pkg.Members["counter"] = g
13284
13285 entry := NewBasicBlock(fn)
13286
13287 p0 := &SSAParameter{name: "%arg0", typ: intType, parent: fn}
13288 fn.Params = append(fn.Params, p0)
13289
13290 alloc := &SSAAlloc{}
13291 alloc.name = "%t1"
13292 alloc.typ = intType
13293 emit(entry, alloc)
13294
13295 c1 := &SSAConst{name: "1", typ: intType, val: 1}
13296
13297 add := &SSABinOp{Op: "add", X: p0, Y: c1}
13298 add.name = "%t2"
13299 add.typ = intType
13300 emit(entry, add)
13301
13302 store := &SSAStore{Addr: alloc, Val: add}
13303 emit(entry, store)
13304
13305 ret := &SSARet{Val: add}
13306 emit(entry, ret)
13307
13308 lookupFn := pkg.Func("main")
13309 _ = lookupFn
13310
13311 lookupGlobal := pkg.Func("counter")
13312 _ = lookupGlobal
13313
13314 ir := renderBlock(entry)
13315 _ = ir
13316
13317 _ = ptrType.String()
13318
13319 blk := add.InstrBlock()
13320 _ = blk
13321
13322 n := int32(0)
13323 for _, b := range fn.Blocks {
13324 n = n + int32(len(b.Instrs))
13325 }
13326 _ = n
13327 }
13328 `, func(ir string) {
13329 assert("296: has SSAFunction", strings.Contains(ir, "SSAFunction"))
13330 assert("296: has SSABinOp.InstrString", strings.Contains(ir, "@main.SSABinOp.InstrString"))
13331 assert("296: has SSARet.InstrString", strings.Contains(ir, "@main.SSARet.InstrString"))
13332 assert("296: has Package.Func", strings.Contains(ir, "@main.Package.Func"))
13333 assert("296: has renderBlock", strings.Contains(ir, "@main.renderBlock"))
13334 assert("296: 2-level embedding block access", strings.Contains(ir, "@main.ssaInstr.InstrBlock"))
13335 assert("296: setBlock via embedding", strings.Contains(ir, "@main.ssaInstr.setBlock"))
13336 assert("296: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13337 assert("296: map operations", strings.Contains(ir, "hashmapContent"))
13338 assert("296: interface boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
13339 })
13340
13341 // Test 297: promoted method called through interface dispatch (the real self-compile pattern)
13342 test(297, `package main
13343
13344 type SSAInstruction interface {
13345 InstrBlock() *Block
13346 InstrString() string
13347 setBlock(*Block)
13348 }
13349
13350 type Block struct {
13351 Index int32
13352 Instrs []SSAInstruction
13353 }
13354
13355 func (b *Block) emit(i SSAInstruction) {
13356 i.setBlock(b)
13357 b.Instrs = append(b.Instrs, i)
13358 }
13359
13360 type instrBase struct {
13361 block *Block
13362 }
13363 func (a *instrBase) InstrBlock() *Block { return a.block }
13364 func (a *instrBase) setBlock(b *Block) { a.block = b }
13365
13366 type register struct {
13367 instrBase
13368 name string
13369 typ string
13370 }
13371
13372 type BinOp struct {
13373 register
13374 Op string
13375 }
13376 func (b *BinOp) InstrString() string { return b.name | " = " | b.Op }
13377
13378 type Store struct {
13379 instrBase
13380 dst string
13381 src string
13382 }
13383 func (s *Store) InstrString() string { return "store " | s.src | " -> " | s.dst }
13384
13385 type Ret struct {
13386 instrBase
13387 val string
13388 }
13389 func (r *Ret) InstrString() string { return "ret " | r.val }
13390
13391 func renderIR(b *Block) string {
13392 var out []byte
13393 for _, instr := range b.Instrs {
13394 s := instr.InstrString()
13395 out = append(out, s...)
13396 out = append(out, '\n')
13397 blk := instr.InstrBlock()
13398 if blk != nil && blk.Index != b.Index {
13399 out = append(out, "; wrong block\n"...)
13400 }
13401 }
13402 return string(out)
13403 }
13404
13405 func main() {
13406 b := &Block{Index: 0}
13407
13408 add := &BinOp{Op: "add"}
13409 add.name = "%t1"
13410 add.typ = "i32"
13411 b.emit(add)
13412
13413 store := &Store{dst: "%x", src: "%t1"}
13414 b.emit(store)
13415
13416 ret := &Ret{val: "%t1"}
13417 b.emit(ret)
13418
13419 ir := renderIR(b)
13420 _ = ir
13421
13422 blk := add.InstrBlock()
13423 _ = blk
13424
13425 n := int32(len(b.Instrs))
13426 _ = n
13427 }
13428 `, func(ir string) {
13429 assert("297: has Block.emit", strings.Contains(ir, "@main.Block.emit"))
13430 assert("297: has renderIR", strings.Contains(ir, "@main.renderIR"))
13431 assert("297: promoted InstrBlock", strings.Contains(ir, "@main.instrBase.InstrBlock"))
13432 assert("297: promoted setBlock", strings.Contains(ir, "@main.instrBase.setBlock"))
13433 assert("297: BinOp.InstrString", strings.Contains(ir, "@main.BinOp.InstrString"))
13434 assert("297: interface dispatch for InstrString", strings.Contains(ir, "icmp eq ptr"))
13435 })
13436
13437 // Test 298: switch on named int type (SSAOp pattern from ssa_types.mx)
13438 test(298, `package main
13439
13440 type Op int32
13441
13442 const (
13443 OpAdd Op = iota
13444 OpSub
13445 OpMul
13446 OpDiv
13447 OpEq
13448 OpNe
13449 OpLt
13450 OpGt
13451 )
13452
13453 func (op Op) String() string {
13454 switch op {
13455 case OpAdd: return "+"
13456 case OpSub: return "-"
13457 case OpMul: return "*"
13458 case OpDiv: return "/"
13459 case OpEq: return "=="
13460 case OpNe: return "!="
13461 case OpLt: return "<"
13462 case OpGt: return ">"
13463 }
13464 return "?"
13465 }
13466
13467 func (op Op) IsComparison() bool {
13468 return op >= OpEq
13469 }
13470
13471 func (op Op) Precedence() int32 {
13472 switch {
13473 case op == OpMul || op == OpDiv:
13474 return 2
13475 case op == OpAdd || op == OpSub:
13476 return 1
13477 }
13478 return 0
13479 }
13480
13481 func main() {
13482 ops := []Op{OpAdd, OpSub, OpMul, OpEq, OpLt}
13483 var strs []string
13484 for _, op := range ops {
13485 strs = append(strs, op.String())
13486 }
13487 _ = strs
13488
13489 b1 := OpEq.IsComparison()
13490 b2 := OpAdd.IsComparison()
13491 _ = b1
13492 _ = b2
13493
13494 p := OpMul.Precedence()
13495 _ = p
13496 }
13497 `, func(ir string) {
13498 assert("298: has Op.String", strings.Contains(ir, "@main.Op.String"))
13499 assert("298: has Op.IsComparison", strings.Contains(ir, "@main.Op.IsComparison"))
13500 assert("298: has Op.Precedence", strings.Contains(ir, "@main.Op.Precedence"))
13501 assert("298: switch on i32", strings.Contains(ir, "icmp eq i32"))
13502 })
13503
13504 // Test 299: map[string]SSAMember with type assertion and iteration
13505 test(299, `package main
13506
13507 type SSAMember interface {
13508 MemberName() string
13509 }
13510
13511 type SSAFunction struct {
13512 name string
13513 body string
13514 }
13515 func (f *SSAFunction) MemberName() string { return f.name }
13516
13517 type SSAGlobal struct {
13518 name string
13519 typ string
13520 }
13521 func (g *SSAGlobal) MemberName() string { return g.name }
13522
13523 type SSAPackage struct {
13524 Members map[string]SSAMember
13525 }
13526
13527 func (p *SSAPackage) Func(name string) *SSAFunction {
13528 m := p.Members[name]
13529 if m == nil { return nil }
13530 fn, ok := m.(*SSAFunction)
13531 if !ok { return nil }
13532 return fn
13533 }
13534
13535 func (p *SSAPackage) AllFuncs() []*SSAFunction {
13536 var funcs []*SSAFunction
13537 for _, m := range p.Members {
13538 if fn, ok := m.(*SSAFunction); ok {
13539 funcs = append(funcs, fn)
13540 }
13541 }
13542 return funcs
13543 }
13544
13545 func (p *SSAPackage) AllNames() []string {
13546 var names []string
13547 for name := range p.Members {
13548 names = append(names, name)
13549 }
13550 return names
13551 }
13552
13553 func main() {
13554 pkg := &SSAPackage{Members: map[string]SSAMember{}}
13555 pkg.Members["main"] = &SSAFunction{name: "main", body: "entry"}
13556 pkg.Members["init"] = &SSAFunction{name: "init", body: ""}
13557 pkg.Members["counter"] = &SSAGlobal{name: "counter", typ: "i32"}
13558
13559 fn := pkg.Func("main")
13560 _ = fn
13561 nilFn := pkg.Func("counter")
13562 _ = nilFn
13563 missingFn := pkg.Func("missing")
13564 _ = missingFn
13565
13566 allFn := pkg.AllFuncs()
13567 _ = allFn
13568 allN := pkg.AllNames()
13569 _ = allN
13570 }
13571 `, func(ir string) {
13572 assert("299: has SSAPackage.Func", strings.Contains(ir, "@main.SSAPackage.Func"))
13573 assert("299: has SSAPackage.AllFuncs", strings.Contains(ir, "@main.SSAPackage.AllFuncs"))
13574 assert("299: has SSAPackage.AllNames", strings.Contains(ir, "@main.SSAPackage.AllNames"))
13575 assert("299: type assertion", strings.Contains(ir, "typeid"))
13576 assert("299: map iteration", strings.Contains(ir, "hashmapNext"))
13577 })
13578
13579 // Test 300: Full 350-line bootstrap simulation - types, builder, emitter pipeline
13580 test(300, `package main
13581
13582 type Type interface {
13583 Underlying() Type
13584 String() string
13585 }
13586 type Basic struct { kind int32; name string }
13587 func (b *Basic) Underlying() Type { return b }
13588 func (b *Basic) String() string { return b.name }
13589 type Pointer struct { base Type }
13590 func (p *Pointer) Underlying() Type { return p }
13591 func (p *Pointer) String() string { return "*" | p.base.String() }
13592 func (p *Pointer) Elem() Type { return p.base }
13593 type Slice struct { elem Type }
13594 func (s *Slice) Underlying() Type { return s }
13595 func (s *Slice) String() string { return "[]" | s.elem.String() }
13596 type Named struct { obj string; underlying Type }
13597 func (n *Named) Underlying() Type {
13598 if n.underlying != nil { return n.underlying }
13599 return n
13600 }
13601 func (n *Named) String() string { return n.obj }
13602 func NewPointer(base Type) *Pointer { return &Pointer{base: base} }
13603 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
13604
13605 type SSAValue interface { SSAName() string; SSAType() Type }
13606 type SSAInstruction interface { InstrString() string; setBlock(*Block) }
13607 type Block struct { index int32; instrs []SSAInstruction }
13608 func (b *Block) emit(i SSAInstruction) {
13609 i.setBlock(b)
13610 b.instrs = append(b.instrs, i)
13611 }
13612 type instrBase struct { block *Block }
13613 func (a *instrBase) setBlock(b *Block) { a.block = b }
13614 type register struct { instrBase; name string; typ Type }
13615 func (r *register) SSAName() string { return r.name }
13616 func (r *register) SSAType() Type { return r.typ }
13617
13618 type SSAConst struct { name string; typ Type; val int32 }
13619 func (c *SSAConst) SSAName() string { return c.name }
13620 func (c *SSAConst) SSAType() Type { return c.typ }
13621
13622 type BinOp struct { register; Op string; X SSAValue; Y SSAValue }
13623 func (b *BinOp) InstrString() string {
13624 return b.name | " = " | b.Op | " " | llvmType300(b.typ) | " " | b.X.SSAName() | ", " | b.Y.SSAName()
13625 }
13626 type Call struct { register; fn SSAValue; args []SSAValue }
13627 func (c *Call) InstrString() string { return c.name | " = call " | c.fn.SSAName() }
13628 type Store struct { instrBase; addr SSAValue; val SSAValue }
13629 func (s *Store) InstrString() string { return "store " | llvmType300(s.val.SSAType()) | " " | s.val.SSAName() | ", ptr " | s.addr.SSAName() }
13630 type Ret struct { instrBase; val SSAValue }
13631 func (r *Ret) InstrString() string {
13632 if r.val == nil { return "ret void" }
13633 return "ret " | llvmType300(r.val.SSAType()) | " " | r.val.SSAName()
13634 }
13635 type Alloc struct { register; heap bool }
13636 func (a *Alloc) InstrString() string {
13637 return a.name | " = alloca " | llvmType300(a.typ)
13638 }
13639 type FieldAddr struct { register; x SSAValue; field int32 }
13640 func (fa *FieldAddr) InstrString() string {
13641 return fa.name | " = getelementptr " | fa.x.SSAName()
13642 }
13643
13644 func llvmType300(t Type) string {
13645 if t == nil { return "void" }
13646 switch u := t.Underlying().(type) {
13647 case *Basic:
13648 switch u.kind {
13649 case 1: return "i8"
13650 case 2: return "i32"
13651 case 3: return "i64"
13652 case 4: return "{ptr, i64, i64}"
13653 }
13654 return "i8"
13655 case *Pointer: return "ptr"
13656 case *Slice: return "{ptr, i64, i64}"
13657 case *Named: return llvmType300(u.Underlying())
13658 }
13659 return "void"
13660 }
13661
13662 type Emitter struct {
13663 buf []byte
13664 nextReg int32
13665 }
13666
13667 func (e *Emitter) w(s string) { e.buf = append(e.buf, s...) }
13668
13669 func (e *Emitter) fresh() string {
13670 e.nextReg = e.nextReg + 1
13671 return "%t" | itoa300(e.nextReg)
13672 }
13673
13674 func (e *Emitter) emitInstr(i SSAInstruction) {
13675 e.w(" ")
13676 e.w(i.InstrString())
13677 e.w("\n")
13678 }
13679
13680 func (e *Emitter) emitBlock(b *Block) {
13681 e.w("b")
13682 e.w(itoa300(int32(b.index)))
13683 e.w(":\n")
13684 for _, instr := range b.instrs {
13685 e.emitInstr(instr)
13686 }
13687 }
13688
13689 func (e *Emitter) emitFunc(name string, blocks []*Block) string {
13690 e.w("define void @")
13691 e.w(name)
13692 e.w("() {\n")
13693 for _, b := range blocks {
13694 e.emitBlock(b)
13695 }
13696 e.w("}\n")
13697 return string(e.buf)
13698 }
13699
13700 func itoa300(n int32) string {
13701 if n == 0 { return "0" }
13702 if n < 0 { return "-" | itoa300(-n) }
13703 var buf [10]byte
13704 i := int32(9)
13705 for n > 0 {
13706 buf[i] = byte(n%10) + '0'
13707 n = n / 10
13708 i = i - 1
13709 }
13710 return string(buf[i+1:])
13711 }
13712
13713 type Scope struct {
13714 parent *Scope
13715 names map[string]SSAValue
13716 }
13717
13718 func (s *Scope) Lookup(name string) SSAValue {
13719 if s.names != nil {
13720 v, ok := s.names[name]
13721 if ok { return v }
13722 }
13723 if s.parent != nil { return s.parent.Lookup(name) }
13724 return nil
13725 }
13726
13727 func main() {
13728 i32 := &Basic{kind: 2, name: "int32"}
13729 i64 := &Basic{kind: 3, name: "int64"}
13730 strType := &Basic{kind: 4, name: "string"}
13731 ptrI32 := NewPointer(i32)
13732 sliceStr := NewSlice(strType)
13733 myInt := &Named{obj: "MyInt", underlying: i32}
13734
13735 _ = llvmType300(i32)
13736 _ = llvmType300(i64)
13737 _ = llvmType300(ptrI32)
13738 _ = llvmType300(sliceStr)
13739 _ = llvmType300(myInt)
13740 _ = llvmType300(nil)
13741
13742 entry := &Block{index: 0}
13743 retBlock := &Block{index: 1}
13744
13745 c1 := &SSAConst{name: "1", typ: i32, val: 1}
13746 c2 := &SSAConst{name: "2", typ: i32, val: 2}
13747
13748 alloc := &Alloc{}
13749 alloc.name = "%t1"
13750 alloc.typ = i32
13751 entry.emit(alloc)
13752
13753 add := &BinOp{Op: "add", X: c1, Y: c2}
13754 add.name = "%t2"
13755 add.typ = i32
13756 entry.emit(add)
13757
13758 store := &Store{addr: alloc, val: add}
13759 entry.emit(store)
13760
13761 fa := &FieldAddr{x: alloc, field: 0}
13762 fa.name = "%t3"
13763 fa.typ = ptrI32
13764 entry.emit(fa)
13765
13766 ret := &Ret{val: add}
13767 retBlock.emit(ret)
13768
13769 retVoid := &Ret{}
13770 retBlock.emit(retVoid)
13771
13772 e := &Emitter{}
13773 ir := e.emitFunc("test", []*Block{entry, retBlock})
13774 _ = ir
13775
13776 scope := &Scope{
13777 names: map[string]SSAValue{},
13778 }
13779 scope.names["x"] = alloc
13780 scope.names["y"] = add
13781
13782 child := &Scope{parent: scope, names: map[string]SSAValue{}}
13783 child.names["z"] = c1
13784
13785 v1 := child.Lookup("z")
13786 v2 := child.Lookup("x")
13787 v3 := child.Lookup("missing")
13788 _ = v1
13789 _ = v2
13790 _ = v3
13791 }
13792 `, func(ir string) {
13793 assert("300: has Emitter.emitFunc", strings.Contains(ir, "@main.Emitter.emitFunc"))
13794 assert("300: has Emitter.emitBlock", strings.Contains(ir, "@main.Emitter.emitBlock"))
13795 assert("300: has Emitter.emitInstr", strings.Contains(ir, "@main.Emitter.emitInstr"))
13796 assert("300: has llvmType300", strings.Contains(ir, "@main.llvmType300"))
13797 assert("300: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
13798 assert("300: 2-level embed setBlock", strings.Contains(ir, "@main.instrBase.setBlock"))
13799 assert("300: type switch dispatch", strings.Contains(ir, "typeid"))
13800 assert("300: nested switch", strings.Contains(ir, "icmp eq i32"))
13801 assert("300: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13802 assert("300: recursive call", strings.Count(ir, "@main.Scope.Lookup") >= 2)
13803 assert("300: map operations", strings.Contains(ir, "hashmapContent"))
13804 assert("300: array subslice", strings.Contains(ir, "alloca [10 x i8]"))
13805 assert("300: nil ret check", strings.Contains(ir, "ret void") || strings.Contains(ir, "zeroinitializer"))
13806 })
13807
13808 // Test 301: import registered package and call function
13809 clearImports()
13810 regPkg("fmt", "fmt")
13811 regFn("fmt", "Sprintf", "string->string")
13812 test(301, `package main
13813
13814 import "fmt"
13815
13816 func main() {
13817 s := fmt.Sprintf("hello")
13818 _ = s
13819 }
13820 `, func(ir string) {
13821 assert("301: has declare for fmt.Sprintf", strings.Contains(ir, "declare") && strings.Contains(ir, "@fmt.Sprintf"))
13822 assert("301: has call to fmt.Sprintf", strings.Contains(ir, "call") && strings.Contains(ir, "@fmt.Sprintf"))
13823 assert("301: result is string type", strings.Contains(ir, "{ptr, i") || strings.Contains(ir, "ptr"))
13824 })
13825
13826 // Test 302: import with multiple functions
13827 clearImports()
13828 regPkg("strconv", "strconv")
13829 regFn("strconv", "Itoa", "int->string")
13830 regFn("strconv", "Atoi", "string->int,error")
13831 test(302, `package main
13832
13833 import "strconv"
13834
13835 func main() {
13836 s := strconv.Itoa(42)
13837 _ = s
13838 }
13839 `, func(ir string) {
13840 assert("302: has declare for strconv.Itoa", strings.Contains(ir, "declare") && strings.Contains(ir, "@strconv.Itoa"))
13841 assert("302: has call to strconv.Itoa", strings.Contains(ir, "call") && strings.Contains(ir, "@strconv.Itoa"))
13842 })
13843
13844 // Test 303: import with global var
13845 clearImports()
13846 regPkg("os", "os")
13847 regVar("os", "Stdout", "ptr")
13848 regFn("os", "Exit", "int")
13849 test(303, `package main
13850
13851 import "os"
13852
13853 func main() {
13854 os.Exit(1)
13855 }
13856 `, func(ir string) {
13857 assert("303: has declare for os.Exit", strings.Contains(ir, "declare") && strings.Contains(ir, "@os.Exit"))
13858 assert("303: has call to os.Exit", strings.Contains(ir, "call") && strings.Contains(ir, "@os.Exit"))
13859 })
13860
13861 // Test 304: import with aliased package name
13862 clearImports()
13863 regPkg("fmt", "fmt")
13864 regFn("fmt", "Sprintf", "string->string")
13865 test(304, `package main
13866
13867 import f "fmt"
13868
13869 func main() {
13870 s := f.Sprintf("hello")
13871 _ = s
13872 }
13873 `, func(ir string) {
13874 assert("304: aliased import calls fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
13875 })
13876
13877 // Test 305: multiple imports in same compilation
13878 clearImports()
13879 regPkg("fmt", "fmt")
13880 regFn("fmt", "Sprintf", "string->string")
13881 regPkg("strconv", "strconv")
13882 regFn("strconv", "Itoa", "int->string")
13883 test(305, `package main
13884
13885 import (
13886 "fmt"
13887 "strconv"
13888 )
13889
13890 func main() {
13891 n := strconv.Itoa(42)
13892 s := fmt.Sprintf(n)
13893 _ = s
13894 }
13895 `, func(ir string) {
13896 assert("305: has fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
13897 assert("305: has strconv.Itoa", strings.Contains(ir, "@strconv.Itoa"))
13898 assert("305: both declared", strings.Count(ir, "declare") >= 2)
13899 })
13900
13901 // Test 306: import function with slice param
13902 clearImports()
13903 regPkg("bytes", "bytes")
13904 regFn("bytes", "Join", "[]string,string->string")
13905 test(306, `package main
13906
13907 import "bytes"
13908
13909 func join(parts []string, sep string) string {
13910 return bytes.Join(parts, sep)
13911 }
13912 `, func(ir string) {
13913 assert("306: has bytes.Join declare", strings.Contains(ir, "@bytes.Join"))
13914 assert("306: passes slice arg", strings.Contains(ir, "call") && strings.Contains(ir, "@bytes.Join"))
13915 })
13916
13917 // Test 307: use imported var (global read)
13918 clearImports()
13919 regPkg("os", "os")
13920 regVar("os", "Args", "[]string")
13921 test(307, `package main
13922
13923 import "os"
13924
13925 func getFirst() string {
13926 return os.Args[0]
13927 }
13928 `, func(ir string) {
13929 assert("307: has external global for os.Args", strings.Contains(ir, "@os.Args") && strings.Contains(ir, "external global"))
13930 assert("307: loads from os.Args", strings.Contains(ir, "load") && strings.Contains(ir, "@os.Args"))
13931 })
13932
13933 // Test 308: import function returning void (no return value)
13934 clearImports()
13935 regPkg("runtime", "runtime")
13936 regFn("runtime", "GC", "")
13937 test(308, `package main
13938
13939 import "runtime"
13940
13941 func main() {
13942 runtime.GC()
13943 }
13944 `, func(ir string) {
13945 assert("308: has runtime.GC declare", strings.Contains(ir, "@runtime.GC"))
13946 assert("308: void call", strings.Contains(ir, "call void"))
13947 })
13948
13949 clearImports()
13950
13951 // Test 309: function returning error interface
13952 clearImports()
13953 regPkg("strconv", "strconv")
13954 regFn("strconv", "Atoi", "string->int,error")
13955 test(309, `package main
13956
13957 import "strconv"
13958
13959 func tryParse(s string) int32 {
13960 n, err := strconv.Atoi(s)
13961 if err != nil {
13962 return -1
13963 }
13964 return n
13965 }
13966 `, func(ir string) {
13967 assert("309: has strconv.Atoi declare", strings.Contains(ir, "@strconv.Atoi"))
13968 assert("309: multi-return extraction", strings.Contains(ir, "extractvalue"))
13969 assert("309: nil check on error", strings.Contains(ir, "icmp"))
13970 })
13971
13972 // Test 310: function taking interface{} parameter
13973 clearImports()
13974 regPkg("fmt", "fmt")
13975 regFn("fmt", "Println", "interface{}->int,error")
13976 test(310, `package main
13977
13978 import "fmt"
13979
13980 func main() {
13981 fmt.Println(42)
13982 }
13983 `, func(ir string) {
13984 assert("310: has fmt.Println declare", strings.Contains(ir, "@fmt.Println"))
13985 assert("310: call with boxing", strings.Contains(ir, "call") && strings.Contains(ir, "@fmt.Println"))
13986 })
13987
13988 // Test 311: imported function used in expression
13989 clearImports()
13990 regPkg("strconv", "strconv")
13991 regFn("strconv", "Itoa", "int->string")
13992 test(311, `package main
13993
13994 import "strconv"
13995
13996 func describe(n int32) string {
13997 return "val:" | strconv.Itoa(n)
13998 }
13999 `, func(ir string) {
14000 assert("311: has strconv.Itoa", strings.Contains(ir, "@strconv.Itoa"))
14001 assert("311: string concat after call", strings.Contains(ir, "sliceAppend") || strings.Contains(ir, "runtime.stringConcat"))
14002 })
14003
14004 clearImports()
14005
14006 // Test 312: pos.mx pattern - value receiver structs, self-referential types, struct compare
14007 clearImports()
14008 regPkg("fmt", "fmt")
14009 regFn("fmt", "Sprintf", "string,interface{},interface{}->string")
14010 test(312, `package main
14011
14012 import "fmt"
14013
14014 const PosMax = 1 << 30
14015
14016 type Pos struct {
14017 base *PosBase
14018 line, col uint32
14019 }
14020
14021 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, sat32(line), sat32(col)} }
14022
14023 func (pos Pos) IsKnown() bool { return pos.line > 0 }
14024 func (pos Pos) Base() *PosBase { return pos.base }
14025 func (pos Pos) Line() uint32 { return pos.line }
14026 func (pos Pos) Col() uint32 { return pos.col }
14027
14028 func (pos Pos) FileBase() *PosBase {
14029 b := pos.base
14030 for b != nil && b != b.pos.base {
14031 b = b.pos.base
14032 }
14033 return b
14034 }
14035
14036 func (pos Pos) RelFilename() string { return pos.base.Filename() }
14037
14038 type position_ struct {
14039 filename string
14040 line, col uint32
14041 }
14042
14043 func (p position_) String() string {
14044 if p.line == 0 {
14045 if p.filename == "" {
14046 return "<unknown position>"
14047 }
14048 return p.filename
14049 }
14050 if p.col == 0 {
14051 return fmt.Sprintf("%s:%d", p.filename, p.line)
14052 }
14053 return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
14054 }
14055
14056 type PosBase struct {
14057 pos Pos
14058 filename string
14059 line, col uint32
14060 trimmed bool
14061 }
14062
14063 func NewFileBase(filename string) *PosBase {
14064 return NewTrimmedFileBase(filename, false)
14065 }
14066
14067 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14068 base := &PosBase{MakePos(nil, 1, 1), filename, 1, 1, trimmed}
14069 base.pos.base = base
14070 return base
14071 }
14072
14073 func (base *PosBase) IsFileBase() bool {
14074 if base == nil {
14075 return false
14076 }
14077 return base.pos.base == base
14078 }
14079
14080 func (base *PosBase) Filename() string {
14081 if base == nil {
14082 return ""
14083 }
14084 return base.filename
14085 }
14086
14087 func (base *PosBase) Line() uint32 {
14088 if base == nil {
14089 return 0
14090 }
14091 return base.line
14092 }
14093
14094 func (base *PosBase) Col() uint32 {
14095 if base == nil {
14096 return 0
14097 }
14098 return base.col
14099 }
14100
14101 func sat32(x uint32) uint32 {
14102 if x > PosMax {
14103 return PosMax
14104 }
14105 return uint32(x)
14106 }
14107
14108 func main() {
14109 base := NewFileBase("test.mx")
14110 pos := MakePos(base, 10, 5)
14111 _ = pos.IsKnown()
14112 _ = pos.Line()
14113 _ = pos.Col()
14114 _ = pos.FileBase()
14115 _ = pos.RelFilename()
14116 _ = base.IsFileBase()
14117 _ = base.Filename()
14118 }
14119 `, func(ir string) {
14120 assert("312: has MakePos", strings.Contains(ir, "@main.MakePos"))
14121 assert("312: has PosBase methods", strings.Contains(ir, "@main.PosBase.Filename"))
14122 assert("312: has value receiver Pos.Line", strings.Contains(ir, "@main.Pos.Line"))
14123 assert("312: has self-ref assignment", strings.Contains(ir, "store"))
14124 assert("312: has nil check", strings.Contains(ir, "icmp"))
14125 assert("312: has fmt.Sprintf declare", strings.Contains(ir, "@fmt.Sprintf"))
14126 assert("312: produces many functions", strings.Count(ir, "\ndefine ") >= 10)
14127 llvmVerify("312: pos.mx pattern", ir)
14128 })
14129
14130 // Test 313: multi-file concat simulation - source.mx + pos.mx constants
14131 test(313, `package main
14132
14133 const Linebase = 1
14134 const Colbase = 1
14135
14136 type Pos struct {
14137 base *PosBase
14138 line, col uint32
14139 }
14140
14141 type PosBase struct {
14142 pos Pos
14143 filename string
14144 line, col uint32
14145 trimmed bool
14146 }
14147
14148 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, line, col} }
14149
14150 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14151 base := &PosBase{MakePos(nil, Linebase, Colbase), filename, Linebase, Colbase, trimmed}
14152 base.pos.base = base
14153 return base
14154 }
14155
14156 func main() {
14157 b := NewTrimmedFileBase("hello.mx", false)
14158 p := MakePos(b, 42, 7)
14159 _ = p.line
14160 _ = p.col
14161 _ = b.pos.line
14162 }
14163 `, func(ir string) {
14164 assert("313: has NewTrimmedFileBase", strings.Contains(ir, "@main.NewTrimmedFileBase"))
14165 assert("313: has MakePos", strings.Contains(ir, "@main.MakePos"))
14166 assert("313: self-referential store", strings.Contains(ir, "store"))
14167 llvmVerify("313: multi-file concat", ir)
14168 })
14169
14170 clearImports()
14171
14172 // Test 315: && with nested struct field access (b.pos.base pattern)
14173 test(315, `package main
14174
14175 type Inner struct {
14176 ref *Outer
14177 val int32
14178 }
14179
14180 type Outer struct {
14181 inner Inner
14182 name string
14183 }
14184
14185 func findRoot(b *Outer) *Outer {
14186 for b != nil && b != b.inner.ref {
14187 b = b.inner.ref
14188 }
14189 return b
14190 }
14191
14192 func main() {
14193 o := &Outer{Inner{nil, 1}, "test"}
14194 o.inner.ref = o
14195 r := findRoot(o)
14196 _ = r
14197 }
14198 `, func(ir string) {
14199 assert("315: has findRoot", strings.Contains(ir, "@main.findRoot"))
14200 assert("315: has loop", strings.Contains(ir, "br i1") || strings.Contains(ir, "br label"))
14201 llvmVerify("315: nested field && pattern", ir)
14202 })
14203
14204 // Test 316: positional struct literal stores values
14205 test(316, `package main
14206
14207 type Vec3 struct {
14208 x, y, z int32
14209 }
14210
14211 func make3(a, b, c int32) Vec3 {
14212 return Vec3{a, b, c}
14213 }
14214
14215 func main() {
14216 v := make3(10, 20, 30)
14217 _ = v.x
14218 _ = v.y
14219 _ = v.z
14220 }
14221 `, func(ir string) {
14222 geps := strings.Count(ir, "getelementptr")
14223 stores := strings.Count(ir, "store")
14224 assert("316: has field stores in make3", geps >= 3 && stores >= 3)
14225 assert("316: stores i32 values", strings.Contains(ir, "store i32"))
14226 llvmVerify("316: positional struct literal", ir)
14227 })
14228
14229 // Test 317: positional struct literal with mixed types
14230 test(317, `package main
14231
14232 type Pair struct {
14233 name string
14234 val int32
14235 }
14236
14237 func makePair(n string, v int32) Pair {
14238 return Pair{n, v}
14239 }
14240
14241 func main() {
14242 p := makePair("hello", 42)
14243 _ = p.name
14244 _ = p.val
14245 }
14246 `, func(ir string) {
14247 assert("317: stores string field", strings.Contains(ir, "store {ptr, i64, i64}"))
14248 assert("317: stores int field", strings.Contains(ir, "store i32"))
14249 llvmVerify("317: mixed positional struct literal", ir)
14250 })
14251
14252 // Test 318: struct comparison with == and !=
14253 test(318, `package main
14254
14255 type Point struct {
14256 x, y int32
14257 }
14258
14259 func equal(a, b Point) bool {
14260 return a == b
14261 }
14262
14263 func notEqual(a, b Point) bool {
14264 return a != b
14265 }
14266
14267 func main() {
14268 p1 := Point{1, 2}
14269 p2 := Point{1, 2}
14270 _ = equal(p1, p2)
14271 _ = notEqual(p1, p2)
14272 }
14273 `, func(ir string) {
14274 assert("318: has comparison", strings.Contains(ir, "icmp"))
14275 llvmVerify("318: struct comparison", ir)
14276 })
14277
14278 // Test 319: struct comparison with string fields
14279 test(319, `package main
14280
14281 type Position struct {
14282 filename string
14283 line, col int32
14284 }
14285
14286 func same(a, b Position) bool {
14287 return a == b
14288 }
14289
14290 func main() {
14291 p1 := Position{"test.go", 10, 5}
14292 p2 := Position{"test.go", 10, 5}
14293 _ = same(p1, p2)
14294 }
14295 `, func(ir string) {
14296 assert("319: has stringEqual call", strings.Contains(ir, "runtime.stringEqual"))
14297 assert("319: has field extracts", strings.Contains(ir, "extractvalue"))
14298 assert("319: has and accumulation", strings.Contains(ir, "and i1"))
14299 llvmVerify("319: struct compare with string", ir)
14300 })
14301
14302 // Test 320: actual pos.mx from bootstrap (with Linebase/Colbase inlined)
14303 clearImports()
14304 regPkg("fmt", "fmt")
14305 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
14306 test(320, `package main
14307
14308 import "fmt"
14309
14310 const PosMax = 1 << 30
14311 const Linebase = 1
14312 const Colbase = 1
14313
14314 type Pos struct {
14315 base *PosBase
14316 line, col uint32
14317 }
14318
14319 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, sat32(line), sat32(col)} }
14320
14321 func (pos Pos) IsKnown() bool { return pos.line > 0 }
14322 func (pos Pos) Base() *PosBase { return pos.base }
14323 func (pos Pos) Line() uint32 { return pos.line }
14324 func (pos Pos) Col() uint32 { return pos.col }
14325
14326 func (pos Pos) FileBase() *PosBase {
14327 b := pos.base
14328 for b != nil && b != b.pos.base {
14329 b = b.pos.base
14330 }
14331 return b
14332 }
14333
14334 func (pos Pos) RelFilename() string { return pos.base.Filename() }
14335
14336 func (pos Pos) RelLine() uint32 {
14337 b := pos.base
14338 if b.Line() == 0 {
14339 return 0
14340 }
14341 return b.Line() + (pos.Line() - b.Pos().Line())
14342 }
14343
14344 func (pos Pos) RelCol() uint32 {
14345 b := pos.base
14346 if b.Col() == 0 {
14347 return 0
14348 }
14349 if pos.Line() == b.Pos().Line() {
14350 return b.Col() + (pos.Col() - b.Pos().Col())
14351 }
14352 return pos.Col()
14353 }
14354
14355 func (p Pos) Cmp(q Pos) int {
14356 pname := p.RelFilename()
14357 qname := q.RelFilename()
14358 switch {
14359 case pname < qname:
14360 return -1
14361 case pname > qname:
14362 return +1
14363 }
14364
14365 pline := p.Line()
14366 qline := q.Line()
14367 switch {
14368 case pline < qline:
14369 return -1
14370 case pline > qline:
14371 return +1
14372 }
14373
14374 pcol := p.Col()
14375 qcol := q.Col()
14376 switch {
14377 case pcol < qcol:
14378 return -1
14379 case pcol > qcol:
14380 return +1
14381 }
14382
14383 return 0
14384 }
14385
14386 func (pos Pos) String() string {
14387 rel := position_{pos.RelFilename(), pos.RelLine(), pos.RelCol()}
14388 abs := position_{pos.Base().Pos().RelFilename(), pos.Line(), pos.Col()}
14389 s := rel.String()
14390 if rel != abs {
14391 s = s | "[" | abs.String() | "]"
14392 }
14393 return s
14394 }
14395
14396 type position_ struct {
14397 filename string
14398 line, col uint32
14399 }
14400
14401 func (p position_) String() string {
14402 if p.line == 0 {
14403 if p.filename == "" {
14404 return "<unknown position>"
14405 }
14406 return p.filename
14407 }
14408 if p.col == 0 {
14409 return fmt.Sprintf("%s:%d", p.filename, p.line)
14410 }
14411 return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
14412 }
14413
14414 type PosBase struct {
14415 pos Pos
14416 filename string
14417 line, col uint32
14418 trimmed bool
14419 }
14420
14421 func NewFileBase(filename string) *PosBase {
14422 return NewTrimmedFileBase(filename, false)
14423 }
14424
14425 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14426 base := &PosBase{MakePos(nil, Linebase, Colbase), filename, Linebase, Colbase, trimmed}
14427 base.pos.base = base
14428 return base
14429 }
14430
14431 func NewLineBase(pos Pos, filename string, trimmed bool, line, col uint32) *PosBase {
14432 return &PosBase{pos, filename, sat32(line), sat32(col), trimmed}
14433 }
14434
14435 func (base *PosBase) IsFileBase() bool {
14436 if base == nil {
14437 return false
14438 }
14439 return base.pos.base == base
14440 }
14441
14442 func (base *PosBase) Pos() (_ Pos) {
14443 if base == nil {
14444 return
14445 }
14446 return base.pos
14447 }
14448
14449 func (base *PosBase) Filename() string {
14450 if base == nil {
14451 return ""
14452 }
14453 return base.filename
14454 }
14455
14456 func (base *PosBase) Line() uint32 {
14457 if base == nil {
14458 return 0
14459 }
14460 return base.line
14461 }
14462
14463 func (base *PosBase) Col() uint32 {
14464 if base == nil {
14465 return 0
14466 }
14467 return base.col
14468 }
14469
14470 func (base *PosBase) Trimmed() bool {
14471 if base == nil {
14472 return false
14473 }
14474 return base.trimmed
14475 }
14476
14477 func sat32(x uint32) uint32 {
14478 if x > PosMax {
14479 return PosMax
14480 }
14481 return uint32(x)
14482 }
14483
14484 func main() {
14485 base := NewFileBase("test.mx")
14486 pos := MakePos(base, 10, 5)
14487 _ = pos.IsKnown()
14488 _ = pos.Line()
14489 _ = pos.Col()
14490 fb := pos.FileBase()
14491 _ = fb
14492 _ = pos.RelFilename()
14493 _ = pos.String()
14494 _ = pos.Cmp(MakePos(base, 20, 1))
14495 _ = base.IsFileBase()
14496 }
14497 `, func(ir string) {
14498 funcCount := strings.Count(ir, "\ndefine ")
14499 assert("320: compiles all pos.mx functions", funcCount >= 20)
14500 assert("320: has MakePos", strings.Contains(ir, "@main.MakePos"))
14501 assert("320: has Pos.String", strings.Contains(ir, "@main.Pos.String"))
14502 assert("320: has Pos.Cmp", strings.Contains(ir, "@main.Pos.Cmp"))
14503 assert("320: has position_.String", strings.Contains(ir, "@main.position_.String"))
14504 assert("320: has NewTrimmedFileBase", strings.Contains(ir, "@main.NewTrimmedFileBase"))
14505 assert("320: has PosBase.Pos", strings.Contains(ir, "@main.PosBase.Pos"))
14506 assert("320: has struct compare", strings.Contains(ir, "extractvalue") && strings.Contains(ir, "and i1"))
14507 assert("320: has fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
14508 llvmVerify("320: real pos.mx", ir)
14509 })
14510
14511 clearImports()
14512
14513 // Test 314: && with field access (isolated from pos.mx FileBase pattern)
14514 test(314, `package main
14515
14516 type Node struct {
14517 parent *Node
14518 val int32
14519 }
14520
14521 func findRoot(n *Node) *Node {
14522 for n != nil && n != n.parent {
14523 n = n.parent
14524 }
14525 return n
14526 }
14527
14528 func main() {
14529 a := &Node{nil, 1}
14530 a.parent = a
14531 r := findRoot(a)
14532 _ = r
14533 }
14534 `, func(ir string) {
14535 assert("314: has findRoot", strings.Contains(ir, "@main.findRoot"))
14536 assert("314: has loop branch", strings.Contains(ir, "br i1") || strings.Contains(ir, "br label"))
14537 })
14538
14539 clearImports()
14540
14541 // Test 321: ssa_types.mx first 100 lines (op codes, switch on named int)
14542 test(321, `package main
14543
14544 type SSAOp int32
14545
14546 const (
14547 OpIllegal SSAOp = iota
14548 OpAdd
14549 OpSub
14550 OpMul
14551 OpQuo
14552 OpRem
14553 OpEql
14554 OpNeq
14555 )
14556
14557 func (op SSAOp) String() string {
14558 switch op {
14559 case OpAdd:
14560 return "+"
14561 case OpSub:
14562 return "-"
14563 case OpMul:
14564 return "*"
14565 case OpQuo:
14566 return "/"
14567 case OpRem:
14568 return "percent"
14569 case OpEql:
14570 return "=="
14571 case OpNeq:
14572 return "!="
14573 }
14574 return "?"
14575 }
14576
14577 type ConstVal interface {
14578 String() string
14579 }
14580
14581 func ssaConstString(val ConstVal) string {
14582 if val == nil {
14583 return "nil"
14584 }
14585 return val.String()
14586 }
14587
14588 type SSAValue interface {
14589 SSAName() string
14590 SSAType() Type
14591 }
14592
14593 type SSAInstruction interface {
14594 setBlock(b *SSABasicBlock)
14595 }
14596
14597 type Type interface {
14598 Underlying() Type
14599 String() string
14600 }
14601
14602 type SSABasicBlock struct {
14603 Index int32
14604 Instrs []SSAInstruction
14605 Succs []*SSABasicBlock
14606 Preds []*SSABasicBlock
14607 }
14608
14609 type SSAFunction struct {
14610 name string
14611 Blocks []*SSABasicBlock
14612 Params []*SSAParameter
14613 FreeVars []*SSAFreeVar
14614 Signature *Signature
14615 Pkg *SSAPackage
14616 Prog *SSAProgram
14617 AnonFuncs []*SSAFunction
14618 }
14619
14620 type SSAParameter struct {
14621 name string
14622 typ Type
14623 parent *SSAFunction
14624 }
14625 func (p *SSAParameter) SSAName() string { return p.name }
14626 func (p *SSAParameter) SSAType() Type { return p.typ }
14627 func (p *SSAParameter) SSAParent() *SSAFunction { return p.parent }
14628
14629 type SSAFreeVar struct {
14630 name string
14631 typ Type
14632 parent *SSAFunction
14633 }
14634 func (f *SSAFreeVar) SSAName() string { return f.name }
14635 func (f *SSAFreeVar) SSAType() Type { return f.typ }
14636
14637 type SSAPackage struct {
14638 Prog *SSAProgram
14639 Members map[string]SSAMember
14640 }
14641
14642 type SSAMember interface {
14643 SSAName() string
14644 }
14645
14646 type SSAProgram struct {
14647 packages map[*TCPackage]*SSAPackage
14648 imported map[string]*SSAPackage
14649 }
14650
14651 type TCPackage struct {
14652 path string
14653 name string
14654 scope *Scope
14655 }
14656 func (p *TCPackage) Path() string { return p.path }
14657 func (p *TCPackage) Name() string { return p.name }
14658 func (p *TCPackage) Scope() *Scope { return p.scope }
14659
14660 type Scope struct {
14661 parent *Scope
14662 objects map[string]Object
14663 }
14664 func NewScope(parent *Scope) *Scope { return &Scope{parent, map[string]Object{}} }
14665 func (s *Scope) Lookup(name string) Object {
14666 if s.objects != nil {
14667 if obj, ok := s.objects[name]; ok {
14668 return obj
14669 }
14670 }
14671 return nil
14672 }
14673
14674 type Object interface {
14675 Name() string
14676 }
14677
14678 type Signature struct {
14679 recv *TCVar
14680 params *Tuple
14681 results *Tuple
14682 }
14683 func NewSignature(recv *TCVar, params *Tuple, results *Tuple) *Signature {
14684 return &Signature{recv, params, results}
14685 }
14686 func (s *Signature) Params() *Tuple { return s.params }
14687 func (s *Signature) Results() *Tuple { return s.results }
14688 func (s *Signature) Underlying() Type { return s }
14689 func (s *Signature) String() string { return "func" }
14690
14691 type TCVar struct {
14692 name string
14693 typ Type
14694 }
14695 func (v *TCVar) Name() string { return v.name }
14696 func (v *TCVar) Type() Type { return v.typ }
14697
14698 type Tuple struct {
14699 vars []*TCVar
14700 }
14701 func NewTuple(vars ...*TCVar) *Tuple {
14702 if len(vars) == 0 { return nil }
14703 return &Tuple{vars}
14704 }
14705 func (t *Tuple) Len() int { return len(t.vars) }
14706 func (t *Tuple) At(i int) *TCVar { return t.vars[i] }
14707
14708 func (prog *SSAProgram) ImportedPackage(path string) *SSAPackage {
14709 return prog.imported[path]
14710 }
14711
14712 func main() {
14713 op := OpAdd
14714 _ = op.String()
14715 _ = ssaConstString(nil)
14716 }
14717 `, func(ir string) {
14718 funcCount := strings.Count(ir, "\ndefine ")
14719 assert("321: many functions from ssa_types", funcCount >= 15)
14720 assert("321: has SSAOp.String", strings.Contains(ir, "@main.SSAOp.String"))
14721 assert("321: has ssaConstString", strings.Contains(ir, "@main.ssaConstString"))
14722 assert("321: has NewScope", strings.Contains(ir, "@main.NewScope"))
14723 llvmVerify("321: ssa_types subset", ir)
14724 })
14725
14726 // Test 322: concat all compile/ .mx files and compile
14727 fmt.Fprintf(os.Stderr, ">>> Starting test 322 (full concat)\n")
14728 clearImports()
14729 regPkg("go/token", "token")
14730 regVar("go/token", "ARROW", "int")
14731 regVar("go/token", "DEFAULT", "int")
14732 regPkg("go/constant", "constant")
14733 regIface("go/constant", "Value", "Kind=->int;String=->string;ExactString=->string")
14734 regFn("go/constant", "MakeInt64", "int64->interface{}")
14735 regFn("go/constant", "MakeFloat64", "float64->interface{}")
14736 regFn("go/constant", "MakeString", "string->interface{}")
14737 regFn("go/constant", "MakeFromLiteral", "string,int,int->interface{}")
14738 regFn("go/constant", "BinaryOp", "interface{},int,interface{}->interface{}")
14739 regFn("go/constant", "UnaryOp", "int,interface{},int->interface{}")
14740 regFn("go/constant", "Compare", "interface{},int,interface{}->bool")
14741 regFn("go/constant", "StringVal", "interface{}->string")
14742 regFn("go/constant", "Int64Val", "interface{}->int64,bool")
14743 regFn("go/constant", "Uint64Val", "interface{}->uint64,bool")
14744 regFn("go/constant", "Float64Val", "interface{}->float64,bool")
14745 regFn("go/constant", "BitLen", "interface{}->int")
14746 regFn("go/constant", "Sign", "interface{}->int")
14747 regFn("go/constant", "Shift", "interface{},int,uint->interface{}")
14748 regFn("go/constant", "MakeBool", "bool->interface{}")
14749 regFn("go/constant", "ToInt", "interface{}->interface{}")
14750 regFn("go/constant", "ToFloat", "interface{}->interface{}")
14751 regFn("go/constant", "Num", "interface{}->interface{}")
14752 regFn("go/constant", "Denom", "interface{}->interface{}")
14753 regFn("go/constant", "Real", "interface{}->interface{}")
14754 regFn("go/constant", "Imag", "interface{}->interface{}")
14755 regPkg("fmt", "fmt")
14756 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
14757 regFn("fmt", "Fprintf", "interface{},string,interface{},interface{}->int,error")
14758 regPkg("os", "os")
14759 regVar("os", "Stderr", "interface{}")
14760 regPkg("strconv", "strconv")
14761 regFn("strconv", "Itoa", "int->string")
14762 regFn("strconv", "FormatInt", "int64,int->string")
14763 regFn("strconv", "FormatFloat", "float64,byte,int,int->string")
14764 regPkg("bytes", "bytes")
14765 regFn("bytes", "NewReader", "*byte->interface{}")
14766 regFn("bytes", "IndexByte", "[]byte,byte->int")
14767 regFn("bytes", "HasPrefix", "[]byte,[]byte->bool")
14768 regFn("bytes", "TrimSpace", "[]byte->[]byte")
14769 regPkg("io", "io")
14770 regIface("io", "Reader", "Read=[]byte->int,error")
14771 regVar("io", "EOF", "error")
14772 regVar("io", "ErrNoProgress", "error")
14773 regPkg("runtime", "runtime")
14774 regFn("runtime", "InitCShared", "")
14775 regPkg("unsafe", "unsafe")
14776 regPkg("unicode", "unicode")
14777 regFn("unicode", "IsLetter", "int32->bool")
14778 regFn("unicode", "IsDigit", "int32->bool")
14779 regFn("unicode", "IsSpace", "int32->bool")
14780 regPkg("unicode/utf8", "utf8")
14781 regFn("unicode/utf8", "DecodeRune", "[]byte->int32,int")
14782 regFn("unicode/utf8", "RuneLen", "int32->int")
14783 {
14784 compileDir := filepath.Join(filepath.Dir(soPath), "compile")
14785 mxFiles := []string{
14786 "pos.mx", "source.mx", "tokens.mx", "nodes.mx", "syntax.mx",
14787 "scanner.mx", "parser.mx",
14788 "tc_scope.mx", "tc_package.mx", "tc_info.mx", "tc_object.mx",
14789 "tc_types.mx", "tc_universe.mx", "tc_const.mx", "tc_resolve.mx",
14790 "tc_checker.mx", "tc_decl.mx", "tc_expr.mx", "tc_stmt.mx", "tc_assign.mx",
14791 "ssa_types.mx", "ssa_builder.mx", "ir_emit.mx",
14792 }
14793 // Incremental concat test - add one file at a time via subprocess
14794 for i := 1; i <= len(mxFiles); i++ {
14795 subset := mxFiles[:i]
14796 combined, fc, tl := concatMxSources(compileDir, subset)
14797 combined = append(combined, []byte("\nfunc main() {}\n")...)
14798 tmpFile := filepath.Join(os.TempDir(), "mxconcat_incr.mx")
14799 os.WriteFile(tmpFile, combined, 0644)
14800 cmd := exec.Command(os.Args[0], soPath, "--compile-file", tmpFile)
14801 cmd.Env = os.Environ()
14802 out, err := cmd.CombinedOutput()
14803 os.Remove(tmpFile)
14804 outStr := strings.TrimSpace(string(out))
14805 if err != nil {
14806 short := outStr
14807 if len(short) > 100 { short = short[:100] }
14808 fmt.Fprintf(os.Stderr, ">>> FAIL +%s: %d files, %d lines: %s\n", mxFiles[i-1], fc, tl, short)
14809 } else {
14810 fmt.Fprintf(os.Stderr, ">>> OK +%s: %d files, %d lines -> %s\n", mxFiles[i-1], fc, tl, outStr)
14811 }
14812 }
14813 assert("322: incremental concat tested", true)
14814 }
14815 clearImports()
14816
14817 // Test 323: compile real pos.mx from disk
14818 fmt.Fprintf(os.Stderr, ">>> Starting test 323\n")
14819 clearImports()
14820 regPkg("fmt", "fmt")
14821 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
14822 {
14823 posPath := filepath.Join(filepath.Dir(soPath), "syntax", "pos.mx")
14824 posSrc, err := os.ReadFile(posPath)
14825 if err != nil {
14826 fmt.Fprintf(os.Stderr, "SKIP test 323: %v\n", err)
14827 } else {
14828 // pos.mx needs Linebase/Colbase from source.mx
14829 extra := []byte("const Linebase = 1\nconst Colbase = 1\n")
14830 src := append(posSrc, extra...)
14831 pkg := []byte("main")
14832 h := compileToIR(
14833 uintptr(unsafe.Pointer(&src[0])), int32(len(src)),
14834 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
14835 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
14836 )
14837 ir := getIR(h)
14838 if ir == "" {
14839 assert("323: pos.mx produces IR", false)
14840 } else {
14841 funcCount := strings.Count(ir, "\ndefine ")
14842 fmt.Printf("=== pos.mx (real file) ===\n")
14843 fmt.Printf("Source: %d lines | IR: %d bytes, %d functions\n",
14844 strings.Count(string(posSrc), "\n"), len(ir), funcCount)
14845 assert("323: produces IR", len(ir) > 5000)
14846 assert("323: many functions", funcCount >= 15)
14847 llvmVerify("323: real pos.mx", ir)
14848 }
14849 irFree(h)
14850 }
14851 }
14852 clearImports()
14853
14854 // Test 212: Scale test
14855 src212 := []byte(`package main
14856
14857 type Type interface {
14858 Underlying() Type
14859 String() string
14860 }
14861
14862 type Basic struct {
14863 kind int32
14864 name string
14865 }
14866 func (b *Basic) Underlying() Type { return b }
14867 func (b *Basic) String() string { return b.name }
14868
14869 type Slice struct{ elem Type }
14870 func (s *Slice) Underlying() Type { return s }
14871 func (s *Slice) String() string { return "[]" | s.elem.String() }
14872 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
14873
14874 type Pointer struct{ base Type }
14875 func (p *Pointer) Underlying() Type { return p }
14876 func (p *Pointer) String() string { return "*" | p.base.String() }
14877 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
14878
14879 type Named struct {
14880 name string
14881 underlying Type
14882 methods []*Func211
14883 }
14884 func (n *Named) Underlying() Type { return n.underlying }
14885 func (n *Named) String() string { return n.name }
14886 func (n *Named) AddMethod(m *Func211) { n.methods = append(n.methods, m) }
14887
14888 type Var211 struct {
14889 name string
14890 typ Type
14891 }
14892 func NewVar211(name string, typ Type) *Var211 { return &Var211{name: name, typ: typ} }
14893 func (v *Var211) Name() string { return v.name }
14894 func (v *Var211) Type() Type { return v.typ }
14895
14896 type Tuple struct{ vars []*Var211 }
14897 func NewTuple(vars ...*Var211) *Tuple {
14898 if len(vars) == 0 { return nil }
14899 return &Tuple{vars: vars}
14900 }
14901 func (t *Tuple) Len() int32 { return int32(len(t.vars)) }
14902 func (t *Tuple) At(i int32) *Var211 { return t.vars[i] }
14903
14904 type Signature struct {
14905 recv *Var211
14906 params *Tuple
14907 results *Tuple
14908 }
14909 func NewSignature(recv *Var211, params *Tuple, results *Tuple) *Signature {
14910 return &Signature{recv: recv, params: params, results: results}
14911 }
14912 func (s *Signature) Underlying() Type { return s }
14913 func (s *Signature) String() string { return "func" }
14914 func (s *Signature) Params() *Tuple { return s.params }
14915 func (s *Signature) Results() *Tuple { return s.results }
14916
14917 type Func211 struct {
14918 name string
14919 typ Type
14920 }
14921
14922 func main() {
14923 intT := &Basic{kind: 2, name: "int"}
14924 strT := &Basic{kind: 14, name: "string"}
14925
14926 sliceInt := NewSlice(intT)
14927 ptrStr := NewPointer(strT)
14928
14929 named := &Named{name: "MyType", underlying: sliceInt}
14930 sig := NewSignature(
14931 NewVar211("s", named),
14932 NewTuple(NewVar211("i", intT)),
14933 NewTuple(NewVar211("", intT)),
14934 )
14935 named.AddMethod(&Func211{name: "Get", typ: sig})
14936
14937 s1 := sliceInt.String()
14938 s2 := ptrStr.String()
14939 s3 := named.String()
14940 _ = s1
14941 _ = s2
14942 _ = s3
14943 _ = sig.Params().Len()
14944 }
14945 `)
14946 name212 := []byte("main")
14947 h212 := compileToIR(
14948 uintptr(unsafe.Pointer(&src212[0])), int32(len(src212)),
14949 uintptr(unsafe.Pointer(&name212[0])), int32(len(name212)),
14950 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
14951 )
14952 ir212 := getIR(h212)
14953 if ir212 == "" {
14954 assert("212: scale test produces IR", false)
14955 } else {
14956 voidCount := strings.Count(ir212, "void %")
14957 funcCount := strings.Count(ir212, "\ndefine ")
14958 lineCount := strings.Count(string(src212), "\n")
14959 fmt.Printf("=== Scale test (211) ===\n")
14960 fmt.Printf("Source: %d lines, %d bytes | IR: %d bytes, %d functions, void fields: %d\n",
14961 lineCount, len(src212), len(ir212), funcCount, voidCount)
14962 assert("212: produces IR", len(ir212) > 1000)
14963 assert("212: zero void fields", voidCount == 0)
14964 assert("212: has NewSignature", strings.Contains(ir212, "@main.NewSignature"))
14965 llvmVerify("212: scale test", ir212)
14966 }
14967 irFree(h212)
14968
14969 fmt.Printf("\n%d/%d tests passed\n", pass, pass+fail)
14970 if fail > 0 {
14971 os.Exit(1)
14972 }
14973 }
14974