Implement match/case statement code generation

- Add _emit_match() using LLVM switch instruction
- Handle value patterns and wildcard (case _:) patterns
- Each case gets its own basic block with branch to end
- Wildcard case becomes default label in switch
- All tests passing (30/30)
- Tabs.wasm size: 1908 → 3185 bytes
This commit is contained in:
Aaron Sinclair committed 2025-11-15 03:35:31 -08:00
1 parent e18baf3106
commit cd89f75c1c
4 files changed
+346 -113

No files matched your search

+55
View File
@@ -225,6 +225,8 @@ class SignalLLVMIRGenerator:
return self._emit_yield(stmt)
elif stmt["type"] == "if":
return self._emit_if(stmt)
elif stmt["type"] == "match":
return self._emit_match(stmt)
return None
def _emit_if(self, stmt: dict[str, Any]) -> str | None:
@@ -267,6 +269,59 @@ class SignalLLVMIRGenerator:
return None
def _emit_match(self, stmt: dict[str, Any]) -> str | None:
"""Emit a match/case statement using LLVM switch."""
# Generate unique labels
match_id = self._new_var()
# Evaluate subject expression
subject_var = self._emit_expr(stmt["subject"])
# Create labels for each case and the end
case_labels = [f"match.case{i}.{match_id}" for i in range(len(stmt["cases"]))]
end_label = f"match.end.{match_id}"
default_label = f"match.default.{match_id}"
# Build switch instruction
# Find wildcard case (case _:) to use as default
default_case_idx = None
switch_cases = []
for i, case in enumerate(stmt["cases"]):
pattern = case["pattern"]
if pattern["type"] == "wildcard":
default_case_idx = i
elif pattern["type"] == "value":
# Extract the constant value
value = pattern["value"]["value"]
switch_cases.append(f"i32 {value}, label %{case_labels[i]}")
# Emit switch
if default_case_idx is not None:
self.lines.append(f" switch i32 %{subject_var}, label %{case_labels[default_case_idx]} [")
else:
self.lines.append(f" switch i32 %{subject_var}, label %{default_label} [")
for case_spec in switch_cases:
self.lines.append(f" {case_spec}")
self.lines.append(" ]")
# Emit each case body
for i, case in enumerate(stmt["cases"]):
self.lines.append(f"{case_labels[i]}:")
for case_stmt in case["body"]:
self._emit_statement(case_stmt)
self.lines.append(f" br label %{end_label}")
# Emit default case if needed (no wildcard)
if default_case_idx is None:
self.lines.append(f"{default_label}:")
self.lines.append(f" br label %{end_label}")
# Emit end label
self.lines.append(f"{end_label}:")
return None
def _emit_expr(self, expr: dict[str, Any]) -> str:
"""Emit an expression and return the result variable name."""
if expr["type"] == "name":