MAJOR ACHIEVEMENT: Full working reactive framework! ## What's Working ✅ Python → AST → Ritz IR → LLVM IR → WASM pipeline ✅ Reactive signals stored in WASM memory (@signal_name = global i32) ✅ Event handlers exported from WASM and callable from JS ✅ Clean runtime with RitzLoader and debug tools ✅ Two working examples: HelloWorld and HighFive counter ## Core Components ### Parser (ritz/parser.py) - Uses Python's ast module to parse components - Handles @component decorator, signals, event handlers - Supports yield, with statements, f-strings, augmented assignment (+=) - Clean syntax: from ritz.syntax import * ### LLVM IR Code Generator (ritz/llvm_codegen_signals.py) - Generates LLVM IR directly (not C!) - Signals as global variables in WASM memory - Exports getter/setter functions for each signal - Exports event handler functions for JS to call - UTF-8 string handling ### Build System (ritz/build.py) - Python → AST → IR → LLVM IR → clang --target=wasm32 → WASM - Saves intermediate .ll files for inspection - Debug symbols support (-g flag) ### Runtime (runtime/ritz-runtime.js) - RitzRuntime class: DOM bridge for WASM - RitzLoader class: Simplified component loading - Debug bar with Ctrl+` toggle - Signal updates trigger DOM updates ## Examples ### HelloWorld.py Simple static content - renders <p>Hello World</p> ### HighFive.py Reactive counter with: - Signal in WASM memory (high_fives = signal(0)) - Event handler (increment function) - DOM updates on signal change ## Test Coverage - 4 parser tests (all passing) - 4 LLVM codegen tests (all passing) - 4 signal parsing tests (all passing) - Code formatted with black and ruff ## Next Steps - <script type="text/ritz"> in-browser compilation - Better signal-to-DOM binding tracking - More complex examples (TodoMVC, forms, lists) - Playwright browser tests --- This is a genuinely innovative framework: write Python, compile to WASM, run with reactive signals in WASM memory. No virtual DOM, no transpilation, just compiled Python with fine-grained reactivity. 🎉 Python → WASM → Reactive UI is REAL!
164 lines
6.1 KiB
Markdown
164 lines
6.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Ritz is a WebAssembly UI framework with Python-like syntax that compiles to high-performance WASM while remaining executable in Python for debugging. The framework uses **valid Python syntax** that can execute in CPython for prototyping/debugging, but is designed to compile to WebAssembly for production.
|
|
|
|
**Current Status**: Python prototype stage. The WASM compilation pipeline is conceptual/architectural.
|
|
|
|
## Development Commands
|
|
|
|
### Running the Prototype
|
|
```bash
|
|
# Run example application showing various components
|
|
python3 example.py
|
|
|
|
# Run simple test
|
|
python3 test.py
|
|
|
|
# Test AST parser
|
|
python3 ast_parser.py
|
|
|
|
# View module system concept
|
|
python3 module_system.py
|
|
|
|
# View compilation pipeline concept
|
|
python3 compiler.py
|
|
|
|
# View debugging concept
|
|
python3 debug_concept.py
|
|
```
|
|
|
|
## Core Architecture
|
|
|
|
### Component Model
|
|
Components are defined using the `@component` decorator with Python generator syntax (yield-based):
|
|
|
|
```python
|
|
@component
|
|
def Counter():
|
|
count = signal(0) # Reactive state
|
|
|
|
def increment():
|
|
count += 1
|
|
|
|
with Div(class_='counter'): # Context managers for element nesting
|
|
yield H1('Counter') # Yield elements/strings/components
|
|
yield P(f'Count: {count}')
|
|
yield Button('Click me', onclick=increment)
|
|
```
|
|
|
|
Key patterns:
|
|
- **Generators**: Components are generator functions that yield children
|
|
- **Context managers**: Use `with Element():` for nested structures
|
|
- **Signals**: Reactive state via `signal(initial_value)`
|
|
- **Mixed content**: Can yield strings, elements, or other components
|
|
|
|
### File Structure
|
|
|
|
**Core Framework Files:**
|
|
- `framework.py` - Python prototype runtime (Signal, VNode, Element, component decorator)
|
|
- `ast_parser.py` - Parses Python components using Python's `ast` module to generate IR
|
|
- `compiler.py` - Complete compilation pipeline concept (Python → IR → LLVM → WASM)
|
|
- `module_system.py` - Progressive module loading architecture for code splitting
|
|
|
|
**Conceptual/Research:**
|
|
- `debug_concept.py` - Python-in-WASM debugging architecture (DWARF symbols, source maps)
|
|
- `RESEARCH.md` - Complete technical architecture and implementation roadmap
|
|
|
|
**Examples:**
|
|
- `example.py` - Demonstrates component syntax with various examples
|
|
- `test.py` - Simple test for debugging framework behavior
|
|
|
|
### Compilation Pipeline (Conceptual)
|
|
|
|
The planned compilation flow:
|
|
1. **Parser**: Uses Python's `ast` module to parse components (no custom parser needed!)
|
|
2. **IR Generation**: Transform Python AST → Ritz intermediate representation
|
|
3. **LLVM Codegen**: Ritz IR → LLVM IR
|
|
4. **WASM Output**: LLVM IR → WebAssembly with debug symbols (DWARF)
|
|
5. **Module Splitting**: Split into multiple WASM modules (bootstrap, core, features)
|
|
|
|
### Reactive System
|
|
|
|
**Signals** are the primitive reactive unit:
|
|
- Store a value and list of subscribers
|
|
- When value changes, notify all subscribers
|
|
- In Python prototype: simple Python class
|
|
- In WASM target: efficient memory layout with direct DOM node references
|
|
|
|
**Key insight**: No virtual DOM. Signals map directly to DOM nodes for updates.
|
|
|
|
### Module System Architecture
|
|
|
|
Apps split into multiple WASM modules for security and performance:
|
|
- `bootstrap.wasm` (~50KB) - Login only, no auth required, no business logic
|
|
- `app-core.wasm` (~200KB) - Main app, requires authentication
|
|
- `features/*.wasm` - Lazy-loaded feature modules
|
|
|
|
**Security benefit**: Unauthenticated users never receive app code containing API endpoints or business logic.
|
|
|
|
## Important Implementation Details
|
|
|
|
### AST Parsing
|
|
The framework uses **Python's own `ast` module** to parse components (not a custom parser). This provides:
|
|
- Zero parsing overhead
|
|
- Perfect Python compatibility
|
|
- Automatic syntax error messages
|
|
- Type hints support
|
|
|
|
See `ast_parser.py` for the `RitzASTTransformer` that converts Python AST to Ritz IR.
|
|
|
|
### VNode Structure
|
|
Internal representation during Python execution:
|
|
- `VNode(tag, props, children)` - Virtual DOM node
|
|
- `to_html()` - Render to HTML string
|
|
- `to_ir()` - Convert to intermediate representation for compilation
|
|
|
|
### Context Stack
|
|
`_context_stack` is a global list tracking nested `with Element():` blocks. The `@component` decorator manages this stack to build the component tree.
|
|
|
|
## Debugging Philosophy
|
|
|
|
**Revolutionary concept**: Debug Python code running in WASM, not JavaScript!
|
|
- DWARF debug symbols embedded in WASM
|
|
- Source maps linking WASM instructions → Python source lines
|
|
- Chrome DevTools can set breakpoints in Python files
|
|
- Inspect Python variables, not mangled JS
|
|
|
|
See `debug_concept.py` and RESEARCH.md sections on debugging.
|
|
|
|
## Design Principles
|
|
|
|
1. **Python-executable, WASM-compilable**: The same code runs in both environments
|
|
2. **Yield-based composition**: Natural Python syntax for building component trees
|
|
3. **Fine-grained reactivity**: Signals update DOM directly, no virtual DOM diffing
|
|
4. **Progressive loading**: Split code into secure, cacheable modules
|
|
5. **Developer experience**: Debug in Python, ship as WASM
|
|
|
|
## Performance Targets
|
|
|
|
Based on SolidJS/Leptos research:
|
|
- Bundle size: < 200KB compressed
|
|
- Startup time: < 500ms on slow 3G
|
|
- Update performance: Within 10% of vanilla JS
|
|
- Memory usage: 70% less than React
|
|
- DOM mutations: 99% fewer than virtual DOM frameworks
|
|
|
|
## When Modifying Code
|
|
|
|
1. **Python prototype** (`framework.py`): Currently functional, can be tested with Python
|
|
2. **Compilation pipeline** (`compiler.py`, `ast_parser.py`): Architectural/conceptual code that demonstrates intended design
|
|
3. **Module system** (`module_system.py`): Demonstrates progressive loading strategy
|
|
4. Components must be valid Python and use generator syntax with yield
|
|
5. All examples should run with `python3 example.py`
|
|
|
|
## Key Technical Decisions
|
|
|
|
- **Why yield?** Natural Python syntax, composable, clear execution order
|
|
- **Why compile vs interpret?** 10-100x performance, smaller bundle, type safety
|
|
- **Why LLVM?** Mature toolchain, excellent WASM backend, optimization passes
|
|
- **Why Python's ast module?** No custom parser needed, perfect compatibility
|