UNPKG

@macroforge/mcp-server

Version:

MCP server for Macroforge documentation and code analysis

109 lines (80 loc) • 4.45 kB
# PartialOrd The `PartialOrd` macro generates a `partialCompare()` method for **partial ordering** comparison. This is analogous to Rust's `PartialOrd` trait, enabling comparison between values where some pairs may be incomparable. Like `partial_cmp` and `cmp` in Rust, it sits beside `Ord`'s `compare()` without colliding. ## Generated Output | Type | Generated Code | Description | | ---------- | --------------------------------------------------------------- | ---------------------------------------------- | | Class | `classNamePartialCompare(a, b)` + `static partialCompare(a, b)` | Standalone function + static wrapper method | | Enum | `enumNamePartialCompare(a, b): number \| null` | Standalone function returning `number \| null` | | Interface | `ifaceNamePartialCompare(a, b): number \| null` | Standalone function returning `number \| null` | | Type Alias | `typeNamePartialCompare(a, b): number \| null` | Standalone function returning `number \| null` | Names use **camelCase** conversion (e.g., `Temperature` → `temperaturePartialCompare`). ## Return Values Unlike `Ord`, `PartialOrd` returns `number | null` to handle incomparable values: - **negative**: `a` is less than `b` - **0**: `a` is equal to `b` - **positive**: `a` is greater than `b` - **null**: Values are incomparable A comparison is `0` exactly when the derived `PartialEq` holds. Strings therefore order by UTF-16 code units, not `localeCompare`, which can call distinct strings equal. ## When to Use PartialOrd vs Ord - **PartialOrd**: When some values may not be comparable - Example: Floating-point NaN values - Example: Mixed-type unions - Example: Type mismatches between objects - **Ord**: When all values are guaranteed comparable (total ordering) ## Comparison Strategy Fields are compared **lexicographically** in declaration order: 1. Compare first field 2. If incomparable, return `null` 3. If not equal, return that result 4. Otherwise, compare next field 5. Continue until a difference is found or all fields are equal ## Type-Specific Comparisons | Type | Comparison Method | | --------------------------- | --------------------------------------------------------------------------- | | `number` | `<` and `>`; `null` when either is `NaN` | | `bigint`, `string` | `<` and `>`, strings by UTF-16 code units | | `boolean` | `false < true` | | Optional and nullable | An absent value orders first | | Arrays | Lexicographic, each element by its own type; `null` on an unordered element | | `Date` | Timestamp; `null` if invalid | | Types deriving `PartialOrd` | Their `partialCompare` function | | Anything else | `structuralCompare` from `@macroforge/core/structural` | ## Requirements `PartialOrd` requires `PartialEq`, as in Rust. Deriving it without `PartialEq` is an expansion error. ## Field-Level Options The `@ord` decorator supports: - `skip` - Exclude the field from ordering comparison ## Example ```typescript before /** @derive(PartialEq, PartialOrd) */ class Temperature { value: number; unit: string; } ``` ```typescript after class Temperature { value: number; unit: string; static partialCompare(a: Temperature, b: Temperature): number | null { return temperaturePartialCompare(a, b); } } export function temperaturePartialCompare(a: Temperature, b: Temperature): number | null { if (a === b) return 0; const cmp0 = a.value < b.value ? -1 : a.value > b.value ? 1 : a.value === b.value ? 0 : null; if (cmp0 === null) return null; if (cmp0 !== 0) return cmp0; const cmp1 = a.unit < b.unit ? -1 : a.unit > b.unit ? 1 : 0; if (cmp1 === null) return null; if (cmp1 !== 0) return cmp1; return 0; } ``` ## Return Type The generated functions return `number | null` where `null` indicates incomparable values.