**Reactive Text Nodes:**
- F-strings with signal dependencies now update automatically
- Added js_create_text_with_int() and js_update_text_with_int() for efficient "prefix{int}" pattern
- Text nodes stored in @reactive_text_N_node globals for updates
- Scan and track f-string dependencies during collection phase
**Binary Operations:**
- Implemented BinOp support in parser and codegen
- Maps Add → add i32, Sub → sub i32, Mult → mul i32, Div → sdiv i32, Mod → srem i32
- count = count + 1 now generates correct arithmetic instead of store i32 0
**LLVM Syntax Fixes (clang 20 compatibility):**
- Fixed getelementptr syntax: removed parentheses around type
- Before: getelementptr inbounds ([N x i8], [N x i8]* @str, ...)
- After: getelementptr inbounds [N x i8], [N x i8]* @str, ...
- Created _emit_string_ptr() helper for consistent string pointer generation
- Fixed in: element creation, attribute setting, event binding, select instructions
**Runtime (ritz-runtime.js):**
- Added js_create_text_with_int(prefix, intValue) - creates text node with "prefix" + intValue
- Added js_update_text_with_int(node, prefix, intValue) - updates text content
**Result:**
✅ TextInput counter increments/decrements correctly
✅ Tabs example works (reactive attributes, conditionals)
✅ Both examples compile with clang 20
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
189 lines
9.6 KiB
LLVM
189 lines
9.6 KiB
LLVM
; Generated by Ritz Framework with Signals
|
||
; Components: TextInput
|
||
|
||
; String constants
|
||
@.str.0 = private unnamed_addr constant [8 x i8] c"Count: \00"
|
||
@.str.1 = private unnamed_addr constant [4 x i8] c"div\00"
|
||
@.str.2 = private unnamed_addr constant [6 x i8] c"class\00"
|
||
@.str.3 = private unnamed_addr constant [10 x i8] c"container\00"
|
||
@.str.4 = private unnamed_addr constant [3 x i8] c"h1\00"
|
||
@.str.5 = private unnamed_addr constant [17 x i8] c"Reactive Counter\00"
|
||
@.str.6 = private unnamed_addr constant [2 x i8] c"p\00"
|
||
@.str.7 = private unnamed_addr constant [13 x i8] c"instructions\00"
|
||
@.str.8 = private unnamed_addr constant [65 x i8] c"Click buttons to see reactive updates (text input coming soon!):\00"
|
||
@.str.9 = private unnamed_addr constant [13 x i8] c"button-group\00"
|
||
@.str.10 = private unnamed_addr constant [7 x i8] c"button\00"
|
||
@.str.11 = private unnamed_addr constant [6 x i8] c"click\00"
|
||
@.str.12 = private unnamed_addr constant [10 x i8] c"decrement\00"
|
||
@.str.13 = private unnamed_addr constant [4 x i8] c"−\00"
|
||
@.str.14 = private unnamed_addr constant [16 x i8] c"counter-display\00"
|
||
@.str.15 = private unnamed_addr constant [10 x i8] c"increment\00"
|
||
@.str.16 = private unnamed_addr constant [2 x i8] c"+\00"
|
||
@.str.17 = private unnamed_addr constant [5 x i8] c"todo\00"
|
||
@.str.18 = private unnamed_addr constant [49 x i8] c"TODO: Replace with text input once we implement:\00"
|
||
@.str.19 = private unnamed_addr constant [3 x i8] c"ul\00"
|
||
@.str.20 = private unnamed_addr constant [10 x i8] c"todo-list\00"
|
||
@.str.21 = private unnamed_addr constant [3 x i8] c"li\00"
|
||
@.str.22 = private unnamed_addr constant [32 x i8] c"1. String signals (i8* not i32)\00"
|
||
@.str.23 = private unnamed_addr constant [25 x i8] c"2. oninput event handler\00"
|
||
@.str.24 = private unnamed_addr constant [23 x i8] c"3. Event value passing\00"
|
||
@.str.25 = private unnamed_addr constant [39 x i8] c"4. F-string interpolation with signals\00"
|
||
|
||
; JavaScript bridge function declarations
|
||
declare i32 @js_create_element(i8*)
|
||
declare i32 @js_create_text(i8*)
|
||
declare i32 @js_create_text_with_int(i8*, i32)
|
||
declare void @js_append_child(i32, i32)
|
||
declare void @js_set_attribute(i32, i8*, i8*)
|
||
declare void @js_set_root(i32)
|
||
declare void @js_bind_event(i32, i8*, i8*)
|
||
declare void @js_update_text_content(i32, i8*)
|
||
declare void @js_update_text_with_int(i32, i8*, i32)
|
||
declare i32 @js_create_marker()
|
||
declare void @js_replace_at_marker(i32, i32, i32)
|
||
|
||
; Signal storage for TextInput (reactive state in WASM memory)
|
||
@signal_TextInput_count = global i32 0
|
||
|
||
; Reactive text node storage
|
||
@reactive_text_0_node = global i32 0
|
||
|
||
; Signal helper functions
|
||
define i32 @get_count() {
|
||
entry:
|
||
%val = load i32, i32* @signal_TextInput_count
|
||
ret i32 %val
|
||
}
|
||
|
||
define void @set_count(i32 %newval) {
|
||
entry:
|
||
store i32 %newval, i32* @signal_TextInput_count
|
||
; TODO: Trigger DOM update callback
|
||
ret void
|
||
}
|
||
|
||
; Event handler: increment
|
||
define void @increment() {
|
||
entry:
|
||
%var0 = load i32, i32* @signal_TextInput_count
|
||
%var1 = add i32 %var0, 1
|
||
store i32 %var1, i32* @signal_TextInput_count
|
||
%var2 = load i32, i32* @reactive_text_0_node
|
||
%var3 = getelementptr inbounds [8 x i8], [8 x i8]* @.str.0, i32 0, i32 0
|
||
%var4 = load i32, i32* @signal_TextInput_count
|
||
call void @js_update_text_with_int(i32 %var2, i8* %var3, i32 %var4)
|
||
ret void
|
||
}
|
||
|
||
; Event handler: decrement
|
||
define void @decrement() {
|
||
entry:
|
||
%var5 = load i32, i32* @signal_TextInput_count
|
||
%var6 = sub i32 %var5, 1
|
||
store i32 %var6, i32* @signal_TextInput_count
|
||
%var7 = load i32, i32* @reactive_text_0_node
|
||
%var8 = getelementptr inbounds [8 x i8], [8 x i8]* @.str.0, i32 0, i32 0
|
||
%var9 = load i32, i32* @signal_TextInput_count
|
||
call void @js_update_text_with_int(i32 %var7, i8* %var8, i32 %var9)
|
||
ret void
|
||
}
|
||
|
||
; Component render function
|
||
define i32 @render_TextInput() {
|
||
entry:
|
||
%var11 = getelementptr inbounds [4 x i8], [4 x i8]* @.str.1, i32 0, i32 0
|
||
%var10 = call i32 @js_create_element(i8* %var11)
|
||
%var12 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var13 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.3, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var10, i8* %var12, i8* %var13)
|
||
%var15 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.4, i32 0, i32 0
|
||
%var14 = call i32 @js_create_element(i8* %var15)
|
||
%var16 = call i32 @js_create_text(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str.5, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var14, i32 %var16)
|
||
call void @js_append_child(i32 %var10, i32 %var14)
|
||
%var18 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.6, i32 0, i32 0
|
||
%var17 = call i32 @js_create_element(i8* %var18)
|
||
%var19 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var20 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.7, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var17, i8* %var19, i8* %var20)
|
||
%var21 = call i32 @js_create_text(i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str.8, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var17, i32 %var21)
|
||
call void @js_append_child(i32 %var10, i32 %var17)
|
||
%var23 = getelementptr inbounds [4 x i8], [4 x i8]* @.str.1, i32 0, i32 0
|
||
%var22 = call i32 @js_create_element(i8* %var23)
|
||
%var24 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var25 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.9, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var22, i8* %var24, i8* %var25)
|
||
%var27 = getelementptr inbounds [7 x i8], [7 x i8]* @.str.10, i32 0, i32 0
|
||
%var26 = call i32 @js_create_element(i8* %var27)
|
||
%var28 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.11, i32 0, i32 0
|
||
%var29 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.12, i32 0, i32 0
|
||
call void @js_bind_event(i32 %var26, i8* %var28, i8* %var29)
|
||
%var30 = call i32 @js_create_text(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.13, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var26, i32 %var30)
|
||
call void @js_append_child(i32 %var22, i32 %var26)
|
||
%var32 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.6, i32 0, i32 0
|
||
%var31 = call i32 @js_create_element(i8* %var32)
|
||
%var33 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var34 = getelementptr inbounds [16 x i8], [16 x i8]* @.str.14, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var31, i8* %var33, i8* %var34)
|
||
%var35 = getelementptr inbounds [8 x i8], [8 x i8]* @.str.0, i32 0, i32 0
|
||
%var36 = load i32, i32* @signal_TextInput_count
|
||
%var37 = call i32 @js_create_text_with_int(i8* %var35, i32 %var36)
|
||
store i32 %var37, i32* @reactive_text_0_node
|
||
call void @js_append_child(i32 %var31, i32 %var37)
|
||
call void @js_append_child(i32 %var22, i32 %var31)
|
||
%var39 = getelementptr inbounds [7 x i8], [7 x i8]* @.str.10, i32 0, i32 0
|
||
%var38 = call i32 @js_create_element(i8* %var39)
|
||
%var40 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.11, i32 0, i32 0
|
||
%var41 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.15, i32 0, i32 0
|
||
call void @js_bind_event(i32 %var38, i8* %var40, i8* %var41)
|
||
%var42 = call i32 @js_create_text(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.16, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var38, i32 %var42)
|
||
call void @js_append_child(i32 %var22, i32 %var38)
|
||
call void @js_append_child(i32 %var10, i32 %var22)
|
||
%var44 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.6, i32 0, i32 0
|
||
%var43 = call i32 @js_create_element(i8* %var44)
|
||
%var45 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var46 = getelementptr inbounds [5 x i8], [5 x i8]* @.str.17, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var43, i8* %var45, i8* %var46)
|
||
%var47 = call i32 @js_create_text(i8* getelementptr inbounds ([49 x i8], [49 x i8]* @.str.18, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var43, i32 %var47)
|
||
call void @js_append_child(i32 %var10, i32 %var43)
|
||
%var49 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.19, i32 0, i32 0
|
||
%var48 = call i32 @js_create_element(i8* %var49)
|
||
%var50 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||
%var51 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.20, i32 0, i32 0
|
||
call void @js_set_attribute(i32 %var48, i8* %var50, i8* %var51)
|
||
%var53 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.21, i32 0, i32 0
|
||
%var52 = call i32 @js_create_element(i8* %var53)
|
||
%var54 = call i32 @js_create_text(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.22, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var52, i32 %var54)
|
||
call void @js_append_child(i32 %var48, i32 %var52)
|
||
%var56 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.21, i32 0, i32 0
|
||
%var55 = call i32 @js_create_element(i8* %var56)
|
||
%var57 = call i32 @js_create_text(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.23, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var55, i32 %var57)
|
||
call void @js_append_child(i32 %var48, i32 %var55)
|
||
%var59 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.21, i32 0, i32 0
|
||
%var58 = call i32 @js_create_element(i8* %var59)
|
||
%var60 = call i32 @js_create_text(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.24, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var58, i32 %var60)
|
||
call void @js_append_child(i32 %var48, i32 %var58)
|
||
%var62 = getelementptr inbounds [3 x i8], [3 x i8]* @.str.21, i32 0, i32 0
|
||
%var61 = call i32 @js_create_element(i8* %var62)
|
||
%var63 = call i32 @js_create_text(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.25, i32 0, i32 0))
|
||
call void @js_append_child(i32 %var61, i32 %var63)
|
||
call void @js_append_child(i32 %var48, i32 %var61)
|
||
call void @js_append_child(i32 %var10, i32 %var48)
|
||
ret i32 %var10
|
||
}
|
||
|
||
; Main entry point
|
||
define void @main() {
|
||
entry:
|
||
%root = call i32 @render_TextInput()
|
||
call void @js_set_root(i32 %root)
|
||
ret void
|
||
}
|