docs: update documentation to match current implementation
- SKILLS.md: Update roadmap phases with actual completion status - Phase 0-1 complete, Phase 2-5 partial, resolved design decisions - OVERVIEW.md: Add HttpServer, Test effect, JIT to completed features - ROADMAP.md: Add HttpServer, Process, Test effects to done list - VISION.md: Update Phase 2-3 tables with current status - guide/05-effects.md: Add Time, HttpServer, Test to effects table - guide/09-stdlib.md: Add HttpServer, Time, Test effect docs - reference/syntax.md: Fix interpolation syntax, remove unsupported literals - testing.md: Add native Test effect documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
125
SKILLS.md
125
SKILLS.md
@@ -569,36 +569,36 @@ type HttpError = { NotFound | Timeout | ..rest }
|
||||
|
||||
## 5. Implementation Roadmap
|
||||
|
||||
### Phase 0: Foundation
|
||||
### Phase 0: Foundation ✅ COMPLETE
|
||||
|
||||
**Goal**: Minimal viable compiler
|
||||
|
||||
- [ ] Lexer and parser for core syntax
|
||||
- [ ] AST representation
|
||||
- [ ] Basic type checker (no effects, no versions, no properties)
|
||||
- [ ] Interpreter for testing semantics
|
||||
- [ ] REPL
|
||||
- [x] Lexer and parser for core syntax
|
||||
- [x] AST representation
|
||||
- [x] Basic type checker (Hindley-Milner inference)
|
||||
- [x] Interpreter for testing semantics
|
||||
- [x] REPL with history, completions, syntax highlighting
|
||||
|
||||
**Deliverable**: Can type-check and interpret pure functional programs
|
||||
**Deliverable**: Can type-check and interpret pure functional programs ✅
|
||||
|
||||
```lux
|
||||
fn fib(n: Int): Int =
|
||||
if n <= 1 then n else fib(n-1) + fib(n-2)
|
||||
```
|
||||
|
||||
### Phase 1: Effect System
|
||||
### Phase 1: Effect System ✅ COMPLETE
|
||||
|
||||
**Goal**: First-class algebraic effects
|
||||
|
||||
- [ ] Effect declarations
|
||||
- [ ] Effect signatures on functions
|
||||
- [ ] Handler definitions
|
||||
- [ ] `run ... with` syntax
|
||||
- [ ] Effect inference within function bodies
|
||||
- [ ] Effect polymorphism
|
||||
- [ ] Built-in effects (Fail, State, etc.)
|
||||
- [x] Effect declarations
|
||||
- [x] Effect signatures on functions
|
||||
- [x] Handler definitions
|
||||
- [x] `run ... with` syntax
|
||||
- [x] Effect inference within function bodies
|
||||
- [x] Effect polymorphism
|
||||
- [x] Built-in effects (Console, Fail, State, Random, File, Http, Time, Process, Test)
|
||||
|
||||
**Deliverable**: Can define, handle, and compose effects
|
||||
**Deliverable**: Can define, handle, and compose effects ✅
|
||||
|
||||
```lux
|
||||
effect Console { fn print(s: String): Unit }
|
||||
@@ -610,28 +610,33 @@ fn main() =
|
||||
run greet("World") with { Console = stdoutConsole }
|
||||
```
|
||||
|
||||
### Phase 2: Code Generation
|
||||
### Phase 2: Code Generation ⚠️ PARTIAL
|
||||
|
||||
**Goal**: Compile to a real target
|
||||
|
||||
- [ ] IR design (effect-aware)
|
||||
- [ ] Backend selection (LLVM, WASM, or JS)
|
||||
- [ ] Effect handler compilation (CPS or evidence-passing)
|
||||
- [x] JIT compiler (Cranelift) - works for numeric code (~160x speedup)
|
||||
- [x] C backend scaffolding
|
||||
- [ ] Full JIT (strings, lists, ADTs, effects)
|
||||
- [ ] JavaScript backend
|
||||
- [ ] WASM backend
|
||||
- [ ] Optimization passes
|
||||
- [ ] Runtime library
|
||||
|
||||
**Deliverable**: Compiled programs that run natively or in browser
|
||||
|
||||
### Phase 3: Schema Evolution
|
||||
**Current**: `lux compile <file>` JIT compiles numeric code. C backend in progress.
|
||||
|
||||
### Phase 3: Schema Evolution ⚠️ PARTIAL
|
||||
|
||||
**Goal**: Versioned types with migrations
|
||||
|
||||
- [ ] Version annotations on types (`@v1`, `@v2`)
|
||||
- [ ] Compatibility checker
|
||||
- [ ] Migration syntax (`from @v1 = ...`)
|
||||
- [ ] Migration chaining
|
||||
- [x] Version annotations on types (`@v1`, `@v2`)
|
||||
- [x] Migration syntax (`from @v1 = ...`)
|
||||
- [x] Version constraints (`@v2+`, `@latest`)
|
||||
- [x] Runtime versioned values
|
||||
- [x] Schema registry & compatibility checking
|
||||
- [ ] Type system integration (versions partially ignored in typechecker)
|
||||
- [ ] Auto-migration generation
|
||||
- [ ] Codec generation
|
||||
- [ ] Version constraints (`@v2+`, `@latest`)
|
||||
|
||||
**Deliverable**: Types with automatic serialization and migration
|
||||
|
||||
@@ -642,16 +647,19 @@ type Config @v2 { host: String, port: Int, from @v1 = { port: 8080, ..v1 } }
|
||||
let cfg: Config @v2 = Codec.decode(legacyBytes)
|
||||
```
|
||||
|
||||
### Phase 4: Behavioral Types
|
||||
### Phase 4: Behavioral Types ⚠️ PARTIAL
|
||||
|
||||
**Goal**: Property specifications and verification
|
||||
|
||||
- [ ] Property syntax (`is pure`, `where result > 0`)
|
||||
- [ ] Built-in properties (pure, total, idempotent, etc.)
|
||||
- [ ] Refinement type checking
|
||||
- [x] Property syntax (`is pure`, `is total`, `is idempotent`, etc.)
|
||||
- [x] Built-in properties parsing
|
||||
- [x] Pure function checking (no effects)
|
||||
- [ ] Total function verification
|
||||
- [ ] Idempotent verification
|
||||
- [ ] Deterministic verification
|
||||
- [ ] Where clause enforcement
|
||||
- [ ] SMT solver integration (Z3)
|
||||
- [ ] Property-based test generation
|
||||
- [ ] Property inference for simple cases
|
||||
- [ ] `assume` escape hatch
|
||||
|
||||
**Deliverable**: Compile-time verification of behavioral properties
|
||||
@@ -664,49 +672,56 @@ fn abs(x: Int): Int
|
||||
= if x < 0 then -x else x
|
||||
```
|
||||
|
||||
### Phase 5: Ecosystem
|
||||
### Phase 5: Ecosystem ✅ MOSTLY COMPLETE
|
||||
|
||||
**Goal**: Usable for real projects
|
||||
|
||||
- [ ] Package manager
|
||||
- [ ] Standard library
|
||||
- [ ] LSP server (IDE support)
|
||||
- [x] Standard library (List, String, Option, Result, Math, Json modules)
|
||||
- [x] LSP server (diagnostics, hover, completions)
|
||||
- [x] REPL with history, tab completion, syntax highlighting
|
||||
- [x] Formatter
|
||||
- [x] Watch mode / hot reload
|
||||
- [x] Basic debugger
|
||||
- [x] Module system (imports, exports, aliases)
|
||||
- [ ] Package manager (manifest parsing exists, not fully functional)
|
||||
- [ ] Documentation generator
|
||||
- [ ] REPL improvements
|
||||
- [ ] Debugger
|
||||
- [ ] Profiler
|
||||
|
||||
### Phase 6: Advanced Features
|
||||
|
||||
**Goal**: Full language vision
|
||||
|
||||
- [ ] Database effect with schema-aware queries
|
||||
- [ ] HTTP effect with API versioning
|
||||
- [ ] Incremental computation (bonus feature)
|
||||
- [x] HTTP client effect
|
||||
- [x] HTTP server effect
|
||||
- [x] File system effect
|
||||
- [x] Process/shell effect
|
||||
- [x] Test effect (native testing framework)
|
||||
- [ ] Database/SQL effect
|
||||
- [ ] Incremental computation
|
||||
- [ ] Distributed effects (location-aware)
|
||||
- [ ] Proof assistant mode (optional full verification)
|
||||
- [ ] Proof assistant mode
|
||||
|
||||
---
|
||||
|
||||
## Open Design Questions
|
||||
## Resolved Design Decisions
|
||||
|
||||
### Syntax
|
||||
### Syntax (Decided)
|
||||
|
||||
- [ ] Significant whitespace vs braces?
|
||||
- [ ] Effect syntax: `with {E1, E2}` vs `!E1 + E2` vs `<E1, E2>`?
|
||||
- [ ] Version syntax: `@v1` vs `v1` vs `#1`?
|
||||
- [x] Braces for blocks, not significant whitespace
|
||||
- [x] Effect syntax: `with {E1, E2}`
|
||||
- [x] Version syntax: `@v1`, `@v2+`, `@latest`
|
||||
|
||||
### Semantics
|
||||
### Semantics (Decided)
|
||||
|
||||
- [ ] Effect handler semantics: deep vs shallow handlers?
|
||||
- [ ] Version compatibility: structural or nominal?
|
||||
- [ ] Property verification: sound or best-effort?
|
||||
- [x] Deep handlers (algebraic effect style with resume)
|
||||
- [x] Structural compatibility for records
|
||||
- [x] Best-effort property verification (gradual)
|
||||
|
||||
### Pragmatics
|
||||
### Pragmatics (In Progress)
|
||||
|
||||
- [ ] Primary compile target: native, WASM, JS?
|
||||
- [ ] Interop story: FFI design?
|
||||
- [ ] Gradual adoption: can you use Lux from other languages?
|
||||
- Primary target: Tree-walking interpreter (default), JIT for performance
|
||||
- FFI: Shell commands via Process effect
|
||||
- [ ] JavaScript backend for browser use
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -362,19 +362,25 @@ Values + Effects Native Code
|
||||
## Future Roadmap
|
||||
|
||||
**Complete:**
|
||||
- ✅ Standard Library (List, String, Option, Result, JSON)
|
||||
- ✅ Module System (imports, exports, aliases)
|
||||
- ✅ LSP Server (basic diagnostics, hover, completions)
|
||||
- ✅ Standard Library (List, String, Option, Result, Math, JSON)
|
||||
- ✅ Module System (imports, exports, aliases, selective imports)
|
||||
- ✅ LSP Server (diagnostics, hover, completions)
|
||||
- ✅ Generics and String Interpolation
|
||||
- ✅ File/HTTP/Random/Time Effects
|
||||
- ✅ File/HTTP/Random/Time/Process Effects
|
||||
- ✅ HTTP Server Effect (listen, accept, respond, stop)
|
||||
- ✅ Test Effect (native testing framework)
|
||||
- ✅ Console.readLine and Console.readInt
|
||||
- ✅ JIT Compiler for numeric code (~160x speedup)
|
||||
- ✅ Watch mode / hot reload
|
||||
- ✅ Formatter
|
||||
|
||||
**In Progress:**
|
||||
1. **Behavioral Type Verification** - Total, idempotent, deterministic checking
|
||||
2. **Schema Evolution** - Type system integration, auto-migration
|
||||
3. **Error Message Quality** - Elm-style suggestions
|
||||
3. **Error Message Quality** - Context lines shown, suggestions partial
|
||||
|
||||
**Planned:**
|
||||
4. **HTTP Server Effect** - Build web APIs
|
||||
5. **SQL Effect** - Database access
|
||||
6. **Package Manager** - Share code
|
||||
7. **JavaScript Backend** - Run in browsers
|
||||
4. **SQL Effect** - Database access
|
||||
5. **Package Manager** - Share code (manifest parsing exists)
|
||||
6. **JavaScript Backend** - Run in browsers
|
||||
7. **Full JIT** - Strings, lists, ADTs, effects
|
||||
|
||||
@@ -273,10 +273,13 @@
|
||||
**Effect System:**
|
||||
- ✅ Effect declarations and handlers
|
||||
- ✅ Console effect (print, readLine, readInt)
|
||||
- ✅ File effect (read, write, exists, delete, listDir)
|
||||
- ✅ HTTP effect (get, post)
|
||||
- ✅ File effect (read, write, exists, delete, listDir, mkdir)
|
||||
- ✅ HTTP client effect (get, post, put, delete)
|
||||
- ✅ HTTP server effect (listen, accept, respond, stop)
|
||||
- ✅ Process effect (exec, env, args, cwd, exit)
|
||||
- ✅ Random effect (int, float, range, bool)
|
||||
- ✅ Time effect (now, sleep)
|
||||
- ✅ Test effect (assert, assertEqual, assertTrue, assertFalse)
|
||||
|
||||
**Module System:**
|
||||
- ✅ Imports, exports, aliases
|
||||
@@ -285,9 +288,12 @@
|
||||
- ✅ Circular dependency detection
|
||||
|
||||
**Standard Library:**
|
||||
- ✅ String operations
|
||||
- ✅ List operations
|
||||
- ✅ JSON parsing/serialization
|
||||
- ✅ String operations (split, join, trim, contains, replace, toUpper, toLower, etc.)
|
||||
- ✅ List operations (map, filter, fold, head, tail, concat, reverse, find, etc.)
|
||||
- ✅ Option operations (map, flatMap, getOrElse, isSome, isNone)
|
||||
- ✅ Result operations (map, flatMap, getOrElse, isOk, isErr)
|
||||
- ✅ Math operations (abs, min, max, sqrt, pow, floor, ceil, round)
|
||||
- ✅ JSON parsing/serialization (parse, stringify, get, object, array)
|
||||
|
||||
**Tooling:**
|
||||
- ✅ JIT compiler (~160x speedup, CLI: `lux compile`)
|
||||
|
||||
@@ -124,25 +124,29 @@ fn retry<F>(action: F, times: Int): Result
|
||||
| REPL | Done | Interactive development |
|
||||
| Type Checking | Done | With effect tracking |
|
||||
|
||||
### Needed for Real Use (Phase 2: Practical)
|
||||
### Completed (Phase 2: Practical)
|
||||
|
||||
| Feature | Effort | Why It Matters |
|
||||
|---------|--------|----------------|
|
||||
| **Module System** | Done | Imports, exports, aliases, selective imports |
|
||||
| **Standard Library** | Done | List.map, String.split, Option.map, etc. |
|
||||
| **File/Network Effects** | 1-2 weeks | Real IO beyond Console |
|
||||
| **Better Error Messages** | 2-3 weeks | Elm-quality diagnostics |
|
||||
| **Full Compilation** | 4-6 weeks | Cranelift JIT exists for numeric code; needs strings, ADTs, effects |
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| **Module System** | ✅ Done | Imports, exports, aliases, selective imports |
|
||||
| **Standard Library** | ✅ Done | List, String, Option, Result, Math, Json modules |
|
||||
| **File Effect** | ✅ Done | read, write, exists, delete, listDir, mkdir |
|
||||
| **HTTP Client Effect** | ✅ Done | get, post, put, delete |
|
||||
| **HTTP Server Effect** | ✅ Done | listen, accept, respond, stop |
|
||||
| **Process Effect** | ✅ Done | exec, env, args, cwd, exit |
|
||||
| **Random/Time Effects** | ✅ Done | int, float, bool, now, sleep |
|
||||
| **JIT Compiler** | ✅ Partial | Numeric code ~160x faster, strings/ADTs pending |
|
||||
| **Error Messages** | ✅ Partial | Context lines shown, suggestions improving |
|
||||
|
||||
### Needed for Full Vision (Phase 3: Differentiation)
|
||||
### In Progress (Phase 3: Differentiation)
|
||||
|
||||
| Feature | Effort | Why It Matters |
|
||||
|---------|--------|----------------|
|
||||
| **Schema Evolution** | 4-6 weeks | The versioned types system |
|
||||
| **Behavioral Types** | 4-6 weeks | is pure, is idempotent, etc. |
|
||||
| **Effect Tracing/Debugging** | 2-3 weeks | Elm-like debugging |
|
||||
| **LSP Server** | 3-4 weeks | IDE support |
|
||||
| **Package Manager** | 2-3 weeks | Share code |
|
||||
| Feature | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| **Schema Evolution** | ⚠️ Partial | Parsing done, type integration pending |
|
||||
| **Behavioral Types** | ⚠️ Partial | Parsing done, verification pending |
|
||||
| **LSP Server** | ✅ Done | Diagnostics, hover, completions working |
|
||||
| **Package Manager** | ⚠️ Partial | Manifest parsing exists |
|
||||
| **Effect Tracing** | Planned | Elm-like debugging |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -48,9 +48,12 @@ Lux provides several built-in effects:
|
||||
| `Fail` | `fail` | Early termination |
|
||||
| `State` | `get`, `put` | Mutable state |
|
||||
| `Random` | `int`, `float`, `bool` | Random numbers |
|
||||
| `File` | `read`, `write`, `exists` | File system |
|
||||
| `Process` | `exec`, `env`, `args` | System processes |
|
||||
| `Time` | `now`, `sleep` | Time operations |
|
||||
| `File` | `read`, `write`, `exists`, `delete`, `list`, `mkdir` | File system |
|
||||
| `Process` | `exec`, `env`, `args`, `cwd`, `exit` | System processes |
|
||||
| `Http` | `get`, `post`, `put`, `delete` | HTTP client |
|
||||
| `HttpServer` | `listen`, `accept`, `respond`, `stop` | HTTP server |
|
||||
| `Test` | `assert`, `assertEqual`, `assertTrue`, `assertFalse` | Testing |
|
||||
|
||||
Example usage:
|
||||
|
||||
|
||||
@@ -260,6 +260,34 @@ fn example(): Unit with {Http} = {
|
||||
}
|
||||
```
|
||||
|
||||
### HttpServer
|
||||
|
||||
```lux
|
||||
fn example(): Unit with {HttpServer, Console} = {
|
||||
HttpServer.listen(8080) // Start server on port
|
||||
Console.print("Server listening on port 8080")
|
||||
|
||||
let req = HttpServer.accept() // Wait for request
|
||||
// req is { method: String, path: String, body: String, headers: List<(String, String)> }
|
||||
|
||||
Console.print("Got " + req.method + " " + req.path)
|
||||
HttpServer.respond(200, "Hello, World!") // Send response
|
||||
|
||||
HttpServer.stop() // Stop server
|
||||
}
|
||||
```
|
||||
|
||||
### Time
|
||||
|
||||
```lux
|
||||
fn example(): Unit with {Time, Console} = {
|
||||
let start = Time.now() // Current timestamp (milliseconds)
|
||||
Time.sleep(1000) // Sleep for 1 second
|
||||
let elapsed = Time.now() - start
|
||||
Console.print("Elapsed: " + toString(elapsed) + "ms")
|
||||
}
|
||||
```
|
||||
|
||||
### Random
|
||||
|
||||
```lux
|
||||
@@ -292,6 +320,24 @@ fn example(): Int with {Fail} = {
|
||||
}
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
Native testing framework:
|
||||
|
||||
```lux
|
||||
fn runTests(): Unit with {Test, Console} = {
|
||||
Test.assert(1 + 1 == 2, "basic math")
|
||||
Test.assertEqual(List.length([1,2,3]), 3, "list length")
|
||||
Test.assertTrue(String.contains("hello", "ell"), "contains check")
|
||||
Test.assertFalse(List.isEmpty([1]), "non-empty list")
|
||||
}
|
||||
|
||||
// Run with test handler
|
||||
fn main(): Unit with {Console} = {
|
||||
run runTests() with { Test = testReporter }
|
||||
}
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Module | Key Functions |
|
||||
@@ -309,9 +355,12 @@ fn example(): Int with {Fail} = {
|
||||
| File | read, write, exists, list, mkdir, delete |
|
||||
| Process | exec, env, args, cwd, exit |
|
||||
| Http | get, post, put, delete |
|
||||
| HttpServer | listen, accept, respond, stop |
|
||||
| Time | now, sleep |
|
||||
| Random | int, float, bool |
|
||||
| State | get, put |
|
||||
| Fail | fail |
|
||||
| Test | assert, assertEqual, assertTrue, assertFalse |
|
||||
|
||||
## Next
|
||||
|
||||
|
||||
@@ -31,18 +31,15 @@ Examples: `foo`, `myVar`, `Type`, `Option`
|
||||
42
|
||||
-17
|
||||
1_000_000 // Underscores for readability
|
||||
0xFF // Hexadecimal
|
||||
0b1010 // Binary
|
||||
|
||||
// Floats
|
||||
3.14
|
||||
2.5e10
|
||||
-1.5e-3
|
||||
-1.5
|
||||
|
||||
// Strings
|
||||
"hello"
|
||||
"line1\nline2" // Escape sequences
|
||||
"value: ${expression}" // String interpolation
|
||||
"value: {expression}" // String interpolation
|
||||
"multi
|
||||
line
|
||||
string"
|
||||
@@ -77,10 +74,13 @@ false
|
||||
| `\n` | Newline |
|
||||
| `\t` | Tab |
|
||||
| `\r` | Carriage return |
|
||||
| `\0` | Null character |
|
||||
| `\\` | Backslash |
|
||||
| `\"` | Double quote |
|
||||
| `\'` | Single quote |
|
||||
| `\$` | Dollar sign |
|
||||
| `\{` | Literal brace (in interpolated strings) |
|
||||
|
||||
Note: Invalid escape sequences (e.g., `\z`) produce a parse error.
|
||||
|
||||
## Declarations
|
||||
|
||||
|
||||
@@ -2,6 +2,50 @@
|
||||
|
||||
This guide explains how to write and run tests for Lux programs.
|
||||
|
||||
## Native Test Effect
|
||||
|
||||
Lux provides a built-in `Test` effect for writing tests:
|
||||
|
||||
```lux
|
||||
fn runTests(): Unit with {Test, Console} = {
|
||||
// Basic assertions
|
||||
Test.assert(1 + 1 == 2, "basic math")
|
||||
|
||||
// Equality checks
|
||||
Test.assertEqual(List.length([1, 2, 3]), 3, "list length")
|
||||
|
||||
// Boolean assertions
|
||||
Test.assertTrue(String.contains("hello", "ell"), "contains check")
|
||||
Test.assertFalse(List.isEmpty([1]), "non-empty list")
|
||||
}
|
||||
|
||||
// Run with the test handler
|
||||
fn main(): Unit with {Console} = {
|
||||
run runTests() with { Test = testReporter }
|
||||
}
|
||||
|
||||
let result = run main() with {}
|
||||
```
|
||||
|
||||
### Test Effect Operations
|
||||
|
||||
| Operation | Purpose |
|
||||
|-----------|---------|
|
||||
| `Test.assert(condition, message)` | Assert condition is true |
|
||||
| `Test.assertEqual(expected, actual, message)` | Assert values are equal |
|
||||
| `Test.assertTrue(condition, message)` | Assert condition is true (alias) |
|
||||
| `Test.assertFalse(condition, message)` | Assert condition is false |
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run a test file
|
||||
lux tests/my_tests.lux
|
||||
|
||||
# Run with the test runner
|
||||
lux test tests/
|
||||
```
|
||||
|
||||
## Test File Structure
|
||||
|
||||
Lux uses a simple test framework based on comparing program output against expected results. Tests are organized in the `tests/` directory.
|
||||
|
||||
Reference in New Issue
Block a user