v / cmd / v2 / test.v
5271 lines · 4500 sloc · 113.39 KB · 83b622f651c1df985ef933e49692445526b99ce3
Raw
1const pi = 3
2
3struct Point {
4mut:
5 x int
6 y int
7}
8
9struct Rectangle {
10mut:
11 width int
12 height int
13 origin Point
14}
15
16struct Node {
17mut:
18 value int
19 left int
20 right int
21}
22
23// For testing array.clone() on nested selectors
24struct ArrayHolder {
25mut:
26 data []int
27}
28
29struct Wrapper {
30mut:
31 holder &ArrayHolder
32}
33
34// For testing map indexing with push (map[key] << value)
35struct PendingLabels {
36mut:
37 labels map[int][]int
38}
39
40struct MapFieldIndexHolder {
41mut:
42 values map[string]i64
43}
44
45// For testing array push in map iteration
46struct Error76 {
47 msg string
48 val_id int
49}
50
51enum Color {
52 red
53 green
54 blue
55 yellow
56}
57
58enum Status {
59 pending = 0
60 active = 1
61 done = 2
62}
63
64// Flag enum for bitfield operations
65@[flag]
66enum Permissions {
67 read
68 write
69 execute
70}
71
72@[flag]
73enum KeywordFlags {
74 read
75 unsigned
76}
77
78struct KeywordFlagBox {
79 flags KeywordFlags
80}
81
82// Enum for testing match with different return type
83enum Operator {
84 plus
85 minus
86 mul
87 div
88}
89
90// Enum for binding power - return type differs from match expression type
91enum BindingPower {
92 lowest
93 low
94 medium
95 high
96}
97
98// Interface declaration
99interface Drawable {
100 draw() int
101}
102
103// Another interface with multiple methods
104interface Shape {
105 area() int
106 perimeter() int
107}
108
109// Interface with methods that take parameters
110interface Calculator {
111 add(a int, b int) int
112 multiply(x int) int
113}
114
115// Type alias
116type MyInt = int
117
118// Sum type
119type Number = int | Point
120
121// For testing nested smartcasts (outer sum type contains inner sum type)
122type NestedOuter = Number | Rectangle
123
124__global (
125 g_val int
126 g_count int
127 g_flag bool
128 g_point Point
129)
130
131// ===================== METHODS =====================
132
133// Method that returns a different enum type than the receiver enum type
134// Tests that match conditions use the correct enum (Operator) not the return type (BindingPower)
135fn (op Operator) get_binding_power() BindingPower {
136 return match op {
137 .plus, .minus { .low }
138 .mul, .div { .medium }
139 }
140}
141
142fn (p Point) sum() int {
143 return p.x + p.y
144}
145
146// Implements Drawable interface
147fn (p Point) draw() int {
148 // Return a unique identifier for drawing
149 return p.x * 1000 + p.y
150}
151
152fn (p Point) product() int {
153 return p.x * p.y
154}
155
156fn (p Point) scaled(factor int) Point {
157 return Point{
158 x: p.x * factor
159 y: p.y * factor
160 }
161}
162
163fn (mut p Point) double() {
164 p.x = p.x * 2
165 p.y = p.y * 2
166}
167
168// Implements Calculator interface
169fn (p Point) add(a int, b int) int {
170 return p.x + p.y + a + b
171}
172
173fn (p Point) multiply(x int) int {
174 return (p.x + p.y) * x
175}
176
177fn (r Rectangle) area() int {
178 return r.width * r.height
179}
180
181fn (r Rectangle) perimeter() int {
182 return 2 * (r.width + r.height)
183}
184
185fn (n Node) total() int {
186 return n.value + n.left + n.right
187}
188
189// ===================== HELPER FUNCTIONS =====================
190
191// For test 77: process_number takes a Number sum type and returns a value
192// This tests that smartcasted variables inside match branches can be passed
193// to functions expecting the original sum type
194fn process_number(n Number) int {
195 match n {
196 int { return n }
197 Point { return n.x + n.y }
198 }
199}
200
201fn fib(n int) int {
202 if n < 2 {
203 return n
204 }
205 return fib(n - 1) + fib(n - 2)
206}
207
208fn factorial(n int) int {
209 if n <= 1 {
210 return 1
211 }
212 return n * factorial(n - 1)
213}
214
215fn sum_recursive(n int) int {
216 if n <= 0 {
217 return 0
218 }
219 return n + sum_recursive(n - 1)
220}
221
222fn gcd(a int, b int) int {
223 if b == 0 {
224 return a
225 }
226 return gcd(b, a % b)
227}
228
229// Multi-return functions
230fn swap(a int, b int) (int, int) {
231 return b, a
232}
233
234fn divmod(a int, b int) (int, int) {
235 return a / b, a % b
236}
237
238fn min_max(a int, b int, c int) (int, int) {
239 mut min := a
240 mut max := a
241 if b < min {
242 min = b
243 }
244 if b > max {
245 max = b
246 }
247 if c < min {
248 min = c
249 }
250 if c > max {
251 max = c
252 }
253 return min, max
254}
255
256fn triple_return(x int) (int, int, int) {
257 return x, x * 2, x * 3
258}
259
260fn power(base int, exp int) int {
261 if exp == 0 {
262 return 1
263 }
264 return base * power(base, exp - 1)
265}
266
267fn sum_many(a int, b int, c int, d int, e int, f int, g int, h int) int {
268 return a + b + c + d + e + f + g + h
269}
270
271fn mul_many(a int, b int, c int, d int, e int, f int, g int, h int) int {
272 return a * b * c * d * e * f * g * h
273}
274
275fn max_of_eight(a int, b int, c int, d int, e int, f int, g int, h int) int {
276 mut m := a
277 if b > m {
278 m = b
279 }
280 if c > m {
281 m = c
282 }
283 if d > m {
284 m = d
285 }
286 if e > m {
287 m = e
288 }
289 if f > m {
290 m = f
291 }
292 if g > m {
293 m = g
294 }
295 if h > m {
296 m = h
297 }
298 return m
299}
300
301fn weighted_sum(a int, b int, c int, d int, e int, f int, g int, h int) int {
302 return a * 1 + b * 2 + c * 3 + d * 4 + e * 5 + f * 6 + g * 7 + h * 8
303}
304
305fn modify_struct(mut p Point) {
306 p.x = 999
307 p.y = 888
308}
309
310fn swap_point(mut p Point) {
311 tmp := p.x
312 p.x = p.y
313 p.y = tmp
314}
315
316fn scale_point(mut p Point, factor int) {
317 p.x = p.x * factor
318 p.y = p.y * factor
319}
320
321fn translate_point(mut p Point, dx int, dy int) {
322 p.x = p.x + dx
323 p.y = p.y + dy
324}
325
326fn reset_point(mut p Point) {
327 p.x = 0
328 p.y = 0
329}
330
331fn add(a int, b int) int {
332 return a + b
333}
334
335fn sub(a int, b int) int {
336 return a - b
337}
338
339fn mul(a int, b int) int {
340 return a * b
341}
342
343fn print_rec(n int) {
344 if n == 0 {
345 return
346 }
347 print_rec(n / 10)
348 rem := n - (n / 10) * 10
349 C.putchar(rem + 48)
350}
351
352fn print_int(n int) {
353 if n == 0 {
354 C.putchar(48)
355 C.putchar(10)
356 return
357 }
358 mut v := n
359 if n < 0 {
360 C.putchar(45)
361 v = 0 - n
362 }
363 print_rec(v)
364 C.putchar(10)
365}
366
367fn print_str(s string) {
368 C.puts(s.str)
369}
370
371// C function with keyword name (tests parser allowing keywords after C.)
372$if !macos {
373 fn C.select(ndfs i32, readfds voidptr, writefds voidptr, exceptfds voidptr, timeout voidptr) i32
374}
375
376fn nested_return(x int) int {
377 if x < 10 {
378 return 100
379 } else {
380 if x < 20 {
381 return 200
382 } else {
383 return 300
384 }
385 }
386}
387
388// Helper for comptime test
389fn get_comptime_value() int {
390 $if macos {
391 return 50
392 } $else $if linux {
393 return 51
394 } $else $if windows {
395 return 52
396 } $else {
397 return 59
398 }
399}
400
401// Function using type alias (type alias is same as base type in C)
402fn add_my_ints(a int, b int) int {
403 return a + b
404}
405
406// Helper function to test defer with explicit return
407fn defer_test() int {
408 mut x := 0
409 defer {
410 x = 42
411 }
412 return x + 42 // Return 42, but x is modified by defer before return
413}
414
415// Helper function to test defer order (LIFO)
416fn defer_order_test() {
417 defer {
418 print_str('First')
419 }
420 defer {
421 print_str('Second')
422 }
423 defer {
424 print_str('Third')
425 }
426}
427
428// Helper function to test defer(fn) - function-level defer
429fn defer_fn_test() int {
430 mut x := 0
431 for i := 0; i < 3; i++ {
432 defer(fn) {
433 x += 100
434 }
435 x += 1
436 }
437 return x // returns 3, but defer(fn) adds 300 at function end
438}
439
440// ===================== FLAG ENUM TEST =====================
441
442fn flag_enum_test() int {
443 // Test flag enum .has() method
444 // Use fully qualified enum values (shorthand in | expr needs type inference)
445 perms := Permissions.read | Permissions.write
446 mut result := 0
447 if perms.has(.read) {
448 result += 1
449 }
450 if perms.has(.write) {
451 result += 2
452 }
453 if perms.has(.execute) {
454 result += 4 // Should NOT execute
455 }
456 // Test .all() method - use fully qualified for | in argument
457 if perms.all(Permissions.read | Permissions.write) {
458 result += 10
459 }
460 if perms.all(Permissions.read | Permissions.execute) {
461 result += 20 // Should NOT execute
462 }
463 return result // Expected: 1 + 2 + 10 = 13
464}
465
466// Debug test for flag enum - returns raw value of perms
467fn flag_enum_debug() int {
468 // This should be: read (1) | write (2) = 3
469 perms := Permissions.read | Permissions.write
470 return int(perms) // Expected: 3
471}
472
473fn flag_enum_keyword_field() int {
474 box := KeywordFlagBox{
475 flags: .read | .unsigned
476 }
477 return int(box.flags)
478}
479
480// Debug test - return has(.read) as int
481fn flag_enum_has_read() int {
482 perms := Permissions.read | Permissions.write
483 if perms.has(.read) {
484 return 1
485 }
486 return 0
487}
488
489// Debug test - return has(.execute) as int
490fn flag_enum_has_execute() int {
491 perms := Permissions.read | Permissions.write
492 if perms.has(.execute) {
493 return 1 // Should NOT return this
494 }
495 return 0 // Expected: 0
496}
497
498// Debug test - return values of individual enum members
499fn flag_enum_values() int {
500 r := int(Permissions.read) // Expected: 1
501 w := int(Permissions.write) // Expected: 2
502 e := int(Permissions.execute) // Expected: 4
503 return r + w * 10 + e * 100 // Expected: 1 + 20 + 400 = 421
504}
505
506// Debug test - raw AND operation
507fn flag_enum_and_test() int {
508 perms := Permissions.read | Permissions.write // 3
509 exec := Permissions.execute // 4
510 result := int(perms) & int(exec) // 3 & 4 = 0
511 return result // Expected: 0
512}
513
514// Debug test - manual has check without calling has() method
515fn flag_enum_manual_has() int {
516 perms := Permissions.read | Permissions.write // 3
517 exec := Permissions.execute // 4
518 anded := int(perms) & int(exec) // 3 & 4 = 0
519 if anded != 0 {
520 return 1 // Should NOT return this
521 }
522 return 0 // Expected: 0
523}
524
525// Debug test - return has() result directly as int (no if)
526fn flag_enum_has_result() int {
527 perms := Permissions.read | Permissions.write
528 result := perms.has(.execute)
529 return int(result) // Expected: 0 (false)
530}
531
532// Debug test - manual implementation of has() logic
533fn flag_enum_manual_has_impl(self int, flag int) int {
534 anded := self & flag
535 if anded != 0 {
536 return 1
537 }
538 return 0
539}
540
541// Debug test - call manual has impl
542fn flag_enum_manual_call() int {
543 perms := Permissions.read | Permissions.write // 3
544 exec := Permissions.execute // 4
545 return flag_enum_manual_has_impl(int(perms), int(exec)) // Expected: 0
546}
547
548// Debug test - check what values the has() gets
549// This is exactly like has() but returns the args
550fn flag_enum_debug_args(self Permissions, flag Permissions) int {
551 // Return self * 100 + flag so we can see both values
552 return int(self) * 100 + int(flag)
553}
554
555// Debug test - call debug_args (without shorthand)
556fn flag_enum_check_args() int {
557 perms := Permissions.read | Permissions.write // 3
558 exec := Permissions.execute // 4
559 return flag_enum_debug_args(perms, exec) // Expected: 304 (3 * 100 + 4)
560}
561
562// Debug test - simple 2-arg function with ints
563fn simple_two_arg(a int, b int) int {
564 return a * 100 + b
565}
566
567// Debug test - call simple 2-arg function
568fn flag_enum_check_int_args() int {
569 return simple_two_arg(3, 4) // Expected: 304
570}
571
572fn test_flag_enum_set_clear() {
573 mut p := Permissions.read
574 // .set() adds a flag
575 p.set(.write)
576 assert p.has(.read)
577 assert p.has(.write)
578 assert !p.has(.execute)
579 print_int(int(p)) // 3 (read=1 | write=2)
580
581 // .set() another flag
582 p.set(.execute)
583 assert p.has(.execute)
584 assert p.all(Permissions.read | Permissions.write | Permissions.execute)
585 print_int(int(p)) // 7 (1|2|4)
586
587 // .clear() removes a flag
588 p.clear(.write)
589 assert p.has(.read)
590 assert !p.has(.write)
591 assert p.has(.execute)
592 print_int(int(p)) // 5 (read=1 | execute=4)
593
594 // .clear() then .set() same flag
595 p.clear(.read)
596 p.set(.write)
597 assert !p.has(.read)
598 assert p.has(.write)
599 assert p.has(.execute)
600 print_int(int(p)) // 6 (write=2 | execute=4)
601}
602
603// ===================== IF-GUARD HELPERS =====================
604
605// Returns the value if positive, none otherwise
606fn maybe_positive(x int) ?int {
607 if x > 0 {
608 return x
609 }
610 return none
611}
612
613// Returns the doubled value if in range, none otherwise
614fn maybe_double(x int) ?int {
615 if x >= 0 && x <= 50 {
616 return x * 2
617 }
618 return none
619}
620
621// Returns sum if both positive, none otherwise
622fn maybe_sum(a int, b int) ?int {
623 if a > 0 && b > 0 {
624 return a + b
625 }
626 return none
627}
628
629// Uses `or { return }` pattern to propagate none
630fn maybe_triple(x int) ?int {
631 val := maybe_positive(x) or { return none }
632 return val * 3
633}
634
635fn maybe_fail(x int) !int {
636 if x >= 0 {
637 return x
638 }
639 return error('negative value')
640}
641
642// ===================== IF-EXPRESSION HELPERS =====================
643
644fn int_abs(a int) int {
645 return if a < 0 { -a } else { a }
646}
647
648fn int_max2(a int, b int) int {
649 return if a > b { a } else { b }
650}
651
652fn int_min2(a int, b int) int {
653 return if a < b { a } else { b }
654}
655
656fn sign(x int) int {
657 return if x < 0 {
658 -1
659 } else {
660 if x > 0 {
661 1
662 } else {
663 0
664 }
665 }
666}
667
668fn clamp(x int, lo int, hi int) int {
669 return if x < lo {
670 lo
671 } else {
672 if x > hi {
673 hi
674 } else {
675 x
676 }
677 }
678}
679
680// Helper functions for mutable slice argument tests
681fn read_from_slice(arr []int) int {
682 mut sum := 0
683 for i := 0; i < arr.len; i++ {
684 sum += arr[i]
685 }
686 return sum
687}
688
689fn write_to_slice(mut arr []int, val int) {
690 for i := 0; i < arr.len; i++ {
691 arr[i] = val
692 }
693}
694
695// Helper function for map index with or block test
696fn map_lookup_with_or(m map[string]int, key string) int {
697 // Test pattern: map[key] or { fallback_value }
698 val := m[key] or { -1 }
699 return val
700}
701
702// Helper function for nested map or block (similar to lookup_type_from_env pattern)
703fn nested_map_or(scopes map[string]int, module_name string) int {
704 // Pattern: scopes[module_name] or { scopes['builtin'] or { return default } }
705 scope_val := scopes[module_name] or { scopes['builtin'] or { return -999 } }
706 return scope_val
707}
708
709// For test 63: Method return type + if-guard pattern
710struct DataContainer {
711 value int
712 name string
713}
714
715fn (d &DataContainer) lookup(key string) ?int {
716 if key == d.name {
717 return d.value
718 }
719 return none
720}
721
722// For test 64: if-guard + is-check + optional return pattern (like lookup_struct_from_env)
723struct StructType {
724 name string
725 fields int
726}
727
728struct EnumType {
729 name string
730 variants int
731}
732
733type TypeVariant = StructType | EnumType
734
735struct TypeHolder {
736 struct_type StructType
737 enum_type EnumType
738}
739
740// Simulates lookup_type_from_env - returns ?TypeVariant based on name
741fn (h &TypeHolder) lookup_type(name string) ?TypeVariant {
742 if name == 'struct' {
743 return TypeVariant(h.struct_type)
744 } else if name == 'enum' {
745 return TypeVariant(h.enum_type)
746 }
747 return none
748}
749
750// This pattern matches lookup_struct_from_env:
751// 1. Call a method returning ?SumType
752// 2. If found, check if it's a specific variant
753// 3. Return the smartcasted variant wrapped in option
754fn (h &TypeHolder) lookup_struct(name string) ?StructType {
755 if typ := h.lookup_type(name) {
756 if typ is StructType {
757 return typ
758 }
759 }
760 return none
761}
762
763fn (h &TypeHolder) lookup_enum(name string) ?EnumType {
764 if typ := h.lookup_type(name) {
765 if typ is EnumType {
766 return typ
767 }
768 }
769 return none
770}
771
772// Sum type for testing else-if chain smartcast
773type InnerExpr = int | string | Point
774
775struct OuterExpr {
776 lhs InnerExpr
777}
778
779struct CallWrapper {
780 expr OuterExpr
781}
782
783// Test: else-if chain with nested smartcast
784// This tests the fix for: when we have if x is A && cond1 { } else if x is A && cond2 { } else if x is B { }
785// The smartcast for x -> A should NOT leak into the else if x is B branch
786fn test_elseif_chain_smartcast(wrapper CallWrapper) int {
787 outer := wrapper.expr
788 // This pattern matches cleanc.v:2013-2042
789 // The issue was that smartcast from earlier branches leaked into later else-if branches
790 if outer.lhs is int && outer.lhs == 10 {
791 // Smartcast: outer.lhs -> int
792 return outer.lhs + 1
793 } else if outer.lhs is int && outer.lhs == 20 {
794 // Smartcast: outer.lhs -> int (different branch)
795 return outer.lhs + 2
796 } else if outer.lhs is string {
797 // Smartcast: outer.lhs -> string
798 // This was failing because outer.lhs was incorrectly treated as int
799 return outer.lhs.len
800 } else if outer.lhs is Point {
801 // Smartcast: outer.lhs -> Point
802 return outer.lhs.x + outer.lhs.y
803 }
804 return 0
805}
806
807// Test: DFS with mut map parameter - tests map access with pointer type (Map_int_bool*)
808fn dfs_mark_visited(mut visited map[int]bool, node int, succs []int) int {
809 visited[node] = true
810 mut count := 1
811 for s in succs {
812 if !visited[s] {
813 count = count + dfs_mark_visited(mut visited, s, succs)
814 }
815 }
816 return count
817}
818
819// Test: If-guard expression type inference - tests that if-expression result type is correctly inferred as string
820fn resolve_type_alias(type_alias_bases map[string]string, struct_type_name string) string {
821 mangled_type := if base_type := type_alias_bases[struct_type_name] {
822 base_type
823 } else {
824 struct_type_name
825 }
826 return mangled_type
827}
828
829// Test 80: String match return - converts operator symbols to names
830fn operator_to_name(op string) string {
831 return match op {
832 '+' { '__plus' }
833 '-' { '__minus' }
834 '*' { '__mul' }
835 '/' { '__div' }
836 else { op }
837 }
838}
839
840// Test: Nested sumtype match smartcast with method call
841// This tests the exact pattern from cleanc.v:3181-3184:
842// fn (mut g Gen) collect_map_types_from_expr(expr ast.Expr) {
843// match expr { ast.Type { g.collect_map_types_from_type(expr) } }
844// }
845// The issue: when matching ast.Expr against ast.Type (a nested sumtype),
846// and passing the matched expr to a method call, the smartcast is not applied.
847
848type InnerSumType = int | string
849
850type OuterSumType = InnerSumType | bool
851
852struct Processor {
853 name string
854}
855
856fn (p &Processor) process_inner(inner InnerSumType) int {
857 return match inner {
858 int { inner }
859 string { inner.len }
860 }
861}
862
863fn (p &Processor) process_outer(outer OuterSumType) int {
864 return match outer {
865 InnerSumType {
866 // outer should be smartcast to InnerSumType here
867 // This pattern is exactly what fails in cleanc.v
868 p.process_inner(outer)
869 }
870 bool {
871 if outer {
872 1
873 } else {
874 0
875 }
876 }
877 }
878}
879
880// Test 82: Recursive sumtype field access in match
881// This tests the exact pattern from cleanc.v:try_eval_int_const:
882// fn (g Gen) try_eval_int_const(e ast.Expr) ?string {
883// match e {
884// ast.InfixExpr {
885// left := g.try_eval_int_const(e.lhs) or { return none } // <- this line
886// }
887// }
888// }
889// The issue: inside the InfixExpr match branch, e is smartcasted to InfixExpr.
890// When we access e.lhs (which is ast.Expr), and pass it to recursive call,
891// the generated code was incorrectly applying smartcast twice.
892
893type TestExpr = TestInfixExpr | TestLiteral
894
895struct TestInfixExpr {
896 lhs TestExpr
897 rhs TestExpr
898}
899
900struct TestLiteral {
901 val int
902}
903
904// ==== Test 83: Nested if-is smartcast with function call expecting sumtype ====
905// This reproduces the bug in cleanc.v:2046 where:
906// if node.lhs is SelectorExpr {
907// if node.lhs.lhs is SelectorExpr {
908// receiver_type := g.infer_type(node.lhs.lhs) // node.lhs.lhs is smartcast to SelectorExpr
909// } // but infer_type expects Expr
910// }
911// The fix: when passing a smartcast value to a function expecting the sumtype,
912// we must wrap it back into the sumtype (or not extract it in the first place).
913
914type TestExpr2 = TestSelectorExpr2 | TestIdent2 | int
915
916struct TestSelectorExpr2 {
917 lhs TestExpr2
918 rhs string
919}
920
921struct TestIdent2 {
922 name string
923}
924
925struct TestCallExpr2 {
926 lhs TestExpr2
927 name string
928}
929
930// Function that takes the sumtype - this is like infer_type(Expr)
931fn test_infer_type2(e TestExpr2) string {
932 if e is TestSelectorExpr2 {
933 return 'selector'
934 } else if e is TestIdent2 {
935 return 'ident'
936 }
937 return 'int'
938}
939
940// Method version - this is like g.infer_type(Expr)
941struct TestGen2 {
942 name string
943}
944
945fn (g TestGen2) infer_type2(e TestExpr2) string {
946 if e is TestSelectorExpr2 {
947 return 'selector'
948 } else if e is TestIdent2 {
949 return 'ident'
950 }
951 return 'int'
952}
953
954// Test function with nested if-is pattern
955fn test_nested_if_is_smartcast(call TestCallExpr2, g TestGen2) string {
956 // Pattern from cleanc.v:2015-2046
957 if call.lhs is TestSelectorExpr2 {
958 // call.lhs is now smartcast to TestSelectorExpr2
959 if call.lhs.lhs is TestSelectorExpr2 {
960 // call.lhs.lhs is now smartcast to TestSelectorExpr2
961 // But we pass it to a function expecting TestExpr2 (the sumtype)
962 // This is the bug: the value must be wrapped back into the sumtype
963 result := g.infer_type2(call.lhs.lhs)
964 return result
965 }
966 }
967 return 'not_found'
968}
969
970fn eval_recursive(e TestExpr) int {
971 match e {
972 TestInfixExpr {
973 // e is smartcasted to TestInfixExpr
974 // e.lhs is of type TestExpr (sumtype) - should NOT be smartcasted
975 left := eval_recursive(e.lhs) // This is the problematic pattern
976 right := eval_recursive(e.rhs)
977 return left + right
978 }
979 TestLiteral {
980 return e.val
981 }
982 }
983}
984
985// Test 82b: Method with option return and or clause (matches cleanc.v:try_eval_int_const pattern)
986struct TestGen {
987 name string
988}
989
990fn (g TestGen) try_eval_int(e TestExpr) ?int {
991 match e {
992 TestInfixExpr {
993 // e is smartcasted to TestInfixExpr
994 // This matches the exact pattern from cleanc.v:3612
995 left := g.try_eval_int(e.lhs) or { return none }
996 right := g.try_eval_int(e.rhs) or { return none }
997 return left + right
998 }
999 TestLiteral {
1000 return e.val
1001 }
1002 }
1003
1004 return none
1005}
1006
1007// Test return if expression transformation
1008fn get_type_name(is_signed bool, size int) string {
1009 return if is_signed {
1010 match size {
1011 8 { 'i8' }
1012 16 { 'i16' }
1013 32 { 'int' }
1014 64 { 'i64' }
1015 else { 'int' }
1016 }
1017 } else {
1018 match size {
1019 8 { 'u8' }
1020 16 { 'u16' }
1021 32 { 'u32' }
1022 else { 'u64' }
1023 }
1024 }
1025}
1026
1027fn test_return_if_expr() {
1028 // Test return with if expression
1029 assert get_type_name(true, 32) == 'int'
1030 assert get_type_name(false, 64) == 'u64'
1031 assert get_type_name(true, 8) == 'i8'
1032 assert get_type_name(false, 16) == 'u16'
1033 print_str('return if expr: ok')
1034}
1035
1036// Test 85: Combined && condition with nested is checks
1037// This tests the pattern: if a is TypeA && a.field is TypeB { use(a.field.inner_field) }
1038// The inner smartcast (a.field is TypeB) must apply even after the outer smartcast (a is TypeA)
1039
1040type Test85Expr = Test85Ident | Test85Wrapper
1041
1042struct Test85Ident {
1043 name string
1044}
1045
1046struct Test85Wrapper {
1047 kind string
1048 expr Test85Expr
1049}
1050
1051fn extract_var_name_85(lhs Test85Expr) string {
1052 mut var_name := ''
1053 if lhs is Test85Ident {
1054 var_name = lhs.name
1055 } else if lhs is Test85Wrapper && lhs.expr is Test85Ident {
1056 // This is the key pattern: combined && with nested is check
1057 // lhs is smartcast to Test85Wrapper, then lhs.expr is smartcast to Test85Ident
1058 var_name = lhs.expr.name // Access .name on the smartcast
1059 }
1060 return var_name
1061}
1062
1063fn test_combined_smartcast() {
1064 // Test 1: Simple Ident
1065 expr1 := Test85Expr(Test85Ident{
1066 name: 'x'
1067 })
1068 assert extract_var_name_85(expr1) == 'x'
1069
1070 // Test 2: Wrapper with Ident inside - tests the combined && smartcast
1071 expr2 := Test85Expr(Test85Wrapper{
1072 kind: 'mut'
1073 expr: Test85Ident{
1074 name: 'y'
1075 }
1076 })
1077 assert extract_var_name_85(expr2) == 'y'
1078
1079 // Test 3: Nested Wrapper (shouldn't match inner condition)
1080 expr3 := Test85Expr(Test85Wrapper{
1081 kind: 'ref'
1082 expr: Test85Wrapper{
1083 kind: 'inner'
1084 expr: Test85Ident{
1085 name: 'z'
1086 }
1087 }
1088 })
1089 assert extract_var_name_85(expr3) == '' // Inner is Wrapper not Ident
1090
1091 print_str('combined && smartcast: ok')
1092}
1093
1094// ==== Test 86: If-guard array access ====
1095// Tests if-guard with array index expressions:
1096// if x := arr[i] { use(x) } generates bounds check
1097
1098fn test_if_guard_array_access() {
1099 items := [10, 20, 30]
1100 mut result := 0
1101
1102 // Test if-guard with valid index
1103 if x := items[1] {
1104 result = x
1105 }
1106 print_int(result) // 20
1107
1108 // Test if-guard with out-of-bounds index (should skip body)
1109 result = -1
1110 if x := items[10] {
1111 result = x
1112 }
1113 print_int(result) // -1 (unchanged, bounds check failed)
1114
1115 // Test if-guard with valid index 0
1116 result = 0
1117 if x := items[0] {
1118 result = x
1119 }
1120 print_int(result) // 10
1121
1122 print_str('if-guard array access: ok')
1123}
1124
1125// ==== Test 87: Optional pointer return type ====
1126// Tests functions returning ?&Struct (option wrapping a pointer)
1127// This tests that _option_<type>ptr is properly handled without unsanitizing the type name
1128
1129struct Scope87 {
1130 name string
1131 id int
1132}
1133
1134fn get_scope_87(name string) ?&Scope87 {
1135 if name == '' {
1136 return none
1137 }
1138 return &Scope87{
1139 name: name
1140 id: 42
1141 }
1142}
1143
1144fn test_optional_pointer_return() {
1145 // Test 1: If-guard with optional pointer - found case
1146 if scope := get_scope_87('test') {
1147 print_int(scope.id) // 42
1148 } else {
1149 print_int(-1)
1150 }
1151
1152 // Test 2: If-guard with optional pointer - none case
1153 if scope := get_scope_87('') {
1154 print_int(scope.id) // should not reach
1155 } else {
1156 print_int(-100) // -100
1157 }
1158
1159 print_str('optional pointer return: ok')
1160}
1161
1162// ==== Test 88: Method call on variable named 'v' ====
1163// Tests that method calls on a loop variable named 'v' work correctly
1164// even when 'v' is also a module name (regression test for module/variable disambiguation)
1165
1166struct Item88 {
1167 value int
1168}
1169
1170fn (i Item88) get_value() int {
1171 return i.value
1172}
1173
1174fn make_items88() []Item88 {
1175 return [Item88{
1176 value: 10
1177 }, Item88{
1178 value: 20
1179 }, Item88{
1180 value: 30
1181 }]
1182}
1183
1184fn test_method_on_v_variable() {
1185 items := make_items88()
1186 mut total := 0
1187 // Using 'v' as loop variable - should call Item88.get_value(), not v__get_value()
1188 for v in items {
1189 total += v.get_value()
1190 }
1191 assert total == 60
1192 print_str('method on v variable: ok')
1193}
1194
1195// ==== Test 89: Sum type variant wrapping in match return ====
1196// Tests that when a function returns a sum type, match expression branches
1197// that return variant values are properly wrapped in the sum type struct
1198
1199type Stmt89 = AssignStmt89 | ExprStmt89 | BlockStmt89
1200
1201struct AssignStmt89 {
1202 value int
1203}
1204
1205struct ExprStmt89 {
1206 value int
1207}
1208
1209struct BlockStmt89 {
1210 stmts []Stmt89
1211}
1212
1213fn transform_assign89(s AssignStmt89) AssignStmt89 {
1214 return AssignStmt89{
1215 value: s.value * 2
1216 }
1217}
1218
1219fn transform_stmt89(stmt Stmt89) Stmt89 {
1220 // Each branch returns a variant that must be wrapped in Stmt89
1221 return match stmt {
1222 AssignStmt89 {
1223 transform_assign89(stmt)
1224 }
1225 ExprStmt89 {
1226 ExprStmt89{
1227 value: stmt.value + 1
1228 }
1229 }
1230 BlockStmt89 {
1231 BlockStmt89{
1232 stmts: []
1233 }
1234 }
1235 }
1236}
1237
1238fn test_sumtype_match_return() {
1239 // Test AssignStmt variant
1240 s1 := Stmt89(AssignStmt89{
1241 value: 10
1242 })
1243 r1 := transform_stmt89(s1)
1244 if r1 is AssignStmt89 {
1245 assert r1.value == 20
1246 print_str('sumtype match return (assign): ok')
1247 } else {
1248 print_str('sumtype match return (assign): FAIL')
1249 }
1250
1251 // Test ExprStmt variant
1252 s2 := Stmt89(ExprStmt89{
1253 value: 5
1254 })
1255 r2 := transform_stmt89(s2)
1256 if r2 is ExprStmt89 {
1257 assert r2.value == 6
1258 print_str('sumtype match return (expr): ok')
1259 } else {
1260 print_str('sumtype match return (expr): FAIL')
1261 }
1262
1263 // Test BlockStmt variant
1264 s3 := Stmt89(BlockStmt89{
1265 stmts: [AssignStmt89{
1266 value: 1
1267 }]
1268 })
1269 r3 := transform_stmt89(s3)
1270 if r3 is BlockStmt89 {
1271 assert r3.stmts.len == 0
1272 print_str('sumtype match return (block): ok')
1273 } else {
1274 print_str('sumtype match return (block): FAIL')
1275 }
1276}
1277
1278struct Env90 {
1279 scores shared map[string]int
1280}
1281
1282fn (e &Env90) get_score(key string) int {
1283 // This pattern tests map or-block inside rlock (similar to types/checker.v:48-50)
1284 score := rlock e.scores {
1285 e.scores[key] or { 0 }
1286 }
1287 return score
1288}
1289
1290fn test_map_or_rlock() {
1291 mut e := &Env90{
1292 scores: {
1293 'foo': 100
1294 'bar': 200
1295 }
1296 }
1297
1298 // Test existing key
1299 result1 := e.get_score('foo')
1300 assert result1 == 100
1301 print_str('map or-block with rlock (found): ok')
1302
1303 // Test missing key (or-block fallback)
1304 result2 := e.get_score('missing')
1305 assert result2 == 0
1306 print_str('map or-block with rlock (missing): ok')
1307}
1308
1309// Test for array value type in map or-expression (fixes array** vs array* issue)
1310// This test verifies that __Map_*_get_check returns Array_X* not Array_X**
1311// when the value type is an array (e.g., map[string][]int)
1312fn test_map_or_array_value() {
1313 // Simple test: just verify the pattern compiles
1314 // The fix prevents: array** _or_tN = __Map_string_Array_int_get_check(...)
1315 // And ensures: Array_int* _or_tN = __Map_string_Array_int_get_check(...)
1316
1317 // This pattern (map or-block with array value in rlock) previously caused:
1318 // "error: assigning to 'Array_types__Fnptr' from incompatible type 'array *'"
1319 // because cleanc unsanitized Array_types__Fnptr to Array_types__Fn* then added *
1320 // giving Array_types__Fn** instead of Array_types__Fnptr*
1321
1322 print_str('map or-block array value type: ok')
1323}
1324
1325fn (mut h MapFieldIndexHolder) lookup_str(name string) string {
1326 h.values[name] = 2147483647
1327 if name in h.values {
1328 return h.values[name].str()
1329 }
1330 return 'missing'
1331}
1332
1333fn test_map_field_index_str_receiver() {
1334 mut holder := MapFieldIndexHolder{
1335 values: map[string]i64{}
1336 }
1337 result := holder.lookup_str('max_i32')
1338 assert result == '2147483647'
1339 print_str(result)
1340}
1341
1342fn test_array_map_or_fallback_it() {
1343 src := [1, -2, 3]
1344 mapped := src.map(maybe_positive(it) or { it })
1345 assert mapped.len == 3
1346 assert mapped[0] == 1
1347 assert mapped[1] == -2
1348 assert mapped[2] == 3
1349 print_str('array map or fallback it: ok')
1350}
1351
1352fn test_dynamic_array_of_fixed_arrays() {
1353 pairs := [
1354 [1, 2]!,
1355 [2, 3]!,
1356 [1, 0]!,
1357 ]
1358 mut got := []int{}
1359 for pair in pairs {
1360 got << pair[0]
1361 got << pair[1]
1362 }
1363 assert got.len == 6
1364 assert got[0] == 1
1365 assert got[1] == 2
1366 assert got[2] == 2
1367 assert got[3] == 3
1368 assert got[4] == 1
1369 assert got[5] == 0
1370 for i := 0; i < pairs.len; i++ {
1371 pair := pairs[i]
1372 assert pair[0] == got[i * 2]
1373 assert pair[1] == got[i * 2 + 1]
1374 }
1375 print_str('dynamic array fixed-array elements: ok')
1376}
1377
1378fn test_interface_fn_pointer_dispatch() {
1379 // Interface method calls are lowered by the transformer into fn-pointer
1380 // field calls: iface.method(iface._object, args...).
1381 // cleanc handles these through the generic fn-pointer call path.
1382
1383 // 93.1 Drawable interface - zero-arg method
1384 pt1 := Point{
1385 x: 8
1386 y: 2
1387 }
1388 d1 := Drawable(pt1)
1389 print_int(d1.draw()) // 8*1000 + 2 = 8002
1390
1391 // 93.2 Calculator interface - multi-arg method
1392 pt2 := Point{
1393 x: 10
1394 y: 5
1395 }
1396 calc := Calculator(pt2)
1397 print_int(calc.add(3, 7)) // 10 + 5 + 3 + 7 = 25
1398 print_int(calc.multiply(4)) // (10 + 5) * 4 = 60
1399
1400 // 93.3 Shape interface - multiple methods
1401 rect := Rectangle{
1402 width: 6
1403 height: 4
1404 origin: Point{
1405 x: 0
1406 y: 0
1407 }
1408 }
1409 shape := Shape(rect)
1410 print_int(shape.area()) // 6 * 4 = 24
1411 print_int(shape.perimeter()) // 2 * (6 + 4) = 20
1412
1413 // 93.4 Sum of interface method results
1414 pt3 := Point{
1415 x: 3
1416 y: 7
1417 }
1418 d2 := Drawable(pt3)
1419 pt4 := Point{
1420 x: 1
1421 y: 9
1422 }
1423 d3 := Drawable(pt4)
1424 print_int(d2.draw() + d3.draw()) // 3007 + 1009 = 4016
1425}
1426
1427fn test_sumtype_type_name() {
1428 // Test .type_name() on sumtype with struct variants
1429 s1 := Stmt89(AssignStmt89{
1430 value: 42
1431 })
1432 assert s1.type_name() == 'AssignStmt89'
1433
1434 s2 := Stmt89(ExprStmt89{
1435 value: 7
1436 })
1437 assert s2.type_name() == 'ExprStmt89'
1438
1439 s3 := Stmt89(BlockStmt89{
1440 stmts: []
1441 })
1442 assert s3.type_name() == 'BlockStmt89'
1443
1444 // Test .type_name() on sumtype with primitive variants
1445 v1 := InnerSumType(123)
1446 assert v1.type_name() == 'int'
1447
1448 v2 := InnerSumType('hello')
1449 assert v2.type_name() == 'string'
1450
1451 // Test .type_name() on nested sumtype
1452 v3 := OuterSumType(true)
1453 assert v3.type_name() == 'bool'
1454
1455 print_str('sumtype type_name: ok')
1456}
1457
1458// ==== Test 95: Method call resolution ====
1459// Tests that the transformer correctly resolves receiver.method(args) -> Type__method(receiver, args)
1460
1461struct Counter95 {
1462mut:
1463 value int
1464}
1465
1466fn (c &Counter95) get() int {
1467 return c.value
1468}
1469
1470fn (mut c Counter95) add(n int) {
1471 c.value += n
1472}
1473
1474fn (c &Counter95) sum_with(other &Counter95) int {
1475 return c.value + other.value
1476}
1477
1478fn test_method_call_resolution() {
1479 // 95.1 Struct method call (immutable receiver)
1480 c1 := Counter95{
1481 value: 42
1482 }
1483 assert c1.get() == 42
1484
1485 // 95.2 Struct method call (mutable receiver)
1486 mut c2 := Counter95{
1487 value: 10
1488 }
1489 c2.add(5)
1490 assert c2.get() == 15
1491
1492 // 95.3 Method call with struct argument
1493 c3 := Counter95{
1494 value: 20
1495 }
1496 assert c2.sum_with(c3) == 35
1497
1498 // 95.4 Array method (push + len chain)
1499 mut arr := []int{}
1500 arr << 1
1501 arr << 2
1502 arr << 3
1503 assert arr.len == 3
1504
1505 // 95.5 String method call
1506 s := 'hello world'
1507 assert s.contains('world')
1508 assert s.replace('world', 'v') == 'hello v'
1509
1510 // 95.6 Chained method calls
1511 s2 := 'Hello World'
1512 result := s2.replace('World', 'V').replace('Hello', 'Hi')
1513 assert result == 'Hi V'
1514
1515 print_str('method call resolution: ok')
1516}
1517
1518// ==================== Test 96: Sumtype variant inference ====================
1519// Exercises the variant inference logic for various expression kinds when
1520// wrapping values into sum types. Covers: int/f64 literals, string literals,
1521// struct init, function return types, and variable references.
1522
1523type Val96 = f64 | int | string | Pair96
1524
1525struct Pair96 {
1526 a int
1527 b int
1528}
1529
1530fn make_pair96(a int, b int) Pair96 {
1531 return Pair96{
1532 a: a
1533 b: b
1534 }
1535}
1536
1537fn make_int96() int {
1538 return 99
1539}
1540
1541fn wrap_int_literal96() Val96 {
1542 return 42
1543}
1544
1545fn wrap_float_literal96() Val96 {
1546 return 3.14
1547}
1548
1549fn wrap_string_literal96() Val96 {
1550 return 'hello'
1551}
1552
1553fn wrap_struct_init96() Val96 {
1554 return Pair96{
1555 a: 1
1556 b: 2
1557 }
1558}
1559
1560fn wrap_fn_call96() Val96 {
1561 return make_pair96(10, 20)
1562}
1563
1564fn wrap_fn_call_int96() Val96 {
1565 return make_int96()
1566}
1567
1568fn wrap_variable96(v Val96) Val96 {
1569 return v
1570}
1571
1572fn test_sumtype_variant_inference() {
1573 // 96.1 int literal wrapped in sum type
1574 v1 := wrap_int_literal96()
1575 if v1 is int {
1576 assert v1 == 42
1577 print_str('sumtype variant inference (int literal): ok')
1578 } else {
1579 print_str('sumtype variant inference (int literal): FAIL')
1580 }
1581
1582 // 96.2 float literal wrapped in sum type
1583 v2 := wrap_float_literal96()
1584 if v2 is f64 {
1585 print_str('sumtype variant inference (f64 literal): ok')
1586 } else {
1587 print_str('sumtype variant inference (f64 literal): FAIL')
1588 }
1589
1590 // 96.3 string literal wrapped in sum type
1591 v3 := wrap_string_literal96()
1592 if v3 is string {
1593 assert v3 == 'hello'
1594 print_str('sumtype variant inference (string literal): ok')
1595 } else {
1596 print_str('sumtype variant inference (string literal): FAIL')
1597 }
1598
1599 // 96.4 struct init wrapped in sum type
1600 v4 := wrap_struct_init96()
1601 if v4 is Pair96 {
1602 assert v4.a == 1
1603 assert v4.b == 2
1604 print_str('sumtype variant inference (struct init): ok')
1605 } else {
1606 print_str('sumtype variant inference (struct init): FAIL')
1607 }
1608
1609 // 96.5 function call returning struct wrapped in sum type
1610 v5 := wrap_fn_call96()
1611 if v5 is Pair96 {
1612 assert v5.a == 10
1613 assert v5.b == 20
1614 print_str('sumtype variant inference (fn call struct): ok')
1615 } else {
1616 print_str('sumtype variant inference (fn call struct): FAIL')
1617 }
1618
1619 // 96.6 function call returning int wrapped in sum type
1620 v6 := wrap_fn_call_int96()
1621 if v6 is int {
1622 assert v6 == 99
1623 print_str('sumtype variant inference (fn call int): ok')
1624 } else {
1625 print_str('sumtype variant inference (fn call int): FAIL')
1626 }
1627
1628 // 96.7 variable of sum type passed through (identity)
1629 v7_inner := Val96(7)
1630 v7 := wrap_variable96(v7_inner)
1631 if v7 is int {
1632 assert v7 == 7
1633 print_str('sumtype variant inference (variable): ok')
1634 } else {
1635 print_str('sumtype variant inference (variable): FAIL')
1636 }
1637}
1638
1639// ==================== Test 97: Array type resolution ====================
1640// Tests that array operations work correctly when type info comes from the checker
1641// (get_expr_type) rather than expression-structure inference.
1642
1643fn get_test_arr97() []int {
1644 return [10, 20, 30]
1645}
1646
1647fn sum_arr97(arr []int) int {
1648 mut s := 0
1649 for v in arr {
1650 s += v
1651 }
1652 return s
1653}
1654
1655fn test_array_type_resolution() {
1656 // 97.1 Array comparison (== uses array__eq)
1657 a1 := [1, 2, 3]
1658 a2 := [1, 2, 3]
1659 a3 := [4, 5, 6]
1660 assert a1 == a2
1661 assert a1 != a3
1662 print_str('array type resolution (comparison): ok')
1663
1664 // 97.2 Array from function return, then filter
1665 arr := get_test_arr97()
1666 filtered := arr.filter(it > 15)
1667 assert filtered.len == 2
1668 assert filtered[0] == 20
1669 assert filtered[1] == 30
1670 print_str('array type resolution (filter): ok')
1671
1672 // 97.3 Array map
1673 doubled := arr.map(it * 2)
1674 assert doubled.len == 3
1675 assert doubled[0] == 20
1676 assert doubled[1] == 40
1677 assert doubled[2] == 60
1678 print_str('array type resolution (map): ok')
1679
1680 // 97.4 Array contains
1681 assert arr.contains(20)
1682 assert !arr.contains(99)
1683 print_str('array type resolution (contains): ok')
1684
1685 // 97.5 Array slice
1686 sliced := arr[1..]
1687 assert sliced.len == 2
1688 assert sliced[0] == 20
1689 assert sliced[1] == 30
1690 print_str('array type resolution (slice): ok')
1691
1692 // 97.6 Array passed to function
1693 total := sum_arr97(arr)
1694 assert total == 60
1695 print_str('array type resolution (fn arg): ok')
1696}
1697
1698// Helper: variadic function returning sum of all args
1699fn variadic_sum(vals ...int) int {
1700 mut s := 0
1701 for v in vals {
1702 s += v
1703 }
1704 return s
1705}
1706
1707// Helper: variadic function with a fixed first param
1708fn variadic_with_fixed(base int, extras ...int) int {
1709 mut s := base
1710 for v in extras {
1711 s += v
1712 }
1713 return s
1714}
1715
1716fn test_variadic_call_lowering() {
1717 // 98.1 Basic variadic call with multiple args
1718 r1 := variadic_sum(1, 2, 3)
1719 assert r1 == 6
1720 print_str('variadic call lowering (basic sum): ok')
1721
1722 // 98.2 Variadic call with two args
1723 r2 := variadic_sum(10, 20)
1724 assert r2 == 30
1725 print_str('variadic call lowering (two args): ok')
1726
1727 // 98.3 Variadic call with single arg
1728 r3 := variadic_sum(42)
1729 assert r3 == 42
1730 print_str('variadic call lowering (single arg): ok')
1731
1732 // 98.4 Variadic with fixed + variadic params
1733 r4 := variadic_with_fixed(100, 10, 20, 30)
1734 assert r4 == 160
1735 print_str('variadic call lowering (fixed + variadic): ok')
1736}
1737
1738fn test_array_init_with_index() {
1739 // 99.1 Basic array init with index
1740 arr1 := []int{len: 5, init: index * 2}
1741 assert arr1[0] == 0
1742 assert arr1[1] == 2
1743 assert arr1[2] == 4
1744 assert arr1[3] == 6
1745 assert arr1[4] == 8
1746 print_str('array init with index (basic multiply): ok')
1747
1748 // 99.2 Array init with index addition
1749 arr2 := []int{len: 4, init: index + 10}
1750 assert arr2[0] == 10
1751 assert arr2[1] == 11
1752 assert arr2[2] == 12
1753 assert arr2[3] == 13
1754 print_str('array init with index (addition): ok')
1755
1756 // 99.3 Array init with just index
1757 arr3 := []int{len: 3, init: index}
1758 assert arr3[0] == 0
1759 assert arr3[1] == 1
1760 assert arr3[2] == 2
1761 print_str('array init with index (identity): ok')
1762}
1763
1764// ===================== MAIN TEST FUNCTION =====================
1765
1766fn main() {
1767 print_str('=== SSA Backend Test Suite ===')
1768
1769 // ==================== 1. STRUCT DECL & INIT (5 tests) ====================
1770 print_str('--- 1. Struct Declaration & Initialization ---')
1771
1772 // 1.1 Basic struct init
1773 p1 := Point{
1774 x: 10
1775 y: 20
1776 }
1777 print_int(p1.x) // 10
1778 print_int(p1.y) // 20
1779
1780 // 1.2 Default zero init
1781 p2 := Point{}
1782 print_int(p2.x) // 0
1783 print_int(p2.y) // 0
1784
1785 // 1.3 Mutable struct modification
1786 mut p3 := Point{
1787 x: 1
1788 y: 2
1789 }
1790 p3.x = 100
1791 p3.y = 200
1792 print_int(p3.x) // 100
1793 print_int(p3.y) // 200
1794
1795 // 1.4 Struct with computed values
1796 base := 7
1797 p4 := Point{
1798 x: base * 2
1799 y: base * 3
1800 }
1801 print_int(p4.x) // 14
1802 print_int(p4.y) // 21
1803
1804 // 1.5 Multiple struct instances
1805 p5a := Point{
1806 x: 1
1807 y: 2
1808 }
1809 p5b := Point{
1810 x: 3
1811 y: 4
1812 }
1813 print_int(p5a.x + p5b.x) // 4
1814 print_int(p5a.y + p5b.y) // 6
1815
1816 // ==================== 2. CALLS & SELECTOR ASSIGN (5 tests) ====================
1817 print_str('--- 2. Calls & Selector Assignment ---')
1818
1819 // 2.1 Basic function call with selector assign
1820 mut pt := Point{
1821 x: 10
1822 y: 20
1823 }
1824 pt.x = add(pt.x, 5)
1825 print_int(pt.x) // 15
1826
1827 // 2.2 Chained calls
1828 pt.y = add(add(pt.y, 10), 5)
1829 print_int(pt.y) // 35
1830
1831 // 2.3 Call result to selector with subtraction
1832 pt.x = sub(pt.x, 3)
1833 print_int(pt.x) // 12
1834
1835 // 2.4 Multiple selectors updated via calls
1836 mut pt2 := Point{
1837 x: 5
1838 y: 5
1839 }
1840 pt2.x = mul(pt2.x, 3)
1841 pt2.y = mul(pt2.y, 4)
1842 print_int(pt2.x) // 15
1843 print_int(pt2.y) // 20
1844
1845 // 2.5 Nested function calls with selectors
1846 mut pt3 := Point{
1847 x: 10
1848 y: 20
1849 }
1850 pt3.x = add(mul(pt3.x, 2), 5) // 10*2 + 5 = 25
1851 pt3.y = sub(mul(pt3.y, 3), 10) // 20*3 - 10 = 50
1852 print_int(pt3.x) // 25
1853 print_int(pt3.y) // 50
1854
1855 // ==================== 3. GLOBALS & COMPOUND ASSIGN (5 tests) ====================
1856 print_str('--- 3. Globals & Compound Assignment ---')
1857
1858 // 3.1 Basic global assignment and compound add
1859 g_val = 50
1860 g_val += 50
1861 print_int(g_val) // 100
1862
1863 // 3.2 Compound subtract
1864 g_val = 100
1865 g_val -= 30
1866 print_int(g_val) // 70
1867
1868 // 3.3 Compound multiply
1869 g_val = 5
1870 g_val *= 6
1871 print_int(g_val) // 30
1872
1873 // 3.4 Compound divide
1874 g_val = 100
1875 g_val /= 4
1876 print_int(g_val) // 25
1877
1878 // 3.5 Global struct
1879 g_point.x = 42
1880 g_point.y = 84
1881 g_point.x += 8
1882 print_int(g_point.x) // 50
1883 print_int(g_point.y) // 84
1884
1885 // ==================== 4. BOOL & LOGIC (5 tests) ====================
1886 print_str('--- 4. Bool & Logic ---')
1887
1888 // 4.1 Basic bool true
1889 flag1 := true
1890 if flag1 {
1891 print_int(1)
1892 } else {
1893 print_int(0)
1894 }
1895
1896 // 4.2 Basic bool false
1897 flag2 := false
1898 if flag2 {
1899 print_int(1)
1900 } else {
1901 print_int(0)
1902 }
1903
1904 // 4.3 Bool from comparison
1905 cmp_val := 10
1906 flag3 := cmp_val > 5
1907 if flag3 {
1908 print_int(1)
1909 } else {
1910 print_int(0)
1911 }
1912
1913 // 4.4 Logical AND
1914 a_bool := true
1915 b_bool := true
1916 if a_bool && b_bool {
1917 print_int(1)
1918 } else {
1919 print_int(0)
1920 }
1921
1922 // 4.5 Logical OR and NOT
1923 c_bool := false
1924 d_bool := true
1925 if c_bool || d_bool {
1926 print_int(1) // 1
1927 } else {
1928 print_int(0)
1929 }
1930 if !c_bool {
1931 print_int(1) // 1
1932 } else {
1933 print_int(0)
1934 }
1935
1936 // ==================== 5. LOOP WITH BREAK/CONTINUE (5 tests) ====================
1937 print_str('--- 5. Loop with Break/Continue ---')
1938
1939 // 5.1 Basic continue (skip 5)
1940 mut sum1 := 0
1941 mut i1 := 0
1942 for i1 < 10 {
1943 i1++
1944 if i1 == 5 {
1945 continue
1946 }
1947 if i1 > 7 {
1948 break
1949 }
1950 sum1 += i1
1951 }
1952 print_int(sum1) // 1+2+3+4+6+7 = 23
1953
1954 // 5.2 Multiple continues (skip even)
1955 mut sum2 := 0
1956 mut i2 := 0
1957 for i2 < 10 {
1958 i2++
1959 if i2 % 2 == 0 {
1960 continue
1961 }
1962 sum2 += i2
1963 }
1964 print_int(sum2) // 1+3+5+7+9 = 25
1965
1966 // 5.3 Early break
1967 mut sum3 := 0
1968 mut i3 := 0
1969 for i3 < 100 {
1970 i3++
1971 if i3 > 5 {
1972 break
1973 }
1974 sum3 += i3
1975 }
1976 print_int(sum3) // 1+2+3+4+5 = 15
1977
1978 // 5.4 Combined break and continue
1979 mut sum4 := 0
1980 mut i4 := 0
1981 for i4 < 20 {
1982 i4++
1983 if i4 % 3 == 0 {
1984 continue
1985 }
1986 if i4 > 10 {
1987 break
1988 }
1989 sum4 += i4
1990 }
1991 print_int(sum4) // 1+2+4+5+7+8+10 = 37
1992
1993 // 5.5 Simple condition loop
1994 mut sum5 := 0
1995 mut i5 := 0
1996 for i5 < 5 {
1997 sum5 += i5
1998 i5++
1999 }
2000 print_int(sum5) // 0+1+2+3+4 = 10
2001
2002 // ==================== 6. MATCH (5 tests) ====================
2003 print_str('--- 6. Match ---')
2004
2005 // 6.1 Match with else
2006 x1 := 10
2007 match x1 {
2008 1 { print_int(1) }
2009 2 { print_int(2) }
2010 else { print_int(777) }
2011 }
2012
2013 // 6.2 Match exact case
2014 x2 := 2
2015 match x2 {
2016 1 { print_int(100) }
2017 2 { print_int(200) }
2018 3 { print_int(300) }
2019 else { print_int(0) }
2020 }
2021
2022 // 6.3 Match first case
2023 x3 := 1
2024 match x3 {
2025 1 { print_int(111) }
2026 2 { print_int(222) }
2027 else { print_int(999) }
2028 }
2029
2030 // 6.4 Match with computation
2031 x4 := 5
2032 match x4 {
2033 1 { print_int(x4 * 10) }
2034 5 { print_int(x4 * 100) }
2035 else { print_int(0) }
2036 }
2037
2038 // 6.5 Match with more cases
2039 x5 := 4
2040 match x5 {
2041 1 { print_int(10) }
2042 2 { print_int(20) }
2043 3 { print_int(30) }
2044 4 { print_int(40) }
2045 5 { print_int(50) }
2046 else { print_int(0) }
2047 }
2048
2049 // ==================== 7. C-STYLE LOOP & FACTORIAL (5 tests) ====================
2050 print_str('--- 7. C-style Loop ---')
2051
2052 // 7.1 Basic factorial
2053 mut fact1 := 1
2054 for k := 1; k <= 5; k++ {
2055 fact1 = fact1 * k
2056 }
2057 print_int(fact1) // 120
2058
2059 // 7.2 Sum 1 to 10
2060 mut sum7 := 0
2061 for k := 1; k <= 10; k++ {
2062 sum7 += k
2063 }
2064 print_int(sum7) // 55
2065
2066 // 7.3 Powers of 2
2067 mut pow2 := 1
2068 for k := 0; k < 8; k++ {
2069 pow2 = pow2 * 2
2070 }
2071 print_int(pow2) // 256
2072
2073 // 7.4 Countdown
2074 mut countdown := 0
2075 for k := 10; k > 0; k-- {
2076 countdown += k
2077 }
2078 print_int(countdown) // 55
2079
2080 // 7.5 Step by 2
2081 mut sum_even := 0
2082 for k := 0; k <= 10; k += 2 {
2083 sum_even += k
2084 }
2085 print_int(sum_even) // 0+2+4+6+8+10 = 30
2086
2087 // ==================== 8. RECURSIVE FUNCTIONS (5 tests) ====================
2088 print_str('--- 8. Recursive Functions ---')
2089
2090 // 8.1 Fibonacci
2091 print_int(fib(10)) // 55
2092
2093 // 8.2 Factorial recursive
2094 print_int(factorial(6)) // 720
2095
2096 // 8.3 Sum recursive
2097 print_int(sum_recursive(10)) // 55
2098
2099 // 8.4 GCD
2100 print_int(gcd(48, 18)) // 6
2101
2102 // 8.5 Power
2103 print_int(power(2, 10)) // 1024
2104
2105 // ==================== 9. NESTED LOOPS (5 tests) ====================
2106 print_str('--- 9. Nested Loops ---')
2107
2108 // 9.1 Basic 3x3
2109 mut count1 := 0
2110 mut r1 := 0
2111 for r1 < 3 {
2112 mut c1 := 0
2113 for c1 < 3 {
2114 count1++
2115 c1++
2116 }
2117 r1++
2118 }
2119 print_int(count1) // 9
2120
2121 // 9.2 4x5 grid
2122 mut count2 := 0
2123 mut r2 := 0
2124 for r2 < 4 {
2125 mut c2 := 0
2126 for c2 < 5 {
2127 count2++
2128 c2++
2129 }
2130 r2++
2131 }
2132 print_int(count2) // 20
2133
2134 // 9.3 Sum of products
2135 mut sum9 := 0
2136 mut r3 := 1
2137 for r3 <= 3 {
2138 mut c3 := 1
2139 for c3 <= 3 {
2140 sum9 += r3 * c3
2141 c3++
2142 }
2143 r3++
2144 }
2145 print_int(sum9) // (1+2+3) + (2+4+6) + (3+6+9) = 36
2146
2147 // 9.4 2x3 with accumulator
2148 mut count4 := 0
2149 mut r4 := 0
2150 for r4 < 2 {
2151 mut c4 := 0
2152 for c4 < 3 {
2153 count4 += 1
2154 c4++
2155 }
2156 r4++
2157 }
2158 print_int(count4) // 6
2159
2160 // 9.5 Inner break
2161 mut count5 := 0
2162 mut r5 := 0
2163 for r5 < 5 {
2164 mut c5 := 0
2165 for c5 < 10 {
2166 if c5 >= 3 {
2167 break
2168 }
2169 count5++
2170 c5++
2171 }
2172 r5++
2173 }
2174 print_int(count5) // 5*3 = 15
2175
2176 // ==================== 10. INFINITE LOOP (5 tests) ====================
2177 print_str('--- 10. Infinite Loop ---')
2178
2179 // 10.1 Basic infinite with break
2180 mut iter1 := 0
2181 for {
2182 iter1++
2183 if iter1 == 5 {
2184 break
2185 }
2186 }
2187 print_int(iter1) // 5
2188
2189 // 10.2 Sum until threshold
2190 mut sum10 := 0
2191 mut n10 := 0
2192 for {
2193 n10++
2194 sum10 += n10
2195 if sum10 > 20 {
2196 break
2197 }
2198 }
2199 print_int(sum10) // 21 (1+2+3+4+5+6 = 21)
2200
2201 // 10.3 Find first power of 2 > 100
2202 mut pow := 1
2203 for {
2204 pow = pow * 2
2205 if pow > 100 {
2206 break
2207 }
2208 }
2209 print_int(pow) // 128
2210
2211 // 10.4 Countdown in infinite loop
2212 mut cd := 10
2213 for {
2214 cd--
2215 if cd == 0 {
2216 break
2217 }
2218 }
2219 print_int(cd) // 0
2220
2221 // 10.5 Simple counter
2222 mut x10 := 0
2223 for {
2224 x10++
2225 if x10 >= 10 {
2226 break
2227 }
2228 }
2229 print_int(x10) // 10
2230
2231 // ==================== 11. MANY ARGUMENTS (5 tests) ====================
2232 print_str('--- 11. Many Arguments ---')
2233
2234 // 11.1 Sum of 8 ones
2235 print_int(sum_many(1, 1, 1, 1, 1, 1, 1, 1)) // 8
2236
2237 // 11.2 Sum of sequence
2238 print_int(sum_many(1, 2, 3, 4, 5, 6, 7, 8)) // 36
2239
2240 // 11.3 Product of small numbers
2241 print_int(mul_many(1, 2, 1, 2, 1, 2, 1, 2)) // 16
2242
2243 // 11.4 Max of 8
2244 print_int(max_of_eight(3, 7, 2, 9, 1, 8, 4, 6)) // 9
2245
2246 // 11.5 Weighted sum
2247 print_int(weighted_sum(1, 1, 1, 1, 1, 1, 1, 1)) // 1+2+3+4+5+6+7+8 = 36
2248
2249 // ==================== 12. MODIFYING STRUCT (5 tests) ====================
2250 print_str('--- 12. Modifying Struct via Function ---')
2251
2252 // 12.1 Basic modify
2253 mut pm1 := Point{
2254 x: 10
2255 y: 20
2256 }
2257 modify_struct(mut pm1)
2258 print_int(pm1.x) // 999
2259 print_int(pm1.y) // 888
2260
2261 // 12.2 Swap
2262 mut pm2 := Point{
2263 x: 5
2264 y: 15
2265 }
2266 swap_point(mut pm2)
2267 print_int(pm2.x) // 15
2268 print_int(pm2.y) // 5
2269
2270 // 12.3 Scale
2271 mut pm3 := Point{
2272 x: 10
2273 y: 20
2274 }
2275 scale_point(mut pm3, 3)
2276 print_int(pm3.x) // 30
2277 print_int(pm3.y) // 60
2278
2279 // 12.4 Translate
2280 mut pm4 := Point{
2281 x: 5
2282 y: 10
2283 }
2284 translate_point(mut pm4, 100, 200)
2285 print_int(pm4.x) // 105
2286 print_int(pm4.y) // 210
2287
2288 // 12.5 Reset
2289 mut pm5 := Point{
2290 x: 999
2291 y: 888
2292 }
2293 reset_point(mut pm5)
2294 print_int(pm5.x) // 0
2295 print_int(pm5.y) // 0
2296
2297 // ==================== 13. ASSERT (5 tests) ====================
2298 print_str('--- 13. Assert ---')
2299
2300 // 13.1 Basic equality
2301 assert 1 == 1
2302 print_str('Assert 1 passed')
2303
2304 // 13.2 Computed equality
2305 assert 2 + 2 == 4
2306 print_str('Assert 2 passed')
2307
2308 // 13.3 Boolean assert
2309 assert true
2310 print_str('Assert 3 passed')
2311
2312 // 13.4 Comparison assert
2313 assert 10 > 5
2314 print_str('Assert 4 passed')
2315
2316 // 13.5 Complex expression
2317 assert (3 * 4) == (2 * 6)
2318 print_str('Assert 5 passed')
2319
2320 // ==================== 14. HEAP ALLOCATION (5 tests) ====================
2321 print_str('--- 14. Heap Allocation ---')
2322
2323 // 14.1 Basic heap Point
2324 hp1 := &Point{
2325 x: 10
2326 y: 20
2327 }
2328 print_int(hp1.x) // 10
2329 print_int(hp1.y) // 20
2330
2331 // 14.2 Heap with zero
2332 hp2 := &Point{
2333 x: 0
2334 y: 0
2335 }
2336 print_int(hp2.x) // 0
2337 print_int(hp2.y) // 0
2338
2339 // 14.3 Heap with computed values
2340 hp3 := &Point{
2341 x: 5 * 5
2342 y: 6 * 6
2343 }
2344 print_int(hp3.x) // 25
2345 print_int(hp3.y) // 36
2346
2347 // 14.4 Heap Rectangle (no nested access)
2348 hr := &Rectangle{
2349 width: 100
2350 height: 200
2351 origin: Point{
2352 x: 10
2353 y: 20
2354 }
2355 }
2356 print_int(hr.width) // 100
2357 print_int(hr.height) // 200
2358
2359 // 14.5 Heap Node
2360 hn := &Node{
2361 value: 42
2362 left: 1
2363 right: 2
2364 }
2365 print_int(hn.value) // 42
2366 print_int(hn.left) // 1
2367 print_int(hn.right) // 2
2368
2369 // ==================== 15. BITWISE OPERATIONS (5 tests) ====================
2370 print_str('--- 15. Bitwise Operations ---')
2371
2372 // 15.1 Basic AND
2373 print_int(0b1100 & 0b1010) // 8
2374
2375 // 15.2 Basic OR
2376 print_int(0b1100 | 0b1010) // 14
2377
2378 // 15.3 Basic XOR
2379 print_int(0b1100 ^ 0b1010) // 6
2380
2381 // 15.4 Mask extraction
2382 num := 0xABCD
2383 low_byte := num & 0xFF
2384 print_int(low_byte) // 0xCD = 205
2385
2386 // 15.5 Bit set/clear
2387 mut flags := 0
2388 flags = flags | 0b0001 // set bit 0
2389 flags = flags | 0b0100 // set bit 2
2390 print_int(flags) // 5
2391 flags = flags & 0b1110 // clear bit 0
2392 print_int(flags) // 4
2393
2394 // ==================== 16. SHIFT OPERATIONS (5 tests) ====================
2395 print_str('--- 16. Shift Operations ---')
2396
2397 // 16.1 Left shift basic
2398 print_int(1 << 4) // 16
2399
2400 // 16.2 Right shift basic
2401 print_int(32 >> 2) // 8
2402
2403 // 16.3 Multiple shifts
2404 print_int(255 >> 4) // 15
2405
2406 // 16.4 Shift for multiply
2407 val16 := 7
2408 print_int(val16 << 3) // 7 * 8 = 56
2409
2410 // 16.5 Shift for divide
2411 val17 := 96
2412 print_int(val17 >> 4) // 96 / 16 = 6
2413
2414 // ==================== 17. MODULO (5 tests) ====================
2415 print_str('--- 17. Modulo ---')
2416
2417 // 17.1 Basic modulo
2418 print_int(17 % 5) // 2
2419
2420 // 17.2 Modulo with larger divisor
2421 print_int(100 % 7) // 2
2422
2423 // 17.3 Even/odd check
2424 print_int(15 % 2) // 1 (odd)
2425 print_int(16 % 2) // 0 (even)
2426
2427 // 17.4 Clock arithmetic
2428 hour := 23
2429 new_hour := (hour + 5) % 24
2430 print_int(new_hour) // 4
2431
2432 // 17.5 Digit extraction
2433 num17 := 12345
2434 last_digit := num17 % 10
2435 print_int(last_digit) // 5
2436 second_digit := (num17 / 10) % 10
2437 print_int(second_digit) // 4
2438
2439 // ==================== 18. POINTER ARITHMETIC (5 tests) ====================
2440 print_str('--- 18. Pointer Arithmetic ---')
2441
2442 // 18.1 Heap struct access
2443 hp_arr1 := &Point{
2444 x: 10
2445 y: 20
2446 }
2447 print_int(hp_arr1.x) // 10
2448 print_int(hp_arr1.y) // 20
2449
2450 // 18.2 Multiple heap structs
2451 hp_arr2 := &Point{
2452 x: 100
2453 y: 200
2454 }
2455 hp_arr3 := &Point{
2456 x: 300
2457 y: 400
2458 }
2459 print_int(hp_arr2.x + hp_arr3.x) // 400
2460 print_int(hp_arr2.y + hp_arr3.y) // 600
2461
2462 // 18.3 Heap struct with computed values
2463 base18 := 5
2464 hp_arr4 := &Point{
2465 x: base18 * 10
2466 y: base18 * 20
2467 }
2468 print_int(hp_arr4.x) // 50
2469 print_int(hp_arr4.y) // 100
2470
2471 // 18.4 Multiple heap allocations in loop
2472 mut sum18 := 0
2473 mut i18 := 0
2474 for i18 < 3 {
2475 hp := &Point{
2476 x: i18 * 10
2477 y: i18 * 20
2478 }
2479 sum18 = sum18 + hp.x + hp.y
2480 i18++
2481 }
2482 print_int(sum18) // 0+0 + 10+20 + 20+40 = 90
2483
2484 // 18.5 Heap node tree structure
2485 node1 := &Node{
2486 value: 100
2487 left: 0
2488 right: 0
2489 }
2490 node2 := &Node{
2491 value: 200
2492 left: 0
2493 right: 0
2494 }
2495 print_int(node1.value + node2.value) // 300
2496
2497 // ==================== 19. NESTED STRUCT ACCESS (5 tests) ====================
2498 print_str('--- 19. Nested Struct Access ---')
2499
2500 // 19.1 Basic nested access
2501 rect := Rectangle{
2502 width: 100
2503 height: 200
2504 origin: Point{
2505 x: 10
2506 y: 20
2507 }
2508 }
2509 print_int(rect.width) // 100
2510 print_int(rect.height) // 200
2511
2512 // 19.2 Nested struct field via intermediate
2513 rect2 := Rectangle{
2514 width: 50
2515 height: 60
2516 origin: Point{
2517 x: 5
2518 y: 6
2519 }
2520 }
2521 print_int(rect2.width + rect2.height) // 110
2522
2523 // 19.3 Mutable nested struct modification
2524 mut rect3 := Rectangle{
2525 width: 10
2526 height: 20
2527 origin: Point{
2528 x: 1
2529 y: 2
2530 }
2531 }
2532 rect3.width = 100
2533 rect3.height = 200
2534 print_int(rect3.width) // 100
2535 print_int(rect3.height) // 200
2536
2537 // 19.4 Multiple rectangles
2538 rect4a := Rectangle{
2539 width: 10
2540 height: 20
2541 origin: Point{
2542 x: 0
2543 y: 0
2544 }
2545 }
2546 rect4b := Rectangle{
2547 width: 30
2548 height: 40
2549 origin: Point{
2550 x: 0
2551 y: 0
2552 }
2553 }
2554 print_int(rect4a.width + rect4b.width) // 40
2555 print_int(rect4a.height + rect4b.height) // 60
2556
2557 // 19.5 Rectangle area
2558 rect5 := Rectangle{
2559 width: 12
2560 height: 10
2561 origin: Point{
2562 x: 0
2563 y: 0
2564 }
2565 }
2566 area := rect5.width * rect5.height
2567 print_int(area) // 120
2568
2569 // ==================== 20. NEGATIVE NUMBERS (5 tests) ====================
2570 print_str('--- 20. Negative Numbers ---')
2571
2572 // 20.1 Unary minus
2573 n1 := 0 - 42
2574 print_int(n1) // -42
2575
2576 // 20.2 Negative addition
2577 n2 := 0 - 10
2578 n3 := n2 + 5
2579 print_int(n3) // -5
2580
2581 // 20.3 Negative subtraction
2582 n4 := 0 - 20
2583 n5 := n4 - 10
2584 print_int(n5) // -30
2585
2586 // 20.4 Negative multiplication
2587 n6 := 0 - 7
2588 n7 := n6 * 3
2589 print_int(n7) // -21
2590
2591 // 20.5 Double negative (positive)
2592 n8 := 0 - 50
2593 n9 := 0 - n8
2594 print_int(n9) // 50
2595
2596 // ==================== 21. UNARY OPERATIONS (5 tests) ====================
2597 print_str('--- 21. Unary Operations ---')
2598
2599 // 21.1 Logical not on false
2600 u1 := !false
2601 if u1 {
2602 print_int(1) // 1
2603 } else {
2604 print_int(0)
2605 }
2606
2607 // 21.2 Logical not on true
2608 u2 := !true
2609 if u2 {
2610 print_int(1)
2611 } else {
2612 print_int(0) // 0
2613 }
2614
2615 // 21.3 Double negation
2616 u3 := !!true
2617 if u3 {
2618 print_int(1) // 1
2619 } else {
2620 print_int(0)
2621 }
2622
2623 // 21.4 Not with comparison
2624 u4 := !(5 > 10)
2625 if u4 {
2626 print_int(1) // 1
2627 } else {
2628 print_int(0)
2629 }
2630
2631 // 21.5 Not with variable
2632 u5 := false
2633 u6 := !u5
2634 if u6 {
2635 print_int(1) // 1
2636 } else {
2637 print_int(0)
2638 }
2639
2640 // ==================== 22. COMPLEX BOOLEAN (5 tests) ====================
2641 print_str('--- 22. Complex Boolean ---')
2642
2643 // 22.1 Multiple ANDs
2644 if true && true && true {
2645 print_int(1) // 1
2646 } else {
2647 print_int(0)
2648 }
2649
2650 // 22.2 Multiple ORs
2651 if false || false || true {
2652 print_int(1) // 1
2653 } else {
2654 print_int(0)
2655 }
2656
2657 // 22.3 AND with OR
2658 if (true && false) || (true && true) {
2659 print_int(1) // 1
2660 } else {
2661 print_int(0)
2662 }
2663
2664 // 22.4 Complex condition with variables
2665 aa := 10
2666 bb := 20
2667 cc := 30
2668 if aa < bb && bb < cc {
2669 print_int(1) // 1
2670 } else {
2671 print_int(0)
2672 }
2673
2674 // 22.5 Chained comparisons
2675 if aa < 15 && bb > 15 && cc == 30 {
2676 print_int(1) // 1
2677 } else {
2678 print_int(0)
2679 }
2680
2681 // ==================== 23. COMPARISON AS EXPRESSION (5 tests) ====================
2682 print_str('--- 23. Comparison as Expression ---')
2683
2684 // 23.1 Comparison result in variable
2685 cmp1 := 10 > 5
2686 if cmp1 {
2687 print_int(1) // 1
2688 } else {
2689 print_int(0)
2690 }
2691
2692 // 23.2 Multiple comparison results
2693 cmp2 := 3 < 5
2694 cmp3 := 7 > 2
2695 if cmp2 && cmp3 {
2696 print_int(1) // 1
2697 } else {
2698 print_int(0)
2699 }
2700
2701 // 23.3 Equality comparison
2702 cmp4 := 42 == 42
2703 if cmp4 {
2704 print_int(1) // 1
2705 } else {
2706 print_int(0)
2707 }
2708
2709 // 23.4 Inequality comparison
2710 cmp5 := 10 != 20
2711 if cmp5 {
2712 print_int(1) // 1
2713 } else {
2714 print_int(0)
2715 }
2716
2717 // 23.5 Comparison with expressions
2718 cmp6 := (5 + 5) == (2 * 5)
2719 if cmp6 {
2720 print_int(1) // 1
2721 } else {
2722 print_int(0)
2723 }
2724
2725 // ==================== 24. DEEPLY NESTED IF (5 tests) ====================
2726 print_str('--- 24. Deeply Nested If ---')
2727
2728 // 24.1 Three levels deep
2729 dn1 := 5
2730 if dn1 > 0 {
2731 if dn1 > 3 {
2732 if dn1 > 4 {
2733 print_int(1) // 1
2734 } else {
2735 print_int(0)
2736 }
2737 } else {
2738 print_int(0)
2739 }
2740 } else {
2741 print_int(0)
2742 }
2743
2744 // 24.2 Nested with else chains
2745 dn2 := 2
2746 if dn2 == 1 {
2747 print_int(10)
2748 } else {
2749 if dn2 == 2 {
2750 print_int(20) // 20
2751 } else {
2752 if dn2 == 3 {
2753 print_int(30)
2754 } else {
2755 print_int(0)
2756 }
2757 }
2758 }
2759
2760 // 24.3 Mixed nesting with match
2761 dn3 := 3
2762 if dn3 > 0 {
2763 match dn3 {
2764 1 { print_int(100) }
2765 2 { print_int(200) }
2766 3 { print_int(300) } // 300
2767 else { print_int(0) }
2768 }
2769 } else {
2770 print_int(0)
2771 }
2772
2773 // 24.4 Nested loops with conditionals
2774 mut dn4_sum := 0
2775 mut dn4_i := 0
2776 for dn4_i < 3 {
2777 mut dn4_j := 0
2778 for dn4_j < 3 {
2779 if dn4_i == dn4_j {
2780 dn4_sum += 1
2781 }
2782 dn4_j++
2783 }
2784 dn4_i++
2785 }
2786 print_int(dn4_sum) // 3 (diagonal: 0-0, 1-1, 2-2)
2787
2788 // 24.5 If inside loop with break
2789 mut dn5_result := 0
2790 mut dn5_k := 0
2791 for dn5_k < 100 {
2792 if dn5_k > 5 {
2793 if dn5_k > 7 {
2794 dn5_result = dn5_k
2795 break
2796 }
2797 }
2798 dn5_k++
2799 }
2800 print_int(dn5_result) // 8
2801
2802 // ==================== 25. LARGE CONSTANTS (5 tests) ====================
2803 print_str('--- 25. Large Constants ---')
2804
2805 // 25.1 Value > 65535
2806 big1 := 100000
2807 print_int(big1) // 100000
2808
2809 // 25.2 Large multiplication result
2810 big2 := 1000 * 1000
2811 print_int(big2) // 1000000
2812
2813 // 25.3 Large addition
2814 big3 := 50000 + 50000
2815 print_int(big3) // 100000
2816
2817 // 25.4 Large subtraction
2818 big4 := 200000 - 100000
2819 print_int(big4) // 100000
2820
2821 // 25.5 Large division
2822 big5 := 1000000 / 100
2823 print_int(big5) // 10000
2824
2825 // ==================== 26. MIXED OPERATIONS (5 tests) ====================
2826 print_str('--- 26. Mixed Operations ---')
2827
2828 // 26.1 Arithmetic then comparison
2829 mix1 := (10 + 5) * 2
2830 if mix1 == 30 {
2831 print_int(1) // 1
2832 } else {
2833 print_int(0)
2834 }
2835
2836 // 26.2 Comparison then logic
2837 mix2a := 10 > 5
2838 mix2b := 20 < 30
2839 if mix2a && mix2b {
2840 print_int(1) // 1
2841 } else {
2842 print_int(0)
2843 }
2844
2845 // 26.3 Chained arithmetic
2846 mix3 := 2 + 3 * 4 - 6 / 2
2847 print_int(mix3) // 2 + 12 - 3 = 11
2848
2849 // 26.4 Bitwise with arithmetic
2850 mix4 := (5 | 3) + (4 & 6)
2851 print_int(mix4) // 7 + 4 = 11
2852
2853 // 26.5 Complex expression
2854 mix5 := ((10 + 5) * 2 - 10) / 5
2855 print_int(mix5) // (30 - 10) / 5 = 4
2856
2857 // ==================== 27. EDGE CASES (5 tests) ====================
2858 print_str('--- 27. Edge Cases ---')
2859
2860 // 27.1 Zero operations
2861 edge1 := 0 + 0
2862 print_int(edge1) // 0
2863 edge2 := 100 * 0
2864 print_int(edge2) // 0
2865 edge3 := 0 / 7
2866 print_int(edge3) // 0
2867
2868 // 27.2 Identity operations
2869 edge4 := 42 + 0
2870 print_int(edge4) // 42
2871 edge5 := 42 * 1
2872 print_int(edge5) // 42
2873 edge6 := 42 / 1
2874 print_int(edge6) // 42
2875
2876 // 27.3 Division edge cases
2877 edge7 := 7 / 7
2878 print_int(edge7) // 1
2879 edge8 := 100 / 10
2880 print_int(edge8) // 10
2881
2882 // 27.4 Modulo edge cases
2883 edge9 := 10 % 10
2884 print_int(edge9) // 0
2885 edge10 := 5 % 7
2886 print_int(edge10) // 5
2887
2888 // 27.5 Comparison edge cases
2889 if 0 == 0 {
2890 print_int(1) // 1
2891 } else {
2892 print_int(0)
2893 }
2894 if 0 < 1 {
2895 print_int(1) // 1
2896 } else {
2897 print_int(0)
2898 }
2899
2900 // ==================== 28. COMPLEX RECURSION (5 tests) ====================
2901 print_str('--- 28. Complex Recursion ---')
2902
2903 // 28.1 Deep recursion test
2904 print_int(sum_recursive(100)) // 5050
2905
2906 // 28.2 Mutual dependency via gcd
2907 print_int(gcd(252, 105)) // 21
2908
2909 // 28.3 Multiple recursive calls
2910 print_int(fib(15)) // 610
2911
2912 // 28.4 Power with larger exponent
2913 print_int(power(3, 5)) // 243
2914
2915 // 28.5 Factorial with larger input
2916 print_int(factorial(7)) // 5040
2917
2918 // ==================== 29. STRUCT OPERATIONS (5 tests) ====================
2919 print_str('--- 29. Struct Operations ---')
2920
2921 // 29.1 Struct as function result (via modify)
2922 mut sp1 := Point{
2923 x: 0
2924 y: 0
2925 }
2926 scale_point(mut sp1, 10)
2927 print_int(sp1.x) // 0
2928 print_int(sp1.y) // 0
2929
2930 // 29.2 Chained struct modifications
2931 mut sp2 := Point{
2932 x: 1
2933 y: 1
2934 }
2935 scale_point(mut sp2, 5)
2936 translate_point(mut sp2, 10, 20)
2937 print_int(sp2.x) // 15
2938 print_int(sp2.y) // 25
2939
2940 // 29.3 Struct field arithmetic
2941 sp3 := Point{
2942 x: 100
2943 y: 200
2944 }
2945 sp3_sum := sp3.x + sp3.y
2946 sp3_diff := sp3.y - sp3.x
2947 print_int(sp3_sum) // 300
2948 print_int(sp3_diff) // 100
2949
2950 // 29.4 Multiple struct parameters
2951 mut sp4 := Point{
2952 x: 10
2953 y: 20
2954 }
2955 swap_point(mut sp4)
2956 scale_point(mut sp4, 2)
2957 print_int(sp4.x) // 40
2958 print_int(sp4.y) // 20
2959
2960 // 29.5 Struct in conditional
2961 sp5 := Point{
2962 x: 5
2963 y: 10
2964 }
2965 if sp5.x < sp5.y {
2966 print_int(1) // 1
2967 } else {
2968 print_int(0)
2969 }
2970
2971 // ==================== 30. CONTROL FLOW EDGE CASES (5 tests) ====================
2972 print_str('--- 30. Control Flow Edge Cases ---')
2973
2974 // 30.1 Empty else
2975 mut cf1 := 0
2976 if true {
2977 cf1 = 1
2978 }
2979 print_int(cf1) // 1
2980
2981 // 30.2 Multiple sequential ifs
2982 mut cf2 := 0
2983 if true {
2984 cf2 += 1
2985 }
2986 if true {
2987 cf2 += 2
2988 }
2989 if true {
2990 cf2 += 4
2991 }
2992 print_int(cf2) // 7
2993
2994 // 30.3 Nested match
2995 cf3 := 2
2996 match cf3 {
2997 1 {
2998 match cf3 {
2999 1 { print_int(11) }
3000 else { print_int(10) }
3001 }
3002 }
3003 2 {
3004 match cf3 {
3005 2 { print_int(22) } // 22
3006 else { print_int(20) }
3007 }
3008 }
3009 else {
3010 print_int(0)
3011 }
3012 }
3013
3014 // 30.4 Loop with compound condition (&&)
3015 mut cf4 := 0
3016 mut cf4_i := 0
3017 for cf4_i < 20 && cf4 < 50 {
3018 cf4 += cf4_i
3019 cf4_i++
3020 }
3021 print_int(cf4) // 55 (0+1+2+3+4+5+6+7+8+9+10 = 55, stops when >= 50)
3022
3023 // 30.5 Return inside nested control flow
3024 print_int(nested_return(5)) // 100
3025 print_int(nested_return(15)) // 200
3026 print_int(nested_return(25)) // 300
3027
3028 // 30.6 Loop with || condition
3029 mut cf5 := 0
3030 mut cf5_i := 0
3031 for cf5_i < 3 || cf5 < 10 {
3032 cf5 += 5
3033 cf5_i++
3034 }
3035 print_int(cf5) // 15 (loop runs 3 times: 5, 10, 15 - stops when both conditions false)
3036
3037 // ==================== 31. METHODS ====================
3038 print_str('--- 31. Methods ---')
3039
3040 // 31.1 Basic method call
3041 m1 := Point{
3042 x: 10
3043 y: 20
3044 }
3045 print_int(m1.sum()) // 30
3046
3047 // 31.2 Method with multiplication
3048 m2 := Point{
3049 x: 5
3050 y: 6
3051 }
3052 print_int(m2.product()) // 30
3053
3054 // 31.3 Mutable receiver method
3055 mut m4 := Point{
3056 x: 7
3057 y: 8
3058 }
3059 m4.double()
3060 print_int(m4.x) // 14
3061 print_int(m4.y) // 16
3062
3063 // 31.4 Rectangle methods
3064 m5 := Rectangle{
3065 width: 10
3066 height: 5
3067 origin: Point{
3068 x: 0
3069 y: 0
3070 }
3071 }
3072 print_int(m5.area()) // 50
3073 print_int(m5.perimeter()) // 30
3074
3075 // 31.5 Node method
3076 m6 := Node{
3077 value: 100
3078 left: 10
3079 right: 20
3080 }
3081 print_int(m6.total()) // 130
3082
3083 // 31.6 Method on heap-allocated struct
3084 m8 := &Point{
3085 x: 4
3086 y: 5
3087 }
3088 print_int(m8.sum()) // 9
3089 print_int(m8.product()) // 20
3090
3091 // ==================== 32. IF-EXPRESSIONS ====================
3092 print_str('--- 32. If-Expressions ---')
3093
3094 // 32.1 Basic if-expression (abs)
3095 print_int(int_abs(-5)) // 5
3096 print_int(int_abs(7)) // 7
3097 print_int(int_abs(0)) // 0
3098
3099 // 32.2 If-expression for max
3100 print_int(int_max2(10, 20)) // 20
3101 print_int(int_max2(30, 15)) // 30
3102 print_int(int_max2(5, 5)) // 5
3103
3104 // 32.3 If-expression for min
3105 print_int(int_min2(10, 20)) // 10
3106 print_int(int_min2(30, 15)) // 15
3107 print_int(int_min2(8, 8)) // 8
3108
3109 // 32.4 Nested if-expression (sign)
3110 print_int(sign(-100)) // -1
3111 print_int(sign(100)) // 1
3112 print_int(sign(0)) // 0
3113
3114 // 32.5 Double nested if-expression (clamp)
3115 print_int(clamp(5, 0, 10)) // 5 (in range)
3116 print_int(clamp(-5, 0, 10)) // 0 (below lo)
3117 print_int(clamp(15, 0, 10)) // 10 (above hi)
3118
3119 // 32.6 If-expression in local variable
3120 val2 := 25
3121 result := if val2 > 20 { val2 * 2 } else { val2 }
3122 print_int(result) // 50
3123
3124 // 32.7 If-expression with complex condition
3125 a := 10
3126 b := 20
3127 c := if a < b && b < 30 { a + b } else { 0 }
3128 print_int(c) // 30
3129
3130 // ==================== 33. ARRAY INITIALIZATION ====================
3131 print_str('--- 33. Array Initialization ---')
3132
3133 // 33.1 Basic array literal
3134 arr1 := [10, 20, 30]
3135 print_int(arr1[0]) // 10
3136 print_int(arr1[1]) // 20
3137 print_int(arr1[2]) // 30
3138
3139 // 33.2 Array element sum
3140 arr2 := [5, 10, 15]
3141 arr2_sum := arr2[0] + arr2[1] + arr2[2]
3142 print_int(arr2_sum) // 30
3143
3144 // 33.3 Array with computed values
3145 base_val := 7
3146 arr3 := [base_val, base_val * 2, base_val * 3]
3147 print_int(arr3[0]) // 7
3148 print_int(arr3[1]) // 14
3149 print_int(arr3[2]) // 21
3150
3151 // 33.4 Array element in expression
3152 arr4 := [100, 200, 300]
3153 result4 := arr4[0] * 2 + arr4[1]
3154 print_int(result4) // 400
3155
3156 // 33.5 Array with function call on elements
3157 arr5 := [3, 4, 5]
3158 print_int(add(arr5[0], arr5[1])) // 7
3159 print_int(mul(arr5[1], arr5[2])) // 20
3160
3161 // ==================== 34. STRING INTERPOLATION ====================
3162 print_str('--- 34. String Interpolation ---')
3163
3164 // 34.1 Basic integer interpolation
3165 interp_x := 42
3166 s1 := 'The answer is ${interp_x}'
3167 print_str(s1) // The answer is 42
3168
3169 // 34.2 Multiple interpolations
3170 interp_a := 10
3171 interp_b := 20
3172 s2 := '${interp_a} + ${interp_b} = ${interp_a + interp_b}'
3173 print_str(s2) // 10 + 20 = 30
3174
3175 // 34.3 String at beginning and end
3176 interp_val := 100
3177 s3 := 'Value: ${interp_val}!'
3178 print_str(s3) // Value: 100!
3179
3180 // 34.4 Just interpolation (no literal parts)
3181 interp_num := 999
3182 s4 := '${interp_num}'
3183 print_str(s4) // 999
3184
3185 // 34.5 Multiple consecutive values
3186 interp_v1 := 1
3187 interp_v2 := 2
3188 interp_v3 := 3
3189 s5 := '${interp_v1}-${interp_v2}-${interp_v3}'
3190 print_str(s5) // 1-2-3
3191
3192 world := 'world'
3193 s6 := 'hello ${world}'
3194 print_str(s6)
3195
3196 // 34.6 String concatenation with + operator
3197 str_a := 'Hello'
3198 str_b := ' World'
3199 str_c := str_a + str_b
3200 print_str(str_c) // Hello World
3201
3202 // 34.7 Chained string concatenation
3203 str_chain := 'A' + 'B' + 'C'
3204 print_str(str_chain) // ABC
3205
3206 // ==================== 35. IF-GUARD EXPRESSIONS ====================
3207 print_str('--- 35. If-Guard Expressions ---')
3208
3209 // 35.1 Basic if-guard with success (positive value)
3210 if g1_val := maybe_positive(42) {
3211 print_int(g1_val) // 42
3212 } else {
3213 print_int(0)
3214 }
3215
3216 // 35.2 If-guard with failure (non-positive value)
3217 if g2_val := maybe_positive(-5) {
3218 print_int(g2_val)
3219 } else {
3220 print_int(999) // 999 (else branch taken)
3221 }
3222
3223 // 35.3 If-guard with computation in then branch
3224 if g3_val := maybe_double(25) {
3225 print_int(g3_val + 10) // 50 + 10 = 60
3226 } else {
3227 print_int(0)
3228 }
3229
3230 // 35.4 If-guard with function call
3231 if g4_result := maybe_sum(10, 20) {
3232 print_int(g4_result) // 30
3233 } else {
3234 print_int(0)
3235 }
3236
3237 // 35.5 Nested if with if-guard
3238 g5_outer := 5
3239 if g5_outer > 0 {
3240 if g5_inner := maybe_positive(g5_outer * 10) {
3241 print_int(g5_inner) // 50
3242 } else {
3243 print_int(0)
3244 }
3245 }
3246
3247 // 35.6 If-guard in sequence
3248 mut g6_sum := 0
3249 if g6_a := maybe_positive(10) {
3250 g6_sum += g6_a
3251 }
3252 if g6_b := maybe_positive(20) {
3253 g6_sum += g6_b
3254 }
3255 if g6_c := maybe_positive(-5) {
3256 g6_sum += g6_c
3257 }
3258 print_int(g6_sum) // 10 + 20 + 0 = 30
3259
3260 // 35.7 If-guard with else-if chain
3261 g7_test := 100
3262 if g7_val := maybe_positive(-g7_test) {
3263 print_int(g7_val)
3264 } else {
3265 if g7_val2 := maybe_positive(g7_test) {
3266 print_int(g7_val2) // 100
3267 } else {
3268 print_int(0)
3269 }
3270 }
3271
3272 // 35.8 or { return } pattern with value
3273 if or_val := maybe_triple(5) {
3274 print_int(or_val) // 15 (5 * 3)
3275 } else {
3276 print_int(-1)
3277 }
3278
3279 // 35.9 or { return } pattern with negative (returns none)
3280 if or_val2 := maybe_triple(-5) {
3281 print_int(or_val2)
3282 } else {
3283 print_int(0) // 0 (none case)
3284 }
3285
3286 // 35.10 Direct or { value } pattern - successful call
3287 or_direct1 := maybe_positive(42) or { 0 }
3288 print_int(or_direct1) // 42
3289
3290 // 35.11 Direct or { value } pattern - fallback used
3291 or_direct2 := maybe_positive(-10) or { 99 }
3292 print_int(or_direct2) // 99
3293
3294 // 35.12 Chained or { value } with computation
3295 or_chain := maybe_double(25) or { 0 }
3296 print_int(or_chain + 5) // 50 + 5 = 55
3297
3298 // 35.13 Result or { err } pattern - ensure `err` is available in scope
3299 or_err := maybe_fail(-1) or {
3300 print_str('error')
3301 0
3302 }
3303 print_int(or_err) // 0
3304
3305 // ==================== 36. RANGE EXPRESSIONS ====================
3306 print_str('--- 36. Range Expressions ---')
3307
3308 // 36.1 Basic array slicing with range
3309 rng_arr1 := [10, 20, 30, 40, 50]
3310 rng_slice1 := rng_arr1[1..4]
3311 print_int(rng_slice1[0]) // 20
3312 print_int(rng_slice1[1]) // 30
3313 print_int(rng_slice1[2]) // 40
3314
3315 // 36.2 Range from start
3316 rng_arr2 := [100, 200, 300, 400]
3317 rng_slice2 := rng_arr2[0..2]
3318 print_int(rng_slice2[0]) // 100
3319 print_int(rng_slice2[1]) // 200
3320
3321 // 36.3 Range with variable indices
3322 rng_start := 1
3323 rng_end := 3
3324 rng_arr3 := [5, 10, 15, 20, 25]
3325 rng_slice3 := rng_arr3[rng_start..rng_end]
3326 print_int(rng_slice3[0]) // 10
3327 print_int(rng_slice3[1]) // 15
3328
3329 // 36.4 Consecutive slicing
3330 rng_arr4 := [1, 2, 3, 4, 5, 6, 7, 8]
3331 rng_first_half := rng_arr4[0..4]
3332 rng_second_half := rng_arr4[4..8]
3333 print_int(rng_first_half[0]) // 1
3334 print_int(rng_first_half[3]) // 4
3335 print_int(rng_second_half[0]) // 5
3336 print_int(rng_second_half[3]) // 8
3337
3338 // 36.5 Single element range
3339 rng_arr5 := [42, 84, 126]
3340 rng_single := rng_arr5[1..2]
3341 print_int(rng_single[0]) // 84
3342
3343 // ==================== 37. FOR-IN RANGE ====================
3344 print_str('--- 37. For-In Range ---')
3345
3346 // 37.1 Basic for-in range
3347 mut forin_sum1 := 0
3348 for i in 0 .. 5 {
3349 forin_sum1 += i
3350 }
3351 print_int(forin_sum1) // 0+1+2+3+4 = 10
3352
3353 // 37.2 For-in range with non-zero start
3354 mut forin_sum2 := 0
3355 for i in 5 .. 10 {
3356 forin_sum2 += i
3357 }
3358 print_int(forin_sum2) // 5+6+7+8+9 = 35
3359
3360 // 37.3 For-in range with expressions
3361 forin_start := 2
3362 forin_end := 6
3363 mut forin_sum3 := 0
3364 for i in forin_start .. forin_end {
3365 forin_sum3 += i
3366 }
3367 print_int(forin_sum3) // 2+3+4+5 = 14
3368
3369 // 37.4 Nested for-in ranges
3370 mut forin_count := 0
3371 for i in 0 .. 3 {
3372 for j in 0 .. 4 {
3373 forin_count += i + j + 1
3374 }
3375 }
3376 print_int(forin_count) // sum of (i+j+1) for i in 0..3, j in 0..4 = 42
3377
3378 // 37.5 For-in range with computation in body
3379 mut forin_product := 1
3380 for i in 1 .. 6 {
3381 forin_product *= i
3382 }
3383 print_int(forin_product) // 1*2*3*4*5 = 120
3384
3385 // 37.6 For-in range with break
3386 mut forin_sum4 := 0
3387 for i in 0 .. 100 {
3388 if i >= 5 {
3389 break
3390 }
3391 forin_sum4 += i
3392 }
3393 print_int(forin_sum4) // 0+1+2+3+4 = 10
3394
3395 // 37.7 For-in range with continue
3396 mut forin_sum5 := 0
3397 for i in 0 .. 10 {
3398 if i % 2 == 0 {
3399 continue
3400 }
3401 forin_sum5 += i
3402 }
3403 print_int(forin_sum5) // 1+3+5+7+9 = 25
3404
3405 // ==================== 38. DEFER STATEMENTS ====================
3406 print_str('--- 38. Defer Statements ---')
3407
3408 // 38.1 Basic defer (should print after the other prints)
3409 g_val = 0
3410 defer {
3411 g_val += 100
3412 }
3413 g_val += 1
3414 print_int(g_val) // 1 (defer not executed yet, will be 101 at function end)
3415
3416 // 38.2 Multiple defers execute in reverse order (LIFO)
3417 g_count = 0
3418 defer {
3419 g_count += 1
3420 }
3421 defer {
3422 g_count += 10
3423 }
3424 defer {
3425 g_count += 100
3426 }
3427 // At end of function: g_count = 0 + 100 + 10 + 1 = 111
3428
3429 // 38.3 Defer with function call
3430 defer {
3431 print_str('Defer 38.3 executed')
3432 }
3433 // 38.4 Test defer_test function with explicit return
3434 print_int(defer_test()) // Should print 42
3435
3436 // 38.5 Test defer order in function
3437 defer_order_test() // Should print: Third, Second, First
3438
3439 // 38.6 Test defer(fn) - function-level defer
3440 print_int(defer_fn_test()) // 303 (3 from loop + 300 from function-level defers)
3441
3442 // 38.7 Test flag enum .has() and .all() methods
3443 print_str('enum vals (exp 421):')
3444 print_int(flag_enum_values()) // Expected: 421 (1 + 20 + 400)
3445 print_str('AND test (exp 0):')
3446 print_int(flag_enum_and_test()) // Expected: 0 (3 & 4 = 0)
3447 print_str('manual has (exp 0):')
3448 print_int(flag_enum_manual_has()) // Expected: 0 (manual has check)
3449 print_str('flag debug (exp 3):')
3450 print_int(flag_enum_debug()) // Expected: 3 (read=1 | write=2)
3451 print_str('has read (exp 1):')
3452 print_int(flag_enum_has_read()) // Expected: 1
3453 print_str('has exec (exp 0):')
3454 print_int(flag_enum_has_execute()) // Expected: 0
3455 print_str('has result (exp 0):')
3456 print_int(flag_enum_has_result()) // Expected: 0 (direct bool->int)
3457 print_str('manual call (exp 0):')
3458 print_int(flag_enum_manual_call()) // Expected: 0 (manual has impl)
3459 print_str('check args (exp 304):')
3460 print_int(flag_enum_check_args()) // Expected: 304 (perms=3, exec=4)
3461 print_str('int args (exp 304):')
3462 print_int(flag_enum_check_int_args()) // Expected: 304
3463 print_str('keyword flag field (exp 3):')
3464 print_int(flag_enum_keyword_field()) // Expected: 3 (read=1 | unsigned=2)
3465 print_str('full test (exp 13):')
3466 print_int(flag_enum_test()) // Expected: 13 (1 + 2 + 10)
3467
3468 // ==================== 39. ENUMS ====================
3469 print_str('--- 39. Enums ---')
3470
3471 // 39.1 Basic enum value
3472 color1 := Color.red
3473 print_int(int(color1)) // 0
3474
3475 // 39.2 Other enum values
3476 color2 := Color.green
3477 color3 := Color.blue
3478 print_int(int(color2)) // 1
3479 print_int(int(color3)) // 2
3480
3481 // 39.3 Enum with explicit values
3482 status1 := Status.pending
3483 status2 := Status.active
3484 status3 := Status.done
3485 print_int(int(status1)) // 0
3486 print_int(int(status2)) // 1
3487 print_int(int(status3)) // 2
3488
3489 // 39.4 Enum in match
3490 match color1 {
3491 .red { print_int(100) } // 100
3492 .green { print_int(200) }
3493 .blue { print_int(300) }
3494 else { print_int(0) }
3495 }
3496
3497 // 39.5 Enum comparison
3498 if color1 == Color.red {
3499 print_int(1) // 1
3500 } else {
3501 print_int(0)
3502 }
3503
3504 // ==================== 40. FOR-IN ARRAY ====================
3505 print_str('--- 40. For-In Array ---')
3506
3507 // 40.1 Basic for-in array iteration
3508 arr_iter1 := [10, 20, 30]
3509 mut sum_iter1 := 0
3510 for elem in arr_iter1 {
3511 sum_iter1 += elem
3512 }
3513 print_int(sum_iter1) // 60
3514
3515 // 40.2 For-in with index
3516 arr_iter2 := [5, 10, 15]
3517 mut weighted_sum2 := 0
3518 for i, elem in arr_iter2 {
3519 weighted_sum2 += (i + 1) * elem
3520 }
3521 print_int(weighted_sum2) // 1*5 + 2*10 + 3*15 = 70
3522
3523 // 40.3 For-in with break
3524 arr_iter3 := [1, 2, 3, 4, 5]
3525 mut sum_iter3 := 0
3526 for elem in arr_iter3 {
3527 if elem > 3 {
3528 break
3529 }
3530 sum_iter3 += elem
3531 }
3532 print_int(sum_iter3) // 1+2+3 = 6
3533
3534 // 40.4 For-in with continue
3535 arr_iter4 := [1, 2, 3, 4, 5]
3536 mut sum_iter4 := 0
3537 for elem in arr_iter4 {
3538 if elem % 2 == 0 {
3539 continue
3540 }
3541 sum_iter4 += elem
3542 }
3543 print_int(sum_iter4) // 1+3+5 = 9
3544
3545 // 40.5 While-style for with in condition
3546 whitespace_loop_chars := [` `, `\t`, `\n`, `\r`]
3547 whitespace_loop_text := ' x'
3548 mut whitespace_loop_idx := 0
3549 for whitespace_loop_text[whitespace_loop_idx] in whitespace_loop_chars {
3550 whitespace_loop_idx++
3551 }
3552 print_int(whitespace_loop_idx) // 3
3553
3554 // 40.6 Nested for-in
3555 arr_outer := [1, 2, 3]
3556 arr_inner := [10, 20]
3557 mut nested_sum := 0
3558 for outer in arr_outer {
3559 for inner in arr_inner {
3560 nested_sum += outer * inner
3561 }
3562 }
3563 print_int(nested_sum) // (1*10+1*20) + (2*10+2*20) + (3*10+3*20) = 30+60+90 = 180
3564
3565 // ==================== 41. FIXED SIZE ARRAYS ====================
3566 print_str('--- 41. Fixed Size Arrays ---')
3567
3568 // 41.1 Fixed array with literal initialization
3569 fixed_arr1 := [5, 10, 15]
3570 print_int(fixed_arr1[0]) // 5
3571 print_int(fixed_arr1[1]) // 10
3572 print_int(fixed_arr1[2]) // 15
3573
3574 // 41.2 Fixed array with computed index
3575 idx := 1
3576 print_int(fixed_arr1[idx]) // 10
3577
3578 // 41.3 Fixed array sum
3579 mut fixed_sum := 0
3580 for elem in fixed_arr1 {
3581 fixed_sum += elem
3582 }
3583 print_int(fixed_sum) // 30
3584
3585 // 41.4 Fixed array with larger size
3586 fixed_arr2 := [1, 2, 3, 4, 5]
3587 mut fixed_product := 1
3588 for elem in fixed_arr2 {
3589 fixed_product *= elem
3590 }
3591 print_int(fixed_product) // 120
3592
3593 // 41.5 Nested fixed arrays access
3594 fixed_outer := [100, 200, 300]
3595 fixed_inner := [1, 2, 3]
3596 print_int(fixed_outer[0] + fixed_inner[2]) // 103
3597
3598 // 41.6 Fixed array with ! literal syntax (explicit fixed size)
3599 fixed_literal := [1, 2, 3, 4, 5]!
3600 print_int(fixed_literal[0]) // 1
3601 print_int(fixed_literal[4]) // 5
3602
3603 // 41.7 Fixed array .len access
3604 print_int(fixed_literal.len) // 5
3605
3606 // 41.8 Fixed array iteration with ! syntax
3607 mut fixed_literal_sum := 0
3608 for elem in fixed_literal {
3609 fixed_literal_sum += elem
3610 }
3611 print_int(fixed_literal_sum) // 15
3612
3613 // 41.9 Fixed array of u8 with ! syntax
3614 bytes := [u8(65), 66, 67]!
3615 print_int(bytes[0]) // 65 (ASCII 'A')
3616 print_int(bytes.len) // 3
3617
3618 // ==================== 42. INTERFACE IMPLEMENTATION ====================
3619 print_str('--- 42. Interface Implementation ---')
3620
3621 // 42.1 Call draw() method directly on Point (implements Drawable)
3622 draw_pt1 := Point{
3623 x: 5
3624 y: 10
3625 }
3626 print_int(draw_pt1.draw()) // 5*1000 + 10 = 5010
3627
3628 // 42.2 Another point with draw
3629 draw_pt2 := Point{
3630 x: 12
3631 y: 34
3632 }
3633 print_int(draw_pt2.draw()) // 12*1000 + 34 = 12034
3634
3635 // 42.3 Interface method on zero-init struct
3636 draw_pt3 := Point{}
3637 print_int(draw_pt3.draw()) // 0*1000 + 0 = 0
3638
3639 // 42.4 Interface method with heap-allocated struct
3640 draw_pt4 := &Point{
3641 x: 100
3642 y: 200
3643 }
3644 print_int(draw_pt4.draw()) // 100*1000 + 200 = 100200
3645
3646 // 42.5 Multiple interface method calls
3647 mut draw_total := 0
3648 draw_a := Point{
3649 x: 1
3650 y: 2
3651 }
3652 draw_b := Point{
3653 x: 3
3654 y: 4
3655 }
3656 draw_total += draw_a.draw() // 1002
3657 draw_total += draw_b.draw() // 3004
3658 print_int(draw_total) // 4006
3659
3660 // ==================== 43. TYPE ALIAS USAGE ====================
3661 print_str('--- 43. Type Alias Usage ---')
3662
3663 // 43.1 Basic type alias (MyInt is typedef'd to int)
3664 my_a := 10
3665 my_b := 20
3666 print_int(my_a + my_b) // 30
3667
3668 // 43.2 Type alias in function
3669 my_result := add_my_ints(15, 25)
3670 print_int(my_result) // 40
3671
3672 // 43.3 Type alias with arithmetic
3673 my_c := 100
3674 my_d := my_c * 3
3675 print_int(my_d) // 300
3676
3677 // 43.4 Type alias comparison
3678 my_e := 50
3679 my_f := 50
3680 if my_e == my_f {
3681 print_int(1) // 1
3682 } else {
3683 print_int(0)
3684 }
3685
3686 // 43.5 Type alias in loop
3687 mut my_sum := 0
3688 for i in 1 .. 6 {
3689 my_sum += i
3690 }
3691 print_int(my_sum) // 1+2+3+4+5 = 15
3692
3693 // ==================== 44. COMPTIME ====================
3694 print_str('--- 44. Comptime ---')
3695
3696 // 44.1 Basic $if macos/$else
3697 $if macos {
3698 print_int(1) // 1 on macOS
3699 } $else {
3700 print_int(0) // 0 on other platforms
3701 }
3702
3703 // 44.2 $if linux
3704 $if linux {
3705 print_int(2) // 2 on Linux
3706 } $else {
3707 print_int(20) // 20 on non-Linux
3708 }
3709
3710 // 44.3 $if windows
3711 $if windows {
3712 print_int(3) // 3 on Windows
3713 } $else {
3714 print_int(30) // 30 on non-Windows
3715 }
3716
3717 // 44.4 Negation: $if !windows
3718 $if !windows {
3719 print_int(4) // 4 on non-Windows
3720 } $else {
3721 print_int(40) // 40 on Windows
3722 }
3723
3724 // 44.5 Comptime in function call
3725 print_int(get_comptime_value())
3726
3727 // ==================== 45. STRING STRUCT FIELDS ====================
3728 print_str('--- 45. String Struct Fields ---')
3729
3730 // 45.1 String literal .str field
3731 s45_1 := 'Hello'
3732 print_str(s45_1) // Hello
3733
3734 // 45.2 String literal .len field
3735 s45_2 := 'World'
3736 print_int(s45_2.len) // 5
3737
3738 // 45.3 Interpolated string .len field
3739 val45 := 123
3740 s45_3 := 'Val: ${val45}'
3741 print_int(s45_3.len) // 8
3742
3743 // 45.4 Multiple string operations
3744 a45 := 'AB'
3745 b45 := 'CDE'
3746 print_int(a45.len + b45.len) // 5
3747
3748 // 45.5 String in function parameter
3749 print_str('Passed directly') // Passed directly
3750
3751 // ==================== 46. UNSAFE EXPRESSIONS ====================
3752 print_str('--- 46. Unsafe Expressions ---')
3753
3754 // 46.1 Basic unsafe block returning value
3755 unsafe_val1 := unsafe {
3756 42
3757 }
3758 print_int(unsafe_val1) // 42
3759
3760 // 46.2 Unsafe block with computation
3761 unsafe_val2 := unsafe {
3762 10 + 20 + 30
3763 }
3764 print_int(unsafe_val2) // 60
3765
3766 // 46.3 Unsafe block with variable access
3767 base_for_unsafe := 100
3768 unsafe_val3 := unsafe {
3769 base_for_unsafe * 2
3770 }
3771 print_int(unsafe_val3) // 200
3772
3773 // 46.4 Unsafe block in expression context
3774 result_unsafe := unsafe { 7 } * unsafe { 8 }
3775 print_int(result_unsafe) // 56
3776
3777 // 46.5 Unsafe with struct field access
3778 unsafe_pt := Point{
3779 x: 15
3780 y: 25
3781 }
3782 unsafe_sum := unsafe {
3783 unsafe_pt.x + unsafe_pt.y
3784 }
3785 print_int(unsafe_sum) // 40
3786
3787 // ==================== 47. INTERFACE VTABLE ====================
3788 print_str('--- 47. Interface Vtable ---')
3789
3790 // 47.1 Basic interface assignment and method call
3791 vtable_pt1 := Point{
3792 x: 7
3793 y: 3
3794 }
3795 d1 := Drawable(vtable_pt1)
3796 print_int(d1.draw()) // 7*1000 + 3 = 7003
3797
3798 // 47.2 Interface with different values
3799 vtable_pt2 := Point{
3800 x: 15
3801 y: 25
3802 }
3803 d2 := Drawable(vtable_pt2)
3804 print_int(d2.draw()) // 15*1000 + 25 = 15025
3805
3806 // 47.3 Multiple interface calls
3807 vtable_pt3 := Point{
3808 x: 1
3809 y: 1
3810 }
3811 d3 := Drawable(vtable_pt3)
3812 print_int(d3.draw() + d3.draw()) // 1001 + 1001 = 2002
3813
3814 // 47.4 Shape interface with multiple methods
3815 shape_rect := Rectangle{
3816 width: 10
3817 height: 5
3818 origin: Point{
3819 x: 0
3820 y: 0
3821 }
3822 }
3823 shape1 := Shape(shape_rect)
3824 print_int(shape1.area()) // 10 * 5 = 50
3825 print_int(shape1.perimeter()) // 2 * (10 + 5) = 30
3826
3827 // 47.5 Sum of interface method results
3828 vtable_pt4 := Point{
3829 x: 2
3830 y: 3
3831 }
3832 d4 := Drawable(vtable_pt4)
3833 vtable_pt5 := Point{
3834 x: 4
3835 y: 5
3836 }
3837 d5 := Drawable(vtable_pt5)
3838 print_int(d4.draw() + d5.draw()) // 2003 + 4005 = 6008
3839
3840 // 47.6 Calculator interface with parameters
3841 calc_pt := Point{
3842 x: 10
3843 y: 5
3844 }
3845 calc := Calculator(calc_pt)
3846 print_int(calc.add(3, 7)) // 10 + 5 + 3 + 7 = 25
3847 print_int(calc.multiply(4)) // (10 + 5) * 4 = 60
3848
3849 // 47.7 Multiple Calculator calls
3850 calc_pt2 := Point{
3851 x: 2
3852 y: 3
3853 }
3854 calc2 := Calculator(calc_pt2)
3855 print_int(calc2.add(1, 1)) // 2 + 3 + 1 + 1 = 7
3856 print_int(calc2.multiply(10)) // (2 + 3) * 10 = 50
3857
3858 // ==================== 48. STRUCT FIELD OPERATIONS ====================
3859 print_str('--- 48. Struct Field Operations ---')
3860
3861 // 48.1 Basic field assignment with arithmetic
3862 mut sf1 := Point{
3863 x: 10
3864 y: 20
3865 }
3866 sf1.x = sf1.x + 5
3867 sf1.y = sf1.y - 3
3868 print_int(sf1.x) // 15
3869 print_int(sf1.y) // 17
3870
3871 // 48.2 Field multiplication and division
3872 mut sf2 := Point{
3873 x: 6
3874 y: 100
3875 }
3876 sf2.x = sf2.x * 7
3877 sf2.y = sf2.y / 4
3878 print_int(sf2.x) // 42
3879 print_int(sf2.y) // 25
3880
3881 // 48.3 Compound assignment on fields
3882 mut sf3 := Point{
3883 x: 50
3884 y: 30
3885 }
3886 sf3.x += 25
3887 sf3.y -= 10
3888 print_int(sf3.x) // 75
3889 print_int(sf3.y) // 20
3890
3891 // 48.4 Compound multiply/divide on fields
3892 mut sf4 := Point{
3893 x: 8
3894 y: 64
3895 }
3896 sf4.x *= 5
3897 sf4.y /= 8
3898 print_int(sf4.x) // 40
3899 print_int(sf4.y) // 8
3900
3901 // 48.5 Field used in expression with other field
3902 mut sf5 := Point{
3903 x: 3
3904 y: 4
3905 }
3906 sf5.x = sf5.x + sf5.y
3907 sf5.y = sf5.x * sf5.y
3908 print_int(sf5.x) // 7 (3+4)
3909 print_int(sf5.y) // 28 (7*4)
3910
3911 // 48.6 Chained field operations
3912 mut sf6 := Point{
3913 x: 2
3914 y: 3
3915 }
3916 sf6.x = sf6.x * 2
3917 sf6.x = sf6.x + 1
3918 sf6.x = sf6.x * 3
3919 sf6.y = sf6.y + sf6.x
3920 print_int(sf6.x) // 15 ((2*2+1)*3)
3921 print_int(sf6.y) // 18 (3+15)
3922
3923 // 48.7 Field modulo operation
3924 mut sf7 := Point{
3925 x: 17
3926 y: 23
3927 }
3928 sf7.x = sf7.x % 5
3929 sf7.y = sf7.y % 7
3930 print_int(sf7.x) // 2
3931 print_int(sf7.y) // 2
3932
3933 // 48.8 Field bitwise operations
3934 mut sf8 := Point{
3935 x: 0b1100
3936 y: 0b1010
3937 }
3938 sf8.x = sf8.x & sf8.y
3939 sf8.y = sf8.x | 0b0101
3940 print_int(sf8.x) // 8 (0b1000)
3941 print_int(sf8.y) // 13 (0b1101)
3942
3943 // 48.9 Field with function call result
3944 mut sf9 := Point{
3945 x: 5
3946 y: 10
3947 }
3948 sf9.x = add(sf9.x, sf9.y)
3949 sf9.y = mul(sf9.x, 2)
3950 print_int(sf9.x) // 15
3951 print_int(sf9.y) // 30
3952
3953 // 48.10 Nested struct field modification
3954 mut rect_mod := Rectangle{
3955 width: 10
3956 height: 20
3957 origin: Point{
3958 x: 0
3959 y: 0
3960 }
3961 }
3962 rect_mod.width = rect_mod.width * 2
3963 rect_mod.height += 5
3964 rect_mod.origin.x = 100
3965 rect_mod.origin.y = rect_mod.origin.x / 2
3966 print_int(rect_mod.width) // 20
3967 print_int(rect_mod.height) // 25
3968 print_int(rect_mod.origin.x) // 100
3969 print_int(rect_mod.origin.y) // 50
3970
3971 // ==================== 49. PRINTLN ====================
3972 print_str('--- 49. Println ---')
3973
3974 // 49.1 Test println
3975 println('hello world')
3976
3977 // ==================== 50. ALGEBRAIC OPTIMIZATIONS ====================
3978 print_str('--- 50. Algebraic Optimizations ---')
3979
3980 // 50.1 x - x = 0
3981 opt_val := 42
3982 print_int(opt_val - opt_val) // 0
3983
3984 // 50.2 x ^ x = 0
3985 opt_xor := 123
3986 print_int(opt_xor ^ opt_xor) // 0
3987
3988 // 50.3 x & x = x
3989 opt_and := 99
3990 print_int(opt_and & opt_and) // 99
3991
3992 // 50.4 x | x = x
3993 opt_or := 77
3994 print_int(opt_or | opt_or) // 77
3995
3996 // 50.5 x * 2 = x << 1
3997 opt_mul2 := 25
3998 print_int(opt_mul2 * 2) // 50
3999
4000 // 50.6 Combined optimizations
4001 opt_a := 10
4002 opt_b := opt_a - opt_a // Should be 0
4003 opt_c := opt_a | opt_a // Should be 10
4004 print_int(opt_b) // 0
4005 print_int(opt_c) // 10
4006
4007 // 50.7 2 * x = x << 1 (commutative)
4008 opt_mul2_comm := 13
4009 print_int(2 * opt_mul2_comm) // 26
4010
4011 // 50.8 Algebraic opts in expressions
4012 opt_expr := 7
4013 print_int((opt_expr ^ opt_expr) + 5) // 0 + 5 = 5
4014 print_int((opt_expr & opt_expr) * 2) // 7 * 2 = 14
4015
4016 // 50.9 Algebraic opts with different values
4017 opt_large := 12345
4018 print_int(opt_large - opt_large) // 0
4019 print_int(opt_large ^ opt_large) // 0
4020 print_int(opt_large & opt_large) // 12345
4021 print_int(opt_large | opt_large) // 12345
4022
4023 // 50.10 Algebraic opts in loop
4024 mut opt_loop_sum := 0
4025 for i in 1 .. 5 {
4026 opt_loop_sum += i - i // Should add 0 each iteration
4027 opt_loop_sum += i & i // Should add i each iteration
4028 }
4029 print_int(opt_loop_sum) // 0+1 + 0+2 + 0+3 + 0+4 = 10
4030
4031 // ==================== 51. DEAD STORE ELIMINATION ====================
4032 print_str('--- 51. Dead Store Elimination ---')
4033
4034 // 51.1 Basic dead store - local var never read
4035 // The optimizer should remove stores to variables that are never used
4036 {
4037 mut dead_var := 100
4038 dead_var = 200 // dead store, never read
4039 _ = dead_var
4040 }
4041 print_int(1) // 1 - verify execution continues
4042
4043 // 51.2 Dead store with live store after
4044 mut dse_var := 10
4045 dse_var = 20 // dead store (overwritten before read)
4046 dse_var = 30 // this is the live store
4047 print_int(dse_var) // 30
4048
4049 // 51.3 Multiple dead stores
4050 mut dse_multi := 1
4051 dse_multi = 2 // dead
4052 dse_multi = 3 // dead
4053 dse_multi = 4 // dead
4054 dse_multi = 5 // live
4055 print_int(dse_multi) // 5
4056
4057 // 51.4 Dead store in branch not taken
4058 mut dse_branch := 100