Wire up reactive signal updates to conditionals
Critical change that makes conditionals reactive: - Added signal_conditional_deps map to track dependencies - Added _extract_signals_from_expr() to find signals in expressions - Populate dependency map during _collect_conditionals() - Replace TODO comments in signal setters with reevaluate calls How it works: 1. During collection, analyze if/match test/subject expressions 2. Extract all signal names referenced in conditions 3. Build map: signal_name -> [conditional_ids that use it] 4. When signal is updated (assign/augassign), call reevaluate for each dependent conditional Example: set_tab_0() now: store i32 0, i32* @signal_Tabs_tab_index call void @reevaluate_conditional_4() call void @reevaluate_conditional_5() call void @reevaluate_conditional_6() call void @reevaluate_conditional_7() This makes tabs fully interactive! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
3540c44abb
commit
ac7726df46
4 files changed
+74
-10
No files matched your search
+24
-6
@@ -121,7 +121,10 @@ entry:
|
|||||||
define void @set_setting_0() {
|
define void @set_setting_0() {
|
||||||
entry:
|
entry:
|
||||||
store i32 0, i32* @signal_VerticalTabs_setting_tab
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +132,10 @@ entry:
|
|||||||
define void @set_setting_1() {
|
define void @set_setting_1() {
|
||||||
entry:
|
entry:
|
||||||
store i32 1, i32* @signal_VerticalTabs_setting_tab
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +143,10 @@ entry:
|
|||||||
define void @set_setting_2() {
|
define void @set_setting_2() {
|
||||||
entry:
|
entry:
|
||||||
store i32 2, i32* @signal_VerticalTabs_setting_tab
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +618,10 @@ entry:
|
|||||||
define void @set_tab_0() {
|
define void @set_tab_0() {
|
||||||
entry:
|
entry:
|
||||||
store i32 0, i32* @signal_Tabs_tab_index
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +629,10 @@ entry:
|
|||||||
define void @set_tab_1() {
|
define void @set_tab_1() {
|
||||||
entry:
|
entry:
|
||||||
store i32 1, i32* @signal_Tabs_tab_index
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,7 +640,10 @@ entry:
|
|||||||
define void @set_tab_2() {
|
define void @set_tab_2() {
|
||||||
entry:
|
entry:
|
||||||
store i32 2, i32* @signal_Tabs_tab_index
|
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
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -37,6 +37,9 @@ class SignalLLVMIRGenerator:
|
|||||||
# Track signal-to-DOM bindings for updates
|
# Track signal-to-DOM bindings for updates
|
||||||
self.signal_dom_bindings: dict[str, list[str]] = {} # signal_name -> [dom_node_ids]
|
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
|
# Track current component for signal scoping
|
||||||
self.current_component = None
|
self.current_component = None
|
||||||
|
|
||||||
@@ -67,6 +70,7 @@ class SignalLLVMIRGenerator:
|
|||||||
self.event_handlers = []
|
self.event_handlers = []
|
||||||
self.conditionals = []
|
self.conditionals = []
|
||||||
self.conditional_map = {}
|
self.conditional_map = {}
|
||||||
|
self.signal_conditional_deps = {}
|
||||||
|
|
||||||
# Collect signals, handlers, and conditionals for this component
|
# Collect signals, handlers, and conditionals for this component
|
||||||
self._collect_signals_and_handlers(component)
|
self._collect_signals_and_handlers(component)
|
||||||
@@ -133,6 +137,44 @@ class SignalLLVMIRGenerator:
|
|||||||
|
|
||||||
scan_statements(component["body"])
|
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:
|
def _emit_header(self) -> None:
|
||||||
"""Emit module header."""
|
"""Emit module header."""
|
||||||
self.lines.append("; Generated by Ritz Framework with Signals")
|
self.lines.append("; Generated by Ritz Framework with Signals")
|
||||||
@@ -248,8 +290,10 @@ class SignalLLVMIRGenerator:
|
|||||||
# Store the value
|
# Store the value
|
||||||
self.lines.append(f" store i32 {value_var}, i32* {self._signal_global(signal_name)}")
|
self.lines.append(f" store i32 {value_var}, i32* {self._signal_global(signal_name)}")
|
||||||
|
|
||||||
# TODO: Trigger DOM updates
|
# Trigger reactive updates for conditionals that depend on this signal
|
||||||
self.lines.append(f" ; TODO: Update DOM nodes bound to {signal_name}")
|
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":
|
elif stmt["type"] == "augassign":
|
||||||
# Handle signal updates (count += 1)
|
# Handle signal updates (count += 1)
|
||||||
signal_name = stmt["target"]
|
signal_name = stmt["target"]
|
||||||
@@ -267,8 +311,10 @@ class SignalLLVMIRGenerator:
|
|||||||
# Store back
|
# Store back
|
||||||
self.lines.append(f" store i32 %{result_var}, i32* {self._signal_global(signal_name)}")
|
self.lines.append(f" store i32 %{result_var}, i32* {self._signal_global(signal_name)}")
|
||||||
|
|
||||||
# TODO: Trigger DOM updates for this signal
|
# Trigger reactive updates for conditionals that depend on this signal
|
||||||
self.lines.append(f" ; TODO: Update DOM nodes bound to {signal_name}")
|
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:
|
def _emit_conditional_functions(self) -> None:
|
||||||
"""Emit init and reevaluate functions for each conditional."""
|
"""Emit init and reevaluate functions for each conditional."""
|
||||||
|
|||||||
Reference in new issue
Block a user