shik 0.7.0

A functional scripting language for shell automation
Documentation
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What This Is

**Shik** is a functional, dynamically-typed scripting language for shell automation, implemented as a Rust tree-walk interpreter. Syntax is inspired by Haskell and Lisp: expression-oriented, whitespace-based function application, automatic currying.

## Commands

```bash
cargo build --release      # build (binary: target/release/shik)
cargo test                 # run all tests
cargo test test_parser     # run a single test file
cargo test my_test_name    # run a single test by name
cargo run -- demo/factorial.shk  # run a script
cargo run                        # start REPL
cargo run --ast      # REPL with AST debug output
```

## Architecture

Classic interpreter pipeline: **Lexer → Parser → AST → Evaluator**

```
src/parser/
  lexer.rs      – tokenization; handles string interpolation {…}, comments (;;)
  parser.rs     – Pratt parser producing AST
  ast.rs        – AST node types (Expr enum)
  tokens.rs     – TokenType definitions
  error.rs      – parse errors with Span

src/eval/
  evaluator.rs  – tree-walk interpreter (Interpretator struct)
  value.rs      – runtime Value enum (Null, Bool, Number, String, List, Object, Lambda, NativeClosure, SpecialForm)
  error.rs      – runtime errors with Span
  utils.rs      – pattern matching helpers (define_match, pattern_match)
  native_functions/  – 16 modules: bool, number, string, list, object, file, shell,
                       keywords, branching, variables, polymorphic, function, misc, help, macros

src/lang.rs     – high-level API: evaluate(), print(), run_repl(), eval_file()
src/main.rs     – CLI entry point (file mode or REPL)
src/cli.rs      – CLI argument parsing (parse_args → Command enum), help/version printers
src/repl/
  mod.rs        – REPL entry point: run(ReplConfig); rustyline Editor setup, history (~/.shik_history), main read-eval loop
  helper.rs     – ReplHelper: wires together Highlighter, Validator, Completer for rustyline
  highlighter.rs – ShikHighlighter: tree-sitter-based syntax highlighting via highlights.scm
  validator.rs  – ShikValidator: returns Incomplete on UnexpectedEndOfInput/UnterminatedString for multi-line input
```

Integration tests live in `tests/`, demo scripts in `demo/*.shk`.

## Key Language Semantics

**Operator precedence** (lowest → highest):
1. `$>` – pipe (passes left result as last arg to right)
2. `$` – right-associative chain/application
3. whitespace – function application
4. `#>` – function composition (highest)

**Argument order conventions** (important when adding native functions):
- *Mutation/write*: destination first (`list.set INDEX LIST VALUE`)
- *Read*: specifier first, then target (`list.at INDEX LIST`)
- Non-associative math operators reverse arg order: `(- 1 5)` = 4, `(/ 2 10)` = 5

**Value model**: all values are `Rc<Value>`; environments use `Rc<RefCell<Env>>` with parent chains for lexical scoping. Lists use a view-based `ListRepr` for O(1) head/tail without copying.

**Special forms** (`let`, `fn`, `match`, `if`) are not evaluated eagerly; they are passed as `SpecialForm` values and handled in `apply_special_fn()` inside `evaluator.rs`.

## Adding Native Functions

1. Implement in the appropriate module under `src/eval/native_functions/`.
2. Use the `paste!` macro patterns already present for defining curried functions.
3. Register the function in the module's `bind_*` function that is called from `Interpretator::new()`.
4. Follow the argument order conventions above.