# CLAUDE.md -- Rust Project Conventions
## Philosophy
Functional, type-driven, domain-driven.
## Architecture
- Modules by domain context.
- One module per built-in family (`console`, `math`, `json`, `globals`).
- Thin lib.rs that wires them together via `build_globals(heap) -> (Env, Heap)`.
## Types
- Newtypes for domain primitives.
- Sum types for variants.
- No public struct fields; enum variants with named fields are permitted.
- `#[must_use]` on getters and constructors.
## Error Handling
- Single project-wide `Error` enum (currently a thin wrapper around `boa_cat::Error`).
- Display + std::error::Error impls by hand; no thiserror, no anyhow.
- Native callables must never panic. Coerce-or-throw via `Value::String("TypeError: ...")` on bad inputs.
## Style
- Prefer match over if/else, except on bool.
- No `return` keyword.
- No `mut`.
- Combinators over loops.
- Never match on Option<_>; use combinators.
- Prefer combinators on Result<_, _>; match only when arms are complex.
- No unwrap()/expect() anywhere.
- No loop or for.
- No scan.
- No Rc/Arc (exception: comp-cat-rs Stream API requires `Arc<dyn Fn(...)>`).
- No naked `as` casts.
- Exhaustive matches; no `_` wildcard arm on enums.
- Iterators over indexed access.
## Traits
- No dyn Trait (exception: comp-cat-rs effect types use dyn internally).
- Implement standard traits over 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.
- Integration tests in tests/ organized by built-in family.
## Dependencies
- `boa-cat = "0.2"` for the engine.
- `ecma-syntax-cat`, `ecma-lex-cat`, `ecma-parse-cat` for the AST/lex/parse layers.
- `comp-cat-rs` foundation.
- `proptest` dev-dep.
- No path dependencies.
## Documentation
- `///` doc comments on every public item.
- `# Examples` with runnable code blocks.
- Doctests must not use unwrap/expect/unreachable.
## Layer context
This crate is the **runtime** in the boa-cat stack:
1. `ecma-syntax-cat` -- AST types.
2. `ecma-lex-cat` -- tokenizer.
3. `ecma-parse-cat` -- parser.
4. `boa-cat` -- engine.
5. **`ecma-runtime-cat`** -- built-ins.
6. `tauri-runtime-servocat` -- Tauri bridge.
## Strategy
Each built-in is a `NativeFn` (`fn(Vec<Value>, Value, Heap, Fuel) -> EvalResult`). `build_globals(heap)` builds an `(Env, Heap)` pair: the env has cells pointing to either the native callable (for top-level functions like `parseInt`) or an object containing the family's natives (for `Math.*`, `console.*`, `JSON.*`). Downstream callers thread these into `boa_cat::evaluate_program_with`.
The runtime never panics. Bad inputs are returned as `Outcome::Throw(Value::String("TypeError: ..."))` so script-level `try`/`catch` can recover.
## v0 scope
In v0 the runtime ships:
- `console.log` / `console.error` / `console.warn` (write to stderr/stdout).
- `Math.{min, max, abs, floor, ceil, round, sqrt, pow, log, exp, sin, cos, tan, atan, atan2, random}` plus constants `Math.{PI, E}`.
- `JSON.stringify` (basic, no replacer/space).
- Globals `parseInt`, `parseFloat`, `isNaN`, `isFinite`, `Number`, `String`, `Boolean`.
Deferred to v0.2+:
- `JSON.parse`.
- `Object.{keys, values, entries, assign}`.
- `Array.{isArray, from, of}` and `Array.prototype.*`.
- `String.prototype.*` (requires prototype-chain support in boa-cat).
- `Date`, `Promise`, `Symbol`, `Error` constructor.