diff --git a/SKILLS.md b/SKILLS.md index a8a1dc2..323bcfe 100644 --- a/SKILLS.md +++ b/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 ` 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 ``? -- [ ] 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 --- diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 3f3c319..80b3714 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -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 diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index fc9fd8a..19574d4 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -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`) diff --git a/docs/VISION.md b/docs/VISION.md index a63fb33..775950e 100644 --- a/docs/VISION.md +++ b/docs/VISION.md @@ -124,25 +124,29 @@ fn retry(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 | --- diff --git a/docs/guide/05-effects.md b/docs/guide/05-effects.md index 769ad00..f22c553 100644 --- a/docs/guide/05-effects.md +++ b/docs/guide/05-effects.md @@ -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: diff --git a/docs/guide/09-stdlib.md b/docs/guide/09-stdlib.md index b85948e..7b2dacc 100644 --- a/docs/guide/09-stdlib.md +++ b/docs/guide/09-stdlib.md @@ -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 diff --git a/docs/reference/syntax.md b/docs/reference/syntax.md index d7a334e..52b5f9f 100644 --- a/docs/reference/syntax.md +++ b/docs/reference/syntax.md @@ -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 diff --git a/docs/testing.md b/docs/testing.md index d0a2a7d..b2a27f8 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -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.