Implement RitzMain() convention and Main.wasm standard

**Convention: RitzMain() entry point**
Every Ritz file now requires a `@component def RitzMain()` as the entry point.
This provides a consistent, predictable entry point for all applications.

**Universal Main.wasm output**
Build system now always outputs Main.wasm instead of ComponentName.wasm.
This means every example uses the exact same HTML boilerplate!

**Changes:**

**Codegen (llvm_codegen_signals.py):**
- Check for RitzMain component at generation time
- Error if RitzMain not found: "No RitzMain component found!"
- Always call `render_RitzMain()` from main() entry point
- Fix: Scope reactive text nodes to components (`@reactive_text_ComponentName_N_node`)
  - Prevents global name collisions when multiple components have reactive text

**Build (build.py):**
- Output Main.wasm in same directory as source file
- Output Main.ll (LLVM IR) for inspection
- Convention over configuration!

**Loader (ritz-runtime.js):**
- Auto-detect component name from WASM filename
- `new RitzLoader().load('Main.wasm')` - no second parameter needed!
- Component name used only for status messages

**Template (examples/template.html):**
- Minimal boilerplate - literally 25 lines
- Just copy and change nothing!
- Loads Main.wasm - works for every example

**Styles (examples/runtime/styles.css):**
- Shared styles for all examples
- Clean, modern defaults
- App container, buttons, inputs, typography

**Example (HighFive):**
```python
@component
def HighFive():
    # ... component logic

@component
def RitzMain():
    """Entry point - required!"""
    yield HighFive()
```

**Result:**
✅ Every example: copy template.html, change nothing
✅ Every example: builds to Main.wasm
✅ Consistent entry point: RitzMain()
✅ No more component name boilerplate

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Aaron SinclairandClaude committed 2025-11-15 15:46:36 -08:00
1 parent 999327172e
commit ddd2c03a9d
9 files changed
+261 -52

No files matched your search

+2 -2
View File
@@ -86,10 +86,10 @@ ritzInstance.exports.increment()</pre>
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
new RitzLoader().load('HighFive.wasm', 'HighFive');
new RitzLoader().load('Main.wasm');
});
} else {
new RitzLoader().load('HighFive.wasm', 'HighFive');
new RitzLoader().load('Main.wasm');
}
</script>
</body>
+6
View File
@@ -24,3 +24,9 @@ def HighFive():
with Button(onclick=increment):
yield "High Five!"
@component
def RitzMain():
"""Entry point - required for all Ritz applications."""
yield HighFive()
+114
View File
@@ -0,0 +1,114 @@
; Generated by Ritz Framework with Signals
; Components: HighFive, RitzMain
; String constants
@.str.0 = private unnamed_addr constant [13 x i8] c"High fives: \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 [14 x i8] c"high-five-app\00"
@.str.4 = private unnamed_addr constant [2 x i8] c"p\00"
@.str.5 = private unnamed_addr constant [25 x i8] c"Give me a high five! ✋\00"
@.str.6 = private unnamed_addr constant [6 x i8] c"count\00"
@.str.7 = private unnamed_addr constant [7 x i8] c"button\00"
@.str.8 = private unnamed_addr constant [6 x i8] c"click\00"
@.str.9 = private unnamed_addr constant [10 x i8] c"increment\00"
@.str.10 = private unnamed_addr constant [11 x i8] c"High Five!\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 HighFive (reactive state in WASM memory)
@signal_HighFive_high_fives = global i32 0
; Reactive text node storage for HighFive
@reactive_text_HighFive_0_node = global i32 0
; Signal helper functions
define i32 @get_high_fives() {
entry:
%val = load i32, i32* @signal_HighFive_high_fives
ret i32 %val
}
define void @set_high_fives(i32 %newval) {
entry:
store i32 %newval, i32* @signal_HighFive_high_fives
; TODO: Trigger DOM update callback
ret void
}
; Event handler: increment
define void @increment() {
entry:
%var0 = load i32, i32* @signal_HighFive_high_fives
%var1 = add i32 %var0, 1
store i32 %var1, i32* @signal_HighFive_high_fives
%var2 = load i32, i32* @reactive_text_HighFive_0_node
%var3 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.0, i32 0, i32 0
%var4 = load i32, i32* @signal_HighFive_high_fives
call void @js_update_text_with_int(i32 %var2, i8* %var3, i32 %var4)
ret void
}
; Component render function
define i32 @render_HighFive() {
entry:
%var6 = getelementptr inbounds [4 x i8], [4 x i8]* @.str.1, i32 0, i32 0
%var5 = call i32 @js_create_element(i8* %var6)
%var7 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
%var8 = getelementptr inbounds [14 x i8], [14 x i8]* @.str.3, i32 0, i32 0
call void @js_set_attribute(i32 %var5, i8* %var7, i8* %var8)
%var10 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.4, i32 0, i32 0
%var9 = call i32 @js_create_element(i8* %var10)
%var11 = call i32 @js_create_text(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.5, i32 0, i32 0))
call void @js_append_child(i32 %var9, i32 %var11)
call void @js_append_child(i32 %var5, i32 %var9)
%var13 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.4, i32 0, i32 0
%var12 = call i32 @js_create_element(i8* %var13)
%var14 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
%var15 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.6, i32 0, i32 0
call void @js_set_attribute(i32 %var12, i8* %var14, i8* %var15)
%var16 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.0, i32 0, i32 0
%var17 = load i32, i32* @signal_HighFive_high_fives
%var18 = call i32 @js_create_text_with_int(i8* %var16, i32 %var17)
store i32 %var18, i32* @reactive_text_HighFive_0_node
call void @js_append_child(i32 %var12, i32 %var18)
call void @js_append_child(i32 %var5, i32 %var12)
%var20 = getelementptr inbounds [7 x i8], [7 x i8]* @.str.7, i32 0, i32 0
%var19 = call i32 @js_create_element(i8* %var20)
%var21 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.8, i32 0, i32 0
%var22 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.9, i32 0, i32 0
call void @js_bind_event(i32 %var19, i8* %var21, i8* %var22)
%var23 = call i32 @js_create_text(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.10, i32 0, i32 0))
call void @js_append_child(i32 %var19, i32 %var23)
call void @js_append_child(i32 %var5, i32 %var19)
ret i32 %var5
}
; Reactive text node storage for RitzMain
@reactive_text_RitzMain_0_node = global i32 0
; Component render function
define i32 @render_RitzMain() {
entry:
%var24 = call i32 @render_HighFive()
ret i32 %var24
}
; Main entry point
define void @main() {
entry:
%root = call i32 @render_RitzMain()
call void @js_set_root(i32 %root)
ret void
}
BIN
View File
Binary file not shown.