diff --git a/examples/tabs/Tabs.ll b/examples/tabs/Tabs.ll index ad1953f..99536cd 100644 --- a/examples/tabs/Tabs.ll +++ b/examples/tabs/Tabs.ll @@ -121,7 +121,10 @@ entry: define void @set_setting_0() { entry: store i32 0, i32* @signal_VerticalTabs_setting_tab - ; TODO: Update DOM nodes bound to setting_tab + call void @reevaluate_conditional_0() + call void @reevaluate_conditional_1() + call void @reevaluate_conditional_2() + call void @reevaluate_conditional_3() ret void } @@ -129,7 +132,10 @@ entry: define void @set_setting_1() { entry: store i32 1, i32* @signal_VerticalTabs_setting_tab - ; TODO: Update DOM nodes bound to setting_tab + call void @reevaluate_conditional_0() + call void @reevaluate_conditional_1() + call void @reevaluate_conditional_2() + call void @reevaluate_conditional_3() ret void } @@ -137,7 +143,10 @@ entry: define void @set_setting_2() { entry: store i32 2, i32* @signal_VerticalTabs_setting_tab - ; TODO: Update DOM nodes bound to setting_tab + call void @reevaluate_conditional_0() + call void @reevaluate_conditional_1() + call void @reevaluate_conditional_2() + call void @reevaluate_conditional_3() ret void } @@ -609,7 +618,10 @@ entry: define void @set_tab_0() { entry: store i32 0, i32* @signal_Tabs_tab_index - ; TODO: Update DOM nodes bound to tab_index + call void @reevaluate_conditional_4() + call void @reevaluate_conditional_5() + call void @reevaluate_conditional_6() + call void @reevaluate_conditional_7() ret void } @@ -617,7 +629,10 @@ entry: define void @set_tab_1() { entry: store i32 1, i32* @signal_Tabs_tab_index - ; TODO: Update DOM nodes bound to tab_index + call void @reevaluate_conditional_4() + call void @reevaluate_conditional_5() + call void @reevaluate_conditional_6() + call void @reevaluate_conditional_7() ret void } @@ -625,7 +640,10 @@ entry: define void @set_tab_2() { entry: store i32 2, i32* @signal_Tabs_tab_index - ; TODO: Update DOM nodes bound to tab_index + call void @reevaluate_conditional_4() + call void @reevaluate_conditional_5() + call void @reevaluate_conditional_6() + call void @reevaluate_conditional_7() ret void } diff --git a/examples/tabs/Tabs.wasm b/examples/tabs/Tabs.wasm index 431e63e..897da2a 100755 Binary files a/examples/tabs/Tabs.wasm and b/examples/tabs/Tabs.wasm differ diff --git a/ritz/__pycache__/llvm_codegen_signals.cpython-313.pyc b/ritz/__pycache__/llvm_codegen_signals.cpython-313.pyc index abab61b..ba36d0b 100644 Binary files a/ritz/__pycache__/llvm_codegen_signals.cpython-313.pyc and b/ritz/__pycache__/llvm_codegen_signals.cpython-313.pyc differ diff --git a/ritz/llvm_codegen_signals.py b/ritz/llvm_codegen_signals.py index db2afab..627c6db 100644 --- a/ritz/llvm_codegen_signals.py +++ b/ritz/llvm_codegen_signals.py @@ -37,6 +37,9 @@ class SignalLLVMIRGenerator: # Track signal-to-DOM bindings for updates self.signal_dom_bindings: dict[str, list[str]] = {} # signal_name -> [dom_node_ids] + # Track signal-to-conditional dependencies for reactivity + self.signal_conditional_deps: dict[str, list[int]] = {} # signal_name -> [conditional_ids] + # Track current component for signal scoping self.current_component = None @@ -67,6 +70,7 @@ class SignalLLVMIRGenerator: self.event_handlers = [] self.conditionals = [] self.conditional_map = {} + self.signal_conditional_deps = {} # Collect signals, handlers, and conditionals for this component self._collect_signals_and_handlers(component) @@ -133,6 +137,44 @@ class SignalLLVMIRGenerator: scan_statements(component["body"]) + # Build signal -> conditional dependency map + for cond_info in self.conditionals: + cond_id = cond_info["id"] + if cond_info["type"] == "if": + # Extract signals from test expression + signals = self._extract_signals_from_expr(cond_info["test"]) + elif cond_info["type"] == "match": + # Extract signals from subject expression + signals = self._extract_signals_from_expr(cond_info["subject"]) + else: + signals = [] + + # Register this conditional as dependent on these signals + for signal_name in signals: + if signal_name not in self.signal_conditional_deps: + self.signal_conditional_deps[signal_name] = [] + self.signal_conditional_deps[signal_name].append(cond_id) + + def _extract_signals_from_expr(self, expr: dict[str, Any]) -> list[str]: + """Extract signal names referenced in an expression.""" + signals = [] + + if expr["type"] == "name": + # Direct signal reference + signal_name = expr["id"] + if signal_name in self.signals: + signals.append(signal_name) + elif expr["type"] == "compare": + # Comparison expression - check left and right + signals.extend(self._extract_signals_from_expr(expr["left"])) + for comparator in expr.get("comparators", []): + signals.extend(self._extract_signals_from_expr(comparator)) + elif expr["type"] == "constant": + # Constants don't reference signals + pass + + return signals + def _emit_header(self) -> None: """Emit module header.""" self.lines.append("; Generated by Ritz Framework with Signals") @@ -248,8 +290,10 @@ class SignalLLVMIRGenerator: # Store the value self.lines.append(f" store i32 {value_var}, i32* {self._signal_global(signal_name)}") - # TODO: Trigger DOM updates - self.lines.append(f" ; TODO: Update DOM nodes bound to {signal_name}") + # Trigger reactive updates for conditionals that depend on this signal + if signal_name in self.signal_conditional_deps: + for cond_id in self.signal_conditional_deps[signal_name]: + self.lines.append(f" call void @reevaluate_conditional_{cond_id}()") elif stmt["type"] == "augassign": # Handle signal updates (count += 1) signal_name = stmt["target"] @@ -267,8 +311,10 @@ class SignalLLVMIRGenerator: # Store back self.lines.append(f" store i32 %{result_var}, i32* {self._signal_global(signal_name)}") - # TODO: Trigger DOM updates for this signal - self.lines.append(f" ; TODO: Update DOM nodes bound to {signal_name}") + # Trigger reactive updates for conditionals that depend on this signal + if signal_name in self.signal_conditional_deps: + for cond_id in self.signal_conditional_deps[signal_name]: + self.lines.append(f" call void @reevaluate_conditional_{cond_id}()") def _emit_conditional_functions(self) -> None: """Emit init and reevaluate functions for each conditional."""