diff --git a/docs/JS_WASM_BACKEND_PLAN.md b/docs/JS_WASM_BACKEND_PLAN.md new file mode 100644 index 0000000..f27d1fd --- /dev/null +++ b/docs/JS_WASM_BACKEND_PLAN.md @@ -0,0 +1,483 @@ +# Lux JavaScript/WASM Backend Plan + +## Goal + +Enable Lux to compile to JavaScript and WebAssembly, allowing: +1. **Browser execution** - Run Lux in web browsers +2. **Self-hosted website** - Build lux-lang.org in Lux itself (like Elm) +3. **Universal deployment** - Same code runs on server (native) and client (JS/WASM) + +## Research Summary + +### How Gleam Does It + +[Gleam compiles to JavaScript](https://gleam.run/news/v0.16-gleam-compiles-to-javascript/) with these characteristics: +- **No runtime overhead** - Generated JS looks like human-written code +- **Promise-based concurrency** - Uses native JS promises, not Erlang actors +- **Good interop** - Gleam functions callable from JS/TS directly +- [30% performance improvement](https://gleam.run/news/gleam-javascript-gets-30-percent-faster/) in v1.11.0 through optimization + +### How Elm Does It + +[Elm compiles to JavaScript](https://guide.elm-lang.org/interop/) with: +- **Virtual DOM** - Efficient updates via diffing +- **Ports** - Explicit interop boundary with JavaScript +- **Small runtime** - Scheduler and virtual DOM +- **Dead code elimination** - Only includes used code +- **Name mangling** - Prefixes with underscore to avoid collisions + +--- + +## Implementation Strategy + +### Approach: Parallel to C Backend + +Create `src/codegen/js_backend.rs` mirroring `c_backend.rs` structure: + +``` +src/codegen/ +├── c_backend.rs # Existing: Lux → C → Native +├── js_backend.rs # New: Lux → JavaScript +└── wasm_backend.rs # Future: Lux → WASM (via C or direct) +``` + +### Type Mappings + +| Lux Type | JavaScript Type | +|----------|-----------------| +| `Int` | `number` (BigInt for large values) | +| `Float` | `number` | +| `Bool` | `boolean` | +| `String` | `string` | +| `Unit` | `undefined` | +| `List` | `Array` | +| `Option` | `{tag: "Some", value: T} \| {tag: "None"}` | +| `Result` | `{tag: "Ok", value: T} \| {tag: "Err", error: E}` | +| `Closure` | `function` (closure environment captured naturally) | +| `ADT` | `{tag: "VariantName", field0: ..., field1: ...}` | + +### Code Generation Examples + +#### Functions + +```lux +fn add(a: Int, b: Int): Int = a + b +``` + +Generates: +```javascript +function add_lux(a, b) { + return a + b; +} +``` + +#### Closures + +```lux +fn makeAdder(x: Int): (Int) -> Int = { + fn(y: Int): Int => x + y +} +``` + +Generates: +```javascript +function makeAdder_lux(x) { + return function(y) { + return x + y; + }; +} +``` + +#### Pattern Matching + +```lux +fn describe(opt: Option): String = { + match opt { + Some(n) => "Got " + toString(n), + None => "Nothing" + } +} +``` + +Generates: +```javascript +function describe_lux(opt) { + if (opt.tag === "Some") { + const n = opt.value; + return "Got " + String(n); + } else { + return "Nothing"; + } +} +``` + +#### ADTs + +```lux +type Tree = + | Leaf + | Node(Int, Tree, Tree) +``` + +Generates: +```javascript +// Constructor functions +function Leaf_lux() { + return { tag: "Leaf" }; +} + +function Node_lux(value, left, right) { + return { tag: "Node", field0: value, field1: left, field2: right }; +} +``` + +#### Effects + +Effects compile to async/await: + +```lux +fn fetchData(): String with Http = { + Http.get("https://api.example.com/data") +} +``` + +Generates: +```javascript +async function fetchData_lux(handlers) { + return await handlers.Http.get("https://api.example.com/data"); +} +``` + +--- + +## Implementation Phases + +### Phase 1: Core Language (2-3 weeks) + +| Feature | Effort | Notes | +|---------|--------|-------| +| Basic types (Int, Float, Bool, String) | 2 days | Direct mapping | +| Arithmetic and comparison operators | 1 day | | +| Functions and calls | 2 days | | +| Let bindings | 1 day | | +| If expressions | 1 day | Ternary or if/else | +| Pattern matching (basic) | 3 days | Tag checks, destructuring | +| ADT definitions and constructors | 2 days | Object literals | +| Closures | 2 days | Native JS closures | +| Lists | 2 days | Map to Array | + +**Milestone:** Can compile `fib.lux` to JS and run in Node.js + +### Phase 2: Standard Library (1-2 weeks) + +| Module | Effort | JS Implementation | +|--------|--------|-------------------| +| Console | 1 day | `console.log` | +| String | 2 days | Native string methods | +| List | 2 days | Array methods | +| Math | 1 day | `Math.*` | +| Option/Result | 1 day | Pattern matching | +| JSON | 2 days | `JSON.parse/stringify` | + +**Milestone:** Standard library examples work in browser + +### Phase 3: Effects in JS (2 weeks) + +| Effect | Effort | JS Implementation | +|--------|--------|-------------------| +| Console | 1 day | `console.log`, `prompt()` | +| Http | 3 days | `fetch()` API | +| File | 2 days | Not available in browser (Node.js only) | +| Time | 1 day | `Date.now()`, `setTimeout` | +| Random | 1 day | `Math.random()` | +| DOM (new) | 5 days | New effect for browser manipulation | + +**Milestone:** HTTP requests work in browser + +### Phase 4: Browser/DOM Support (2-3 weeks) + +New `Dom` effect for browser manipulation: + +```lux +effect Dom { + fn querySelector(selector: String): Option + fn createElement(tag: String): Element + fn appendChild(parent: Element, child: Element): Unit + fn addEventListener(el: Element, event: String, handler: () -> Unit): Unit + fn setTextContent(el: Element, text: String): Unit + fn setAttribute(el: Element, name: String, value: String): Unit + fn getInputValue(el: Element): String +} +``` + +| Feature | Effort | Notes | +|---------|--------|-------| +| Basic DOM queries | 2 days | querySelector, getElementById | +| Element creation | 2 days | createElement, appendChild | +| Event handling | 3 days | addEventListener with closures | +| Attribute manipulation | 2 days | setAttribute, classList | +| Form handling | 2 days | Input values, form submission | +| Virtual DOM (optional) | 5 days | Efficient updates | + +**Milestone:** Can build interactive web page in Lux + +### Phase 5: CLI Integration (1 week) + +```bash +# Compile to JavaScript +lux compile app.lux --target js -o app.js + +# Compile to JavaScript module (ES modules) +lux compile app.lux --target js --module -o app.mjs + +# Compile with bundled runtime +lux compile app.lux --target js --bundle -o app.bundle.js + +# Run in Node.js +lux run app.lux --target js +``` + +### Phase 6: WASM Backend (3-4 weeks) + +Options: +1. **Lux → C → Emscripten → WASM** (easiest, reuse C backend) +2. **Lux → WASM directly** (more control, harder) +3. **Lux → AssemblyScript → WASM** (middle ground) + +Recommended: Start with Emscripten approach, direct WASM later. + +--- + +## Architecture + +### JS Backend Module Structure + +```rust +// src/codegen/js_backend.rs + +pub struct JsBackend { + output: String, + indent: usize, + functions: HashSet, + name_counter: usize, +} + +impl JsBackend { + pub fn new() -> Self { ... } + + pub fn compile(program: &[Decl]) -> Result { ... } + + fn emit_decl(&mut self, decl: &Decl) -> Result<(), JsGenError> { ... } + fn emit_function(&mut self, func: &Function) -> Result<(), JsGenError> { ... } + fn emit_expr(&mut self, expr: &Expr) -> Result { ... } + fn emit_pattern(&mut self, pattern: &Pattern, value: &str) -> Result { ... } + fn emit_adt(&mut self, adt: &TypeDecl) -> Result<(), JsGenError> { ... } + + // JS-specific + fn emit_runtime(&mut self) { ... } // Minimal runtime helpers + fn emit_effect_handlers(&mut self, effects: &[Effect]) { ... } +} +``` + +### Runtime (Minimal) + +```javascript +// Lux JS Runtime (embedded in generated code) +const Lux = { + // Option helpers + Some: (value) => ({ tag: "Some", value }), + None: () => ({ tag: "None" }), + + // Result helpers + Ok: (value) => ({ tag: "Ok", value }), + Err: (error) => ({ tag: "Err", error }), + + // List helpers + Cons: (head, tail) => [head, ...tail], + Nil: () => [], + + // Effect handler invoker + handle: async (computation, handlers) => { + return await computation(handlers); + } +}; +``` + +--- + +## Browser Integration + +### Entry Point + +```lux +// app.lux +fn main(): Unit with Dom = { + let button = Dom.createElement("button") + Dom.setTextContent(button, "Click me!") + Dom.addEventListener(button, "click", fn(): Unit => { + Dom.setTextContent(button, "Clicked!") + }) + let body = Dom.querySelector("body") + match body { + Some(el) => Dom.appendChild(el, button), + None => () + } +} +``` + +Compiles to: +```javascript +async function main_lux(handlers) { + const button = handlers.Dom.createElement("button"); + handlers.Dom.setTextContent(button, "Click me!"); + handlers.Dom.addEventListener(button, "click", function() { + handlers.Dom.setTextContent(button, "Clicked!"); + }); + const body = handlers.Dom.querySelector("body"); + if (body.tag === "Some") { + handlers.Dom.appendChild(body.value, button); + } +} + +// Browser handler +const BrowserDom = { + createElement: (tag) => document.createElement(tag), + setTextContent: (el, text) => { el.textContent = text; }, + addEventListener: (el, event, handler) => el.addEventListener(event, handler), + querySelector: (sel) => { + const el = document.querySelector(sel); + return el ? Lux.Some(el) : Lux.None(); + }, + appendChild: (parent, child) => parent.appendChild(child) +}; + +// Initialize +main_lux({ Dom: BrowserDom }); +``` + +### HTML Integration + +```html + + + + Lux App + + + + + + +``` + +--- + +## Self-Hosting the Website + +Once the JS backend is complete, the lux-lang.org website can be built in Lux: + +```lux +// website/src/Main.lux + +import Html.{div, h1, p, button, text} +import App.{Model, Msg, init, update, view} + +fn main(): Unit with Dom = { + let model = init() + let root = Dom.querySelector("#app") + match root { + Some(el) => render(el, model), + None => Console.print("No #app element found") + } +} + +fn render(root: Element, model: Model): Unit with Dom = { + let html = view(model) + Dom.setInnerHtml(root, html) +} +``` + +--- + +## Testing Strategy + +### Unit Tests + +```rust +#[test] +fn test_js_function_generation() { + let input = "fn add(a: Int, b: Int): Int = a + b"; + let js = JsBackend::compile(input).unwrap(); + assert!(js.contains("function add_lux(a, b)")); + assert!(js.contains("return a + b")); +} +``` + +### Integration Tests + +Run generated JS in Node.js and compare output: + +```rust +#[test] +fn test_fibonacci_js() { + let lux_code = include_str!("../../examples/fibonacci.lux"); + let js_code = JsBackend::compile(lux_code).unwrap(); + + let output = Command::new("node") + .arg("-e") + .arg(&js_code) + .output() + .unwrap(); + + assert!(String::from_utf8_lossy(&output.stdout).contains("fib(10) = 55")); +} +``` + +### Browser Tests + +Use Playwright/Puppeteer to test DOM manipulation: + +```javascript +test('button click works', async ({ page }) => { + await page.goto('http://localhost:3000/test.html'); + await page.click('button'); + expect(await page.textContent('button')).toBe('Clicked!'); +}); +``` + +--- + +## Timeline + +| Phase | Duration | Milestone | +|-------|----------|-----------| +| Phase 1: Core Language | 2-3 weeks | Fibonacci runs in Node.js | +| Phase 2: Standard Library | 1-2 weeks | Examples work in browser | +| Phase 3: Effects | 2 weeks | HTTP works in browser | +| Phase 4: DOM Support | 2-3 weeks | Interactive page in Lux | +| Phase 5: CLI Integration | 1 week | `lux compile --target js` | +| Phase 6: WASM | 3-4 weeks | WASM execution | + +**Total: 11-15 weeks** for full JS/WASM support + +--- + +## Success Criteria + +1. **Correctness**: All existing tests pass when targeting JS +2. **Performance**: Within 2x of hand-written JS for benchmarks +3. **Size**: Generated JS is reasonable size (< 2x hand-written equivalent) +4. **Interop**: Easy to call Lux from JS and JS from Lux +5. **Self-hosting**: lux-lang.org runs entirely on Lux-compiled JS + +--- + +## References + +- [Gleam JS Compilation](https://gleam.run/news/v0.16-gleam-compiles-to-javascript/) +- [Elm JavaScript Interop](https://guide.elm-lang.org/interop/) +- [Koka JavaScript Backend](https://koka-lang.github.io/koka/doc/book.html) +- [PureScript Code Generation](https://github.com/purescript/purescript/tree/master/src/Language/PureScript/CodeGen) diff --git a/docs/WEBSITE_PLAN.md b/docs/WEBSITE_PLAN.md new file mode 100644 index 0000000..2ca5210 --- /dev/null +++ b/docs/WEBSITE_PLAN.md @@ -0,0 +1,323 @@ +# Lux Language Website Plan + +## Research Summary + +Analyzed 6 beloved language websites: **Elm**, **Gleam**, **Rust**, **Elixir**, **Zig**, and **Go**. + +### Key Patterns from Successful Language Websites + +| Pattern | Examples | Why It Works | +|---------|----------|--------------| +| **Emotional benefits over features** | Elm: "deploy and go to sleep" | Developers buy peace of mind, not feature lists | +| **Problem-first messaging** | Rust: addresses memory bugs, Zig: "no hidden control flow" | Validates pain points before offering solution | +| **Runnable code immediately** | Go Playground, Gleam Tour | Reduces friction, proves language works | +| **Social proof** | Go: PayPal, Google testimonials | Builds credibility for enterprise adoption | +| **Use-case segmentation** | Rust: CLI, WASM, networking, embedded | Helps users self-identify relevance | +| **Progressive disclosure** | All: simple → complex | Doesn't overwhelm newcomers | +| **Built with itself** | Elm site is built in Elm | Meta demonstration of capabilities | +| **Inclusive community** | Gleam: prominent Code of Conduct | Signals healthy ecosystem | + +--- + +## Lux's Unique Value Proposition + +### Core Differentiators + +1. **Effects are better than monads** - More intuitive for learning FP +2. **Compile-time effect tracking** - Know exactly what code does +3. **Swap handlers for testing** - No mocks needed +4. **Native performance** - Compiles to C, matches Rust/C speed +5. **Functional but practical** - Not academic, production-ready + +### Tagline Options + +- "A functional language with first-class effects" +- "Know what your code does. All of it." +- "Effects you can see. Tests you can trust." +- "Functional programming that makes sense" + +### Target Audiences + +1. **Haskell/FP developers** frustrated by monads +2. **Backend developers** wanting type safety without Java verbosity +3. **Educators** teaching functional programming +4. **Teams** wanting testable, maintainable code + +--- + +## Website Structure + +### Navigation + +``` +[Logo: Lux] Learn Docs Playground Community GitHub +``` + +### Section 1: Hero + +**Headline:** "Functional programming with first-class effects" + +**Subheadline:** "See exactly what your code does. Test it without mocks. Deploy with confidence." + +**CTA Buttons:** +- [Try Lux] → Interactive playground +- [Get Started] → Installation guide + +**Visual:** Animated effect flow visualization or side-by-side code showing effect signatures + +### Section 2: The Problem (Pain Points) + +**"The problem with side effects"** + +> "Most bugs come from code doing things you didn't expect—network calls, file writes, database queries hidden deep in the call stack." + +Show side-by-side: +- **Other languages:** Function signature doesn't reveal what it does +- **Lux:** Effect signature makes all side effects explicit + +```lux +// In Lux, the type tells you everything +fn fetchUser(id: Int): User with Http, Database = { + // You KNOW this touches network and database +} +``` + +### Section 3: The Solution (3 Pillars) + +#### Pillar 1: Effects You Can See +- Every function declares its effects +- No hidden surprises in production +- Refactor with confidence + +```lux +fn processOrder(order: Order): Result with Database, Email = { + let saved = Database.save(order) + Email.send(order.customer, "Order confirmed!") + Ok(Receipt(saved.id)) +} +``` + +#### Pillar 2: Testing Without Mocks +- Swap effect handlers at runtime +- Test database code without a database +- Test HTTP code without network + +```lux +// Production +handle processOrder(order) with { + Database -> realDatabase, + Email -> smtpServer +} + +// Test - same code, different handlers +handle processOrder(order) with { + Database -> inMemoryStore, + Email -> collectMessages +} +``` + +#### Pillar 3: Native Performance +- Compiles to C via gcc -O2 +- Matches Rust/C performance +- Reference counting with FBIP optimization + +| Benchmark | Lux | Rust | Go | Node.js | +|-----------|-----|------|----|---------| +| Fibonacci | 0.015s | 0.018s | 0.041s | 0.110s | +| Ackermann | 0.020s | 0.029s | 0.107s | 0.207s | + +### Section 4: Learn by Example + +**Interactive code snippets** (using playground embeds): + +1. **Hello World** - Basic syntax +2. **Pattern Matching** - ADTs and matching +3. **Effects** - Console, File, HTTP +4. **Handlers** - Swapping implementations +5. **Testing** - Effect-based testing + +Each example: Code + "Run" button + explanation + +### Section 5: Use Cases + +#### Backend Services +- Effect tracking documents all side effects +- Swap database handlers for testing +- JSON, HTTP, SQL built-in + +#### Reliable Systems +- `is pure`, `is total` behavioral types +- Compile-time guarantees +- Idempotency verification (coming soon) + +#### Teaching FP +- Effects more intuitive than monads +- Clear progression: pure → effects → handlers +- Excellent error messages + +### Section 6: Social Proof + +**"What developers are saying"** + +(Placeholder for future testimonials) + +**Companies using Lux** (logos when available) + +**Benchmark results** - Comparison chart vs Rust, Go, Node, Python + +### Section 7: Getting Started + +```bash +# Install +curl -sSL https://lux-lang.org/install.sh | sh + +# Create project +lux new my-app +cd my-app + +# Run +lux run +``` + +**Next steps:** +- [Language Tour] - Interactive tutorial +- [Guide] - In-depth documentation +- [Examples] - Real-world code +- [API Reference] - Standard library + +### Section 8: Community + +- **GitHub** - Source code, issues, PRs +- **Discord** - Chat with the community +- **Forum** - Discussions +- **Code of Conduct** - Inclusive community + +--- + +## Design Principles + +### Visual Identity + +- **Primary color:** Deep purple/violet (#6B46C1) - unique, memorable +- **Accent:** Teal (#0D9488) for CTAs +- **Background:** Clean whites and light grays +- **Typography:** System fonts for performance, monospace for code + +### Code Highlighting + +Syntax highlighting theme that emphasizes: +- **Effects** - Different color to make them stand out +- **Types** - Clear distinction from values +- **Keywords** - Subtle but readable + +### Interactive Elements + +- **Playground embeds** - Run code in browser +- **Animated effects flow** - Visualize how effects propagate +- **Hover tooltips** - Type information on code examples + +--- + +## Technical Implementation + +### Self-Hosting Goal + +The website should be **built in Lux** (like Elm's site), demonstrating: +- Lux compiles to JavaScript/WASM +- Full-stack Lux is possible +- The language is production-ready + +### Architecture + +``` +┌─────────────────────────────────────────┐ +│ lux-lang.org │ +├─────────────────────────────────────────┤ +│ Frontend (Lux → WASM/JS) │ +│ - Interactive playground │ +│ - Animated examples │ +│ - Client-side routing │ +├─────────────────────────────────────────┤ +│ Backend (Lux → Native) │ +│ - Serve static content │ +│ - Playground compilation API │ +│ - Package registry (future) │ +└─────────────────────────────────────────┘ +``` + +### Required Language Features + +To build the website in Lux, we need: + +| Feature | Status | Priority | +|---------|--------|----------| +| JS backend | Missing | P0 | +| WASM backend | Missing | P1 | +| DOM manipulation effect | Missing | P1 | +| HTML DSL | Missing | P2 | +| CSS-in-Lux | Missing | P2 | +| Virtual DOM/diffing | Missing | P2 | +| Client routing | Missing | P2 | + +--- + +## Content Priorities + +### Phase 1: Essential Content + +1. **Landing page** - Hero, 3 pillars, getting started +2. **Installation guide** - All platforms +3. **Language tour** - Interactive tutorial +4. **Effect system guide** - Core concept explanation +5. **Standard library reference** - API docs + +### Phase 2: Expansion + +6. **Cookbook** - Common patterns +7. **Video tutorials** - YouTube/embedded +8. **Comparison guides** - vs Haskell, vs Rust, vs TypeScript +9. **Blog** - Updates, deep dives +10. **Showcase** - Projects built with Lux + +### Phase 3: Community + +11. **Package registry** - Browse packages +12. **Forum integration** - Discussions +13. **Contribution guide** - How to contribute +14. **Governance** - RFC process + +--- + +## Success Metrics + +| Metric | Target | +|--------|--------| +| Time to first code run | < 60 seconds | +| Tutorial completion rate | > 50% | +| GitHub stars after website launch | 1000 in 6 months | +| Package registry submissions | 50 in first year | +| "I finally understand effects" comments | Qualitative goal | + +--- + +## Inspiration Summary + +| From | Take | +|------|------| +| **Elm** | Emotional messaging, interactive demos, built-with-itself | +| **Gleam** | Friendly tone, ecosystem emphasis, inclusive community | +| **Rust** | Problem-first messaging, use-case segmentation | +| **Go** | Pragmatic testimonials, playground, multiple learning paths | +| **Elixir** | Case studies, real code examples, ecosystem confidence | +| **Zig** | Transparency, C interop story, pragmatic positioning | + +--- + +## Next Steps + +1. **Build JS/WASM backend** - Required to self-host +2. **Create playground** - Run Lux in browser +3. **Write language tour** - Interactive tutorial +4. **Design visual identity** - Logo, colors, typography +5. **Build MVP landing page** - Even if not in Lux initially +6. **Launch and iterate** - Get feedback early