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 var registerType func(uintptr, int32, uintptr, int32, uintptr, int32)
124 purego.RegisterLibFunc(®isterType, lib, "moxie_register_type")
125
126 var registerMethod func(uintptr, int32, uintptr, int32, uintptr, int32, uintptr, int32, int32)
127 purego.RegisterLibFunc(®isterMethod, lib, "moxie_register_method")
128
129 var registerConst func(uintptr, int32, uintptr, int32, uintptr, int32, int64)
130 purego.RegisterLibFunc(®isterConst, lib, "moxie_register_const")
131
132 regPkg := func(path, name string) {
133 pb := []byte(path)
134 nb := []byte(name)
135 registerPackage(uintptr(unsafe.Pointer(&pb[0])), int32(len(pb)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)))
136 }
137 regFn := func(pkgPath, name, sig string) {
138 pp := []byte(pkgPath)
139 nb := []byte(name)
140 if sig == "" {
141 registerFunc(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), 0, 0)
142 return
143 }
144 sb := []byte(sig)
145 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)))
146 }
147 regVar := func(pkgPath, name, typ string) {
148 pp := []byte(pkgPath)
149 nb := []byte(name)
150 tb := []byte(typ)
151 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)))
152 }
153 _ = regVar
154 regConst := func(pkgPath, name, typ string, val int64) {
155 pp := []byte(pkgPath)
156 nb := []byte(name)
157 tb := []byte(typ)
158 registerConst(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), uintptr(unsafe.Pointer(&tb[0])), int32(len(tb)), val)
159 }
160 _ = regConst
161 regIface := func(pkgPath, name, methods string) {
162 pp := []byte(pkgPath)
163 nb := []byte(name)
164 mb := []byte(methods)
165 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)))
166 }
167 _ = regIface
168 regType := func(pkgPath, name, underlying string) {
169 pp := []byte(pkgPath)
170 nb := []byte(name)
171 if underlying == "" {
172 registerType(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), 0, 0)
173 } else {
174 ub := []byte(underlying)
175 registerType(uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)), uintptr(unsafe.Pointer(&nb[0])), int32(len(nb)), uintptr(unsafe.Pointer(&ub[0])), int32(len(ub)))
176 }
177 }
178 _ = regType
179 regMethod := func(pkgPath, typeName, methodName, sig string, ptrRecv bool) {
180 pp := []byte(pkgPath)
181 tn := []byte(typeName)
182 mn := []byte(methodName)
183 sb := []byte(sig)
184 pr := int32(0)
185 if ptrRecv { pr = 1 }
186 registerMethod(
187 uintptr(unsafe.Pointer(&pp[0])), int32(len(pp)),
188 uintptr(unsafe.Pointer(&tn[0])), int32(len(tn)),
189 uintptr(unsafe.Pointer(&mn[0])), int32(len(mn)),
190 uintptr(unsafe.Pointer(&sb[0])), int32(len(sb)),
191 pr,
192 )
193 }
194 _ = regMethod
195
196 // Subprocess mode: compile a single file and report result
197 if len(os.Args) >= 4 && os.Args[2] == "--compile-file" {
198 src, err := os.ReadFile(os.Args[3])
199 if err != nil {
200 fmt.Fprintf(os.Stderr, "read error: %v", err)
201 os.Exit(1)
202 }
203 // Warm up: compile a trivial source to initialize universe types (Typ[] etc.)
204 // before registering imports that depend on parseTypeDesc.
205 warmup := []byte("package main\nfunc main() {}\n")
206 wpkg := []byte("main")
207 wh := compileToIR(
208 uintptr(unsafe.Pointer(&warmup[0])), int32(len(warmup)),
209 uintptr(unsafe.Pointer(&wpkg[0])), int32(len(wpkg)),
210 uintptr(unsafe.Pointer(&[]byte("x86_64-unknown-linux-musl")[0])), 25,
211 )
212 irFree(wh)
213 clearImports()
214 regPkg("go/token", "token")
215 regConst("go/token", "ILLEGAL", "int", 0)
216 regConst("go/token", "EOF", "int", 1)
217 regConst("go/token", "COMMENT", "int", 2)
218 regConst("go/token", "IDENT", "int", 4)
219 regConst("go/token", "INT", "int", 5)
220 regConst("go/token", "FLOAT", "int", 6)
221 regConst("go/token", "IMAG", "int", 7)
222 regConst("go/token", "CHAR", "int", 8)
223 regConst("go/token", "STRING", "int", 9)
224 regConst("go/token", "ADD", "int", 12)
225 regConst("go/token", "SUB", "int", 13)
226 regConst("go/token", "MUL", "int", 14)
227 regConst("go/token", "QUO", "int", 15)
228 regConst("go/token", "REM", "int", 16)
229 regConst("go/token", "AND", "int", 17)
230 regConst("go/token", "OR", "int", 18)
231 regConst("go/token", "XOR", "int", 19)
232 regConst("go/token", "SHL", "int", 20)
233 regConst("go/token", "SHR", "int", 21)
234 regConst("go/token", "AND_NOT", "int", 22)
235 regConst("go/token", "LAND", "int", 34)
236 regConst("go/token", "LOR", "int", 35)
237 regConst("go/token", "ARROW", "int", 36)
238 regConst("go/token", "INC", "int", 37)
239 regConst("go/token", "DEC", "int", 38)
240 regConst("go/token", "EQL", "int", 39)
241 regConst("go/token", "LSS", "int", 40)
242 regConst("go/token", "GTR", "int", 41)
243 regConst("go/token", "ASSIGN", "int", 42)
244 regConst("go/token", "NOT", "int", 43)
245 regConst("go/token", "NEQ", "int", 44)
246 regConst("go/token", "LEQ", "int", 45)
247 regConst("go/token", "GEQ", "int", 46)
248 regConst("go/token", "DEFINE", "int", 47)
249 regConst("go/token", "ELLIPSIS", "int", 48)
250 regConst("go/token", "DEFAULT", "int", 62)
251 regType("go/token", "Token", "int")
252 regPkg("go/constant", "constant")
253 regConst("go/constant", "Unknown", "int", 0)
254 regConst("go/constant", "Bool", "int", 1)
255 regConst("go/constant", "String", "int", 2)
256 regConst("go/constant", "Int", "int", 3)
257 regConst("go/constant", "Float", "int", 4)
258 regConst("go/constant", "Complex", "int", 5)
259 regIface("go/constant", "Value", "Kind=->int;String=->string;ExactString=->string")
260 regFn("go/constant", "MakeInt64", "int64->interface{}")
261 regFn("go/constant", "MakeFloat64", "float64->interface{}")
262 regFn("go/constant", "MakeString", "string->interface{}")
263 regFn("go/constant", "MakeFromLiteral", "string,int,int->interface{}")
264 regFn("go/constant", "BinaryOp", "interface{},int,interface{}->interface{}")
265 regFn("go/constant", "UnaryOp", "int,interface{},int->interface{}")
266 regFn("go/constant", "Compare", "interface{},int,interface{}->bool")
267 regFn("go/constant", "StringVal", "interface{}->string")
268 regFn("go/constant", "Int64Val", "interface{}->int64,bool")
269 regFn("go/constant", "Uint64Val", "interface{}->uint64,bool")
270 regFn("go/constant", "Float64Val", "interface{}->float64,bool")
271 regFn("go/constant", "BitLen", "interface{}->int")
272 regFn("go/constant", "Sign", "interface{}->int")
273 regPkg("fmt", "fmt")
274 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
275 regFn("fmt", "Fprintf", "interface{},string,interface{},interface{}->int,error")
276 regPkg("os", "os")
277 regVar("os", "Stderr", "interface{}")
278 regPkg("strconv", "strconv")
279 regFn("strconv", "Itoa", "int->string")
280 regFn("strconv", "FormatInt", "int64,int->string")
281 regFn("strconv", "FormatFloat", "float64,byte,int,int->string")
282 regFn("strconv", "ParseInt", "string,int,int->int64,error")
283 regFn("strconv", "ParseUint", "string,int,int->uint64,error")
284 regFn("strconv", "ParseFloat", "string,int->float64,error")
285 regFn("strconv", "Unquote", "string->string,error")
286 regPkg("bytes", "bytes")
287 regFn("bytes", "NewReader", "*byte->interface{}")
288 regType("bytes", "Reader", "")
289 regMethod("bytes", "Reader", "Read", "[]byte->int,error", true)
290 regFn("bytes", "IndexByte", "[]byte,byte->int")
291 regFn("bytes", "HasPrefix", "[]byte,[]byte->bool")
292 regFn("bytes", "TrimSpace", "[]byte->[]byte")
293 regFn("bytes", "Index", "[]byte,[]byte->int")
294 regFn("bytes", "LastIndexByte", "[]byte,byte->int")
295 regFn("bytes", "Trim", "[]byte,string->[]byte")
296 regPkg("io", "io")
297 regIface("io", "Reader", "Read=[]byte->int,error")
298 regVar("io", "EOF", "error")
299 regVar("io", "ErrNoProgress", "error")
300 regPkg("runtime", "runtime")
301 regFn("runtime", "InitCShared", "")
302 regPkg("unsafe", "unsafe")
303 regPkg("unicode", "unicode")
304 regType("unicode", "Tables", "")
305 regMethod("unicode", "Tables", "IsLetter", "int32->bool", true)
306 regMethod("unicode", "Tables", "IsDigit", "int32->bool", true)
307 regFn("unicode", "NewTables", "->ptr")
308 regFn("unicode", "IsLetter", "int32->bool")
309 regFn("unicode", "IsDigit", "int32->bool")
310 regFn("unicode", "IsSpace", "int32->bool")
311 regVar("unicode", "MaxRune", "int32")
312 regPkg("unicode/utf8", "utf8")
313 regFn("unicode/utf8", "DecodeRune", "[]byte->int32,int")
314 regFn("unicode/utf8", "RuneLen", "int32->int")
315 regVar("unicode/utf8", "RuneSelf", "int")
316 regVar("unicode/utf8", "UTFMax", "int")
317 regVar("unicode/utf8", "RuneError", "int32")
318 regFn("unicode/utf8", "FullRune", "[]byte->bool")
319 triple := []byte("x86_64-unknown-linux-musl")
320 pkg := []byte("main")
321 fmt.Fprintf(os.Stderr, "[sub] compiling %d bytes from %s\n", len(src), os.Args[3])
322 h := compileToIR(
323 uintptr(unsafe.Pointer(&src[0])), int32(len(src)),
324 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
325 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
326 )
327 fmt.Fprintf(os.Stderr, "[sub] compile returned h=%d\n", h)
328 l := irLen(h)
329 if l == 0 {
330 fmt.Print("IR=0")
331 os.Exit(0)
332 }
333 buf := make([]byte, l)
334 irCopy(h, uintptr(unsafe.Pointer(&buf[0])), l)
335 ir := string(buf)
336 funcCount := strings.Count(ir, "\ndefine ")
337 if funcCount == 0 {
338 fmt.Printf("IR=%d funcs=%d\n%s", len(ir), funcCount, ir)
339 } else {
340 fmt.Printf("IR=%d funcs=%d", len(ir), funcCount)
341 }
342 if len(os.Args) >= 5 && os.Args[4] != "" {
343 os.WriteFile(os.Args[4], []byte(ir), 0644)
344 fmt.Fprintf(os.Stderr, "[sub] wrote IR to %s\n", os.Args[4])
345 }
346 irFree(h)
347 os.Exit(0)
348 }
349
350 // --dump-gen1 <output.ll>: concatenate all 23 compiler .mx files, compile via gen0, write IR
351 if len(os.Args) >= 4 && os.Args[2] == "--dump-gen1" {
352 outFile := os.Args[3]
353 warmup := []byte("package main\nfunc main() {}\n")
354 wpkg := []byte("main")
355 wh := compileToIR(
356 uintptr(unsafe.Pointer(&warmup[0])), int32(len(warmup)),
357 uintptr(unsafe.Pointer(&wpkg[0])), int32(len(wpkg)),
358 uintptr(unsafe.Pointer(&[]byte("x86_64-unknown-linux-musl")[0])), 25,
359 )
360 irFree(wh)
361 clearImports()
362 regPkg("go/token", "token")
363 regConst("go/token", "ILLEGAL", "int", 0)
364 regConst("go/token", "EOF", "int", 1)
365 regConst("go/token", "COMMENT", "int", 2)
366 regConst("go/token", "IDENT", "int", 4)
367 regConst("go/token", "INT", "int", 5)
368 regConst("go/token", "FLOAT", "int", 6)
369 regConst("go/token", "IMAG", "int", 7)
370 regConst("go/token", "CHAR", "int", 8)
371 regConst("go/token", "STRING", "int", 9)
372 regConst("go/token", "ADD", "int", 12)
373 regConst("go/token", "SUB", "int", 13)
374 regConst("go/token", "MUL", "int", 14)
375 regConst("go/token", "QUO", "int", 15)
376 regConst("go/token", "REM", "int", 16)
377 regConst("go/token", "AND", "int", 17)
378 regConst("go/token", "OR", "int", 18)
379 regConst("go/token", "XOR", "int", 19)
380 regConst("go/token", "SHL", "int", 20)
381 regConst("go/token", "SHR", "int", 21)
382 regConst("go/token", "AND_NOT", "int", 22)
383 regConst("go/token", "LAND", "int", 34)
384 regConst("go/token", "LOR", "int", 35)
385 regConst("go/token", "ARROW", "int", 36)
386 regConst("go/token", "INC", "int", 37)
387 regConst("go/token", "DEC", "int", 38)
388 regConst("go/token", "EQL", "int", 39)
389 regConst("go/token", "LSS", "int", 40)
390 regConst("go/token", "GTR", "int", 41)
391 regConst("go/token", "ASSIGN", "int", 42)
392 regConst("go/token", "NOT", "int", 43)
393 regConst("go/token", "NEQ", "int", 44)
394 regConst("go/token", "LEQ", "int", 45)
395 regConst("go/token", "GEQ", "int", 46)
396 regConst("go/token", "DEFINE", "int", 47)
397 regConst("go/token", "ELLIPSIS", "int", 48)
398 regConst("go/token", "DEFAULT", "int", 62)
399 regType("go/token", "Token", "int")
400 regPkg("go/constant", "constant")
401 regConst("go/constant", "Unknown", "int", 0)
402 regConst("go/constant", "Bool", "int", 1)
403 regConst("go/constant", "String", "int", 2)
404 regConst("go/constant", "Int", "int", 3)
405 regConst("go/constant", "Float", "int", 4)
406 regConst("go/constant", "Complex", "int", 5)
407 regIface("go/constant", "Value", "Kind=->int;String=->string;ExactString=->string")
408 regFn("go/constant", "MakeInt64", "int64->interface{}")
409 regFn("go/constant", "MakeFloat64", "float64->interface{}")
410 regFn("go/constant", "MakeString", "string->interface{}")
411 regFn("go/constant", "MakeFromLiteral", "string,int,int->interface{}")
412 regFn("go/constant", "BinaryOp", "interface{},int,interface{}->interface{}")
413 regFn("go/constant", "UnaryOp", "int,interface{},int->interface{}")
414 regFn("go/constant", "Compare", "interface{},int,interface{}->bool")
415 regFn("go/constant", "StringVal", "interface{}->string")
416 regFn("go/constant", "Int64Val", "interface{}->int64,bool")
417 regFn("go/constant", "Uint64Val", "interface{}->uint64,bool")
418 regFn("go/constant", "Float64Val", "interface{}->float64,bool")
419 regFn("go/constant", "BitLen", "interface{}->int")
420 regFn("go/constant", "Sign", "interface{}->int")
421 regPkg("fmt", "fmt")
422 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
423 regFn("fmt", "Fprintf", "interface{},string,interface{},interface{}->int,error")
424 regPkg("os", "os")
425 regVar("os", "Stderr", "interface{}")
426 regPkg("strconv", "strconv")
427 regFn("strconv", "Itoa", "int->string")
428 regFn("strconv", "FormatInt", "int64,int->string")
429 regFn("strconv", "FormatFloat", "float64,byte,int,int->string")
430 regFn("strconv", "ParseInt", "string,int,int->int64,error")
431 regFn("strconv", "ParseUint", "string,int,int->uint64,error")
432 regFn("strconv", "ParseFloat", "string,int->float64,error")
433 regFn("strconv", "Unquote", "string->string,error")
434 regPkg("bytes", "bytes")
435 regFn("bytes", "NewReader", "*byte->interface{}")
436 regType("bytes", "Reader", "")
437 regMethod("bytes", "Reader", "Read", "[]byte->int,error", true)
438 regFn("bytes", "IndexByte", "[]byte,byte->int")
439 regFn("bytes", "HasPrefix", "[]byte,[]byte->bool")
440 regFn("bytes", "TrimSpace", "[]byte->[]byte")
441 regFn("bytes", "Index", "[]byte,[]byte->int")
442 regFn("bytes", "LastIndexByte", "[]byte,byte->int")
443 regFn("bytes", "Trim", "[]byte,string->[]byte")
444 regPkg("io", "io")
445 regIface("io", "Reader", "Read=[]byte->int,error")
446 regVar("io", "EOF", "error")
447 regVar("io", "ErrNoProgress", "error")
448 regPkg("runtime", "runtime")
449 regFn("runtime", "InitCShared", "")
450 regPkg("unsafe", "unsafe")
451 regPkg("unicode", "unicode")
452 regType("unicode", "Tables", "")
453 regMethod("unicode", "Tables", "IsLetter", "int32->bool", true)
454 regMethod("unicode", "Tables", "IsDigit", "int32->bool", true)
455 regFn("unicode", "NewTables", "->ptr")
456 regFn("unicode", "IsLetter", "int32->bool")
457 regFn("unicode", "IsDigit", "int32->bool")
458 regFn("unicode", "IsSpace", "int32->bool")
459 regVar("unicode", "MaxRune", "int32")
460 regPkg("unicode/utf8", "utf8")
461 regFn("unicode/utf8", "DecodeRune", "[]byte->int32,int")
462 regFn("unicode/utf8", "RuneLen", "int32->int")
463 regVar("unicode/utf8", "RuneSelf", "int")
464 regVar("unicode/utf8", "UTFMax", "int")
465 regVar("unicode/utf8", "RuneError", "int32")
466 regFn("unicode/utf8", "FullRune", "[]byte->bool")
467 compileDir := filepath.Join(filepath.Dir(soPath), "compile")
468 mxFiles := []string{
469 "pos.mx", "source.mx", "tokens.mx", "nodes.mx", "syntax.mx",
470 "scanner.mx", "parser.mx",
471 "tc_scope.mx", "tc_package.mx", "tc_info.mx", "tc_object.mx",
472 "tc_types.mx", "tc_universe.mx", "tc_const.mx", "tc_resolve.mx",
473 "tc_checker.mx", "tc_decl.mx", "tc_expr.mx", "tc_stmt.mx", "tc_assign.mx",
474 "ssa_types.mx", "ssa_builder.mx", "ir_emit.mx",
475 }
476 combined, fc, tl := concatMxSources(compileDir, mxFiles)
477 exportsPath := filepath.Join(filepath.Dir(soPath), "gen1_exports.mx")
478 exportsData, eerr := os.ReadFile(exportsPath)
479 if eerr == nil {
480 lines := strings.Split(string(exportsData), "\n")
481 var body []string
482 for _, line := range lines {
483 trimmed := strings.TrimSpace(line)
484 if strings.HasPrefix(trimmed, "package ") {
485 continue
486 }
487 body = append(body, line)
488 }
489 combined = append(combined, []byte(strings.Join(body, "\n"))...)
490 fc++
491 tl += len(lines)
492 }
493 combined = append(combined, []byte("\nfunc main() {}\n")...)
494 fmt.Fprintf(os.Stderr, "gen1 extract: %d files, %d lines, %d bytes\n", fc, tl, len(combined))
495 triple := []byte("x86_64-unknown-linux-musl")
496 pkg := []byte("main")
497 h := compileToIR(
498 uintptr(unsafe.Pointer(&combined[0])), int32(len(combined)),
499 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
500 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
501 )
502 l := irLen(h)
503 if l == 0 {
504 fmt.Fprintf(os.Stderr, "FATAL: gen1 compilation produced no IR\n")
505 os.Exit(1)
506 }
507 buf := make([]byte, l)
508 irCopy(h, uintptr(unsafe.Pointer(&buf[0])), l)
509 ir := string(buf)
510 funcCount := strings.Count(ir, "\ndefine ")
511 fmt.Fprintf(os.Stderr, "gen1 IR: %d bytes, %d functions\n", len(ir), funcCount)
512 os.WriteFile(outFile, []byte(ir), 0644)
513 fmt.Fprintf(os.Stderr, "wrote %s\n", outFile)
514 irFree(h)
515 os.Exit(0)
516 }
517
518 pass := 0
519 fail := 0
520 assert := func(name string, cond bool) {
521 if cond {
522 pass++
523 } else {
524 fail++
525 fmt.Fprintf(os.Stderr, "FAIL: %s\n", name)
526 }
527 }
528
529 llvmVerify := func(name, ir string) {
530 if ir == "" {
531 fail++
532 fmt.Fprintf(os.Stderr, "FAIL: %s llvm-verify (empty IR)\n", name)
533 return
534 }
535 cmd := exec.Command("llvm-as-21", "-o", "/dev/null")
536 cmd.Stdin = strings.NewReader(ir)
537 out, err := cmd.CombinedOutput()
538 if err != nil {
539 fail++
540 fmt.Fprintf(os.Stderr, "FAIL: %s llvm-verify: %s\n%s\n", name, err, out)
541 } else {
542 pass++
543 }
544 }
545
546 getIR := func(h int32) string {
547 n := irLen(h)
548 if n <= 0 {
549 return ""
550 }
551 buf := make([]byte, n)
552 got := irCopy(h, uintptr(unsafe.Pointer(&buf[0])), n)
553 return string(buf[:got])
554 }
555
556 name1 := []byte("mypkg")
557 triple := []byte("x86_64-unknown-linux-musl")
558
559 dumpTests := map[int]bool{}
560 test := func(num int, src string, checks func(string)) {
561 srcb := []byte(src)
562 pkg := []byte("main")
563 if strings.HasPrefix(src, "package mypkg") {
564 pkg = name1
565 }
566 h := compileToIR(
567 uintptr(unsafe.Pointer(&srcb[0])), int32(len(srcb)),
568 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
569 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
570 )
571 ir := getIR(h)
572 if ir == "" {
573 fail++
574 fmt.Fprintf(os.Stderr, "FAIL: test %d: empty IR\n", num)
575 irFree(h)
576 return
577 }
578 if dumpTests[num] {
579 fmt.Fprintf(os.Stderr, "=== IR test %d ===\n%s\n", num, ir)
580 }
581 llvmVerify(fmt.Sprintf("test %d", num), ir)
582 checks(ir)
583 irFree(h)
584 }
585 _ = test
586
587 // Test 1: Simple add function
588 src1 := []byte(`package mypkg
589
590 func add(a, b int32) int32 {
591 return a + b
592 }
593 `)
594 h1 := compileToIR(
595 uintptr(unsafe.Pointer(&src1[0])), int32(len(src1)),
596 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
597 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
598 )
599 assert("compile returns handle >= 0", h1 >= 0)
600
601 ir1 := getIR(h1)
602 fmt.Println("=== IR for add ===")
603 fmt.Println(ir1)
604
605 llvmVerify("add", ir1)
606 assert("IR contains target triple", strings.Contains(ir1, "x86_64"))
607 assert("IR contains define", strings.Contains(ir1, "define"))
608 assert("IR contains @mypkg.add", strings.Contains(ir1, "@mypkg.add"))
609 assert("IR contains i32", strings.Contains(ir1, "i32"))
610 assert("IR contains add instruction", strings.Contains(ir1, "add i32"))
611 assert("IR contains ret", strings.Contains(ir1, "ret i32"))
612 assert("IR contains entry block", strings.Contains(ir1, "entry:"))
613
614 irFree(h1)
615
616 // Test 2: Control flow (if/else)
617 src2 := []byte(`package mypkg
618
619 func max(a, b int32) int32 {
620 if a > b {
621 return a
622 }
623 return b
624 }
625 `)
626 h2 := compileToIR(
627 uintptr(unsafe.Pointer(&src2[0])), int32(len(src2)),
628 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
629 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
630 )
631 ir2 := getIR(h2)
632 fmt.Println("=== IR for max ===")
633 fmt.Println(ir2)
634
635 llvmVerify("max", ir2)
636 assert("max IR contains icmp", strings.Contains(ir2, "icmp"))
637 assert("max IR contains br", strings.Contains(ir2, "br"))
638 assert("max IR contains multiple blocks", strings.Count(ir2, ":") >= 2)
639
640 irFree(h2)
641
642 // Test 3: Global variables
643 src3 := []byte(`package mypkg
644
645 var counter int32
646
647 func inc() {
648 counter = counter + 1
649 }
650 `)
651 h3 := compileToIR(
652 uintptr(unsafe.Pointer(&src3[0])), int32(len(src3)),
653 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
654 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
655 )
656 ir3 := getIR(h3)
657 fmt.Println("=== IR for counter ===")
658 fmt.Println(ir3)
659
660 llvmVerify("counter", ir3)
661 assert("counter IR has global", strings.Contains(ir3, "@mypkg.counter"))
662 assert("counter IR has global decl", strings.Contains(ir3, "global"))
663
664 irFree(h3)
665
666 // Test 4: Function calls
667 src4 := []byte(`package mypkg
668
669 func double(x int32) int32 {
670 return x + x
671 }
672
673 func quadruple(x int32) int32 {
674 return double(double(x))
675 }
676 `)
677 h4 := compileToIR(
678 uintptr(unsafe.Pointer(&src4[0])), int32(len(src4)),
679 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
680 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
681 )
682 ir4 := getIR(h4)
683 fmt.Println("=== IR for calls ===")
684 fmt.Println(ir4)
685
686 llvmVerify("calls", ir4)
687 assert("calls IR has call instruction", strings.Contains(ir4, "call"))
688 assert("calls IR has @mypkg.double", strings.Contains(ir4, "@mypkg.double"))
689 assert("calls IR has @mypkg.quadruple", strings.Contains(ir4, "@mypkg.quadruple"))
690
691 irFree(h4)
692
693 // Test 5: For loop
694 src5 := []byte(`package mypkg
695
696 func sum(n int32) int32 {
697 s := int32(0)
698 i := int32(0)
699 for i < n {
700 s = s + i
701 i = i + 1
702 }
703 return s
704 }
705 `)
706 h5 := compileToIR(
707 uintptr(unsafe.Pointer(&src5[0])), int32(len(src5)),
708 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
709 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
710 )
711 ir5 := getIR(h5)
712 fmt.Println("=== IR for loop ===")
713 fmt.Println(ir5)
714
715 llvmVerify("loop", ir5)
716 assert("loop IR has phi or branch back", strings.Contains(ir5, "br"))
717 assert("loop IR has icmp", strings.Contains(ir5, "icmp"))
718 assert("loop IR has multiple blocks", strings.Count(ir5, ":") >= 3)
719
720 irFree(h5)
721
722 // Test 6: Type conversion
723 src6 := []byte(`package mypkg
724
725 func widen(x int32) int64 {
726 return int64(x)
727 }
728
729 func narrow(x int64) int32 {
730 return int32(x)
731 }
732 `)
733 h6 := compileToIR(
734 uintptr(unsafe.Pointer(&src6[0])), int32(len(src6)),
735 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
736 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
737 )
738 ir6 := getIR(h6)
739 fmt.Println("=== IR for conversions ===")
740 fmt.Println(ir6)
741
742 llvmVerify("conversions", ir6)
743 assert("widen IR has sext", strings.Contains(ir6, "sext"))
744 assert("narrow IR has trunc", strings.Contains(ir6, "trunc"))
745
746 irFree(h6)
747
748 // Test 7: Pointer operations
749 src7 := []byte(`package mypkg
750
751 func setPtr(p *int32, v int32) {
752 *p = v
753 }
754
755 func getPtr(p *int32) int32 {
756 return *p
757 }
758 `)
759 h7 := compileToIR(
760 uintptr(unsafe.Pointer(&src7[0])), int32(len(src7)),
761 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
762 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
763 )
764 ir7 := getIR(h7)
765 fmt.Println("=== IR for pointers ===")
766 fmt.Println(ir7)
767
768 llvmVerify("pointers", ir7)
769 assert("setPtr IR has store", strings.Contains(ir7, "store"))
770 assert("getPtr IR has load", strings.Contains(ir7, "load"))
771 assert("pointer IR has ptr param", strings.Contains(ir7, "ptr %p"))
772
773 irFree(h7)
774
775 // Test 8: Boolean operations
776 src8 := []byte(`package mypkg
777
778 func both(a, b bool) bool {
779 if a {
780 if b {
781 return true
782 }
783 }
784 return false
785 }
786 `)
787 h8 := compileToIR(
788 uintptr(unsafe.Pointer(&src8[0])), int32(len(src8)),
789 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
790 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
791 )
792 ir8 := getIR(h8)
793 fmt.Println("=== IR for booleans ===")
794 fmt.Println(ir8)
795
796 llvmVerify("booleans", ir8)
797 assert("bool IR has i1 type", strings.Contains(ir8, "i1"))
798 assert("bool IR has br", strings.Contains(ir8, "br"))
799 assert("bool IR has true/false", strings.Contains(ir8, "true") || strings.Contains(ir8, "false"))
800
801 irFree(h8)
802
803 // Test 9: Structs
804 src9 := []byte(`package mypkg
805
806 type Point struct {
807 X int32
808 Y int32
809 }
810
811 func getX(p Point) int32 {
812 return p.X
813 }
814
815 func setY(p *Point, v int32) {
816 p.Y = v
817 }
818 `)
819 h9 := compileToIR(
820 uintptr(unsafe.Pointer(&src9[0])), int32(len(src9)),
821 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
822 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
823 )
824 ir9 := getIR(h9)
825 fmt.Println("=== IR for structs ===")
826 fmt.Println(ir9)
827
828 llvmVerify("structs", ir9)
829 assert("struct IR has getelementptr", strings.Contains(ir9, "getelementptr"))
830 assert("struct IR has i32 field type", strings.Contains(ir9, "i32"))
831 assert("struct IR has struct type", strings.Contains(ir9, "{") && strings.Contains(ir9, "}"))
832
833 irFree(h9)
834
835 // Test 10: Multiple return values
836 src10 := []byte(`package mypkg
837
838 func divmod(a, b int32) (int32, int32) {
839 return a / b, a % b
840 }
841 `)
842 h10 := compileToIR(
843 uintptr(unsafe.Pointer(&src10[0])), int32(len(src10)),
844 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
845 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
846 )
847 ir10 := getIR(h10)
848 fmt.Println("=== IR for multi-return ===")
849 fmt.Println(ir10)
850
851 llvmVerify("multi-return", ir10)
852 assert("multi-ret IR has sdiv", strings.Contains(ir10, "sdiv"))
853 assert("multi-ret IR has srem", strings.Contains(ir10, "srem"))
854 assert("multi-ret IR has insertvalue", strings.Contains(ir10, "insertvalue"))
855
856 irFree(h10)
857
858 // Test 11: Short variable declaration and address-of
859 src11 := []byte(`package mypkg
860
861 func newInt(v int32) *int32 {
862 x := v
863 return &x
864 }
865 `)
866 h11 := compileToIR(
867 uintptr(unsafe.Pointer(&src11[0])), int32(len(src11)),
868 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
869 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
870 )
871 ir11 := getIR(h11)
872 fmt.Println("=== IR for addr-of ===")
873 fmt.Println(ir11)
874
875 llvmVerify("addr-of", ir11)
876 assert("addr-of IR has alloca", strings.Contains(ir11, "alloca"))
877 assert("addr-of IR returns ptr", strings.Contains(ir11, "ret ptr"))
878
879 irFree(h11)
880
881 // Test 12: Unsigned operations
882 src12 := []byte(`package mypkg
883
884 func udiv(a, b uint32) uint32 {
885 return a / b
886 }
887
888 func ucomp(a, b uint32) bool {
889 return a < b
890 }
891 `)
892 h12 := compileToIR(
893 uintptr(unsafe.Pointer(&src12[0])), int32(len(src12)),
894 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
895 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
896 )
897 ir12 := getIR(h12)
898 fmt.Println("=== IR for unsigned ===")
899 fmt.Println(ir12)
900
901 llvmVerify("unsigned", ir12)
902 assert("unsigned IR has udiv", strings.Contains(ir12, "udiv"))
903 assert("unsigned IR has ult", strings.Contains(ir12, "ult"))
904
905 irFree(h12)
906
907 // Test 13: Extract from multi-return call
908 src13 := []byte(`package mypkg
909
910 func divmod(a, b int32) (int32, int32) {
911 return a / b, a % b
912 }
913
914 func justQuot(a, b int32) int32 {
915 q, _ := divmod(a, b)
916 return q
917 }
918
919 func justRem(a, b int32) int32 {
920 _, r := divmod(a, b)
921 return r
922 }
923 `)
924 h13 := compileToIR(
925 uintptr(unsafe.Pointer(&src13[0])), int32(len(src13)),
926 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
927 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
928 )
929 ir13 := getIR(h13)
930 fmt.Println("=== IR for extract ===")
931 fmt.Println(ir13)
932
933 llvmVerify("extract", ir13)
934 assert("extract IR has call", strings.Contains(ir13, "call {i32, i32}"))
935 assert("extract IR has extractvalue", strings.Contains(ir13, "extractvalue"))
936 assert("extract IR has extractvalue 0", strings.Contains(ir13, ", 0"))
937 assert("extract IR has extractvalue 1", strings.Contains(ir13, ", 1"))
938
939 irFree(h13)
940
941 // Test 14: Slice operations - make, len, cap, index
942 src14 := []byte(`package mypkg
943
944 func sliceLen(s []int32) int32 {
945 return len(s)
946 }
947
948 func sliceCap(s []int32) int32 {
949 return cap(s)
950 }
951
952 func sliceGet(s []int32, i int32) int32 {
953 return s[i]
954 }
955
956 func sliceSet(s []int32, i int32, v int32) {
957 s[i] = v
958 }
959 `)
960 h14 := compileToIR(
961 uintptr(unsafe.Pointer(&src14[0])), int32(len(src14)),
962 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
963 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
964 )
965 ir14 := getIR(h14)
966 fmt.Println("=== IR for slices ===")
967 fmt.Println(ir14)
968
969 llvmVerify("slices", ir14)
970 assert("slice len extracts field 1", strings.Contains(ir14, "extractvalue {ptr, i64, i64}") && strings.Contains(ir14, ", 1"))
971 assert("slice cap extracts field 2", strings.Contains(ir14, ", 2"))
972 assert("slice index has extractvalue 0", strings.Contains(ir14, ", 0"))
973 assert("slice index has getelementptr", strings.Contains(ir14, "getelementptr"))
974
975 irFree(h14)
976
977 // Test 15: Slice sub-expression
978 src15 := []byte(`package mypkg
979
980 func subslice(s []int32, lo, hi int32) []int32 {
981 return s[lo:hi]
982 }
983 `)
984 h15 := compileToIR(
985 uintptr(unsafe.Pointer(&src15[0])), int32(len(src15)),
986 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
987 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
988 )
989 ir15 := getIR(h15)
990 fmt.Println("=== IR for subslice ===")
991 fmt.Println(ir15)
992
993 llvmVerify("subslice", ir15)
994 assert("subslice has extractvalue", strings.Contains(ir15, "extractvalue"))
995 assert("subslice has getelementptr", strings.Contains(ir15, "getelementptr"))
996 assert("subslice has insertvalue", strings.Contains(ir15, "insertvalue"))
997 assert("subslice has sub for new len", strings.Contains(ir15, "sub"))
998
999 irFree(h15)
1000
1001 // Test 16: make([]T, n) and append
1002 src16 := []byte(`package mypkg
1003
1004 func makeSlice(n int32) []int32 {
1005 return make([]int32, n)
1006 }
1007
1008 func makeAndAppend(n int32) []int32 {
1009 s := make([]int32, 0, n)
1010 i := int32(0)
1011 for i < n {
1012 s = append(s, i)
1013 i = i + 1
1014 }
1015 return s
1016 }
1017 `)
1018 h16 := compileToIR(
1019 uintptr(unsafe.Pointer(&src16[0])), int32(len(src16)),
1020 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1021 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1022 )
1023 ir16 := getIR(h16)
1024 fmt.Println("=== IR for make+append ===")
1025 fmt.Println(ir16)
1026
1027 llvmVerify("make+append", ir16)
1028 assert("make has runtime.alloc", strings.Contains(ir16, "@runtime.alloc"))
1029 assert("make has insertvalue for slice", strings.Contains(ir16, "insertvalue"))
1030 assert("append has sliceAppend", strings.Contains(ir16, "@runtime.sliceAppend"))
1031
1032 irFree(h16)
1033
1034 // Test 17: Switch statement
1035 src17 := []byte(`package mypkg
1036
1037 func classify(x int32) int32 {
1038 switch {
1039 case x < 0:
1040 return -1
1041 case x == 0:
1042 return 0
1043 }
1044 return 1
1045 }
1046 `)
1047 h17 := compileToIR(
1048 uintptr(unsafe.Pointer(&src17[0])), int32(len(src17)),
1049 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1050 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1051 )
1052 ir17 := getIR(h17)
1053 fmt.Println("=== IR for switch ===")
1054 fmt.Println(ir17)
1055
1056 llvmVerify("switch", ir17)
1057 assert("switch has icmp", strings.Contains(ir17, "icmp"))
1058 assert("switch has multiple br", strings.Count(ir17, "br ") >= 2)
1059
1060 irFree(h17)
1061
1062 // Test 18: Nested struct access
1063 src18 := []byte(`package mypkg
1064
1065 type Inner struct {
1066 V int32
1067 }
1068
1069 type Outer struct {
1070 A Inner
1071 B int32
1072 }
1073
1074 func getInnerV(o *Outer) int32 {
1075 return o.A.V
1076 }
1077 `)
1078 h18 := compileToIR(
1079 uintptr(unsafe.Pointer(&src18[0])), int32(len(src18)),
1080 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1081 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1082 )
1083 ir18 := getIR(h18)
1084 fmt.Println("=== IR for nested struct ===")
1085 fmt.Println(ir18)
1086
1087 llvmVerify("nested struct", ir18)
1088 assert("nested struct has getelementptr", strings.Contains(ir18, "getelementptr"))
1089 assert("nested struct has load i32", strings.Contains(ir18, "load i32"))
1090
1091 irFree(h18)
1092
1093 // Test 19: Nil pointer check
1094 src19 := []byte(`package mypkg
1095
1096 func isNil(p *int32) bool {
1097 if p == nil {
1098 return true
1099 }
1100 return false
1101 }
1102 `)
1103 h19 := compileToIR(
1104 uintptr(unsafe.Pointer(&src19[0])), int32(len(src19)),
1105 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1106 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1107 )
1108 ir19 := getIR(h19)
1109 fmt.Println("=== IR for nil check ===")
1110 fmt.Println(ir19)
1111
1112 llvmVerify("nil check", ir19)
1113 assert("nil check has icmp", strings.Contains(ir19, "icmp"))
1114 assert("nil check has null/zeroinit", strings.Contains(ir19, "null") || strings.Contains(ir19, "zeroinitializer"))
1115
1116 irFree(h19)
1117
1118 // Test 20: Bitwise operations
1119 src20 := []byte(`package mypkg
1120
1121 func bitAnd(a, b int32) int32 {
1122 return a & b
1123 }
1124
1125 func bitXor(a, b int32) int32 {
1126 return a ^ b
1127 }
1128
1129 func bitShiftL(a int32, n uint32) int32 {
1130 return a << n
1131 }
1132
1133 func bitShiftR(a int32, n uint32) int32 {
1134 return a >> n
1135 }
1136 `)
1137 h20 := compileToIR(
1138 uintptr(unsafe.Pointer(&src20[0])), int32(len(src20)),
1139 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1140 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1141 )
1142 ir20 := getIR(h20)
1143 fmt.Println("=== IR for bitwise ===")
1144 fmt.Println(ir20)
1145
1146 llvmVerify("bitwise", ir20)
1147 assert("bitwise has and", strings.Contains(ir20, "and i32"))
1148 assert("bitwise has xor", strings.Contains(ir20, "xor i32"))
1149 assert("bitwise has shl", strings.Contains(ir20, "shl i32"))
1150 assert("bitwise has ashr", strings.Contains(ir20, "ashr i32"))
1151
1152 irFree(h20)
1153
1154 // Test 21: Slice/string concat (| operator -> OpAdd on slice type)
1155 src21 := []byte(`package mypkg
1156
1157 func concat(a, b []int32) []int32 {
1158 return a | b
1159 }
1160 `)
1161 h21 := compileToIR(
1162 uintptr(unsafe.Pointer(&src21[0])), int32(len(src21)),
1163 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1164 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1165 )
1166 ir21 := getIR(h21)
1167 fmt.Println("=== IR for slice concat ===")
1168 fmt.Println(ir21)
1169
1170 llvmVerify("slice concat", ir21)
1171 assert("concat calls sliceAppend", strings.Contains(ir21, "@runtime.sliceAppend"))
1172 assert("concat extracts ptr", strings.Contains(ir21, "extractvalue"))
1173 assert("concat builds result", strings.Contains(ir21, "insertvalue"))
1174
1175 irFree(h21)
1176
1177 // Test 22: for-range over slice
1178 src22 := []byte(`package mypkg
1179
1180 func sumRange(s []int32) int32 {
1181 total := int32(0)
1182 for _, v := range s {
1183 total = total + v
1184 }
1185 return total
1186 }
1187 `)
1188 h22 := compileToIR(
1189 uintptr(unsafe.Pointer(&src22[0])), int32(len(src22)),
1190 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1191 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1192 )
1193 ir22 := getIR(h22)
1194 fmt.Println("=== IR for range ===")
1195 fmt.Println(ir22)
1196
1197 llvmVerify("range", ir22)
1198 assert("range has alloca for iter", strings.Contains(ir22, "alloca i64"))
1199 assert("range has icmp ult", strings.Contains(ir22, "icmp ult"))
1200 assert("range has getelementptr", strings.Contains(ir22, "getelementptr"))
1201 assert("range has select", strings.Contains(ir22, "select"))
1202
1203 irFree(h22)
1204
1205 // Test 23: Map operations (make, set, get)
1206 src23 := []byte(`package mypkg
1207
1208 func mapSetGet() int32 {
1209 m := make(map[int32]int32)
1210 m[1] = 42
1211 return m[1]
1212 }
1213 `)
1214 h23 := compileToIR(
1215 uintptr(unsafe.Pointer(&src23[0])), int32(len(src23)),
1216 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1217 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1218 )
1219 ir23 := getIR(h23)
1220 fmt.Println("=== IR for map ops ===")
1221 fmt.Println(ir23)
1222
1223 llvmVerify("map ops", ir23)
1224 assert("map has hashmapMake", strings.Contains(ir23, "@runtime.hashmapMake"))
1225 assert("map has hashmapBinarySet", strings.Contains(ir23, "@runtime.hashmapBinarySet"))
1226 assert("map has hashmapBinaryGet", strings.Contains(ir23, "@runtime.hashmapBinaryGet"))
1227
1228 irFree(h23)
1229
1230 // Test 24: panic
1231 src24 := []byte(`package mypkg
1232
1233 func mustPositive(n int32) int32 {
1234 if n <= 0 {
1235 panic("negative")
1236 }
1237 return n
1238 }
1239 `)
1240 h24 := compileToIR(
1241 uintptr(unsafe.Pointer(&src24[0])), int32(len(src24)),
1242 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1243 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1244 )
1245 ir24 := getIR(h24)
1246 fmt.Println("=== IR for panic ===")
1247 fmt.Println(ir24)
1248
1249 llvmVerify("panic", ir24)
1250 assert("panic has runtime._panic", strings.Contains(ir24, "@runtime._panic"))
1251 assert("panic has unreachable", strings.Contains(ir24, "unreachable"))
1252
1253 irFree(h24)
1254
1255 // Test 25: copy builtin
1256 src25 := []byte(`package mypkg
1257
1258 func copySlice(dst, src []int32) int32 {
1259 return copy(dst, src)
1260 }
1261 `)
1262 h25 := compileToIR(
1263 uintptr(unsafe.Pointer(&src25[0])), int32(len(src25)),
1264 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1265 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1266 )
1267 ir25 := getIR(h25)
1268 fmt.Println("=== IR for copy ===")
1269 fmt.Println(ir25)
1270
1271 llvmVerify("copy", ir25)
1272 assert("copy calls sliceCopy", strings.Contains(ir25, "@runtime.sliceCopy"))
1273
1274 irFree(h25)
1275
1276 // Test 26: delete from map
1277 src26 := []byte(`package mypkg
1278
1279 func mapDelete(m map[int32]int32, k int32) {
1280 delete(m, k)
1281 }
1282 `)
1283 h26 := compileToIR(
1284 uintptr(unsafe.Pointer(&src26[0])), int32(len(src26)),
1285 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1286 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1287 )
1288 ir26 := getIR(h26)
1289 fmt.Println("=== IR for delete ===")
1290 fmt.Println(ir26)
1291
1292 llvmVerify("delete", ir26)
1293 assert("delete calls hashmapBinaryDelete", strings.Contains(ir26, "@runtime.hashmapBinaryDelete"))
1294
1295 irFree(h26)
1296
1297 // Test 27: float operations
1298 src27 := []byte(`package mypkg
1299
1300 func fadd(a, b float64) float64 {
1301 return a + b
1302 }
1303
1304 func fmul(a, b float64) float64 {
1305 return a * b
1306 }
1307
1308 func fcmp(a, b float64) bool {
1309 return a < b
1310 }
1311 `)
1312 h27 := compileToIR(
1313 uintptr(unsafe.Pointer(&src27[0])), int32(len(src27)),
1314 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1315 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1316 )
1317 ir27 := getIR(h27)
1318 fmt.Println("=== IR for float ===")
1319 fmt.Println(ir27)
1320
1321 llvmVerify("float", ir27)
1322 assert("float has fadd", strings.Contains(ir27, "fadd"))
1323 assert("float has fmul", strings.Contains(ir27, "fmul"))
1324 assert("float has fcmp", strings.Contains(ir27, "fcmp"))
1325
1326 irFree(h27)
1327
1328 // Test 28: Function value (function as first-class value passed as ptr)
1329 src28 := []byte(`package mypkg
1330
1331 func apply(f func(int32) int32, x int32) int32 {
1332 return f(x)
1333 }
1334 `)
1335 h28 := compileToIR(
1336 uintptr(unsafe.Pointer(&src28[0])), int32(len(src28)),
1337 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1338 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1339 )
1340 ir28 := getIR(h28)
1341 fmt.Println("=== IR for func value ===")
1342 fmt.Println(ir28)
1343
1344 llvmVerify("func value", ir28)
1345 assert("func value has call ptr", strings.Contains(ir28, "call i32 %"))
1346
1347 irFree(h28)
1348
1349 // Test 29: Array operations
1350 src29 := []byte(`package mypkg
1351
1352 func arrayGet(a [4]int32, i int32) int32 {
1353 return a[i]
1354 }
1355 `)
1356 h29 := compileToIR(
1357 uintptr(unsafe.Pointer(&src29[0])), int32(len(src29)),
1358 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1359 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1360 )
1361 ir29 := getIR(h29)
1362 fmt.Println("=== IR for array ===")
1363 fmt.Println(ir29)
1364
1365 llvmVerify("array", ir29)
1366 assert("array has [4 x i32]", strings.Contains(ir29, "[4 x i32]"))
1367 assert("array has getelementptr", strings.Contains(ir29, "getelementptr"))
1368
1369 irFree(h29)
1370
1371 // Test 30: Map comma-ok lookup
1372 src30 := []byte(`package mypkg
1373
1374 func mapLookup(m map[int32]int32, k int32) (int32, bool) {
1375 v, ok := m[k]
1376 return v, ok
1377 }
1378 `)
1379 h30 := compileToIR(
1380 uintptr(unsafe.Pointer(&src30[0])), int32(len(src30)),
1381 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1382 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1383 )
1384 ir30 := getIR(h30)
1385 fmt.Println("=== IR for comma-ok ===")
1386 fmt.Println(ir30)
1387
1388 llvmVerify("comma-ok", ir30)
1389 assert("comma-ok has hashmapBinaryGet", strings.Contains(ir30, "@runtime.hashmapBinaryGet"))
1390 assert("comma-ok returns tuple", strings.Contains(ir30, "{i32, i1}") || strings.Contains(ir30, "insertvalue"))
1391
1392 irFree(h30)
1393
1394 // Test 31: println with int and string
1395 src31 := []byte(`package mypkg
1396
1397 func hello(n int32) {
1398 println("hello", n)
1399 }
1400 `)
1401 h31 := compileToIR(
1402 uintptr(unsafe.Pointer(&src31[0])), int32(len(src31)),
1403 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1404 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1405 )
1406 ir31 := getIR(h31)
1407 fmt.Println("=== IR for println ===")
1408 fmt.Println(ir31)
1409
1410 llvmVerify("println", ir31)
1411 assert("println has printlock", strings.Contains(ir31, "@runtime.printlock"))
1412 assert("println has printstring", strings.Contains(ir31, "@runtime.printstring"))
1413 assert("println has printint32", strings.Contains(ir31, "@runtime.printint32"))
1414 assert("println has printspace", strings.Contains(ir31, "@runtime.printspace"))
1415 assert("println has printnl", strings.Contains(ir31, "@runtime.printnl"))
1416 assert("println has printunlock", strings.Contains(ir31, "@runtime.printunlock"))
1417
1418 irFree(h31)
1419
1420 // Test 32: print with bool and float
1421 src32 := []byte(`package mypkg
1422
1423 func debug(ok bool, val float64) {
1424 print(ok, val)
1425 }
1426 `)
1427 h32 := compileToIR(
1428 uintptr(unsafe.Pointer(&src32[0])), int32(len(src32)),
1429 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1430 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1431 )
1432 ir32 := getIR(h32)
1433 fmt.Println("=== IR for print ===")
1434 fmt.Println(ir32)
1435
1436 llvmVerify("print", ir32)
1437 assert("print has printbool", strings.Contains(ir32, "@runtime.printbool"))
1438 assert("print has printfloat64", strings.Contains(ir32, "@runtime.printfloat64"))
1439 assert("print no printspace", !strings.Contains(ir32, "@runtime.printspace"))
1440 assert("print no printnl", !strings.Contains(ir32, "@runtime.printnl"))
1441
1442 irFree(h32)
1443
1444 // Test 33: for-range over map
1445 src33 := []byte(`package mypkg
1446
1447 func sumMap(m map[int32]int32) int32 {
1448 total := int32(0)
1449 for _, v := range m {
1450 total = total + v
1451 }
1452 return total
1453 }
1454 `)
1455 h33 := compileToIR(
1456 uintptr(unsafe.Pointer(&src33[0])), int32(len(src33)),
1457 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1458 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1459 )
1460 ir33 := getIR(h33)
1461 fmt.Println("=== IR for map range ===")
1462 fmt.Println(ir33)
1463
1464 llvmVerify("map range", ir33)
1465 assert("map range has hashmapNext", strings.Contains(ir33, "@runtime.hashmapNext"))
1466 assert("map range has memset", strings.Contains(ir33, "llvm.memset"))
1467 assert("map range has alloca [48 x i8]", strings.Contains(ir33, "alloca [48 x i8]"))
1468
1469 irFree(h33)
1470
1471 // Test 34: string constant in println
1472 src34 := []byte(`package mypkg
1473
1474 func greet(name string) {
1475 println("hello", name)
1476 }
1477 `)
1478 h34 := compileToIR(
1479 uintptr(unsafe.Pointer(&src34[0])), int32(len(src34)),
1480 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1481 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1482 )
1483 ir34 := getIR(h34)
1484 fmt.Println("=== IR for string const ===")
1485 fmt.Println(ir34)
1486
1487 llvmVerify("string const", ir34)
1488 assert("string const has global", strings.Contains(ir34, "@.str."))
1489 assert("string const has c\"hello\"", strings.Contains(ir34, `c"hello"`))
1490 assert("string const has printstring with ptr", strings.Contains(ir34, "{ ptr @.str."))
1491
1492 irFree(h34)
1493
1494 // Test 35: global string variable
1495 src35 := []byte(`package mypkg
1496
1497 var greeting = "world"
1498
1499 func getGreeting() string {
1500 return greeting
1501 }
1502 `)
1503 h35 := compileToIR(
1504 uintptr(unsafe.Pointer(&src35[0])), int32(len(src35)),
1505 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1506 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1507 )
1508 ir35 := getIR(h35)
1509 fmt.Println("=== IR for global string ===")
1510 fmt.Println(ir35)
1511
1512 llvmVerify("global string", ir35)
1513 assert("global string has global var", strings.Contains(ir35, "@mypkg.greeting"))
1514 assert("global string has load slice", strings.Contains(ir35, "load {ptr, i64, i64}"))
1515
1516 irFree(h35)
1517
1518 // Test 36: logical not (unary !)
1519 src36 := []byte(`package mypkg
1520
1521 func negate(b bool) bool {
1522 return !b
1523 }
1524 `)
1525 h36 := compileToIR(
1526 uintptr(unsafe.Pointer(&src36[0])), int32(len(src36)),
1527 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1528 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1529 )
1530 ir36 := getIR(h36)
1531 fmt.Println("=== IR for not ===")
1532 fmt.Println(ir36)
1533
1534 llvmVerify("not", ir36)
1535 assert("not has xor", strings.Contains(ir36, "xor i1"))
1536
1537 irFree(h36)
1538
1539 // Test 37: global int variable (inferred type)
1540 src37 := []byte(`package mypkg
1541
1542 var counter = 42
1543
1544 func getCounter() int {
1545 return counter
1546 }
1547 `)
1548 h37 := compileToIR(
1549 uintptr(unsafe.Pointer(&src37[0])), int32(len(src37)),
1550 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1551 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1552 )
1553 ir37 := getIR(h37)
1554 fmt.Println("=== IR for global int ===")
1555 fmt.Println(ir37)
1556
1557 llvmVerify("global int", ir37)
1558 assert("global int has global var", strings.Contains(ir37, "@mypkg.counter = global i32"))
1559 assert("global int has load i32", strings.Contains(ir37, "load i32"))
1560
1561 irFree(h37)
1562
1563 // Test 38: string comparison
1564 src38 := []byte(`package mypkg
1565
1566 func isHello(s string) bool {
1567 return s == "hello"
1568 }
1569 `)
1570 h38 := compileToIR(
1571 uintptr(unsafe.Pointer(&src38[0])), int32(len(src38)),
1572 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1573 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1574 )
1575 ir38 := getIR(h38)
1576 fmt.Println("=== IR for string compare ===")
1577 fmt.Println(ir38)
1578
1579 llvmVerify("string compare", ir38)
1580 assert("string compare has call", strings.Contains(ir38, "call") || strings.Contains(ir38, "icmp"))
1581
1582 irFree(h38)
1583
1584 // Test 39: tagless switch (switch { case ... })
1585 src39 := []byte(`package mypkg
1586
1587 func classify(x int) int {
1588 switch {
1589 case x < 0:
1590 return -1
1591 case x == 0:
1592 return 0
1593 default:
1594 return 1
1595 }
1596 }
1597 `)
1598 h39 := compileToIR(
1599 uintptr(unsafe.Pointer(&src39[0])), int32(len(src39)),
1600 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1601 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1602 )
1603 ir39 := getIR(h39)
1604 fmt.Println("=== IR for tagless switch ===")
1605 fmt.Println(ir39)
1606
1607 llvmVerify("tagless switch", ir39)
1608 assert("tagless switch has icmp", strings.Contains(ir39, "icmp"))
1609 assert("tagless switch has br", strings.Contains(ir39, "br"))
1610
1611 irFree(h39)
1612
1613 // Test 40: slice of strings
1614 src40 := []byte(`package mypkg
1615
1616 func firstWord(words []string) string {
1617 return words[0]
1618 }
1619 `)
1620 h40 := compileToIR(
1621 uintptr(unsafe.Pointer(&src40[0])), int32(len(src40)),
1622 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1623 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1624 )
1625 ir40 := getIR(h40)
1626 fmt.Println("=== IR for slice of strings ===")
1627 fmt.Println(ir40)
1628
1629 llvmVerify("slice of strings", ir40)
1630 assert("slice of strings has gep", strings.Contains(ir40, "getelementptr"))
1631
1632 irFree(h40)
1633
1634 // Test 41: const declarations
1635 src41 := []byte(`package mypkg
1636
1637 const limit = 100
1638 const name = "test"
1639
1640 func getLimit() int { return limit }
1641 func getName() string { return name }
1642 `)
1643 h41 := compileToIR(
1644 uintptr(unsafe.Pointer(&src41[0])), int32(len(src41)),
1645 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1646 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1647 )
1648 ir41 := getIR(h41)
1649 fmt.Println("=== IR for const decls ===")
1650 fmt.Println(ir41)
1651
1652 llvmVerify("const decls", ir41)
1653 assert("const int returns i32", strings.Contains(ir41, "ret i32 100"))
1654 assert("const string has str ref", strings.Contains(ir41, "@.str."))
1655
1656 irFree(h41)
1657
1658 // Test 42: global variable mutation
1659 src42 := []byte(`package mypkg
1660
1661 var count int
1662
1663 func increment() {
1664 count = count + 1
1665 }
1666 `)
1667 h42 := compileToIR(
1668 uintptr(unsafe.Pointer(&src42[0])), int32(len(src42)),
1669 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1670 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1671 )
1672 ir42 := getIR(h42)
1673 fmt.Println("=== IR for global mutation ===")
1674 fmt.Println(ir42)
1675
1676 llvmVerify("global mutation", ir42)
1677 assert("global mutation has load", strings.Contains(ir42, "load i32, ptr @mypkg.count"))
1678 assert("global mutation has store", strings.Contains(ir42, "store i32"))
1679
1680 irFree(h42)
1681
1682 // Test 43: multiple return with named results
1683 src43 := []byte(`package mypkg
1684
1685 func divmod(a, b int) (int, int) {
1686 return a / b, a % b
1687 }
1688 `)
1689 h43 := compileToIR(
1690 uintptr(unsafe.Pointer(&src43[0])), int32(len(src43)),
1691 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1692 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1693 )
1694 ir43 := getIR(h43)
1695 fmt.Println("=== IR for divmod ===")
1696 fmt.Println(ir43)
1697
1698 llvmVerify("divmod", ir43)
1699 assert("divmod has sdiv", strings.Contains(ir43, "sdiv"))
1700 assert("divmod has srem", strings.Contains(ir43, "srem"))
1701 assert("divmod returns tuple", strings.Contains(ir43, "ret {i32, i32}"))
1702
1703 irFree(h43)
1704
1705 // Test 44: len on string
1706 src44 := []byte(`package mypkg
1707
1708 func strLen(s string) int {
1709 return len(s)
1710 }
1711 `)
1712 h44 := compileToIR(
1713 uintptr(unsafe.Pointer(&src44[0])), int32(len(src44)),
1714 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1715 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1716 )
1717 ir44 := getIR(h44)
1718 fmt.Println("=== IR for strlen ===")
1719 fmt.Println(ir44)
1720
1721 llvmVerify("strlen", ir44)
1722 assert("strlen has extractvalue for len", strings.Contains(ir44, "extractvalue"))
1723 assert("strlen has trunc", strings.Contains(ir44, "trunc"))
1724
1725 irFree(h44)
1726
1727 // Test 45: global bool variable (inferred type)
1728 src45 := []byte(`package mypkg
1729
1730 var enabled = true
1731
1732 func isEnabled() bool { return enabled }
1733 `)
1734 h45 := compileToIR(
1735 uintptr(unsafe.Pointer(&src45[0])), int32(len(src45)),
1736 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1737 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1738 )
1739 ir45 := getIR(h45)
1740 fmt.Println("=== IR for global bool ===")
1741 fmt.Println(ir45)
1742
1743 llvmVerify("global bool", ir45)
1744 assert("global bool has i1", strings.Contains(ir45, "@mypkg.enabled = global i1"))
1745
1746 irFree(h45)
1747
1748 // Test 46: string concat with + (which is | in Moxie SSA)
1749 src46 := []byte(`package mypkg
1750
1751 func greet(name string) string {
1752 return "hello " | name
1753 }
1754 `)
1755 h46 := compileToIR(
1756 uintptr(unsafe.Pointer(&src46[0])), int32(len(src46)),
1757 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1758 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1759 )
1760 ir46 := getIR(h46)
1761 fmt.Println("=== IR for string concat ===")
1762 fmt.Println(ir46)
1763
1764 llvmVerify("string concat", ir46)
1765 assert("string concat calls sliceAppend", strings.Contains(ir46, "@runtime.sliceAppend"))
1766
1767 irFree(h46)
1768
1769 // Test 47: cap on string (strings have len == cap)
1770 src47 := []byte(`package mypkg
1771
1772 func strCap(s string) int {
1773 return cap(s)
1774 }
1775 `)
1776 h47 := compileToIR(
1777 uintptr(unsafe.Pointer(&src47[0])), int32(len(src47)),
1778 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1779 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1780 )
1781 ir47 := getIR(h47)
1782 fmt.Println("=== IR for string cap ===")
1783 fmt.Println(ir47)
1784
1785 llvmVerify("string cap", ir47)
1786 assert("string cap has extractvalue", strings.Contains(ir47, "extractvalue"))
1787
1788 irFree(h47)
1789
1790 // Test 48: nested if/else with multiple returns
1791 src48 := []byte(`package mypkg
1792
1793 func clamp(x, lo, hi int) int {
1794 if x < lo {
1795 return lo
1796 } else if x > hi {
1797 return hi
1798 }
1799 return x
1800 }
1801 `)
1802 h48 := compileToIR(
1803 uintptr(unsafe.Pointer(&src48[0])), int32(len(src48)),
1804 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1805 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1806 )
1807 ir48 := getIR(h48)
1808 fmt.Println("=== IR for clamp ===")
1809 fmt.Println(ir48)
1810
1811 llvmVerify("clamp", ir48)
1812 assert("clamp has icmp slt", strings.Contains(ir48, "icmp slt"))
1813 assert("clamp has icmp sgt", strings.Contains(ir48, "icmp sgt"))
1814
1815 irFree(h48)
1816
1817 // Test 49: Closure (captures variable from outer scope)
1818 src49 := []byte(`package mypkg
1819
1820 func adder(x int32) func(int32) int32 {
1821 return func(y int32) int32 {
1822 return x + y
1823 }
1824 }
1825 `)
1826 h49 := compileToIR(
1827 uintptr(unsafe.Pointer(&src49[0])), int32(len(src49)),
1828 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1829 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1830 )
1831 ir49 := getIR(h49)
1832 fmt.Println("=== IR for closure ===")
1833 fmt.Println(ir49)
1834
1835 llvmVerify("closure", ir49)
1836 assert("closure has anon func", strings.Contains(ir49, "@mypkg.adder__anon"))
1837 assert("closure has runtime.alloc", strings.Contains(ir49, "@runtime.alloc"))
1838 assert("closure has insertvalue {ptr, ptr}", strings.Contains(ir49, "insertvalue {ptr, ptr}"))
1839 assert("closure has getelementptr for context", strings.Contains(ir49, "getelementptr"))
1840 assert("closure anon has context param", strings.Contains(ir49, "ptr %context"))
1841
1842 irFree(h49)
1843
1844 // Test 50: Closure with multiple captures
1845 src50 := []byte(`package mypkg
1846
1847 func makeCounter(start int32, step int32) func() int32 {
1848 val := start
1849 return func() int32 {
1850 result := val
1851 val = val + step
1852 return result
1853 }
1854 }
1855 `)
1856 h50 := compileToIR(
1857 uintptr(unsafe.Pointer(&src50[0])), int32(len(src50)),
1858 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1859 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1860 )
1861 ir50 := getIR(h50)
1862 fmt.Println("=== IR for multi-capture closure ===")
1863 fmt.Println(ir50)
1864
1865 llvmVerify("multi-capture closure", ir50)
1866 assert("multi-capture has anon func", strings.Contains(ir50, "@mypkg.makeCounter__anon"))
1867 assert("multi-capture has alloc", strings.Contains(ir50, "@runtime.alloc"))
1868
1869 irFree(h50)
1870
1871 // Test 51: Function value call (indirect call through {ptr, ptr})
1872 src51 := []byte(`package mypkg
1873
1874 func apply(f func(int32) int32, x int32) int32 {
1875 return f(x)
1876 }
1877
1878 func double(x int32) int32 {
1879 return x + x
1880 }
1881
1882 func test() int32 {
1883 return apply(double, 5)
1884 }
1885 `)
1886 h51 := compileToIR(
1887 uintptr(unsafe.Pointer(&src51[0])), int32(len(src51)),
1888 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1889 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1890 )
1891 ir51 := getIR(h51)
1892 fmt.Println("=== IR for func value call ===")
1893 fmt.Println(ir51)
1894
1895 llvmVerify("func value call", ir51)
1896 assert("func value call has extractvalue", strings.Contains(ir51, "extractvalue {ptr, ptr}"))
1897 assert("func value call passes context", strings.Contains(ir51, "ptr %ctx"))
1898
1899 irFree(h51)
1900
1901 // Test 52: Method with value receiver
1902 src52 := []byte(`package mypkg
1903
1904 type Point struct {
1905 X int32
1906 Y int32
1907 }
1908
1909 func (p Point) Sum() int32 {
1910 return p.X + p.Y
1911 }
1912
1913 func test() int32 {
1914 p := Point{X: 3, Y: 4}
1915 return p.Sum()
1916 }
1917 `)
1918 h52 := compileToIR(
1919 uintptr(unsafe.Pointer(&src52[0])), int32(len(src52)),
1920 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1921 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1922 )
1923 ir52 := getIR(h52)
1924 fmt.Println("=== IR for value receiver method ===")
1925 fmt.Println(ir52)
1926
1927 llvmVerify("value receiver method", ir52)
1928 assert("value recv method defined", strings.Contains(ir52, "@mypkg.Point.Sum"))
1929 assert("value recv method takes struct", strings.Contains(ir52, "define i32 @mypkg.Point.Sum("))
1930
1931 irFree(h52)
1932
1933 // Test 53: Method with pointer receiver
1934 src53 := []byte(`package mypkg
1935
1936 type Counter struct {
1937 Val int32
1938 }
1939
1940 func (c *Counter) Inc() {
1941 c.Val = c.Val + 1
1942 }
1943
1944 func (c *Counter) Get() int32 {
1945 return c.Val
1946 }
1947
1948 func test() int32 {
1949 c := Counter{Val: 10}
1950 c.Inc()
1951 c.Inc()
1952 return c.Get()
1953 }
1954 `)
1955 h53 := compileToIR(
1956 uintptr(unsafe.Pointer(&src53[0])), int32(len(src53)),
1957 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1958 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1959 )
1960 ir53 := getIR(h53)
1961 fmt.Println("=== IR for pointer receiver method ===")
1962 fmt.Println(ir53)
1963
1964 llvmVerify("pointer receiver method", ir53)
1965 assert("ptr recv Inc defined", strings.Contains(ir53, "@mypkg.Counter.Inc"))
1966 assert("ptr recv Get defined", strings.Contains(ir53, "@mypkg.Counter.Get"))
1967 assert("ptr recv method takes ptr", strings.Contains(ir53, "define") && strings.Contains(ir53, "@mypkg.Counter.Inc(ptr"))
1968
1969 irFree(h53)
1970
1971 // Test 54: Slice make literal {: syntax rewrite
1972 src54 := []byte(`package mypkg
1973
1974 func test() int32 {
1975 a := []int32{:5}
1976 b := []int32{:0:10}
1977 return int32(len(a)) + int32(len(b))
1978 }
1979 `)
1980 h54 := compileToIR(
1981 uintptr(unsafe.Pointer(&src54[0])), int32(len(src54)),
1982 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
1983 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
1984 )
1985 ir54 := getIR(h54)
1986 fmt.Println("=== IR for slice make literal ===")
1987 fmt.Println(ir54)
1988
1989 llvmVerify("slice make literal", ir54)
1990 assert("make literal has alloc", strings.Contains(ir54, "@runtime.alloc"))
1991 assert("make literal no parse error", !strings.Contains(ir54, "parse error"))
1992
1993 irFree(h54)
1994
1995 // Test 55: Interface dispatch
1996 src55 := []byte(`package mypkg
1997
1998 type Stringer interface {
1999 String() string
2000 }
2001
2002 type Name struct {
2003 First string
2004 Last string
2005 }
2006
2007 func (n Name) String() string {
2008 return n.First | " " | n.Last
2009 }
2010
2011 func greet(s Stringer) string {
2012 return "Hello, " | s.String()
2013 }
2014
2015 func test() int32 {
2016 n := Name{First: "John", Last: "Doe"}
2017 r := greet(n)
2018 if len(r) > 0 {
2019 return 42
2020 }
2021 return 0
2022 }
2023 `)
2024 h55 := compileToIR(
2025 uintptr(unsafe.Pointer(&src55[0])), int32(len(src55)),
2026 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2027 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2028 )
2029 ir55 := getIR(h55)
2030 fmt.Println("=== IR for interface dispatch ===")
2031 fmt.Println(ir55)
2032
2033 llvmVerify("interface dispatch", ir55)
2034 assert("iface has typeid", strings.Contains(ir55, "typeid"))
2035 assert("iface has makeinterface", strings.Contains(ir55, "insertvalue {ptr, ptr}"))
2036 assert("iface has Name.String method", strings.Contains(ir55, "@mypkg.Name.String"))
2037 assert("iface greet takes iface", strings.Contains(ir55, "define") && strings.Contains(ir55, "@mypkg.greet"))
2038 assert("iface no parse error", !strings.Contains(ir55, "parse error"))
2039
2040 irFree(h55)
2041
2042 // Test 56: Multi-impl interface dispatch
2043 src56 := []byte(`package mypkg
2044
2045 type Sizer interface {
2046 Size() int32
2047 }
2048
2049 type Box struct {
2050 W int32
2051 H int32
2052 }
2053
2054 type Circle struct {
2055 R int32
2056 }
2057
2058 func (b Box) Size() int32 {
2059 return b.W * b.H
2060 }
2061
2062 func (c Circle) Size() int32 {
2063 return c.R * c.R * 3
2064 }
2065
2066 func getSize(s Sizer) int32 {
2067 return s.Size()
2068 }
2069
2070 func test() int32 {
2071 b := Box{W: 3, H: 4}
2072 return getSize(b)
2073 }
2074 `)
2075 h56 := compileToIR(
2076 uintptr(unsafe.Pointer(&src56[0])), int32(len(src56)),
2077 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2078 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2079 )
2080 ir56 := getIR(h56)
2081 fmt.Println("=== IR for multi-impl interface ===")
2082 fmt.Println(ir56)
2083
2084 llvmVerify("multi-impl interface", ir56)
2085 assert("multi has Box.Size", strings.Contains(ir56, "@mypkg.Box.Size"))
2086 assert("multi has Circle.Size", strings.Contains(ir56, "@mypkg.Circle.Size"))
2087 assert("multi has typeid Box", strings.Contains(ir56, "typeid.Box"))
2088 assert("multi has typeid Circle", strings.Contains(ir56, "typeid.Circle"))
2089 assert("multi dispatch has icmp", strings.Contains(ir56, "icmp eq ptr"))
2090 assert("multi no parse error", !strings.Contains(ir56, "parse error"))
2091
2092 irFree(h56)
2093
2094 // Test 57: Type assertion (comma-ok)
2095 src57 := []byte(`package mypkg
2096
2097 type Animal interface {
2098 Sound() string
2099 }
2100
2101 type Dog struct {
2102 Name string
2103 }
2104
2105 func (d Dog) Sound() string {
2106 return "woof"
2107 }
2108
2109 func tryDog(a Animal) int32 {
2110 d, ok := a.(Dog)
2111 if ok {
2112 if len(d.Name) > 0 {
2113 return 1
2114 }
2115 return 2
2116 }
2117 return 0
2118 }
2119
2120 func test() int32 {
2121 d := Dog{Name: "Rex"}
2122 return tryDog(d)
2123 }
2124 `)
2125 h57 := compileToIR(
2126 uintptr(unsafe.Pointer(&src57[0])), int32(len(src57)),
2127 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2128 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2129 )
2130 ir57 := getIR(h57)
2131 fmt.Println("=== IR for type assertion ===")
2132 fmt.Println(ir57)
2133
2134 llvmVerify("type assertion", ir57)
2135 assert("ta has typeid compare", strings.Contains(ir57, "icmp eq ptr") && strings.Contains(ir57, "typeid.Dog"))
2136 assert("ta has extractvalue", strings.Contains(ir57, "extractvalue {ptr, ptr}"))
2137 assert("ta has insertvalue tuple", strings.Contains(ir57, "insertvalue"))
2138 assert("ta no parse error", !strings.Contains(ir57, "parse error"))
2139
2140 irFree(h57)
2141
2142 // Test 58: Type switch
2143 src58 := []byte(`package mypkg
2144
2145 type Shape interface {
2146 Area() int32
2147 }
2148
2149 type Rect struct {
2150 W int32
2151 H int32
2152 }
2153
2154 type Tri struct {
2155 B int32
2156 H int32
2157 }
2158
2159 func (r Rect) Area() int32 {
2160 return r.W * r.H
2161 }
2162
2163 func (t Tri) Area() int32 {
2164 return t.B * t.H / 2
2165 }
2166
2167 func describe(s Shape) int32 {
2168 switch v := s.(type) {
2169 case Rect:
2170 return v.W + v.H
2171 case Tri:
2172 return v.B + v.H
2173 }
2174 return 0
2175 }
2176
2177 func test() int32 {
2178 r := Rect{W: 3, H: 4}
2179 return describe(r)
2180 }
2181 `)
2182 h58 := compileToIR(
2183 uintptr(unsafe.Pointer(&src58[0])), int32(len(src58)),
2184 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2185 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2186 )
2187 ir58 := getIR(h58)
2188 fmt.Println("=== IR for type switch ===")
2189 fmt.Println(ir58)
2190
2191 llvmVerify("type switch", ir58)
2192 assert("ts has typeid Rect", strings.Contains(ir58, "typeid.Rect"))
2193 assert("ts has typeid Tri", strings.Contains(ir58, "typeid.Tri"))
2194 assert("ts has typeassert", strings.Contains(ir58, "icmp eq ptr"))
2195 assert("ts no parse error", !strings.Contains(ir58, "parse error"))
2196
2197 irFree(h58)
2198
2199 // Test 59: Pointer receiver interface dispatch
2200 src59 := []byte(`package mypkg
2201
2202 type Writer interface {
2203 Write(data int32) int32
2204 }
2205
2206 type Buffer struct {
2207 Count int32
2208 }
2209
2210 func (b *Buffer) Write(data int32) int32 {
2211 b.Count = b.Count + data
2212 return b.Count
2213 }
2214
2215 func writeAll(w Writer, v int32) int32 {
2216 return w.Write(v)
2217 }
2218
2219 func test() int32 {
2220 b := Buffer{Count: 0}
2221 return writeAll(&b, 10)
2222 }
2223 `)
2224 h59 := compileToIR(
2225 uintptr(unsafe.Pointer(&src59[0])), int32(len(src59)),
2226 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2227 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2228 )
2229 ir59 := getIR(h59)
2230 fmt.Println("=== IR for ptr recv interface ===")
2231 fmt.Println(ir59)
2232
2233 llvmVerify("ptr recv interface", ir59)
2234 assert("ptr iface has Buffer.Write", strings.Contains(ir59, "@mypkg.Buffer.Write"))
2235 assert("ptr iface dispatch passes ptr", strings.Contains(ir59, "call i32 @mypkg.Buffer.Write(ptr"))
2236 assert("ptr iface no parse error", !strings.Contains(ir59, "parse error"))
2237
2238 irFree(h59)
2239
2240 // Test 60: AndNot operator
2241 src60 := []byte(`package mypkg
2242
2243 func test() int32 {
2244 x := int32(0xFF)
2245 mask := int32(0x0F)
2246 return x &^ mask
2247 }
2248 `)
2249 h60 := compileToIR(
2250 uintptr(unsafe.Pointer(&src60[0])), int32(len(src60)),
2251 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2252 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2253 )
2254 ir60 := getIR(h60)
2255 fmt.Println("=== IR for andnot ===")
2256 fmt.Println(ir60)
2257
2258 llvmVerify("andnot", ir60)
2259 assert("andnot has xor", strings.Contains(ir60, "xor"))
2260 assert("andnot has and", strings.Contains(ir60, " and "))
2261 assert("andnot no parse error", !strings.Contains(ir60, "parse error"))
2262
2263 irFree(h60)
2264
2265 // Test 61: Nil comparison
2266 src61 := []byte(`package mypkg
2267
2268 func test() int32 {
2269 var p *int32
2270 if p == nil {
2271 return 1
2272 }
2273 return 0
2274 }
2275 `)
2276 h61 := compileToIR(
2277 uintptr(unsafe.Pointer(&src61[0])), int32(len(src61)),
2278 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2279 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2280 )
2281 ir61 := getIR(h61)
2282 fmt.Println("=== IR for nil compare ===")
2283 fmt.Println(ir61)
2284
2285 llvmVerify("nil compare", ir61)
2286 assert("nil has icmp eq ptr null", strings.Contains(ir61, "icmp eq ptr") && strings.Contains(ir61, "null"))
2287 assert("nil no parse error", !strings.Contains(ir61, "parse error"))
2288
2289 irFree(h61)
2290
2291 // Test 62: Key-only map range
2292 src62 := []byte(`package mypkg
2293
2294 func test() int32 {
2295 m := map[string]int32{"a": 1, "b": 2, "c": 3}
2296 count := int32(0)
2297 for k := range m {
2298 count = count + int32(len(k))
2299 }
2300 return count
2301 }
2302 `)
2303 h62 := compileToIR(
2304 uintptr(unsafe.Pointer(&src62[0])), int32(len(src62)),
2305 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2306 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2307 )
2308 ir62 := getIR(h62)
2309 fmt.Println("=== IR for key-only map range ===")
2310 fmt.Println(ir62)
2311
2312 llvmVerify("key-only map range", ir62)
2313 assert("key range has hashmapNext", strings.Contains(ir62, "@runtime.hashmapNext"))
2314 assert("key range no parse error", !strings.Contains(ir62, "parse error"))
2315
2316 irFree(h62)
2317
2318 // Test 63: Local closure capturing mutable outer var
2319 src63 := []byte(`package mypkg
2320
2321 func test() int32 {
2322 counter := int32(0)
2323 inc := func() int32 {
2324 counter = counter + 1
2325 return counter
2326 }
2327 inc()
2328 inc()
2329 return inc()
2330 }
2331 `)
2332 h63 := compileToIR(
2333 uintptr(unsafe.Pointer(&src63[0])), int32(len(src63)),
2334 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2335 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2336 )
2337 ir63 := getIR(h63)
2338 fmt.Println("=== IR for mutable closure ===")
2339 fmt.Println(ir63)
2340
2341 llvmVerify("mutable closure", ir63)
2342 assert("closure has makeclosure", strings.Contains(ir63, "insertvalue {ptr, ptr}") || strings.Contains(ir63, "makeclosure"))
2343 assert("closure no parse error", !strings.Contains(ir63, "parse error"))
2344
2345 irFree(h63)
2346
2347 // Test 64: Classic for loop
2348 src64 := []byte(`package mypkg
2349
2350 func test() int32 {
2351 sum := int32(0)
2352 for i := int32(0); i < 10; i++ {
2353 sum = sum + i
2354 }
2355 return sum
2356 }
2357 `)
2358 h64 := compileToIR(
2359 uintptr(unsafe.Pointer(&src64[0])), int32(len(src64)),
2360 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2361 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2362 )
2363 ir64 := getIR(h64)
2364 fmt.Println("=== IR for classic for loop ===")
2365 fmt.Println(ir64)
2366
2367 llvmVerify("classic for loop", ir64)
2368 assert("for has icmp slt", strings.Contains(ir64, "icmp slt"))
2369 assert("for has add", strings.Contains(ir64, "add"))
2370 assert("for no parse error", !strings.Contains(ir64, "parse error"))
2371
2372 irFree(h64)
2373
2374 // Test 65: Multi-return value
2375 src65 := []byte(`package mypkg
2376
2377 func divmod(a, b int32) (int32, int32) {
2378 return a / b, a - (a / b) * b
2379 }
2380
2381 func test() int32 {
2382 q, r := divmod(17, 5)
2383 return q + r
2384 }
2385 `)
2386 h65 := compileToIR(
2387 uintptr(unsafe.Pointer(&src65[0])), int32(len(src65)),
2388 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2389 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2390 )
2391 ir65 := getIR(h65)
2392 fmt.Println("=== IR for multi-return ===")
2393 fmt.Println(ir65)
2394
2395 llvmVerify("multi-return", ir65)
2396 assert("multi-ret has extractvalue", strings.Contains(ir65, "extractvalue"))
2397 assert("multi-ret has divmod", strings.Contains(ir65, "@mypkg.divmod"))
2398 assert("multi-ret no parse error", !strings.Contains(ir65, "parse error"))
2399
2400 irFree(h65)
2401
2402 // Test 66: new() builtin
2403 src66 := []byte(`package mypkg
2404
2405 func test() int32 {
2406 p := new(int32)
2407 *p = 42
2408 return *p
2409 }
2410 `)
2411 h66 := compileToIR(
2412 uintptr(unsafe.Pointer(&src66[0])), int32(len(src66)),
2413 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2414 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2415 )
2416 ir66 := getIR(h66)
2417 fmt.Println("=== IR for new builtin ===")
2418 fmt.Println(ir66)
2419
2420 llvmVerify("new builtin", ir66)
2421 assert("new has alloc or alloca", strings.Contains(ir66, "alloc") || strings.Contains(ir66, "alloca"))
2422 assert("new has store 42", strings.Contains(ir66, "store i32 42"))
2423 assert("new no parse error", !strings.Contains(ir66, "parse error"))
2424
2425 irFree(h66)
2426
2427 // Test 67: Logical AND / OR operators
2428 src67 := []byte(`package mypkg
2429
2430 func test() int32 {
2431 a := true
2432 b := false
2433 c := true
2434 r := int32(0)
2435 if a && c {
2436 r = r + 1
2437 }
2438 if a || b {
2439 r = r + 10
2440 }
2441 if b && c {
2442 r = r + 100
2443 }
2444 if b || c {
2445 r = r + 1000
2446 }
2447 return r
2448 }
2449 `)
2450 h67 := compileToIR(
2451 uintptr(unsafe.Pointer(&src67[0])), int32(len(src67)),
2452 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2453 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2454 )
2455 ir67 := getIR(h67)
2456 fmt.Println("=== IR for logical AND/OR ===")
2457 fmt.Println(ir67)
2458
2459 llvmVerify("logical AND/OR", ir67)
2460 assert("land has short-circuit branch", strings.Contains(ir67, "phi i1 [false,") || strings.Contains(ir67, "and i1"))
2461 assert("lor has short-circuit branch", strings.Contains(ir67, "phi i1 [true,") || strings.Contains(ir67, "or i1"))
2462 assert("land/lor no parse error", !strings.Contains(ir67, "parse error"))
2463
2464 irFree(h67)
2465
2466 // Test 68: Multi-value switch case
2467 src68 := []byte(`package mypkg
2468
2469 func test() int32 {
2470 x := int32(3)
2471 r := int32(0)
2472 switch x {
2473 case 1, 2:
2474 r = 10
2475 case 3, 4:
2476 r = 20
2477 case 5:
2478 r = 30
2479 }
2480 return r
2481 }
2482 `)
2483 h68 := compileToIR(
2484 uintptr(unsafe.Pointer(&src68[0])), int32(len(src68)),
2485 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2486 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2487 )
2488 ir68 := getIR(h68)
2489 fmt.Println("=== IR for multi-value switch ===")
2490 fmt.Println(ir68)
2491
2492 llvmVerify("multi-value switch", ir68)
2493 assert("multi-case has icmp", strings.Contains(ir68, "icmp eq"))
2494 assert("multi-case no parse error", !strings.Contains(ir68, "parse error"))
2495
2496 irFree(h68)
2497
2498 // Test 69: Variadic append
2499 src69 := []byte(`package mypkg
2500
2501 func test() int32 {
2502 s := make([]int32, 0)
2503 s = append(s, 10, 20, 30)
2504 return s[0] + s[1] + s[2]
2505 }
2506 `)
2507 h69 := compileToIR(
2508 uintptr(unsafe.Pointer(&src69[0])), int32(len(src69)),
2509 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2510 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2511 )
2512 ir69 := getIR(h69)
2513 fmt.Println("=== IR for variadic append ===")
2514 fmt.Println(ir69)
2515
2516 llvmVerify("variadic append", ir69)
2517 assert("variadic append has sliceAppend", strings.Contains(ir69, "runtime.sliceAppend"))
2518 assert("variadic append no parse error", !strings.Contains(ir69, "parse error"))
2519
2520 irFree(h69)
2521
2522 // Test 70: Iota constants
2523 src70 := []byte(`package mypkg
2524
2525 const (
2526 A = iota
2527 B
2528 C
2529 )
2530
2531 const (
2532 X = 1 << iota
2533 Y
2534 Z
2535 )
2536
2537 func test() int32 {
2538 return int32(A + B + C + X + Y + Z)
2539 }
2540 `)
2541 h70 := compileToIR(
2542 uintptr(unsafe.Pointer(&src70[0])), int32(len(src70)),
2543 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2544 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2545 )
2546 ir70 := getIR(h70)
2547 fmt.Println("=== IR for iota constants ===")
2548 fmt.Println(ir70)
2549
2550 llvmVerify("iota constants", ir70)
2551 assert("iota no parse error", !strings.Contains(ir70, "parse error"))
2552
2553 irFree(h70)
2554
2555 // Test 71: Typed iota const + switch dispatch
2556 src71 := []byte(`package mypkg
2557
2558 type Color int32
2559
2560 const (
2561 Red Color = iota
2562 Green
2563 Blue
2564 )
2565
2566 func describe(c Color) int32 {
2567 switch c {
2568 case Red:
2569 return 1
2570 case Green:
2571 return 2
2572 case Blue:
2573 return 3
2574 }
2575 return 0
2576 }
2577
2578 func test() int32 {
2579 return describe(Red) + describe(Green) + describe(Blue)
2580 }
2581 `)
2582 h71 := compileToIR(
2583 uintptr(unsafe.Pointer(&src71[0])), int32(len(src71)),
2584 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2585 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2586 )
2587 ir71 := getIR(h71)
2588 fmt.Println("=== IR for typed iota switch ===")
2589 fmt.Println(ir71)
2590
2591 llvmVerify("typed iota switch", ir71)
2592 assert("typed iota has icmp", strings.Contains(ir71, "icmp eq"))
2593 assert("typed iota no parse error", !strings.Contains(ir71, "parse error"))
2594
2595 irFree(h71)
2596
2597 // Test 72: String switch
2598 src72 := []byte(`package mypkg
2599
2600 func classify(s string) int32 {
2601 switch s {
2602 case "hello":
2603 return 1
2604 case "world":
2605 return 2
2606 }
2607 return 0
2608 }
2609
2610 func test() int32 {
2611 return classify("hello") + classify("world")
2612 }
2613 `)
2614 h72 := compileToIR(
2615 uintptr(unsafe.Pointer(&src72[0])), int32(len(src72)),
2616 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2617 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2618 )
2619 ir72 := getIR(h72)
2620 fmt.Println("=== IR for string switch ===")
2621 fmt.Println(ir72)
2622
2623 llvmVerify("string switch", ir72)
2624 assert("string switch no parse error", !strings.Contains(ir72, "parse error"))
2625
2626 irFree(h72)
2627
2628 // Test 73: Nested field access (a.b.c pattern)
2629 src73 := []byte(`package mypkg
2630
2631 type Inner struct {
2632 val int32
2633 }
2634 type Outer struct {
2635 inner Inner
2636 extra int32
2637 }
2638
2639 func test() int32 {
2640 o := Outer{inner: Inner{val: 42}, extra: 8}
2641 return o.inner.val + o.extra
2642 }
2643 `)
2644 h73 := compileToIR(
2645 uintptr(unsafe.Pointer(&src73[0])), int32(len(src73)),
2646 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2647 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2648 )
2649 ir73 := getIR(h73)
2650 fmt.Println("=== IR for nested field access ===")
2651 fmt.Println(ir73)
2652
2653 llvmVerify("nested field access", ir73)
2654 assert("nested field has gep", strings.Contains(ir73, "getelementptr"))
2655 assert("nested field no parse error", !strings.Contains(ir73, "parse error"))
2656
2657 irFree(h73)
2658
2659 // Test 74: Method on pointer receiver with field mutation
2660 src74 := []byte(`package mypkg
2661
2662 type Counter struct {
2663 n int32
2664 }
2665
2666 func (c *Counter) inc() {
2667 c.n = c.n + 1
2668 }
2669
2670 func (c *Counter) get() int32 {
2671 return c.n
2672 }
2673
2674 func test() int32 {
2675 c := Counter{n: 0}
2676 c.inc()
2677 c.inc()
2678 c.inc()
2679 return c.get()
2680 }
2681 `)
2682 h74 := compileToIR(
2683 uintptr(unsafe.Pointer(&src74[0])), int32(len(src74)),
2684 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2685 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2686 )
2687 ir74 := getIR(h74)
2688 fmt.Println("=== IR for method mutation ===")
2689 fmt.Println(ir74)
2690
2691 llvmVerify("method mutation", ir74)
2692 assert("method mutation has Counter.inc", strings.Contains(ir74, "Counter.inc"))
2693 assert("method mutation no parse error", !strings.Contains(ir74, "parse error"))
2694
2695 irFree(h74)
2696
2697 // Test 75: Closure capturing method receiver (p := func() { e.field++ })
2698 src75 := []byte(`package mypkg
2699
2700 type Builder struct {
2701 count int32
2702 }
2703
2704 func (b *Builder) build() int32 {
2705 inc := func() {
2706 b.count = b.count + 1
2707 }
2708 inc()
2709 inc()
2710 inc()
2711 return b.count
2712 }
2713
2714 func test() int32 {
2715 b := Builder{count: 0}
2716 return b.build()
2717 }
2718 `)
2719 h75 := compileToIR(
2720 uintptr(unsafe.Pointer(&src75[0])), int32(len(src75)),
2721 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2722 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2723 )
2724 ir75 := getIR(h75)
2725 fmt.Println("=== IR for closure with receiver ===")
2726 fmt.Println(ir75)
2727
2728 llvmVerify("closure with receiver", ir75)
2729 assert("closure recv no parse error", !strings.Contains(ir75, "parse error"))
2730
2731 irFree(h75)
2732
2733 // Test 76: Slice of structs with append and field access
2734 src76 := []byte(`package mypkg
2735
2736 type Item struct {
2737 id int32
2738 val int32
2739 }
2740
2741 func test() int32 {
2742 items := make([]Item, 0)
2743 items = append(items, Item{id: 1, val: 10})
2744 items = append(items, Item{id: 2, val: 20})
2745 return items[0].val + items[1].val
2746 }
2747 `)
2748 h76 := compileToIR(
2749 uintptr(unsafe.Pointer(&src76[0])), int32(len(src76)),
2750 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2751 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2752 )
2753 ir76 := getIR(h76)
2754 fmt.Println("=== IR for slice of structs ===")
2755 fmt.Println(ir76)
2756
2757 llvmVerify("slice of structs", ir76)
2758 assert("slice structs has sliceAppend", strings.Contains(ir76, "sliceAppend"))
2759 assert("slice structs no parse error", !strings.Contains(ir76, "parse error"))
2760
2761 irFree(h76)
2762
2763 // Test 77: Global variable read/write
2764 src77 := []byte(`package mypkg
2765
2766 var counter int32
2767
2768 func inc() {
2769 counter = counter + 1
2770 }
2771
2772 func test() int32 {
2773 inc()
2774 inc()
2775 inc()
2776 return counter
2777 }
2778 `)
2779 h77 := compileToIR(
2780 uintptr(unsafe.Pointer(&src77[0])), int32(len(src77)),
2781 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2782 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2783 )
2784 ir77 := getIR(h77)
2785 fmt.Println("=== IR for global variable ===")
2786 fmt.Println(ir77)
2787
2788 llvmVerify("global variable", ir77)
2789 assert("global has @mypkg.counter", strings.Contains(ir77, "@mypkg.counter"))
2790 assert("global no parse error", !strings.Contains(ir77, "parse error"))
2791
2792 irFree(h77)
2793
2794 // Test 78: String indexing via parameter (string = []byte)
2795 src78 := []byte(`package mypkg
2796
2797 func getByte(s string, i int32) int32 {
2798 return int32(s[i])
2799 }
2800
2801 func test() int32 {
2802 return getByte("hello", 1)
2803 }
2804 `)
2805 h78 := compileToIR(
2806 uintptr(unsafe.Pointer(&src78[0])), int32(len(src78)),
2807 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2808 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2809 )
2810 ir78 := getIR(h78)
2811 fmt.Println("=== IR for string indexing ===")
2812 fmt.Println(ir78)
2813
2814 llvmVerify("string indexing", ir78)
2815 assert("string idx no parse error", !strings.Contains(ir78, "parse error"))
2816
2817 irFree(h78)
2818
2819 // Test 79: Byte slice from string (type conversion)
2820 src79 := []byte(`package mypkg
2821
2822 func test() int32 {
2823 s := "abc"
2824 b := []byte(s)
2825 return int32(b[0]) + int32(b[2])
2826 }
2827 `)
2828 h79 := compileToIR(
2829 uintptr(unsafe.Pointer(&src79[0])), int32(len(src79)),
2830 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2831 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2832 )
2833 ir79 := getIR(h79)
2834 fmt.Println("=== IR for byte slice from string ===")
2835 fmt.Println(ir79)
2836
2837 llvmVerify("byte slice from string", ir79)
2838 assert("byte slice no parse error", !strings.Contains(ir79, "parse error"))
2839
2840 irFree(h79)
2841
2842 // Test 80: Multiple return with named types
2843 src80 := []byte(`package mypkg
2844
2845 type Result struct {
2846 ok bool
2847 val int32
2848 }
2849
2850 func check(x int32) (Result, bool) {
2851 if x > 0 {
2852 return Result{ok: true, val: x}, true
2853 }
2854 return Result{ok: false, val: 0}, false
2855 }
2856
2857 func test() int32 {
2858 r, ok := check(42)
2859 if ok && r.ok {
2860 return r.val
2861 }
2862 return 0
2863 }
2864 `)
2865 h80 := compileToIR(
2866 uintptr(unsafe.Pointer(&src80[0])), int32(len(src80)),
2867 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2868 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2869 )
2870 ir80 := getIR(h80)
2871 fmt.Println("=== IR for struct return + logical AND ===")
2872 fmt.Println(ir80)
2873
2874 llvmVerify("struct return + logical AND", ir80)
2875 assert("struct ret no parse error", !strings.Contains(ir80, "parse error"))
2876
2877 irFree(h80)
2878
2879 // Test 81: Map with string keys and struct values
2880 src81 := []byte(`package mypkg
2881
2882 type Entry struct {
2883 name string
2884 val int32
2885 }
2886
2887 func test() int32 {
2888 m := make(map[string]Entry)
2889 m["x"] = Entry{name: "ex", val: 10}
2890 m["y"] = Entry{name: "why", val: 20}
2891 e := m["x"]
2892 return e.val
2893 }
2894 `)
2895 h81 := compileToIR(
2896 uintptr(unsafe.Pointer(&src81[0])), int32(len(src81)),
2897 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2898 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2899 )
2900 ir81 := getIR(h81)
2901 fmt.Println("=== IR for map struct values ===")
2902 fmt.Println(ir81)
2903
2904 llvmVerify("map struct values", ir81)
2905 assert("map struct no parse error", !strings.Contains(ir81, "parse error"))
2906
2907 irFree(h81)
2908
2909 // Test 82: Interface with two concrete method impls
2910 src82 := []byte(`package mypkg
2911
2912 type Expr interface {
2913 compute() int32
2914 }
2915
2916 type Lit struct {
2917 val int32
2918 }
2919
2920 func (l Lit) compute() int32 {
2921 return l.val
2922 }
2923
2924 type Binop struct {
2925 x int32
2926 y int32
2927 }
2928
2929 func (a Binop) compute() int32 {
2930 return a.x + a.y
2931 }
2932
2933 func run(e Expr) int32 {
2934 return e.compute()
2935 }
2936
2937 func test() int32 {
2938 a := Lit{val: 10}
2939 b := Binop{x: 20, y: 12}
2940 return run(a) + run(b)
2941 }
2942 `)
2943 h82 := compileToIR(
2944 uintptr(unsafe.Pointer(&src82[0])), int32(len(src82)),
2945 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2946 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2947 )
2948 ir82 := getIR(h82)
2949 fmt.Println("=== IR for interface method dispatch ===")
2950 fmt.Println(ir82)
2951
2952 llvmVerify("interface method dispatch", ir82)
2953 assert("iface dispatch has typeid", strings.Contains(ir82, "typeid"))
2954 assert("iface dispatch no parse error", !strings.Contains(ir82, "parse error"))
2955
2956 irFree(h82)
2957
2958 // Test 83: For loop with break
2959 src83 := []byte(`package mypkg
2960
2961 func test() int32 {
2962 sum := int32(0)
2963 for i := int32(0); i < 100; i = i + 1 {
2964 if i == 10 {
2965 break
2966 }
2967 sum = sum + i
2968 }
2969 return sum
2970 }
2971 `)
2972 h83 := compileToIR(
2973 uintptr(unsafe.Pointer(&src83[0])), int32(len(src83)),
2974 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
2975 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
2976 )
2977 ir83 := getIR(h83)
2978 fmt.Println("=== IR for break in loop ===")
2979 fmt.Println(ir83)
2980
2981 llvmVerify("break in loop", ir83)
2982 assert("break no parse error", !strings.Contains(ir83, "parse error"))
2983
2984 irFree(h83)
2985
2986 // Test 84: Continue in loop
2987 src84 := []byte(`package mypkg
2988
2989 func test() int32 {
2990 sum := int32(0)
2991 for i := int32(0); i < 10; i = i + 1 {
2992 if i == 5 {
2993 continue
2994 }
2995 sum = sum + i
2996 }
2997 return sum
2998 }
2999 `)
3000 h84 := compileToIR(
3001 uintptr(unsafe.Pointer(&src84[0])), int32(len(src84)),
3002 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3003 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3004 )
3005 ir84 := getIR(h84)
3006 fmt.Println("=== IR for continue in loop ===")
3007 fmt.Println(ir84)
3008
3009 llvmVerify("continue in loop", ir84)
3010 assert("continue no parse error", !strings.Contains(ir84, "parse error"))
3011
3012 irFree(h84)
3013
3014 // Test 85: String slicing
3015 src85 := []byte(`package mypkg
3016
3017 func test() int32 {
3018 s := "hello world"
3019 prefix := s[:5]
3020 return int32(len(prefix))
3021 }
3022 `)
3023 h85 := compileToIR(
3024 uintptr(unsafe.Pointer(&src85[0])), int32(len(src85)),
3025 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3026 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3027 )
3028 ir85 := getIR(h85)
3029 fmt.Println("=== IR for string slicing ===")
3030 fmt.Println(ir85)
3031
3032 llvmVerify("string slicing", ir85)
3033 assert("string slice no parse error", !strings.Contains(ir85, "parse error"))
3034
3035 irFree(h85)
3036
3037 // Test 86: Const in expression
3038 src86 := []byte(`package mypkg
3039
3040 const maxSize = 100
3041
3042 func test() int32 {
3043 x := int32(maxSize)
3044 return x + 1
3045 }
3046 `)
3047 h86 := compileToIR(
3048 uintptr(unsafe.Pointer(&src86[0])), int32(len(src86)),
3049 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3050 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3051 )
3052 ir86 := getIR(h86)
3053 fmt.Println("=== IR for const expression ===")
3054 fmt.Println(ir86)
3055
3056 llvmVerify("const expression", ir86)
3057 assert("const expr no parse error", !strings.Contains(ir86, "parse error"))
3058
3059 irFree(h86)
3060
3061 // Test 87: Assign to map value field (m[k] = v pattern)
3062 src87 := []byte(`package mypkg
3063
3064 func test() int32 {
3065 m := make(map[int32]int32)
3066 m[1] = 10
3067 m[2] = 20
3068 v1, ok1 := m[1]
3069 v2, ok2 := m[2]
3070 if ok1 && ok2 {
3071 return v1 + v2
3072 }
3073 return 0
3074 }
3075 `)
3076 h87 := compileToIR(
3077 uintptr(unsafe.Pointer(&src87[0])), int32(len(src87)),
3078 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3079 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3080 )
3081 ir87 := getIR(h87)
3082 fmt.Println("=== IR for map comma-ok ===")
3083 fmt.Println(ir87)
3084
3085 llvmVerify("map comma-ok", ir87)
3086 assert("map comma ok no parse error", !strings.Contains(ir87, "parse error"))
3087
3088 irFree(h87)
3089
3090 // Test 88: Nested if-else chains
3091 src88 := []byte(`package mypkg
3092
3093 func classify(x int32) int32 {
3094 if x < 0 {
3095 return -1
3096 } else if x == 0 {
3097 return 0
3098 } else if x < 10 {
3099 return 1
3100 } else {
3101 return 2
3102 }
3103 }
3104
3105 func test() int32 {
3106 return classify(-5) + classify(0) + classify(5) + classify(50)
3107 }
3108 `)
3109 h88 := compileToIR(
3110 uintptr(unsafe.Pointer(&src88[0])), int32(len(src88)),
3111 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3112 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3113 )
3114 ir88 := getIR(h88)
3115 fmt.Println("=== IR for if-else chain ===")
3116 fmt.Println(ir88)
3117
3118 llvmVerify("if-else chain", ir88)
3119 assert("if-else no parse error", !strings.Contains(ir88, "parse error"))
3120
3121 irFree(h88)
3122
3123 // Test 89: String concatenation via | operator (Moxie-specific)
3124 src89 := []byte(`package mypkg
3125
3126 func test() int32 {
3127 a := "hello"
3128 b := " world"
3129 c := a | b
3130 return int32(len(c))
3131 }
3132 `)
3133 h89 := compileToIR(
3134 uintptr(unsafe.Pointer(&src89[0])), int32(len(src89)),
3135 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3136 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3137 )
3138 ir89 := getIR(h89)
3139 fmt.Println("=== IR for string | concat ===")
3140 fmt.Println(ir89)
3141
3142 llvmVerify("string | concat", ir89)
3143 assert("pipe concat has sliceAppend", strings.Contains(ir89, "sliceAppend"))
3144 assert("pipe concat no parse error", !strings.Contains(ir89, "parse error"))
3145
3146 irFree(h89)
3147
3148 // Test 90: Switch with default case
3149 src90 := []byte(`package mypkg
3150
3151 func test() int32 {
3152 x := int32(99)
3153 switch x {
3154 case 1:
3155 return 10
3156 case 2:
3157 return 20
3158 default:
3159 return 42
3160 }
3161 }
3162 `)
3163 h90 := compileToIR(
3164 uintptr(unsafe.Pointer(&src90[0])), int32(len(src90)),
3165 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3166 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3167 )
3168 ir90 := getIR(h90)
3169 fmt.Println("=== IR for switch default ===")
3170 fmt.Println(ir90)
3171
3172 llvmVerify("switch default", ir90)
3173 assert("switch default no parse error", !strings.Contains(ir90, "parse error"))
3174
3175 irFree(h90)
3176
3177 // Test 91: Boolean negation
3178 src91 := []byte(`package mypkg
3179
3180 func test() int32 {
3181 a := true
3182 b := false
3183 r := int32(0)
3184 if !a {
3185 r = r + 1
3186 }
3187 if !b {
3188 r = r + 10
3189 }
3190 return r
3191 }
3192 `)
3193 h91 := compileToIR(
3194 uintptr(unsafe.Pointer(&src91[0])), int32(len(src91)),
3195 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3196 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3197 )
3198 ir91 := getIR(h91)
3199 fmt.Println("=== IR for boolean negation ===")
3200 fmt.Println(ir91)
3201
3202 llvmVerify("boolean negation", ir91)
3203 assert("bool neg has xor", strings.Contains(ir91, "xor"))
3204 assert("bool neg no parse error", !strings.Contains(ir91, "parse error"))
3205
3206 irFree(h91)
3207
3208 // Test 92: Tuple swap (slice element swap)
3209 src92 := []byte(`package mypkg
3210
3211 func test() int32 {
3212 s := make([]int32, 3)
3213 s[0] = 1
3214 s[1] = 2
3215 s[2] = 3
3216 s[0], s[1] = s[1], s[0]
3217 return s[0] + s[1]*10 + s[2]*100
3218 }
3219 `)
3220 h92 := compileToIR(
3221 uintptr(unsafe.Pointer(&src92[0])), int32(len(src92)),
3222 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3223 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3224 )
3225 ir92 := getIR(h92)
3226 fmt.Println("=== IR for tuple swap ===")
3227 fmt.Println(ir92)
3228
3229 llvmVerify("tuple swap", ir92)
3230 assert("tuple swap no parse error", !strings.Contains(ir92, "parse error"))
3231
3232 irFree(h92)
3233
3234 // Test 93: String less-than comparison
3235 src93 := []byte(`package mypkg
3236
3237 func test() int32 {
3238 a := "apple"
3239 b := "banana"
3240 if a < b {
3241 return 1
3242 }
3243 return 0
3244 }
3245 `)
3246 h93 := compileToIR(
3247 uintptr(unsafe.Pointer(&src93[0])), int32(len(src93)),
3248 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3249 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3250 )
3251 ir93 := getIR(h93)
3252 fmt.Println("=== IR for string less-than ===")
3253 fmt.Println(ir93)
3254
3255 llvmVerify("string less-than", ir93)
3256 assert("str lt has stringLess", strings.Contains(ir93, "stringLess"))
3257 assert("str lt no parse error", !strings.Contains(ir93, "parse error"))
3258
3259 irFree(h93)
3260
3261 // Test 94: Integer negation
3262 src94 := []byte(`package mypkg
3263
3264 func abs(x int32) int32 {
3265 if x < 0 {
3266 return -x
3267 }
3268 return x
3269 }
3270
3271 func test() int32 {
3272 return abs(-5) + abs(3)
3273 }
3274 `)
3275 h94 := compileToIR(
3276 uintptr(unsafe.Pointer(&src94[0])), int32(len(src94)),
3277 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3278 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3279 )
3280 ir94 := getIR(h94)
3281 fmt.Println("=== IR for integer negation ===")
3282 fmt.Println(ir94)
3283
3284 llvmVerify("integer negation", ir94)
3285 assert("int neg has sub i32 0", strings.Contains(ir94, "sub i32 0"))
3286 assert("int neg no parse error", !strings.Contains(ir94, "parse error"))
3287
3288 irFree(h94)
3289
3290 // Test 95: Int64 arithmetic
3291 src95 := []byte(`package mypkg
3292
3293 func test() int32 {
3294 a := int64(1000000)
3295 b := int64(2000000)
3296 c := a + b
3297 return int32(c / int64(1000))
3298 }
3299 `)
3300 h95 := compileToIR(
3301 uintptr(unsafe.Pointer(&src95[0])), int32(len(src95)),
3302 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3303 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3304 )
3305 ir95 := getIR(h95)
3306 fmt.Println("=== IR for int64 arithmetic ===")
3307 fmt.Println(ir95)
3308
3309 llvmVerify("int64 arithmetic", ir95)
3310 assert("int64 has i64", strings.Contains(ir95, "i64"))
3311 assert("int64 no parse error", !strings.Contains(ir95, "parse error"))
3312
3313 irFree(h95)
3314
3315 // Test 96: Global variable with initializer
3316 src96 := []byte(`package mypkg
3317
3318 var offset int32 = 100
3319
3320 func test() int32 {
3321 return offset + 5
3322 }
3323 `)
3324 h96 := compileToIR(
3325 uintptr(unsafe.Pointer(&src96[0])), int32(len(src96)),
3326 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3327 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3328 )
3329 ir96 := getIR(h96)
3330 fmt.Println("=== IR for global var initializer ===")
3331 fmt.Println(ir96)
3332
3333 llvmVerify("global var initializer", ir96)
3334 assert("global init has @mypkg.offset", strings.Contains(ir96, "@mypkg.offset"))
3335 assert("global init no parse error", !strings.Contains(ir96, "parse error"))
3336
3337 irFree(h96)
3338
3339 // Test 97: Blank identifier in multi-return
3340 src97 := []byte(`package mypkg
3341
3342 func pair() (int32, int32) {
3343 return 10, 20
3344 }
3345
3346 func test() int32 {
3347 _, b := pair()
3348 return b
3349 }
3350 `)
3351 h97 := compileToIR(
3352 uintptr(unsafe.Pointer(&src97[0])), int32(len(src97)),
3353 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3354 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3355 )
3356 ir97 := getIR(h97)
3357 fmt.Println("=== IR for blank identifier ===")
3358 fmt.Println(ir97)
3359
3360 llvmVerify("blank identifier", ir97)
3361 assert("blank id no parse error", !strings.Contains(ir97, "parse error"))
3362
3363 irFree(h97)
3364
3365 // Test 98: For range with index only (i := range slice)
3366 src98 := []byte(`package mypkg
3367
3368 func test() int32 {
3369 s := []int32{10, 20, 30, 40}
3370 sum := int32(0)
3371 for i := range s {
3372 sum = sum + int32(i)
3373 }
3374 return sum
3375 }
3376 `)
3377 h98 := compileToIR(
3378 uintptr(unsafe.Pointer(&src98[0])), int32(len(src98)),
3379 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3380 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3381 )
3382 ir98 := getIR(h98)
3383 fmt.Println("=== IR for range index only ===")
3384 fmt.Println(ir98)
3385
3386 llvmVerify("range index only", ir98)
3387 assert("range idx no parse error", !strings.Contains(ir98, "parse error"))
3388
3389 irFree(h98)
3390
3391 // Test 99: Append with variadic expansion (append(buf, s...))
3392 src99 := []byte(`package mypkg
3393
3394 func test() int32 {
3395 buf := make([]byte, 0)
3396 s := "hello"
3397 buf = append(buf, s...)
3398 return int32(len(buf))
3399 }
3400 `)
3401 h99 := compileToIR(
3402 uintptr(unsafe.Pointer(&src99[0])), int32(len(src99)),
3403 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3404 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3405 )
3406 ir99 := getIR(h99)
3407 fmt.Println("=== IR for append with dots ===")
3408 fmt.Println(ir99)
3409
3410 llvmVerify("append with dots", ir99)
3411 assert("append dots has sliceAppend", strings.Contains(ir99, "sliceAppend"))
3412 assert("append dots no parse error", !strings.Contains(ir99, "parse error"))
3413
3414 irFree(h99)
3415
3416 // Test 100: Assign to struct field through pointer
3417 src100 := []byte(`package mypkg
3418
3419 type Node struct {
3420 val int32
3421 next *Node
3422 }
3423
3424 func test() int32 {
3425 a := Node{val: 10}
3426 b := Node{val: 20, next: &a}
3427 return b.val + b.next.val
3428 }
3429 `)
3430 h100 := compileToIR(
3431 uintptr(unsafe.Pointer(&src100[0])), int32(len(src100)),
3432 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3433 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3434 )
3435 ir100 := getIR(h100)
3436 fmt.Println("=== IR for struct pointer chain ===")
3437 fmt.Println(ir100)
3438
3439 llvmVerify("struct pointer chain", ir100)
3440 assert("ptr chain no parse error", !strings.Contains(ir100, "parse error"))
3441
3442 irFree(h100)
3443
3444 // Test 101: Address-of operator
3445 src101 := []byte(`package mypkg
3446
3447 func setVal(p *int32, v int32) {
3448 *p = v
3449 }
3450
3451 func test() int32 {
3452 x := int32(0)
3453 setVal(&x, 42)
3454 return x
3455 }
3456 `)
3457 h101 := compileToIR(
3458 uintptr(unsafe.Pointer(&src101[0])), int32(len(src101)),
3459 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3460 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3461 )
3462 ir101 := getIR(h101)
3463 fmt.Println("=== IR for address-of ===")
3464 fmt.Println(ir101)
3465
3466 llvmVerify("address-of", ir101)
3467 assert("addr-of no parse error", !strings.Contains(ir101, "parse error"))
3468
3469 irFree(h101)
3470
3471 // Test 102: Map delete
3472 src102 := []byte(`package mypkg
3473
3474 func test() int32 {
3475 m := map[string]int32{"a": 1, "b": 2, "c": 3}
3476 delete(m, "b")
3477 _, ok := m["b"]
3478 if ok {
3479 return 0
3480 }
3481 return 1
3482 }
3483 `)
3484 h102 := compileToIR(
3485 uintptr(unsafe.Pointer(&src102[0])), int32(len(src102)),
3486 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3487 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3488 )
3489 ir102 := getIR(h102)
3490 fmt.Println("=== IR for map delete ===")
3491 fmt.Println(ir102)
3492
3493 llvmVerify("map delete", ir102)
3494 assert("map del has hashmapDelete", strings.Contains(ir102, "hashmapDelete") || strings.Contains(ir102, "hashmapBinaryDelete"))
3495 assert("map del no parse error", !strings.Contains(ir102, "parse error"))
3496
3497 irFree(h102)
3498
3499 // Test 103: String constant
3500 src103 := []byte(`package mypkg
3501
3502 const greeting = "hello"
3503
3504 func test() int32 {
3505 s := greeting
3506 return int32(len(s))
3507 }
3508 `)
3509 h103 := compileToIR(
3510 uintptr(unsafe.Pointer(&src103[0])), int32(len(src103)),
3511 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3512 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3513 )
3514 ir103 := getIR(h103)
3515 fmt.Println("=== IR for string const ===")
3516 fmt.Println(ir103)
3517
3518 llvmVerify("string const", ir103)
3519 assert("str const no parse error", !strings.Contains(ir103, "parse error"))
3520
3521 irFree(h103)
3522
3523 // Test 104: Nested method calls (a.b().c())
3524 src104 := []byte(`package mypkg
3525
3526 type Builder struct {
3527 buf []byte
3528 }
3529
3530 func (b *Builder) write(s string) *Builder {
3531 b.buf = append(b.buf, s...)
3532 return b
3533 }
3534
3535 func (b *Builder) length() int32 {
3536 return int32(len(b.buf))
3537 }
3538
3539 func test() int32 {
3540 b := Builder{buf: make([]byte, 0)}
3541 b.write("hello")
3542 b.write(" world")
3543 return b.length()
3544 }
3545 `)
3546 h104 := compileToIR(
3547 uintptr(unsafe.Pointer(&src104[0])), int32(len(src104)),
3548 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3549 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3550 )
3551 ir104 := getIR(h104)
3552 fmt.Println("=== IR for method chaining ===")
3553 fmt.Println(ir104)
3554
3555 llvmVerify("method chaining", ir104)
3556 assert("method chain has Builder.write", strings.Contains(ir104, "Builder.write"))
3557 assert("method chain no parse error", !strings.Contains(ir104, "parse error"))
3558
3559 irFree(h104)
3560
3561 // Test 105: Unary not on comparison
3562 src105 := []byte(`package mypkg
3563
3564 func test() int32 {
3565 x := int32(5)
3566 if !(x > 10) {
3567 return 1
3568 }
3569 return 0
3570 }
3571 `)
3572 h105 := compileToIR(
3573 uintptr(unsafe.Pointer(&src105[0])), int32(len(src105)),
3574 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3575 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3576 )
3577 ir105 := getIR(h105)
3578 fmt.Println("=== IR for not-comparison ===")
3579 fmt.Println(ir105)
3580
3581 llvmVerify("not-comparison", ir105)
3582 assert("not cmp no parse error", !strings.Contains(ir105, "parse error"))
3583
3584 irFree(h105)
3585
3586 // Test 106: Self-compilation pattern - irItoa-like function
3587 src106 := []byte(`package mypkg
3588
3589 func itoa(n int) string {
3590 if n == 0 {
3591 return "0"
3592 }
3593 neg := false
3594 if n < 0 {
3595 neg = true
3596 n = -n
3597 }
3598 buf := make([]byte, 0)
3599 for n > 0 {
3600 buf = append(buf, byte(n%10)+'0')
3601 n = n / 10
3602 }
3603 if neg {
3604 buf = append(buf, '-')
3605 }
3606 result := make([]byte, len(buf))
3607 for i := 0; i < len(buf); i = i + 1 {
3608 result[i] = buf[len(buf)-1-i]
3609 }
3610 return string(result)
3611 }
3612
3613 func test() int32 {
3614 s := itoa(42)
3615 return int32(len(s))
3616 }
3617 `)
3618 h106 := compileToIR(
3619 uintptr(unsafe.Pointer(&src106[0])), int32(len(src106)),
3620 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3621 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3622 )
3623 ir106 := getIR(h106)
3624 fmt.Println("=== IR for itoa self-compilation pattern ===")
3625 fmt.Println(ir106)
3626
3627 llvmVerify("itoa self-compile", ir106)
3628 assert("itoa has sliceAppend", strings.Contains(ir106, "sliceAppend"))
3629 assert("itoa no parse error", !strings.Contains(ir106, "parse error"))
3630
3631 irFree(h106)
3632
3633 // Test 107: Type method returning interface (SSAMember pattern)
3634 src107 := []byte(`package mypkg
3635
3636 type Member interface {
3637 Name() string
3638 }
3639
3640 type Func struct {
3641 name string
3642 }
3643
3644 func (f *Func) Name() string {
3645 return f.name
3646 }
3647
3648 type Global struct {
3649 name string
3650 }
3651
3652 func (g *Global) Name() string {
3653 return g.name
3654 }
3655
3656 func getMember(which int32) Member {
3657 if which == 0 {
3658 return &Func{name: "test"}
3659 }
3660 return &Global{name: "counter"}
3661 }
3662
3663 func test() int32 {
3664 m := getMember(0)
3665 n := m.Name()
3666 return int32(len(n))
3667 }
3668 `)
3669 h107 := compileToIR(
3670 uintptr(unsafe.Pointer(&src107[0])), int32(len(src107)),
3671 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3672 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3673 )
3674 ir107 := getIR(h107)
3675 fmt.Println("=== IR for interface return ===")
3676 fmt.Println(ir107)
3677
3678 llvmVerify("interface return", ir107)
3679 assert("iface ret has typeid", strings.Contains(ir107, "typeid"))
3680 assert("iface ret no parse error", !strings.Contains(ir107, "parse error"))
3681
3682 irFree(h107)
3683
3684 // Test 108: Interface variable assignment
3685 src108 := []byte(`package mypkg
3686
3687 type Stringer interface {
3688 str() string
3689 }
3690
3691 type Num struct {
3692 val int32
3693 }
3694
3695 func (n Num) str() string {
3696 return "num"
3697 }
3698
3699 func test() int32 {
3700 var s Stringer
3701 s = Num{val: 42}
3702 name := s.str()
3703 return int32(len(name))
3704 }
3705 `)
3706 h108 := compileToIR(
3707 uintptr(unsafe.Pointer(&src108[0])), int32(len(src108)),
3708 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3709 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3710 )
3711 ir108 := getIR(h108)
3712 fmt.Println("=== IR for iface var assign ===")
3713 fmt.Println(ir108)
3714
3715 llvmVerify("iface var assign", ir108)
3716 assert("iface assign has typeid", strings.Contains(ir108, "typeid"))
3717 assert("iface assign no parse error", !strings.Contains(ir108, "parse error"))
3718
3719 irFree(h108)
3720
3721 // Test 109: string(buf) conversion from []byte
3722 src109 := []byte(`package mypkg
3723
3724 func test() int32 {
3725 buf := []byte{72, 105}
3726 s := string(buf)
3727 return int32(len(s))
3728 }
3729 `)
3730 h109 := compileToIR(
3731 uintptr(unsafe.Pointer(&src109[0])), int32(len(src109)),
3732 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3733 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3734 )
3735 ir109 := getIR(h109)
3736 fmt.Println("=== IR for string(buf) ===")
3737 fmt.Println(ir109)
3738
3739 llvmVerify("string(buf)", ir109)
3740 assert("string buf no parse error", !strings.Contains(ir109, "parse error"))
3741
3742 irFree(h109)
3743
3744 // Test 110: byte(expr) conversion + char literal
3745 src110 := []byte(`package mypkg
3746
3747 func test() int32 {
3748 n := int32(5)
3749 b := byte('0' + n)
3750 return int32(b)
3751 }
3752 `)
3753 h110 := compileToIR(
3754 uintptr(unsafe.Pointer(&src110[0])), int32(len(src110)),
3755 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3756 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3757 )
3758 ir110 := getIR(h110)
3759 fmt.Println("=== IR for byte conversion ===")
3760 fmt.Println(ir110)
3761
3762 llvmVerify("byte conversion", ir110)
3763 assert("byte conv no parse error", !strings.Contains(ir110, "parse error"))
3764
3765 irFree(h110)
3766
3767 // Test 111: Slice append in loop (builder pattern from ir_emit)
3768 src111 := []byte(`package mypkg
3769
3770 type Writer struct {
3771 buf []byte
3772 }
3773
3774 func (w *Writer) write(s string) {
3775 w.buf = append(w.buf, s...)
3776 }
3777
3778 func (w *Writer) result() string {
3779 return string(w.buf)
3780 }
3781
3782 func test() int32 {
3783 w := Writer{buf: make([]byte, 0)}
3784 w.write("he")
3785 w.write("llo")
3786 s := w.result()
3787 return int32(len(s))
3788 }
3789 `)
3790 h111 := compileToIR(
3791 uintptr(unsafe.Pointer(&src111[0])), int32(len(src111)),
3792 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3793 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3794 )
3795 ir111 := getIR(h111)
3796 fmt.Println("=== IR for writer pattern ===")
3797 fmt.Println(ir111)
3798
3799 llvmVerify("writer pattern", ir111)
3800 assert("writer has sliceAppend", strings.Contains(ir111, "sliceAppend"))
3801 assert("writer no parse error", !strings.Contains(ir111, "parse error"))
3802
3803 irFree(h111)
3804
3805 // Test 112: Map with string values and range iteration
3806 src112 := []byte(`package mypkg
3807
3808 func test() int32 {
3809 m := map[string]string{"a": "alpha", "b": "beta"}
3810 total := int32(0)
3811 for _, v := range m {
3812 total = total + int32(len(v))
3813 }
3814 return total
3815 }
3816 `)
3817 h112 := compileToIR(
3818 uintptr(unsafe.Pointer(&src112[0])), int32(len(src112)),
3819 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3820 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3821 )
3822 ir112 := getIR(h112)
3823 fmt.Println("=== IR for map string range ===")
3824 fmt.Println(ir112)
3825
3826 llvmVerify("map string range", ir112)
3827 assert("map str range no parse error", !strings.Contains(ir112, "parse error"))
3828
3829 irFree(h112)
3830
3831 // Test 113: Nested if with type assertion
3832 src113 := []byte(`package mypkg
3833
3834 type Animal interface {
3835 sound() string
3836 }
3837
3838 type Dog struct{}
3839
3840 func (d Dog) sound() string { return "woof" }
3841
3842 type Cat struct{}
3843
3844 func (c Cat) sound() string { return "meow" }
3845
3846 func describe(a Animal) int32 {
3847 if d, ok := a.(Dog); ok {
3848 s := d.sound()
3849 return int32(len(s))
3850 }
3851 if c, ok := a.(Cat); ok {
3852 s := c.sound()
3853 return int32(len(s))
3854 }
3855 return 0
3856 }
3857
3858 func test() int32 {
3859 return describe(Dog{}) + describe(Cat{})
3860 }
3861 `)
3862 h113 := compileToIR(
3863 uintptr(unsafe.Pointer(&src113[0])), int32(len(src113)),
3864 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3865 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3866 )
3867 ir113 := getIR(h113)
3868 fmt.Println("=== IR for if type assertion ===")
3869 fmt.Println(ir113)
3870
3871 llvmVerify("if type assertion", ir113)
3872 assert("if type assert no parse error", !strings.Contains(ir113, "parse error"))
3873
3874 irFree(h113)
3875
3876 // Test 114: Large switch on int constant (simulates SSA op dispatch)
3877 src114 := []byte(`package mypkg
3878
3879 const (
3880 OpAdd = iota
3881 OpSub
3882 OpMul
3883 OpDiv
3884 OpEql
3885 OpNeq
3886 OpLss
3887 OpGtr
3888 )
3889
3890 func opName(op int32) string {
3891 switch op {
3892 case OpAdd:
3893 return "add"
3894 case OpSub:
3895 return "sub"
3896 case OpMul:
3897 return "mul"
3898 case OpDiv:
3899 return "div"
3900 case OpEql:
3901 return "eq"
3902 case OpNeq:
3903 return "ne"
3904 case OpLss:
3905 return "lt"
3906 case OpGtr:
3907 return "gt"
3908 default:
3909 return "?"
3910 }
3911 }
3912
3913 func test() int32 {
3914 s1 := opName(OpAdd)
3915 s2 := opName(OpDiv)
3916 return int32(len(s1) + len(s2))
3917 }
3918 `)
3919 h114 := compileToIR(
3920 uintptr(unsafe.Pointer(&src114[0])), int32(len(src114)),
3921 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3922 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3923 )
3924 ir114 := getIR(h114)
3925 fmt.Println("=== IR for large iota switch ===")
3926 fmt.Println(ir114)
3927
3928 llvmVerify("large iota switch", ir114)
3929 assert("large switch has icmp", strings.Contains(ir114, "icmp eq"))
3930 assert("large switch no parse error", !strings.Contains(ir114, "parse error"))
3931
3932 irFree(h114)
3933
3934 // Test 115: Nested type switch (primary dispatch pattern in ir_emit.mx)
3935 src115 := []byte(`package mypkg
3936
3937 type Node interface {
3938 nodeType() int32
3939 }
3940
3941 type Lit struct {
3942 val int32
3943 }
3944 func (l Lit) nodeType() int32 { return 1 }
3945
3946 type BinOp struct {
3947 op int32
3948 x Node
3949 y Node
3950 }
3951 func (b BinOp) nodeType() int32 { return 2 }
3952
3953 type UnOp struct {
3954 op int32
3955 x Node
3956 }
3957 func (u UnOp) nodeType() int32 { return 3 }
3958
3959 func eval(n Node) int32 {
3960 switch v := n.(type) {
3961 case Lit:
3962 return v.val
3963 case BinOp:
3964 lv := eval(v.x)
3965 rv := eval(v.y)
3966 switch v.op {
3967 case 1:
3968 return lv + rv
3969 case 2:
3970 return lv - rv
3971 default:
3972 return 0
3973 }
3974 case UnOp:
3975 inner := eval(v.x)
3976 if v.op == 1 {
3977 return 0 - inner
3978 }
3979 return inner
3980 }
3981 return 0
3982 }
3983
3984 func test() int32 {
3985 a := Lit{val: 10}
3986 b := Lit{val: 3}
3987 sum := BinOp{op: 1, x: a, y: b}
3988 return eval(sum)
3989 }
3990 `)
3991 h115 := compileToIR(
3992 uintptr(unsafe.Pointer(&src115[0])), int32(len(src115)),
3993 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
3994 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
3995 )
3996 ir115 := getIR(h115)
3997 fmt.Println("=== IR for nested type switch ===")
3998 fmt.Println(ir115)
3999
4000 llvmVerify("nested type switch", ir115)
4001 assert("nested tswitch has eval", strings.Contains(ir115, "@mypkg.eval"))
4002 assert("nested tswitch no parse error", !strings.Contains(ir115, "parse error"))
4003
4004 irFree(h115)
4005
4006 // Test 116: String concatenation via | operator (Moxie-specific)
4007 src116 := []byte(`package mypkg
4008
4009 func join(a string, b string) string {
4010 return a | b
4011 }
4012
4013 func test() int32 {
4014 s := join("hel", "lo")
4015 return int32(len(s))
4016 }
4017 `)
4018 h116 := compileToIR(
4019 uintptr(unsafe.Pointer(&src116[0])), int32(len(src116)),
4020 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4021 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4022 )
4023 ir116 := getIR(h116)
4024 fmt.Println("=== IR for string concat ===")
4025 fmt.Println(ir116)
4026
4027 llvmVerify("string concat", ir116)
4028 assert("str concat has sliceAppend", strings.Contains(ir116, "sliceAppend"))
4029 assert("str concat no parse error", !strings.Contains(ir116, "parse error"))
4030
4031 irFree(h116)
4032
4033 // Test 117: Multiple return values with named usage
4034 src117 := []byte(`package mypkg
4035
4036 func divmod(a int32, b int32) (int32, int32) {
4037 return a / b, a % b
4038 }
4039
4040 func test() int32 {
4041 q, r := divmod(17, 5)
4042 return q*10 + r
4043 }
4044 `)
4045 h117 := compileToIR(
4046 uintptr(unsafe.Pointer(&src117[0])), int32(len(src117)),
4047 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4048 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4049 )
4050 ir117 := getIR(h117)
4051 fmt.Println("=== IR for multi-return ===")
4052 fmt.Println(ir117)
4053
4054 llvmVerify("multi-return", ir117)
4055 assert("multi-return has extractvalue", strings.Contains(ir117, "extractvalue"))
4056 assert("multi-return no parse error", !strings.Contains(ir117, "parse error"))
4057
4058 irFree(h117)
4059
4060 // Test 118: For-range over string (byte iteration - Moxie string=[]byte)
4061 src118 := []byte(`package mypkg
4062
4063 func countUpper(s string) int32 {
4064 n := int32(0)
4065 for _, c := range s {
4066 if int32(c) >= 65 && int32(c) <= 90 {
4067 n = n + 1
4068 }
4069 }
4070 return n
4071 }
4072
4073 func test() int32 {
4074 return countUpper("Hello World")
4075 }
4076 `)
4077 h118 := compileToIR(
4078 uintptr(unsafe.Pointer(&src118[0])), int32(len(src118)),
4079 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4080 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4081 )
4082 ir118 := getIR(h118)
4083 fmt.Println("=== IR for range over string ===")
4084 fmt.Println(ir118)
4085
4086 llvmVerify("range over string", ir118)
4087 assert("range string no parse error", !strings.Contains(ir118, "parse error"))
4088
4089 irFree(h118)
4090
4091 // Test 119: Nested struct field write through pointer receiver
4092 src119 := []byte(`package mypkg
4093
4094 type Inner struct {
4095 val int32
4096 }
4097
4098 type Outer struct {
4099 inner Inner
4100 count int32
4101 }
4102
4103 func (o *Outer) setVal(v int32) {
4104 o.inner.val = v
4105 o.count = o.count + 1
4106 }
4107
4108 func (o *Outer) getVal() int32 {
4109 return o.inner.val
4110 }
4111
4112 func test() int32 {
4113 o := Outer{inner: Inner{val: 0}, count: 0}
4114 o.setVal(42)
4115 return o.getVal() + o.count
4116 }
4117 `)
4118 h119 := compileToIR(
4119 uintptr(unsafe.Pointer(&src119[0])), int32(len(src119)),
4120 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4121 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4122 )
4123 ir119 := getIR(h119)
4124 fmt.Println("=== IR for nested struct write ===")
4125 fmt.Println(ir119)
4126
4127 llvmVerify("nested struct write", ir119)
4128 assert("nested struct has getelementptr", strings.Contains(ir119, "getelementptr"))
4129 assert("nested struct no parse error", !strings.Contains(ir119, "parse error"))
4130
4131 irFree(h119)
4132
4133 // Test 120: Global variable with simple init and function-level map
4134 src120 := []byte(`package mypkg
4135
4136 var globalCount int32 = 10
4137
4138 func lookup(s string) int32 {
4139 m := map[string]int32{"if": 1, "for": 3}
4140 v, ok := m[s]
4141 if ok {
4142 return v + globalCount
4143 }
4144 return 0
4145 }
4146
4147 func test() int32 {
4148 return lookup("if") + lookup("for")
4149 }
4150 `)
4151 h120 := compileToIR(
4152 uintptr(unsafe.Pointer(&src120[0])), int32(len(src120)),
4153 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4154 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4155 )
4156 ir120 := getIR(h120)
4157 fmt.Println("=== IR for global var + local map ===")
4158 fmt.Println(ir120)
4159
4160 llvmVerify("global var + local map", ir120)
4161 assert("global var has globalCount", strings.Contains(ir120, "@mypkg.globalCount"))
4162 assert("global var no parse error", !strings.Contains(ir120, "parse error"))
4163
4164 irFree(h120)
4165
4166 // Test 121: Recursive data structure (linked list - forward ref types)
4167 src121 := []byte(`package mypkg
4168
4169 type ListNode struct {
4170 val int32
4171 next *ListNode
4172 }
4173
4174 func sum(n *ListNode) int32 {
4175 total := int32(0)
4176 cur := n
4177 for cur != nil {
4178 total = total + cur.val
4179 cur = cur.next
4180 }
4181 return total
4182 }
4183
4184 func test() int32 {
4185 c := ListNode{val: 3, next: nil}
4186 b := ListNode{val: 2, next: &c}
4187 a := ListNode{val: 1, next: &b}
4188 return sum(&a)
4189 }
4190 `)
4191 h121 := compileToIR(
4192 uintptr(unsafe.Pointer(&src121[0])), int32(len(src121)),
4193 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4194 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4195 )
4196 ir121 := getIR(h121)
4197 fmt.Println("=== IR for linked list ===")
4198 fmt.Println(ir121)
4199
4200 llvmVerify("linked list", ir121)
4201 assert("linked list has icmp ne ptr", strings.Contains(ir121, "icmp ne ptr"))
4202 assert("linked list no parse error", !strings.Contains(ir121, "parse error"))
4203
4204 irFree(h121)
4205
4206 // Test 122: Slice of interfaces (heterogeneous collection)
4207 src122 := []byte(`package mypkg
4208
4209 type Sizer interface {
4210 size() int32
4211 }
4212
4213 type Small struct{}
4214 func (s Small) size() int32 { return 1 }
4215
4216 type Big struct{ n int32 }
4217 func (b Big) size() int32 { return b.n }
4218
4219 func totalSize(items []Sizer) int32 {
4220 total := int32(0)
4221 for _, item := range items {
4222 total = total + item.size()
4223 }
4224 return total
4225 }
4226
4227 func test() int32 {
4228 items := []Sizer{Small{}, Big{n: 5}, Small{}, Big{n: 10}}
4229 return totalSize(items)
4230 }
4231 `)
4232 h122 := compileToIR(
4233 uintptr(unsafe.Pointer(&src122[0])), int32(len(src122)),
4234 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4235 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4236 )
4237 ir122 := getIR(h122)
4238 fmt.Println("=== IR for interface slice ===")
4239 fmt.Println(ir122)
4240
4241 llvmVerify("interface slice", ir122)
4242 assert("iface slice no parse error", !strings.Contains(ir122, "parse error"))
4243
4244 irFree(h122)
4245
4246 // Test 123: Nested function calls with method chaining pattern
4247 src123 := []byte(`package mypkg
4248
4249 type Builder struct {
4250 n int32
4251 }
4252
4253 func newBuilder() *Builder {
4254 b := Builder{n: 0}
4255 return &b
4256 }
4257
4258 func (b *Builder) add(v int32) *Builder {
4259 b.n = b.n + v
4260 return b
4261 }
4262
4263 func (b *Builder) result() int32 {
4264 return b.n
4265 }
4266
4267 func test() int32 {
4268 return newBuilder().add(10).add(20).add(3).result()
4269 }
4270 `)
4271 h123 := compileToIR(
4272 uintptr(unsafe.Pointer(&src123[0])), int32(len(src123)),
4273 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4274 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4275 )
4276 ir123 := getIR(h123)
4277 fmt.Println("=== IR for method chaining ===")
4278 fmt.Println(ir123)
4279
4280 llvmVerify("method chaining", ir123)
4281 assert("chain has newBuilder", strings.Contains(ir123, "@mypkg.newBuilder"))
4282 assert("chain no parse error", !strings.Contains(ir123, "parse error"))
4283
4284 irFree(h123)
4285
4286 // Test 124: Local slice lookup with bounds check
4287 src124 := []byte(`package mypkg
4288
4289 func opName(i int32) string {
4290 names := []string{"add", "sub", "mul", "div", "mod"}
4291 if i >= 0 && i < int32(len(names)) {
4292 return names[i]
4293 }
4294 return "?"
4295 }
4296
4297 func test() int32 {
4298 s := opName(2)
4299 return int32(len(s))
4300 }
4301 `)
4302 h124 := compileToIR(
4303 uintptr(unsafe.Pointer(&src124[0])), int32(len(src124)),
4304 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4305 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4306 )
4307 ir124 := getIR(h124)
4308 fmt.Println("=== IR for local slice lookup ===")
4309 fmt.Println(ir124)
4310
4311 llvmVerify("local slice lookup", ir124)
4312 assert("local slice no parse error", !strings.Contains(ir124, "parse error"))
4313
4314 irFree(h124)
4315
4316 // Test 125: Multiple `:=` with same name in sibling if-blocks (scoping)
4317 src125 := []byte(`package mypkg
4318
4319 func classify(n int32) int32 {
4320 if n > 100 {
4321 r := n - 100
4322 return r
4323 }
4324 if n > 50 {
4325 r := n - 50
4326 return r * 2
4327 }
4328 if n > 0 {
4329 r := n
4330 return r * 3
4331 }
4332 return 0
4333 }
4334
4335 func test() int32 {
4336 return classify(120) + classify(75)
4337 }
4338 `)
4339 h125 := compileToIR(
4340 uintptr(unsafe.Pointer(&src125[0])), int32(len(src125)),
4341 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4342 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4343 )
4344 ir125 := getIR(h125)
4345 fmt.Println("=== IR for variable shadowing ===")
4346 fmt.Println(ir125)
4347
4348 llvmVerify("variable shadowing", ir125)
4349 assert("shadowing no parse error", !strings.Contains(ir125, "parse error"))
4350
4351 irFree(h125)
4352
4353 // Test 126: Multiple interface implementations with method dispatch
4354 src126 := []byte(`package mypkg
4355
4356 type Formatter interface {
4357 format() string
4358 }
4359
4360 type IntFmt struct{ val int32 }
4361 func (f IntFmt) format() string {
4362 if f.val > 0 {
4363 return "positive"
4364 }
4365 return "non-positive"
4366 }
4367
4368 type StrFmt struct{ val string }
4369 func (f StrFmt) format() string {
4370 return f.val
4371 }
4372
4373 type NilFmt struct{}
4374 func (f NilFmt) format() string {
4375 return "nil"
4376 }
4377
4378 func formatLen(f Formatter) int32 {
4379 s := f.format()
4380 return int32(len(s))
4381 }
4382
4383 func test() int32 {
4384 a := formatLen(IntFmt{val: 5})
4385 b := formatLen(StrFmt{val: "hello"})
4386 c := formatLen(NilFmt{})
4387 return a + b + c
4388 }
4389 `)
4390 h126 := compileToIR(
4391 uintptr(unsafe.Pointer(&src126[0])), int32(len(src126)),
4392 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4393 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4394 )
4395 ir126 := getIR(h126)
4396 fmt.Println("=== IR for multi-impl dispatch ===")
4397 fmt.Println(ir126)
4398
4399 llvmVerify("multi-impl dispatch", ir126)
4400 assert("multi-impl has typeid", strings.Contains(ir126, "typeid"))
4401 assert("multi-impl no parse error", !strings.Contains(ir126, "parse error"))
4402
4403 irFree(h126)
4404
4405 // Test 127: Nested composite literal (struct containing struct containing slice)
4406 src127 := []byte(`package mypkg
4407
4408 type Pos struct {
4409 line int32
4410 col int32
4411 }
4412
4413 type Token struct {
4414 pos Pos
4415 kind int32
4416 text string
4417 }
4418
4419 func tokenLen(t Token) int32 {
4420 return int32(len(t.text)) + t.pos.line
4421 }
4422
4423 func test() int32 {
4424 t := Token{
4425 pos: Pos{line: 1, col: 5},
4426 kind: 42,
4427 text: "hello",
4428 }
4429 return tokenLen(t)
4430 }
4431 `)
4432 h127 := compileToIR(
4433 uintptr(unsafe.Pointer(&src127[0])), int32(len(src127)),
4434 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4435 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4436 )
4437 ir127 := getIR(h127)
4438 fmt.Println("=== IR for nested struct literal ===")
4439 fmt.Println(ir127)
4440
4441 llvmVerify("nested struct literal", ir127)
4442 assert("nested struct lit has gep", strings.Contains(ir127, "getelementptr"))
4443 assert("nested struct lit no parse error", !strings.Contains(ir127, "parse error"))
4444
4445 irFree(h127)
4446
4447 // Test 128: Recursive function with multiple base cases
4448 src128 := []byte(`package mypkg
4449
4450 func fib(n int32) int32 {
4451 if n <= 0 {
4452 return 0
4453 }
4454 if n == 1 {
4455 return 1
4456 }
4457 return fib(n-1) + fib(n-2)
4458 }
4459
4460 func test() int32 {
4461 return fib(7)
4462 }
4463 `)
4464 h128 := compileToIR(
4465 uintptr(unsafe.Pointer(&src128[0])), int32(len(src128)),
4466 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4467 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4468 )
4469 ir128 := getIR(h128)
4470 fmt.Println("=== IR for fibonacci ===")
4471 fmt.Println(ir128)
4472
4473 llvmVerify("fibonacci", ir128)
4474 assert("fib has recursive call", strings.Contains(ir128, "@mypkg.fib"))
4475 assert("fib no parse error", !strings.Contains(ir128, "parse error"))
4476
4477 irFree(h128)
4478
4479 // Test 129: Slice of structs with append and field access in loop
4480 src129 := []byte(`package mypkg
4481
4482 type Entry struct {
4483 key string
4484 value int32
4485 }
4486
4487 func totalValue(entries []Entry) int32 {
4488 total := int32(0)
4489 for _, e := range entries {
4490 total = total + e.value
4491 }
4492 return total
4493 }
4494
4495 func test() int32 {
4496 entries := []Entry{
4497 Entry{key: "a", value: 10},
4498 Entry{key: "b", value: 20},
4499 Entry{key: "c", value: 30},
4500 }
4501 return totalValue(entries)
4502 }
4503 `)
4504 h129 := compileToIR(
4505 uintptr(unsafe.Pointer(&src129[0])), int32(len(src129)),
4506 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4507 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4508 )
4509 ir129 := getIR(h129)
4510 fmt.Println("=== IR for struct slice ===")
4511 fmt.Println(ir129)
4512
4513 llvmVerify("struct slice", ir129)
4514 assert("struct slice no parse error", !strings.Contains(ir129, "parse error"))
4515
4516 irFree(h129)
4517
4518 // Test 130: Type switch with mixed types (pattern from ir_emit.mx dispatch)
4519 src130 := []byte(`package mypkg
4520
4521 type Expr interface {
4522 eval() int32
4523 }
4524
4525 type Const struct{ val int32 }
4526 func (c Const) eval() int32 { return c.val }
4527
4528 type Add struct{ x Expr; y Expr }
4529 func (a Add) eval() int32 { return a.x.eval() + a.y.eval() }
4530
4531 type Neg struct{ x Expr }
4532 func (n Neg) eval() int32 { return 0 - n.x.eval() }
4533
4534 func describe(e Expr) int32 {
4535 switch v := e.(type) {
4536 case Const:
4537 return v.val
4538 case Add:
4539 return v.eval()
4540 case Neg:
4541 return v.eval()
4542 }
4543 return 0
4544 }
4545
4546 func test() int32 {
4547 c1 := Const{val: 5}
4548 c2 := Const{val: 3}
4549 sum := Add{x: c1, y: c2}
4550 neg := Neg{x: c1}
4551 return describe(sum) + describe(neg)
4552 }
4553 `)
4554 h130 := compileToIR(
4555 uintptr(unsafe.Pointer(&src130[0])), int32(len(src130)),
4556 uintptr(unsafe.Pointer(&name1[0])), int32(len(name1)),
4557 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4558 )
4559 ir130 := getIR(h130)
4560 fmt.Println("=== IR for expr eval dispatch ===")
4561 fmt.Println(ir130)
4562
4563 llvmVerify("expr eval dispatch", ir130)
4564 assert("expr eval has typeid", strings.Contains(ir130, "typeid"))
4565 assert("expr eval no parse error", !strings.Contains(ir130, "parse error"))
4566
4567 irFree(h130)
4568
4569 // Test 131: Cross-package function call
4570 regPkg("mathutil", "mathutil")
4571 regFn("mathutil", "Double", "int32->int32")
4572 regFn("mathutil", "Add", "int32,int32->int32")
4573
4574 src131 := []byte(`package mypkg
4575
4576 import "mathutil"
4577
4578 func compute(x int32) int32 {
4579 return mathutil.Add(mathutil.Double(x), 10)
4580 }
4581 `)
4582 name131 := []byte("mypkg")
4583 h131 := compileToIR(
4584 uintptr(unsafe.Pointer(&src131[0])), int32(len(src131)),
4585 uintptr(unsafe.Pointer(&name131[0])), int32(len(name131)),
4586 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4587 )
4588 ir131 := getIR(h131)
4589 fmt.Println("=== IR for cross-package call ===")
4590 fmt.Println(ir131)
4591
4592 llvmVerify("cross-package call", ir131)
4593 assert("cross-pkg has declare @mathutil.Double", strings.Contains(ir131, "declare") && strings.Contains(ir131, "@mathutil.Double"))
4594 assert("cross-pkg has declare @mathutil.Add", strings.Contains(ir131, "@mathutil.Add"))
4595 assert("cross-pkg calls Double", strings.Contains(ir131, "call i32 @mathutil.Double("))
4596 assert("cross-pkg calls Add", strings.Contains(ir131, "call i32 @mathutil.Add("))
4597 assert("cross-pkg no parse error", !strings.Contains(ir131, "parse error"))
4598
4599 irFree(h131)
4600 clearImports()
4601
4602 // Test 132: Cross-package variable access
4603 regPkg("config", "config")
4604 regVar("config", "MaxRetries", "int32")
4605 regFn("config", "GetTimeout", "->int32")
4606
4607 src132 := []byte(`package mypkg
4608
4609 import "config"
4610
4611 func retries() int32 {
4612 return config.MaxRetries
4613 }
4614
4615 func timeout() int32 {
4616 return config.GetTimeout()
4617 }
4618 `)
4619 name132 := []byte("mypkg")
4620 h132 := compileToIR(
4621 uintptr(unsafe.Pointer(&src132[0])), int32(len(src132)),
4622 uintptr(unsafe.Pointer(&name132[0])), int32(len(name132)),
4623 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4624 )
4625 ir132 := getIR(h132)
4626 fmt.Println("=== IR for cross-package variable ===")
4627 fmt.Println(ir132)
4628
4629 llvmVerify("cross-package variable", ir132)
4630 assert("cross-pkg-var has @config.MaxRetries global", strings.Contains(ir132, "@config.MaxRetries"))
4631 assert("cross-pkg-var loads MaxRetries", strings.Contains(ir132, "load i32, ptr @config.MaxRetries"))
4632 assert("cross-pkg-var calls GetTimeout", strings.Contains(ir132, "call i32 @config.GetTimeout("))
4633 assert("cross-pkg-var no parse error", !strings.Contains(ir132, "parse error"))
4634
4635 irFree(h132)
4636 clearImports()
4637
4638 // Test 133: Aliased import
4639 regPkg("long/path/util", "util")
4640 regFn("long/path/util", "Helper", "int32->int32")
4641
4642 src133 := []byte(`package mypkg
4643
4644 import u "long/path/util"
4645
4646 func wrapped(x int32) int32 {
4647 return u.Helper(x)
4648 }
4649 `)
4650 name133 := []byte("mypkg")
4651 h133 := compileToIR(
4652 uintptr(unsafe.Pointer(&src133[0])), int32(len(src133)),
4653 uintptr(unsafe.Pointer(&name133[0])), int32(len(name133)),
4654 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4655 )
4656 ir133 := getIR(h133)
4657 fmt.Println("=== IR for aliased import ===")
4658 fmt.Println(ir133)
4659
4660 llvmVerify("aliased import", ir133)
4661 assert("aliased import calls @long/path/util.Helper", strings.Contains(ir133, `@"long/path/util.Helper"`))
4662 assert("aliased import has declare", strings.Contains(ir133, "declare"))
4663 assert("aliased import no parse error", !strings.Contains(ir133, "parse error"))
4664
4665 irFree(h133)
4666 clearImports()
4667
4668 // Test 134: Cross-package multi-return function
4669 regPkg("parser", "parser")
4670 regFn("parser", "Parse", "[]byte->int32,bool")
4671
4672 src134 := []byte(`package mypkg
4673
4674 import "parser"
4675
4676 func tryParse(data []byte) int32 {
4677 n, ok := parser.Parse(data)
4678 if ok {
4679 return n
4680 }
4681 return -1
4682 }
4683 `)
4684 name134 := []byte("mypkg")
4685 h134 := compileToIR(
4686 uintptr(unsafe.Pointer(&src134[0])), int32(len(src134)),
4687 uintptr(unsafe.Pointer(&name134[0])), int32(len(name134)),
4688 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4689 )
4690 ir134 := getIR(h134)
4691 fmt.Println("=== IR for cross-pkg multi-return ===")
4692 fmt.Println(ir134)
4693
4694 llvmVerify("cross-pkg multi-return", ir134)
4695 assert("cross-pkg multi-ret calls Parse", strings.Contains(ir134, "call {i32, i1} @parser.Parse("))
4696 assert("cross-pkg multi-ret extracts value", strings.Contains(ir134, "extractvalue"))
4697 assert("cross-pkg multi-ret no parse error", !strings.Contains(ir134, "parse error"))
4698
4699 irFree(h134)
4700 clearImports()
4701
4702 // Test 135: Cross-package slice-returning function
4703 regPkg("codec", "codec")
4704 regFn("codec", "Encode", "int32->[]byte")
4705
4706 src135 := []byte(`package mypkg
4707
4708 import "codec"
4709
4710 func encodeVal(v int32) []byte {
4711 return codec.Encode(v)
4712 }
4713 `)
4714 name135 := []byte("mypkg")
4715 h135 := compileToIR(
4716 uintptr(unsafe.Pointer(&src135[0])), int32(len(src135)),
4717 uintptr(unsafe.Pointer(&name135[0])), int32(len(name135)),
4718 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4719 )
4720 ir135 := getIR(h135)
4721 fmt.Println("=== IR for cross-pkg slice return ===")
4722 fmt.Println(ir135)
4723
4724 llvmVerify("cross-pkg slice return", ir135)
4725 assert("cross-pkg slice calls Encode", strings.Contains(ir135, "call {ptr, i64, i64} @codec.Encode("))
4726 assert("cross-pkg slice has declare", strings.Contains(ir135, "declare"))
4727 assert("cross-pkg slice no parse error", !strings.Contains(ir135, "parse error"))
4728
4729 irFree(h135)
4730 clearImports()
4731
4732 // Test 136: Cross-package function as argument to local function
4733 regPkg("strings", "strings")
4734 regFn("strings", "Contains", "string,string->bool")
4735 regFn("strings", "HasPrefix", "string,string->bool")
4736
4737 src136 := []byte(`package mypkg
4738
4739 import "strings"
4740
4741 func check(s string) bool {
4742 if strings.HasPrefix(s, "test") {
4743 return strings.Contains(s, "pass")
4744 }
4745 return false
4746 }
4747 `)
4748 name136 := []byte("mypkg")
4749 h136 := compileToIR(
4750 uintptr(unsafe.Pointer(&src136[0])), int32(len(src136)),
4751 uintptr(unsafe.Pointer(&name136[0])), int32(len(name136)),
4752 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4753 )
4754 ir136 := getIR(h136)
4755 fmt.Println("=== IR for cross-pkg chained calls ===")
4756 fmt.Println(ir136)
4757
4758 llvmVerify("cross-pkg chained calls", ir136)
4759 assert("cross-pkg chain calls HasPrefix", strings.Contains(ir136, "@strings.HasPrefix"))
4760 assert("cross-pkg chain calls Contains", strings.Contains(ir136, "@strings.Contains"))
4761 assert("cross-pkg chain both declared", strings.Count(ir136, "declare") >= 2)
4762 assert("cross-pkg chain no parse error", !strings.Contains(ir136, "parse error"))
4763
4764 irFree(h136)
4765 clearImports()
4766
4767 // Test 137: Cross-package void function (no return value)
4768 regPkg("log", "log")
4769 regFn("log", "Print", "string")
4770
4771 src137 := []byte(`package mypkg
4772
4773 import "log"
4774
4775 func logMsg(msg string) {
4776 log.Print(msg)
4777 }
4778 `)
4779 name137 := []byte("mypkg")
4780 h137 := compileToIR(
4781 uintptr(unsafe.Pointer(&src137[0])), int32(len(src137)),
4782 uintptr(unsafe.Pointer(&name137[0])), int32(len(name137)),
4783 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4784 )
4785 ir137 := getIR(h137)
4786 fmt.Println("=== IR for cross-pkg void call ===")
4787 fmt.Println(ir137)
4788
4789 llvmVerify("cross-pkg void call", ir137)
4790 assert("cross-pkg void calls Print", strings.Contains(ir137, "call void @log.Print("))
4791 assert("cross-pkg void has declare", strings.Contains(ir137, "declare void @log.Print("))
4792 assert("cross-pkg void no parse error", !strings.Contains(ir137, "parse error"))
4793
4794 irFree(h137)
4795 clearImports()
4796
4797 // Test 138: Multiple imports in one file
4798 regPkg("bytes", "bytes")
4799 regFn("bytes", "NewReader", "[]byte->*int32")
4800 regPkg("strconv", "strconv")
4801 regFn("strconv", "Itoa", "int32->string")
4802
4803 src138 := []byte(`package mypkg
4804
4805 import (
4806 "bytes"
4807 "strconv"
4808 )
4809
4810 func format(n int32) []byte {
4811 s := strconv.Itoa(n)
4812 return s
4813 }
4814
4815 func reader(data []byte) *int32 {
4816 return bytes.NewReader(data)
4817 }
4818 `)
4819 name138 := []byte("mypkg")
4820 h138 := compileToIR(
4821 uintptr(unsafe.Pointer(&src138[0])), int32(len(src138)),
4822 uintptr(unsafe.Pointer(&name138[0])), int32(len(name138)),
4823 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4824 )
4825 ir138 := getIR(h138)
4826 fmt.Println("=== IR for multi-import ===")
4827 fmt.Println(ir138)
4828
4829 llvmVerify("multi-import", ir138)
4830 assert("multi-import calls Itoa", strings.Contains(ir138, "@strconv.Itoa"))
4831 assert("multi-import calls NewReader", strings.Contains(ir138, "@bytes.NewReader"))
4832 assert("multi-import no parse error", !strings.Contains(ir138, "parse error"))
4833
4834 irFree(h138)
4835 clearImports()
4836
4837 // Test 139: Named type with methods and switch - pattern from ssa_types.mx
4838 src139 := []byte(`package mypkg
4839
4840 type Op int32
4841
4842 const (
4843 OpAdd Op = iota
4844 OpSub
4845 OpMul
4846 )
4847
4848 func (op Op) String() string {
4849 switch op {
4850 case OpAdd:
4851 return "+"
4852 case OpSub:
4853 return "-"
4854 case OpMul:
4855 return "*"
4856 }
4857 return "?"
4858 }
4859
4860 func describe(op Op) string {
4861 return op.String()
4862 }
4863 `)
4864 name139 := []byte("mypkg")
4865 h139 := compileToIR(
4866 uintptr(unsafe.Pointer(&src139[0])), int32(len(src139)),
4867 uintptr(unsafe.Pointer(&name139[0])), int32(len(name139)),
4868 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4869 )
4870 ir139 := getIR(h139)
4871 fmt.Println("=== IR for named type method ===")
4872 fmt.Println(ir139)
4873
4874 llvmVerify("named type method", ir139)
4875 assert("named-type has Op.String method", strings.Contains(ir139, "@mypkg.Op.String"))
4876 assert("named-type has switch comparisons", strings.Contains(ir139, "icmp eq i32"))
4877 assert("named-type describe calls String", strings.Contains(ir139, "call"))
4878 assert("named-type no parse error", !strings.Contains(ir139, "parse error"))
4879
4880 irFree(h139)
4881
4882 // Test 140: Struct with method returning pointer to self - pattern from SSA builder
4883 src140 := []byte(`package mypkg
4884
4885 type Builder struct {
4886 buf []byte
4887 count int32
4888 }
4889
4890 func (b *Builder) Write(data []byte) *Builder {
4891 b.buf = append(b.buf, data...)
4892 b.count = b.count + 1
4893 return b
4894 }
4895
4896 func (b *Builder) Len() int32 {
4897 return int32(len(b.buf))
4898 }
4899
4900 func chain() int32 {
4901 b := &Builder{buf: []byte{:0:64}}
4902 b.Write([]byte("hello")).Write([]byte(" world"))
4903 return b.Len()
4904 }
4905 `)
4906 name140 := []byte("mypkg")
4907 h140 := compileToIR(
4908 uintptr(unsafe.Pointer(&src140[0])), int32(len(src140)),
4909 uintptr(unsafe.Pointer(&name140[0])), int32(len(name140)),
4910 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4911 )
4912 ir140 := getIR(h140)
4913 fmt.Println("=== IR for struct method chain ===")
4914 fmt.Println(ir140)
4915
4916 llvmVerify("struct method chain", ir140)
4917 assert("method-chain has Write method", strings.Contains(ir140, "@mypkg.Builder.Write"))
4918 assert("method-chain has Len method", strings.Contains(ir140, "@mypkg.Builder.Len"))
4919 assert("method-chain chain calls Write twice", strings.Count(ir140, "call ptr @mypkg.Write") >= 2 || strings.Count(ir140, "call") >= 3)
4920 assert("method-chain no parse error", !strings.Contains(ir140, "parse error"))
4921
4922 irFree(h140)
4923
4924 // Test 141: Cross-package function result used in local map
4925 regPkg("strconv", "strconv")
4926 regFn("strconv", "Itoa", "int32->string")
4927
4928 src141 := []byte(`package mypkg
4929
4930 import "strconv"
4931
4932 func buildTable(n int32) map[int32]string {
4933 m := map[int32]string{}
4934 var i int32
4935 for i = 0; i < n; i++ {
4936 m[i] = strconv.Itoa(i)
4937 }
4938 return m
4939 }
4940 `)
4941 name141 := []byte("mypkg")
4942 h141 := compileToIR(
4943 uintptr(unsafe.Pointer(&src141[0])), int32(len(src141)),
4944 uintptr(unsafe.Pointer(&name141[0])), int32(len(name141)),
4945 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4946 )
4947 ir141 := getIR(h141)
4948 fmt.Println("=== IR for cross-pkg in map ===")
4949 fmt.Println(ir141)
4950
4951 llvmVerify("cross-pkg in map", ir141)
4952 assert("cross-pkg-map calls Itoa", strings.Contains(ir141, "@strconv.Itoa"))
4953 assert("cross-pkg-map has hashmapBinarySet", strings.Contains(ir141, "runtime.hashmapBinarySet"))
4954 assert("cross-pkg-map no parse error", !strings.Contains(ir141, "parse error"))
4955
4956 irFree(h141)
4957 clearImports()
4958
4959 // Test 142: Cross-package function result stored in struct field
4960 regPkg("codec", "codec")
4961 regFn("codec", "Encode", "int32->[]byte")
4962
4963 src142 := []byte(`package mypkg
4964
4965 import "codec"
4966
4967 type Packet struct {
4968 data []byte
4969 seq int32
4970 }
4971
4972 func newPacket(seq int32) Packet {
4973 return Packet{
4974 data: codec.Encode(seq),
4975 seq: seq,
4976 }
4977 }
4978 `)
4979 name142 := []byte("mypkg")
4980 h142 := compileToIR(
4981 uintptr(unsafe.Pointer(&src142[0])), int32(len(src142)),
4982 uintptr(unsafe.Pointer(&name142[0])), int32(len(name142)),
4983 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
4984 )
4985 ir142 := getIR(h142)
4986 fmt.Println("=== IR for cross-pkg in struct ===")
4987 fmt.Println(ir142)
4988
4989 llvmVerify("cross-pkg in struct", ir142)
4990 assert("cross-pkg-struct calls Encode", strings.Contains(ir142, "@codec.Encode"))
4991 assert("cross-pkg-struct has struct GEP", strings.Contains(ir142, "getelementptr"))
4992 assert("cross-pkg-struct no parse error", !strings.Contains(ir142, "parse error"))
4993
4994 irFree(h142)
4995 clearImports()
4996
4997 // Test 143: Cross-package function in conditional expression
4998 regPkg("strings", "strings")
4999 regFn("strings", "HasPrefix", "string,string->bool")
5000 regFn("strings", "TrimPrefix", "string,string->string")
5001
5002 src143 := []byte(`package mypkg
5003
5004 import "strings"
5005
5006 func clean(s string) string {
5007 if strings.HasPrefix(s, "//") {
5008 return strings.TrimPrefix(s, "//")
5009 }
5010 return s
5011 }
5012 `)
5013 name143 := []byte("mypkg")
5014 h143 := compileToIR(
5015 uintptr(unsafe.Pointer(&src143[0])), int32(len(src143)),
5016 uintptr(unsafe.Pointer(&name143[0])), int32(len(name143)),
5017 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5018 )
5019 ir143 := getIR(h143)
5020 fmt.Println("=== IR for cross-pkg conditional ===")
5021 fmt.Println(ir143)
5022
5023 llvmVerify("cross-pkg conditional", ir143)
5024 assert("cross-pkg-cond calls HasPrefix", strings.Contains(ir143, "@strings.HasPrefix"))
5025 assert("cross-pkg-cond calls TrimPrefix", strings.Contains(ir143, "@strings.TrimPrefix"))
5026 assert("cross-pkg-cond has branch", strings.Contains(ir143, "br i1"))
5027 assert("cross-pkg-cond no parse error", !strings.Contains(ir143, "parse error"))
5028
5029 irFree(h143)
5030 clearImports()
5031
5032 // Test 144: Cross-package variable write (store to external global)
5033 regPkg("state", "state")
5034 regVar("state", "Counter", "int32")
5035 regVar("state", "Name", "string")
5036
5037 src144 := []byte(`package mypkg
5038
5039 import "state"
5040
5041 func increment() {
5042 state.Counter = state.Counter + 1
5043 }
5044
5045 func setName(s string) {
5046 state.Name = s
5047 }
5048 `)
5049 name144 := []byte("mypkg")
5050 h144 := compileToIR(
5051 uintptr(unsafe.Pointer(&src144[0])), int32(len(src144)),
5052 uintptr(unsafe.Pointer(&name144[0])), int32(len(name144)),
5053 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5054 )
5055 ir144 := getIR(h144)
5056 fmt.Println("=== IR for cross-pkg variable write ===")
5057 fmt.Println(ir144)
5058
5059 llvmVerify("cross-pkg variable write", ir144)
5060 assert("cross-pkg-write loads Counter", strings.Contains(ir144, "load i32, ptr @state.Counter"))
5061 assert("cross-pkg-write stores Counter", strings.Contains(ir144, "store i32") && strings.Contains(ir144, "@state.Counter"))
5062 assert("cross-pkg-write stores Name", strings.Contains(ir144, "store {ptr, i64, i64}") && strings.Contains(ir144, "@state.Name"))
5063 assert("cross-pkg-write has external globals", strings.Contains(ir144, "external global"))
5064 assert("cross-pkg-write no parse error", !strings.Contains(ir144, "parse error"))
5065
5066 irFree(h144)
5067 clearImports()
5068
5069 // Test 145: String escape pattern from ir_emit.mx (string indexing, bit shift, hex table)
5070 src145 := []byte(`package mypkg
5071
5072 func escape(s string) []byte {
5073 var buf []byte
5074 for i := 0; i < len(s); i++ {
5075 c := s[i]
5076 if c >= 32 && c < 127 {
5077 buf = append(buf, c)
5078 } else {
5079 buf = append(buf, '\\')
5080 buf = append(buf, "0123456789ABCDEF"[c>>4])
5081 buf = append(buf, "0123456789ABCDEF"[c&0xf])
5082 }
5083 }
5084 return buf
5085 }
5086 `)
5087 name145 := []byte("mypkg")
5088 h145 := compileToIR(
5089 uintptr(unsafe.Pointer(&src145[0])), int32(len(src145)),
5090 uintptr(unsafe.Pointer(&name145[0])), int32(len(name145)),
5091 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5092 )
5093 ir145 := getIR(h145)
5094 fmt.Println("=== IR for string escape ===")
5095 fmt.Println(ir145)
5096
5097 llvmVerify("string escape", ir145)
5098 assert("escape has shr (>>4)", strings.Contains(ir145, "lshr") || strings.Contains(ir145, "ashr"))
5099 assert("escape has and (&0xf)", strings.Contains(ir145, "and"))
5100 assert("escape has string index GEP", strings.Contains(ir145, "getelementptr"))
5101 assert("escape no parse error", !strings.Contains(ir145, "parse error"))
5102
5103 irFree(h145)
5104
5105 // Test 146: String builder pattern from ir_emit.mx (append bytes, return string)
5106 src146 := []byte(`package mypkg
5107
5108 func build(parts []string) string {
5109 var buf []byte
5110 for i := 0; i < len(parts); i++ {
5111 if i > 0 {
5112 buf = append(buf, ',')
5113 }
5114 buf = append(buf, parts[i]...)
5115 }
5116 return string(buf)
5117 }
5118 `)
5119 name146 := []byte("mypkg")
5120 h146 := compileToIR(
5121 uintptr(unsafe.Pointer(&src146[0])), int32(len(src146)),
5122 uintptr(unsafe.Pointer(&name146[0])), int32(len(name146)),
5123 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5124 )
5125 ir146 := getIR(h146)
5126 fmt.Println("=== IR for string builder ===")
5127 fmt.Println(ir146)
5128
5129 llvmVerify("string builder", ir146)
5130 assert("builder has sliceAppend", strings.Contains(ir146, "sliceAppend"))
5131 assert("builder has loop", strings.Contains(ir146, "br i1"))
5132 assert("builder no parse error", !strings.Contains(ir146, "parse error"))
5133
5134 irFree(h146)
5135
5136 // Test 147: Multiple return with cross-package call in one return value
5137 regPkg("conv", "conv")
5138 regFn("conv", "Parse", "string->int32,bool")
5139
5140 src147 := []byte(`package mypkg
5141
5142 import "conv"
5143
5144 func tryGet(s string) (int32, string) {
5145 n, ok := conv.Parse(s)
5146 if !ok {
5147 return 0, "error"
5148 }
5149 return n, "ok"
5150 }
5151 `)
5152 name147 := []byte("mypkg")
5153 h147 := compileToIR(
5154 uintptr(unsafe.Pointer(&src147[0])), int32(len(src147)),
5155 uintptr(unsafe.Pointer(&name147[0])), int32(len(name147)),
5156 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5157 )
5158 ir147 := getIR(h147)
5159 fmt.Println("=== IR for multi-ret cross-pkg ===")
5160 fmt.Println(ir147)
5161
5162 llvmVerify("multi-ret cross-pkg", ir147)
5163 assert("multi-ret calls Parse", strings.Contains(ir147, "@conv.Parse"))
5164 assert("multi-ret extracts bool", strings.Contains(ir147, "extractvalue"))
5165 assert("multi-ret returns tuple", strings.Contains(ir147, "ret {i32, {ptr, i64, i64}}"))
5166 assert("multi-ret no parse error", !strings.Contains(ir147, "parse error"))
5167
5168 irFree(h147)
5169 clearImports()
5170
5171 // Test 148: Realistic emitter pattern - struct with map fields, methods, string building
5172 src148 := []byte(`package mypkg
5173
5174 type Emitter struct {
5175 buf []byte
5176 names map[string]int32
5177 next int32
5178 }
5179
5180 func newEmitter() *Emitter {
5181 return &Emitter{
5182 buf: []byte{:0:1024},
5183 names: map[string]int32{},
5184 }
5185 }
5186
5187 func (e *Emitter) w(s string) {
5188 e.buf = append(e.buf, s...)
5189 }
5190
5191 func (e *Emitter) nextName() string {
5192 e.next = e.next + 1
5193 return "t"
5194 }
5195
5196 func (e *Emitter) lookup(name string) int32 {
5197 if n, ok := e.names[name]; ok {
5198 return n
5199 }
5200 n := e.next
5201 e.next = e.next + 1
5202 e.names[name] = n
5203 return n
5204 }
5205
5206 func (e *Emitter) emit() string {
5207 e.w("define void @main() {\n")
5208 e.w("entry:\n")
5209 e.w(" ret void\n")
5210 e.w("}\n")
5211 return string(e.buf)
5212 }
5213
5214 func run() string {
5215 e := newEmitter()
5216 e.lookup("x")
5217 e.lookup("y")
5218 return e.emit()
5219 }
5220 `)
5221 name148 := []byte("mypkg")
5222 h148 := compileToIR(
5223 uintptr(unsafe.Pointer(&src148[0])), int32(len(src148)),
5224 uintptr(unsafe.Pointer(&name148[0])), int32(len(name148)),
5225 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5226 )
5227 ir148 := getIR(h148)
5228 fmt.Println("=== IR for emitter pattern ===")
5229 fmt.Println(ir148)
5230
5231 llvmVerify("emitter pattern", ir148)
5232 assert("emitter has Emitter.w method", strings.Contains(ir148, "@mypkg.Emitter.w"))
5233 assert("emitter has Emitter.lookup method", strings.Contains(ir148, "@mypkg.Emitter.lookup"))
5234 assert("emitter has Emitter.emit method", strings.Contains(ir148, "@mypkg.Emitter.emit"))
5235 assert("emitter has map operations", strings.Contains(ir148, "hashmap"))
5236 assert("emitter has newEmitter", strings.Contains(ir148, "@mypkg.newEmitter"))
5237 assert("emitter no parse error", !strings.Contains(ir148, "parse error"))
5238
5239 irFree(h148)
5240
5241 // Test 149: Interface dispatch with method set - pattern from SSA instruction emit
5242 src149 := []byte(`package mypkg
5243
5244 type Instruction interface {
5245 String() string
5246 }
5247
5248 type Add struct {
5249 left int32
5250 right int32
5251 }
5252
5253 type Ret struct {
5254 val int32
5255 }
5256
5257 func (a *Add) String() string {
5258 return "add"
5259 }
5260
5261 func (r *Ret) String() string {
5262 return "ret"
5263 }
5264
5265 func emit(instr Instruction) string {
5266 return instr.String()
5267 }
5268
5269 func test() string {
5270 a := &Add{left: 1, right: 2}
5271 r := &Ret{val: 42}
5272 s1 := emit(a)
5273 s2 := emit(r)
5274 return s1 | s2
5275 }
5276 `)
5277 name149 := []byte("mypkg")
5278 h149 := compileToIR(
5279 uintptr(unsafe.Pointer(&src149[0])), int32(len(src149)),
5280 uintptr(unsafe.Pointer(&name149[0])), int32(len(name149)),
5281 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5282 )
5283 ir149 := getIR(h149)
5284 fmt.Println("=== IR for interface dispatch ===")
5285 fmt.Println(ir149)
5286
5287 llvmVerify("interface dispatch", ir149)
5288 assert("iface-dispatch has Add.String", strings.Contains(ir149, "Add.String"))
5289 assert("iface-dispatch has Ret.String", strings.Contains(ir149, "Ret.String"))
5290 assert("iface-dispatch has typeid", strings.Contains(ir149, "typeid"))
5291 assert("iface-dispatch has emit function", strings.Contains(ir149, "@mypkg.emit"))
5292 assert("iface-dispatch no parse error", !strings.Contains(ir149, "parse error"))
5293
5294 irFree(h149)
5295
5296 // Test 150: Switch on type with fallthrough to handler - mirrors emitInstr dispatch
5297 src150 := []byte(`package mypkg
5298
5299 type Node interface {
5300 nodeTag()
5301 }
5302
5303 type Lit struct {
5304 val int32
5305 }
5306
5307 type Bin struct {
5308 op int32
5309 left Node
5310 right Node
5311 }
5312
5313 func (l *Lit) nodeTag() {}
5314 func (b *Bin) nodeTag() {}
5315
5316 func eval(n Node) int32 {
5317 switch v := n.(type) {
5318 case *Lit:
5319 return v.val
5320 case *Bin:
5321 l := eval(v.left)
5322 r := eval(v.right)
5323 if v.op == 0 {
5324 return l + r
5325 }
5326 return l - r
5327 }
5328 return 0
5329 }
5330 `)
5331 name150 := []byte("mypkg")
5332 h150 := compileToIR(
5333 uintptr(unsafe.Pointer(&src150[0])), int32(len(src150)),
5334 uintptr(unsafe.Pointer(&name150[0])), int32(len(name150)),
5335 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5336 )
5337 ir150 := getIR(h150)
5338 fmt.Println("=== IR for type switch dispatch ===")
5339 fmt.Println(ir150)
5340
5341 llvmVerify("type switch dispatch", ir150)
5342 assert("type-switch has eval function", strings.Contains(ir150, "@mypkg.eval"))
5343 assert("type-switch has typeid comparisons", strings.Contains(ir150, "icmp eq ptr"))
5344 assert("type-switch recursive call", strings.Count(ir150, "call i32 @mypkg.eval") >= 2)
5345 assert("type-switch no parse error", !strings.Contains(ir150, "parse error"))
5346
5347 irFree(h150)
5348
5349 // Test 151: Verify pointer type switch gets DISTINCT typeids (regression test)
5350 src151 := []byte(`package mypkg
5351
5352 type Animal interface {
5353 Sound() string
5354 }
5355
5356 type Dog struct {
5357 name string
5358 }
5359
5360 type Cat struct {
5361 name string
5362 }
5363
5364 type Bird struct {
5365 name string
5366 }
5367
5368 func (d *Dog) Sound() string { return "woof" }
5369 func (c *Cat) Sound() string { return "meow" }
5370 func (b *Bird) Sound() string { return "tweet" }
5371
5372 func classify(a Animal) int32 {
5373 switch a.(type) {
5374 case *Dog:
5375 return 1
5376 case *Cat:
5377 return 2
5378 case *Bird:
5379 return 3
5380 }
5381 return 0
5382 }
5383 `)
5384 name151 := []byte("mypkg")
5385 h151 := compileToIR(
5386 uintptr(unsafe.Pointer(&src151[0])), int32(len(src151)),
5387 uintptr(unsafe.Pointer(&name151[0])), int32(len(name151)),
5388 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5389 )
5390 ir151 := getIR(h151)
5391 fmt.Println("=== IR for pointer typeids ===")
5392 fmt.Println(ir151)
5393
5394 llvmVerify("pointer typeids", ir151)
5395 assert("ptr-typeid has distinct Dog typeid", strings.Contains(ir151, "typeid.ptr.Dog"))
5396 assert("ptr-typeid has distinct Cat typeid", strings.Contains(ir151, "typeid.ptr.Cat"))
5397 assert("ptr-typeid has distinct Bird typeid", strings.Contains(ir151, "typeid.ptr.Bird"))
5398 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)
5399 assert("ptr-typeid no parse error", !strings.Contains(ir151, "parse error"))
5400
5401 irFree(h151)
5402
5403 // Test 152: Real bootstrap code - irItoa (modulo, division, byte conversion)
5404 src152 := []byte(`package mypkg
5405
5406 func itoa(n int32) string {
5407 if n == 0 {
5408 return "0"
5409 }
5410 buf := []byte{:0:20}
5411 for n > 0 {
5412 buf = append(buf, byte('0' + n % 10))
5413 n = n / 10
5414 }
5415 return string(buf)
5416 }
5417 `)
5418 name152 := []byte("mypkg")
5419 h152 := compileToIR(
5420 uintptr(unsafe.Pointer(&src152[0])), int32(len(src152)),
5421 uintptr(unsafe.Pointer(&name152[0])), int32(len(name152)),
5422 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5423 )
5424 ir152 := getIR(h152)
5425 fmt.Println("=== IR for irItoa ===")
5426 fmt.Println(ir152)
5427
5428 llvmVerify("irItoa", ir152)
5429 assert("itoa has srem (modulo)", strings.Contains(ir152, "srem"))
5430 assert("itoa has sdiv (division)", strings.Contains(ir152, "sdiv"))
5431 assert("itoa no parse error", !strings.Contains(ir152, "parse error"))
5432
5433 irFree(h152)
5434
5435 // Test 153: Real bootstrap code - irEscapeString (string indexing, bit ops)
5436 src153 := []byte(`package mypkg
5437
5438 func escapeStr(s string) string {
5439 var buf []byte
5440 for i := 0; i < len(s); i++ {
5441 c := s[i]
5442 if c >= 32 && c < 127 && c != '\\' && c != '"' {
5443 buf = append(buf, c)
5444 } else {
5445 buf = append(buf, '\\')
5446 buf = append(buf, "0123456789ABCDEF"[c>>4])
5447 buf = append(buf, "0123456789ABCDEF"[c&0xf])
5448 }
5449 }
5450 return string(buf)
5451 }
5452 `)
5453 name153 := []byte("mypkg")
5454 h153 := compileToIR(
5455 uintptr(unsafe.Pointer(&src153[0])), int32(len(src153)),
5456 uintptr(unsafe.Pointer(&name153[0])), int32(len(name153)),
5457 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5458 )
5459 ir153 := getIR(h153)
5460 fmt.Println("=== IR for escapeStr ===")
5461 fmt.Println(ir153)
5462
5463 llvmVerify("escapeStr", ir153)
5464 assert("escape has lshr (>>4)", strings.Contains(ir153, "lshr") || strings.Contains(ir153, "ashr"))
5465 assert("escape has and (&0xf)", strings.Contains(ir153, "and i"))
5466 assert("escape no parse error", !strings.Contains(ir153, "parse error"))
5467
5468 irFree(h153)
5469
5470 // Test 154: Full IRWriter pattern (restored after bisection shows individual parts pass)
5471 src154 := []byte(`package mypkg
5472
5473 type IRWriter struct {
5474 buf []byte
5475 lines []string
5476 seen map[string]int32
5477 }
5478
5479 func (w *IRWriter) emit(s string) {
5480 w.buf = append(w.buf, s...)
5481 }
5482
5483 func (w *IRWriter) newline() {
5484 w.lines = append(w.lines, string(w.buf))
5485 w.buf = w.buf[:0]
5486 }
5487
5488 func (w *IRWriter) writeLine(s string) {
5489 w.emit(s)
5490 w.newline()
5491 }
5492
5493 func itoa154(n int32) string {
5494 if n == 0 {
5495 return "0"
5496 }
5497 neg := n < 0
5498 if neg {
5499 n = -n
5500 }
5501 buf := []byte{:0:20}
5502 for n > 0 {
5503 buf = append(buf, byte('0' + n % 10))
5504 n = n / 10
5505 }
5506 if neg {
5507 buf = append(buf, '-')
5508 }
5509 i := 0
5510 j := int32(len(buf)) - 1
5511 for i < j {
5512 buf[i], buf[j] = buf[j], buf[i]
5513 i = i + 1
5514 j = j - 1
5515 }
5516 return string(buf)
5517 }
5518
5519 func (w *IRWriter) writeInt(n int32) {
5520 w.emit(itoa154(n))
5521 }
5522
5523 func (w *IRWriter) emitDecl(name string, idx int32) {
5524 w.emit("define ")
5525 w.emit(name)
5526 w.emit("(")
5527 w.emit(itoa154(idx))
5528 w.emit(")")
5529 w.newline()
5530 }
5531
5532 func (w *IRWriter) track(key string) {
5533 w.seen[key] = w.seen[key] + 1
5534 }
5535
5536 func (w *IRWriter) count() int32 {
5537 return int32(len(w.lines))
5538 }
5539 `)
5540 name154 := []byte("mypkg")
5541 h154 := compileToIR(
5542 uintptr(unsafe.Pointer(&src154[0])), int32(len(src154)),
5543 uintptr(unsafe.Pointer(&name154[0])), int32(len(name154)),
5544 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5545 )
5546 ir154 := getIR(h154)
5547 fmt.Println("=== IR for Writer+itoa ===")
5548 fmt.Println(ir154)
5549
5550 llvmVerify("IRWriter", ir154)
5551 assert("irwriter has emit method", strings.Contains(ir154, "@mypkg.IRWriter.emit"))
5552 assert("irwriter has writeInt method", strings.Contains(ir154, "@mypkg.IRWriter.writeInt"))
5553 assert("irwriter has emitDecl method", strings.Contains(ir154, "@mypkg.IRWriter.emitDecl"))
5554 assert("irwriter has track method", strings.Contains(ir154, "@mypkg.IRWriter.track"))
5555 assert("itoa154 has srem", strings.Contains(ir154, "srem"))
5556 assert("irwriter no parse error", !strings.Contains(ir154, "parse error"))
5557
5558 irFree(h154)
5559
5560 // Test 155: Real bootstrap pattern - SSA instruction switch dispatch
5561 src155 := []byte(`package mypkg
5562
5563 type Value interface {
5564 valTag()
5565 }
5566
5567 type Const struct {
5568 val int32
5569 }
5570
5571 type Param struct {
5572 name string
5573 idx int32
5574 }
5575
5576 type BinOp struct {
5577 op int32
5578 x Value
5579 y Value
5580 }
5581
5582 func (c *Const) valTag() {}
5583 func (p *Param) valTag() {}
5584 func (b *BinOp) valTag() {}
5585
5586 func operand(v Value) string {
5587 switch v := v.(type) {
5588 case *Const:
5589 return itoa155(v.val)
5590 case *Param:
5591 return "%" | v.name
5592 case *BinOp:
5593 x := operand(v.x)
5594 y := operand(v.y)
5595 switch v.op {
5596 case 0:
5597 return x | " + " | y
5598 case 1:
5599 return x | " - " | y
5600 case 2:
5601 return x | " * " | y
5602 }
5603 return x | " ? " | y
5604 }
5605 return "undef"
5606 }
5607
5608 func itoa155(n int32) string {
5609 if n == 0 {
5610 return "0"
5611 }
5612 buf := []byte{:0:10}
5613 for n > 0 {
5614 buf = append(buf, byte('0' + n % 10))
5615 n = n / 10
5616 }
5617 return string(buf)
5618 }
5619 `)
5620 name155 := []byte("mypkg")
5621 h155 := compileToIR(
5622 uintptr(unsafe.Pointer(&src155[0])), int32(len(src155)),
5623 uintptr(unsafe.Pointer(&name155[0])), int32(len(name155)),
5624 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5625 )
5626 ir155 := getIR(h155)
5627 fmt.Println("=== IR for SSA operand dispatch ===")
5628 fmt.Println(ir155)
5629
5630 llvmVerify("SSA operand dispatch", ir155)
5631 assert("ssa-dispatch has operand", strings.Contains(ir155, "@mypkg.operand"))
5632 assert("ssa-dispatch has typeid Const", strings.Contains(ir155, "typeid.ptr.Const"))
5633 assert("ssa-dispatch has typeid Param", strings.Contains(ir155, "typeid.ptr.Param"))
5634 assert("ssa-dispatch has typeid BinOp", strings.Contains(ir155, "typeid.ptr.BinOp"))
5635 assert("ssa-dispatch recursive operand calls", strings.Count(ir155, "call {ptr, i64, i64} @mypkg.operand") >= 2)
5636 assert("ssa-dispatch has nested switch", strings.Contains(ir155, "icmp eq i32"))
5637 assert("ssa-dispatch no parse error", !strings.Contains(ir155, "parse error"))
5638
5639 irFree(h155)
5640
5641 // Test 156: Nil interface comparison
5642 src156 := []byte(`package mypkg
5643
5644 type Stringer interface {
5645 String() string
5646 }
5647
5648 func isNil(s Stringer) bool {
5649 return s == nil
5650 }
5651
5652 func isNotNil(s Stringer) bool {
5653 return s != nil
5654 }
5655 `)
5656 name156 := []byte("mypkg")
5657 h156 := compileToIR(
5658 uintptr(unsafe.Pointer(&src156[0])), int32(len(src156)),
5659 uintptr(unsafe.Pointer(&name156[0])), int32(len(name156)),
5660 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5661 )
5662 ir156 := getIR(h156)
5663 fmt.Println("=== IR for nil interface ===")
5664 fmt.Println(ir156)
5665
5666 llvmVerify("nil interface", ir156)
5667 assert("nil-iface has isNil", strings.Contains(ir156, "@mypkg.isNil"))
5668 assert("nil-iface has isNotNil", strings.Contains(ir156, "@mypkg.isNotNil"))
5669 assert("nil-iface no parse error", !strings.Contains(ir156, "parse error"))
5670
5671 irFree(h156)
5672
5673 // Test 157: Nil slice comparison
5674 src157 := []byte(`package mypkg
5675
5676 func sliceIsNil(s []int32) bool {
5677 return s == nil
5678 }
5679
5680 func sliceNotNil(s []int32) bool {
5681 return s != nil
5682 }
5683 `)
5684 name157 := []byte("mypkg")
5685 h157 := compileToIR(
5686 uintptr(unsafe.Pointer(&src157[0])), int32(len(src157)),
5687 uintptr(unsafe.Pointer(&name157[0])), int32(len(name157)),
5688 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5689 )
5690 ir157 := getIR(h157)
5691 fmt.Println("=== IR for nil slice ===")
5692 fmt.Println(ir157)
5693
5694 llvmVerify("nil slice", ir157)
5695 assert("nil-slice has sliceIsNil", strings.Contains(ir157, "@mypkg.sliceIsNil"))
5696 assert("nil-slice has sliceNotNil", strings.Contains(ir157, "@mypkg.sliceNotNil"))
5697 assert("nil-slice no parse error", !strings.Contains(ir157, "parse error"))
5698
5699 irFree(h157)
5700
5701 // Test 158: Nested method calls with string concat (emitter pattern)
5702 src158 := []byte(`package mypkg
5703
5704 type Buf struct {
5705 data []byte
5706 }
5707
5708 func (b *Buf) write(s string) {
5709 b.data = append(b.data, s...)
5710 }
5711
5712 func (b *Buf) writeQuoted(s string) {
5713 b.write("\"")
5714 b.write(s)
5715 b.write("\"")
5716 }
5717
5718 func (b *Buf) writeKV(k string, v string) {
5719 b.write(k)
5720 b.write(": ")
5721 b.writeQuoted(v)
5722 b.write("\n")
5723 }
5724
5725 func (b *Buf) result() string {
5726 return string(b.data)
5727 }
5728 `)
5729 name158 := []byte("mypkg")
5730 h158 := compileToIR(
5731 uintptr(unsafe.Pointer(&src158[0])), int32(len(src158)),
5732 uintptr(unsafe.Pointer(&name158[0])), int32(len(name158)),
5733 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5734 )
5735 ir158 := getIR(h158)
5736 fmt.Println("=== IR for Buf methods ===")
5737 fmt.Println(ir158)
5738
5739 llvmVerify("Buf methods", ir158)
5740 assert("buf has write", strings.Contains(ir158, "@mypkg.Buf.write"))
5741 assert("buf has writeQuoted", strings.Contains(ir158, "@mypkg.Buf.writeQuoted"))
5742 assert("buf has writeKV", strings.Contains(ir158, "@mypkg.Buf.writeKV"))
5743 assert("buf has result", strings.Contains(ir158, "@mypkg.Buf.result"))
5744 assert("buf no parse error", !strings.Contains(ir158, "parse error"))
5745
5746 irFree(h158)
5747
5748 // Test 159: Struct with interface field + factory function + method dispatch
5749 src159 := []byte(`package mypkg
5750
5751 type Node interface {
5752 nodeTag()
5753 }
5754
5755 type Literal struct {
5756 val int32
5757 }
5758
5759 type Binary struct {
5760 op int32
5761 left Node
5762 right Node
5763 }
5764
5765 func (l *Literal) nodeTag() {}
5766 func (b *Binary) nodeTag() {}
5767
5768 func newLit(v int32) *Literal {
5769 return &Literal{val: v}
5770 }
5771
5772 func newBin(op int32, l Node, r Node) *Binary {
5773 return &Binary{op: op, left: l, right: r}
5774 }
5775
5776 func depth(n Node) int32 {
5777 switch n := n.(type) {
5778 case *Literal:
5779 return 1
5780 case *Binary:
5781 ld := depth(n.left)
5782 rd := depth(n.right)
5783 if ld > rd {
5784 return ld + 1
5785 }
5786 return rd + 1
5787 }
5788 return 0
5789 }
5790 `)
5791 name159 := []byte("mypkg")
5792 h159 := compileToIR(
5793 uintptr(unsafe.Pointer(&src159[0])), int32(len(src159)),
5794 uintptr(unsafe.Pointer(&name159[0])), int32(len(name159)),
5795 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5796 )
5797 ir159 := getIR(h159)
5798 fmt.Println("=== IR for Node tree ===")
5799 fmt.Println(ir159)
5800
5801 llvmVerify("Node tree", ir159)
5802 assert("node has newLit", strings.Contains(ir159, "@mypkg.newLit"))
5803 assert("node has newBin", strings.Contains(ir159, "@mypkg.newBin"))
5804 assert("node has depth", strings.Contains(ir159, "@mypkg.depth"))
5805 assert("node depth recursive", strings.Count(ir159, "call i32 @mypkg.depth") >= 2)
5806 assert("node distinct typeids", strings.Contains(ir159, "typeid.ptr.Literal") && strings.Contains(ir159, "typeid.ptr.Binary"))
5807 assert("node no parse error", !strings.Contains(ir159, "parse error"))
5808
5809 irFree(h159)
5810
5811 // Test 160: Large struct with many fields (emitter-scale struct)
5812 src160 := []byte(`package mypkg
5813
5814 type Emitter struct {
5815 pkg string
5816 triple string
5817 buf []byte
5818 decls []string
5819 globals map[string]string
5820 types map[string]int32
5821 tempCount int32
5822 indent int32
5823 }
5824
5825 func newEmitter(pkg string, triple string) *Emitter {
5826 return &Emitter{
5827 pkg: pkg,
5828 triple: triple,
5829 globals: map[string]string{},
5830 types: map[string]int32{},
5831 }
5832 }
5833
5834 func (e *Emitter) nextTemp() string {
5835 e.tempCount = e.tempCount + 1
5836 return "%t" | itoa160(e.tempCount)
5837 }
5838
5839 func (e *Emitter) addDecl(s string) {
5840 e.decls = append(e.decls, s)
5841 }
5842
5843 func (e *Emitter) setGlobal(name string, val string) {
5844 e.globals[name] = val
5845 }
5846
5847 func (e *Emitter) hasType(name string) bool {
5848 _, ok := e.types[name]
5849 return ok
5850 }
5851
5852 func itoa160(n int32) string {
5853 if n == 0 {
5854 return "0"
5855 }
5856 buf := []byte{:0:10}
5857 for n > 0 {
5858 buf = append(buf, byte('0' + n % 10))
5859 n = n / 10
5860 }
5861 return string(buf)
5862 }
5863 `)
5864 name160 := []byte("mypkg")
5865 h160 := compileToIR(
5866 uintptr(unsafe.Pointer(&src160[0])), int32(len(src160)),
5867 uintptr(unsafe.Pointer(&name160[0])), int32(len(name160)),
5868 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5869 )
5870 ir160 := getIR(h160)
5871 fmt.Println("=== IR for Emitter struct ===")
5872 fmt.Println(ir160)
5873
5874 llvmVerify("Emitter struct", ir160)
5875 assert("emitter has newEmitter", strings.Contains(ir160, "@mypkg.newEmitter"))
5876 assert("emitter has nextTemp", strings.Contains(ir160, "@mypkg.Emitter.nextTemp"))
5877 assert("emitter has addDecl", strings.Contains(ir160, "@mypkg.Emitter.addDecl"))
5878 assert("emitter has setGlobal", strings.Contains(ir160, "@mypkg.Emitter.setGlobal"))
5879 assert("emitter has hasType", strings.Contains(ir160, "@mypkg.Emitter.hasType"))
5880 assert("emitter no parse error", !strings.Contains(ir160, "parse error"))
5881
5882 irFree(h160)
5883
5884 // Test 161: Closure-like pattern (function variable in struct)
5885 src161 := []byte(`package mypkg
5886
5887 type Handler struct {
5888 name string
5889 fn func(string) string
5890 }
5891
5892 func identity(s string) string {
5893 return s
5894 }
5895
5896 func upper(s string) string {
5897 return s
5898 }
5899
5900 func newHandler(name string) *Handler {
5901 return &Handler{name: name, fn: identity}
5902 }
5903
5904 func (h *Handler) setFn(f func(string) string) {
5905 h.fn = f
5906 }
5907
5908 func (h *Handler) run(input string) string {
5909 return h.fn(input)
5910 }
5911 `)
5912 name161 := []byte("mypkg")
5913 h161 := compileToIR(
5914 uintptr(unsafe.Pointer(&src161[0])), int32(len(src161)),
5915 uintptr(unsafe.Pointer(&name161[0])), int32(len(name161)),
5916 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5917 )
5918 ir161 := getIR(h161)
5919 fmt.Println("=== IR for func var ===")
5920 fmt.Println(ir161)
5921
5922 llvmVerify("func var", ir161)
5923 assert("funcvar has newHandler", strings.Contains(ir161, "@mypkg.newHandler"))
5924 assert("funcvar has run method", strings.Contains(ir161, "@mypkg.Handler.run"))
5925 assert("funcvar no parse error", !strings.Contains(ir161, "parse error"))
5926
5927 irFree(h161)
5928
5929 // Test 162: Map iteration (range over map)
5930 src162 := []byte(`package mypkg
5931
5932 func sumMap(m map[string]int32) int32 {
5933 total := int32(0)
5934 for _, v := range m {
5935 total = total + v
5936 }
5937 return total
5938 }
5939
5940 func keys(m map[string]int32) []string {
5941 var result []string
5942 for k := range m {
5943 result = append(result, k)
5944 }
5945 return result
5946 }
5947 `)
5948 name162 := []byte("mypkg")
5949 h162 := compileToIR(
5950 uintptr(unsafe.Pointer(&src162[0])), int32(len(src162)),
5951 uintptr(unsafe.Pointer(&name162[0])), int32(len(name162)),
5952 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
5953 )
5954 ir162 := getIR(h162)
5955 fmt.Println("=== IR for map iteration ===")
5956 fmt.Println(ir162)
5957
5958 llvmVerify("map iteration", ir162)
5959 assert("mapiter has sumMap", strings.Contains(ir162, "@mypkg.sumMap"))
5960 assert("mapiter has keys", strings.Contains(ir162, "@mypkg.keys"))
5961 assert("mapiter uses hashmapNext", strings.Contains(ir162, "hashmapNext") || strings.Contains(ir162, "hashmapBinaryNext"))
5962 assert("mapiter no parse error", !strings.Contains(ir162, "parse error"))
5963
5964 irFree(h162)
5965
5966 // Test 163: Multi-level type switch with method calls (ir_emit pattern)
5967 src163 := []byte(`package mypkg
5968
5969 type Type interface {
5970 typeTag()
5971 }
5972
5973 type BasicType struct {
5974 kind int32
5975 }
5976
5977 type SliceType struct {
5978 elem Type
5979 }
5980
5981 type PointerType struct {
5982 elem Type
5983 }
5984
5985 type StructType struct {
5986 fields []Type
5987 }
5988
5989 func (b *BasicType) typeTag() {}
5990 func (s *SliceType) typeTag() {}
5991 func (p *PointerType) typeTag() {}
5992 func (s *StructType) typeTag() {}
5993
5994 func typeSize(t Type) int32 {
5995 switch t := t.(type) {
5996 case *BasicType:
5997 switch t.kind {
5998 case 0:
5999 return 1
6000 case 1:
6001 return 4
6002 case 2:
6003 return 8
6004 }
6005 return 0
6006 case *SliceType:
6007 return 24
6008 case *PointerType:
6009 return 8
6010 case *StructType:
6011 total := int32(0)
6012 for _, f := range t.fields {
6013 total = total + typeSize(f)
6014 }
6015 return total
6016 }
6017 return 0
6018 }
6019
6020 func typeName(t Type) string {
6021 switch t := t.(type) {
6022 case *BasicType:
6023 switch t.kind {
6024 case 0:
6025 return "i8"
6026 case 1:
6027 return "i32"
6028 case 2:
6029 return "i64"
6030 }
6031 return "void"
6032 case *SliceType:
6033 return "[]" | typeName(t.elem)
6034 case *PointerType:
6035 return "*" | typeName(t.elem)
6036 case *StructType:
6037 return "struct"
6038 }
6039 return "unknown"
6040 }
6041 `)
6042 name163 := []byte("mypkg")
6043 h163 := compileToIR(
6044 uintptr(unsafe.Pointer(&src163[0])), int32(len(src163)),
6045 uintptr(unsafe.Pointer(&name163[0])), int32(len(name163)),
6046 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6047 )
6048 ir163 := getIR(h163)
6049 fmt.Println("=== IR for type system ===")
6050 fmt.Println(ir163)
6051
6052 llvmVerify("type system", ir163)
6053 assert("typesys has typeSize", strings.Contains(ir163, "@mypkg.typeSize"))
6054 assert("typesys has typeName", strings.Contains(ir163, "@mypkg.typeName"))
6055 assert("typesys has 4 distinct typeids",
6056 strings.Contains(ir163, "typeid.ptr.BasicType") &&
6057 strings.Contains(ir163, "typeid.ptr.SliceType") &&
6058 strings.Contains(ir163, "typeid.ptr.PointerType") &&
6059 strings.Contains(ir163, "typeid.ptr.StructType"))
6060 assert("typesys typeSize recursive", strings.Count(ir163, "call i32 @mypkg.typeSize") >= 1)
6061 assert("typesys typeName recursive", strings.Count(ir163, "call {ptr, i64, i64} @mypkg.typeName") >= 1)
6062 assert("typesys no parse error", !strings.Contains(ir163, "parse error"))
6063
6064 irFree(h163)
6065
6066 // Test 164: String building with map lookup (ir_emit core pattern)
6067 src164 := []byte(`package mypkg
6068
6069 type IRGen struct {
6070 regs map[string]string
6071 buf []byte
6072 n int32
6073 }
6074
6075 func (g *IRGen) fresh(prefix string) string {
6076 g.n = g.n + 1
6077 return prefix | itoa164(g.n)
6078 }
6079
6080 func (g *IRGen) emit(s string) {
6081 g.buf = append(g.buf, s...)
6082 }
6083
6084 func (g *IRGen) emitLine(parts []string) {
6085 for i := 0; i < len(parts); i++ {
6086 g.emit(parts[i])
6087 }
6088 g.emit("\n")
6089 }
6090
6091 func (g *IRGen) setReg(name string, val string) {
6092 g.regs[name] = val
6093 }
6094
6095 func (g *IRGen) getReg(name string) string {
6096 v, ok := g.regs[name]
6097 if !ok {
6098 return "undef"
6099 }
6100 return v
6101 }
6102
6103 func itoa164(n int32) string {
6104 if n == 0 {
6105 return "0"
6106 }
6107 buf := []byte{:0:10}
6108 for n > 0 {
6109 buf = append(buf, byte('0' + n % 10))
6110 n = n / 10
6111 }
6112 i := 0
6113 j := int32(len(buf)) - 1
6114 for i < j {
6115 buf[i], buf[j] = buf[j], buf[i]
6116 i = i + 1
6117 j = j - 1
6118 }
6119 return string(buf)
6120 }
6121 `)
6122 name164 := []byte("mypkg")
6123 h164 := compileToIR(
6124 uintptr(unsafe.Pointer(&src164[0])), int32(len(src164)),
6125 uintptr(unsafe.Pointer(&name164[0])), int32(len(name164)),
6126 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6127 )
6128 ir164 := getIR(h164)
6129 fmt.Println("=== IR for IRGen ===")
6130 fmt.Println(ir164)
6131
6132 llvmVerify("IRGen", ir164)
6133 assert("irgen has fresh", strings.Contains(ir164, "@mypkg.IRGen.fresh"))
6134 assert("irgen has emit", strings.Contains(ir164, "@mypkg.IRGen.emit"))
6135 assert("irgen has emitLine", strings.Contains(ir164, "@mypkg.IRGen.emitLine"))
6136 assert("irgen has getReg with ok check", strings.Contains(ir164, "@mypkg.IRGen.getReg"))
6137 assert("irgen no parse error", !strings.Contains(ir164, "parse error"))
6138
6139 irFree(h164)
6140
6141 // Test 165: Cross-package calls inside type switch (compile pattern)
6142 clearImports()
6143 regPkg("ext/types", "types")
6144 regFn("ext/types", "BasicSize", "int32->int32")
6145 regFn("ext/types", "SliceSize", "->int32")
6146 src165 := []byte(`package mypkg
6147
6148 import "ext/types"
6149
6150 type Typ interface {
6151 tag()
6152 }
6153
6154 type Basic165 struct {
6155 kind int32
6156 }
6157
6158 type Slice165 struct {
6159 elem Typ
6160 }
6161
6162 func (b *Basic165) tag() {}
6163 func (s *Slice165) tag() {}
6164
6165 func size(t Typ) int32 {
6166 switch t := t.(type) {
6167 case *Basic165:
6168 return types.BasicSize(t.kind)
6169 case *Slice165:
6170 return types.SliceSize()
6171 }
6172 return 0
6173 }
6174 `)
6175 name165 := []byte("mypkg")
6176 h165 := compileToIR(
6177 uintptr(unsafe.Pointer(&src165[0])), int32(len(src165)),
6178 uintptr(unsafe.Pointer(&name165[0])), int32(len(name165)),
6179 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6180 )
6181 ir165 := getIR(h165)
6182 fmt.Println("=== IR for cross-pkg type switch ===")
6183 fmt.Println(ir165)
6184
6185 llvmVerify("cross-pkg type switch", ir165)
6186 assert("xpkg-tswitch has size func", strings.Contains(ir165, "@mypkg.size"))
6187 assert("xpkg-tswitch calls BasicSize", strings.Contains(ir165, "BasicSize"))
6188 assert("xpkg-tswitch calls SliceSize", strings.Contains(ir165, "SliceSize"))
6189 assert("xpkg-tswitch no parse error", !strings.Contains(ir165, "parse error"))
6190
6191 irFree(h165)
6192 clearImports()
6193
6194 // Test 166: Multiple return values from method
6195 src166 := []byte(`package mypkg
6196
6197 type Scanner struct {
6198 src []byte
6199 pos int32
6200 }
6201
6202 func (s *Scanner) peek() (byte, bool) {
6203 if int32(s.pos) >= int32(len(s.src)) {
6204 return 0, false
6205 }
6206 return s.src[s.pos], true
6207 }
6208
6209 func (s *Scanner) advance() byte {
6210 ch, ok := s.peek()
6211 if !ok {
6212 return 0
6213 }
6214 s.pos = s.pos + 1
6215 return ch
6216 }
6217
6218 func (s *Scanner) skipWhile(ch byte) {
6219 for {
6220 c, ok := s.peek()
6221 if !ok || c != ch {
6222 return
6223 }
6224 s.pos = s.pos + 1
6225 }
6226 }
6227 `)
6228 name166 := []byte("mypkg")
6229 h166 := compileToIR(
6230 uintptr(unsafe.Pointer(&src166[0])), int32(len(src166)),
6231 uintptr(unsafe.Pointer(&name166[0])), int32(len(name166)),
6232 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6233 )
6234 ir166 := getIR(h166)
6235 fmt.Println("=== IR for Scanner ===")
6236 fmt.Println(ir166)
6237
6238 llvmVerify("Scanner", ir166)
6239 assert("scanner has peek", strings.Contains(ir166, "@mypkg.Scanner.peek"))
6240 assert("scanner has advance", strings.Contains(ir166, "@mypkg.Scanner.advance"))
6241 assert("scanner has skipWhile", strings.Contains(ir166, "@mypkg.Scanner.skipWhile"))
6242 assert("scanner peek returns tuple", strings.Contains(ir166, "{i8, i1}"))
6243 assert("scanner advance calls peek", strings.Contains(ir166, "call {i8, i1} @mypkg.Scanner.peek"))
6244 assert("scanner no parse error", !strings.Contains(ir166, "parse error"))
6245
6246 irFree(h166)
6247
6248 // Test 167: Repeated short method calls (w() pattern from ir_emit)
6249 src167 := []byte(`package mypkg
6250
6251 type Builder struct {
6252 buf []byte
6253 }
6254
6255 func (b *Builder) w(s string) {
6256 b.buf = append(b.buf, s...)
6257 }
6258
6259 func (b *Builder) emitAdd(dst string, ty string, lhs string, rhs string) {
6260 b.w(" ")
6261 b.w(dst)
6262 b.w(" = add ")
6263 b.w(ty)
6264 b.w(" ")
6265 b.w(lhs)
6266 b.w(", ")
6267 b.w(rhs)
6268 b.w("\n")
6269 }
6270
6271 func (b *Builder) emitStore(ty string, val string, ptr string) {
6272 b.w(" store ")
6273 b.w(ty)
6274 b.w(" ")
6275 b.w(val)
6276 b.w(", ptr ")
6277 b.w(ptr)
6278 b.w("\n")
6279 }
6280
6281 func (b *Builder) emitRet(ty string, val string) {
6282 b.w(" ret ")
6283 b.w(ty)
6284 b.w(" ")
6285 b.w(val)
6286 b.w("\n")
6287 }
6288
6289 func (b *Builder) result() string {
6290 return string(b.buf)
6291 }
6292 `)
6293 name167 := []byte("mypkg")
6294 h167 := compileToIR(
6295 uintptr(unsafe.Pointer(&src167[0])), int32(len(src167)),
6296 uintptr(unsafe.Pointer(&name167[0])), int32(len(name167)),
6297 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6298 )
6299 ir167 := getIR(h167)
6300 fmt.Println("=== IR for Builder w() ===")
6301 fmt.Println(ir167)
6302
6303 llvmVerify("Builder w()", ir167)
6304 assert("builder has w method", strings.Contains(ir167, "@mypkg.Builder.w"))
6305 assert("builder has emitAdd", strings.Contains(ir167, "@mypkg.Builder.emitAdd"))
6306 assert("builder has emitStore", strings.Contains(ir167, "@mypkg.Builder.emitStore"))
6307 assert("builder has emitRet", strings.Contains(ir167, "@mypkg.Builder.emitRet"))
6308 assert("builder emitAdd calls w many times", strings.Count(ir167, "call void @mypkg.Builder.w") >= 10)
6309 assert("builder no parse error", !strings.Contains(ir167, "parse error"))
6310
6311 irFree(h167)
6312
6313 // Test 168: Nested struct access + interface field (SSA node pattern)
6314 src168 := []byte(`package mypkg
6315
6316 type Pos struct {
6317 line int32
6318 col int32
6319 }
6320
6321 type Token struct {
6322 kind int32
6323 pos Pos
6324 text string
6325 }
6326
6327 type ASTNode interface {
6328 astTag()
6329 }
6330
6331 type ExprStmt struct {
6332 pos Pos
6333 expr ASTNode
6334 }
6335
6336 type ReturnStmt struct {
6337 pos Pos
6338 result ASTNode
6339 }
6340
6341 func (e *ExprStmt) astTag() {}
6342 func (r *ReturnStmt) astTag() {}
6343
6344 func stmtLine(n ASTNode) int32 {
6345 switch n := n.(type) {
6346 case *ExprStmt:
6347 return n.pos.line
6348 case *ReturnStmt:
6349 return n.pos.line
6350 }
6351 return 0
6352 }
6353
6354 func stmtCol(n ASTNode) int32 {
6355 switch n := n.(type) {
6356 case *ExprStmt:
6357 return n.pos.col
6358 case *ReturnStmt:
6359 return n.pos.col
6360 }
6361 return 0
6362 }
6363 `)
6364 name168 := []byte("mypkg")
6365 h168 := compileToIR(
6366 uintptr(unsafe.Pointer(&src168[0])), int32(len(src168)),
6367 uintptr(unsafe.Pointer(&name168[0])), int32(len(name168)),
6368 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6369 )
6370 ir168 := getIR(h168)
6371 fmt.Println("=== IR for AST nodes ===")
6372 fmt.Println(ir168)
6373
6374 llvmVerify("AST nodes", ir168)
6375 assert("ast has stmtLine", strings.Contains(ir168, "@mypkg.stmtLine"))
6376 assert("ast has stmtCol", strings.Contains(ir168, "@mypkg.stmtCol"))
6377 assert("ast nested field getelementptr", strings.Count(ir168, "getelementptr") >= 4)
6378 assert("ast no parse error", !strings.Contains(ir168, "parse error"))
6379
6380 irFree(h168)
6381
6382 // Test 169: Struct embedding - basic field access through embedded struct
6383 src169 := []byte(`package mypkg
6384
6385 type base struct {
6386 name string
6387 val int32
6388 }
6389
6390 func (b *base) Name() string { return b.name }
6391 func (b *base) Val() int32 { return b.val }
6392
6393 type Derived struct {
6394 base
6395 extra int32
6396 }
6397
6398 func newDerived(name string, val int32, extra int32) *Derived {
6399 return &Derived{base: base{name: name, val: val}, extra: extra}
6400 }
6401
6402 func getName(d *Derived) string {
6403 return d.Name()
6404 }
6405
6406 func getVal(d *Derived) int32 {
6407 return d.Val()
6408 }
6409 `)
6410 name169 := []byte("mypkg")
6411 h169 := compileToIR(
6412 uintptr(unsafe.Pointer(&src169[0])), int32(len(src169)),
6413 uintptr(unsafe.Pointer(&name169[0])), int32(len(name169)),
6414 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6415 )
6416 ir169 := getIR(h169)
6417 fmt.Println("=== IR for struct embedding ===")
6418 fmt.Println(ir169)
6419
6420 if ir169 == "" || strings.Contains(ir169, "parse error") {
6421 fmt.Println("NOTE: struct embedding may not be supported yet")
6422 assert("embedding produces IR", ir169 != "")
6423 } else {
6424 llvmVerify("struct embedding", ir169)
6425 assert("embed has newDerived", strings.Contains(ir169, "@mypkg.newDerived"))
6426 assert("embed has getName", strings.Contains(ir169, "@mypkg.getName"))
6427 assert("embed has base.Name method", strings.Contains(ir169, "@mypkg.base.Name"))
6428 assert("embed no parse error", !strings.Contains(ir169, "parse error"))
6429 }
6430
6431 irFree(h169)
6432
6433 // Test 170: Embedded field direct access (d.name -> base.name)
6434 src170 := []byte(`package mypkg
6435
6436 type inner struct {
6437 x int32
6438 y int32
6439 }
6440
6441 type Outer struct {
6442 inner
6443 z int32
6444 }
6445
6446 func sumOuter(o *Outer) int32 {
6447 return o.x + o.y + o.z
6448 }
6449
6450 func setX(o *Outer, v int32) {
6451 o.x = v
6452 }
6453 `)
6454 name170 := []byte("mypkg")
6455 h170 := compileToIR(
6456 uintptr(unsafe.Pointer(&src170[0])), int32(len(src170)),
6457 uintptr(unsafe.Pointer(&name170[0])), int32(len(name170)),
6458 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6459 )
6460 ir170 := getIR(h170)
6461 fmt.Println("=== IR for embedded field access ===")
6462 fmt.Println(ir170)
6463
6464 llvmVerify("embedded field access", ir170)
6465 assert("embed-field has sumOuter", strings.Contains(ir170, "@mypkg.sumOuter"))
6466 assert("embed-field has setX", strings.Contains(ir170, "@mypkg.setX"))
6467 assert("embed-field accesses nested field (two GEPs)", strings.Count(ir170, "getelementptr") >= 4)
6468 assert("embed-field no parse error", !strings.Contains(ir170, "parse error"))
6469
6470 irFree(h170)
6471
6472 // Test 171: Interface satisfaction via embedded methods (tc_object pattern)
6473 src171 := []byte(`package mypkg
6474
6475 type Named interface {
6476 GetName() string
6477 GetKind() int32
6478 }
6479
6480 type baseObj struct {
6481 name string
6482 kind int32
6483 }
6484
6485 func (b *baseObj) GetName() string { return b.name }
6486 func (b *baseObj) GetKind() int32 { return b.kind }
6487
6488 type TypeObj struct {
6489 baseObj
6490 extra bool
6491 }
6492
6493 type FuncObj struct {
6494 baseObj
6495 sig string
6496 }
6497
6498 func classify(n Named) string {
6499 switch n.(type) {
6500 case *TypeObj:
6501 return "type"
6502 case *FuncObj:
6503 return "func"
6504 }
6505 return "unknown"
6506 }
6507
6508 func describe(n Named) string {
6509 return n.GetName() | ":" | itoa171(n.GetKind())
6510 }
6511
6512 func itoa171(n int32) string {
6513 if n == 0 {
6514 return "0"
6515 }
6516 buf := []byte{:0:10}
6517 for n > 0 {
6518 buf = append(buf, byte('0' + n % 10))
6519 n = n / 10
6520 }
6521 return string(buf)
6522 }
6523 `)
6524 name171 := []byte("mypkg")
6525 h171 := compileToIR(
6526 uintptr(unsafe.Pointer(&src171[0])), int32(len(src171)),
6527 uintptr(unsafe.Pointer(&name171[0])), int32(len(name171)),
6528 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6529 )
6530 ir171 := getIR(h171)
6531 fmt.Println("=== IR for interface via embedding ===")
6532 fmt.Println(ir171)
6533
6534 llvmVerify("interface via embedding", ir171)
6535 assert("iface-embed has classify", strings.Contains(ir171, "@mypkg.classify"))
6536 assert("iface-embed has describe", strings.Contains(ir171, "@mypkg.describe"))
6537 assert("iface-embed has TypeObj typeid", strings.Contains(ir171, "typeid.ptr.TypeObj"))
6538 assert("iface-embed has FuncObj typeid", strings.Contains(ir171, "typeid.ptr.FuncObj"))
6539 assert("iface-embed no parse error", !strings.Contains(ir171, "parse error"))
6540
6541 irFree(h171)
6542
6543 // Test 172: Map with interface values + nil return (tc_scope pattern)
6544 src172 := []byte(`package mypkg
6545
6546 type Entry interface {
6547 Key() string
6548 }
6549
6550 type StrEntry struct {
6551 key string
6552 val string
6553 }
6554
6555 func (e *StrEntry) Key() string { return e.key }
6556
6557 type Table struct {
6558 elems map[string]Entry
6559 }
6560
6561 func newTable() *Table {
6562 return &Table{elems: map[string]Entry{}}
6563 }
6564
6565 func (t *Table) get(name string) Entry {
6566 return t.elems[name]
6567 }
6568
6569 func (t *Table) set(e Entry) {
6570 t.elems[e.Key()] = e
6571 }
6572
6573 func (t *Table) has(name string) bool {
6574 _, ok := t.elems[name]
6575 return ok
6576 }
6577 `)
6578 name172 := []byte("mypkg")
6579 h172 := compileToIR(
6580 uintptr(unsafe.Pointer(&src172[0])), int32(len(src172)),
6581 uintptr(unsafe.Pointer(&name172[0])), int32(len(name172)),
6582 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6583 )
6584 ir172 := getIR(h172)
6585 fmt.Println("=== IR for map[string]interface ===")
6586 fmt.Println(ir172)
6587
6588 llvmVerify("map[string]interface", ir172)
6589 assert("map-iface has newTable", strings.Contains(ir172, "@mypkg.newTable"))
6590 assert("map-iface has get method", strings.Contains(ir172, "@mypkg.Table.get"))
6591 assert("map-iface has set method", strings.Contains(ir172, "@mypkg.Table.set"))
6592 assert("map-iface has has method", strings.Contains(ir172, "@mypkg.Table.has"))
6593 assert("map-iface no parse error", !strings.Contains(ir172, "parse error"))
6594
6595 irFree(h172)
6596
6597 // Test 173: Pointer chain walking with nil check (tc_scope.LookupParent pattern)
6598 src173 := []byte(`package mypkg
6599
6600 type Chain struct {
6601 parent *Chain
6602 name string
6603 val int32
6604 }
6605
6606 func walk(c *Chain, target string) int32 {
6607 for s := c; s != nil; s = s.parent {
6608 if s.name == target {
6609 return s.val
6610 }
6611 }
6612 return -1
6613 }
6614
6615 func depth(c *Chain) int32 {
6616 n := int32(0)
6617 for s := c; s != nil; s = s.parent {
6618 n = n + 1
6619 }
6620 return n
6621 }
6622 `)
6623 name173 := []byte("mypkg")
6624 h173 := compileToIR(
6625 uintptr(unsafe.Pointer(&src173[0])), int32(len(src173)),
6626 uintptr(unsafe.Pointer(&name173[0])), int32(len(name173)),
6627 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6628 )
6629 ir173 := getIR(h173)
6630 fmt.Println("=== IR for pointer chain walk ===")
6631 fmt.Println(ir173)
6632
6633 llvmVerify("pointer chain walk", ir173)
6634 assert("chain has walk", strings.Contains(ir173, "@mypkg.walk"))
6635 assert("chain has depth", strings.Contains(ir173, "@mypkg.depth"))
6636 assert("chain has null comparison", strings.Contains(ir173, "icmp") && strings.Contains(ir173, "null"))
6637 assert("chain no parse error", !strings.Contains(ir173, "parse error"))
6638
6639 irFree(h173)
6640
6641 // Test 174: Full tc_scope pattern with concrete types
6642 src174 := []byte(`package mypkg
6643
6644 type Object interface {
6645 Name() string
6646 }
6647
6648 type SimpleObj struct {
6649 name string
6650 }
6651
6652 func (o *SimpleObj) Name() string { return o.name }
6653
6654 type Scope struct {
6655 parent *Scope
6656 elems map[string]Object
6657 }
6658
6659 func NewScope(parent *Scope) *Scope {
6660 return &Scope{parent: parent, elems: map[string]Object{}}
6661 }
6662
6663 func (s *Scope) Parent() *Scope { return s.parent }
6664 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
6665
6666 func (s *Scope) Lookup(name string) Object {
6667 return s.elems[name]
6668 }
6669
6670 func (s *Scope) LookupParent(name string) (*Scope, Object) {
6671 for sc := s; sc != nil; sc = sc.parent {
6672 if obj, ok := sc.elems[name]; ok {
6673 return sc, obj
6674 }
6675 }
6676 return nil, nil
6677 }
6678
6679 func (s *Scope) Insert(obj Object) Object {
6680 name := obj.Name()
6681 if alt, ok := s.elems[name]; ok {
6682 return alt
6683 }
6684 s.elems[name] = obj
6685 return nil
6686 }
6687
6688 func (s *Scope) Names() []string {
6689 names := []string{:0:len(s.elems)}
6690 for n := range s.elems {
6691 names = append(names, n)
6692 }
6693 return names
6694 }
6695 `)
6696 name174 := []byte("mypkg")
6697 h174 := compileToIR(
6698 uintptr(unsafe.Pointer(&src174[0])), int32(len(src174)),
6699 uintptr(unsafe.Pointer(&name174[0])), int32(len(name174)),
6700 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6701 )
6702 ir174 := getIR(h174)
6703 fmt.Println("=== IR for Scope ===")
6704 fmt.Println(ir174)
6705
6706 if ir174 == "" {
6707 assert("scope produces IR", false)
6708 } else {
6709 llvmVerify("Scope", ir174)
6710 assert("scope has NewScope", strings.Contains(ir174, "@mypkg.NewScope"))
6711 assert("scope has Lookup", strings.Contains(ir174, "@mypkg.Scope.Lookup"))
6712 assert("scope has LookupParent", strings.Contains(ir174, "@mypkg.Scope.LookupParent"))
6713 assert("scope has Insert", strings.Contains(ir174, "@mypkg.Scope.Insert"))
6714 assert("scope has Names", strings.Contains(ir174, "@mypkg.Scope.Names"))
6715 assert("scope Insert calls Name via invoke", strings.Contains(ir174, "call {ptr, i64, i64} @mypkg.SimpleObj.Name"))
6716 assert("scope no parse error", !strings.Contains(ir174, "parse error"))
6717 }
6718
6719 irFree(h174)
6720
6721 // Test 175: tc_object pattern - Object hierarchy with embedding
6722 src175 := []byte(`package mypkg
6723
6724 type Type interface {
6725 typeTag()
6726 }
6727
6728 type BasicType175 struct {
6729 kind int32
6730 }
6731
6732 func (b *BasicType175) typeTag() {}
6733
6734 type Pkg175 struct {
6735 path string
6736 name string
6737 }
6738
6739 type Object interface {
6740 Name() string
6741 ObjType() Type
6742 ObjPkg() *Pkg175
6743 Exported() bool
6744 }
6745
6746 type object175 struct {
6747 pkg *Pkg175
6748 name string
6749 typ Type
6750 }
6751
6752 func (o *object175) Name() string { return o.name }
6753 func (o *object175) ObjType() Type { return o.typ }
6754 func (o *object175) ObjPkg() *Pkg175 { return o.pkg }
6755 func (o *object175) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
6756
6757 type TypeName175 struct {
6758 object175
6759 }
6760
6761 func NewTypeName175(pkg *Pkg175, name string, typ Type) *TypeName175 {
6762 return &TypeName175{object175{pkg: pkg, name: name, typ: typ}}
6763 }
6764
6765 func (o *TypeName175) String() string { return "type " | o.name }
6766
6767 type FuncObj175 struct {
6768 object175
6769 ptrRecv bool
6770 }
6771
6772 func NewFuncObj175(pkg *Pkg175, name string) *FuncObj175 {
6773 return &FuncObj175{object175: object175{pkg: pkg, name: name}}
6774 }
6775
6776 func (o *FuncObj175) HasPtrRecv() bool { return o.ptrRecv }
6777 func (o *FuncObj175) String() string { return "func " | o.name }
6778
6779 func classify175(obj Object) string {
6780 switch obj.(type) {
6781 case *TypeName175:
6782 return "type"
6783 case *FuncObj175:
6784 return "func"
6785 }
6786 return "unknown"
6787 }
6788 `)
6789 name175 := []byte("mypkg")
6790 h175 := compileToIR(
6791 uintptr(unsafe.Pointer(&src175[0])), int32(len(src175)),
6792 uintptr(unsafe.Pointer(&name175[0])), int32(len(name175)),
6793 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6794 )
6795 ir175 := getIR(h175)
6796 fmt.Println("=== IR for tc_object ===")
6797 fmt.Println(ir175)
6798
6799 if ir175 == "" {
6800 assert("tc_object produces IR", false)
6801 } else {
6802 llvmVerify("tc_object", ir175)
6803 assert("obj has NewTypeName175", strings.Contains(ir175, "@mypkg.NewTypeName175"))
6804 assert("obj has NewFuncObj175", strings.Contains(ir175, "@mypkg.NewFuncObj175"))
6805 assert("obj has classify175", strings.Contains(ir175, "@mypkg.classify175"))
6806 assert("obj has Exported method", strings.Contains(ir175, "@mypkg.object175.Exported"))
6807 assert("obj TypeName175 typeid", strings.Contains(ir175, "typeid.ptr.TypeName175"))
6808 assert("obj FuncObj175 typeid", strings.Contains(ir175, "typeid.ptr.FuncObj175"))
6809 assert("obj no parse error", !strings.Contains(ir175, "parse error"))
6810 }
6811
6812 irFree(h175)
6813
6814 // Test 176: Combined Scope + Object pattern (tc_scope + tc_object together)
6815 src176 := []byte(`package mypkg
6816
6817 type Type176 interface {
6818 typeTag()
6819 }
6820
6821 type Object176 interface {
6822 Name() string
6823 }
6824
6825 type obj176 struct {
6826 name string
6827 }
6828
6829 func (o *obj176) Name() string { return o.name }
6830
6831 type VarObj176 struct {
6832 obj176
6833 typ Type176
6834 }
6835
6836 type ConstObj176 struct {
6837 obj176
6838 val int32
6839 }
6840
6841 type Scope176 struct {
6842 parent *Scope176
6843 elems map[string]Object176
6844 }
6845
6846 func NewScope176(parent *Scope176) *Scope176 {
6847 return &Scope176{parent: parent, elems: map[string]Object176{}}
6848 }
6849
6850 func (s *Scope176) Insert(obj Object176) Object176 {
6851 name := obj.Name()
6852 if alt, ok := s.elems[name]; ok {
6853 return alt
6854 }
6855 s.elems[name] = obj
6856 return nil
6857 }
6858
6859 func (s *Scope176) Lookup(name string) Object176 {
6860 return s.elems[name]
6861 }
6862
6863 func (s *Scope176) LookupParent(name string) (*Scope176, Object176) {
6864 for sc := s; sc != nil; sc = sc.parent {
6865 if obj, ok := sc.elems[name]; ok {
6866 return sc, obj
6867 }
6868 }
6869 return nil, nil
6870 }
6871
6872 func (s *Scope176) Len() int32 {
6873 return int32(len(s.elems))
6874 }
6875
6876 func classifyObj176(obj Object176) string {
6877 switch obj.(type) {
6878 case *VarObj176:
6879 return "var"
6880 case *ConstObj176:
6881 return "const"
6882 }
6883 return "unknown"
6884 }
6885 `)
6886 name176 := []byte("mypkg")
6887 h176 := compileToIR(
6888 uintptr(unsafe.Pointer(&src176[0])), int32(len(src176)),
6889 uintptr(unsafe.Pointer(&name176[0])), int32(len(name176)),
6890 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6891 )
6892 ir176 := getIR(h176)
6893 fmt.Println("=== IR for scope+object ===")
6894 fmt.Println(ir176)
6895
6896 if ir176 == "" {
6897 assert("scope+object produces IR", false)
6898 } else {
6899 llvmVerify("scope+object", ir176)
6900 assert("so has NewScope176", strings.Contains(ir176, "@mypkg.NewScope176"))
6901 assert("so has Insert", strings.Contains(ir176, "@mypkg.Scope176.Insert"))
6902 assert("so has LookupParent", strings.Contains(ir176, "@mypkg.Scope176.LookupParent"))
6903 assert("so has classifyObj176", strings.Contains(ir176, "@mypkg.classifyObj176"))
6904 assert("so has hashmapLen", strings.Contains(ir176, "hashmapLen"))
6905 assert("so VarObj176 typeid", strings.Contains(ir176, "typeid.ptr.VarObj176"))
6906 assert("so ConstObj176 typeid", strings.Contains(ir176, "typeid.ptr.ConstObj176"))
6907 assert("so no parse error", !strings.Contains(ir176, "parse error"))
6908 }
6909
6910 irFree(h176)
6911
6912 // Test 177: Scanner pattern (tc_scanner core loop)
6913 src177 := []byte(`package mypkg
6914
6915 type Scanner177 struct {
6916 src []byte
6917 pos int32
6918 line int32
6919 col int32
6920 }
6921
6922 func NewScanner177(src []byte) *Scanner177 {
6923 return &Scanner177{src: src, line: 1, col: 1}
6924 }
6925
6926 func (s *Scanner177) peek() byte {
6927 if s.pos >= int32(len(s.src)) {
6928 return 0
6929 }
6930 return s.src[s.pos]
6931 }
6932
6933 func (s *Scanner177) next() byte {
6934 ch := s.peek()
6935 if ch == 0 {
6936 return 0
6937 }
6938 s.pos = s.pos + 1
6939 if ch == '\n' {
6940 s.line = s.line + 1
6941 s.col = 1
6942 } else {
6943 s.col = s.col + 1
6944 }
6945 return ch
6946 }
6947
6948 func (s *Scanner177) skipSpace() {
6949 for {
6950 ch := s.peek()
6951 if ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' {
6952 return
6953 }
6954 s.next()
6955 }
6956 }
6957
6958 func (s *Scanner177) readIdent() string {
6959 start := s.pos
6960 for {
6961 ch := s.peek()
6962 if (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9') && ch != '_' {
6963 break
6964 }
6965 s.pos = s.pos + 1
6966 }
6967 return string(s.src[start:s.pos])
6968 }
6969
6970 func (s *Scanner177) atEnd() bool {
6971 return s.pos >= int32(len(s.src))
6972 }
6973 `)
6974 name177 := []byte("mypkg")
6975 h177 := compileToIR(
6976 uintptr(unsafe.Pointer(&src177[0])), int32(len(src177)),
6977 uintptr(unsafe.Pointer(&name177[0])), int32(len(name177)),
6978 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
6979 )
6980 ir177 := getIR(h177)
6981 fmt.Println("=== IR for scanner ===")
6982 fmt.Println(ir177)
6983
6984 if ir177 == "" {
6985 assert("scanner produces IR", false)
6986 } else {
6987 llvmVerify("scanner", ir177)
6988 assert("scan has NewScanner177", strings.Contains(ir177, "@mypkg.NewScanner177"))
6989 assert("scan has peek", strings.Contains(ir177, "@mypkg.Scanner177.peek"))
6990 assert("scan has next", strings.Contains(ir177, "@mypkg.Scanner177.next"))
6991 assert("scan has skipSpace", strings.Contains(ir177, "@mypkg.Scanner177.skipSpace"))
6992 assert("scan has readIdent", strings.Contains(ir177, "@mypkg.Scanner177.readIdent"))
6993 assert("scan next calls peek", strings.Contains(ir177, "call i8 @mypkg.Scanner177.peek"))
6994 assert("scan no parse error", !strings.Contains(ir177, "parse error"))
6995 }
6996
6997 irFree(h177)
6998
6999 // Test 178: tc_types core pattern - Type interface hierarchy
7000 src178 := []byte(`package mypkg
7001
7002 type Type interface {
7003 Underlying() Type
7004 String() string
7005 }
7006
7007 type BasicKind int32
7008
7009 const (
7010 Invalid BasicKind = iota
7011 Bool178
7012 Int8Kind
7013 Int32Kind
7014 Int64Kind
7015 StringKind
7016 )
7017
7018 type BasicInfo int32
7019
7020 const (
7021 IsBoolean BasicInfo = 1 << iota
7022 IsInteger
7023 IsUnsigned
7024 IsFloat
7025 IsString178
7026 )
7027
7028 type Basic178 struct {
7029 kind BasicKind
7030 info BasicInfo
7031 name string
7032 }
7033
7034 func (t *Basic178) Kind() BasicKind { return t.kind }
7035 func (t *Basic178) Info() BasicInfo { return t.info }
7036 func (t *Basic178) Name() string { return t.name }
7037 func (t *Basic178) Underlying() Type { return t }
7038 func (t *Basic178) String() string { return t.name }
7039
7040 type Slice178 struct {
7041 elem Type
7042 }
7043
7044 func NewSlice178(elem Type) *Slice178 { return &Slice178{elem: elem} }
7045 func (t *Slice178) Elem() Type { return t.elem }
7046 func (t *Slice178) Underlying() Type { return t }
7047 func (t *Slice178) String() string { return "[]" | t.elem.String() }
7048
7049 type Pointer178 struct {
7050 base Type
7051 }
7052
7053 func NewPointer178(base Type) *Pointer178 { return &Pointer178{base: base} }
7054 func (t *Pointer178) Elem() Type { return t.base }
7055 func (t *Pointer178) Underlying() Type { return t }
7056 func (t *Pointer178) String() string { return "*" | t.base.String() }
7057
7058 type Map178 struct {
7059 key Type
7060 elem Type
7061 }
7062
7063 func NewMap178(key Type, elem Type) *Map178 { return &Map178{key: key, elem: elem} }
7064 func (t *Map178) Key() Type { return t.key }
7065 func (t *Map178) Elem() Type { return t.elem }
7066 func (t *Map178) Underlying() Type { return t }
7067
7068 func isInteger(t Type) bool {
7069 if b, ok := t.(*Basic178); ok {
7070 return b.info & IsInteger != 0
7071 }
7072 return false
7073 }
7074
7075 func elemType(t Type) Type {
7076 switch t := t.(type) {
7077 case *Slice178:
7078 return t.elem
7079 case *Pointer178:
7080 return t.base
7081 case *Map178:
7082 return t.elem
7083 }
7084 return nil
7085 }
7086 `)
7087 name178 := []byte("mypkg")
7088 h178 := compileToIR(
7089 uintptr(unsafe.Pointer(&src178[0])), int32(len(src178)),
7090 uintptr(unsafe.Pointer(&name178[0])), int32(len(name178)),
7091 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7092 )
7093 ir178 := getIR(h178)
7094 fmt.Println("=== IR for type system ===")
7095 fmt.Println(ir178)
7096
7097 if ir178 == "" {
7098 assert("type system produces IR", false)
7099 } else {
7100 llvmVerify("type system", ir178)
7101 assert("ts has Basic178 methods", strings.Contains(ir178, "@mypkg.Basic178.String"))
7102 assert("ts has Slice178.String", strings.Contains(ir178, "@mypkg.Slice178.String"))
7103 assert("ts has Pointer178.String", strings.Contains(ir178, "@mypkg.Pointer178.String"))
7104 assert("ts has isInteger", strings.Contains(ir178, "@mypkg.isInteger"))
7105 assert("ts has elemType", strings.Contains(ir178, "@mypkg.elemType"))
7106 assert("ts bitmask and", strings.Contains(ir178, "and i32"))
7107 assert("ts has Slice178 typeid", strings.Contains(ir178, "typeid.ptr.Slice178"))
7108 assert("ts has Pointer178 typeid", strings.Contains(ir178, "typeid.ptr.Pointer178"))
7109 assert("ts has Map178 typeid", strings.Contains(ir178, "typeid.ptr.Map178"))
7110 assert("ts Slice.String calls elem.String", strings.Contains(ir178, "call {ptr, i64, i64}") || strings.Contains(ir178, "invoke"))
7111 assert("ts no parse error", !strings.Contains(ir178, "parse error"))
7112 }
7113
7114 irFree(h178)
7115
7116 // Test 179: Named type with methods + Underlying (key tc_types pattern)
7117 src179 := []byte(`package mypkg
7118
7119 type Type179 interface {
7120 Underlying() Type179
7121 }
7122
7123 type Named179 struct {
7124 obj *TypeObj179
7125 underlying Type179
7126 methods []*FuncObj179
7127 }
7128
7129 type TypeObj179 struct {
7130 name string
7131 }
7132
7133 type FuncObj179 struct {
7134 name string
7135 }
7136
7137 func NewNamed179(obj *TypeObj179, underlying Type179) *Named179 {
7138 return &Named179{obj: obj, underlying: underlying}
7139 }
7140
7141 func (t *Named179) Obj() *TypeObj179 { return t.obj }
7142 func (t *Named179) Underlying() Type179 { return t.underlying }
7143 func (t *Named179) NumMethods() int32 { return int32(len(t.methods)) }
7144 func (t *Named179) Method(i int32) *FuncObj179 { return t.methods[i] }
7145 func (t *Named179) AddMethod(m *FuncObj179) {
7146 t.methods = append(t.methods, m)
7147 }
7148
7149 func (t *Named179) SetUnderlying(u Type179) {
7150 t.underlying = u
7151 }
7152
7153 type Struct179 struct {
7154 fields []*Field179
7155 }
7156
7157 type Field179 struct {
7158 name string
7159 typ Type179
7160 anon bool
7161 }
7162
7163 func (t *Struct179) Underlying() Type179 { return t }
7164 func (t *Struct179) NumFields() int32 { return int32(len(t.fields)) }
7165 func (t *Struct179) Field(i int32) *Field179 { return t.fields[i] }
7166
7167 func underlyingType(t Type179) Type179 {
7168 if n, ok := t.(*Named179); ok {
7169 return n.underlying
7170 }
7171 return t
7172 }
7173 `)
7174 name179 := []byte("mypkg")
7175 h179 := compileToIR(
7176 uintptr(unsafe.Pointer(&src179[0])), int32(len(src179)),
7177 uintptr(unsafe.Pointer(&name179[0])), int32(len(name179)),
7178 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7179 )
7180 ir179 := getIR(h179)
7181 fmt.Println("=== IR for Named type ===")
7182 fmt.Println(ir179)
7183
7184 if ir179 == "" {
7185 assert("named type produces IR", false)
7186 } else {
7187 llvmVerify("Named type", ir179)
7188 assert("named has NewNamed179", strings.Contains(ir179, "@mypkg.NewNamed179"))
7189 assert("named has AddMethod", strings.Contains(ir179, "@mypkg.Named179.AddMethod"))
7190 assert("named has SetUnderlying", strings.Contains(ir179, "@mypkg.Named179.SetUnderlying"))
7191 assert("named has underlyingType", strings.Contains(ir179, "@mypkg.underlyingType"))
7192 assert("named has Named179 typeid", strings.Contains(ir179, "typeid.ptr.Named179"))
7193 assert("named no parse error", !strings.Contains(ir179, "parse error"))
7194 }
7195
7196 irFree(h179)
7197
7198 // Test 180: Signature/Tuple pattern + nil field access
7199 src180 := []byte(`package mypkg
7200
7201 type Type180 interface {
7202 Underlying() Type180
7203 }
7204
7205 type Var180 struct {
7206 name string
7207 typ Type180
7208 }
7209
7210 type Tuple180 struct {
7211 vars []*Var180
7212 }
7213
7214 func NewTuple180(vars []*Var180) *Tuple180 { return &Tuple180{vars: vars} }
7215 func (t *Tuple180) Len() int32 { return int32(len(t.vars)) }
7216 func (t *Tuple180) At(i int32) *Var180 { return t.vars[i] }
7217
7218 type Signature180 struct {
7219 recv *Var180
7220 params *Tuple180
7221 results *Tuple180
7222 variadic bool
7223 }
7224
7225 func NewSig180(recv *Var180, params *Tuple180, results *Tuple180) *Signature180 {
7226 return &Signature180{recv: recv, params: params, results: results}
7227 }
7228
7229 func (s *Signature180) Recv() *Var180 { return s.recv }
7230 func (s *Signature180) Params() *Tuple180 { return s.params }
7231 func (s *Signature180) Results() *Tuple180 { return s.results }
7232 func (s *Signature180) Variadic() bool { return s.variadic }
7233 func (s *Signature180) Underlying() Type180 { return s }
7234
7235 func numParams(s *Signature180) int32 {
7236 if s.params == nil {
7237 return 0
7238 }
7239 return s.params.Len()
7240 }
7241
7242 func numResults(s *Signature180) int32 {
7243 if s.results == nil {
7244 return 0
7245 }
7246 return s.results.Len()
7247 }
7248
7249 func hasReceiver(s *Signature180) bool {
7250 return s.recv != nil
7251 }
7252
7253 func paramName(s *Signature180, i int32) string {
7254 if s.params == nil || i >= s.params.Len() {
7255 return ""
7256 }
7257 return s.params.At(i).name
7258 }
7259 `)
7260 name180 := []byte("mypkg")
7261 h180 := compileToIR(
7262 uintptr(unsafe.Pointer(&src180[0])), int32(len(src180)),
7263 uintptr(unsafe.Pointer(&name180[0])), int32(len(name180)),
7264 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7265 )
7266 ir180 := getIR(h180)
7267 fmt.Println("=== IR for Signature ===")
7268 fmt.Println(ir180)
7269
7270 if ir180 == "" {
7271 assert("signature produces IR", false)
7272 } else {
7273 llvmVerify("Signature", ir180)
7274 assert("sig has NewSig180", strings.Contains(ir180, "@mypkg.NewSig180"))
7275 assert("sig has numParams", strings.Contains(ir180, "@mypkg.numParams"))
7276 assert("sig has numResults", strings.Contains(ir180, "@mypkg.numResults"))
7277 assert("sig has hasReceiver", strings.Contains(ir180, "@mypkg.hasReceiver"))
7278 assert("sig has paramName", strings.Contains(ir180, "@mypkg.paramName"))
7279 assert("sig nil check on params", strings.Contains(ir180, "icmp") && strings.Contains(ir180, "null"))
7280 assert("sig no parse error", !strings.Contains(ir180, "parse error"))
7281 }
7282
7283 irFree(h180)
7284
7285 // Test 181: SSA instruction hierarchy (the pattern from ssa_types.mx)
7286 src181 := []byte(`package mypkg
7287
7288 type SSAType181 interface {
7289 Underlying() SSAType181
7290 }
7291
7292 type SSAValue181 interface {
7293 SSAType() SSAType181
7294 Name181() string
7295 }
7296
7297 type ssaNode181 struct {
7298 name string
7299 typ SSAType181
7300 }
7301
7302 func (n *ssaNode181) SSAType() SSAType181 { return n.typ }
7303 func (n *ssaNode181) Name181() string { return n.name }
7304
7305 type SSAConst181 struct {
7306 ssaNode181
7307 val int64
7308 }
7309
7310 type SSAAlloc181 struct {
7311 ssaNode181
7312 heap bool
7313 }
7314
7315 type SSABinOp181 struct {
7316 ssaNode181
7317 op int32
7318 x SSAValue181
7319 y SSAValue181
7320 }
7321
7322 type SSACall181 struct {
7323 ssaNode181
7324 fn string
7325 args []SSAValue181
7326 }
7327
7328 func isConst(v SSAValue181) bool {
7329 _, ok := v.(*SSAConst181)
7330 return ok
7331 }
7332
7333 func operandName(v SSAValue181) string {
7334 if v == nil {
7335 return "undef"
7336 }
7337 if c, ok := v.(*SSAConst181); ok {
7338 return itoa181(int32(c.val))
7339 }
7340 return "%" | v.Name181()
7341 }
7342
7343 func itoa181(n int32) string {
7344 if n == 0 {
7345 return "0"
7346 }
7347 buf := []byte{:0:10}
7348 for n > 0 {
7349 buf = append(buf, byte('0' + n % 10))
7350 n = n / 10
7351 }
7352 return string(buf)
7353 }
7354
7355 func countArgs(c *SSACall181) int32 {
7356 return int32(len(c.args))
7357 }
7358 `)
7359 name181 := []byte("mypkg")
7360 h181 := compileToIR(
7361 uintptr(unsafe.Pointer(&src181[0])), int32(len(src181)),
7362 uintptr(unsafe.Pointer(&name181[0])), int32(len(name181)),
7363 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7364 )
7365 ir181 := getIR(h181)
7366 fmt.Println("=== IR for SSA types ===")
7367 fmt.Println(ir181)
7368
7369 if ir181 == "" {
7370 assert("ssa types produces IR", false)
7371 } else {
7372 llvmVerify("SSA types", ir181)
7373 assert("ssa has isConst", strings.Contains(ir181, "@mypkg.isConst"))
7374 assert("ssa has operandName", strings.Contains(ir181, "@mypkg.operandName"))
7375 assert("ssa has countArgs", strings.Contains(ir181, "@mypkg.countArgs"))
7376 assert("ssa SSAConst181 typeid", strings.Contains(ir181, "typeid.ptr.SSAConst181"))
7377 assert("ssa promotes Name181 via embed", strings.Contains(ir181, "ssaNode181.Name181") || strings.Contains(ir181, "SSAConst181.Name181"))
7378 assert("ssa no parse error", !strings.Contains(ir181, "parse error"))
7379 }
7380
7381 irFree(h181)
7382
7383 // Test 182: Self-compilation pattern - mini IR emitter compiling mini IR emitter
7384 src182 := []byte(`package mypkg
7385
7386 type Type182 interface {
7387 Underlying() Type182
7388 String() string
7389 }
7390
7391 type Basic182 struct {
7392 kind int32
7393 name string
7394 }
7395
7396 func (t *Basic182) Underlying() Type182 { return t }
7397 func (t *Basic182) String() string { return t.name }
7398
7399 type Slice182 struct {
7400 elem Type182
7401 }
7402
7403 func (t *Slice182) Underlying() Type182 { return t }
7404 func (t *Slice182) String() string { return "[]" | t.elem.String() }
7405
7406 type Pointer182 struct {
7407 base Type182
7408 }
7409
7410 func (t *Pointer182) Underlying() Type182 { return t }
7411 func (t *Pointer182) String() string { return "*" | t.base.String() }
7412
7413 type SSAValue182 interface {
7414 ValType() Type182
7415 ValName() string
7416 }
7417
7418 type ssaBase182 struct {
7419 name string
7420 typ Type182
7421 }
7422
7423 func (n *ssaBase182) ValType() Type182 { return n.typ }
7424 func (n *ssaBase182) ValName() string { return n.name }
7425
7426 type SSAConst182 struct {
7427 ssaBase182
7428 val int64
7429 }
7430
7431 type SSABinOp182 struct {
7432 ssaBase182
7433 op int32
7434 x SSAValue182
7435 y SSAValue182
7436 }
7437
7438 type SSAFieldAddr182 struct {
7439 ssaBase182
7440 x SSAValue182
7441 field int32
7442 }
7443
7444 type Emitter182 struct {
7445 buf []byte
7446 decls map[string]bool
7447 tempCount int32
7448 pkg string
7449 }
7450
7451 func NewEmitter182(pkg string) *Emitter182 {
7452 return &Emitter182{pkg: pkg, decls: map[string]bool{}}
7453 }
7454
7455 func (e *Emitter182) w(s string) {
7456 e.buf = append(e.buf, s...)
7457 }
7458
7459 func (e *Emitter182) nextTemp() string {
7460 e.tempCount = e.tempCount + 1
7461 return "%t" | itoa182(e.tempCount)
7462 }
7463
7464 func (e *Emitter182) llvmType(t Type182) string {
7465 switch t.(type) {
7466 case *Basic182:
7467 b := t.(*Basic182)
7468 switch b.kind {
7469 case 0:
7470 return "i32"
7471 case 1:
7472 return "i64"
7473 case 2:
7474 return "{ptr, i64, i64}"
7475 }
7476 return "i32"
7477 case *Slice182:
7478 return "{ptr, i64, i64}"
7479 case *Pointer182:
7480 return "ptr"
7481 }
7482 return "i32"
7483 }
7484
7485 func (e *Emitter182) operand(v SSAValue182) string {
7486 if v == nil {
7487 return "zeroinitializer"
7488 }
7489 if c, ok := v.(*SSAConst182); ok {
7490 return itoa182(int32(c.val))
7491 }
7492 return "%" | v.ValName()
7493 }
7494
7495 func (e *Emitter182) emitBinOp(b *SSABinOp182) {
7496 reg := e.nextTemp()
7497 lt := e.llvmType(b.x.ValType())
7498 lv := e.operand(b.x)
7499 rv := e.operand(b.y)
7500 e.w(" ")
7501 e.w(reg)
7502 e.w(" = add ")
7503 e.w(lt)
7504 e.w(" ")
7505 e.w(lv)
7506 e.w(", ")
7507 e.w(rv)
7508 e.w("\n")
7509 }
7510
7511 func (e *Emitter182) result() string {
7512 return string(e.buf)
7513 }
7514
7515 func itoa182(n int32) string {
7516 if n == 0 {
7517 return "0"
7518 }
7519 buf := []byte{:0:10}
7520 for n > 0 {
7521 buf = append(buf, byte('0' + n % 10))
7522 n = n / 10
7523 }
7524 i := 0
7525 j := int32(len(buf)) - 1
7526 for i < j {
7527 buf[i], buf[j] = buf[j], buf[i]
7528 i = i + 1
7529 j = j - 1
7530 }
7531 return string(buf)
7532 }
7533 `)
7534 name182 := []byte("mypkg")
7535 h182 := compileToIR(
7536 uintptr(unsafe.Pointer(&src182[0])), int32(len(src182)),
7537 uintptr(unsafe.Pointer(&name182[0])), int32(len(name182)),
7538 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7539 )
7540 ir182 := getIR(h182)
7541 fmt.Println("=== IR for self-compile pattern ===")
7542 fmt.Println(ir182)
7543
7544 if ir182 == "" {
7545 assert("self-compile produces IR", false)
7546 } else {
7547 llvmVerify("self-compile", ir182)
7548 assert("sc has NewEmitter182", strings.Contains(ir182, "@mypkg.NewEmitter182"))
7549 assert("sc has emitBinOp", strings.Contains(ir182, "@mypkg.Emitter182.emitBinOp"))
7550 assert("sc has llvmType", strings.Contains(ir182, "@mypkg.Emitter182.llvmType"))
7551 assert("sc has operand", strings.Contains(ir182, "@mypkg.Emitter182.operand"))
7552 assert("sc has nextTemp", strings.Contains(ir182, "@mypkg.Emitter182.nextTemp"))
7553 assert("sc Basic182 typeid", strings.Contains(ir182, "typeid.ptr.Basic182"))
7554 assert("sc Slice182 typeid", strings.Contains(ir182, "typeid.ptr.Slice182"))
7555 assert("sc Pointer182 typeid", strings.Contains(ir182, "typeid.ptr.Pointer182"))
7556 assert("sc SSAConst182 typeid", strings.Contains(ir182, "typeid.ptr.SSAConst182"))
7557 assert("sc no parse error", !strings.Contains(ir182, "parse error"))
7558 }
7559
7560 irFree(h182)
7561
7562 // Test 183: Real bootstrap files - tc_package + tc_scope + Object (concatenated)
7563 src183 := []byte(`package main
7564
7565 type Type interface {
7566 Underlying() Type
7567 String() string
7568 }
7569
7570 type Object interface {
7571 Name() string
7572 Type() Type
7573 Pkg() *TCPackage
7574 Exported() bool
7575 }
7576
7577 type object struct {
7578 pkg *TCPackage
7579 name string
7580 typ Type
7581 }
7582
7583 func (o *object) Name() string { return o.name }
7584 func (o *object) Type() Type { return o.typ }
7585 func (o *object) Pkg() *TCPackage { return o.pkg }
7586 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
7587
7588 type TypeName struct {
7589 object
7590 }
7591
7592 func NewTypeName(pkg *TCPackage, name string, typ Type) *TypeName {
7593 return &TypeName{object{pkg: pkg, name: name, typ: typ}}
7594 }
7595
7596 type TCVar struct {
7597 pkg *TCPackage
7598 name string
7599 typ Type
7600 anonymous bool
7601 }
7602
7603 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
7604 return &TCVar{pkg: pkg, name: name, typ: typ, anonymous: anonymous}
7605 }
7606
7607 func (v *TCVar) Name() string { return v.name }
7608 func (v *TCVar) Type() Type { return v.typ }
7609 func (v *TCVar) Pkg() *TCPackage { return v.pkg }
7610 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
7611 func (v *TCVar) Anonymous() bool { return v.anonymous }
7612
7613 type TCPackage struct {
7614 path string
7615 name string
7616 scope *Scope
7617 imports []*TCPackage
7618 complete bool
7619 }
7620
7621 func NewTCPackage(path string, name string) *TCPackage {
7622 return &TCPackage{
7623 path: path,
7624 name: name,
7625 scope: NewScope(nil),
7626 }
7627 }
7628
7629 func (p *TCPackage) Path() string { return p.path }
7630 func (p *TCPackage) Name() string { return p.name }
7631 func (p *TCPackage) Scope() *Scope { return p.scope }
7632 func (p *TCPackage) Complete() bool { return p.complete }
7633 func (p *TCPackage) MarkComplete() { p.complete = true }
7634 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
7635 func (p *TCPackage) Imports() []*TCPackage { return p.imports }
7636 func (p *TCPackage) SetImports(imps []*TCPackage) { p.imports = imps }
7637
7638 type Scope struct {
7639 parent *Scope
7640 children []*Scope
7641 elems map[string]Object
7642 }
7643
7644 func NewScope(parent *Scope) *Scope {
7645 return &Scope{parent: parent, elems: map[string]Object{}}
7646 }
7647
7648 func (s *Scope) Parent() *Scope { return s.parent }
7649 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
7650
7651 func (s *Scope) Lookup(name string) Object {
7652 return s.elems[name]
7653 }
7654
7655 func (s *Scope) LookupParent(name string) (*Scope, Object) {
7656 for sc := s; sc != nil; sc = sc.parent {
7657 if obj, ok := sc.elems[name]; ok {
7658 return sc, obj
7659 }
7660 }
7661 return nil, nil
7662 }
7663
7664 func (s *Scope) Insert(obj Object) Object {
7665 name := obj.Name()
7666 if alt, ok := s.elems[name]; ok {
7667 return alt
7668 }
7669 s.elems[name] = obj
7670 return nil
7671 }
7672
7673 func (s *Scope) Names() []string {
7674 names := []string{:0:len(s.elems)}
7675 for n := range s.elems {
7676 names = append(names, n)
7677 }
7678 return names
7679 }
7680 `)
7681 name183 := []byte("main")
7682 h183 := compileToIR(
7683 uintptr(unsafe.Pointer(&src183[0])), int32(len(src183)),
7684 uintptr(unsafe.Pointer(&name183[0])), int32(len(name183)),
7685 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
7686 )
7687 ir183 := getIR(h183)
7688 fmt.Println("=== IR for real bootstrap concat ===")
7689 if len(ir183) > 200 {
7690 fmt.Println(ir183[:200])
7691 fmt.Println("... [truncated, total", len(ir183), "bytes]")
7692 } else {
7693 fmt.Println(ir183)
7694 }
7695
7696 if ir183 == "" {
7697 assert("bootstrap concat produces IR", false)
7698 } else {
7699 llvmVerify("bootstrap concat", ir183)
7700 assert("bc has NewTCPackage", strings.Contains(ir183, "@main.NewTCPackage"))
7701 assert("bc has NewScope", strings.Contains(ir183, "@main.NewScope"))
7702 assert("bc has Scope.Insert", strings.Contains(ir183, "@main.Scope.Insert"))
7703 assert("bc has Scope.LookupParent", strings.Contains(ir183, "@main.Scope.LookupParent"))
7704 assert("bc has Scope.Names", strings.Contains(ir183, "@main.Scope.Names"))
7705 assert("bc has object.Exported", strings.Contains(ir183, "@main.object.Exported"))
7706 assert("bc has NewTypeName", strings.Contains(ir183, "@main.NewTypeName"))
7707 assert("bc has TCPackage.String", strings.Contains(ir183, "@main.TCPackage.String"))
7708 assert("bc has hashmapLen", strings.Contains(ir183, "hashmapLen"))
7709 assert("bc no parse error", !strings.Contains(ir183, "parse error"))
7710 }
7711
7712 irFree(h183)
7713
7714 // Test 184: copy builtin
7715 test(184, `package main
7716 func copyBytes(dst []byte, src []byte) int32 {
7717 return int32(copy(dst, src))
7718 }
7719 func main() {
7720 a := []byte{:10}
7721 b := []byte("hello")
7722 n := copyBytes(a, b)
7723 _ = n
7724 }
7725 `, func(ir string) {
7726 assert("184: copy call", strings.Contains(ir, "sliceCopy"))
7727 })
7728
7729 // Test 185: panic builtin
7730 test(185, `package main
7731 func mustNotBeNil(p *int32) {
7732 if p == nil {
7733 panic("nil pointer")
7734 }
7735 }
7736 func main() {
7737 var x int32
7738 mustNotBeNil(&x)
7739 }
7740 `, func(ir string) {
7741 assert("185: panic call", strings.Contains(ir, "_panic"))
7742 })
7743
7744 // Test 186: named returns
7745 test(186, `package main
7746 func divide(a int32, b int32) (q int32, r int32) {
7747 q = a / b
7748 r = a - q*b
7749 return
7750 }
7751 func main() {
7752 q, r := divide(17, 5)
7753 _ = q
7754 _ = r
7755 }
7756 `, func(ir string) {
7757 assert("186: divide defined", strings.Contains(ir, "@main.divide"))
7758 })
7759
7760 // Test 187: function values as struct fields
7761 test(187, `package main
7762 type Handler struct {
7763 onEvent func(int32) bool
7764 name string
7765 }
7766 func process(h *Handler, val int32) bool {
7767 if h.onEvent != nil {
7768 return h.onEvent(val)
7769 }
7770 return false
7771 }
7772 func main() {
7773 h := &Handler{
7774 onEvent: func(v int32) bool { return v > 0 },
7775 name: "test",
7776 }
7777 result := process(h, 42)
7778 _ = result
7779 }
7780 `, func(ir string) {
7781 assert("187: process defined", strings.Contains(ir, "@main.process"))
7782 })
7783
7784 // Test 188: goto statement
7785 test(188, `package main
7786 func search(data []byte, target byte) int32 {
7787 var i int32
7788 loop:
7789 if i >= int32(len(data)) {
7790 return -1
7791 }
7792 if data[i] == target {
7793 return i
7794 }
7795 i++
7796 goto loop
7797 }
7798 func main() {
7799 data := []byte("hello")
7800 idx := search(data, 'l')
7801 _ = idx
7802 }
7803 `, func(ir string) {
7804 assert("188: search defined", strings.Contains(ir, "@main.search"))
7805 })
7806
7807 // Test 189: multiple assignment
7808 test(189, `package main
7809 func swap(a int32, b int32) (int32, int32) {
7810 return b, a
7811 }
7812 func main() {
7813 x, y := swap(1, 2)
7814 _ = x
7815 _ = y
7816 }
7817 `, func(ir string) {
7818 assert("189: swap defined", strings.Contains(ir, "@main.swap"))
7819 })
7820
7821 // Test 190: rune type and comparisons
7822 test(190, `package main
7823 func isDigit(ch rune) bool {
7824 return ch >= '0' && ch <= '9'
7825 }
7826 func isLetter(ch rune) bool {
7827 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
7828 }
7829 func main() {
7830 d := isDigit('5')
7831 l := isLetter('x')
7832 _ = d
7833 _ = l
7834 }
7835 `, func(ir string) {
7836 assert("190: isDigit defined", strings.Contains(ir, "@main.isDigit"))
7837 assert("190: isLetter defined", strings.Contains(ir, "@main.isLetter"))
7838 })
7839
7840 // Test 191: function value nil check and call through variable
7841 test(191, `package main
7842 type Callback func(string)
7843 func invoke(cb Callback, msg string) {
7844 if cb != nil {
7845 cb(msg)
7846 }
7847 }
7848 func main() {
7849 var cb Callback
7850 invoke(cb, "test")
7851 }
7852 `, func(ir string) {
7853 assert("191: invoke defined", strings.Contains(ir, "@main.invoke"))
7854 })
7855
7856 // Test 192: struct value return (non-pointer)
7857 test(192, `package main
7858 type Point struct {
7859 x int32
7860 y int32
7861 }
7862 func makePoint(x int32, y int32) Point {
7863 return Point{x, y}
7864 }
7865 func addPoints(a Point, b Point) Point {
7866 return Point{a.x + b.x, a.y + b.y}
7867 }
7868 func main() {
7869 p1 := makePoint(1, 2)
7870 p2 := makePoint(3, 4)
7871 p3 := addPoints(p1, p2)
7872 _ = p3
7873 }
7874 `, func(ir string) {
7875 assert("192: makePoint defined", strings.Contains(ir, "@main.makePoint"))
7876 assert("192: addPoints defined", strings.Contains(ir, "@main.addPoints"))
7877 })
7878
7879 // Test 193: Source-like pattern (nextch with goto, byte indexing, rune)
7880 test(193, `package main
7881 const sentinel = 128
7882 type Source struct {
7883 buf []byte
7884 b int32
7885 r int32
7886 e int32
7887 line uint32
7888 col uint32
7889 ch rune
7890 chw int32
7891 }
7892 func (s *Source) start() { s.b = s.r - s.chw }
7893 func (s *Source) stop() { s.b = -1 }
7894 func (s *Source) segment() []byte { return s.buf[s.b : s.r-s.chw] }
7895 func (s *Source) nextch() {
7896 s.col += uint32(s.chw)
7897 if s.ch == '\n' {
7898 s.line++
7899 s.col = 0
7900 }
7901 if s.ch = rune(s.buf[s.r]); s.ch < sentinel {
7902 s.r++
7903 s.chw = 1
7904 if s.ch == 0 {
7905 return
7906 }
7907 return
7908 }
7909 s.ch = -1
7910 s.chw = 0
7911 }
7912 func main() {
7913 s := &Source{buf: []byte("hello\nworld"), r: 0, e: 11, ch: ' ', b: -1}
7914 s.nextch()
7915 }
7916 `, func(ir string) {
7917 assert("193: nextch defined", strings.Contains(ir, "@main.Source.nextch"))
7918 assert("193: segment defined", strings.Contains(ir, "@main.Source.segment"))
7919 })
7920
7921 // Test 194: Token-like const enum with type conversion
7922 test(194, `package main
7923 type Token uint32
7924 const (
7925 _ Token = iota
7926 EOF
7927 NameType
7928 Literal
7929 OperatorType
7930 AssignOp
7931 Lparen
7932 Rparen
7933 Comma
7934 Semi
7935 tokenCount
7936 )
7937 const _ uint64 = 1 << (tokenCount - 1)
7938 func contains(tokset uint64, tok Token) bool {
7939 return tokset&(1<<tok) != 0
7940 }
7941 type LitKind uint8
7942 const (
7943 IntLit LitKind = iota
7944 FloatLit
7945 StringLit
7946 )
7947 func main() {
7948 b := contains(1<<EOF|1<<NameType, EOF)
7949 _ = b
7950 }
7951 `, func(ir string) {
7952 assert("194: contains defined", strings.Contains(ir, "@main.contains"))
7953 })
7954
7955 // Test 195: Pos-like value receiver with nested struct access
7956 test(195, `package main
7957 type PosBase struct {
7958 filename string
7959 line uint32
7960 col uint32
7961 }
7962 type Pos struct {
7963 base *PosBase
7964 line uint32
7965 col uint32
7966 }
7967 func MakePos(base *PosBase, line uint32, col uint32) Pos {
7968 return Pos{base, line, col}
7969 }
7970 func (pos Pos) IsKnown() bool { return pos.line > 0 }
7971 func (pos Pos) Base() *PosBase { return pos.base }
7972 func (pos Pos) Line() uint32 { return pos.line }
7973 func (pos Pos) Col() uint32 { return pos.col }
7974 func (pos Pos) Filename() string {
7975 if pos.base == nil {
7976 return ""
7977 }
7978 return pos.base.filename
7979 }
7980 func main() {
7981 base := &PosBase{filename: "test.mx", line: 1, col: 1}
7982 p := MakePos(base, 10, 5)
7983 known := p.IsKnown()
7984 name := p.Filename()
7985 _ = known
7986 _ = name
7987 }
7988 `, func(ir string) {
7989 assert("195: MakePos defined", strings.Contains(ir, "@main.MakePos"))
7990 assert("195: Filename defined", strings.Contains(ir, "@main.Pos.Filename"))
7991 })
7992
7993 // Test 196: Scanner-like pattern with for loop and byte comparisons
7994 test(196, `package main
7995 type Scanner struct {
7996 src []byte
7997 pos int32
7998 ch byte
7999 }
8000 func (s *Scanner) setup(src []byte) {
8001 s.src = src
8002 s.pos = 0
8003 if len(src) > 0 {
8004 s.ch = src[0]
8005 }
8006 }
8007 func (s *Scanner) next() {
8008 s.pos++
8009 if s.pos < int32(len(s.src)) {
8010 s.ch = s.src[s.pos]
8011 } else {
8012 s.ch = 0
8013 }
8014 }
8015 func (s *Scanner) skipSpace() {
8016 for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' || s.ch == '\r' {
8017 s.next()
8018 }
8019 }
8020 func (s *Scanner) readIdent() string {
8021 start := s.pos
8022 for s.ch >= 'a' && s.ch <= 'z' || s.ch >= 'A' && s.ch <= 'Z' || s.ch == '_' || s.ch >= '0' && s.ch <= '9' {
8023 s.next()
8024 }
8025 return string(s.src[start:s.pos])
8026 }
8027 func main() {
8028 sc := &Scanner{}
8029 sc.setup([]byte(" hello world"))
8030 sc.skipSpace()
8031 word := sc.readIdent()
8032 _ = word
8033 }
8034 `, func(ir string) {
8035 assert("196: setup defined", strings.Contains(ir, "@main.Scanner.setup"))
8036 assert("196: skipSpace defined", strings.Contains(ir, "@main.Scanner.skipSpace"))
8037 assert("196: readIdent defined", strings.Contains(ir, "@main.Scanner.readIdent"))
8038 })
8039
8040 // Test 197: Node hierarchy with interface and type switch
8041 test(197, `package main
8042 type Node interface {
8043 nodeTag()
8044 }
8045 type Expr interface {
8046 Node
8047 exprTag()
8048 }
8049 type Name struct {
8050 Value string
8051 }
8052 func (n *Name) nodeTag() {}
8053 func (n *Name) exprTag() {}
8054 type BasicLit struct {
8055 Value string
8056 Kind int32
8057 }
8058 func (b *BasicLit) nodeTag() {}
8059 func (b *BasicLit) exprTag() {}
8060 type BinaryExpr struct {
8061 X Expr
8062 Op int32
8063 Y Expr
8064 }
8065 func (b *BinaryExpr) nodeTag() {}
8066 func (b *BinaryExpr) exprTag() {}
8067 func exprName(e Expr) string {
8068 switch x := e.(type) {
8069 case *Name:
8070 return x.Value
8071 case *BasicLit:
8072 return x.Value
8073 case *BinaryExpr:
8074 return "binary"
8075 }
8076 return ""
8077 }
8078 func main() {
8079 n := &Name{Value: "foo"}
8080 var e Expr = n
8081 result := exprName(e)
8082 _ = result
8083 }
8084 `, func(ir string) {
8085 assert("197: exprName defined", strings.Contains(ir, "@main.exprName"))
8086 assert("197: has type switch", strings.Contains(ir, "icmp eq ptr"))
8087 })
8088
8089 // Test 198: Linked list pattern (self-referential struct)
8090 test(198, `package main
8091 type ListNode struct {
8092 value int32
8093 next *ListNode
8094 }
8095 func push(head *ListNode, val int32) *ListNode {
8096 return &ListNode{value: val, next: head}
8097 }
8098 func length(head *ListNode) int32 {
8099 n := int32(0)
8100 for p := head; p != nil; p = p.next {
8101 n++
8102 }
8103 return n
8104 }
8105 func sum(head *ListNode) int32 {
8106 s := int32(0)
8107 for p := head; p != nil; p = p.next {
8108 s += p.value
8109 }
8110 return s
8111 }
8112 func main() {
8113 var head *ListNode
8114 head = push(head, 1)
8115 head = push(head, 2)
8116 head = push(head, 3)
8117 n := length(head)
8118 s := sum(head)
8119 _ = n
8120 _ = s
8121 }
8122 `, func(ir string) {
8123 assert("198: push defined", strings.Contains(ir, "@main.push"))
8124 assert("198: length defined", strings.Contains(ir, "@main.length"))
8125 assert("198: sum defined", strings.Contains(ir, "@main.sum"))
8126 })
8127
8128 // Test 199: Slice of structs with append
8129 test(199, `package main
8130 type Entry struct {
8131 name string
8132 value int32
8133 }
8134 func addEntry(entries []Entry, name string, val int32) []Entry {
8135 return append(entries, Entry{name: name, value: val})
8136 }
8137 func findEntry(entries []Entry, name string) int32 {
8138 for i := int32(0); i < int32(len(entries)); i++ {
8139 if entries[i].name == name {
8140 return entries[i].value
8141 }
8142 }
8143 return -1
8144 }
8145 func main() {
8146 var entries []Entry
8147 entries = addEntry(entries, "x", 10)
8148 entries = addEntry(entries, "y", 20)
8149 v := findEntry(entries, "x")
8150 _ = v
8151 }
8152 `, func(ir string) {
8153 assert("199: addEntry defined", strings.Contains(ir, "@main.addEntry"))
8154 assert("199: findEntry defined", strings.Contains(ir, "@main.findEntry"))
8155 })
8156
8157 // Test 200: bytes.Buffer-like pattern (write methods, grow)
8158 test(200, `package main
8159 type Buffer struct {
8160 buf []byte
8161 }
8162 func (b *Buffer) Len() int32 { return int32(len(b.buf)) }
8163 func (b *Buffer) Bytes() []byte { return b.buf }
8164 func (b *Buffer) String() string { return string(b.buf) }
8165 func (b *Buffer) Reset() { b.buf = b.buf[:0] }
8166 func (b *Buffer) WriteByte(c byte) {
8167 b.buf = append(b.buf, c)
8168 }
8169 func (b *Buffer) WriteString(s string) {
8170 b.buf = append(b.buf, s...)
8171 }
8172 func (b *Buffer) Write(p []byte) int32 {
8173 b.buf = append(b.buf, p...)
8174 return int32(len(p))
8175 }
8176 func main() {
8177 var buf Buffer
8178 buf.WriteByte('(')
8179 buf.WriteString("hello")
8180 buf.WriteByte(')')
8181 s := buf.String()
8182 _ = s
8183 }
8184 `, func(ir string) {
8185 assert("200: WriteByte defined", strings.Contains(ir, "@main.Buffer.WriteByte"))
8186 assert("200: WriteString defined", strings.Contains(ir, "@main.Buffer.WriteString"))
8187 assert("200: String defined", strings.Contains(ir, "@main.Buffer.String"))
8188 })
8189
8190 // Test 201: Checker-like pattern with Info struct and map lookups
8191 test(201, `package main
8192 type Node interface{ nodeTag() }
8193 type Expr interface {
8194 Node
8195 exprTag()
8196 }
8197 type Name struct { Value string }
8198 func (n *Name) nodeTag() {}
8199 func (n *Name) exprTag() {}
8200 type TypeAndValue struct {
8201 Type int32
8202 mode int32
8203 }
8204 func (tv TypeAndValue) IsValue() bool { return tv.mode == 1 || tv.mode == 2 }
8205 func (tv TypeAndValue) IsConst() bool { return tv.mode == 3 }
8206 type Info struct {
8207 Types map[Expr]TypeAndValue
8208 Defs map[*Name]int32
8209 }
8210 func NewInfo() *Info {
8211 return &Info{
8212 Types: map[Expr]TypeAndValue{},
8213 Defs: map[*Name]int32{},
8214 }
8215 }
8216 func (info *Info) TypeOf(e Expr) int32 {
8217 if tv, ok := info.Types[e]; ok {
8218 return tv.Type
8219 }
8220 return 0
8221 }
8222 func main() {
8223 info := NewInfo()
8224 n := &Name{Value: "x"}
8225 info.Types[n] = TypeAndValue{Type: 42, mode: 1}
8226 t := info.TypeOf(n)
8227 _ = t
8228 }
8229 `, func(ir string) {
8230 assert("201: NewInfo defined", strings.Contains(ir, "@main.NewInfo"))
8231 assert("201: TypeOf defined", strings.Contains(ir, "@main.Info.TypeOf"))
8232 })
8233
8234 // Test 202: Multi-level pointer chain (a->b->c field access)
8235 test(202, `package main
8236 type Inner struct {
8237 value int32
8238 }
8239 type Middle struct {
8240 inner *Inner
8241 name string
8242 }
8243 type Outer struct {
8244 mid *Middle
8245 tag int32
8246 }
8247 func getValue(o *Outer) int32 {
8248 return o.mid.inner.value
8249 }
8250 func getName(o *Outer) string {
8251 return o.mid.name
8252 }
8253 func main() {
8254 i := &Inner{value: 42}
8255 m := &Middle{inner: i, name: "hello"}
8256 o := &Outer{mid: m, tag: 1}
8257 v := getValue(o)
8258 n := getName(o)
8259 _ = v
8260 _ = n
8261 }
8262 `, func(ir string) {
8263 assert("202: getValue defined", strings.Contains(ir, "@main.getValue"))
8264 assert("202: getName defined", strings.Contains(ir, "@main.getName"))
8265 })
8266
8267 // Test 203: String comparison in if/else chain
8268 test(203, `package main
8269 func classify(s string) int32 {
8270 if s == "int" {
8271 return 1
8272 } else if s == "string" {
8273 return 2
8274 } else if s == "bool" {
8275 return 3
8276 }
8277 return 0
8278 }
8279 func main() {
8280 c := classify("int")
8281 _ = c
8282 }
8283 `, func(ir string) {
8284 assert("203: classify defined", strings.Contains(ir, "@main.classify"))
8285 })
8286
8287 // Test 204: Variadic-like append pattern
8288 test(204, `package main
8289 func joinStrings(sep string, parts []string) string {
8290 if len(parts) == 0 {
8291 return ""
8292 }
8293 result := parts[0]
8294 for i := int32(1); i < int32(len(parts)); i++ {
8295 result = result | sep | parts[i]
8296 }
8297 return result
8298 }
8299 func main() {
8300 parts := []string{"a", "b", "c"}
8301 s := joinStrings(", ", parts)
8302 _ = s
8303 }
8304 `, func(ir string) {
8305 assert("204: joinStrings defined", strings.Contains(ir, "@main.joinStrings"))
8306 })
8307
8308 // Test 205: Alloc with field initialization in loop
8309 test(205, `package main
8310 type Node struct {
8311 key string
8312 value int32
8313 next *Node
8314 }
8315 func buildList(keys []string) *Node {
8316 var head *Node
8317 for i := int32(len(keys)) - 1; i >= 0; i-- {
8318 n := &Node{key: keys[i], value: i, next: head}
8319 head = n
8320 }
8321 return head
8322 }
8323 func main() {
8324 keys := []string{"a", "b", "c"}
8325 list := buildList(keys)
8326 _ = list
8327 }
8328 `, func(ir string) {
8329 assert("205: buildList defined", strings.Contains(ir, "@main.buildList"))
8330 })
8331
8332 // Test 206: Token types with const enums (no globals)
8333 test(206, `package main
8334 type Token uint32
8335 const (
8336 _ Token = iota
8337 EOF
8338 NameType
8339 Literal
8340 tokenCount
8341 )
8342 const _ uint64 = 1 << (tokenCount - 1)
8343 func contains(tokset uint64, tok Token) bool {
8344 return tokset&(1<<tok) != 0
8345 }
8346 func main() {
8347 b := contains(1<<EOF|1<<NameType, Literal)
8348 _ = b
8349 }
8350 `, func(ir string) {
8351 assert("206: contains defined", strings.Contains(ir, "@main.contains"))
8352 })
8353
8354 // Test 207: Full tc_types-like pattern (Type interface, Named types, methods)
8355 test(207, `package main
8356 type Type interface {
8357 Underlying() Type
8358 String() string
8359 }
8360 type BasicInfo int32
8361 const (
8362 IsBoolean BasicInfo = 1 << iota
8363 IsInteger
8364 IsUnsigned
8365 IsFloat
8366 IsString
8367 IsUntyped
8368 )
8369 type BasicKind int32
8370 type Basic struct {
8371 kind BasicKind
8372 info BasicInfo
8373 name string
8374 }
8375 func (b *Basic) Underlying() Type { return b }
8376 func (b *Basic) String() string { return b.name }
8377 func (b *Basic) Kind() BasicKind { return b.kind }
8378 func (b *Basic) Info() BasicInfo { return b.info }
8379 func (b *Basic) Name() string { return b.name }
8380 type Slice struct {
8381 elem Type
8382 }
8383 func (s *Slice) Underlying() Type { return s }
8384 func (s *Slice) String() string { return "[]" | s.elem.String() }
8385 func (s *Slice) Elem() Type { return s.elem }
8386 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
8387 type Pointer struct {
8388 base Type
8389 }
8390 func (p *Pointer) Underlying() Type { return p }
8391 func (p *Pointer) String() string { return "*" | p.base.String() }
8392 func (p *Pointer) Elem() Type { return p.base }
8393 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
8394 type Named struct {
8395 name string
8396 under Type
8397 methods []*Func
8398 }
8399 func (n *Named) Underlying() Type { return n.under }
8400 func (n *Named) String() string { return n.name }
8401 func (n *Named) NumMethods() int32 { return int32(len(n.methods)) }
8402 func (n *Named) Method(i int32) *Func { return n.methods[i] }
8403 func (n *Named) AddMethod(m *Func) { n.methods = append(n.methods, m) }
8404 type Func struct {
8405 name string
8406 typ Type
8407 }
8408 func (f *Func) Name() string { return f.name }
8409 func (f *Func) Type() Type { return f.typ }
8410 func main() {
8411 intType := &Basic{kind: 2, info: IsInteger, name: "int"}
8412 sliceType := NewSlice(intType)
8413 ptrType := NewPointer(intType)
8414 named := &Named{name: "MyInt", under: intType}
8415 named.AddMethod(&Func{name: "String", typ: intType})
8416 s1 := intType.String()
8417 s2 := sliceType.String()
8418 s3 := ptrType.String()
8419 n := named.NumMethods()
8420 _ = s1
8421 _ = s2
8422 _ = s3
8423 _ = n
8424 }
8425 `, func(ir string) {
8426 assert("207: Basic.String defined", strings.Contains(ir, "@main.Basic.String"))
8427 assert("207: Slice.String defined", strings.Contains(ir, "@main.Slice.String"))
8428 assert("207: Pointer.String defined", strings.Contains(ir, "@main.Pointer.String"))
8429 assert("207: Named.AddMethod defined", strings.Contains(ir, "@main.Named.AddMethod"))
8430 })
8431
8432 // Test 208: Checker-like pattern with type resolution
8433 test(208, `package main
8434 type Type interface {
8435 Underlying() Type
8436 }
8437 type Basic208 struct {
8438 kind int32
8439 name string
8440 }
8441 func (b *Basic208) Underlying() Type { return b }
8442 type Pointer208 struct {
8443 base Type
8444 }
8445 func (p *Pointer208) Underlying() Type { return p }
8446 func (p *Pointer208) Elem() Type { return p.base }
8447 type Checker struct {
8448 pkg string
8449 types map[string]Type
8450 }
8451 func NewChecker(pkg string) *Checker {
8452 return &Checker{pkg: pkg, types: map[string]Type{}}
8453 }
8454 func (c *Checker) Define(name string, t Type) {
8455 c.types[name] = t
8456 }
8457 func (c *Checker) Resolve(name string) Type {
8458 t, ok := c.types[name]
8459 if ok {
8460 return t
8461 }
8462 return nil
8463 }
8464 func (c *Checker) IsPointer(t Type) bool {
8465 _, ok := t.(*Pointer208)
8466 return ok
8467 }
8468 func main() {
8469 c := NewChecker("main")
8470 intT := &Basic208{kind: 1, name: "int"}
8471 c.Define("int", intT)
8472 c.Define("*int", &Pointer208{base: intT})
8473 t := c.Resolve("int")
8474 ip := c.IsPointer(t)
8475 _ = ip
8476 }
8477 `, func(ir string) {
8478 assert("208: NewChecker defined", strings.Contains(ir, "@main.NewChecker"))
8479 assert("208: Resolve defined", strings.Contains(ir, "@main.Checker.Resolve"))
8480 assert("208: IsPointer defined", strings.Contains(ir, "@main.Checker.IsPointer"))
8481 })
8482
8483 // Test 209: Full scanner pattern with rune processing
8484 test(209, `package main
8485 type Scanner struct {
8486 src []byte
8487 pos int32
8488 ch rune
8489 chw int32
8490 }
8491 func (s *Scanner) peek() rune {
8492 if s.pos >= int32(len(s.src)) {
8493 return -1
8494 }
8495 return rune(s.src[s.pos])
8496 }
8497 func (s *Scanner) next() {
8498 if s.pos >= int32(len(s.src)) {
8499 s.ch = -1
8500 s.chw = 0
8501 return
8502 }
8503 s.ch = rune(s.src[s.pos])
8504 s.chw = 1
8505 s.pos++
8506 }
8507 func (s *Scanner) skipSpace() {
8508 for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' || s.ch == '\r' {
8509 s.next()
8510 }
8511 }
8512 func isLetter(ch rune) bool {
8513 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'
8514 }
8515 func isDigit(ch rune) bool {
8516 return ch >= '0' && ch <= '9'
8517 }
8518 func (s *Scanner) scanIdent() string {
8519 start := s.pos - s.chw
8520 for isLetter(s.ch) || isDigit(s.ch) {
8521 s.next()
8522 }
8523 return string(s.src[start : s.pos-s.chw])
8524 }
8525 func (s *Scanner) scanNumber() string {
8526 start := s.pos - s.chw
8527 for isDigit(s.ch) {
8528 s.next()
8529 }
8530 return string(s.src[start : s.pos-s.chw])
8531 }
8532 func (s *Scanner) scanString() string {
8533 start := s.pos
8534 for s.ch != '"' && s.ch >= 0 {
8535 s.next()
8536 }
8537 val := string(s.src[start : s.pos-s.chw])
8538 if s.ch == '"' {
8539 s.next()
8540 }
8541 return val
8542 }
8543 type TokenKind int32
8544 const (
8545 TokEOF TokenKind = iota
8546 TokIdent
8547 TokNumber
8548 TokString
8549 TokPunct
8550 )
8551 type ScanToken struct {
8552 kind TokenKind
8553 value string
8554 }
8555 func (s *Scanner) scan() ScanToken {
8556 s.skipSpace()
8557 if s.ch < 0 {
8558 return ScanToken{kind: TokEOF}
8559 }
8560 if isLetter(s.ch) {
8561 return ScanToken{kind: TokIdent, value: s.scanIdent()}
8562 }
8563 if isDigit(s.ch) {
8564 return ScanToken{kind: TokNumber, value: s.scanNumber()}
8565 }
8566 if s.ch == '"' {
8567 s.next()
8568 return ScanToken{kind: TokString, value: s.scanString()}
8569 }
8570 ch := string([]byte{byte(s.ch)})
8571 s.next()
8572 return ScanToken{kind: TokPunct, value: ch}
8573 }
8574 func main() {
8575 sc := &Scanner{src: []byte("hello 42 \"world\""), ch: ' '}
8576 sc.next()
8577 t1 := sc.scan()
8578 t2 := sc.scan()
8579 t3 := sc.scan()
8580 _ = t1
8581 _ = t2
8582 _ = t3
8583 }
8584 `, func(ir string) {
8585 assert("209: scan defined", strings.Contains(ir, "@main.Scanner.scan"))
8586 assert("209: scanIdent defined", strings.Contains(ir, "@main.Scanner.scanIdent"))
8587 assert("209: scanString defined", strings.Contains(ir, "@main.Scanner.scanString"))
8588 })
8589
8590 // Test 210a: Incremental - many types to reproduce void field bug
8591 test(2100, `package main
8592 type Type interface {
8593 Underlying() Type
8594 String() string
8595 }
8596 type BasicInfo int32
8597 type BasicKind int32
8598 type Basic struct {
8599 kind BasicKind
8600 info BasicInfo
8601 name string
8602 }
8603 func (b *Basic) Underlying() Type { return b }
8604 func (b *Basic) String() string { return b.name }
8605 type Slice struct{ elem Type }
8606 func (s *Slice) Underlying() Type { return s }
8607 func (s *Slice) String() string { return "[]" | s.elem.String() }
8608 func (s *Slice) Elem() Type { return s.elem }
8609 type Pointer struct{ base Type }
8610 func (p *Pointer) Underlying() Type { return p }
8611 func (p *Pointer) String() string { return "*" | p.base.String() }
8612 func (p *Pointer) Elem() Type { return p.base }
8613 type TCMap struct {
8614 key Type
8615 elem Type
8616 }
8617 func (m *TCMap) Underlying() Type { return m }
8618 func (m *TCMap) String() string { return "map" }
8619 type TCInterface struct {
8620 methods []string
8621 }
8622 func (t *TCInterface) Underlying() Type { return t }
8623 func (t *TCInterface) String() string { return "interface" }
8624 type Signature struct {
8625 recv *TCVar
8626 params *Tuple
8627 results *Tuple
8628 }
8629 func (s *Signature) Underlying() Type { return s }
8630 func (s *Signature) String() string { return "func" }
8631 type Named struct {
8632 name string
8633 under Type
8634 methods []*TCFunc
8635 }
8636 func (n *Named) Underlying() Type { return n.under }
8637 func (n *Named) String() string { return n.name }
8638 type Tuple struct{ vars []*TCVar }
8639 type Object interface {
8640 Name() string
8641 Type() Type
8642 Exported() bool
8643 }
8644 type object struct {
8645 name string
8646 typ Type
8647 }
8648 func (o *object) Name() string { return o.name }
8649 func (o *object) Type() Type { return o.typ }
8650 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
8651 type TypeName struct{ object }
8652 func NewTypeName(name string, typ Type) *TypeName {
8653 return &TypeName{object{name: name, typ: typ}}
8654 }
8655 type TCVar struct {
8656 name string
8657 typ Type
8658 }
8659 func (v *TCVar) Name() string { return v.name }
8660 func (v *TCVar) Type() Type { return v.typ }
8661 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
8662 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
8663 return &TCVar{name: name, typ: typ}
8664 }
8665 type TCFunc struct {
8666 object
8667 sig *Signature
8668 }
8669 type TCPackage struct {
8670 path string
8671 name string
8672 scope *Scope
8673 }
8674 func NewTCPackage(path string, name string) *TCPackage {
8675 return &TCPackage{path: path, name: name, scope: NewScope(nil)}
8676 }
8677 type Scope struct {
8678 parent *Scope
8679 elems map[string]Object
8680 }
8681 func NewScope(parent *Scope) *Scope {
8682 return &Scope{parent: parent, elems: map[string]Object{}}
8683 }
8684 func (s *Scope) Lookup(name string) Object {
8685 return s.elems[name]
8686 }
8687 func (s *Scope) Insert(obj Object) Object {
8688 nm := obj.Name()
8689 if alt, ok := s.elems[nm]; ok {
8690 return alt
8691 }
8692 s.elems[nm] = obj
8693 return nil
8694 }
8695 func (s *Scope) LookupParent(name string) (*Scope, Object) {
8696 for sc := s; sc != nil; sc = sc.parent {
8697 if obj, ok := sc.elems[name]; ok {
8698 return sc, obj
8699 }
8700 }
8701 return nil, nil
8702 }
8703 func (s *Scope) Names() []string {
8704 names := []string{:0:len(s.elems)}
8705 for n := range s.elems {
8706 names = append(names, n)
8707 }
8708 return names
8709 }
8710 func (p *TCPackage) Path() string { return p.path }
8711 func (p *TCPackage) Name() string { return p.name }
8712 func (p *TCPackage) Scope() *Scope { return p.scope }
8713 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
8714 type exprMode uint8
8715 const (
8716 modeInvalid exprMode = iota
8717 modeValue
8718 modeVar
8719 modeConst
8720 )
8721 type TypeAndValue struct {
8722 Typ Type
8723 mode exprMode
8724 }
8725 func (tv TypeAndValue) IsValue() bool { return tv.mode == modeValue || tv.mode == modeVar }
8726 func main() {
8727 b := &Basic{kind: 2, info: 2, name: "int"}
8728 pkg := NewTCPackage("main", "main")
8729 tn := NewTypeName("MyType", b)
8730 pkg.Scope().Insert(tn)
8731 f := NewTCField(pkg, "x", b, false)
8732 _ = f
8733 }
8734 `, func(ir string) {
8735 assert("210a: NewTypeName no void", !strings.Contains(ir, "void %typ"))
8736 assert("210a: NewTCField no void", !strings.Contains(ir, "void %typ"))
8737 })
8738
8739 // Test 210: Large concat - tc_types + tc_scope + tc_object + tc_info patterns
8740 src210 := []byte(`package main
8741 type Type interface {
8742 Underlying() Type
8743 String() string
8744 }
8745 type BasicInfo int32
8746 const (
8747 IsBoolean BasicInfo = 1 << iota
8748 IsInteger
8749 IsUnsigned
8750 IsFloat
8751 IsString210
8752 IsUntyped
8753 )
8754 type BasicKind int32
8755 type Basic struct {
8756 kind BasicKind
8757 info BasicInfo
8758 name string
8759 }
8760 func (b *Basic) Underlying() Type { return b }
8761 func (b *Basic) String() string { return b.name }
8762 func (b *Basic) Kind() BasicKind { return b.kind }
8763 func (b *Basic) Info() BasicInfo { return b.info }
8764 type Slice struct{ elem Type }
8765 func (s *Slice) Underlying() Type { return s }
8766 func (s *Slice) String() string { return "[]" | s.elem.String() }
8767 func (s *Slice) Elem() Type { return s.elem }
8768 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
8769 type Pointer struct{ base Type }
8770 func (p *Pointer) Underlying() Type { return p }
8771 func (p *Pointer) String() string { return "*" | p.base.String() }
8772 func (p *Pointer) Elem() Type { return p.base }
8773 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
8774 type TCMap struct {
8775 key Type
8776 elem Type
8777 }
8778 func (m *TCMap) Underlying() Type { return m }
8779 func (m *TCMap) String() string { return "map" }
8780 func (m *TCMap) Key() Type { return m.key }
8781 func (m *TCMap) Elem() Type { return m.elem }
8782 type TCInterface struct {
8783 methods []string
8784 }
8785 func (t *TCInterface) Underlying() Type { return t }
8786 func (t *TCInterface) String() string { return "interface" }
8787 func (t *TCInterface) NumMethods() int32 { return int32(len(t.methods)) }
8788 type Signature struct {
8789 recv *TCVar
8790 params *Tuple
8791 results *Tuple
8792 }
8793 func NewSignature(recv *TCVar, params *Tuple, results *Tuple) *Signature {
8794 return &Signature{recv: recv, params: params, results: results}
8795 }
8796 func (s *Signature) Underlying() Type { return s }
8797 func (s *Signature) String() string { return "func" }
8798 func (s *Signature) Recv() *TCVar { return s.recv }
8799 func (s *Signature) Params() *Tuple { return s.params }
8800 func (s *Signature) Results() *Tuple { return s.results }
8801 type Named struct {
8802 name string
8803 under Type
8804 methods []*TCFunc
8805 }
8806 func (n *Named) Underlying() Type { return n.under }
8807 func (n *Named) String() string { return n.name }
8808 func (n *Named) NumMethods() int32 { return int32(len(n.methods)) }
8809 func (n *Named) Method(i int32) *TCFunc { return n.methods[i] }
8810 func (n *Named) AddMethod(m *TCFunc) { n.methods = append(n.methods, m) }
8811 type Tuple struct{ vars []*TCVar }
8812 func NewTuple(vars []*TCVar) *Tuple { return &Tuple{vars: vars} }
8813 func (t *Tuple) Len() int32 { return int32(len(t.vars)) }
8814 func (t *Tuple) At(i int32) *TCVar { return t.vars[i] }
8815 type Object interface {
8816 Name() string
8817 Type() Type
8818 Pkg() *TCPackage
8819 Exported() bool
8820 }
8821 type object struct {
8822 pkg *TCPackage
8823 name string
8824 typ Type
8825 }
8826 func (o *object) Name() string { return o.name }
8827 func (o *object) Type() Type { return o.typ }
8828 func (o *object) Pkg() *TCPackage { return o.pkg }
8829 func (o *object) Exported() bool { return len(o.name) > 0 && o.name[0] >= 'A' && o.name[0] <= 'Z' }
8830 type TypeName struct{ object }
8831 func NewTypeName(pkg *TCPackage, name string, typ Type) *TypeName {
8832 return &TypeName{object{pkg: pkg, name: name, typ: typ}}
8833 }
8834 type TCVar struct {
8835 pkg *TCPackage
8836 name string
8837 typ Type
8838 anonymous bool
8839 }
8840 func NewTCField(pkg *TCPackage, name string, typ Type, anonymous bool) *TCVar {
8841 return &TCVar{pkg: pkg, name: name, typ: typ, anonymous: anonymous}
8842 }
8843 func (v *TCVar) Name() string { return v.name }
8844 func (v *TCVar) Type() Type { return v.typ }
8845 func (v *TCVar) Pkg() *TCPackage { return v.pkg }
8846 func (v *TCVar) Exported() bool { return len(v.name) > 0 && v.name[0] >= 'A' && v.name[0] <= 'Z' }
8847 func (v *TCVar) Anonymous() bool { return v.anonymous }
8848 type TCFunc struct {
8849 object
8850 sig *Signature
8851 }
8852 func (f *TCFunc) Signature() *Signature { return f.sig }
8853 type TCPackage struct {
8854 path string
8855 name string
8856 scope *Scope
8857 imports []*TCPackage
8858 complete bool
8859 }
8860 func NewTCPackage(path string, name string) *TCPackage {
8861 return &TCPackage{
8862 path: path,
8863 name: name,
8864 scope: NewScope(nil),
8865 }
8866 }
8867 func (p *TCPackage) Path() string { return p.path }
8868 func (p *TCPackage) Name() string { return p.name }
8869 func (p *TCPackage) Scope() *Scope { return p.scope }
8870 func (p *TCPackage) Complete() bool { return p.complete }
8871 func (p *TCPackage) MarkComplete() { p.complete = true }
8872 func (p *TCPackage) String() string { return "package " | p.name | " (" | p.path | ")" }
8873 func (p *TCPackage) Imports() []*TCPackage { return p.imports }
8874 type Scope struct {
8875 parent *Scope
8876 children []*Scope
8877 elems map[string]Object
8878 }
8879 func NewScope(parent *Scope) *Scope {
8880 return &Scope{parent: parent, elems: map[string]Object{}}
8881 }
8882 func (s *Scope) Parent() *Scope { return s.parent }
8883 func (s *Scope) Len() int32 { return int32(len(s.elems)) }
8884 func (s *Scope) Lookup(name string) Object {
8885 return s.elems[name]
8886 }
8887 func (s *Scope) LookupParent(name string) (*Scope, Object) {
8888 for sc := s; sc != nil; sc = sc.parent {
8889 if obj, ok := sc.elems[name]; ok {
8890 return sc, obj
8891 }
8892 }
8893 return nil, nil
8894 }
8895 func (s *Scope) Insert(obj Object) Object {
8896 name := obj.Name()
8897 if alt, ok := s.elems[name]; ok {
8898 return alt
8899 }
8900 s.elems[name] = obj
8901 return nil
8902 }
8903 func (s *Scope) Names() []string {
8904 names := []string{:0:len(s.elems)}
8905 for n := range s.elems {
8906 names = append(names, n)
8907 }
8908 return names
8909 }
8910 type exprMode uint8
8911 const (
8912 modeInvalid exprMode = iota
8913 modeValue
8914 modeVar
8915 modeConst
8916 modeType
8917 )
8918 type TypeAndValue struct {
8919 Typ Type
8920 mode exprMode
8921 }
8922 func (tv TypeAndValue) IsValue() bool { return tv.mode == modeValue || tv.mode == modeVar }
8923 func (tv TypeAndValue) IsConst() bool { return tv.mode == modeConst }
8924 func main() {
8925 intT := &Basic{kind: 2, info: IsInteger, name: "int"}
8926 strT := &Basic{kind: 17, info: IsString210, name: "string"}
8927 sliceInt := NewSlice(intT)
8928 ptrInt := NewPointer(intT)
8929 pkg := NewTCPackage("main", "main")
8930 scope := pkg.Scope()
8931 tn := NewTypeName(pkg, "MyType", intT)
8932 scope.Insert(tn)
8933 field := NewTCField(pkg, "x", intT, false)
8934 sig := NewSignature(nil, NewTuple([]*TCVar{field}), NewTuple([]*TCVar{NewTCField(nil, "", strT, false)}))
8935 named := &Named{name: "MyStruct", under: intT}
8936 named.AddMethod(&TCFunc{object: object{pkg: pkg, name: "String", typ: sig}, sig: sig})
8937 _, obj := scope.LookupParent("MyType")
8938 if obj != nil {
8939 n := obj.Name()
8940 _ = n
8941 }
8942 s1 := sliceInt.String()
8943 s2 := ptrInt.String()
8944 nm := named.NumMethods()
8945 m0 := named.Method(0)
8946 ms := m0.Signature()
8947 _ = s1
8948 _ = s2
8949 _ = nm
8950 _ = ms
8951 tv := TypeAndValue{Typ: intT, mode: modeValue}
8952 isVal := tv.IsValue()
8953 _ = isVal
8954 }
8955 `)
8956 name210 := []byte("main")
8957 h210 := compileToIR(
8958 uintptr(unsafe.Pointer(&src210[0])), int32(len(src210)),
8959 uintptr(unsafe.Pointer(&name210[0])), int32(len(name210)),
8960 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
8961 )
8962 ir210 := getIR(h210)
8963 if ir210 == "" {
8964 assert("210: full type system concat produces IR", false)
8965 } else {
8966 assert("210: has NewTCPackage", strings.Contains(ir210, "@main.NewTCPackage"))
8967 assert("210: has Scope.LookupParent", strings.Contains(ir210, "@main.Scope.LookupParent"))
8968 assert("210: has TypeAndValue.IsValue", strings.Contains(ir210, "@main.TypeAndValue.IsValue"))
8969 assert("210: no parse error", !strings.Contains(ir210, "parse error"))
8970 voidFieldCount := strings.Count(ir210, "void %typ")
8971 fmt.Println("=== Full type system concat ===")
8972 fmt.Printf("IR size: %d bytes, functions: ~%d, void fields: %d (known issue)\n", len(ir210),
8973 strings.Count(ir210, "\ndefine "), voidFieldCount)
8974 }
8975 irFree(h210)
8976
8977 // Test 211: Variadic function - definition + call
8978 test(211, `package main
8979
8980 func sum(nums ...int32) int32 {
8981 total := int32(0)
8982 for _, n := range nums {
8983 total = total + n
8984 }
8985 return total
8986 }
8987
8988 func main() {
8989 s := sum(1, 2, 3)
8990 _ = s
8991 }
8992 `, func(ir string) {
8993 assert("211: has sum", strings.Contains(ir, "@main.sum"))
8994 assert("211: sum takes slice", strings.Contains(ir, "define i32 @main.sum({ptr, i64, i64} %nums"))
8995 assert("211: makeslice len 3", strings.Contains(ir, "sext i32 3 to i64"))
8996 assert("211: call passes slice", strings.Contains(ir, "call i32 @main.sum({ptr, i64, i64}"))
8997 })
8998
8999 // Test 213: Variadic call with zero args
9000 test(213, `package main
9001
9002 func sum(nums ...int32) int32 {
9003 return int32(0)
9004 }
9005
9006 func main() {
9007 s := sum()
9008 _ = s
9009 }
9010 `, func(ir string) {
9011 assert("213: has sum", strings.Contains(ir, "@main.sum"))
9012 assert("213: nil slice arg", strings.Contains(ir, "call i32 @main.sum({ptr, i64, i64} zeroinitializer"))
9013 })
9014
9015 // Test 214: Variadic with fixed args
9016 test(214, `package main
9017
9018 func printf(format string, args ...int32) int32 {
9019 return int32(0)
9020 }
9021
9022 func main() {
9023 s := printf("hello", 1, 2)
9024 _ = s
9025 }
9026 `, func(ir string) {
9027 assert("214: has printf", strings.Contains(ir, "@main.printf"))
9028 assert("214: takes string then slice", strings.Contains(ir, "define i32 @main.printf({ptr, i64, i64} %format, {ptr, i64, i64} %args"))
9029 })
9030
9031 // Test 215: String building with | operator, method chains
9032 test(215, `package main
9033
9034 type Builder struct {
9035 buf []byte
9036 }
9037
9038 func (b *Builder) write(s string) {
9039 b.buf = b.buf | []byte(s)
9040 }
9041
9042 func (b *Builder) writeInt(n int32) {
9043 if n == 0 {
9044 b.buf = append(b.buf, byte('0'))
9045 return
9046 }
9047 tmp := []byte{:0:10}
9048 for n > 0 {
9049 tmp = append(tmp, byte('0' + n % 10))
9050 n = n / 10
9051 }
9052 for i := len(tmp) - 1; i >= 0; i = i - 1 {
9053 b.buf = append(b.buf, tmp[i])
9054 }
9055 }
9056
9057 func (b *Builder) String() string {
9058 return string(b.buf)
9059 }
9060
9061 func main() {
9062 b := &Builder{buf: []byte{:0:64}}
9063 b.write("hello")
9064 b.write(" ")
9065 b.write("world")
9066 b.writeInt(42)
9067 s := b.String()
9068 _ = s
9069 }
9070 `, func(ir string) {
9071 assert("215: has Builder.write", strings.Contains(ir, "@main.Builder.write"))
9072 assert("215: has Builder.writeInt", strings.Contains(ir, "@main.Builder.writeInt"))
9073 assert("215: has Builder.String", strings.Contains(ir, "@main.Builder.String"))
9074 assert("215: uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
9075 })
9076
9077 // Test 216: Type switch with multiple cases
9078 test(216, `package main
9079
9080 type Node interface {
9081 Kind() int32
9082 }
9083
9084 type Literal struct {
9085 val int32
9086 }
9087 func (l *Literal) Kind() int32 { return 1 }
9088
9089 type BinOp struct {
9090 op int32
9091 lhs Node
9092 rhs Node
9093 }
9094 func (b *BinOp) Kind() int32 { return 2 }
9095
9096 type UnaryOp struct {
9097 op int32
9098 operand Node
9099 }
9100 func (u *UnaryOp) Kind() int32 { return 3 }
9101
9102 func eval(n Node) int32 {
9103 switch v := n.(type) {
9104 case *Literal:
9105 return v.val
9106 case *BinOp:
9107 l := eval(v.lhs)
9108 r := eval(v.rhs)
9109 if v.op == 1 {
9110 return l + r
9111 }
9112 return l - r
9113 case *UnaryOp:
9114 x := eval(v.operand)
9115 return -x
9116 }
9117 return 0
9118 }
9119
9120 func main() {
9121 a := &Literal{val: 10}
9122 b := &Literal{val: 3}
9123 sum := &BinOp{op: 1, lhs: a, rhs: b}
9124 neg := &UnaryOp{op: 1, operand: a}
9125 r1 := eval(sum)
9126 r2 := eval(neg)
9127 _ = r1
9128 _ = r2
9129 }
9130 `, func(ir string) {
9131 assert("216: has eval", strings.Contains(ir, "@main.eval"))
9132 assert("216: type switch has typeid", strings.Contains(ir, "typeid"))
9133 assert("216: recursive call", strings.Count(ir, "call i32 @main.eval") >= 2)
9134 })
9135
9136 // Test 217: Map with string keys, comma-ok lookup, delete
9137 test(217, `package main
9138
9139 func lookup(m map[string]int32, key string) (int32, bool) {
9140 v, ok := m[key]
9141 return v, ok
9142 }
9143
9144 func main() {
9145 m := map[string]int32{}
9146 m["hello"] = 1
9147 m["world"] = 2
9148 v, ok := lookup(m, "hello")
9149 _ = v
9150 _ = ok
9151 delete(m, "world")
9152 n := len(m)
9153 _ = n
9154 }
9155 `, func(ir string) {
9156 assert("217: has lookup", strings.Contains(ir, "@main.lookup"))
9157 assert("217: map make", strings.Contains(ir, "hashmapMake"))
9158 assert("217: map update", strings.Contains(ir, "hashmapContentSet"))
9159 assert("217: map delete", strings.Contains(ir, "hashmapDelete") || strings.Contains(ir, "hashmapBinaryDelete"))
9160 })
9161
9162 // Test 218: Function value as variable, call through variable
9163 test(218, `package main
9164
9165 type Transformer func(int32) int32
9166
9167 func apply(f Transformer, x int32) int32 {
9168 return f(x)
9169 }
9170
9171 func double(x int32) int32 {
9172 return x + x
9173 }
9174
9175 func main() {
9176 var f Transformer
9177 f = double
9178 r := apply(f, 5)
9179 _ = r
9180 }
9181 `, func(ir string) {
9182 assert("218: has apply", strings.Contains(ir, "@main.apply"))
9183 assert("218: has double", strings.Contains(ir, "@main.double"))
9184 assert("218: indirect call", strings.Contains(ir, "call i32 %"))
9185 })
9186
9187 // Test 219: Multi-value return with type assertion comma-ok
9188 test(219, `package main
9189
9190 type Value interface {
9191 String() string
9192 }
9193
9194 type IntVal struct {
9195 v int32
9196 }
9197 func (i *IntVal) String() string { return "int" }
9198
9199 func asInt(v Value) (*IntVal, bool) {
9200 i, ok := v.(*IntVal)
9201 return i, ok
9202 }
9203
9204 func main() {
9205 var v Value
9206 v = &IntVal{v: 42}
9207 i, ok := asInt(v)
9208 _ = i
9209 _ = ok
9210 }
9211 `, func(ir string) {
9212 assert("219: has asInt", strings.Contains(ir, "@main.asInt"))
9213 assert("219: type assert", strings.Contains(ir, "typeid") || strings.Contains(ir, "icmp"))
9214 })
9215
9216 // Test 220: Const block with iota, string concat in method
9217 test(220, `package main
9218
9219 const (
9220 KindA = iota
9221 KindB
9222 KindC
9223 )
9224
9225 type Item struct {
9226 kind int32
9227 name string
9228 }
9229
9230 func (it *Item) Label() string {
9231 prefix := "item:"
9232 return prefix | it.name
9233 }
9234
9235 func kindName(k int32) string {
9236 switch k {
9237 case KindA:
9238 return "A"
9239 case KindB:
9240 return "B"
9241 case KindC:
9242 return "C"
9243 }
9244 return "?"
9245 }
9246
9247 func main() {
9248 it := &Item{kind: KindB, name: "test"}
9249 s := it.Label()
9250 n := kindName(KindC)
9251 _ = s
9252 _ = n
9253 }
9254 `, func(ir string) {
9255 assert("220: has Item.Label", strings.Contains(ir, "@main.Item.Label"))
9256 assert("220: has kindName", strings.Contains(ir, "@main.kindName"))
9257 assert("220: string concat uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
9258 assert("220: switch has icmp", strings.Contains(ir, "icmp eq"))
9259 })
9260
9261 // Test 221: Mini IR emitter - exercises self-compilation patterns
9262 test221src := []byte(`package main
9263
9264 type Type interface {
9265 Kind() int32
9266 LLVMType() string
9267 }
9268
9269 type BasicType struct {
9270 kind int32
9271 name string
9272 llvm string
9273 }
9274 func (b *BasicType) Kind() int32 { return b.kind }
9275 func (b *BasicType) LLVMType() string { return b.llvm }
9276
9277 type PtrType struct {
9278 elem Type
9279 }
9280 func (p *PtrType) Kind() int32 { return 4 }
9281 func (p *PtrType) LLVMType() string { return "ptr" }
9282
9283 type SliceType struct {
9284 elem Type
9285 }
9286 func (s *SliceType) Kind() int32 { return 5 }
9287 func (s *SliceType) LLVMType() string { return "{ptr, i64, i64}" }
9288
9289 type FuncSig struct {
9290 params []Type
9291 results []Type
9292 }
9293 func (f *FuncSig) Kind() int32 { return 6 }
9294 func (f *FuncSig) LLVMType() string { return "ptr" }
9295
9296 type Emitter struct {
9297 buf []byte
9298 nextReg int32
9299 types map[string]Type
9300 }
9301
9302 func NewEmitter() *Emitter {
9303 e := &Emitter{
9304 buf: []byte{:0:256},
9305 types: map[string]Type{},
9306 }
9307 e.types["int32"] = &BasicType{kind: 1, name: "int32", llvm: "i32"}
9308 e.types["string"] = &BasicType{kind: 14, name: "string", llvm: "{ptr, i64, i64}"}
9309 return e
9310 }
9311
9312 func (e *Emitter) w(s string) {
9313 e.buf = e.buf | []byte(s)
9314 }
9315
9316 func (e *Emitter) nextName() string {
9317 e.nextReg = e.nextReg + 1
9318 return "%t" | itoa(e.nextReg)
9319 }
9320
9321 func itoa(n int32) string {
9322 if n == 0 { return "0" }
9323 buf := []byte{:0:10}
9324 for n > 0 {
9325 buf = append(buf, byte('0' + n % 10))
9326 n = n / 10
9327 }
9328 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
9329 buf[i], buf[j] = buf[j], buf[i]
9330 }
9331 return string(buf)
9332 }
9333
9334 func (e *Emitter) emitType(t Type) string {
9335 switch v := t.(type) {
9336 case *BasicType:
9337 return v.llvm
9338 case *PtrType:
9339 return "ptr"
9340 case *SliceType:
9341 return "{ptr, i64, i64}"
9342 case *FuncSig:
9343 return e.emitFuncType(v)
9344 }
9345 return "void"
9346 }
9347
9348 func (e *Emitter) emitFuncType(f *FuncSig) string {
9349 result := "void"
9350 if len(f.results) > 0 {
9351 result = e.emitType(f.results[0])
9352 }
9353 s := result | " ("
9354 for i, p := range f.params {
9355 if i > 0 {
9356 s = s | ", "
9357 }
9358 s = s | e.emitType(p)
9359 }
9360 s = s | ")"
9361 return s
9362 }
9363
9364 func (e *Emitter) emitAlloc(t Type) string {
9365 name := e.nextName()
9366 e.w(" " | name | " = alloca " | e.emitType(t) | "\n")
9367 return name
9368 }
9369
9370 func (e *Emitter) emitStore(addr string, val string, t Type) {
9371 e.w(" store " | e.emitType(t) | " " | val | ", ptr " | addr | "\n")
9372 }
9373
9374 func (e *Emitter) emitLoad(addr string, t Type) string {
9375 name := e.nextName()
9376 e.w(" " | name | " = load " | e.emitType(t) | ", ptr " | addr | "\n")
9377 return name
9378 }
9379
9380 func (e *Emitter) lookupType(name string) (Type, bool) {
9381 t, ok := e.types[name]
9382 return t, ok
9383 }
9384
9385 func (e *Emitter) Result() string {
9386 return string(e.buf)
9387 }
9388
9389 func main() {
9390 em := NewEmitter()
9391 intT, _ := em.lookupType("int32")
9392 strT, _ := em.lookupType("string")
9393
9394 sig := &FuncSig{
9395 params: []Type{intT, strT},
9396 results: []Type{intT},
9397 }
9398
9399 em.w("define " | em.emitFuncType(sig) | " @main.add(")
9400 em.w(em.emitType(intT) | " %a, ")
9401 em.w(em.emitType(strT) | " %b) {\n")
9402 em.w("entry:\n")
9403 a1 := em.emitAlloc(intT)
9404 em.emitStore(a1, "%a", intT)
9405 v1 := em.emitLoad(a1, intT)
9406 _ = v1
9407 em.w(" ret " | em.emitType(intT) | " " | v1 | "\n")
9408 em.w("}\n")
9409
9410 ir := em.Result()
9411 _ = ir
9412 }
9413 `)
9414 name221 := []byte("main")
9415 h221 := compileToIR(
9416 uintptr(unsafe.Pointer(&test221src[0])), int32(len(test221src)),
9417 uintptr(unsafe.Pointer(&name221[0])), int32(len(name221)),
9418 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
9419 )
9420 ir221 := getIR(h221)
9421 if ir221 == "" {
9422 assert("221: mini emitter produces IR", false)
9423 } else {
9424 voidCount := strings.Count(ir221, "void %")
9425 funcCount := strings.Count(ir221, "\ndefine ")
9426 lineCount := strings.Count(string(test221src), "\n")
9427 fmt.Printf("=== Mini emitter test (221) ===\n")
9428 fmt.Printf("Source: %d lines, %d bytes | IR: %d bytes, %d functions, void fields: %d\n",
9429 lineCount, len(test221src), len(ir221), funcCount, voidCount)
9430 assert("221: produces IR", len(ir221) > 1000)
9431 assert("221: zero void fields", voidCount == 0)
9432 assert("221: has NewEmitter", strings.Contains(ir221, "@main.NewEmitter"))
9433 assert("221: has emitType", strings.Contains(ir221, "@main.Emitter.emitType"))
9434 assert("221: has emitFuncType", strings.Contains(ir221, "@main.Emitter.emitFuncType"))
9435 assert("221: has itoa", strings.Contains(ir221, "@main.itoa"))
9436 assert("221: has lookupType", strings.Contains(ir221, "@main.Emitter.lookupType"))
9437 assert("221: type switch typeid", strings.Contains(ir221, "typeid"))
9438 assert("221: uses sliceAppend", strings.Contains(ir221, "@runtime.sliceAppend"))
9439 assert("221: uses hashmapMake", strings.Contains(ir221, "@runtime.hashmapMake"))
9440 llvmVerify("221: mini emitter", ir221)
9441 }
9442 irFree(h221)
9443
9444 // Test 222: Scope/Object hierarchy - mirrors tc_scope.mx, tc_object.mx patterns
9445 test(222, `package main
9446
9447 type Object interface {
9448 Name() string
9449 Type() Type
9450 }
9451
9452 type Type interface {
9453 Underlying() Type
9454 String() string
9455 }
9456
9457 type Scope struct {
9458 parent *Scope
9459 entries map[string]Object
9460 }
9461
9462 func NewScope(parent *Scope) *Scope {
9463 return &Scope{parent: parent, entries: map[string]Object{}}
9464 }
9465
9466 func (s *Scope) Insert(obj Object) Object {
9467 name := obj.Name()
9468 old, ok := s.entries[name]
9469 if ok {
9470 return old
9471 }
9472 s.entries[name] = obj
9473 return nil
9474 }
9475
9476 func (s *Scope) Lookup(name string) Object {
9477 obj, ok := s.entries[name]
9478 if ok {
9479 return obj
9480 }
9481 if s.parent != nil {
9482 return s.parent.Lookup(name)
9483 }
9484 return nil
9485 }
9486
9487 func (s *Scope) Len() int32 {
9488 return int32(len(s.entries))
9489 }
9490
9491 type BasicType struct {
9492 kind int32
9493 name string
9494 }
9495 func (b *BasicType) Underlying() Type { return b }
9496 func (b *BasicType) String() string { return b.name }
9497
9498 type PointerType struct {
9499 base Type
9500 }
9501 func (p *PointerType) Underlying() Type { return p }
9502 func (p *PointerType) String() string { return "*" | p.base.String() }
9503
9504 type TypeName struct {
9505 name string
9506 typ Type
9507 }
9508 func (t *TypeName) Name() string { return t.name }
9509 func (t *TypeName) Type() Type { return t.typ }
9510
9511 type Var struct {
9512 name string
9513 typ Type
9514 }
9515 func (v *Var) Name() string { return v.name }
9516 func (v *Var) Type() Type { return v.typ }
9517
9518 type Func struct {
9519 name string
9520 typ Type
9521 }
9522 func (f *Func) Name() string { return f.name }
9523 func (f *Func) Type() Type { return f.typ }
9524
9525 type Checker struct {
9526 pkg *Package
9527 scope *Scope
9528 }
9529
9530 type Package struct {
9531 name string
9532 scope *Scope
9533 }
9534
9535 func NewChecker(pkg *Package) *Checker {
9536 return &Checker{pkg: pkg, scope: pkg.scope}
9537 }
9538
9539 func (c *Checker) lookup(name string) Object {
9540 return c.scope.Lookup(name)
9541 }
9542
9543 func (c *Checker) resolveTypeName(name string) Type {
9544 obj := c.lookup(name)
9545 if obj == nil {
9546 return nil
9547 }
9548 tn, ok := obj.(*TypeName)
9549 if !ok {
9550 return nil
9551 }
9552 return tn.typ
9553 }
9554
9555 func main() {
9556 universe := NewScope(nil)
9557 intT := &BasicType{kind: 2, name: "int32"}
9558 strT := &BasicType{kind: 14, name: "string"}
9559 boolT := &BasicType{kind: 1, name: "bool"}
9560
9561 universe.Insert(&TypeName{name: "int32", typ: intT})
9562 universe.Insert(&TypeName{name: "string", typ: strT})
9563 universe.Insert(&TypeName{name: "bool", typ: boolT})
9564
9565 pkgScope := NewScope(universe)
9566 pkg := &Package{name: "main", scope: pkgScope}
9567
9568 ptrInt := &PointerType{base: intT}
9569 pkgScope.Insert(&TypeName{name: "PtrInt", typ: ptrInt})
9570 pkgScope.Insert(&Var{name: "x", typ: intT})
9571 pkgScope.Insert(&Func{name: "foo", typ: nil})
9572
9573 chk := NewChecker(pkg)
9574
9575 t1 := chk.resolveTypeName("int32")
9576 t2 := chk.resolveTypeName("PtrInt")
9577 t3 := chk.resolveTypeName("missing")
9578 _ = t1
9579 _ = t2
9580 _ = t3
9581
9582 n := pkgScope.Len()
9583 _ = n
9584
9585 s1 := intT.String()
9586 s2 := ptrInt.String()
9587 _ = s1
9588 _ = s2
9589 }
9590 `, func(ir string) {
9591 assert("222: has NewScope", strings.Contains(ir, "@main.NewScope"))
9592 assert("222: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
9593 assert("222: has Scope.Insert", strings.Contains(ir, "@main.Scope.Insert"))
9594 assert("222: has NewChecker", strings.Contains(ir, "@main.NewChecker"))
9595 assert("222: has resolveTypeName", strings.Contains(ir, "@main.Checker.resolveTypeName"))
9596 assert("222: recursive lookup", strings.Contains(ir, "call {ptr, ptr} @main.Scope.Lookup"))
9597 assert("222: type assert typeid", strings.Contains(ir, "typeid"))
9598 assert("222: map operations", strings.Contains(ir, "hashmapMake"))
9599 })
9600
9601 // Test 223: Multi-value assign (tuple swap), array literal, byte operations
9602 test(223, `package main
9603
9604 func swap(a []int32) {
9605 if len(a) >= 2 {
9606 a[0], a[1] = a[1], a[0]
9607 }
9608 }
9609
9610 func reverseBytes(s string) string {
9611 b := []byte(s)
9612 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
9613 b[i], b[j] = b[j], b[i]
9614 }
9615 return string(b)
9616 }
9617
9618 func countChar(s string, c byte) int32 {
9619 n := int32(0)
9620 for i := 0; i < len(s); i = i + 1 {
9621 if s[i] == c {
9622 n = n + 1
9623 }
9624 }
9625 return n
9626 }
9627
9628 func main() {
9629 a := []int32{10, 20, 30}
9630 swap(a)
9631 s := reverseBytes("hello")
9632 n := countChar("banana", byte('a'))
9633 _ = s
9634 _ = n
9635 }
9636 `, func(ir string) {
9637 assert("223: has swap", strings.Contains(ir, "@main.swap"))
9638 assert("223: has reverseBytes", strings.Contains(ir, "@main.reverseBytes"))
9639 assert("223: has countChar", strings.Contains(ir, "@main.countChar"))
9640 })
9641
9642 // Test 224: Nested method calls, chained returns, early returns in switch
9643 test(224, `package main
9644
9645 type Node interface {
9646 Emit(buf *Buffer)
9647 }
9648
9649 type Buffer struct {
9650 data []byte
9651 }
9652
9653 func NewBuffer() *Buffer {
9654 return &Buffer{data: []byte{:0:64}}
9655 }
9656
9657 func (b *Buffer) Write(s string) {
9658 b.data = b.data | []byte(s)
9659 }
9660
9661 func (b *Buffer) WriteByte(c byte) {
9662 b.data = append(b.data, c)
9663 }
9664
9665 func (b *Buffer) String() string {
9666 return string(b.data)
9667 }
9668
9669 func (b *Buffer) Len() int32 {
9670 return int32(len(b.data))
9671 }
9672
9673 type IntNode struct {
9674 val int32
9675 }
9676
9677 func (n *IntNode) Emit(buf *Buffer) {
9678 if n.val == 0 {
9679 buf.Write("0")
9680 return
9681 }
9682 v := n.val
9683 tmp := []byte{:0:10}
9684 for v > 0 {
9685 tmp = append(tmp, byte('0' + v % 10))
9686 v = v / 10
9687 }
9688 for i, j := 0, len(tmp)-1; i < j; i, j = i+1, j-1 {
9689 tmp[i], tmp[j] = tmp[j], tmp[i]
9690 }
9691 buf.Write(string(tmp))
9692 }
9693
9694 type StrNode struct {
9695 val string
9696 }
9697
9698 func (n *StrNode) Emit(buf *Buffer) {
9699 buf.WriteByte(byte('"'))
9700 buf.Write(n.val)
9701 buf.WriteByte(byte('"'))
9702 }
9703
9704 type BinNode struct {
9705 op string
9706 lhs Node
9707 rhs Node
9708 }
9709
9710 func (n *BinNode) Emit(buf *Buffer) {
9711 buf.WriteByte(byte('('))
9712 n.lhs.Emit(buf)
9713 buf.Write(" " | n.op | " ")
9714 n.rhs.Emit(buf)
9715 buf.WriteByte(byte(')'))
9716 }
9717
9718 func main() {
9719 buf := NewBuffer()
9720 expr := &BinNode{
9721 op: "+",
9722 lhs: &IntNode{val: 42},
9723 rhs: &BinNode{
9724 op: "*",
9725 lhs: &IntNode{val: 3},
9726 rhs: &StrNode{val: "x"},
9727 },
9728 }
9729 expr.Emit(buf)
9730 result := buf.String()
9731 n := buf.Len()
9732 _ = result
9733 _ = n
9734 }
9735 `, func(ir string) {
9736 assert("224: has Buffer.Write", strings.Contains(ir, "@main.Buffer.Write"))
9737 assert("224: has IntNode.Emit", strings.Contains(ir, "@main.IntNode.Emit"))
9738 assert("224: has BinNode.Emit", strings.Contains(ir, "@main.BinNode.Emit"))
9739 assert("224: interface dispatch", strings.Contains(ir, "typeid"))
9740 assert("224: uses sliceAppend", strings.Contains(ir, "@runtime.sliceAppend"))
9741 })
9742
9743 // Test 225: Byte indexing, tagless switch
9744 test(225, `package main
9745
9746 func isExported(name string) bool {
9747 if len(name) == 0 {
9748 return false
9749 }
9750 c := name[0]
9751 if c >= 65 && c <= 90 {
9752 return true
9753 }
9754 return false
9755 }
9756
9757 func classify(x int32) string {
9758 switch {
9759 case x < 0:
9760 return "negative"
9761 case x == 0:
9762 return "zero"
9763 case x > 100:
9764 return "large"
9765 }
9766 return "small"
9767 }
9768
9769 func main() {
9770 e1 := isExported("Hello")
9771 e2 := isExported("hello")
9772 _ = e1
9773 _ = e2
9774 c1 := classify(-1)
9775 c2 := classify(0)
9776 c3 := classify(200)
9777 c4 := classify(50)
9778 _ = c1
9779 _ = c2
9780 _ = c3
9781 _ = c4
9782 }
9783 `, func(ir string) {
9784 assert("225: has isExported", strings.Contains(ir, "@main.isExported"))
9785 assert("225: has classify", strings.Contains(ir, "@main.classify"))
9786 })
9787
9788 // Test 226: Named return values, multi-return with named results
9789 test(226, `package main
9790
9791 func divide(a int32, b int32) (q int32, r int32) {
9792 if b == 0 {
9793 return 0, 0
9794 }
9795 q = a / b
9796 r = a - q*b
9797 return q, r
9798 }
9799
9800 func main() {
9801 q, r := divide(17, 5)
9802 _ = q
9803 _ = r
9804 }
9805 `, func(ir string) {
9806 assert("226: has divide", strings.Contains(ir, "@main.divide"))
9807 assert("226: divide returns tuple", strings.Contains(ir, "define {i32, i32} @main.divide"))
9808 })
9809
9810 // Test 227: For-range over map, delete from map
9811 test(227, `package main
9812
9813 func countEntries(m map[string]int32) int32 {
9814 n := int32(0)
9815 for range m {
9816 n = n + 1
9817 }
9818 return n
9819 }
9820
9821 func removeKey(m map[string]int32, key string) {
9822 delete(m, key)
9823 }
9824
9825 func main() {
9826 m := map[string]int32{"a": 1, "b": 2, "c": 3}
9827 n := countEntries(m)
9828 _ = n
9829 removeKey(m, "b")
9830 }
9831 `, func(ir string) {
9832 assert("227: has countEntries", strings.Contains(ir, "@main.countEntries"))
9833 assert("227: has removeKey", strings.Contains(ir, "@main.removeKey"))
9834 assert("227: hashmapNext for range", strings.Contains(ir, "hashmapNext"))
9835 assert("227: hashmapBinaryDelete", strings.Contains(ir, "hashmapBinaryDelete"))
9836 })
9837
9838 // Test 228: Multi-level struct embedding, promoted methods
9839 test(228, `package main
9840
9841 type base struct {
9842 name string
9843 }
9844
9845 func (b *base) Name() string { return b.name }
9846
9847 type TypeName struct {
9848 base
9849 typ int32
9850 }
9851
9852 func NewTypeName(name string, typ int32) *TypeName {
9853 return &TypeName{base: base{name: name}, typ: typ}
9854 }
9855
9856 func main() {
9857 tn := NewTypeName("int", 1)
9858 n := tn.Name()
9859 _ = n
9860 }
9861 `, func(ir string) {
9862 assert("228: has NewTypeName", strings.Contains(ir, "@main.NewTypeName"))
9863 assert("228: has base.Name", strings.Contains(ir, "@main.base.Name"))
9864 assert("228: promoted method call", strings.Contains(ir, "call") && strings.Contains(ir, "base.Name"))
9865 })
9866
9867 // Test 229: Simple append with spread
9868 test(229, `package main
9869
9870 func join(a []byte, b []byte) []byte {
9871 return append(a, b...)
9872 }
9873
9874 func main() {
9875 x := []byte("abc")
9876 y := []byte("def")
9877 z := join(x, y)
9878 _ = z
9879 }
9880 `, func(ir string) {
9881 assert("229: has join", strings.Contains(ir, "@main.join"))
9882 assert("229: sliceAppend for spread", strings.Contains(ir, "sliceAppend"))
9883 })
9884
9885 // Test 230: []byte(nil) conversion + spread append (self-compile pattern)
9886 test(230, `package main
9887
9888 func copyBytes(s []byte) []byte {
9889 return append([]byte(nil), s...)
9890 }
9891
9892 func main() {
9893 x := []byte("test")
9894 y := copyBytes(x)
9895 _ = y
9896 }
9897 `, func(ir string) {
9898 assert("230: has copyBytes", strings.Contains(ir, "@main.copyBytes"))
9899 })
9900
9901 // Test 231: String copy via append+spread (common bootstrap pattern)
9902 test(231, `package main
9903
9904 func copyString(s string) string {
9905 return string(append([]byte(nil), s...))
9906 }
9907
9908 func main() {
9909 s := copyString("hello")
9910 _ = s
9911 }
9912 `, func(ir string) {
9913 assert("231: has copyString", strings.Contains(ir, "@main.copyString"))
9914 })
9915
9916 // Test 232: Closures and function values
9917 test(232, `package main
9918
9919 func apply(f func(int32) int32, x int32) int32 {
9920 return f(x)
9921 }
9922
9923 func main() {
9924 double := func(x int32) int32 { return x * 2 }
9925 r := apply(double, 5)
9926 _ = r
9927 }
9928 `, func(ir string) {
9929 assert("232: has apply", strings.Contains(ir, "@main.apply"))
9930 })
9931
9932 // Test 233: Closure with capture (makeAdder pattern)
9933 test(233, `package main
9934
9935 func makeAdder(n int32) func(int32) int32 {
9936 return func(x int32) int32 {
9937 return x + n
9938 }
9939 }
9940
9941 func main() {
9942 add3 := makeAdder(3)
9943 r := add3(10)
9944 _ = r
9945 }
9946 `, func(ir string) {
9947 assert("233: has makeAdder", strings.Contains(ir, "@main.makeAdder"))
9948 })
9949
9950 // Test 234: Named return values with bare return
9951 test(234, `package main
9952
9953 func divide(a int32, b int32) (q int32, r int32) {
9954 if b == 0 {
9955 return
9956 }
9957 q = a / b
9958 r = a - q*b
9959 return
9960 }
9961
9962 func main() {
9963 q, r := divide(17, 5)
9964 _ = q
9965 _ = r
9966 q2, r2 := divide(5, 0)
9967 _ = q2
9968 _ = r2
9969 }
9970 `, func(ir string) {
9971 assert("234: has divide", strings.Contains(ir, "@main.divide"))
9972 assert("234: returns tuple", strings.Contains(ir, "define {i32, i32} @main.divide"))
9973 })
9974
9975 test(235, `package main
9976
9977 type Color int32
9978 const (
9979 Red Color = iota
9980 Green
9981 Blue
9982 )
9983
9984 func colorName(c Color) string {
9985 switch c {
9986 case Red:
9987 return "red"
9988 case Green:
9989 return "green"
9990 case Blue:
9991 return "blue"
9992 }
9993 return "unknown"
9994 }
9995
9996 func main() {
9997 n := colorName(Green)
9998 _ = n
9999 }
10000 `, func(ir string) {
10001 assert("235: has colorName", strings.Contains(ir, "@main.colorName"))
10002 assert("235: Red=0 in switch", strings.Contains(ir, "icmp eq i32 %t2, 0"))
10003 assert("235: Green=1 in switch", strings.Contains(ir, "icmp eq i32 %t2, 1"))
10004 assert("235: Blue=2 in switch", strings.Contains(ir, "icmp eq i32 %t2, 2"))
10005 })
10006
10007 test(236, `package main
10008
10009 type Op int32
10010 const (
10011 _ Op = iota
10012 Add
10013 Sub
10014 Mul
10015 Div
10016 )
10017
10018 func priority(op Op) int32 {
10019 switch op {
10020 case Add, Sub:
10021 return 1
10022 case Mul, Div:
10023 return 2
10024 }
10025 return 0
10026 }
10027
10028 func main() {
10029 p := priority(Mul)
10030 _ = p
10031 }
10032 `, func(ir string) {
10033 assert("236: has priority", strings.Contains(ir, "@main.priority"))
10034 assert("236: Add=1 (skip blank)", strings.Contains(ir, "i32 1") || strings.Contains(ir, "i32 2"))
10035 })
10036
10037 test(237, `package main
10038
10039 const (
10040 FlagA int32 = 1 << iota
10041 FlagB
10042 FlagC
10043 FlagD
10044 )
10045
10046 func hasFlag(flags int32, f int32) bool {
10047 return flags & f != 0
10048 }
10049
10050 func main() {
10051 flags := FlagA | FlagC
10052 a := hasFlag(flags, FlagA)
10053 b := hasFlag(flags, FlagB)
10054 _ = a
10055 _ = b
10056 }
10057 `, func(ir string) {
10058 assert("237: has hasFlag", strings.Contains(ir, "@main.hasFlag"))
10059 assert("237: has FlagA=1", strings.Contains(ir, "i32 1"))
10060 assert("237: has or op", strings.Contains(ir, " or "))
10061 assert("237: has and op", strings.Contains(ir, " and "))
10062 })
10063
10064 test(238, `package main
10065
10066 func greet(name string) string {
10067 return "hello, " | name | "!"
10068 }
10069
10070 func bits(a int32, b int32) int32 {
10071 return (a | b) & 0xFF
10072 }
10073
10074 func main() {
10075 s := greet("world")
10076 _ = s
10077 r := bits(3, 12)
10078 _ = r
10079 }
10080 `, func(ir string) {
10081 assert("238: has greet", strings.Contains(ir, "@main.greet"))
10082 assert("238: has bits", strings.Contains(ir, "@main.bits"))
10083 assert("238: string concat via sliceAppend", strings.Contains(ir, "runtime.sliceAppend"))
10084 assert("238: bitwise or in bits", strings.Contains(ir, " or "))
10085 assert("238: bitwise and in bits", strings.Contains(ir, " and "))
10086 })
10087
10088 test(239, `package main
10089
10090 type Pos struct {
10091 line int32
10092 col int32
10093 }
10094
10095 type Node struct {
10096 pos Pos
10097 kind int32
10098 }
10099
10100 func makeNode(line int32, col int32, kind int32) *Node {
10101 return &Node{pos: Pos{line: line, col: col}, kind: kind}
10102 }
10103
10104 func getLine(n *Node) int32 {
10105 return n.pos.line
10106 }
10107
10108 func main() {
10109 n := makeNode(10, 5, 1)
10110 l := getLine(n)
10111 _ = l
10112 }
10113 `, func(ir string) {
10114 assert("239: has makeNode", strings.Contains(ir, "@main.makeNode"))
10115 assert("239: has getLine", strings.Contains(ir, "@main.getLine"))
10116 assert("239: nested struct access", strings.Contains(ir, "getelementptr"))
10117 })
10118
10119 test(240, `package main
10120
10121 type Builder struct {
10122 buf []byte
10123 }
10124
10125 func (b *Builder) writeByte(c byte) {
10126 b.buf = append(b.buf, c)
10127 }
10128
10129 func (b *Builder) writeString(s string) {
10130 b.buf = append(b.buf, s...)
10131 }
10132
10133 func (b *Builder) String() string {
10134 return string(b.buf)
10135 }
10136
10137 func main() {
10138 b := &Builder{}
10139 b.writeByte('H')
10140 b.writeString("ello")
10141 s := b.String()
10142 _ = s
10143 }
10144 `, func(ir string) {
10145 assert("240: has Builder.writeByte", strings.Contains(ir, "@main.Builder.writeByte"))
10146 assert("240: has Builder.writeString", strings.Contains(ir, "@main.Builder.writeString"))
10147 assert("240: has Builder.String", strings.Contains(ir, "@main.Builder.String"))
10148 assert("240: append call", strings.Contains(ir, "runtime.sliceAppend"))
10149 })
10150
10151 test(241, `package main
10152
10153 var counter int32
10154
10155 func inc() int32 {
10156 counter++
10157 return counter
10158 }
10159
10160 func dec() int32 {
10161 counter--
10162 return counter
10163 }
10164
10165 func main() {
10166 a := inc()
10167 b := inc()
10168 c := dec()
10169 _ = a
10170 _ = b
10171 _ = c
10172 }
10173 `, func(ir string) {
10174 assert("241: has inc", strings.Contains(ir, "@main.inc"))
10175 assert("241: has dec", strings.Contains(ir, "@main.dec"))
10176 assert("241: has global counter", strings.Contains(ir, "@main.counter"))
10177 })
10178
10179 test(242, `package main
10180
10181 type Token int32
10182 const (
10183 EOF Token = iota
10184 Ident
10185 Number
10186 Plus
10187 Minus
10188 Star
10189 Slash
10190 Lparen
10191 Rparen
10192 )
10193
10194 func isOperator(t Token) bool {
10195 switch t {
10196 case Plus, Minus, Star, Slash:
10197 return true
10198 }
10199 return false
10200 }
10201
10202 func precedence(t Token) int32 {
10203 switch t {
10204 case Plus, Minus:
10205 return 1
10206 case Star, Slash:
10207 return 2
10208 }
10209 return 0
10210 }
10211
10212 func main() {
10213 t := Star
10214 op := isOperator(t)
10215 p := precedence(t)
10216 _ = op
10217 _ = p
10218 }
10219 `, func(ir string) {
10220 assert("242: has isOperator", strings.Contains(ir, "@main.isOperator"))
10221 assert("242: has precedence", strings.Contains(ir, "@main.precedence"))
10222 assert("242: multi-case switch", strings.Contains(ir, "icmp eq"))
10223 })
10224
10225 test(243, `package main
10226
10227 type Pair struct {
10228 key string
10229 value int32
10230 }
10231
10232 func lookup(pairs []Pair, key string) (int32, bool) {
10233 for i := 0; i < len(pairs); i++ {
10234 if pairs[i].key == key {
10235 return pairs[i].value, true
10236 }
10237 }
10238 return 0, false
10239 }
10240
10241 func main() {
10242 pairs := []Pair{
10243 {key: "a", value: 1},
10244 {key: "b", value: 2},
10245 {key: "c", value: 3},
10246 }
10247 v, ok := lookup(pairs, "b")
10248 _ = v
10249 _ = ok
10250 }
10251 `, func(ir string) {
10252 assert("243: has lookup", strings.Contains(ir, "@main.lookup"))
10253 assert("243: returns tuple", strings.Contains(ir, "{i32, i1}"))
10254 assert("243: slice indexing", strings.Contains(ir, "getelementptr"))
10255 })
10256
10257 test(244, `package main
10258
10259 type Writer interface {
10260 Write(data []byte) int32
10261 }
10262
10263 type Buffer struct {
10264 data []byte
10265 }
10266
10267 func (b *Buffer) Write(data []byte) int32 {
10268 b.data = append(b.data, data...)
10269 return int32(len(data))
10270 }
10271
10272 func (b *Buffer) Len() int32 {
10273 return int32(len(b.data))
10274 }
10275
10276 func writeAll(w Writer, chunks []string) int32 {
10277 total := int32(0)
10278 for i := 0; i < len(chunks); i++ {
10279 n := w.Write([]byte(chunks[i]))
10280 total = total + n
10281 }
10282 return total
10283 }
10284
10285 func main() {
10286 buf := &Buffer{}
10287 chunks := []string{"hello", " ", "world"}
10288 n := writeAll(buf, chunks)
10289 _ = n
10290 l := buf.Len()
10291 _ = l
10292 }
10293 `, func(ir string) {
10294 assert("244: has Buffer.Write", strings.Contains(ir, "@main.Buffer.Write"))
10295 assert("244: has writeAll", strings.Contains(ir, "@main.writeAll"))
10296 assert("244: interface method call", strings.Contains(ir, "call"))
10297 assert("244: has Buffer.Len", strings.Contains(ir, "@main.Buffer.Len"))
10298 })
10299
10300 test(245, `package main
10301
10302 type SSAOp int32
10303 const (
10304 OpAdd SSAOp = iota + 1
10305 OpSub
10306 OpMul
10307 OpOr
10308 OpAnd
10309 )
10310
10311 type SSABinOp struct {
10312 Op SSAOp
10313 X int32
10314 Y int32
10315 }
10316
10317 func eval(b *SSABinOp) int32 {
10318 switch b.Op {
10319 case OpAdd:
10320 return b.X + b.Y
10321 case OpSub:
10322 return b.X - b.Y
10323 case OpMul:
10324 return b.X * b.Y
10325 case OpOr:
10326 return b.X | b.Y
10327 case OpAnd:
10328 return b.X & b.Y
10329 }
10330 return 0
10331 }
10332
10333 func main() {
10334 b := &SSABinOp{Op: OpOr, X: 5, Y: 3}
10335 r := eval(b)
10336 _ = r
10337 }
10338 `, func(ir string) {
10339 assert("245: has eval", strings.Contains(ir, "@main.eval"))
10340 assert("245: switch on field", strings.Contains(ir, "icmp eq"))
10341 assert("245: iota+1 offset", strings.Contains(ir, "i32 4"))
10342 })
10343
10344 test(246, `package main
10345
10346 type Scope struct {
10347 parent *Scope
10348 elems map[string]int32
10349 }
10350
10351 func NewScope(parent *Scope) *Scope {
10352 return &Scope{parent: parent, elems: map[string]int32{}}
10353 }
10354
10355 func (s *Scope) Insert(name string, val int32) {
10356 s.elems[name] = val
10357 }
10358
10359 func (s *Scope) Lookup(name string) (int32, bool) {
10360 v, ok := s.elems[name]
10361 if ok {
10362 return v, true
10363 }
10364 if s.parent != nil {
10365 return s.parent.Lookup(name)
10366 }
10367 return 0, false
10368 }
10369
10370 func main() {
10371 outer := NewScope(nil)
10372 outer.Insert("x", 42)
10373 inner := NewScope(outer)
10374 inner.Insert("y", 7)
10375 v1, _ := inner.Lookup("x")
10376 v2, _ := inner.Lookup("y")
10377 _ = v1
10378 _ = v2
10379 }
10380 `, func(ir string) {
10381 assert("246: has NewScope", strings.Contains(ir, "@main.NewScope"))
10382 assert("246: has Scope.Insert", strings.Contains(ir, "@main.Scope.Insert"))
10383 assert("246: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
10384 assert("246: recursive method call", strings.Contains(ir, "call {i32, i1} @main.Scope.Lookup"))
10385 })
10386
10387 test(247, `package main
10388
10389 type Entry struct {
10390 name string
10391 typ int32
10392 }
10393
10394 type Registry struct {
10395 entries []Entry
10396 }
10397
10398 func (r *Registry) add(name string, typ int32) {
10399 r.entries = append(r.entries, Entry{name: name, typ: typ})
10400 }
10401
10402 func (r *Registry) find(name string) int32 {
10403 for i := 0; i < len(r.entries); i++ {
10404 if r.entries[i].name == name {
10405 return r.entries[i].typ
10406 }
10407 }
10408 return -1
10409 }
10410
10411 func main() {
10412 r := &Registry{}
10413 r.add("int", 1)
10414 r.add("string", 2)
10415 r.add("bool", 3)
10416 t := r.find("string")
10417 _ = t
10418 }
10419 `, func(ir string) {
10420 assert("247: has Registry.add", strings.Contains(ir, "@main.Registry.add"))
10421 assert("247: has Registry.find", strings.Contains(ir, "@main.Registry.find"))
10422 assert("247: append struct to slice", strings.Contains(ir, "runtime.sliceAppend"))
10423 })
10424
10425 test(248, `package main
10426
10427 func prefixMatch(s string, prefix string) bool {
10428 if len(s) < len(prefix) {
10429 return false
10430 }
10431 return s[:len(prefix)] == prefix
10432 }
10433
10434 func trimPrefix(s string, prefix string) string {
10435 if prefixMatch(s, prefix) {
10436 return s[len(prefix):]
10437 }
10438 return s
10439 }
10440
10441 func main() {
10442 r := prefixMatch("hello world", "hello")
10443 _ = r
10444 t := trimPrefix("hello world", "hello")
10445 _ = t
10446 }
10447 `, func(ir string) {
10448 assert("248: has prefixMatch", strings.Contains(ir, "@main.prefixMatch"))
10449 assert("248: has trimPrefix", strings.Contains(ir, "@main.trimPrefix"))
10450 assert("248: string compare", strings.Contains(ir, "runtime.stringEqual"))
10451 assert("248: slice sub-expr", strings.Contains(ir, "extractvalue"))
10452 })
10453
10454 test(249, `package main
10455
10456 type Emitter struct {
10457 buf []byte
10458 indent int32
10459 }
10460
10461 func newEmitter() *Emitter {
10462 return &Emitter{buf: []byte{:0:1024}, indent: 0}
10463 }
10464
10465 func (e *Emitter) w(s string) {
10466 e.buf = append(e.buf, s...)
10467 }
10468
10469 func (e *Emitter) nl() {
10470 e.buf = append(e.buf, '\n')
10471 for i := int32(0); i < e.indent; i++ {
10472 e.buf = append(e.buf, ' ')
10473 e.buf = append(e.buf, ' ')
10474 }
10475 }
10476
10477 func (e *Emitter) enter() {
10478 e.indent++
10479 }
10480
10481 func (e *Emitter) leave() {
10482 if e.indent > 0 {
10483 e.indent--
10484 }
10485 }
10486
10487 func (e *Emitter) String() string {
10488 return string(e.buf)
10489 }
10490
10491 func main() {
10492 em := newEmitter()
10493 em.w("func main() {")
10494 em.enter()
10495 em.nl()
10496 em.w("x := 1")
10497 em.leave()
10498 em.nl()
10499 em.w("}")
10500 s := em.String()
10501 _ = s
10502 }
10503 `, func(ir string) {
10504 assert("249: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
10505 assert("249: has Emitter.nl", strings.Contains(ir, "@main.Emitter.nl"))
10506 assert("249: has Emitter.enter", strings.Contains(ir, "@main.Emitter.enter"))
10507 assert("249: has newEmitter", strings.Contains(ir, "@main.newEmitter"))
10508 assert("249: append byte", strings.Contains(ir, "runtime.sliceAppend"))
10509 })
10510
10511 test(250, `package main
10512
10513 func itoa(n int32) string {
10514 if n == 0 {
10515 return "0"
10516 }
10517 neg := n < 0
10518 if neg {
10519 n = -n
10520 }
10521 buf := []byte{:0:20}
10522 for n > 0 {
10523 buf = append(buf, byte('0' + n % 10))
10524 n = n / 10
10525 }
10526 if neg {
10527 buf = append(buf, '-')
10528 }
10529 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
10530 buf[i], buf[j] = buf[j], buf[i]
10531 }
10532 return string(buf)
10533 }
10534
10535 func main() {
10536 s1 := itoa(0)
10537 s2 := itoa(42)
10538 s3 := itoa(-123)
10539 _ = s1
10540 _ = s2
10541 _ = s3
10542 }
10543 `, func(ir string) {
10544 assert("250: has itoa", strings.Contains(ir, "@main.itoa"))
10545 assert("250: modulo op", strings.Contains(ir, "srem"))
10546 assert("250: division", strings.Contains(ir, "sdiv"))
10547 assert("250: reverse loop", strings.Contains(ir, "icmp slt"))
10548 })
10549
10550 test(251, `package main
10551
10552 type Object interface {
10553 Name() string
10554 }
10555
10556 type Var struct {
10557 name string
10558 typ string
10559 }
10560
10561 func (v *Var) Name() string { return v.name }
10562
10563 type Func struct {
10564 name string
10565 sig string
10566 }
10567
10568 func (f *Func) Name() string { return f.name }
10569
10570 func describe(o Object) string {
10571 switch o := o.(type) {
10572 case *Var:
10573 return "var " | o.name | " " | o.typ
10574 case *Func:
10575 return "func " | o.name | o.sig
10576 }
10577 return "unknown"
10578 }
10579
10580 func main() {
10581 var objs []Object
10582 objs = append(objs, &Var{name: "x", typ: "int"})
10583 objs = append(objs, &Func{name: "foo", sig: "()"})
10584 for i := 0; i < len(objs); i++ {
10585 d := describe(objs[i])
10586 _ = d
10587 }
10588 }
10589 `, func(ir string) {
10590 assert("251: has describe", strings.Contains(ir, "@main.describe"))
10591 assert("251: has Var.Name", strings.Contains(ir, "@main.Var.Name"))
10592 assert("251: has Func.Name", strings.Contains(ir, "@main.Func.Name"))
10593 assert("251: type switch typeid", strings.Contains(ir, "typeid"))
10594 assert("251: string concat", strings.Contains(ir, "runtime.sliceAppend"))
10595 })
10596
10597 test(252, `package main
10598
10599 type Node struct {
10600 kind int32
10601 children []*Node
10602 value string
10603 }
10604
10605 func newLeaf(val string) *Node {
10606 return &Node{kind: 1, value: val}
10607 }
10608
10609 func newBranch(children []*Node) *Node {
10610 return &Node{kind: 2, children: children}
10611 }
10612
10613 func countLeaves(n *Node) int32 {
10614 if n.kind == 1 {
10615 return 1
10616 }
10617 total := int32(0)
10618 for i := 0; i < len(n.children); i++ {
10619 total = total + countLeaves(n.children[i])
10620 }
10621 return total
10622 }
10623
10624 func main() {
10625 a := newLeaf("x")
10626 b := newLeaf("y")
10627 c := newLeaf("z")
10628 branch := newBranch([]*Node{a, b, c})
10629 n := countLeaves(branch)
10630 _ = n
10631 }
10632 `, func(ir string) {
10633 assert("252: has countLeaves", strings.Contains(ir, "@main.countLeaves"))
10634 assert("252: recursive call", strings.Contains(ir, "call i32 @main.countLeaves"))
10635 assert("252: has newBranch", strings.Contains(ir, "@main.newBranch"))
10636 assert("252: slice of ptr indexing", strings.Contains(ir, "getelementptr"))
10637 })
10638
10639 test(253, `package main
10640
10641 type Checker struct {
10642 errors []string
10643 pkg string
10644 }
10645
10646 func (c *Checker) errorf(msg string) {
10647 c.errors = append(c.errors, c.pkg | ": " | msg)
10648 }
10649
10650 func (c *Checker) hasErrors() bool {
10651 return len(c.errors) > 0
10652 }
10653
10654 func (c *Checker) check(name string, typ string) {
10655 if typ == "" {
10656 c.errorf("undefined type for " | name)
10657 return
10658 }
10659 if name == "" {
10660 c.errorf("empty name")
10661 }
10662 }
10663
10664 func main() {
10665 c := &Checker{pkg: "main"}
10666 c.check("x", "int")
10667 c.check("y", "")
10668 has := c.hasErrors()
10669 _ = has
10670 }
10671 `, func(ir string) {
10672 assert("253: has Checker.errorf", strings.Contains(ir, "@main.Checker.errorf"))
10673 assert("253: has Checker.check", strings.Contains(ir, "@main.Checker.check"))
10674 assert("253: has Checker.hasErrors", strings.Contains(ir, "@main.Checker.hasErrors"))
10675 assert("253: string concat in errorf", strings.Contains(ir, "runtime.sliceAppend"))
10676 assert("253: string equal for empty check", strings.Contains(ir, "runtime.stringEqual"))
10677 })
10678
10679 test(254, `package main
10680
10681 type Type interface {
10682 Underlying() Type
10683 String() string
10684 }
10685
10686 type Basic struct {
10687 name string
10688 kind int32
10689 }
10690
10691 func (b *Basic) Underlying() Type { return b }
10692 func (b *Basic) String() string { return b.name }
10693
10694 type Pointer struct {
10695 base Type
10696 }
10697
10698 func (p *Pointer) Underlying() Type { return p }
10699 func (p *Pointer) String() string { return "*" | p.base.String() }
10700 func (p *Pointer) Elem() Type { return p.base }
10701
10702 type Named struct {
10703 name string
10704 underlying Type
10705 }
10706
10707 func (n *Named) Underlying() Type {
10708 if n.underlying != nil {
10709 return n.underlying.Underlying()
10710 }
10711 return n
10712 }
10713
10714 func (n *Named) String() string { return n.name }
10715
10716 func NewPointer(base Type) *Pointer { return &Pointer{base: base} }
10717 func NewNamed(name string, underlying Type) *Named {
10718 return &Named{name: name, underlying: underlying}
10719 }
10720
10721 func isPointer(t Type) bool {
10722 _, ok := t.Underlying().(*Pointer)
10723 return ok
10724 }
10725
10726 func baseType(t Type) Type {
10727 if p, ok := t.Underlying().(*Pointer); ok {
10728 return p.Elem()
10729 }
10730 return t
10731 }
10732
10733 func main() {
10734 intT := &Basic{name: "int", kind: 1}
10735 ptrInt := NewPointer(intT)
10736 named := NewNamed("MyInt", intT)
10737 ptrNamed := NewPointer(named)
10738
10739 s1 := ptrInt.String()
10740 s2 := named.String()
10741 ip := isPointer(ptrNamed)
10742 bt := baseType(ptrNamed)
10743 _ = s1
10744 _ = s2
10745 _ = ip
10746 _ = bt
10747 }
10748 `, func(ir string) {
10749 assert("254: has Pointer.String", strings.Contains(ir, "@main.Pointer.String"))
10750 assert("254: has Named.Underlying", strings.Contains(ir, "@main.Named.Underlying"))
10751 assert("254: has isPointer", strings.Contains(ir, "@main.isPointer"))
10752 assert("254: has baseType", strings.Contains(ir, "@main.baseType"))
10753 assert("254: interface method dispatch", strings.Contains(ir, "typeid"))
10754 })
10755
10756 test(255, `package main
10757
10758 type Instruction interface {
10759 Operands() int32
10760 }
10761
10762 type BinOp struct {
10763 op string
10764 x int32
10765 y int32
10766 }
10767
10768 func (b *BinOp) Operands() int32 { return 2 }
10769
10770 type UnOp struct {
10771 op string
10772 x int32
10773 }
10774
10775 func (u *UnOp) Operands() int32 { return 1 }
10776
10777 type Block struct {
10778 instrs []Instruction
10779 }
10780
10781 func (bl *Block) add(i Instruction) {
10782 bl.instrs = append(bl.instrs, i)
10783 }
10784
10785 func (bl *Block) count() int32 {
10786 total := int32(0)
10787 for i := 0; i < len(bl.instrs); i++ {
10788 total = total + bl.instrs[i].Operands()
10789 }
10790 return total
10791 }
10792
10793 func main() {
10794 bl := &Block{}
10795 bl.add(&BinOp{op: "add", x: 1, y: 2})
10796 bl.add(&UnOp{op: "neg", x: 3})
10797 bl.add(&BinOp{op: "mul", x: 4, y: 5})
10798 c := bl.count()
10799 _ = c
10800 }
10801 `, func(ir string) {
10802 assert("255: has Block.add", strings.Contains(ir, "@main.Block.add"))
10803 assert("255: has Block.count", strings.Contains(ir, "@main.Block.count"))
10804 assert("255: has BinOp.Operands", strings.Contains(ir, "@main.BinOp.Operands"))
10805 assert("255: interface dispatch in count", strings.Contains(ir, "typeid"))
10806 })
10807
10808 test(256, `package main
10809
10810 func reverse(s string) string {
10811 b := []byte(s)
10812 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
10813 b[i], b[j] = b[j], b[i]
10814 }
10815 return string(b)
10816 }
10817
10818 func contains(s string, sub string) bool {
10819 if len(sub) == 0 {
10820 return true
10821 }
10822 if len(sub) > len(s) {
10823 return false
10824 }
10825 for i := 0; i <= len(s)-len(sub); i++ {
10826 if s[i:i+len(sub)] == sub {
10827 return true
10828 }
10829 }
10830 return false
10831 }
10832
10833 func main() {
10834 r := reverse("hello")
10835 _ = r
10836 c := contains("hello world", "world")
10837 _ = c
10838 }
10839 `, func(ir string) {
10840 assert("256: has reverse", strings.Contains(ir, "@main.reverse"))
10841 assert("256: has contains", strings.Contains(ir, "@main.contains"))
10842 assert("256: string equal", strings.Contains(ir, "runtime.stringEqual"))
10843 assert("256: byte swap", strings.Contains(ir, "getelementptr"))
10844 })
10845
10846 test(257, `package main
10847
10848 type Gen struct {
10849 counter int32
10850 prefix string
10851 }
10852
10853 func (g *Gen) emit() string {
10854 p := func(tag string) string {
10855 g.counter++
10856 return g.prefix | tag | itoa257(g.counter)
10857 }
10858 a := p("a")
10859 b := p("b")
10860 c := p("a")
10861 return a | " " | b | " " | c
10862 }
10863
10864 func itoa257(n int32) string {
10865 if n == 0 { return "0" }
10866 buf := []byte{:0:10}
10867 for n > 0 {
10868 buf = append(buf, byte('0' + n % 10))
10869 n = n / 10
10870 }
10871 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
10872 buf[i], buf[j] = buf[j], buf[i]
10873 }
10874 return string(buf)
10875 }
10876
10877 func main() {
10878 g := &Gen{prefix: "%t"}
10879 result := g.emit()
10880 _ = result
10881 }
10882 `, func(ir string) {
10883 assert("257: has Gen.emit", strings.Contains(ir, "@main.Gen.emit"))
10884 assert("257: closure function", strings.Contains(ir, "@main.Gen.emit__anon1"))
10885 })
10886
10887 test(258, `package main
10888
10889 type MapEntry struct {
10890 key string
10891 val int32
10892 }
10893
10894 func sortEntries(entries []MapEntry) {
10895 for i := 1; i < len(entries); i++ {
10896 for j := i; j > 0; j-- {
10897 if entries[j].key < entries[j-1].key {
10898 entries[j], entries[j-1] = entries[j-1], entries[j]
10899 }
10900 }
10901 }
10902 }
10903
10904 func main() {
10905 entries := []MapEntry{
10906 {key: "c", val: 3},
10907 {key: "a", val: 1},
10908 {key: "b", val: 2},
10909 }
10910 sortEntries(entries)
10911 }
10912 `, func(ir string) {
10913 assert("258: has sortEntries", strings.Contains(ir, "@main.sortEntries"))
10914 assert("258: string less-than", strings.Contains(ir, "runtime.stringLess"))
10915 assert("258: swap pattern", strings.Contains(ir, "getelementptr"))
10916 })
10917
10918 test(259, `package main
10919
10920 type Scope struct {
10921 parent *Scope
10922 names map[string]bool
10923 }
10924
10925 func (s *Scope) define(name string) {
10926 s.names[name] = true
10927 }
10928
10929 func (s *Scope) isDefined(name string) bool {
10930 if s.names[name] {
10931 return true
10932 }
10933 if s.parent != nil {
10934 return s.parent.isDefined(name)
10935 }
10936 return false
10937 }
10938
10939 func (s *Scope) allNames() []string {
10940 var result []string
10941 for k, _ := range s.names {
10942 result = append(result, k)
10943 }
10944 return result
10945 }
10946
10947 func main() {
10948 outer := &Scope{names: map[string]bool{}}
10949 outer.define("x")
10950 outer.define("y")
10951 inner := &Scope{parent: outer, names: map[string]bool{}}
10952 inner.define("z")
10953 d := inner.isDefined("x")
10954 names := inner.allNames()
10955 _ = d
10956 _ = names
10957 }
10958 `, func(ir string) {
10959 assert("259: has Scope.define", strings.Contains(ir, "@main.Scope.define"))
10960 assert("259: has Scope.isDefined", strings.Contains(ir, "@main.Scope.isDefined"))
10961 assert("259: has Scope.allNames", strings.Contains(ir, "@main.Scope.allNames"))
10962 assert("259: recursive method", strings.Contains(ir, "call i1 @main.Scope.isDefined"))
10963 assert("259: for-range map", strings.Contains(ir, "hashmapNext"))
10964 })
10965
10966 test(260, `package main
10967
10968 type SSAOp int32
10969 const (
10970 OpIllegal SSAOp = iota
10971 OpAdd
10972 OpSub
10973 OpMul
10974 OpOr
10975 OpAnd
10976 )
10977
10978 type SSAValue interface {
10979 Name() string
10980 Type() string
10981 }
10982
10983 type SSAConst struct {
10984 name string
10985 typ string
10986 val int32
10987 }
10988
10989 func (c *SSAConst) Name() string { return c.name }
10990 func (c *SSAConst) Type() string { return c.typ }
10991
10992 type SSABinOp struct {
10993 name string
10994 typ string
10995 Op SSAOp
10996 X SSAValue
10997 Y SSAValue
10998 }
10999
11000 func (b *SSABinOp) Name() string { return b.name }
11001 func (b *SSABinOp) Type() string { return b.typ }
11002
11003 type Emitter struct {
11004 buf []byte
11005 regs int32
11006 }
11007
11008 func (e *Emitter) w(s string) {
11009 e.buf = append(e.buf, s...)
11010 }
11011
11012 func (e *Emitter) nextReg() string {
11013 e.regs++
11014 return "%t" | itoa260(e.regs)
11015 }
11016
11017 func (e *Emitter) emitBinOp(b *SSABinOp) {
11018 reg := b.Name()
11019 lv := b.X.Name()
11020 rv := b.Y.Name()
11021 op := ""
11022 switch b.Op {
11023 case OpAdd:
11024 op = "add"
11025 case OpSub:
11026 op = "sub"
11027 case OpMul:
11028 op = "mul"
11029 case OpOr:
11030 op = "or"
11031 case OpAnd:
11032 op = "and"
11033 }
11034 e.w(" ") ; e.w(reg) ; e.w(" = ") ; e.w(op) ; e.w(" ")
11035 e.w(b.Type()) ; e.w(" ") ; e.w(lv) ; e.w(", ") ; e.w(rv) ; e.w("\n")
11036 }
11037
11038 func (e *Emitter) emit(instrs []SSAValue) string {
11039 for i := 0; i < len(instrs); i++ {
11040 switch v := instrs[i].(type) {
11041 case *SSABinOp:
11042 e.emitBinOp(v)
11043 }
11044 }
11045 return string(e.buf)
11046 }
11047
11048 func itoa260(n int32) string {
11049 if n == 0 { return "0" }
11050 buf := []byte{:0:10}
11051 for n > 0 {
11052 buf = append(buf, byte('0' + n % 10))
11053 n = n / 10
11054 }
11055 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
11056 buf[i], buf[j] = buf[j], buf[i]
11057 }
11058 return string(buf)
11059 }
11060
11061 func main() {
11062 c1 := &SSAConst{name: "%c1", typ: "i32", val: 5}
11063 c2 := &SSAConst{name: "%c2", typ: "i32", val: 3}
11064 add := &SSABinOp{name: "%t1", typ: "i32", Op: OpAdd, X: c1, Y: c2}
11065 c3 := &SSAConst{name: "%c3", typ: "i32", val: 7}
11066 mul := &SSABinOp{name: "%t2", typ: "i32", Op: OpMul, X: add, Y: c3}
11067
11068 em := &Emitter{}
11069 var instrs []SSAValue
11070 instrs = append(instrs, add)
11071 instrs = append(instrs, mul)
11072 result := em.emit(instrs)
11073 _ = result
11074 }
11075 `, func(ir string) {
11076 assert("260: has Emitter.emit", strings.Contains(ir, "@main.Emitter.emit"))
11077 assert("260: has Emitter.emitBinOp", strings.Contains(ir, "@main.Emitter.emitBinOp"))
11078 assert("260: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
11079 assert("260: SSAValue interface dispatch", strings.Contains(ir, "typeid"))
11080 assert("260: type switch on SSAValue", strings.Contains(ir, "typeid.ptr.SSABinOp"))
11081 assert("260: append interface coercion", strings.Contains(ir, "typeid.ptr.SSAConst") || strings.Contains(ir, "insertvalue {ptr, ptr}"))
11082 })
11083
11084 test(261, `package main
11085
11086 type TokenKind int32
11087
11088 const (
11089 TokEOF TokenKind = iota
11090 TokIdent
11091 TokNumber
11092 TokPlus
11093 TokMinus
11094 TokStar
11095 )
11096
11097 func (k TokenKind) String() string {
11098 switch k {
11099 case TokEOF:
11100 return "EOF"
11101 case TokIdent:
11102 return "IDENT"
11103 case TokNumber:
11104 return "NUMBER"
11105 case TokPlus:
11106 return "+"
11107 case TokMinus:
11108 return "-"
11109 case TokStar:
11110 return "*"
11111 }
11112 return "?"
11113 }
11114
11115 func (k TokenKind) IsOperator() bool {
11116 return k >= TokPlus && k <= TokStar
11117 }
11118
11119 type Token struct {
11120 kind TokenKind
11121 lit string
11122 }
11123
11124 func (t *Token) String() string {
11125 if t.lit != "" {
11126 return t.kind.String() | "(" | t.lit | ")"
11127 }
11128 return t.kind.String()
11129 }
11130
11131 func main() {
11132 t := &Token{kind: TokIdent, lit: "foo"}
11133 s := t.String()
11134 _ = s
11135 op := TokPlus.IsOperator()
11136 _ = op
11137 name := TokIdent.String()
11138 _ = name
11139 }
11140 `, func(ir string) {
11141 assert("261: method on named int", strings.Contains(ir, "@main.TokenKind.String"))
11142 assert("261: TokenKind.IsOperator", strings.Contains(ir, "@main.TokenKind.IsOperator"))
11143 assert("261: Token.String calls kind.String", strings.Contains(ir, "call {ptr, i64, i64} @main.TokenKind.String"))
11144 assert("261: value receiver method", strings.Contains(ir, "define {ptr, i64, i64} @main.TokenKind.String(i32 %k"))
11145 })
11146
11147 test(262, `package main
11148
11149 type Info int32
11150 const (
11151 IsInteger Info = 1 << iota
11152 IsFloat
11153 IsUnsigned
11154 IsString
11155 IsUntyped
11156 )
11157
11158 func (i Info) Has(flag Info) bool {
11159 return i & flag != 0
11160 }
11161
11162 type BasicKind int32
11163 const (
11164 Int32Kind BasicKind = iota
11165 Uint32Kind
11166 Float64Kind
11167 StringKind
11168 )
11169
11170 type Basic struct {
11171 kind BasicKind
11172 info Info
11173 name string
11174 }
11175
11176 var basics = [4]*Basic{
11177 &Basic{kind: Int32Kind, info: IsInteger, name: "int32"},
11178 &Basic{kind: Uint32Kind, info: IsInteger | IsUnsigned, name: "uint32"},
11179 &Basic{kind: Float64Kind, info: IsFloat, name: "float64"},
11180 &Basic{kind: StringKind, info: IsString, name: "string"},
11181 }
11182
11183 func lookupBasic(kind BasicKind) *Basic {
11184 if int32(kind) >= 0 && int32(kind) < 4 {
11185 return basics[int32(kind)]
11186 }
11187 return nil
11188 }
11189
11190 func main() {
11191 b := lookupBasic(Uint32Kind)
11192 isInt := b.info.Has(IsInteger)
11193 isUns := b.info.Has(IsUnsigned)
11194 isFlt := b.info.Has(IsFloat)
11195 _ = isInt
11196 _ = isUns
11197 _ = isFlt
11198 }
11199 `, func(ir string) {
11200 assert("262: has Info.Has", strings.Contains(ir, "@main.Info.Has"))
11201 assert("262: has lookupBasic", strings.Contains(ir, "@main.lookupBasic"))
11202 assert("262: array global", strings.Contains(ir, "@main.basics"))
11203 assert("262: bitwise and in Has", strings.Contains(ir, " and "))
11204 assert("262: const flags passed to Has", strings.Contains(ir, "i32 1") && strings.Contains(ir, "i32 4"))
11205 })
11206
11207 test(263, `package main
11208
11209 type Member interface {
11210 MemberName() string
11211 }
11212
11213 type Function struct {
11214 name string
11215 params []string
11216 }
11217
11218 func (f *Function) MemberName() string { return f.name }
11219
11220 type Global struct {
11221 name string
11222 typ string
11223 }
11224
11225 func (g *Global) MemberName() string { return g.name }
11226
11227 type Package struct {
11228 members map[string]Member
11229 }
11230
11231 func NewPackage() *Package {
11232 return &Package{members: map[string]Member{}}
11233 }
11234
11235 func (p *Package) addFunc(name string, params []string) {
11236 p.members[name] = &Function{name: name, params: params}
11237 }
11238
11239 func (p *Package) addGlobal(name string, typ string) {
11240 p.members[name] = &Global{name: name, typ: typ}
11241 }
11242
11243 func (p *Package) lookup(name string) Member {
11244 m, ok := p.members[name]
11245 if ok {
11246 return m
11247 }
11248 return nil
11249 }
11250
11251 func (p *Package) sortedNames() []string {
11252 var names []string
11253 for k, _ := range p.members {
11254 names = append(names, k)
11255 }
11256 for i := 1; i < len(names); i++ {
11257 for j := i; j > 0 && names[j] < names[j-1]; j-- {
11258 names[j], names[j-1] = names[j-1], names[j]
11259 }
11260 }
11261 return names
11262 }
11263
11264 func main() {
11265 pkg := NewPackage()
11266 pkg.addFunc("main", nil)
11267 pkg.addFunc("helper", []string{"x", "y"})
11268 pkg.addGlobal("counter", "int32")
11269 m := pkg.lookup("helper")
11270 _ = m
11271 names := pkg.sortedNames()
11272 _ = names
11273 }
11274 `, func(ir string) {
11275 assert("263: has Package.addFunc", strings.Contains(ir, "@main.Package.addFunc"))
11276 assert("263: has Package.lookup", strings.Contains(ir, "@main.Package.lookup"))
11277 assert("263: has Package.sortedNames", strings.Contains(ir, "@main.Package.sortedNames"))
11278 assert("263: map interface store", strings.Contains(ir, "hashmapContentSet"))
11279 assert("263: for-range map", strings.Contains(ir, "hashmapNext"))
11280 assert("263: insertion sort", strings.Contains(ir, "stringLess"))
11281 })
11282
11283 test(264, `package main
11284
11285 type SSAOp int32
11286 const (
11287 OpIllegal SSAOp = iota
11288 OpAdd
11289 OpSub
11290 OpMul
11291 OpQuo
11292 OpRem
11293 OpAnd
11294 OpOr
11295 OpXor
11296 OpShl
11297 OpShr
11298 )
11299
11300 func (op SSAOp) String() string {
11301 switch op {
11302 case OpAdd: return "+"
11303 case OpSub: return "-"
11304 case OpMul: return "*"
11305 case OpQuo: return "/"
11306 case OpRem: return "%"
11307 case OpAnd: return "&"
11308 case OpOr: return "|"
11309 case OpXor: return "^"
11310 case OpShl: return "<<"
11311 case OpShr: return ">>"
11312 }
11313 return "?"
11314 }
11315
11316 type Type interface {
11317 Underlying() Type
11318 String() string
11319 }
11320
11321 type Basic struct {
11322 kind int32
11323 info int32
11324 name string
11325 }
11326
11327 func (b *Basic) Underlying() Type { return b }
11328 func (b *Basic) String() string { return b.name }
11329
11330 type Pointer struct {
11331 base Type
11332 }
11333
11334 func (p *Pointer) Underlying() Type { return p }
11335 func (p *Pointer) String() string { return "*" | p.base.String() }
11336 func (p *Pointer) Elem() Type { return p.base }
11337
11338 type Slice struct {
11339 elem Type
11340 }
11341
11342 func (s *Slice) Underlying() Type { return s }
11343 func (s *Slice) String() string { return "[]" | s.elem.String() }
11344 func (s *Slice) Elem() Type { return s.elem }
11345
11346 type Scope struct {
11347 parent *Scope
11348 elems map[string]Type
11349 }
11350
11351 func NewScope(parent *Scope) *Scope {
11352 return &Scope{parent: parent, elems: map[string]Type{}}
11353 }
11354
11355 func (s *Scope) Insert(name string, t Type) {
11356 s.elems[name] = t
11357 }
11358
11359 func (s *Scope) Lookup(name string) Type {
11360 t, ok := s.elems[name]
11361 if ok {
11362 return t
11363 }
11364 if s.parent != nil {
11365 return s.parent.Lookup(name)
11366 }
11367 return nil
11368 }
11369
11370 type SSAValue interface {
11371 SSAName() string
11372 SSAType() Type
11373 }
11374
11375 type SSAConst struct {
11376 name string
11377 typ Type
11378 val int32
11379 }
11380
11381 func (c *SSAConst) SSAName() string { return c.name }
11382 func (c *SSAConst) SSAType() Type { return c.typ }
11383
11384 type SSABinOp struct {
11385 name string
11386 typ Type
11387 Op SSAOp
11388 X SSAValue
11389 Y SSAValue
11390 }
11391
11392 func (b *SSABinOp) SSAName() string { return b.name }
11393 func (b *SSABinOp) SSAType() Type { return b.typ }
11394
11395 type Emitter struct {
11396 buf []byte
11397 nextReg int32
11398 scope *Scope
11399 }
11400
11401 func NewEmitter() *Emitter {
11402 s := NewScope(nil)
11403 s.Insert("int32", &Basic{kind: 0, info: 1, name: "int32"})
11404 s.Insert("string", &Basic{kind: 1, info: 8, name: "string"})
11405 s.Insert("bool", &Basic{kind: 2, info: 0, name: "bool"})
11406 return &Emitter{buf: []byte{:0:4096}, scope: s}
11407 }
11408
11409 func (e *Emitter) w(s string) {
11410 e.buf = append(e.buf, s...)
11411 }
11412
11413 func (e *Emitter) reg() string {
11414 e.nextReg++
11415 return "%t" | itoa264(e.nextReg)
11416 }
11417
11418 func (e *Emitter) llvmType(t Type) string {
11419 if t == nil {
11420 return "void"
11421 }
11422 switch t := t.Underlying().(type) {
11423 case *Basic:
11424 if t.name == "int32" {
11425 return "i32"
11426 }
11427 if t.name == "bool" {
11428 return "i1"
11429 }
11430 if t.name == "string" {
11431 return "{ptr, i64, i64}"
11432 }
11433 case *Pointer:
11434 return "ptr"
11435 case *Slice:
11436 return "{ptr, i64, i64}"
11437 }
11438 return "void"
11439 }
11440
11441 func (e *Emitter) emitBinOp(b *SSABinOp) string {
11442 reg := e.reg()
11443 lt := e.llvmType(b.X.SSAType())
11444 lv := b.X.SSAName()
11445 rv := b.Y.SSAName()
11446 op := ""
11447 switch b.Op {
11448 case OpAdd: op = "add"
11449 case OpSub: op = "sub"
11450 case OpMul: op = "mul"
11451 case OpOr: op = "or"
11452 case OpAnd: op = "and"
11453 }
11454 if op == "" {
11455 return reg
11456 }
11457 e.w(" ") ; e.w(reg) ; e.w(" = ") ; e.w(op) ; e.w(" ")
11458 e.w(lt) ; e.w(" ") ; e.w(lv) ; e.w(", ") ; e.w(rv) ; e.w("\n")
11459 return reg
11460 }
11461
11462 func (e *Emitter) String() string {
11463 return string(e.buf)
11464 }
11465
11466 func itoa264(n int32) string {
11467 if n == 0 { return "0" }
11468 buf := []byte{:0:10}
11469 for n > 0 {
11470 buf = append(buf, byte('0' + n % 10))
11471 n = n / 10
11472 }
11473 for i, j := int32(0), int32(len(buf)-1); i < j; i, j = i+1, j-1 {
11474 buf[i], buf[j] = buf[j], buf[i]
11475 }
11476 return string(buf)
11477 }
11478
11479 func main() {
11480 em := NewEmitter()
11481 int32Type := em.scope.Lookup("int32")
11482
11483 c1 := &SSAConst{name: "1", typ: int32Type, val: 1}
11484 c2 := &SSAConst{name: "2", typ: int32Type, val: 2}
11485 add := &SSABinOp{name: "%t1", typ: int32Type, Op: OpAdd, X: c1, Y: c2}
11486 c3 := &SSAConst{name: "3", typ: int32Type, val: 3}
11487 mul := &SSABinOp{name: "%t2", typ: int32Type, Op: OpMul, X: add, Y: c3}
11488 c4 := &SSAConst{name: "7", typ: int32Type, val: 7}
11489 bor := &SSABinOp{name: "%t3", typ: int32Type, Op: OpOr, X: mul, Y: c4}
11490
11491 em.emitBinOp(add)
11492 em.emitBinOp(mul)
11493 em.emitBinOp(bor)
11494
11495 result := em.String()
11496 _ = result
11497
11498 lt := em.llvmType(&Pointer{base: int32Type})
11499 _ = lt
11500 st := em.llvmType(&Slice{elem: int32Type})
11501 _ = st
11502 }
11503 `, func(ir string) {
11504 assert("264: has Emitter.emitBinOp", strings.Contains(ir, "@main.Emitter.emitBinOp"))
11505 assert("264: has Emitter.llvmType", strings.Contains(ir, "@main.Emitter.llvmType"))
11506 assert("264: SSAOp.String method on named int", strings.Contains(ir, "@main.SSAOp.String"))
11507 assert("264: Scope.Lookup recursive", strings.Contains(ir, "call {ptr, ptr} @main.Scope.Lookup"))
11508 assert("264: type switch in llvmType", strings.Contains(ir, "typeid"))
11509 assert("264: interface dispatch SSAConst", strings.Contains(ir, "typeid.SSAConst") || strings.Contains(ir, "typeid.ptr.SSAConst"))
11510 assert("264: string concat via |", strings.Contains(ir, "runtime.sliceAppend"))
11511 assert("264: scope map lookup", strings.Contains(ir, "hashmapContentGet"))
11512 })
11513
11514 test(265, `package main
11515
11516 type Instruction interface {
11517 Block() *BasicBlock
11518 InstrString() string
11519 }
11520
11521 type Value interface {
11522 Name() string
11523 Type() string
11524 }
11525
11526 type instrBase struct {
11527 block *BasicBlock
11528 }
11529
11530 func (a *instrBase) Block() *BasicBlock { return a.block }
11531
11532 type register struct {
11533 instrBase
11534 name string
11535 typ string
11536 }
11537
11538 func (r *register) Name() string { return r.name }
11539 func (r *register) Type() string { return r.typ }
11540
11541 type BinOp struct {
11542 register
11543 Op string
11544 X Value
11545 Y Value
11546 }
11547
11548 func (b *BinOp) InstrString() string {
11549 return b.Op | " " | b.X.Name() | " " | b.Y.Name()
11550 }
11551
11552 type Store struct {
11553 instrBase
11554 Addr Value
11555 Val Value
11556 }
11557
11558 func (s *Store) InstrString() string {
11559 return "store " | s.Val.Name() | " -> " | s.Addr.Name()
11560 }
11561
11562 type BasicBlock struct {
11563 index int32
11564 name string
11565 instrs []Instruction
11566 }
11567
11568 func (bl *BasicBlock) emit(i Instruction) {
11569 bl.instrs = append(bl.instrs, i)
11570 }
11571
11572 type Const struct {
11573 name string
11574 typ string
11575 val int32
11576 }
11577
11578 func (c *Const) Name() string { return c.name }
11579 func (c *Const) Type() string { return c.typ }
11580
11581 func main() {
11582 bl := &BasicBlock{index: 0, name: "entry"}
11583 c1 := &Const{name: "%c1", typ: "i32", val: 1}
11584 c2 := &Const{name: "%c2", typ: "i32", val: 2}
11585
11586 add := &BinOp{
11587 register: register{instrBase: instrBase{block: bl}, name: "%t1", typ: "i32"},
11588 Op: "add", X: c1, Y: c2,
11589 }
11590 bl.emit(add)
11591
11592 store := &Store{
11593 instrBase: instrBase{block: bl},
11594 Addr: c1, Val: add,
11595 }
11596 bl.emit(store)
11597
11598 s1 := add.InstrString()
11599 s2 := store.InstrString()
11600 _ = s1
11601 _ = s2
11602
11603 n := add.Name()
11604 t := add.Type()
11605 b := add.Block()
11606 _ = n
11607 _ = t
11608 _ = b
11609 }
11610 `, func(ir string) {
11611 assert("265: has BinOp.InstrString", strings.Contains(ir, "@main.BinOp.InstrString"))
11612 assert("265: has Store.InstrString", strings.Contains(ir, "@main.Store.InstrString"))
11613 assert("265: multi-level embed register.Name", strings.Contains(ir, "@main.register.Name"))
11614 assert("265: deep embed instrBase.Block", strings.Contains(ir, "@main.instrBase.Block"))
11615 assert("265: interface append with boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11616 assert("265: promoted field access", strings.Contains(ir, "getelementptr"))
11617 })
11618
11619 // Test 266: comma-ok type assertions
11620 test(266, `package main
11621
11622 type Node interface {
11623 Kind() string
11624 }
11625
11626 type Ident struct {
11627 name string
11628 }
11629 func (i *Ident) Kind() string { return "ident" }
11630
11631 type Literal struct {
11632 val int32
11633 }
11634 func (l *Literal) Kind() string { return "literal" }
11635
11636 func classify(n Node) string {
11637 if id, ok := n.(*Ident); ok {
11638 return id.name
11639 }
11640 if lit, ok := n.(*Literal); ok {
11641 _ = lit.val
11642 return "lit"
11643 }
11644 return "unknown"
11645 }
11646
11647 func main() {
11648 var n Node
11649 n = &Ident{name: "foo"}
11650 s1 := classify(n)
11651 _ = s1
11652
11653 n = &Literal{val: 42}
11654 s2 := classify(n)
11655 _ = s2
11656 }
11657 `, func(ir string) {
11658 assert("266: has classify", strings.Contains(ir, "@main.classify"))
11659 assert("266: typeid for assertions", strings.Contains(ir, "typeid"))
11660 assert("266: icmp for type check", strings.Contains(ir, "icmp eq ptr"))
11661 })
11662
11663 // Test 267: for-range map with key and value
11664 test(267, `package main
11665
11666 type Entry struct {
11667 name string
11668 val int32
11669 }
11670
11671 func sumMap(m map[string]int32) int32 {
11672 total := int32(0)
11673 for _, v := range m {
11674 total = total + v
11675 }
11676 return total
11677 }
11678
11679 func collectKeys(m map[string]*Entry) []string {
11680 var keys []string
11681 for k := range m {
11682 keys = append(keys, k)
11683 }
11684 return keys
11685 }
11686
11687 func main() {
11688 m := map[string]int32{}
11689 m["a"] = 1
11690 m["b"] = 2
11691 s := sumMap(m)
11692 _ = s
11693
11694 entries := map[string]*Entry{}
11695 entries["x"] = &Entry{name: "x", val: 10}
11696 keys := collectKeys(entries)
11697 _ = keys
11698 }
11699 `, func(ir string) {
11700 assert("267: has sumMap", strings.Contains(ir, "@main.sumMap"))
11701 assert("267: has collectKeys", strings.Contains(ir, "@main.collectKeys"))
11702 assert("267: hashmapNext for range", strings.Contains(ir, "hashmapNext"))
11703 })
11704
11705 // Test 268: closure capturing struct pointer, called multiple times
11706 test(268, `package main
11707
11708 type Builder struct {
11709 buf []byte
11710 indent int32
11711 }
11712
11713 func (b *Builder) build() string {
11714 p := func(s string) {
11715 b.buf = append(b.buf, s...)
11716 }
11717 nl := func() {
11718 b.buf = append(b.buf, '\n')
11719 }
11720 p("func main() {")
11721 nl()
11722 p(" return")
11723 nl()
11724 p("}")
11725 nl()
11726 return string(b.buf)
11727 }
11728
11729 func main() {
11730 b := &Builder{}
11731 result := b.build()
11732 _ = result
11733 }
11734 `, func(ir string) {
11735 assert("268: has Builder.build", strings.Contains(ir, "@main.Builder.build"))
11736 assert("268: closure captures", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11737 assert("268: sliceAppend for buf", strings.Contains(ir, "sliceAppend"))
11738 })
11739
11740 // Test 269: multiple comma-ok assertions in sequence with branching
11741 test(269, `package main
11742
11743 type Type interface {
11744 Underlying() Type
11745 }
11746
11747 type Basic struct {
11748 kind int32
11749 }
11750 func (b *Basic) Underlying() Type { return b }
11751
11752 type Pointer struct {
11753 elem Type
11754 }
11755 func (p *Pointer) Underlying() Type { return p }
11756 func (p *Pointer) Elem() Type { return p.elem }
11757
11758 type Named struct {
11759 name string
11760 underlying Type
11761 }
11762 func (n *Named) Underlying() Type { return n.underlying }
11763
11764 func resolve(t Type) Type {
11765 if p, ok := t.(*Pointer); ok {
11766 return p.Elem()
11767 }
11768 if n, ok := t.(*Named); ok {
11769 return n.Underlying()
11770 }
11771 return t
11772 }
11773
11774 func isPointerTo(t Type, kind int32) bool {
11775 p, ok := t.(*Pointer)
11776 if !ok {
11777 return false
11778 }
11779 b, ok2 := p.Elem().(*Basic)
11780 if !ok2 {
11781 return false
11782 }
11783 return b.kind == kind
11784 }
11785
11786 func main() {
11787 intType := &Basic{kind: 1}
11788 ptrInt := &Pointer{elem: intType}
11789 named := &Named{name: "myint", underlying: intType}
11790
11791 r1 := resolve(ptrInt)
11792 _ = r1
11793 r2 := resolve(named)
11794 _ = r2
11795 r3 := resolve(intType)
11796 _ = r3
11797
11798 yes := isPointerTo(ptrInt, 1)
11799 no := isPointerTo(intType, 1)
11800 _ = yes
11801 _ = no
11802 }
11803 `, func(ir string) {
11804 assert("269: has resolve", strings.Contains(ir, "@main.resolve"))
11805 assert("269: has isPointerTo", strings.Contains(ir, "@main.isPointerTo"))
11806 assert("269: multiple type assertions", strings.Count(ir, "icmp eq ptr") >= 3)
11807 })
11808
11809 // Test 270: string([]byte) and []byte(string) conversions with itoa pattern
11810 test(270, `package main
11811
11812 func itoa(n int32) string {
11813 if n == 0 {
11814 return "0"
11815 }
11816 neg := false
11817 if n < 0 {
11818 neg = true
11819 n = -n
11820 }
11821 var buf [20]byte
11822 i := int32(19)
11823 for n > 0 {
11824 buf[i] = byte(n%10) + '0'
11825 n = n / 10
11826 i = i - 1
11827 }
11828 if neg {
11829 buf[i] = '-'
11830 i = i - 1
11831 }
11832 return string(buf[i+1:])
11833 }
11834
11835 func concat(parts []string) string {
11836 var buf []byte
11837 for _, p := range parts {
11838 buf = append(buf, p...)
11839 }
11840 return string(buf)
11841 }
11842
11843 func main() {
11844 s1 := itoa(42)
11845 s2 := itoa(-7)
11846 s3 := itoa(0)
11847 _ = s1
11848 _ = s2
11849 _ = s3
11850
11851 parts := []string{"hello", " ", "world"}
11852 joined := concat(parts)
11853 _ = joined
11854 }
11855 `, func(ir string) {
11856 assert("270: has itoa", strings.Contains(ir, "@main.itoa"))
11857 assert("270: has concat", strings.Contains(ir, "@main.concat"))
11858 assert("270: array alloca for buf", strings.Contains(ir, "alloca [20 x i8]"))
11859 assert("270: sliceAppend for concat", strings.Contains(ir, "sliceAppend"))
11860 })
11861
11862 // Test 271: for-range over map with both key and value, building output
11863 test(271, `package main
11864
11865 type Member interface {
11866 Name() string
11867 }
11868
11869 type Func struct {
11870 name string
11871 }
11872 func (f *Func) Name() string { return f.name }
11873
11874 type Global struct {
11875 name string
11876 typ string
11877 }
11878 func (g *Global) Name() string { return g.name }
11879
11880 type Package struct {
11881 members map[string]Member
11882 }
11883
11884 func (p *Package) addFunc(name string) {
11885 p.members[name] = &Func{name: name}
11886 }
11887
11888 func (p *Package) addGlobal(name string, typ string) {
11889 p.members[name] = &Global{name: name, typ: typ}
11890 }
11891
11892 func (p *Package) allNames() []string {
11893 var names []string
11894 for k, m := range p.members {
11895 _ = m
11896 names = append(names, k)
11897 }
11898 return names
11899 }
11900
11901 func (p *Package) findFuncs() []*Func {
11902 var funcs []*Func
11903 for _, m := range p.members {
11904 if f, ok := m.(*Func); ok {
11905 funcs = append(funcs, f)
11906 }
11907 }
11908 return funcs
11909 }
11910
11911 func main() {
11912 p := &Package{members: map[string]Member{}}
11913 p.addFunc("main")
11914 p.addFunc("init")
11915 p.addGlobal("x", "i32")
11916
11917 names := p.allNames()
11918 _ = names
11919
11920 funcs := p.findFuncs()
11921 _ = funcs
11922 }
11923 `, func(ir string) {
11924 assert("271: has allNames", strings.Contains(ir, "@main.Package.allNames"))
11925 assert("271: has findFuncs", strings.Contains(ir, "@main.Package.findFuncs"))
11926 assert("271: range map hashmapNext", strings.Contains(ir, "hashmapNext"))
11927 assert("271: type assertion in range body", strings.Contains(ir, "icmp eq ptr"))
11928 })
11929
11930 // Test 272: nested closure calls - p("text") pattern from ir_emit.mx
11931 test(272, `package main
11932
11933 type Emitter struct {
11934 buf []byte
11935 nextReg int32
11936 }
11937
11938 func (e *Emitter) emit() string {
11939 p := func(prefix string) string {
11940 e.nextReg = e.nextReg + 1
11941 return "%" | prefix | itoa272(e.nextReg)
11942 }
11943 var out []byte
11944 r1 := p("t")
11945 out = append(out, r1...)
11946 out = append(out, ' ')
11947 r2 := p("t")
11948 out = append(out, r2...)
11949 out = append(out, ' ')
11950 r3 := p("mi")
11951 out = append(out, r3...)
11952 return string(out)
11953 }
11954
11955 func itoa272(n int32) string {
11956 if n == 0 { return "0" }
11957 var buf [10]byte
11958 i := int32(9)
11959 for n > 0 {
11960 buf[i] = byte(n%10) + '0'
11961 n = n / 10
11962 i = i - 1
11963 }
11964 return string(buf[i+1:])
11965 }
11966
11967 func main() {
11968 e := &Emitter{}
11969 result := e.emit()
11970 _ = result
11971 }
11972 `, func(ir string) {
11973 assert("272: has Emitter.emit", strings.Contains(ir, "@main.Emitter.emit"))
11974 assert("272: closure with capture", strings.Contains(ir, "insertvalue {ptr, ptr}"))
11975 assert("272: string concat via or", strings.Contains(ir, "sliceAppend"))
11976 })
11977
11978 // Test 273: chained method calls with intermediate results
11979 test(273, `package main
11980
11981 type Scope struct {
11982 parent *Scope
11983 names map[string]int32
11984 }
11985
11986 func (s *Scope) Lookup(name string) int32 {
11987 if s.names != nil {
11988 v, ok := s.names[name]
11989 if ok {
11990 return v
11991 }
11992 }
11993 if s.parent != nil {
11994 return s.parent.Lookup(name)
11995 }
11996 return -1
11997 }
11998
11999 func (s *Scope) LookupParent(name string) (*Scope, int32) {
12000 if s.names != nil {
12001 v, ok := s.names[name]
12002 if ok {
12003 return s, v
12004 }
12005 }
12006 if s.parent != nil {
12007 return s.parent.LookupParent(name)
12008 }
12009 return nil, -1
12010 }
12011
12012 func main() {
12013 inner := &Scope{
12014 names: map[string]int32{"x": 1},
12015 }
12016 outer := &Scope{
12017 names: map[string]int32{"y": 2},
12018 }
12019 inner.parent = outer
12020
12021 v1 := inner.Lookup("x")
12022 v2 := inner.Lookup("y")
12023 v3 := inner.Lookup("z")
12024 _ = v1
12025 _ = v2
12026 _ = v3
12027
12028 s, v := inner.LookupParent("y")
12029 _ = s
12030 _ = v
12031 }
12032 `, func(ir string) {
12033 assert("273: has Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
12034 assert("273: has LookupParent", strings.Contains(ir, "@main.Scope.LookupParent"))
12035 assert("273: recursive call", strings.Count(ir, "call") >= 2)
12036 assert("273: multi-return", strings.Contains(ir, "extractvalue"))
12037 })
12038
12039 // Test 274: map[string]bool and delete pattern
12040 test(274, `package main
12041
12042 func main() {
12043 seen := map[string]bool{}
12044 names := []string{"a", "b", "a", "c", "b"}
12045 var unique []string
12046 for _, n := range names {
12047 if !seen[n] {
12048 seen[n] = true
12049 unique = append(unique, n)
12050 }
12051 }
12052 _ = unique
12053
12054 delete(seen, "a")
12055 has := seen["a"]
12056 _ = has
12057 }
12058 `, func(ir string) {
12059 assert("274: hashmapContentSet for map assign", strings.Contains(ir, "hashmapContentSet"))
12060 assert("274: hashmapContentGet for map lookup", strings.Contains(ir, "hashmapContentGet"))
12061 assert("274: hashmapBinaryDelete for delete", strings.Contains(ir, "hashmapBinaryDelete"))
12062 })
12063
12064 // Test 275: interface dispatch with multiple implementors and return values
12065 test(275, `package main
12066
12067 type SSAValue interface {
12068 SSAName() string
12069 SSAType() string
12070 }
12071
12072 type SSAConst struct {
12073 name string
12074 typ string
12075 val int32
12076 }
12077 func (c *SSAConst) SSAName() string { return c.name }
12078 func (c *SSAConst) SSAType() string { return c.typ }
12079
12080 type SSABinOp struct {
12081 name string
12082 typ string
12083 op string
12084 x SSAValue
12085 y SSAValue
12086 }
12087 func (b *SSABinOp) SSAName() string { return b.name }
12088 func (b *SSABinOp) SSAType() string { return b.typ }
12089
12090 func operand(v SSAValue) string {
12091 return v.SSAName()
12092 }
12093
12094 func emitBinOp(b *SSABinOp) string {
12095 return b.SSAName() | " = " | b.op | " " | b.SSAType() | " " | operand(b.x) | ", " | operand(b.y)
12096 }
12097
12098 func main() {
12099 c1 := &SSAConst{name: "%c1", typ: "i32", val: 1}
12100 c2 := &SSAConst{name: "%c2", typ: "i32", val: 2}
12101 add := &SSABinOp{name: "%t1", typ: "i32", op: "add", x: c1, y: c2}
12102 result := emitBinOp(add)
12103 _ = result
12104
12105 name := operand(c1)
12106 _ = name
12107 }
12108 `, func(ir string) {
12109 assert("275: has operand", strings.Contains(ir, "@main.operand"))
12110 assert("275: has emitBinOp", strings.Contains(ir, "@main.emitBinOp"))
12111 assert("275: interface dispatch", strings.Contains(ir, "icmp eq ptr") || strings.Contains(ir, "SSAName"))
12112 })
12113
12114 // Test 276: struct with map field, range with both key and value used
12115 test(276, `package main
12116
12117 type Scope struct {
12118 parent *Scope
12119 objects map[string]*Object
12120 }
12121
12122 type Object struct {
12123 name string
12124 kind int32
12125 }
12126
12127 func NewScope(parent *Scope) *Scope {
12128 return &Scope{parent: parent, objects: map[string]*Object{}}
12129 }
12130
12131 func (s *Scope) Insert(obj *Object) {
12132 s.objects[obj.name] = obj
12133 }
12134
12135 func (s *Scope) Lookup(name string) *Object {
12136 if s.objects != nil {
12137 obj, ok := s.objects[name]
12138 if ok {
12139 return obj
12140 }
12141 }
12142 if s.parent != nil {
12143 return s.parent.Lookup(name)
12144 }
12145 return nil
12146 }
12147
12148 func (s *Scope) NumObjects() int32 {
12149 n := int32(0)
12150 for _, obj := range s.objects {
12151 _ = obj
12152 n = n + 1
12153 }
12154 return n
12155 }
12156
12157 func main() {
12158 outer := NewScope(nil)
12159 outer.Insert(&Object{name: "int", kind: 1})
12160 outer.Insert(&Object{name: "string", kind: 2})
12161
12162 inner := NewScope(outer)
12163 inner.Insert(&Object{name: "x", kind: 3})
12164
12165 o1 := inner.Lookup("x")
12166 o2 := inner.Lookup("int")
12167 o3 := inner.Lookup("missing")
12168 _ = o1
12169 _ = o2
12170 _ = o3
12171
12172 n := outer.NumObjects()
12173 _ = n
12174 }
12175 `, func(ir string) {
12176 assert("276: has NewScope", strings.Contains(ir, "@main.NewScope"))
12177 assert("276: has Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
12178 assert("276: has NumObjects", strings.Contains(ir, "@main.Scope.NumObjects"))
12179 assert("276: map operations", strings.Contains(ir, "hashmapContentGet"))
12180 })
12181
12182 // Test 277: type switch with nil check and multiple concrete types
12183 test(277, `package main
12184
12185 type Expr interface {
12186 exprNode()
12187 }
12188
12189 type Ident struct {
12190 name string
12191 }
12192 func (i *Ident) exprNode() {}
12193
12194 type Call struct {
12195 fn Expr
12196 args []Expr
12197 }
12198 func (c *Call) exprNode() {}
12199
12200 type Literal struct {
12201 val int32
12202 }
12203 func (l *Literal) exprNode() {}
12204
12205 func describe(e Expr) string {
12206 if e == nil {
12207 return "nil"
12208 }
12209 switch x := e.(type) {
12210 case *Ident:
12211 return "ident:" | x.name
12212 case *Call:
12213 return "call"
12214 case *Literal:
12215 _ = x.val
12216 return "literal"
12217 }
12218 return "unknown"
12219 }
12220
12221 func main() {
12222 i := &Ident{name: "foo"}
12223 l := &Literal{val: 42}
12224 c := &Call{fn: i, args: []Expr{l}}
12225
12226 s1 := describe(i)
12227 s2 := describe(l)
12228 s3 := describe(c)
12229 s4 := describe(nil)
12230 _ = s1
12231 _ = s2
12232 _ = s3
12233 _ = s4
12234 }
12235 `, func(ir string) {
12236 assert("277: has describe", strings.Contains(ir, "@main.describe"))
12237 assert("277: nil check", strings.Contains(ir, "icmp eq") || strings.Contains(ir, "null"))
12238 assert("277: type switch branches", strings.Contains(ir, "typeid"))
12239 })
12240
12241 // Test 278: func literal returning value, multiple closures in same func
12242 test(278, `package main
12243
12244 type Writer struct {
12245 buf []byte
12246 }
12247
12248 func (w *Writer) emit(prefix string, n int32) string {
12249 p := func(s string) {
12250 w.buf = append(w.buf, s...)
12251 }
12252 num := func(v int32) string {
12253 if v == 0 { return "0" }
12254 var b [10]byte
12255 i := int32(9)
12256 for v > 0 {
12257 b[i] = byte(v%10) + '0'
12258 v = v / 10
12259 i = i - 1
12260 }
12261 return string(b[i+1:])
12262 }
12263 p(prefix)
12264 s := num(n)
12265 p(s)
12266 return string(w.buf)
12267 }
12268
12269 func main() {
12270 w := &Writer{}
12271 result := w.emit("count=", 42)
12272 _ = result
12273 }
12274 `, func(ir string) {
12275 assert("278: has Writer.emit", strings.Contains(ir, "@main.Writer.emit"))
12276 assert("278: two closures", strings.Count(ir, "insertvalue {ptr, ptr}") >= 2)
12277 assert("278: array subslice in closure", strings.Contains(ir, "alloca [10 x i8]"))
12278 })
12279
12280 // Test 279: method on result of method call (chained dispatch)
12281 test(279, `package main
12282
12283 type Token struct {
12284 kind int32
12285 text string
12286 }
12287
12288 type Scanner struct {
12289 src []byte
12290 pos int32
12291 }
12292
12293 func (s *Scanner) peek() byte {
12294 if int32(len(s.src)) <= s.pos {
12295 return 0
12296 }
12297 return s.src[s.pos]
12298 }
12299
12300 func (s *Scanner) next() *Token {
12301 ch := s.peek()
12302 if ch == 0 {
12303 return &Token{kind: 0, text: ""}
12304 }
12305 s.pos = s.pos + 1
12306 return &Token{kind: int32(ch), text: string(s.src[s.pos-1:s.pos])}
12307 }
12308
12309 func main() {
12310 s := &Scanner{src: []byte("abc"), pos: 0}
12311 t1 := s.next()
12312 t2 := s.next()
12313 _ = t1.text
12314 _ = t2.kind
12315 }
12316 `, func(ir string) {
12317 assert("279: has Scanner.peek", strings.Contains(ir, "@main.Scanner.peek"))
12318 assert("279: has Scanner.next", strings.Contains(ir, "@main.Scanner.next"))
12319 assert("279: field access on result", strings.Contains(ir, "getelementptr"))
12320 })
12321
12322 // Test 280: interface slice iteration with type assertion
12323 test(280, `package main
12324
12325 type Instruction interface {
12326 String() string
12327 }
12328
12329 type Add struct {
12330 dst string
12331 x string
12332 y string
12333 }
12334 func (a *Add) String() string { return a.dst | " = add " | a.x | " " | a.y }
12335
12336 type Ret struct {
12337 val string
12338 }
12339 func (r *Ret) String() string { return "ret " | r.val }
12340
12341 func printAll(instrs []Instruction) string {
12342 var out []byte
12343 for _, instr := range instrs {
12344 s := instr.String()
12345 out = append(out, s...)
12346 out = append(out, '\n')
12347 }
12348 return string(out)
12349 }
12350
12351 func countAdds(instrs []Instruction) int32 {
12352 n := int32(0)
12353 for _, instr := range instrs {
12354 if _, ok := instr.(*Add); ok {
12355 n = n + 1
12356 }
12357 }
12358 return n
12359 }
12360
12361 func main() {
12362 instrs := []Instruction{
12363 &Add{dst: "%1", x: "%a", y: "%b"},
12364 &Add{dst: "%2", x: "%1", y: "%c"},
12365 &Ret{val: "%2"},
12366 }
12367 s := printAll(instrs)
12368 _ = s
12369 n := countAdds(instrs)
12370 _ = n
12371 }
12372 `, func(ir string) {
12373 assert("280: has printAll", strings.Contains(ir, "@main.printAll"))
12374 assert("280: has countAdds", strings.Contains(ir, "@main.countAdds"))
12375 assert("280: interface invoke String", strings.Contains(ir, "icmp eq ptr"))
12376 assert("280: slice of interfaces", strings.Contains(ir, "insertvalue {ptr, ptr}"))
12377 })
12378
12379 // Test 281: nested struct literal with embedded field init
12380 test(281, `package main
12381
12382 type Pos struct {
12383 line int32
12384 col int32
12385 }
12386
12387 type Name struct {
12388 Value string
12389 pos Pos
12390 }
12391
12392 type Field struct {
12393 Name *Name
12394 Type *Name
12395 Exported bool
12396 }
12397
12398 type StructType struct {
12399 fields []*Field
12400 }
12401
12402 func (s *StructType) NumFields() int32 { return int32(len(s.fields)) }
12403
12404 func main() {
12405 st := &StructType{
12406 fields: []*Field{
12407 {Name: &Name{Value: "x", pos: Pos{line: 1, col: 5}}, Type: &Name{Value: "int32"}, Exported: false},
12408 {Name: &Name{Value: "Y", pos: Pos{line: 2, col: 5}}, Type: &Name{Value: "string"}, Exported: true},
12409 },
12410 }
12411 n := st.NumFields()
12412 _ = n
12413 f0 := st.fields[0]
12414 _ = f0.Name.Value
12415 }
12416 `, func(ir string) {
12417 assert("281: has NumFields", strings.Contains(ir, "@main.StructType.NumFields"))
12418 assert("281: nested struct alloc", strings.Contains(ir, "runtime.alloc"))
12419 assert("281: field access chain", strings.Contains(ir, "getelementptr"))
12420 })
12421
12422 // Test 282: byte to int32 conversion and int32 to byte
12423 test(282, `package main
12424
12425 func isLetter(ch byte) bool {
12426 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'
12427 }
12428
12429 func isDigit(ch byte) bool {
12430 return ch >= '0' && ch <= '9'
12431 }
12432
12433 func scanIdent(src []byte, pos int32) (string, int32) {
12434 start := pos
12435 for int32(len(src)) > pos && (isLetter(src[pos]) || isDigit(src[pos])) {
12436 pos = pos + 1
12437 }
12438 return string(src[start:pos]), pos
12439 }
12440
12441 func main() {
12442 src := []byte("hello123 world")
12443 name, end := scanIdent(src, 0)
12444 _ = name
12445 _ = end
12446
12447 b1 := isLetter('x')
12448 b2 := isDigit('5')
12449 b3 := isLetter('9')
12450 _ = b1
12451 _ = b2
12452 _ = b3
12453 }
12454 `, func(ir string) {
12455 assert("282: has isLetter", strings.Contains(ir, "@main.isLetter"))
12456 assert("282: has scanIdent", strings.Contains(ir, "@main.scanIdent"))
12457 assert("282: byte comparison", strings.Contains(ir, "icmp"))
12458 assert("282: multi-return", strings.Contains(ir, "insertvalue"))
12459 })
12460
12461 // Test 283: nil comparison with interface and pointer
12462 test(283, `package main
12463
12464 type Node interface {
12465 Kind() string
12466 }
12467
12468 type Leaf struct {
12469 val int32
12470 }
12471 func (l *Leaf) Kind() string { return "leaf" }
12472
12473 func checkNil(n Node) bool {
12474 return n == nil
12475 }
12476
12477 func checkPtrNil(l *Leaf) bool {
12478 return l == nil
12479 }
12480
12481 func safeKind(n Node) string {
12482 if n == nil {
12483 return "nil"
12484 }
12485 return n.Kind()
12486 }
12487
12488 func main() {
12489 var n Node
12490 b1 := checkNil(n)
12491 _ = b1
12492
12493 l := &Leaf{val: 1}
12494 n = l
12495 b2 := checkNil(n)
12496 _ = b2
12497
12498 b3 := checkPtrNil(nil)
12499 b4 := checkPtrNil(l)
12500 _ = b3
12501 _ = b4
12502
12503 s := safeKind(nil)
12504 _ = s
12505 }
12506 `, func(ir string) {
12507 assert("283: has checkNil", strings.Contains(ir, "@main.checkNil"))
12508 assert("283: has safeKind", strings.Contains(ir, "@main.safeKind"))
12509 assert("283: nil comparison", strings.Contains(ir, "icmp"))
12510 })
12511
12512 // Test 284: switch on string value
12513 test(284, `package main
12514
12515 func tokenKind(s string) int32 {
12516 switch s {
12517 case "func":
12518 return 1
12519 case "var":
12520 return 2
12521 case "type":
12522 return 3
12523 case "return":
12524 return 4
12525 }
12526 return 0
12527 }
12528
12529 func main() {
12530 k1 := tokenKind("func")
12531 k2 := tokenKind("var")
12532 k3 := tokenKind("other")
12533 _ = k1
12534 _ = k2
12535 _ = k3
12536 }
12537 `, func(ir string) {
12538 assert("284: has tokenKind", strings.Contains(ir, "@main.tokenKind"))
12539 assert("284: string compare calls", strings.Contains(ir, "stringEqual") || strings.Contains(ir, "icmp"))
12540 })
12541
12542 // Test 285: for-range with index only (map key iteration)
12543 test(285, `package main
12544
12545 func keys(m map[string]int32) []string {
12546 var result []string
12547 for k := range m {
12548 result = append(result, k)
12549 }
12550 return result
12551 }
12552
12553 func sumValues(m map[string]int32) int32 {
12554 total := int32(0)
12555 for _, v := range m {
12556 total = total + v
12557 }
12558 return total
12559 }
12560
12561 func main() {
12562 m := map[string]int32{"a": 1, "b": 2, "c": 3}
12563 ks := keys(m)
12564 _ = ks
12565 s := sumValues(m)
12566 _ = s
12567 }
12568 `, func(ir string) {
12569 assert("285: has keys", strings.Contains(ir, "@main.keys"))
12570 assert("285: has sumValues", strings.Contains(ir, "@main.sumValues"))
12571 assert("285: map iteration", strings.Contains(ir, "hashmapNext"))
12572 })
12573
12574 // Test 286: SSA builder pattern - func builder with emit method and block management
12575 test(286, `package main
12576
12577 type Instruction interface {
12578 String() string
12579 }
12580
12581 type Block struct {
12582 instrs []Instruction
12583 name string
12584 }
12585
12586 type Add struct {
12587 dst string
12588 src string
12589 }
12590 func (a *Add) String() string { return a.dst | " = add " | a.src }
12591
12592 type Ret struct{}
12593 func (r *Ret) String() string { return "ret" }
12594
12595 type FuncBuilder struct {
12596 blocks []*Block
12597 cur *Block
12598 nextN int32
12599 }
12600
12601 func (fb *FuncBuilder) newBlock(name string) *Block {
12602 b := &Block{name: name}
12603 fb.blocks = append(fb.blocks, b)
12604 return b
12605 }
12606
12607 func (fb *FuncBuilder) emit(i Instruction) {
12608 fb.cur.instrs = append(fb.cur.instrs, i)
12609 }
12610
12611 func (fb *FuncBuilder) nextName() string {
12612 fb.nextN = fb.nextN + 1
12613 return "%t" | itoa286(fb.nextN)
12614 }
12615
12616 func itoa286(n int32) string {
12617 if n == 0 { return "0" }
12618 var buf [10]byte
12619 i := int32(9)
12620 for n > 0 {
12621 buf[i] = byte(n%10) + '0'
12622 n = n / 10
12623 i = i - 1
12624 }
12625 return string(buf[i+1:])
12626 }
12627
12628 func main() {
12629 fb := &FuncBuilder{}
12630 entry := fb.newBlock("entry")
12631 fb.cur = entry
12632 n1 := fb.nextName()
12633 n2 := fb.nextName()
12634 fb.emit(&Add{dst: n1, src: "%arg0"})
12635 fb.emit(&Add{dst: n2, src: n1})
12636 fb.emit(&Ret{})
12637 total := int32(0)
12638 for _, b := range fb.blocks {
12639 total = total + int32(len(b.instrs))
12640 }
12641 _ = total
12642 }
12643 `, func(ir string) {
12644 assert("286: has FuncBuilder.emit", strings.Contains(ir, "@main.FuncBuilder.emit"))
12645 assert("286: has FuncBuilder.nextName", strings.Contains(ir, "@main.FuncBuilder.nextName"))
12646 assert("286: has FuncBuilder.newBlock", strings.Contains(ir, "@main.FuncBuilder.newBlock"))
12647 assert("286: interface boxing in emit", strings.Contains(ir, "insertvalue {ptr, ptr}"))
12648 })
12649
12650 // Test 287: type resolution pattern - resolve through Named and Pointer layers
12651 test(287, `package main
12652
12653 type Type interface {
12654 Underlying() Type
12655 }
12656
12657 type Basic struct {
12658 kind int32
12659 name string
12660 }
12661 func (b *Basic) Underlying() Type { return b }
12662
12663 type Pointer struct {
12664 base Type
12665 }
12666 func (p *Pointer) Underlying() Type { return p }
12667 func (p *Pointer) Elem() Type { return p.base }
12668
12669 type Named struct {
12670 obj *TypeName
12671 underlying Type
12672 }
12673 func (n *Named) Underlying() Type {
12674 if n.underlying != nil {
12675 return n.underlying
12676 }
12677 return n
12678 }
12679 func (n *Named) Obj() *TypeName { return n.obj }
12680
12681 type TypeName struct {
12682 name string
12683 typ Type
12684 }
12685 func (tn *TypeName) Name() string { return tn.name }
12686 func (tn *TypeName) Type() Type { return tn.typ }
12687
12688 type Slice struct {
12689 elem Type
12690 }
12691 func (s *Slice) Underlying() Type { return s }
12692 func (s *Slice) Elem() Type { return s.elem }
12693
12694 func llvmType(t Type) string {
12695 if t == nil {
12696 return "void"
12697 }
12698 switch u := t.Underlying().(type) {
12699 case *Basic:
12700 switch u.kind {
12701 case 1: return "i32"
12702 case 2: return "i64"
12703 case 3: return "{ptr, i64, i64}"
12704 }
12705 case *Pointer:
12706 return "ptr"
12707 case *Slice:
12708 return "{ptr, i64, i64}"
12709 }
12710 return "void"
12711 }
12712
12713 func isPointer(t Type) bool {
12714 _, ok := t.Underlying().(*Pointer)
12715 return ok
12716 }
12717
12718 func main() {
12719 intType := &Basic{kind: 1, name: "int32"}
12720 strType := &Basic{kind: 3, name: "string"}
12721 ptrInt := &Pointer{base: intType}
12722 tn := &TypeName{name: "MyInt"}
12723 named := &Named{obj: tn, underlying: intType}
12724 tn.typ = named
12725 sliceStr := &Slice{elem: strType}
12726
12727 s1 := llvmType(intType)
12728 s2 := llvmType(ptrInt)
12729 s3 := llvmType(named)
12730 s4 := llvmType(sliceStr)
12731 s5 := llvmType(nil)
12732 _ = s1
12733 _ = s2
12734 _ = s3
12735 _ = s4
12736 _ = s5
12737
12738 b1 := isPointer(ptrInt)
12739 b2 := isPointer(intType)
12740 _ = b1
12741 _ = b2
12742 }
12743 `, func(ir string) {
12744 assert("287: has llvmType", strings.Contains(ir, "@main.llvmType"))
12745 assert("287: has isPointer", strings.Contains(ir, "@main.isPointer"))
12746 assert("287: type switch dispatch", strings.Contains(ir, "icmp eq ptr"))
12747 assert("287: nested switch", strings.Contains(ir, "icmp eq i32"))
12748 })
12749
12750 // Test 288: emitter pattern - write() calls with string concat building IR output
12751 test(288, `package main
12752
12753 type Emitter struct {
12754 buf []byte
12755 nextReg int32
12756 }
12757
12758 func (e *Emitter) w(s string) {
12759 e.buf = append(e.buf, s...)
12760 }
12761
12762 func (e *Emitter) regName() string {
12763 e.nextReg = e.nextReg + 1
12764 return "%t" | itoa288(e.nextReg)
12765 }
12766
12767 func (e *Emitter) emitAdd(dst string, lhs string, rhs string) {
12768 e.w(" ")
12769 e.w(dst)
12770 e.w(" = add i32 ")
12771 e.w(lhs)
12772 e.w(", ")
12773 e.w(rhs)
12774 e.w("\n")
12775 }
12776
12777 func (e *Emitter) emitRet(val string) {
12778 e.w(" ret i32 ")
12779 e.w(val)
12780 e.w("\n")
12781 }
12782
12783 func itoa288(n int32) string {
12784 if n == 0 { return "0" }
12785 var buf [10]byte
12786 i := int32(9)
12787 for n > 0 {
12788 buf[i] = byte(n%10) + '0'
12789 n = n / 10
12790 i = i - 1
12791 }
12792 return string(buf[i+1:])
12793 }
12794
12795 func main() {
12796 e := &Emitter{}
12797 r1 := e.regName()
12798 r2 := e.regName()
12799 e.emitAdd(r1, "%arg0", "%arg1")
12800 e.emitAdd(r2, r1, "%arg2")
12801 e.emitRet(r2)
12802 result := string(e.buf)
12803 _ = result
12804 }
12805 `, func(ir string) {
12806 assert("288: has Emitter.w", strings.Contains(ir, "@main.Emitter.w"))
12807 assert("288: has Emitter.regName", strings.Contains(ir, "@main.Emitter.regName"))
12808 assert("288: has Emitter.emitAdd", strings.Contains(ir, "@main.Emitter.emitAdd"))
12809 assert("288: sliceAppend for buf", strings.Contains(ir, "sliceAppend"))
12810 })
12811
12812 // Test 289: SSA const pattern - nil type, typed nil, constant values
12813 test(289, `package main
12814
12815 type Type interface {
12816 String() string
12817 }
12818
12819 type Basic struct {
12820 name string
12821 }
12822 func (b *Basic) String() string { return b.name }
12823
12824 type Const struct {
12825 typ Type
12826 val int32
12827 }
12828
12829 func (c *Const) SSAType() Type { return c.typ }
12830
12831 func operand289(c *Const) string {
12832 if c.typ == nil {
12833 return "null"
12834 }
12835 if c.val == 0 {
12836 return "zeroinitializer"
12837 }
12838 return itoa289(c.val)
12839 }
12840
12841 func itoa289(n int32) string {
12842 if n < 0 {
12843 return "-" | itoa289(-n)
12844 }
12845 if n == 0 { return "0" }
12846 var buf [10]byte
12847 i := int32(9)
12848 for n > 0 {
12849 buf[i] = byte(n%10) + '0'
12850 n = n / 10
12851 i = i - 1
12852 }
12853 return string(buf[i+1:])
12854 }
12855
12856 func main() {
12857 intType := &Basic{name: "i32"}
12858 c1 := &Const{typ: intType, val: 42}
12859 c2 := &Const{typ: intType, val: 0}
12860 c3 := &Const{typ: nil, val: 0}
12861
12862 s1 := operand289(c1)
12863 s2 := operand289(c2)
12864 s3 := operand289(c3)
12865 _ = s1
12866 _ = s2
12867 _ = s3
12868
12869 t := c1.SSAType()
12870 _ = t
12871 }
12872 `, func(ir string) {
12873 assert("289: has operand289", strings.Contains(ir, "@main.operand289"))
12874 assert("289: has itoa289", strings.Contains(ir, "@main.itoa289"))
12875 assert("289: recursive call for negative", strings.Count(ir, "call") >= 2)
12876 })
12877
12878 // Test 290: 300-line stress test - mini compiler pipeline
12879 test(290, `package main
12880
12881 type Token struct {
12882 kind int32
12883 text string
12884 pos int32
12885 }
12886
12887 type Expr interface {
12888 exprNode()
12889 }
12890
12891 type NameExpr struct {
12892 name string
12893 }
12894 func (n *NameExpr) exprNode() {}
12895
12896 type BinExpr struct {
12897 op string
12898 x Expr
12899 y Expr
12900 }
12901 func (b *BinExpr) exprNode() {}
12902
12903 type CallExpr struct {
12904 fn Expr
12905 args []Expr
12906 }
12907 func (c *CallExpr) exprNode() {}
12908
12909 type LitExpr struct {
12910 val int32
12911 }
12912 func (l *LitExpr) exprNode() {}
12913
12914 type Stmt interface {
12915 stmtNode()
12916 }
12917
12918 type ReturnStmt struct {
12919 val Expr
12920 }
12921 func (r *ReturnStmt) stmtNode() {}
12922
12923 type AssignStmt struct {
12924 name string
12925 val Expr
12926 }
12927 func (a *AssignStmt) stmtNode() {}
12928
12929 type SSAValue interface {
12930 Name() string
12931 Type() string
12932 }
12933
12934 type SSAReg struct {
12935 name string
12936 typ string
12937 }
12938 func (r *SSAReg) Name() string { return r.name }
12939 func (r *SSAReg) Type() string { return r.typ }
12940
12941 type SSAConst struct {
12942 name string
12943 typ string
12944 val int32
12945 }
12946 func (c *SSAConst) Name() string { return c.name }
12947 func (c *SSAConst) Type() string { return c.typ }
12948
12949 type SSAInstr interface {
12950 InstrString() string
12951 }
12952
12953 type SSABinOp struct {
12954 dst SSAValue
12955 op string
12956 x SSAValue
12957 y SSAValue
12958 }
12959 func (b *SSABinOp) InstrString() string {
12960 return b.dst.Name() | " = " | b.op | " " | b.dst.Type() | " " | b.x.Name() | ", " | b.y.Name()
12961 }
12962
12963 type SSARet struct {
12964 val SSAValue
12965 }
12966 func (r *SSARet) InstrString() string {
12967 if r.val == nil {
12968 return "ret void"
12969 }
12970 return "ret " | r.val.Type() | " " | r.val.Name()
12971 }
12972
12973 type SSABlock struct {
12974 name string
12975 instrs []SSAInstr
12976 }
12977
12978 func (b *SSABlock) emit(i SSAInstr) {
12979 b.instrs = append(b.instrs, i)
12980 }
12981
12982 type Builder struct {
12983 blocks []*SSABlock
12984 cur *SSABlock
12985 nextID int32
12986 env map[string]SSAValue
12987 }
12988
12989 func NewBuilder() *Builder {
12990 b := &Builder{env: map[string]SSAValue{}}
12991 entry := &SSABlock{name: "entry"}
12992 b.blocks = append(b.blocks, entry)
12993 b.cur = entry
12994 return b
12995 }
12996
12997 func (b *Builder) fresh() string {
12998 b.nextID = b.nextID + 1
12999 return "%t" | itoa290(b.nextID)
13000 }
13001
13002 func (b *Builder) buildExpr(e Expr) SSAValue {
13003 switch x := e.(type) {
13004 case *LitExpr:
13005 return &SSAConst{name: itoa290(x.val), typ: "i32", val: x.val}
13006 case *NameExpr:
13007 v, ok := b.env[x.name]
13008 if ok {
13009 return v
13010 }
13011 return &SSAReg{name: "%" | x.name, typ: "i32"}
13012 case *BinExpr:
13013 lhs := b.buildExpr(x.x)
13014 rhs := b.buildExpr(x.y)
13015 dst := &SSAReg{name: b.fresh(), typ: "i32"}
13016 b.cur.emit(&SSABinOp{dst: dst, op: x.op, x: lhs, y: rhs})
13017 return dst
13018 case *CallExpr:
13019 dst := &SSAReg{name: b.fresh(), typ: "i32"}
13020 return dst
13021 }
13022 return nil
13023 }
13024
13025 func (b *Builder) buildStmt(s Stmt) {
13026 switch x := s.(type) {
13027 case *AssignStmt:
13028 v := b.buildExpr(x.val)
13029 if v != nil {
13030 b.env[x.name] = v
13031 }
13032 case *ReturnStmt:
13033 v := b.buildExpr(x.val)
13034 b.cur.emit(&SSARet{val: v})
13035 }
13036 }
13037
13038 func (b *Builder) render() string {
13039 var out []byte
13040 for _, bl := range b.blocks {
13041 out = append(out, bl.name...)
13042 out = append(out, ':')
13043 out = append(out, '\n')
13044 for _, instr := range bl.instrs {
13045 out = append(out, ' ')
13046 out = append(out, ' ')
13047 s := instr.InstrString()
13048 out = append(out, s...)
13049 out = append(out, '\n')
13050 }
13051 }
13052 return string(out)
13053 }
13054
13055 func itoa290(n int32) string {
13056 if n == 0 { return "0" }
13057 neg := false
13058 if n < 0 {
13059 neg = true
13060 n = -n
13061 }
13062 var buf [10]byte
13063 i := int32(9)
13064 for n > 0 {
13065 buf[i] = byte(n%10) + '0'
13066 n = n / 10
13067 i = i - 1
13068 }
13069 if neg {
13070 buf[i] = '-'
13071 i = i - 1
13072 }
13073 return string(buf[i+1:])
13074 }
13075
13076 func main() {
13077 b := NewBuilder()
13078
13079 stmts := []Stmt{
13080 &AssignStmt{name: "sum", val: &BinExpr{op: "add", x: &LitExpr{val: 1}, y: &LitExpr{val: 2}}},
13081 &AssignStmt{name: "prod", val: &BinExpr{op: "mul", x: &NameExpr{name: "sum"}, y: &LitExpr{val: 3}}},
13082 &ReturnStmt{val: &NameExpr{name: "prod"}},
13083 }
13084 for _, s := range stmts {
13085 b.buildStmt(s)
13086 }
13087 result := b.render()
13088 _ = result
13089
13090 n := int32(0)
13091 for _, bl := range b.blocks {
13092 n = n + int32(len(bl.instrs))
13093 }
13094 _ = n
13095 }
13096 `, func(ir string) {
13097 assert("290: has NewBuilder", strings.Contains(ir, "@main.NewBuilder"))
13098 assert("290: has Builder.buildExpr", strings.Contains(ir, "@main.Builder.buildExpr"))
13099 assert("290: has Builder.buildStmt", strings.Contains(ir, "@main.Builder.buildStmt"))
13100 assert("290: has Builder.render", strings.Contains(ir, "@main.Builder.render"))
13101 assert("290: type switches in buildExpr", strings.Contains(ir, "typeid"))
13102 assert("290: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13103 assert("290: map operations", strings.Contains(ir, "hashmapContent"))
13104 assert("290: interface slice boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
13105 })
13106
13107 // Test 291: tagless switch (switch { case cond: }) and if-init
13108 test(291, `package main
13109
13110 func classify(n int32) string {
13111 switch {
13112 case n < 0:
13113 return "negative"
13114 case n == 0:
13115 return "zero"
13116 case n < 10:
13117 return "small"
13118 case n < 100:
13119 return "medium"
13120 }
13121 return "large"
13122 }
13123
13124 func safeLookup(m map[string]int32, key string) int32 {
13125 if v, ok := m[key]; ok {
13126 return v
13127 }
13128 return -1
13129 }
13130
13131 func main() {
13132 s1 := classify(-5)
13133 s2 := classify(0)
13134 s3 := classify(7)
13135 s4 := classify(50)
13136 s5 := classify(200)
13137 _ = s1
13138 _ = s2
13139 _ = s3
13140 _ = s4
13141 _ = s5
13142
13143 m := map[string]int32{"x": 42}
13144 v1 := safeLookup(m, "x")
13145 v2 := safeLookup(m, "missing")
13146 _ = v1
13147 _ = v2
13148 }
13149 `, func(ir string) {
13150 assert("291: has classify", strings.Contains(ir, "@main.classify"))
13151 assert("291: has safeLookup", strings.Contains(ir, "@main.safeLookup"))
13152 assert("291: branch for cases", strings.Contains(ir, "br i1"))
13153 })
13154
13155 // Test 292: string indexing, byte comparison, break/continue
13156 test(292, `package main
13157
13158 func indexOf(s string, ch byte) int32 {
13159 for i := int32(0); i < int32(len(s)); i = i + 1 {
13160 if s[i] == ch {
13161 return i
13162 }
13163 }
13164 return -1
13165 }
13166
13167 func countChar(s string, ch byte) int32 {
13168 n := int32(0)
13169 for i := int32(0); i < int32(len(s)); i = i + 1 {
13170 if s[i] != ch {
13171 continue
13172 }
13173 n = n + 1
13174 }
13175 return n
13176 }
13177
13178 func skipSpaces(s string, pos int32) int32 {
13179 for pos < int32(len(s)) {
13180 if s[pos] != ' ' && s[pos] != '\t' {
13181 break
13182 }
13183 pos = pos + 1
13184 }
13185 return pos
13186 }
13187
13188 func main() {
13189 i1 := indexOf("hello", 'l')
13190 i2 := indexOf("hello", 'z')
13191 _ = i1
13192 _ = i2
13193
13194 c := countChar("abracadabra", 'a')
13195 _ = c
13196
13197 p := skipSpaces(" hello", 0)
13198 _ = p
13199 }
13200 `, func(ir string) {
13201 assert("292: has indexOf", strings.Contains(ir, "@main.indexOf"))
13202 assert("292: has countChar", strings.Contains(ir, "@main.countChar"))
13203 assert("292: has skipSpaces", strings.Contains(ir, "@main.skipSpaces"))
13204 assert("292: string index gep", strings.Contains(ir, "getelementptr"))
13205 })
13206
13207 // Test 293: nested function calls as arguments f(g(x))
13208 test(293, `package main
13209
13210 type Type interface {
13211 Underlying() Type
13212 }
13213
13214 type Basic struct {
13215 kind int32
13216 }
13217 func (b *Basic) Underlying() Type { return b }
13218
13219 type Pointer struct {
13220 base Type
13221 }
13222 func (p *Pointer) Underlying() Type { return p }
13223 func (p *Pointer) Elem() Type { return p.base }
13224
13225 func NewPointer(base Type) *Pointer {
13226 return &Pointer{base: base}
13227 }
13228
13229 func llvmType(t Type) string {
13230 if t == nil { return "void" }
13231 switch u := t.Underlying().(type) {
13232 case *Basic:
13233 if u.kind == 1 { return "i32" }
13234 if u.kind == 2 { return "i64" }
13235 return "i8"
13236 case *Pointer:
13237 return "ptr"
13238 }
13239 return "void"
13240 }
13241
13242 func ptrType(t Type) string {
13243 return llvmType(NewPointer(t))
13244 }
13245
13246 func main() {
13247 intT := &Basic{kind: 1}
13248 s1 := ptrType(intT)
13249 _ = s1
13250 s2 := llvmType(NewPointer(NewPointer(intT)))
13251 _ = s2
13252 }
13253 `, func(ir string) {
13254 assert("293: has NewPointer", strings.Contains(ir, "@main.NewPointer"))
13255 assert("293: has ptrType", strings.Contains(ir, "@main.ptrType"))
13256 assert("293: nested calls", strings.Count(ir, "call") >= 3)
13257 })
13258
13259 // Test 294: type switch with default, fallthrough to default
13260 test(294, `package main
13261
13262 type Node interface {
13263 nodeKind() int32
13264 }
13265
13266 type IntNode struct {
13267 val int32
13268 }
13269 func (n *IntNode) nodeKind() int32 { return 1 }
13270
13271 type StrNode struct {
13272 val string
13273 }
13274 func (n *StrNode) nodeKind() int32 { return 2 }
13275
13276 type ListNode struct {
13277 items []Node
13278 }
13279 func (n *ListNode) nodeKind() int32 { return 3 }
13280
13281 func describe(n Node) string {
13282 switch x := n.(type) {
13283 case *IntNode:
13284 _ = x.val
13285 return "int"
13286 case *StrNode:
13287 return "str:" | x.val
13288 case *ListNode:
13289 _ = len(x.items)
13290 return "list"
13291 default:
13292 return "unknown"
13293 }
13294 }
13295
13296 func main() {
13297 nodes := []Node{
13298 &IntNode{val: 42},
13299 &StrNode{val: "hello"},
13300 &ListNode{items: []Node{&IntNode{val: 1}}},
13301 }
13302 var results []string
13303 for _, n := range nodes {
13304 s := describe(n)
13305 results = append(results, s)
13306 }
13307 _ = results
13308 }
13309 `, func(ir string) {
13310 assert("294: has describe", strings.Contains(ir, "@main.describe"))
13311 assert("294: type switch with 3 cases", strings.Count(ir, "typeid") >= 3)
13312 assert("294: default case", strings.Contains(ir, "br label") || strings.Contains(ir, "unreachable"))
13313 })
13314
13315 // Test 295: map[string]interface{} pattern (map with interface values)
13316 test(295, `package main
13317
13318 type Value interface {
13319 String() string
13320 }
13321
13322 type IntVal struct {
13323 v int32
13324 }
13325 func (i *IntVal) String() string { return "int" }
13326
13327 type StrVal struct {
13328 v string
13329 }
13330 func (s *StrVal) String() string { return s.v }
13331
13332 func buildEnv() map[string]Value {
13333 env := map[string]Value{}
13334 env["x"] = &IntVal{v: 1}
13335 env["name"] = &StrVal{v: "hello"}
13336 return env
13337 }
13338
13339 func lookupString(env map[string]Value, key string) string {
13340 v, ok := env[key]
13341 if !ok {
13342 return ""
13343 }
13344 return v.String()
13345 }
13346
13347 func main() {
13348 env := buildEnv()
13349 s1 := lookupString(env, "x")
13350 s2 := lookupString(env, "name")
13351 s3 := lookupString(env, "missing")
13352 _ = s1
13353 _ = s2
13354 _ = s3
13355 }
13356 `, func(ir string) {
13357 assert("295: has buildEnv", strings.Contains(ir, "@main.buildEnv"))
13358 assert("295: has lookupString", strings.Contains(ir, "@main.lookupString"))
13359 assert("295: map with interface values", strings.Contains(ir, "hashmapContent"))
13360 assert("295: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13361 })
13362
13363 // Test 296: full SSA type hierarchy - replicates ssa_types.mx patterns
13364 test(296, `package main
13365
13366 type Type interface {
13367 Underlying() Type
13368 String() string
13369 }
13370
13371 type Basic struct {
13372 kind int32
13373 name string
13374 }
13375 func (b *Basic) Underlying() Type { return b }
13376 func (b *Basic) String() string { return b.name }
13377
13378 type Pointer struct {
13379 base Type
13380 }
13381 func (p *Pointer) Underlying() Type { return p }
13382 func (p *Pointer) String() string { return "*" | p.base.String() }
13383 func (p *Pointer) Elem() Type { return p.base }
13384
13385 type Slice struct {
13386 elem Type
13387 }
13388 func (s *Slice) Underlying() Type { return s }
13389 func (s *Slice) String() string { return "[]" | s.elem.String() }
13390 func (s *Slice) Elem() Type { return s.elem }
13391
13392 type SSAValue interface {
13393 SSAName() string
13394 SSAType() Type
13395 }
13396
13397 type SSAInstruction interface {
13398 InstrBlock() *SSABasicBlock
13399 InstrString() string
13400 setBlock(*SSABasicBlock)
13401 }
13402
13403 type SSAMember interface {
13404 MemberName() string
13405 MemberType() Type
13406 }
13407
13408 type SSABasicBlock struct {
13409 Index int32
13410 parent *SSAFunction
13411 Instrs []SSAInstruction
13412 }
13413
13414 type SSAFunction struct {
13415 name string
13416 Blocks []*SSABasicBlock
13417 Params []*SSAParameter
13418 }
13419 func (f *SSAFunction) MemberName() string { return f.name }
13420 func (f *SSAFunction) MemberType() Type { return nil }
13421 func (f *SSAFunction) SSAName() string { return f.name }
13422 func (f *SSAFunction) SSAType() Type { return nil }
13423
13424 type SSAGlobal struct {
13425 name string
13426 typ Type
13427 }
13428 func (g *SSAGlobal) MemberName() string { return g.name }
13429 func (g *SSAGlobal) MemberType() Type { return g.typ }
13430 func (g *SSAGlobal) SSAName() string { return g.name }
13431 func (g *SSAGlobal) SSAType() Type { return g.typ }
13432
13433 type SSAParameter struct {
13434 name string
13435 typ Type
13436 parent *SSAFunction
13437 }
13438 func (p *SSAParameter) SSAName() string { return p.name }
13439 func (p *SSAParameter) SSAType() Type { return p.typ }
13440
13441 type ssaInstr struct {
13442 block *SSABasicBlock
13443 }
13444 func (a *ssaInstr) InstrBlock() *SSABasicBlock { return a.block }
13445 func (a *ssaInstr) setBlock(b *SSABasicBlock) { a.block = b }
13446
13447 type ssaRegister struct {
13448 ssaInstr
13449 name string
13450 typ Type
13451 }
13452 func (r *ssaRegister) SSAName() string { return r.name }
13453 func (r *ssaRegister) SSAType() Type { return r.typ }
13454
13455 type SSAConst struct {
13456 name string
13457 typ Type
13458 val int32
13459 }
13460 func (c *SSAConst) SSAName() string { return c.name }
13461 func (c *SSAConst) SSAType() Type { return c.typ }
13462
13463 type SSABinOp struct {
13464 ssaRegister
13465 Op string
13466 X SSAValue
13467 Y SSAValue
13468 }
13469 func (b *SSABinOp) InstrString() string {
13470 return b.name | " = " | b.Op | " " | b.X.SSAName() | " " | b.Y.SSAName()
13471 }
13472
13473 type SSACall struct {
13474 ssaRegister
13475 Fn SSAValue
13476 Args []SSAValue
13477 }
13478 func (c *SSACall) InstrString() string { return c.name | " = call " | c.Fn.SSAName() }
13479
13480 type SSAStore struct {
13481 ssaInstr
13482 Addr SSAValue
13483 Val SSAValue
13484 }
13485 func (s *SSAStore) InstrString() string { return "store " | s.Val.SSAName() | " -> " | s.Addr.SSAName() }
13486
13487 type SSARet struct {
13488 ssaInstr
13489 Val SSAValue
13490 }
13491 func (r *SSARet) InstrString() string {
13492 if r.Val == nil { return "ret void" }
13493 return "ret " | r.Val.SSAName()
13494 }
13495
13496 type SSAAlloc struct {
13497 ssaRegister
13498 Heap bool
13499 }
13500 func (a *SSAAlloc) InstrString() string {
13501 if a.Heap { return "new " | a.typ.String() }
13502 return "local " | a.typ.String()
13503 }
13504
13505 func NewBasicBlock(f *SSAFunction) *SSABasicBlock {
13506 b := &SSABasicBlock{Index: int32(len(f.Blocks)), parent: f}
13507 f.Blocks = append(f.Blocks, b)
13508 return b
13509 }
13510
13511 func emit(b *SSABasicBlock, i SSAInstruction) {
13512 i.setBlock(b)
13513 b.Instrs = append(b.Instrs, i)
13514 }
13515
13516 type Package struct {
13517 Members map[string]SSAMember
13518 }
13519
13520 func (p *Package) Func(name string) *SSAFunction {
13521 m := p.Members[name]
13522 if m == nil { return nil }
13523 fn, _ := m.(*SSAFunction)
13524 return fn
13525 }
13526
13527 func renderBlock(b *SSABasicBlock) string {
13528 var out []byte
13529 for _, instr := range b.Instrs {
13530 out = append(out, ' ')
13531 out = append(out, ' ')
13532 s := instr.InstrString()
13533 out = append(out, s...)
13534 out = append(out, '\n')
13535 }
13536 return string(out)
13537 }
13538
13539 func main() {
13540 intType := &Basic{kind: 1, name: "i32"}
13541 ptrType := &Pointer{base: intType}
13542
13543 pkg := &Package{Members: map[string]SSAMember{}}
13544
13545 fn := &SSAFunction{name: "main"}
13546 pkg.Members["main"] = fn
13547
13548 g := &SSAGlobal{name: "counter", typ: intType}
13549 pkg.Members["counter"] = g
13550
13551 entry := NewBasicBlock(fn)
13552
13553 p0 := &SSAParameter{name: "%arg0", typ: intType, parent: fn}
13554 fn.Params = append(fn.Params, p0)
13555
13556 alloc := &SSAAlloc{}
13557 alloc.name = "%t1"
13558 alloc.typ = intType
13559 emit(entry, alloc)
13560
13561 c1 := &SSAConst{name: "1", typ: intType, val: 1}
13562
13563 add := &SSABinOp{Op: "add", X: p0, Y: c1}
13564 add.name = "%t2"
13565 add.typ = intType
13566 emit(entry, add)
13567
13568 store := &SSAStore{Addr: alloc, Val: add}
13569 emit(entry, store)
13570
13571 ret := &SSARet{Val: add}
13572 emit(entry, ret)
13573
13574 lookupFn := pkg.Func("main")
13575 _ = lookupFn
13576
13577 lookupGlobal := pkg.Func("counter")
13578 _ = lookupGlobal
13579
13580 ir := renderBlock(entry)
13581 _ = ir
13582
13583 _ = ptrType.String()
13584
13585 blk := add.InstrBlock()
13586 _ = blk
13587
13588 n := int32(0)
13589 for _, b := range fn.Blocks {
13590 n = n + int32(len(b.Instrs))
13591 }
13592 _ = n
13593 }
13594 `, func(ir string) {
13595 assert("296: has SSAFunction", strings.Contains(ir, "SSAFunction"))
13596 assert("296: has SSABinOp.InstrString", strings.Contains(ir, "@main.SSABinOp.InstrString"))
13597 assert("296: has SSARet.InstrString", strings.Contains(ir, "@main.SSARet.InstrString"))
13598 assert("296: has Package.Func", strings.Contains(ir, "@main.Package.Func"))
13599 assert("296: has renderBlock", strings.Contains(ir, "@main.renderBlock"))
13600 assert("296: 2-level embedding block access", strings.Contains(ir, "@main.ssaInstr.InstrBlock"))
13601 assert("296: setBlock via embedding", strings.Contains(ir, "@main.ssaInstr.setBlock"))
13602 assert("296: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
13603 assert("296: map operations", strings.Contains(ir, "hashmapContent"))
13604 assert("296: interface boxing", strings.Contains(ir, "insertvalue {ptr, ptr}"))
13605 })
13606
13607 // Test 297: promoted method called through interface dispatch (the real self-compile pattern)
13608 test(297, `package main
13609
13610 type SSAInstruction interface {
13611 InstrBlock() *Block
13612 InstrString() string
13613 setBlock(*Block)
13614 }
13615
13616 type Block struct {
13617 Index int32
13618 Instrs []SSAInstruction
13619 }
13620
13621 func (b *Block) emit(i SSAInstruction) {
13622 i.setBlock(b)
13623 b.Instrs = append(b.Instrs, i)
13624 }
13625
13626 type instrBase struct {
13627 block *Block
13628 }
13629 func (a *instrBase) InstrBlock() *Block { return a.block }
13630 func (a *instrBase) setBlock(b *Block) { a.block = b }
13631
13632 type register struct {
13633 instrBase
13634 name string
13635 typ string
13636 }
13637
13638 type BinOp struct {
13639 register
13640 Op string
13641 }
13642 func (b *BinOp) InstrString() string { return b.name | " = " | b.Op }
13643
13644 type Store struct {
13645 instrBase
13646 dst string
13647 src string
13648 }
13649 func (s *Store) InstrString() string { return "store " | s.src | " -> " | s.dst }
13650
13651 type Ret struct {
13652 instrBase
13653 val string
13654 }
13655 func (r *Ret) InstrString() string { return "ret " | r.val }
13656
13657 func renderIR(b *Block) string {
13658 var out []byte
13659 for _, instr := range b.Instrs {
13660 s := instr.InstrString()
13661 out = append(out, s...)
13662 out = append(out, '\n')
13663 blk := instr.InstrBlock()
13664 if blk != nil && blk.Index != b.Index {
13665 out = append(out, "; wrong block\n"...)
13666 }
13667 }
13668 return string(out)
13669 }
13670
13671 func main() {
13672 b := &Block{Index: 0}
13673
13674 add := &BinOp{Op: "add"}
13675 add.name = "%t1"
13676 add.typ = "i32"
13677 b.emit(add)
13678
13679 store := &Store{dst: "%x", src: "%t1"}
13680 b.emit(store)
13681
13682 ret := &Ret{val: "%t1"}
13683 b.emit(ret)
13684
13685 ir := renderIR(b)
13686 _ = ir
13687
13688 blk := add.InstrBlock()
13689 _ = blk
13690
13691 n := int32(len(b.Instrs))
13692 _ = n
13693 }
13694 `, func(ir string) {
13695 assert("297: has Block.emit", strings.Contains(ir, "@main.Block.emit"))
13696 assert("297: has renderIR", strings.Contains(ir, "@main.renderIR"))
13697 assert("297: promoted InstrBlock", strings.Contains(ir, "@main.instrBase.InstrBlock"))
13698 assert("297: promoted setBlock", strings.Contains(ir, "@main.instrBase.setBlock"))
13699 assert("297: BinOp.InstrString", strings.Contains(ir, "@main.BinOp.InstrString"))
13700 assert("297: interface dispatch for InstrString", strings.Contains(ir, "icmp eq ptr"))
13701 })
13702
13703 // Test 298: switch on named int type (SSAOp pattern from ssa_types.mx)
13704 test(298, `package main
13705
13706 type Op int32
13707
13708 const (
13709 OpAdd Op = iota
13710 OpSub
13711 OpMul
13712 OpDiv
13713 OpEq
13714 OpNe
13715 OpLt
13716 OpGt
13717 )
13718
13719 func (op Op) String() string {
13720 switch op {
13721 case OpAdd: return "+"
13722 case OpSub: return "-"
13723 case OpMul: return "*"
13724 case OpDiv: return "/"
13725 case OpEq: return "=="
13726 case OpNe: return "!="
13727 case OpLt: return "<"
13728 case OpGt: return ">"
13729 }
13730 return "?"
13731 }
13732
13733 func (op Op) IsComparison() bool {
13734 return op >= OpEq
13735 }
13736
13737 func (op Op) Precedence() int32 {
13738 switch {
13739 case op == OpMul || op == OpDiv:
13740 return 2
13741 case op == OpAdd || op == OpSub:
13742 return 1
13743 }
13744 return 0
13745 }
13746
13747 func main() {
13748 ops := []Op{OpAdd, OpSub, OpMul, OpEq, OpLt}
13749 var strs []string
13750 for _, op := range ops {
13751 strs = append(strs, op.String())
13752 }
13753 _ = strs
13754
13755 b1 := OpEq.IsComparison()
13756 b2 := OpAdd.IsComparison()
13757 _ = b1
13758 _ = b2
13759
13760 p := OpMul.Precedence()
13761 _ = p
13762 }
13763 `, func(ir string) {
13764 assert("298: has Op.String", strings.Contains(ir, "@main.Op.String"))
13765 assert("298: has Op.IsComparison", strings.Contains(ir, "@main.Op.IsComparison"))
13766 assert("298: has Op.Precedence", strings.Contains(ir, "@main.Op.Precedence"))
13767 assert("298: switch on i32", strings.Contains(ir, "icmp eq i32"))
13768 })
13769
13770 // Test 299: map[string]SSAMember with type assertion and iteration
13771 test(299, `package main
13772
13773 type SSAMember interface {
13774 MemberName() string
13775 }
13776
13777 type SSAFunction struct {
13778 name string
13779 body string
13780 }
13781 func (f *SSAFunction) MemberName() string { return f.name }
13782
13783 type SSAGlobal struct {
13784 name string
13785 typ string
13786 }
13787 func (g *SSAGlobal) MemberName() string { return g.name }
13788
13789 type SSAPackage struct {
13790 Members map[string]SSAMember
13791 }
13792
13793 func (p *SSAPackage) Func(name string) *SSAFunction {
13794 m := p.Members[name]
13795 if m == nil { return nil }
13796 fn, ok := m.(*SSAFunction)
13797 if !ok { return nil }
13798 return fn
13799 }
13800
13801 func (p *SSAPackage) AllFuncs() []*SSAFunction {
13802 var funcs []*SSAFunction
13803 for _, m := range p.Members {
13804 if fn, ok := m.(*SSAFunction); ok {
13805 funcs = append(funcs, fn)
13806 }
13807 }
13808 return funcs
13809 }
13810
13811 func (p *SSAPackage) AllNames() []string {
13812 var names []string
13813 for name := range p.Members {
13814 names = append(names, name)
13815 }
13816 return names
13817 }
13818
13819 func main() {
13820 pkg := &SSAPackage{Members: map[string]SSAMember{}}
13821 pkg.Members["main"] = &SSAFunction{name: "main", body: "entry"}
13822 pkg.Members["init"] = &SSAFunction{name: "init", body: ""}
13823 pkg.Members["counter"] = &SSAGlobal{name: "counter", typ: "i32"}
13824
13825 fn := pkg.Func("main")
13826 _ = fn
13827 nilFn := pkg.Func("counter")
13828 _ = nilFn
13829 missingFn := pkg.Func("missing")
13830 _ = missingFn
13831
13832 allFn := pkg.AllFuncs()
13833 _ = allFn
13834 allN := pkg.AllNames()
13835 _ = allN
13836 }
13837 `, func(ir string) {
13838 assert("299: has SSAPackage.Func", strings.Contains(ir, "@main.SSAPackage.Func"))
13839 assert("299: has SSAPackage.AllFuncs", strings.Contains(ir, "@main.SSAPackage.AllFuncs"))
13840 assert("299: has SSAPackage.AllNames", strings.Contains(ir, "@main.SSAPackage.AllNames"))
13841 assert("299: type assertion", strings.Contains(ir, "typeid"))
13842 assert("299: map iteration", strings.Contains(ir, "hashmapNext"))
13843 })
13844
13845 // Test 300: Full 350-line bootstrap simulation - types, builder, emitter pipeline
13846 test(300, `package main
13847
13848 type Type interface {
13849 Underlying() Type
13850 String() string
13851 }
13852 type Basic struct { kind int32; name string }
13853 func (b *Basic) Underlying() Type { return b }
13854 func (b *Basic) String() string { return b.name }
13855 type Pointer struct { base Type }
13856 func (p *Pointer) Underlying() Type { return p }
13857 func (p *Pointer) String() string { return "*" | p.base.String() }
13858 func (p *Pointer) Elem() Type { return p.base }
13859 type Slice struct { elem Type }
13860 func (s *Slice) Underlying() Type { return s }
13861 func (s *Slice) String() string { return "[]" | s.elem.String() }
13862 type Named struct { obj string; underlying Type }
13863 func (n *Named) Underlying() Type {
13864 if n.underlying != nil { return n.underlying }
13865 return n
13866 }
13867 func (n *Named) String() string { return n.obj }
13868 func NewPointer(base Type) *Pointer { return &Pointer{base: base} }
13869 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
13870
13871 type SSAValue interface { SSAName() string; SSAType() Type }
13872 type SSAInstruction interface { InstrString() string; setBlock(*Block) }
13873 type Block struct { index int32; instrs []SSAInstruction }
13874 func (b *Block) emit(i SSAInstruction) {
13875 i.setBlock(b)
13876 b.instrs = append(b.instrs, i)
13877 }
13878 type instrBase struct { block *Block }
13879 func (a *instrBase) setBlock(b *Block) { a.block = b }
13880 type register struct { instrBase; name string; typ Type }
13881 func (r *register) SSAName() string { return r.name }
13882 func (r *register) SSAType() Type { return r.typ }
13883
13884 type SSAConst struct { name string; typ Type; val int32 }
13885 func (c *SSAConst) SSAName() string { return c.name }
13886 func (c *SSAConst) SSAType() Type { return c.typ }
13887
13888 type BinOp struct { register; Op string; X SSAValue; Y SSAValue }
13889 func (b *BinOp) InstrString() string {
13890 return b.name | " = " | b.Op | " " | llvmType300(b.typ) | " " | b.X.SSAName() | ", " | b.Y.SSAName()
13891 }
13892 type Call struct { register; fn SSAValue; args []SSAValue }
13893 func (c *Call) InstrString() string { return c.name | " = call " | c.fn.SSAName() }
13894 type Store struct { instrBase; addr SSAValue; val SSAValue }
13895 func (s *Store) InstrString() string { return "store " | llvmType300(s.val.SSAType()) | " " | s.val.SSAName() | ", ptr " | s.addr.SSAName() }
13896 type Ret struct { instrBase; val SSAValue }
13897 func (r *Ret) InstrString() string {
13898 if r.val == nil { return "ret void" }
13899 return "ret " | llvmType300(r.val.SSAType()) | " " | r.val.SSAName()
13900 }
13901 type Alloc struct { register; heap bool }
13902 func (a *Alloc) InstrString() string {
13903 return a.name | " = alloca " | llvmType300(a.typ)
13904 }
13905 type FieldAddr struct { register; x SSAValue; field int32 }
13906 func (fa *FieldAddr) InstrString() string {
13907 return fa.name | " = getelementptr " | fa.x.SSAName()
13908 }
13909
13910 func llvmType300(t Type) string {
13911 if t == nil { return "void" }
13912 switch u := t.Underlying().(type) {
13913 case *Basic:
13914 switch u.kind {
13915 case 1: return "i8"
13916 case 2: return "i32"
13917 case 3: return "i64"
13918 case 4: return "{ptr, i64, i64}"
13919 }
13920 return "i8"
13921 case *Pointer: return "ptr"
13922 case *Slice: return "{ptr, i64, i64}"
13923 case *Named: return llvmType300(u.Underlying())
13924 }
13925 return "void"
13926 }
13927
13928 type Emitter struct {
13929 buf []byte
13930 nextReg int32
13931 }
13932
13933 func (e *Emitter) w(s string) { e.buf = append(e.buf, s...) }
13934
13935 func (e *Emitter) fresh() string {
13936 e.nextReg = e.nextReg + 1
13937 return "%t" | itoa300(e.nextReg)
13938 }
13939
13940 func (e *Emitter) emitInstr(i SSAInstruction) {
13941 e.w(" ")
13942 e.w(i.InstrString())
13943 e.w("\n")
13944 }
13945
13946 func (e *Emitter) emitBlock(b *Block) {
13947 e.w("b")
13948 e.w(itoa300(int32(b.index)))
13949 e.w(":\n")
13950 for _, instr := range b.instrs {
13951 e.emitInstr(instr)
13952 }
13953 }
13954
13955 func (e *Emitter) emitFunc(name string, blocks []*Block) string {
13956 e.w("define void @")
13957 e.w(name)
13958 e.w("() {\n")
13959 for _, b := range blocks {
13960 e.emitBlock(b)
13961 }
13962 e.w("}\n")
13963 return string(e.buf)
13964 }
13965
13966 func itoa300(n int32) string {
13967 if n == 0 { return "0" }
13968 if n < 0 { return "-" | itoa300(-n) }
13969 var buf [10]byte
13970 i := int32(9)
13971 for n > 0 {
13972 buf[i] = byte(n%10) + '0'
13973 n = n / 10
13974 i = i - 1
13975 }
13976 return string(buf[i+1:])
13977 }
13978
13979 type Scope struct {
13980 parent *Scope
13981 names map[string]SSAValue
13982 }
13983
13984 func (s *Scope) Lookup(name string) SSAValue {
13985 if s.names != nil {
13986 v, ok := s.names[name]
13987 if ok { return v }
13988 }
13989 if s.parent != nil { return s.parent.Lookup(name) }
13990 return nil
13991 }
13992
13993 func main() {
13994 i32 := &Basic{kind: 2, name: "int32"}
13995 i64 := &Basic{kind: 3, name: "int64"}
13996 strType := &Basic{kind: 4, name: "string"}
13997 ptrI32 := NewPointer(i32)
13998 sliceStr := NewSlice(strType)
13999 myInt := &Named{obj: "MyInt", underlying: i32}
14000
14001 _ = llvmType300(i32)
14002 _ = llvmType300(i64)
14003 _ = llvmType300(ptrI32)
14004 _ = llvmType300(sliceStr)
14005 _ = llvmType300(myInt)
14006 _ = llvmType300(nil)
14007
14008 entry := &Block{index: 0}
14009 retBlock := &Block{index: 1}
14010
14011 c1 := &SSAConst{name: "1", typ: i32, val: 1}
14012 c2 := &SSAConst{name: "2", typ: i32, val: 2}
14013
14014 alloc := &Alloc{}
14015 alloc.name = "%t1"
14016 alloc.typ = i32
14017 entry.emit(alloc)
14018
14019 add := &BinOp{Op: "add", X: c1, Y: c2}
14020 add.name = "%t2"
14021 add.typ = i32
14022 entry.emit(add)
14023
14024 store := &Store{addr: alloc, val: add}
14025 entry.emit(store)
14026
14027 fa := &FieldAddr{x: alloc, field: 0}
14028 fa.name = "%t3"
14029 fa.typ = ptrI32
14030 entry.emit(fa)
14031
14032 ret := &Ret{val: add}
14033 retBlock.emit(ret)
14034
14035 retVoid := &Ret{}
14036 retBlock.emit(retVoid)
14037
14038 e := &Emitter{}
14039 ir := e.emitFunc("test", []*Block{entry, retBlock})
14040 _ = ir
14041
14042 scope := &Scope{
14043 names: map[string]SSAValue{},
14044 }
14045 scope.names["x"] = alloc
14046 scope.names["y"] = add
14047
14048 child := &Scope{parent: scope, names: map[string]SSAValue{}}
14049 child.names["z"] = c1
14050
14051 v1 := child.Lookup("z")
14052 v2 := child.Lookup("x")
14053 v3 := child.Lookup("missing")
14054 _ = v1
14055 _ = v2
14056 _ = v3
14057 }
14058 `, func(ir string) {
14059 assert("300: has Emitter.emitFunc", strings.Contains(ir, "@main.Emitter.emitFunc"))
14060 assert("300: has Emitter.emitBlock", strings.Contains(ir, "@main.Emitter.emitBlock"))
14061 assert("300: has Emitter.emitInstr", strings.Contains(ir, "@main.Emitter.emitInstr"))
14062 assert("300: has llvmType300", strings.Contains(ir, "@main.llvmType300"))
14063 assert("300: has Scope.Lookup", strings.Contains(ir, "@main.Scope.Lookup"))
14064 assert("300: 2-level embed setBlock", strings.Contains(ir, "@main.instrBase.setBlock"))
14065 assert("300: type switch dispatch", strings.Contains(ir, "typeid"))
14066 assert("300: nested switch", strings.Contains(ir, "icmp eq i32"))
14067 assert("300: interface dispatch", strings.Contains(ir, "icmp eq ptr"))
14068 assert("300: recursive call", strings.Count(ir, "@main.Scope.Lookup") >= 2)
14069 assert("300: map operations", strings.Contains(ir, "hashmapContent"))
14070 assert("300: array subslice", strings.Contains(ir, "alloca [10 x i8]"))
14071 assert("300: nil ret check", strings.Contains(ir, "ret void") || strings.Contains(ir, "zeroinitializer"))
14072 })
14073
14074 // Test 301: import registered package and call function
14075 clearImports()
14076 regPkg("fmt", "fmt")
14077 regFn("fmt", "Sprintf", "string->string")
14078 test(301, `package main
14079
14080 import "fmt"
14081
14082 func main() {
14083 s := fmt.Sprintf("hello")
14084 _ = s
14085 }
14086 `, func(ir string) {
14087 assert("301: has declare for fmt.Sprintf", strings.Contains(ir, "declare") && strings.Contains(ir, "@fmt.Sprintf"))
14088 assert("301: has call to fmt.Sprintf", strings.Contains(ir, "call") && strings.Contains(ir, "@fmt.Sprintf"))
14089 assert("301: result is string type", strings.Contains(ir, "{ptr, i") || strings.Contains(ir, "ptr"))
14090 })
14091
14092 // Test 302: import with multiple functions
14093 clearImports()
14094 regPkg("strconv", "strconv")
14095 regFn("strconv", "Itoa", "int->string")
14096 regFn("strconv", "Atoi", "string->int,error")
14097 test(302, `package main
14098
14099 import "strconv"
14100
14101 func main() {
14102 s := strconv.Itoa(42)
14103 _ = s
14104 }
14105 `, func(ir string) {
14106 assert("302: has declare for strconv.Itoa", strings.Contains(ir, "declare") && strings.Contains(ir, "@strconv.Itoa"))
14107 assert("302: has call to strconv.Itoa", strings.Contains(ir, "call") && strings.Contains(ir, "@strconv.Itoa"))
14108 })
14109
14110 // Test 303: import with global var
14111 clearImports()
14112 regPkg("os", "os")
14113 regVar("os", "Stdout", "ptr")
14114 regFn("os", "Exit", "int")
14115 test(303, `package main
14116
14117 import "os"
14118
14119 func main() {
14120 os.Exit(1)
14121 }
14122 `, func(ir string) {
14123 assert("303: has declare for os.Exit", strings.Contains(ir, "declare") && strings.Contains(ir, "@os.Exit"))
14124 assert("303: has call to os.Exit", strings.Contains(ir, "call") && strings.Contains(ir, "@os.Exit"))
14125 })
14126
14127 // Test 304: import with aliased package name
14128 clearImports()
14129 regPkg("fmt", "fmt")
14130 regFn("fmt", "Sprintf", "string->string")
14131 test(304, `package main
14132
14133 import f "fmt"
14134
14135 func main() {
14136 s := f.Sprintf("hello")
14137 _ = s
14138 }
14139 `, func(ir string) {
14140 assert("304: aliased import calls fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
14141 })
14142
14143 // Test 305: multiple imports in same compilation
14144 clearImports()
14145 regPkg("fmt", "fmt")
14146 regFn("fmt", "Sprintf", "string->string")
14147 regPkg("strconv", "strconv")
14148 regFn("strconv", "Itoa", "int->string")
14149 test(305, `package main
14150
14151 import (
14152 "fmt"
14153 "strconv"
14154 )
14155
14156 func main() {
14157 n := strconv.Itoa(42)
14158 s := fmt.Sprintf(n)
14159 _ = s
14160 }
14161 `, func(ir string) {
14162 assert("305: has fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
14163 assert("305: has strconv.Itoa", strings.Contains(ir, "@strconv.Itoa"))
14164 assert("305: both declared", strings.Count(ir, "declare") >= 2)
14165 })
14166
14167 // Test 306: import function with slice param
14168 clearImports()
14169 regPkg("bytes", "bytes")
14170 regFn("bytes", "Join", "[]string,string->string")
14171 test(306, `package main
14172
14173 import "bytes"
14174
14175 func join(parts []string, sep string) string {
14176 return bytes.Join(parts, sep)
14177 }
14178 `, func(ir string) {
14179 assert("306: has bytes.Join declare", strings.Contains(ir, "@bytes.Join"))
14180 assert("306: passes slice arg", strings.Contains(ir, "call") && strings.Contains(ir, "@bytes.Join"))
14181 })
14182
14183 // Test 307: use imported var (global read)
14184 clearImports()
14185 regPkg("os", "os")
14186 regVar("os", "Args", "[]string")
14187 test(307, `package main
14188
14189 import "os"
14190
14191 func getFirst() string {
14192 return os.Args[0]
14193 }
14194 `, func(ir string) {
14195 assert("307: has external global for os.Args", strings.Contains(ir, "@os.Args") && strings.Contains(ir, "external global"))
14196 assert("307: loads from os.Args", strings.Contains(ir, "load") && strings.Contains(ir, "@os.Args"))
14197 })
14198
14199 // Test 308: import function returning void (no return value)
14200 clearImports()
14201
14202 // Test 309: function returning error interface
14203 clearImports()
14204 regPkg("strconv", "strconv")
14205 regFn("strconv", "Atoi", "string->int,error")
14206 test(309, `package main
14207
14208 import "strconv"
14209
14210 func tryParse(s string) int32 {
14211 n, err := strconv.Atoi(s)
14212 if err != nil {
14213 return -1
14214 }
14215 return n
14216 }
14217 `, func(ir string) {
14218 assert("309: has strconv.Atoi declare", strings.Contains(ir, "@strconv.Atoi"))
14219 assert("309: multi-return extraction", strings.Contains(ir, "extractvalue"))
14220 assert("309: nil check on error", strings.Contains(ir, "icmp"))
14221 })
14222
14223 // Test 310: function taking interface{} parameter
14224 clearImports()
14225 regPkg("fmt", "fmt")
14226 regFn("fmt", "Println", "interface{}->int,error")
14227 test(310, `package main
14228
14229 import "fmt"
14230
14231 func main() {
14232 fmt.Println(42)
14233 }
14234 `, func(ir string) {
14235 assert("310: has fmt.Println declare", strings.Contains(ir, "@fmt.Println"))
14236 assert("310: call with boxing", strings.Contains(ir, "call") && strings.Contains(ir, "@fmt.Println"))
14237 })
14238
14239 // Test 311: imported function used in expression
14240 clearImports()
14241 regPkg("strconv", "strconv")
14242 regFn("strconv", "Itoa", "int->string")
14243 test(311, `package main
14244
14245 import "strconv"
14246
14247 func describe(n int32) string {
14248 return "val:" | strconv.Itoa(n)
14249 }
14250 `, func(ir string) {
14251 assert("311: has strconv.Itoa", strings.Contains(ir, "@strconv.Itoa"))
14252 assert("311: string concat after call", strings.Contains(ir, "sliceAppend") || strings.Contains(ir, "runtime.stringConcat"))
14253 })
14254
14255 clearImports()
14256
14257 // Test 312: pos.mx pattern - value receiver structs, self-referential types, struct compare
14258 clearImports()
14259 regPkg("fmt", "fmt")
14260 regFn("fmt", "Sprintf", "string,interface{},interface{}->string")
14261 test(312, `package main
14262
14263 import "fmt"
14264
14265 const PosMax = 1 << 30
14266
14267 type Pos struct {
14268 base *PosBase
14269 line, col uint32
14270 }
14271
14272 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, sat32(line), sat32(col)} }
14273
14274 func (pos Pos) IsKnown() bool { return pos.line > 0 }
14275 func (pos Pos) Base() *PosBase { return pos.base }
14276 func (pos Pos) Line() uint32 { return pos.line }
14277 func (pos Pos) Col() uint32 { return pos.col }
14278
14279 func (pos Pos) FileBase() *PosBase {
14280 b := pos.base
14281 for b != nil && b != b.pos.base {
14282 b = b.pos.base
14283 }
14284 return b
14285 }
14286
14287 func (pos Pos) RelFilename() string { return pos.base.Filename() }
14288
14289 type position_ struct {
14290 filename string
14291 line, col uint32
14292 }
14293
14294 func (p position_) String() string {
14295 if p.line == 0 {
14296 if p.filename == "" {
14297 return "<unknown position>"
14298 }
14299 return p.filename
14300 }
14301 if p.col == 0 {
14302 return fmt.Sprintf("%s:%d", p.filename, p.line)
14303 }
14304 return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
14305 }
14306
14307 type PosBase struct {
14308 pos Pos
14309 filename string
14310 line, col uint32
14311 trimmed bool
14312 }
14313
14314 func NewFileBase(filename string) *PosBase {
14315 return NewTrimmedFileBase(filename, false)
14316 }
14317
14318 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14319 base := &PosBase{MakePos(nil, 1, 1), filename, 1, 1, trimmed}
14320 base.pos.base = base
14321 return base
14322 }
14323
14324 func (base *PosBase) IsFileBase() bool {
14325 if base == nil {
14326 return false
14327 }
14328 return base.pos.base == base
14329 }
14330
14331 func (base *PosBase) Filename() string {
14332 if base == nil {
14333 return ""
14334 }
14335 return base.filename
14336 }
14337
14338 func (base *PosBase) Line() uint32 {
14339 if base == nil {
14340 return 0
14341 }
14342 return base.line
14343 }
14344
14345 func (base *PosBase) Col() uint32 {
14346 if base == nil {
14347 return 0
14348 }
14349 return base.col
14350 }
14351
14352 func sat32(x uint32) uint32 {
14353 if x > PosMax {
14354 return PosMax
14355 }
14356 return uint32(x)
14357 }
14358
14359 func main() {
14360 base := NewFileBase("test.mx")
14361 pos := MakePos(base, 10, 5)
14362 _ = pos.IsKnown()
14363 _ = pos.Line()
14364 _ = pos.Col()
14365 _ = pos.FileBase()
14366 _ = pos.RelFilename()
14367 _ = base.IsFileBase()
14368 _ = base.Filename()
14369 }
14370 `, func(ir string) {
14371 assert("312: has MakePos", strings.Contains(ir, "@main.MakePos"))
14372 assert("312: has PosBase methods", strings.Contains(ir, "@main.PosBase.Filename"))
14373 assert("312: has value receiver Pos.Line", strings.Contains(ir, "@main.Pos.Line"))
14374 assert("312: has self-ref assignment", strings.Contains(ir, "store"))
14375 assert("312: has nil check", strings.Contains(ir, "icmp"))
14376 assert("312: has fmt.Sprintf declare", strings.Contains(ir, "@fmt.Sprintf"))
14377 assert("312: produces many functions", strings.Count(ir, "\ndefine ") >= 10)
14378 llvmVerify("312: pos.mx pattern", ir)
14379 })
14380
14381 // Test 313: multi-file concat simulation - source.mx + pos.mx constants
14382 test(313, `package main
14383
14384 const Linebase = 1
14385 const Colbase = 1
14386
14387 type Pos struct {
14388 base *PosBase
14389 line, col uint32
14390 }
14391
14392 type PosBase struct {
14393 pos Pos
14394 filename string
14395 line, col uint32
14396 trimmed bool
14397 }
14398
14399 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, line, col} }
14400
14401 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14402 base := &PosBase{MakePos(nil, Linebase, Colbase), filename, Linebase, Colbase, trimmed}
14403 base.pos.base = base
14404 return base
14405 }
14406
14407 func main() {
14408 b := NewTrimmedFileBase("hello.mx", false)
14409 p := MakePos(b, 42, 7)
14410 _ = p.line
14411 _ = p.col
14412 _ = b.pos.line
14413 }
14414 `, func(ir string) {
14415 assert("313: has NewTrimmedFileBase", strings.Contains(ir, "@main.NewTrimmedFileBase"))
14416 assert("313: has MakePos", strings.Contains(ir, "@main.MakePos"))
14417 assert("313: self-referential store", strings.Contains(ir, "store"))
14418 llvmVerify("313: multi-file concat", ir)
14419 })
14420
14421 clearImports()
14422
14423 // Test 315: && with nested struct field access (b.pos.base pattern)
14424 test(315, `package main
14425
14426 type Inner struct {
14427 ref *Outer
14428 val int32
14429 }
14430
14431 type Outer struct {
14432 inner Inner
14433 name string
14434 }
14435
14436 func findRoot(b *Outer) *Outer {
14437 for b != nil && b != b.inner.ref {
14438 b = b.inner.ref
14439 }
14440 return b
14441 }
14442
14443 func main() {
14444 o := &Outer{Inner{nil, 1}, "test"}
14445 o.inner.ref = o
14446 r := findRoot(o)
14447 _ = r
14448 }
14449 `, func(ir string) {
14450 assert("315: has findRoot", strings.Contains(ir, "@main.findRoot"))
14451 assert("315: has loop", strings.Contains(ir, "br i1") || strings.Contains(ir, "br label"))
14452 llvmVerify("315: nested field && pattern", ir)
14453 })
14454
14455 // Test 316: positional struct literal stores values
14456 test(316, `package main
14457
14458 type Vec3 struct {
14459 x, y, z int32
14460 }
14461
14462 func make3(a, b, c int32) Vec3 {
14463 return Vec3{a, b, c}
14464 }
14465
14466 func main() {
14467 v := make3(10, 20, 30)
14468 _ = v.x
14469 _ = v.y
14470 _ = v.z
14471 }
14472 `, func(ir string) {
14473 geps := strings.Count(ir, "getelementptr")
14474 stores := strings.Count(ir, "store")
14475 assert("316: has field stores in make3", geps >= 3 && stores >= 3)
14476 assert("316: stores i32 values", strings.Contains(ir, "store i32"))
14477 llvmVerify("316: positional struct literal", ir)
14478 })
14479
14480 // Test 317: positional struct literal with mixed types
14481 test(317, `package main
14482
14483 type Pair struct {
14484 name string
14485 val int32
14486 }
14487
14488 func makePair(n string, v int32) Pair {
14489 return Pair{n, v}
14490 }
14491
14492 func main() {
14493 p := makePair("hello", 42)
14494 _ = p.name
14495 _ = p.val
14496 }
14497 `, func(ir string) {
14498 assert("317: stores string field", strings.Contains(ir, "store {ptr, i64, i64}"))
14499 assert("317: stores int field", strings.Contains(ir, "store i32"))
14500 llvmVerify("317: mixed positional struct literal", ir)
14501 })
14502
14503 // Test 318: struct comparison with == and !=
14504 test(318, `package main
14505
14506 type Point struct {
14507 x, y int32
14508 }
14509
14510 func equal(a, b Point) bool {
14511 return a == b
14512 }
14513
14514 func notEqual(a, b Point) bool {
14515 return a != b
14516 }
14517
14518 func main() {
14519 p1 := Point{1, 2}
14520 p2 := Point{1, 2}
14521 _ = equal(p1, p2)
14522 _ = notEqual(p1, p2)
14523 }
14524 `, func(ir string) {
14525 assert("318: has comparison", strings.Contains(ir, "icmp"))
14526 llvmVerify("318: struct comparison", ir)
14527 })
14528
14529 // Test 319: struct comparison with string fields
14530 test(319, `package main
14531
14532 type Position struct {
14533 filename string
14534 line, col int32
14535 }
14536
14537 func same(a, b Position) bool {
14538 return a == b
14539 }
14540
14541 func main() {
14542 p1 := Position{"test.go", 10, 5}
14543 p2 := Position{"test.go", 10, 5}
14544 _ = same(p1, p2)
14545 }
14546 `, func(ir string) {
14547 assert("319: has stringEqual call", strings.Contains(ir, "runtime.stringEqual"))
14548 assert("319: has field extracts", strings.Contains(ir, "extractvalue"))
14549 assert("319: has and accumulation", strings.Contains(ir, "and i1"))
14550 llvmVerify("319: struct compare with string", ir)
14551 })
14552
14553 // Test 320: actual pos.mx from bootstrap (with Linebase/Colbase inlined)
14554 clearImports()
14555 regPkg("fmt", "fmt")
14556 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
14557 test(320, `package main
14558
14559 import "fmt"
14560
14561 const PosMax = 1 << 30
14562 const Linebase = 1
14563 const Colbase = 1
14564
14565 type Pos struct {
14566 base *PosBase
14567 line, col uint32
14568 }
14569
14570 func MakePos(base *PosBase, line, col uint32) Pos { return Pos{base, sat32(line), sat32(col)} }
14571
14572 func (pos Pos) IsKnown() bool { return pos.line > 0 }
14573 func (pos Pos) Base() *PosBase { return pos.base }
14574 func (pos Pos) Line() uint32 { return pos.line }
14575 func (pos Pos) Col() uint32 { return pos.col }
14576
14577 func (pos Pos) FileBase() *PosBase {
14578 b := pos.base
14579 for b != nil && b != b.pos.base {
14580 b = b.pos.base
14581 }
14582 return b
14583 }
14584
14585 func (pos Pos) RelFilename() string { return pos.base.Filename() }
14586
14587 func (pos Pos) RelLine() uint32 {
14588 b := pos.base
14589 if b.Line() == 0 {
14590 return 0
14591 }
14592 return b.Line() + (pos.Line() - b.Pos().Line())
14593 }
14594
14595 func (pos Pos) RelCol() uint32 {
14596 b := pos.base
14597 if b.Col() == 0 {
14598 return 0
14599 }
14600 if pos.Line() == b.Pos().Line() {
14601 return b.Col() + (pos.Col() - b.Pos().Col())
14602 }
14603 return pos.Col()
14604 }
14605
14606 func (p Pos) Cmp(q Pos) int {
14607 pname := p.RelFilename()
14608 qname := q.RelFilename()
14609 switch {
14610 case pname < qname:
14611 return -1
14612 case pname > qname:
14613 return +1
14614 }
14615
14616 pline := p.Line()
14617 qline := q.Line()
14618 switch {
14619 case pline < qline:
14620 return -1
14621 case pline > qline:
14622 return +1
14623 }
14624
14625 pcol := p.Col()
14626 qcol := q.Col()
14627 switch {
14628 case pcol < qcol:
14629 return -1
14630 case pcol > qcol:
14631 return +1
14632 }
14633
14634 return 0
14635 }
14636
14637 func (pos Pos) String() string {
14638 rel := position_{pos.RelFilename(), pos.RelLine(), pos.RelCol()}
14639 abs := position_{pos.Base().Pos().RelFilename(), pos.Line(), pos.Col()}
14640 s := rel.String()
14641 if rel != abs {
14642 s = s | "[" | abs.String() | "]"
14643 }
14644 return s
14645 }
14646
14647 type position_ struct {
14648 filename string
14649 line, col uint32
14650 }
14651
14652 func (p position_) String() string {
14653 if p.line == 0 {
14654 if p.filename == "" {
14655 return "<unknown position>"
14656 }
14657 return p.filename
14658 }
14659 if p.col == 0 {
14660 return fmt.Sprintf("%s:%d", p.filename, p.line)
14661 }
14662 return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col)
14663 }
14664
14665 type PosBase struct {
14666 pos Pos
14667 filename string
14668 line, col uint32
14669 trimmed bool
14670 }
14671
14672 func NewFileBase(filename string) *PosBase {
14673 return NewTrimmedFileBase(filename, false)
14674 }
14675
14676 func NewTrimmedFileBase(filename string, trimmed bool) *PosBase {
14677 base := &PosBase{MakePos(nil, Linebase, Colbase), filename, Linebase, Colbase, trimmed}
14678 base.pos.base = base
14679 return base
14680 }
14681
14682 func NewLineBase(pos Pos, filename string, trimmed bool, line, col uint32) *PosBase {
14683 return &PosBase{pos, filename, sat32(line), sat32(col), trimmed}
14684 }
14685
14686 func (base *PosBase) IsFileBase() bool {
14687 if base == nil {
14688 return false
14689 }
14690 return base.pos.base == base
14691 }
14692
14693 func (base *PosBase) Pos() (_ Pos) {
14694 if base == nil {
14695 return
14696 }
14697 return base.pos
14698 }
14699
14700 func (base *PosBase) Filename() string {
14701 if base == nil {
14702 return ""
14703 }
14704 return base.filename
14705 }
14706
14707 func (base *PosBase) Line() uint32 {
14708 if base == nil {
14709 return 0
14710 }
14711 return base.line
14712 }
14713
14714 func (base *PosBase) Col() uint32 {
14715 if base == nil {
14716 return 0
14717 }
14718 return base.col
14719 }
14720
14721 func (base *PosBase) Trimmed() bool {
14722 if base == nil {
14723 return false
14724 }
14725 return base.trimmed
14726 }
14727
14728 func sat32(x uint32) uint32 {
14729 if x > PosMax {
14730 return PosMax
14731 }
14732 return uint32(x)
14733 }
14734
14735 func main() {
14736 base := NewFileBase("test.mx")
14737 pos := MakePos(base, 10, 5)
14738 _ = pos.IsKnown()
14739 _ = pos.Line()
14740 _ = pos.Col()
14741 fb := pos.FileBase()
14742 _ = fb
14743 _ = pos.RelFilename()
14744 _ = pos.String()
14745 _ = pos.Cmp(MakePos(base, 20, 1))
14746 _ = base.IsFileBase()
14747 }
14748 `, func(ir string) {
14749 funcCount := strings.Count(ir, "\ndefine ")
14750 assert("320: compiles all pos.mx functions", funcCount >= 20)
14751 assert("320: has MakePos", strings.Contains(ir, "@main.MakePos"))
14752 assert("320: has Pos.String", strings.Contains(ir, "@main.Pos.String"))
14753 assert("320: has Pos.Cmp", strings.Contains(ir, "@main.Pos.Cmp"))
14754 assert("320: has position_.String", strings.Contains(ir, "@main.position_.String"))
14755 assert("320: has NewTrimmedFileBase", strings.Contains(ir, "@main.NewTrimmedFileBase"))
14756 assert("320: has PosBase.Pos", strings.Contains(ir, "@main.PosBase.Pos"))
14757 assert("320: has struct compare", strings.Contains(ir, "extractvalue") && strings.Contains(ir, "and i1"))
14758 assert("320: has fmt.Sprintf", strings.Contains(ir, "@fmt.Sprintf"))
14759 llvmVerify("320: real pos.mx", ir)
14760 })
14761
14762 clearImports()
14763
14764 // Test 314: && with field access (isolated from pos.mx FileBase pattern)
14765 test(314, `package main
14766
14767 type Node struct {
14768 parent *Node
14769 val int32
14770 }
14771
14772 func findRoot(n *Node) *Node {
14773 for n != nil && n != n.parent {
14774 n = n.parent
14775 }
14776 return n
14777 }
14778
14779 func main() {
14780 a := &Node{nil, 1}
14781 a.parent = a
14782 r := findRoot(a)
14783 _ = r
14784 }
14785 `, func(ir string) {
14786 assert("314: has findRoot", strings.Contains(ir, "@main.findRoot"))
14787 assert("314: has loop branch", strings.Contains(ir, "br i1") || strings.Contains(ir, "br label"))
14788 })
14789
14790 clearImports()
14791
14792 // Test 321: ssa_types.mx first 100 lines (op codes, switch on named int)
14793 test(321, `package main
14794
14795 type SSAOp int32
14796
14797 const (
14798 OpIllegal SSAOp = iota
14799 OpAdd
14800 OpSub
14801 OpMul
14802 OpQuo
14803 OpRem
14804 OpEql
14805 OpNeq
14806 )
14807
14808 func (op SSAOp) String() string {
14809 switch op {
14810 case OpAdd:
14811 return "+"
14812 case OpSub:
14813 return "-"
14814 case OpMul:
14815 return "*"
14816 case OpQuo:
14817 return "/"
14818 case OpRem:
14819 return "percent"
14820 case OpEql:
14821 return "=="
14822 case OpNeq:
14823 return "!="
14824 }
14825 return "?"
14826 }
14827
14828 type ConstVal interface {
14829 String() string
14830 }
14831
14832 func ssaConstString(val ConstVal) string {
14833 if val == nil {
14834 return "nil"
14835 }
14836 return val.String()
14837 }
14838
14839 type SSAValue interface {
14840 SSAName() string
14841 SSAType() Type
14842 }
14843
14844 type SSAInstruction interface {
14845 setBlock(b *SSABasicBlock)
14846 }
14847
14848 type Type interface {
14849 Underlying() Type
14850 String() string
14851 }
14852
14853 type SSABasicBlock struct {
14854 Index int32
14855 Instrs []SSAInstruction
14856 Succs []*SSABasicBlock
14857 Preds []*SSABasicBlock
14858 }
14859
14860 type SSAFunction struct {
14861 name string
14862 Blocks []*SSABasicBlock
14863 Params []*SSAParameter
14864 FreeVars []*SSAFreeVar
14865 Signature *Signature
14866 Pkg *SSAPackage
14867 Prog *SSAProgram
14868 AnonFuncs []*SSAFunction
14869 }
14870
14871 type SSAParameter struct {
14872 name string
14873 typ Type
14874 parent *SSAFunction
14875 }
14876 func (p *SSAParameter) SSAName() string { return p.name }
14877 func (p *SSAParameter) SSAType() Type { return p.typ }
14878 func (p *SSAParameter) SSAParent() *SSAFunction { return p.parent }
14879
14880 type SSAFreeVar struct {
14881 name string
14882 typ Type
14883 parent *SSAFunction
14884 }
14885 func (f *SSAFreeVar) SSAName() string { return f.name }
14886 func (f *SSAFreeVar) SSAType() Type { return f.typ }
14887
14888 type SSAPackage struct {
14889 Prog *SSAProgram
14890 Members map[string]SSAMember
14891 }
14892
14893 type SSAMember interface {
14894 SSAName() string
14895 }
14896
14897 type SSAProgram struct {
14898 packages map[*TCPackage]*SSAPackage
14899 imported map[string]*SSAPackage
14900 }
14901
14902 type TCPackage struct {
14903 path string
14904 name string
14905 scope *Scope
14906 }
14907 func (p *TCPackage) Path() string { return p.path }
14908 func (p *TCPackage) Name() string { return p.name }
14909 func (p *TCPackage) Scope() *Scope { return p.scope }
14910
14911 type Scope struct {
14912 parent *Scope
14913 objects map[string]Object
14914 }
14915 func NewScope(parent *Scope) *Scope { return &Scope{parent, map[string]Object{}} }
14916 func (s *Scope) Lookup(name string) Object {
14917 if s.objects != nil {
14918 if obj, ok := s.objects[name]; ok {
14919 return obj
14920 }
14921 }
14922 return nil
14923 }
14924
14925 type Object interface {
14926 Name() string
14927 }
14928
14929 type Signature struct {
14930 recv *TCVar
14931 params *Tuple
14932 results *Tuple
14933 }
14934 func NewSignature(recv *TCVar, params *Tuple, results *Tuple) *Signature {
14935 return &Signature{recv, params, results}
14936 }
14937 func (s *Signature) Params() *Tuple { return s.params }
14938 func (s *Signature) Results() *Tuple { return s.results }
14939 func (s *Signature) Underlying() Type { return s }
14940 func (s *Signature) String() string { return "func" }
14941
14942 type TCVar struct {
14943 name string
14944 typ Type
14945 }
14946 func (v *TCVar) Name() string { return v.name }
14947 func (v *TCVar) Type() Type { return v.typ }
14948
14949 type Tuple struct {
14950 vars []*TCVar
14951 }
14952 func NewTuple(vars ...*TCVar) *Tuple {
14953 if len(vars) == 0 { return nil }
14954 return &Tuple{vars}
14955 }
14956 func (t *Tuple) Len() int { return len(t.vars) }
14957 func (t *Tuple) At(i int) *TCVar { return t.vars[i] }
14958
14959 func (prog *SSAProgram) ImportedPackage(path string) *SSAPackage {
14960 return prog.imported[path]
14961 }
14962
14963 func main() {
14964 op := OpAdd
14965 _ = op.String()
14966 _ = ssaConstString(nil)
14967 }
14968 `, func(ir string) {
14969 funcCount := strings.Count(ir, "\ndefine ")
14970 assert("321: many functions from ssa_types", funcCount >= 15)
14971 assert("321: has SSAOp.String", strings.Contains(ir, "@main.SSAOp.String"))
14972 assert("321: has ssaConstString", strings.Contains(ir, "@main.ssaConstString"))
14973 assert("321: has NewScope", strings.Contains(ir, "@main.NewScope"))
14974 llvmVerify("321: ssa_types subset", ir)
14975 })
14976
14977 // Test 322: concat all compile/ .mx files and compile
14978 fmt.Fprintf(os.Stderr, ">>> Starting test 322 (full concat)\n")
14979 clearImports()
14980 regPkg("go/token", "token")
14981 regConst("go/token", "ILLEGAL", "int", 0)
14982 regConst("go/token", "EOF", "int", 1)
14983 regConst("go/token", "COMMENT", "int", 2)
14984 regConst("go/token", "IDENT", "int", 4)
14985 regConst("go/token", "INT", "int", 5)
14986 regConst("go/token", "FLOAT", "int", 6)
14987 regConst("go/token", "IMAG", "int", 7)
14988 regConst("go/token", "CHAR", "int", 8)
14989 regConst("go/token", "STRING", "int", 9)
14990 regConst("go/token", "ADD", "int", 12)
14991 regConst("go/token", "SUB", "int", 13)
14992 regConst("go/token", "MUL", "int", 14)
14993 regConst("go/token", "QUO", "int", 15)
14994 regConst("go/token", "REM", "int", 16)
14995 regConst("go/token", "AND", "int", 17)
14996 regConst("go/token", "OR", "int", 18)
14997 regConst("go/token", "XOR", "int", 19)
14998 regConst("go/token", "SHL", "int", 20)
14999 regConst("go/token", "SHR", "int", 21)
15000 regConst("go/token", "AND_NOT", "int", 22)
15001 regConst("go/token", "LAND", "int", 34)
15002 regConst("go/token", "LOR", "int", 35)
15003 regConst("go/token", "ARROW", "int", 36)
15004 regConst("go/token", "INC", "int", 37)
15005 regConst("go/token", "DEC", "int", 38)
15006 regConst("go/token", "EQL", "int", 39)
15007 regConst("go/token", "LSS", "int", 40)
15008 regConst("go/token", "GTR", "int", 41)
15009 regConst("go/token", "ASSIGN", "int", 42)
15010 regConst("go/token", "NOT", "int", 43)
15011 regConst("go/token", "NEQ", "int", 44)
15012 regConst("go/token", "LEQ", "int", 45)
15013 regConst("go/token", "GEQ", "int", 46)
15014 regConst("go/token", "DEFINE", "int", 47)
15015 regConst("go/token", "ELLIPSIS", "int", 48)
15016 regConst("go/token", "DEFAULT", "int", 62)
15017 regType("go/token", "Token", "int")
15018 regPkg("go/constant", "constant")
15019 regConst("go/constant", "Unknown", "int", 0)
15020 regConst("go/constant", "Bool", "int", 1)
15021 regConst("go/constant", "String", "int", 2)
15022 regConst("go/constant", "Int", "int", 3)
15023 regConst("go/constant", "Float", "int", 4)
15024 regConst("go/constant", "Complex", "int", 5)
15025 regIface("go/constant", "Value", "Kind=->int;String=->string;ExactString=->string")
15026 regFn("go/constant", "MakeInt64", "int64->interface{}")
15027 regFn("go/constant", "MakeFloat64", "float64->interface{}")
15028 regFn("go/constant", "MakeString", "string->interface{}")
15029 regFn("go/constant", "MakeFromLiteral", "string,int,int->interface{}")
15030 regFn("go/constant", "BinaryOp", "interface{},int,interface{}->interface{}")
15031 regFn("go/constant", "UnaryOp", "int,interface{},int->interface{}")
15032 regFn("go/constant", "Compare", "interface{},int,interface{}->bool")
15033 regFn("go/constant", "StringVal", "interface{}->string")
15034 regFn("go/constant", "Int64Val", "interface{}->int64,bool")
15035 regFn("go/constant", "Uint64Val", "interface{}->uint64,bool")
15036 regFn("go/constant", "Float64Val", "interface{}->float64,bool")
15037 regFn("go/constant", "BitLen", "interface{}->int")
15038 regFn("go/constant", "Sign", "interface{}->int")
15039 regFn("go/constant", "Shift", "interface{},int,uint->interface{}")
15040 regFn("go/constant", "MakeBool", "bool->interface{}")
15041 regFn("go/constant", "ToInt", "interface{}->interface{}")
15042 regFn("go/constant", "ToFloat", "interface{}->interface{}")
15043 regFn("go/constant", "Num", "interface{}->interface{}")
15044 regFn("go/constant", "Denom", "interface{}->interface{}")
15045 regFn("go/constant", "Real", "interface{}->interface{}")
15046 regFn("go/constant", "Imag", "interface{}->interface{}")
15047 regPkg("fmt", "fmt")
15048 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
15049 regFn("fmt", "Fprintf", "interface{},string,interface{},interface{}->int,error")
15050 regPkg("os", "os")
15051 regVar("os", "Stderr", "interface{}")
15052 regPkg("strconv", "strconv")
15053 regFn("strconv", "Itoa", "int->string")
15054 regFn("strconv", "FormatInt", "int64,int->string")
15055 regFn("strconv", "FormatFloat", "float64,byte,int,int->string")
15056 regPkg("bytes", "bytes")
15057 regFn("bytes", "NewReader", "*byte->interface{}")
15058 regFn("bytes", "IndexByte", "[]byte,byte->int")
15059 regFn("bytes", "HasPrefix", "[]byte,[]byte->bool")
15060 regFn("bytes", "TrimSpace", "[]byte->[]byte")
15061 regPkg("io", "io")
15062 regIface("io", "Reader", "Read=[]byte->int,error")
15063 regVar("io", "EOF", "error")
15064 regVar("io", "ErrNoProgress", "error")
15065 regPkg("runtime", "runtime")
15066 regFn("runtime", "InitCShared", "")
15067 regPkg("unsafe", "unsafe")
15068 regPkg("unicode", "unicode")
15069 regType("unicode", "Tables", "")
15070 regMethod("unicode", "Tables", "IsLetter", "int32->bool", true)
15071 regMethod("unicode", "Tables", "IsDigit", "int32->bool", true)
15072 regFn("unicode", "NewTables", "->ptr")
15073 regFn("unicode", "IsLetter", "int32->bool")
15074 regFn("unicode", "IsDigit", "int32->bool")
15075 regFn("unicode", "IsSpace", "int32->bool")
15076 regVar("unicode", "MaxRune", "int32")
15077 regPkg("unicode/utf8", "utf8")
15078 regFn("unicode/utf8", "DecodeRune", "[]byte->int32,int")
15079 regFn("unicode/utf8", "RuneLen", "int32->int")
15080 regVar("unicode/utf8", "RuneSelf", "int")
15081 regVar("unicode/utf8", "UTFMax", "int")
15082 regVar("unicode/utf8", "RuneError", "int32")
15083 regFn("unicode/utf8", "FullRune", "[]byte->bool")
15084 {
15085 compileDir := filepath.Join(filepath.Dir(soPath), "compile")
15086 mxFiles := []string{
15087 "pos.mx", "source.mx", "tokens.mx", "nodes.mx", "syntax.mx",
15088 "scanner.mx", "parser.mx",
15089 "tc_scope.mx", "tc_package.mx", "tc_info.mx", "tc_object.mx",
15090 "tc_types.mx", "tc_universe.mx", "tc_const.mx", "tc_resolve.mx",
15091 "tc_checker.mx", "tc_decl.mx", "tc_expr.mx", "tc_stmt.mx", "tc_assign.mx",
15092 "ssa_types.mx", "ssa_builder.mx", "ir_emit.mx",
15093 }
15094 // Incremental concat test - add one file at a time via subprocess
15095 for i := 1; i <= len(mxFiles); i++ {
15096 subset := mxFiles[:i]
15097 combined, fc, tl := concatMxSources(compileDir, subset)
15098 combined = append(combined, []byte("\nfunc main() {}\n")...)
15099 tmpFile := filepath.Join(os.TempDir(), "mxconcat_incr.mx")
15100 os.WriteFile(tmpFile, combined, 0644)
15101 cmd := exec.Command(os.Args[0], soPath, "--compile-file", tmpFile)
15102 cmd.Env = os.Environ()
15103 out, err := cmd.CombinedOutput()
15104 os.Remove(tmpFile)
15105 outStr := strings.TrimSpace(string(out))
15106 if err != nil {
15107 short := outStr
15108 if len(short) > 100 { short = short[:100] }
15109 fmt.Fprintf(os.Stderr, ">>> FAIL +%s: %d files, %d lines: %s\n", mxFiles[i-1], fc, tl, short)
15110 } else {
15111 fmt.Fprintf(os.Stderr, ">>> OK +%s: %d files, %d lines -> %s\n", mxFiles[i-1], fc, tl, outStr)
15112 }
15113 }
15114 assert("322: incremental concat tested", true)
15115 }
15116 clearImports()
15117
15118 // Test 323: compile real pos.mx from disk
15119 fmt.Fprintf(os.Stderr, ">>> Starting test 323\n")
15120 clearImports()
15121 regPkg("fmt", "fmt")
15122 regFn("fmt", "Sprintf", "string,interface{},interface{},interface{}->string")
15123 {
15124 posPath := filepath.Join(filepath.Dir(soPath), "syntax", "pos.mx")
15125 posSrc, err := os.ReadFile(posPath)
15126 if err != nil {
15127 fmt.Fprintf(os.Stderr, "SKIP test 323: %v\n", err)
15128 } else {
15129 // pos.mx needs Linebase/Colbase from source.mx
15130 extra := []byte("const Linebase = 1\nconst Colbase = 1\n")
15131 src := append(posSrc, extra...)
15132 pkg := []byte("main")
15133 h := compileToIR(
15134 uintptr(unsafe.Pointer(&src[0])), int32(len(src)),
15135 uintptr(unsafe.Pointer(&pkg[0])), int32(len(pkg)),
15136 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
15137 )
15138 ir := getIR(h)
15139 if ir == "" {
15140 assert("323: pos.mx produces IR", false)
15141 } else {
15142 funcCount := strings.Count(ir, "\ndefine ")
15143 fmt.Printf("=== pos.mx (real file) ===\n")
15144 fmt.Printf("Source: %d lines | IR: %d bytes, %d functions\n",
15145 strings.Count(string(posSrc), "\n"), len(ir), funcCount)
15146 assert("323: produces IR", len(ir) > 5000)
15147 assert("323: many functions", funcCount >= 15)
15148 llvmVerify("323: real pos.mx", ir)
15149 }
15150 irFree(h)
15151 }
15152 }
15153 clearImports()
15154
15155 // Test 212: Scale test
15156 src212 := []byte(`package main
15157
15158 type Type interface {
15159 Underlying() Type
15160 String() string
15161 }
15162
15163 type Basic struct {
15164 kind int32
15165 name string
15166 }
15167 func (b *Basic) Underlying() Type { return b }
15168 func (b *Basic) String() string { return b.name }
15169
15170 type Slice struct{ elem Type }
15171 func (s *Slice) Underlying() Type { return s }
15172 func (s *Slice) String() string { return "[]" | s.elem.String() }
15173 func NewSlice(elem Type) *Slice { return &Slice{elem: elem} }
15174
15175 type Pointer struct{ base Type }
15176 func (p *Pointer) Underlying() Type { return p }
15177 func (p *Pointer) String() string { return "*" | p.base.String() }
15178 func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
15179
15180 type Named struct {
15181 name string
15182 underlying Type
15183 methods []*Func211
15184 }
15185 func (n *Named) Underlying() Type { return n.underlying }
15186 func (n *Named) String() string { return n.name }
15187 func (n *Named) AddMethod(m *Func211) { n.methods = append(n.methods, m) }
15188
15189 type Var211 struct {
15190 name string
15191 typ Type
15192 }
15193 func NewVar211(name string, typ Type) *Var211 { return &Var211{name: name, typ: typ} }
15194 func (v *Var211) Name() string { return v.name }
15195 func (v *Var211) Type() Type { return v.typ }
15196
15197 type Tuple struct{ vars []*Var211 }
15198 func NewTuple(vars ...*Var211) *Tuple {
15199 if len(vars) == 0 { return nil }
15200 return &Tuple{vars: vars}
15201 }
15202 func (t *Tuple) Len() int32 { return int32(len(t.vars)) }
15203 func (t *Tuple) At(i int32) *Var211 { return t.vars[i] }
15204
15205 type Signature struct {
15206 recv *Var211
15207 params *Tuple
15208 results *Tuple
15209 }
15210 func NewSignature(recv *Var211, params *Tuple, results *Tuple) *Signature {
15211 return &Signature{recv: recv, params: params, results: results}
15212 }
15213 func (s *Signature) Underlying() Type { return s }
15214 func (s *Signature) String() string { return "func" }
15215 func (s *Signature) Params() *Tuple { return s.params }
15216 func (s *Signature) Results() *Tuple { return s.results }
15217
15218 type Func211 struct {
15219 name string
15220 typ Type
15221 }
15222
15223 func main() {
15224 intT := &Basic{kind: 2, name: "int"}
15225 strT := &Basic{kind: 14, name: "string"}
15226
15227 sliceInt := NewSlice(intT)
15228 ptrStr := NewPointer(strT)
15229
15230 named := &Named{name: "MyType", underlying: sliceInt}
15231 sig := NewSignature(
15232 NewVar211("s", named),
15233 NewTuple(NewVar211("i", intT)),
15234 NewTuple(NewVar211("", intT)),
15235 )
15236 named.AddMethod(&Func211{name: "Get", typ: sig})
15237
15238 s1 := sliceInt.String()
15239 s2 := ptrStr.String()
15240 s3 := named.String()
15241 _ = s1
15242 _ = s2
15243 _ = s3
15244 _ = sig.Params().Len()
15245 }
15246 `)
15247 name212 := []byte("main")
15248 h212 := compileToIR(
15249 uintptr(unsafe.Pointer(&src212[0])), int32(len(src212)),
15250 uintptr(unsafe.Pointer(&name212[0])), int32(len(name212)),
15251 uintptr(unsafe.Pointer(&triple[0])), int32(len(triple)),
15252 )
15253 ir212 := getIR(h212)
15254 if ir212 == "" {
15255 assert("212: scale test produces IR", false)
15256 } else {
15257 voidCount := strings.Count(ir212, "void %")
15258 funcCount := strings.Count(ir212, "\ndefine ")
15259 lineCount := strings.Count(string(src212), "\n")
15260 fmt.Printf("=== Scale test (211) ===\n")
15261 fmt.Printf("Source: %d lines, %d bytes | IR: %d bytes, %d functions, void fields: %d\n",
15262 lineCount, len(src212), len(ir212), funcCount, voidCount)
15263 assert("212: produces IR", len(ir212) > 1000)
15264 assert("212: zero void fields", voidCount == 0)
15265 assert("212: has NewSignature", strings.Contains(ir212, "@main.NewSignature"))
15266 llvmVerify("212: scale test", ir212)
15267 }
15268 irFree(h212)
15269
15270 fmt.Printf("\n%d/%d tests passed\n", pass, pass+fail)
15271 if fail > 0 {
15272 os.Exit(1)
15273 }
15274 }
15275