Skip to content

Commit a60b557

Browse files
authored
fix: refactor if-statement codegen and enhance test runner (#257)
1 parent 78c2179 commit a60b557

File tree

3 files changed

+101
-37
lines changed

3 files changed

+101
-37
lines changed

.github/FUNDING.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
github: [LunaStev]
2-
custom: [https://www.lunastev.org/ko/sponsor]

llvm_temporary/src/llvm_temporary/statement.rs

Lines changed: 72 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ pub fn generate_statement_ir<'ctx>(
575575
}) => {
576576
let current_fn = builder.get_insert_block().unwrap().get_parent().unwrap();
577577

578-
let cond_value = generate_expression_ir(
578+
let cond_any = generate_expression_ir(
579579
context,
580580
builder,
581581
condition,
@@ -587,15 +587,32 @@ pub fn generate_statement_ir<'ctx>(
587587
struct_field_indices,
588588
);
589589

590+
let cond_i1 = match cond_any {
591+
BasicValueEnum::IntValue(iv) => {
592+
if iv.get_type().get_bit_width() == 1 {
593+
iv
594+
} else {
595+
let zero = iv.get_type().const_zero();
596+
builder.build_int_compare(inkwell::IntPredicate::NE, iv, zero, "if_cond").unwrap()
597+
}
598+
}
599+
BasicValueEnum::FloatValue(fv) => {
600+
let zero = fv.get_type().const_float(0.0);
601+
builder.build_float_compare(inkwell::FloatPredicate::ONE, fv, zero, "if_cond").unwrap()
602+
}
603+
BasicValueEnum::PointerValue(pv) => builder.build_is_not_null(pv, "if_cond").unwrap(),
604+
_ => panic!("Unsupported if condition type"),
605+
};
606+
590607
let then_block = context.append_basic_block(current_fn, "then");
591608
let else_block_bb = context.append_basic_block(current_fn, "else");
592609
let merge_block = context.append_basic_block(current_fn, "merge");
593610

594611
let _ = builder.build_conditional_branch(
595-
cond_value.try_into().unwrap(),
612+
cond_i1,
596613
then_block,
597614
else_block_bb,
598-
);
615+
).unwrap();
599616

600617
// ---- then block ----
601618
builder.position_at_end(then_block);
@@ -615,19 +632,20 @@ pub fn generate_statement_ir<'ctx>(
615632
struct_field_indices,
616633
);
617634
}
618-
let then_has_terminator = then_block.get_terminator().is_some();
619-
if !then_has_terminator {
620-
let _ = builder.build_unconditional_branch(merge_block);
635+
636+
let then_end = builder.get_insert_block().unwrap();
637+
if then_end.get_terminator().is_none() {
638+
builder.build_unconditional_branch(merge_block).unwrap();
621639
}
622640

623-
// ---- else block ----
624-
builder.position_at_end(else_block_bb);
641+
let _ = builder.position_at_end(else_block_bb);
642+
let mut current_check_bb = else_block_bb;
625643

626-
let else_has_terminator = if let Some(else_ifs) = else_if_blocks {
627-
let mut current_bb = else_block_bb;
644+
if let Some(else_ifs) = else_if_blocks {
628645
for (else_if_cond, else_if_body) in else_ifs.iter() {
629-
let current_fn = builder.get_insert_block().unwrap().get_parent().unwrap();
630-
let cond_value = generate_expression_ir(
646+
builder.position_at_end(current_check_bb);
647+
648+
let c_any = generate_expression_ir(
631649
context,
632650
builder,
633651
else_if_cond,
@@ -638,13 +656,30 @@ pub fn generate_statement_ir<'ctx>(
638656
&struct_types,
639657
struct_field_indices,
640658
);
659+
let c_i1 = match c_any {
660+
BasicValueEnum::IntValue(iv) => {
661+
if iv.get_type().get_bit_width() == 1 { iv } else {
662+
let zero = iv.get_type().const_zero();
663+
builder.build_int_compare(inkwell::IntPredicate::NE, iv, zero, "elif_cond").unwrap()
664+
}
665+
}
666+
BasicValueEnum::FloatValue(fv) => {
667+
let zero = fv.get_type().const_float(0.0);
668+
builder.build_float_compare(inkwell::FloatPredicate::ONE, fv, zero, "elif_cond").unwrap()
669+
}
670+
BasicValueEnum::PointerValue(pv) => builder.build_is_not_null(pv, "elif_cond").unwrap(),
671+
_ => panic!("Unsupported else-if condition type"),
672+
};
673+
641674
let then_bb = context.append_basic_block(current_fn, "else_if_then");
642675
let next_check_bb = context.append_basic_block(current_fn, "next_else_if");
676+
643677
let _ = builder.build_conditional_branch(
644-
cond_value.try_into().unwrap(),
678+
c_i1,
645679
then_bb,
646680
next_check_bb,
647-
);
681+
).unwrap();
682+
648683
builder.position_at_end(then_bb);
649684
for stmt in else_if_body {
650685
generate_statement_ir(
@@ -662,13 +697,17 @@ pub fn generate_statement_ir<'ctx>(
662697
struct_field_indices,
663698
);
664699
}
665-
if then_bb.get_terminator().is_none() {
700+
701+
let end_bb = builder.get_insert_block().unwrap();
702+
if end_bb.get_terminator().is_none() {
666703
let _ = builder.build_unconditional_branch(merge_block);
667704
}
668-
builder.position_at_end(next_check_bb);
669-
current_bb = next_check_bb;
705+
706+
current_check_bb = next_check_bb;
670707
}
671708

709+
builder.position_at_end(current_check_bb);
710+
672711
// === FIX: Generate else_block after else_if blocks ===
673712
if let Some(else_body) = else_block {
674713
for stmt in else_body.iter() {
@@ -687,11 +726,18 @@ pub fn generate_statement_ir<'ctx>(
687726
struct_field_indices,
688727
);
689728
}
690-
current_bb.get_terminator().is_some()
691-
} else {
692-
current_bb.get_terminator().is_some()
693729
}
694-
} else if let Some(else_body) = else_block {
730+
let else_end = builder.get_insert_block().unwrap();
731+
if else_end.get_terminator().is_none() {
732+
builder.build_unconditional_branch(merge_block).unwrap();
733+
}
734+
735+
builder.position_at_end(merge_block);
736+
}
737+
738+
builder.position_at_end(current_check_bb);
739+
740+
if let Some(else_body) = else_block.as_deref() {
695741
for stmt in else_body.iter() {
696742
generate_statement_ir(
697743
context,
@@ -708,18 +754,14 @@ pub fn generate_statement_ir<'ctx>(
708754
struct_field_indices,
709755
);
710756
}
711-
else_block_bb.get_terminator().is_some()
712-
} else {
713-
false
714-
};
715-
716-
if !else_has_terminator {
717-
let _ = builder.build_unconditional_branch(merge_block);
718757
}
719758

720-
if !then_has_terminator || !else_has_terminator {
721-
builder.position_at_end(merge_block);
759+
let else_end = builder.get_insert_block().unwrap();
760+
if else_end.get_terminator().is_none() {
761+
builder.build_unconditional_branch(merge_block).unwrap();
722762
}
763+
764+
builder.position_at_end(merge_block);
723765
}
724766
ASTNode::Statement(StatementNode::While { condition, body }) => {
725767
let current_fn = builder.get_insert_block().unwrap().get_parent().unwrap();

tools/run_tests.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import subprocess
33
import time
44
from pathlib import Path
5+
import threading
6+
import socket
57

68
ROOT = Path(__file__).resolve().parent.parent
79
TEST_DIR = ROOT / "test"
@@ -13,18 +15,33 @@
1315
RED = "\033[91m"
1416
YELLOW = "\033[93m"
1517
BLUE = "\033[94m"
18+
CYAN = "\033[96m"
1619
RESET = "\033[0m"
1720

21+
KNOWN_TIMEOUT = {
22+
"test22.wave", # input() not implemented
23+
}
24+
1825
if not WAVEC.exists():
1926
print("wavec not found. Run `cargo build --release` first.")
2027
exit(1)
2128

2229
results = []
2330

31+
def send_udp_for_test61():
32+
time.sleep(0.5)
33+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
34+
sock.sendto(b"hello from python\n", ("127.0.0.1", 8080))
35+
sock.close()
36+
2437
def run_and_classify(name, cmd):
2538
print(f"{BLUE}RUN {name}{RESET}")
2639

2740
try:
41+
if name == "test61.wave":
42+
t = threading.Thread(target=send_udp_for_test61, daemon=True)
43+
t.start()
44+
2845
result = subprocess.run(
2946
cmd,
3047
stdout=subprocess.PIPE,
@@ -41,11 +58,13 @@ def run_and_classify(name, cmd):
4158
return 0
4259

4360
except subprocess.TimeoutExpired:
44-
print(f"{YELLOW}→ TIMEOUT ({TIMEOUT_SEC}s){RESET}\n")
45-
return -1
46-
61+
if name in KNOWN_TIMEOUT:
62+
print(f"{CYAN}→ SKIP (expected blocking / unimplemented){RESET}\n")
63+
return 2
64+
else:
65+
print(f"{YELLOW}→ TIMEOUT ({TIMEOUT_SEC}s){RESET}\n")
66+
return -1
4767

48-
# test*.wave
4968
for path in sorted(TEST_DIR.glob("test*.wave")):
5069
name = path.name
5170
cmd = [str(WAVEC), "run", f"test/{name}"]
@@ -63,12 +82,11 @@ def run_and_classify(name, cmd):
6382
)
6483
results.append(("test28 (dir)", result))
6584

66-
# 집계
6785
pass_tests = [name for name, r in results if r == 1]
6886
fail_tests = [name for name, r in results if r == 0]
6987
timeout_tests = [name for name, r in results if r == -1]
88+
skip_tests = [name for name, r in results if r == 2]
7089

71-
# 최종 출력
7290
print("\n=========================")
7391
print("🎉 FINAL TEST RESULT")
7492
print("=========================\n")
@@ -77,6 +95,10 @@ def run_and_classify(name, cmd):
7795
for name in pass_tests:
7896
print(f" - {name}")
7997

98+
print(f"\n{CYAN}SKIP ({len(skip_tests)}){RESET}")
99+
for name in skip_tests:
100+
print(f" - {name}")
101+
80102
print(f"\n{RED}FAIL ({len(fail_tests)}){RESET}")
81103
for name in fail_tests:
82104
print(f" - {name}")
@@ -87,6 +109,7 @@ def run_and_classify(name, cmd):
87109

88110
print("\n=========================")
89111
print(f"{GREEN}PASS: {len(pass_tests)}{RESET}")
112+
print(f"{CYAN}SKIP: {len(skip_tests)}{RESET}")
90113
print(f"{RED}FAIL: {len(fail_tests)}{RESET}")
91114
print(f"{YELLOW}TIMEOUT: {len(timeout_tests)}{RESET}")
92115
print("=========================\n")

0 commit comments

Comments
 (0)