--- epic: 1 story: 1.3 title: "Interpreter / Evaluator" status: draft --- ## Epic 1 — Core Calculation Engine (Rust Crate) **Goal:** Build `calcpad-engine` as a standalone Rust crate that powers all platforms. This is the foundation. ### Story 1.3: Interpreter / Evaluator As a CalcPad engine consumer, I want the AST evaluated into typed results with metadata, So that each line produces a meaningful, displayable calculation result. **Acceptance Criteria:** **Given** an AST representing `2 + 3` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `Number` with value `5` **Given** an AST representing `5kg + 200g` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `UnitValue` with value `5.2 kg` **And** the result unit matches the left-hand operand's unit **Given** an AST representing `$20 in EUR` **When** the interpreter evaluates it within a context that has exchange rates loaded **Then** it returns a `CalcResult` of type `CurrencyValue` with the converted amount and target currency `EUR` **Given** an AST representing `today + 3 weeks` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `DateTime` with the correct future date **Given** an AST representing `March 12 to July 30` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `TimeDelta` representing the duration between the two dates **Given** an AST representing `5 > 3` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `Boolean` with value `true` **Given** an AST representing `100 - 20%` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `Number` with value `80` **And** the percentage is interpreted as "20% of 100" subtracted from 100 **Given** an AST representing `$100 + 10%` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `CurrencyValue` with value `$110` **Given** an AST with incompatible unit arithmetic such as `5kg + 3m` **When** the interpreter evaluates it **Then** it returns a `CalcResult` of type `Error` with a message indicating incompatible units **And** the error includes the span of the offending expression **Given** any evaluated result **When** the result is produced **Then** it includes metadata: the input span, the result type, display-formatted string, and raw numeric value where applicable