# Hamelin TypedAST

The Type-Checked Abstract Syntax Tree for the Hamelin query language. This layer
performs semantic analysis, type checking, and schema validation on the parsed
AST before SQL translation.

## Overview

The TypedAST transforms the untyped AST into a fully type-checked representation where:
- Every expression has a resolved type
- Every command tracks input and output schemas
- Field references are validated against schemas
- Function signatures are checked
- Type coercion rules are applied

## Architecture

### Three-Layer Design

```
TypedStatement     → Top-level with CTEs and pipeline classification
    ↓
TypedPipeline     → Query/DML/DDL pipeline variants with schema tracking
    ↓
TypedCommand      → Individual commands with input/output schemas
    ↓
TypedExpression   → Fully typed expressions with resolved types
```

### Core Types

#### TypedCommand
```rust
pub struct TypedCommand {
    pub ast: Rc<Command>,           // Original AST node
    pub input_schema: Arc<Environment>,  // Schema before command
    pub output_schema: Arc<Environment>, // Schema after command
    pub kind: TypedCommandKind,     // Command-specific typed variant
}
```

#### TypedExpression
```rust
pub struct TypedExpression {
    pub ast: Rc<Expression>,        // Original AST node
    pub resolved_type: Rc<Type>,    // Inferred/resolved type
    pub kind: TypedExpressionKind,  // Expression-specific typed variant
}
```

## Type System

### Type Inference

The TypedAST performs bidirectional type checking:

1. **Bottom-up inference** for literals and field references
2. **Top-down checking** for function arguments and operators
3. **Constraint solving** for complex expressions

Example:
```rust
// Input: x > 5
// Process:
// 1. Lookup x in schema → Int
// 2. Literal 5 → Int
// 3. Check operator > (Int, Int) → Bool
// 4. Result type: Bool
```

### Schema Tracking

Every command maintains schema flow:

```
FROM events                 → Schema: {timestamp, severity, message}
| WHERE severity > 3        → Schema: {timestamp, severity, message} (unchanged)
| SELECT timestamp, message → Schema: {timestamp, message} (transformed)
```

## Command Classification

The TypedAST classifies pipelines into three categories:

### Query Pipelines
Read-only operations that produce result sets:
- `FROM`, `WHERE`, `SELECT`, `JOIN`, `AGG`, `WINDOW`, `SORT`, `LIMIT`

### DML Pipelines
Data modification operations:
- `APPEND`,

### DDL Pipelines
Schema modification operations:
- `CREATE`,

## Error Handling

### Diagnostic Sink Pattern

The TypedAST uses an efficient diagnostic sink for error collection:

```rust
// Errors accumulate in the translation context
let mut ctx = StatementTranslationContext::new(environment);

// Beautiful error construction with context
ctx.error("type mismatch in binary operation")
    .at(expr)                           // Attach span
    .add_context(left_span, "left: Int")
    .add_context(right_span, "right: String")
    .emit();                            // Add to sink

let errors = ctx.take_errors();
```

### Error Recovery

Even with type errors, the TypedAST maintains structure:

```rust
// Type error → Unknown type, but structure preserved
let typed_expr = TypedExpression {
    ast: expr,
    resolved_type: Rc::new(Type::Unknown),  // Graceful degradation
    kind: TypedExpressionKind::Error(err),
};
```

## Usage

### Type-Checking a Pipeline

```rust
use hamelin_lib::tree::typed_ast::TypedPipeline;

// Parse AST first
let (ast, parse_errors) = Pipeline::parse("FROM events | WHERE severity > 3");

// Type-check with environment
let mut ctx = StatementTranslationContext::new(environment);
let typed_pipeline = TypedPipeline::from_ast_with_context(ast, &mut ctx);
let type_errors = ctx.take_errors();

// Access schema information
match typed_pipeline {
    TypedPipeline::Query(q) => {
        if let TypedQueryPipelineKind::Valid { final_schema, .. } = &q.kind {
            println!("Output schema: {:?}", final_schema);
        }
    }
    _ => {}
}
```

## Design Principles

1. **Complete Type Information**: Every expression has a resolved type
2. **Schema Flow Tracking**: Commands explicitly track schema transformations
3. **Error Recovery**: Maintain structure even with type errors
4. **Zero-Copy Sharing**: Use Rc/Arc throughout for efficiency
5. **Diagnostic Sink**: O(1) error collection without tree traversal
6. **Contextual Errors**: Rich error messages with spans and context
