Fix nested components - render functions now return i32
Changes: - Component render functions return i32 (root element) instead of void - Nested components (yield SomeComponent()) now work correctly - Added main() entry point that calls top-level component and sets root - Updated runtime to call main() instead of render_ComponentName() Note: Active state in ternary expressions still needs reactive updates This commit fixes the nested component rendering issue All tests passing (51 passed, 2 skipped) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
adf95f424d
commit
b0e38db22c
26 files changed
+2310
-1222
No files matched your search
Binary file not shown.
Binary file not shown.
@@ -87,6 +87,10 @@ class SignalLLVMIRGenerator:
|
||||
self._emit_conditional_functions()
|
||||
self._emit_component(component)
|
||||
|
||||
# Emit main entry point for the last (top-level) component
|
||||
if self.components:
|
||||
self._emit_main_entry(self.components[-1]["name"])
|
||||
|
||||
# Prepend string constants
|
||||
return self._finalize_with_strings()
|
||||
|
||||
@@ -641,6 +645,17 @@ class SignalLLVMIRGenerator:
|
||||
self.lines.append("}")
|
||||
self.lines.append("")
|
||||
|
||||
def _emit_main_entry(self, component_name: str) -> None:
|
||||
"""Emit main entry point that renders top-level component and sets root."""
|
||||
self.lines.append("; Main entry point")
|
||||
self.lines.append("define void @main() {")
|
||||
self.lines.append("entry:")
|
||||
self.lines.append(f" %root = call i32 @render_{component_name}()")
|
||||
self.lines.append(" call void @js_set_root(i32 %root)")
|
||||
self.lines.append(" ret void")
|
||||
self.lines.append("}")
|
||||
self.lines.append("")
|
||||
|
||||
def _emit_component(self, ir: dict[str, Any]) -> None:
|
||||
"""Emit component render function."""
|
||||
component_name = ir["name"]
|
||||
@@ -654,7 +669,7 @@ class SignalLLVMIRGenerator:
|
||||
param_str = ", ".join(param_list) if param_list else ""
|
||||
|
||||
self.lines.append("; Component render function")
|
||||
self.lines.append(f"define void @render_{component_name}({param_str}) {{")
|
||||
self.lines.append(f"define i32 @render_{component_name}({param_str}) {{")
|
||||
self.lines.append("entry:")
|
||||
|
||||
# Process component body (skip signals and functions, already handled)
|
||||
@@ -666,11 +681,13 @@ class SignalLLVMIRGenerator:
|
||||
if root_var is None and var:
|
||||
root_var = var
|
||||
|
||||
# Set root element
|
||||
# Return root element (caller decides whether to set as root or append)
|
||||
if root_var:
|
||||
self.lines.append(f" call void @js_set_root(i32 %{root_var})")
|
||||
self.lines.append(f" ret i32 %{root_var}")
|
||||
else:
|
||||
# No root element - return 0
|
||||
self.lines.append(" ret i32 0")
|
||||
|
||||
self.lines.append(" ret void")
|
||||
self.lines.append("}")
|
||||
self.lines.append("")
|
||||
|
||||
@@ -767,14 +784,20 @@ class SignalLLVMIRGenerator:
|
||||
arg_var = self._emit_expr(arg)
|
||||
arg_values.append(f"i32 {arg_var}")
|
||||
|
||||
# Build argument list and call
|
||||
# Call component render function and capture returned root element
|
||||
elem_var = self._new_var()
|
||||
if arg_values:
|
||||
arg_list = ", ".join(arg_values)
|
||||
self.lines.append(f" call void @render_{component_name}({arg_list})")
|
||||
self.lines.append(f" %{elem_var} = call i32 @render_{component_name}({arg_list})")
|
||||
else:
|
||||
self.lines.append(f" call void @render_{component_name}()")
|
||||
self.lines.append(f" %{elem_var} = call i32 @render_{component_name}()")
|
||||
|
||||
return None
|
||||
# Append to parent if we have one
|
||||
if self.parent_element_stack:
|
||||
parent_var = self.parent_element_stack[-1]
|
||||
self.lines.append(f" call void @js_append_child(i32 %{parent_var}, i32 %{elem_var})")
|
||||
|
||||
return elem_var
|
||||
|
||||
def _emit_match(self, stmt: dict[str, Any]) -> str | None:
|
||||
"""Emit a match/case statement with reactive rendering."""
|
||||
|
||||
Reference in new issue
Block a user