shape-runtime 0.3.0

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// @module std::core::sub
/// `Sub` and `SubAssign` — operator traits for `-` and `-=`.
///
/// Shape's strict-typing arithmetic dispatch for built-in scalar types
/// (`int`, `number`, `decimal`, `bigint`) emits typed opcodes
/// (`SubInt`, `SubNumber`, ...) at compile time and never routes through
/// this trait. User-defined types (`type X { ... }`) that want to
/// participate in `-` / `-=` opt in by providing an
/// `impl Sub for X { method sub(other: X) -> X { ... } }` block; the
/// compiler then desugars `a - b` to `Sub::sub(a, b)` via the operator
/// trait dispatch path at `compiler/expressions/binary_ops.rs:1459-1473`
/// (the generic arithmetic arm — `BinaryOp::Sub` has no dedicated arm
/// like `BinaryOp::Add` does, so it falls into the shared `_ =>` branch
/// where `try_emit_trait_dispatch` / `operator_trait_for_op` look up
/// `Sub`).
///
/// `SubAssign` is the in-place counterpart. `a -= b` is grammar-desugared
/// at parse time to `a = a - b`, so authoring an `impl Sub for X` already
/// covers `-=` for user-defined types without a separate
/// `SubAssign::sub_assign` body. `SubAssign` is declared here for symmetry
/// with future in-place optimizations (e.g. `Buffer.sub_assign(other)`
/// that mutates in-place instead of allocating a fresh value) and so
/// generic bounds `fn f<T: SubAssign>(...)` can be authored today.
///
/// ## Architectural note (mirrors `std::core::add`)
///
/// `SubAssign::sub_assign` is declared with an explicit `Self` return
/// type by convention (the in-place op canonically returns `self` for
/// chaining). See the parallel `add.shape` note for the W6 imprecision 83
/// background that previously forced `: Self` on the AddAssign trait
/// method as a parse-failure-cascade workaround; for SubAssign we follow
/// the same shape for symmetry, not because the workaround is required.
///
/// ## Known implementations
///
/// | Type        | Dispatch source                                  |
/// |-------------|--------------------------------------------------|
/// | int         | typed `SubInt` opcode (no trait dispatch)        |
/// | number      | typed `SubNumber` opcode (no trait dispatch)     |
/// | decimal     | typed decimal-sub opcode (no trait dispatch)     |
/// | bigint      | typed bigint-sub opcode (no trait dispatch)      |
/// | DateTime    | builtin `DATETIME_METHODS::sub` PHF entry        |
/// | TimeSpan    | builtin `TIMESPAN_METHODS::sub` PHF entry        |
/// | user type X | `impl Sub for X { method sub(other: X) -> X }`   |

/// Operator trait for `-`. Implementing `Sub` for a user-defined type
/// enables the binary `-` operator on values of that type. The compiler
/// calls `Sub::sub(lhs, rhs)` via UFCS dispatch through the
/// `function_name_index` for `X::sub`.
trait Sub {
    /// Return `self - other`. By convention the result is a fresh value;
    /// in-place mutation belongs to `SubAssign::sub_assign`.
    method sub(other: Self) -> Self;
}

/// Operator trait for `-=`. The grammar desugars `a -= b` to `a = a - b`,
/// so providing `impl Sub for X` already covers `-=` for user-defined
/// types — `SubAssign` is declared here for generic bounds and for the
/// future in-place specialization opt-in.
///
/// The return type is `Self` for symmetry with `AddAssign` (see the
/// module-level architectural note); implementations may mutate `self`
/// in place and `return self` from the method body. The parse-time
/// desugar means the return value is unused under current semantics.
trait SubAssign {
    /// Mutate `self` in place by subtracting `other`. Return `self` for chaining.
    method sub_assign(other: Self) -> Self;
}