# CLAUDE.md -- Rust Project Conventions

## Philosophy

This project follows **functional**, **type-driven**, and **domain-driven** design principles.  The type system is the primary tool for correctness.

## Architecture

- **Modules by domain context**, not by technical layer.
- Each bounded context gets its own module with its own types.
- Prefer thin `main.rs`/`lib.rs` that wires contexts together.

## Types

- **Newtypes** for all domain primitives.
- **Sum types (enums)** to model variants.
- **No public struct fields**.  Enum variants with named fields are permitted.
- `#[must_use]` on pure functions and types whose values should not be silently dropped.

## Error Handling

- A single project-wide `Error` enum in a dedicated `error` module.
- Implement `std::fmt::Display` and `std::error::Error` by hand -- no `thiserror`, no `anyhow`.
- Domain logic returns `Result<T, Error>`.  Never panic.

## Style

- **Prefer `match` over `if`/`else`**, except when branching on `bool`.
- **No `return` keyword**.
- **No `mut`**.
- **Combinators** over loops where readable.
- **Never match on `Option<_>`**.  Use combinators.
- **Prefer combinators on `Result<_, _>`**.
- **No `unwrap()`/`expect()`**.
- **No `loop` or `for`**.  Use combinators or recursion.
- **No `scan`**.
- **No reference counting** (`Rc`, `Arc`).
- **No naked `as` casts**.
- **Exhaustive matches**.  Never use `_` wildcard arm on enum matches.
- Prefer iterators over indexed access.

## Traits

- **No dynamic polymorphism** (`dyn Trait`).
- **Implement standard traits** instead of ad-hoc methods.

## Linting

```toml
[lints.clippy]
all = { level = "deny", priority = -1 }
pedantic = { level = "warn", priority = -1 }
needless_pass_by_value = "warn"
manual_map = "warn"
```

## Verification

- Always run `RUSTFLAGS="-D warnings" cargo clippy --all-targets`.
- Always run `cargo fmt`.

## Testing

- Tests return `Result<(), Error>` and propagate failures with `?`.  No `assert!`, `assert_eq!`, `panic!`, `unreachable!`, `unwrap`, `expect`.
- Unit tests in `#[cfg(test)]` modules in the same file.
- Integration tests in `tests/`.

## Dependencies

- `ecma-syntax-cat = "0.1"` for `Span`, `Position`, and the AST types this crate's tokens map to.
- `proptest` as dev-dependency.
- **No path dependencies** in `Cargo.toml`.  Plain crates.io versions only.
- No `thiserror`, no `anyhow`.

## Documentation

- `///` doc comments on every public item.
- `# Examples` with runnable code blocks.
- Doctests must not use `unwrap`, `expect`, or `unreachable!`.

## Layer context

This crate is the **lexer** in the boa-cat stack:

1. `ecma-syntax-cat` -- AST types (foundation, no deps).
2. **`ecma-lex-cat`** -- tokenizer; consumes a source string, produces `Vec<Token>`.
3. `ecma-parse-cat` -- parser; consumes tokens, produces `ecma-syntax-cat::Program`.
4. `boa-cat` -- engine; evaluates programs.
5. `ecma-runtime-cat` -- built-in globals and intrinsics.
6. `tauri-runtime-servocat` -- Tauri bridge.

The lexer is the only layer where context-sensitive disambiguation (regex vs division, template literal vs expression) lives at the token level; downstream layers see a clean stream of `Token` values.
