# Hamelin AST

The Abstract Syntax Tree for the Hamelin query language. This is the structured representation of parsed Hamelin queries used for SQL translation.

## Architecture

The AST is built in layers, with each layer depending only on those below:

```
query.rs        → Top-level queries with WITH clauses
    ↓
pipeline.rs     → Sequences of piped commands
    ↓
command.rs      → Individual commands (WHERE, SELECT, JOIN, etc.)
    ↓
clause.rs       → Reusable components (assignments, sort specs)
    ↓
expression.rs   → Expressions (literals, operators, functions)
```

## Key Design Principles

1. **Error Recovery**: Every AST node can represent errors, allowing partial parsing to continue
2. **Diagnostic Sink**: Errors accumulate in a diagnostic sink during construction, but are also stored in the AST
3. **CST Preservation**: Optional references to Concrete Syntax Tree nodes
4. **No Panics**: All conversions are safe. Never `unwrap()` or `expect()`
5. **Builder Pattern**: AST builders for ergonomic AST construction
6. **Zero-Copy Errors**: Errors use `Rc<TranslationError>` for efficient sharing between tree and sink

## Core Types

- `Query` - Entry point, handles WITH clauses and main pipeline
- `Pipeline` - Chain of commands connected by pipes
- `Command` - Individual operations (20+ variants like WHERE, SELECT, JOIN)
- `Expression` - Values, operators, function calls
- `Pattern` - Pattern matching for the MATCH command
- `Identifier` - Names that can be simple or qualified

## Usage

```rust
// Parse a query
let (ast, errors) = Query::parse("FROM events | WHERE severity > 3");

// AST preserves structure even with errors
if !errors.is_empty() {
    // Render beautiful error messages with source context
    eprintln!("{}", errors);
}

// During parsing, errors accumulate in the diagnostic sink
let mut ctx = ParseContext::new();
let ast = Query::from_cst(cst, &mut ctx);
let errors = ctx.take_errors();  // O(1) error collection
```

## Error Handling

The AST uses a **Diagnostic Sink Pattern** for efficient error collection:

- **Diagnostic Sink**: Errors accumulate in a `Vec<Rc<TranslationError>>` during construction
- **ErrorBuilder API**: Fluent interface for constructing rich errors with context
- **O(1) Collection**: No tree traversal needed to get the errors. But they stay in the tree if you need them.

### Error Construction
```rust
// Beautiful fluent API for error building
ctx.error("type mismatch")
    .at(expr)                        // Attach span from AST node
    .with_source(underlying_error)   // Chain errors
    .add_context(span, "expected Int") // Add contextual information
    .emit();                         // Add to sink & return Rc
```
