shape-runtime 0.3.2

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// @module std::core::add
/// `Add` and `AddAssign` — operator traits for `+` and `+=`.
///
/// Shape's strict-typing arithmetic dispatch for built-in scalar types
/// (`int`, `number`, `decimal`, `bigint`, `string`) emits typed opcodes
/// (`AddInt`, `AddNumber`, `StringConcatTyped`, ...) 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 Add for X { method add(other: X) -> X { ... } }` block; the
/// compiler then desugars `a + b` to `Add::add(a, b)` via the operator
/// trait dispatch path at `compiler/expressions/binary_ops.rs:69-83`.
///
/// `AddAssign` is the in-place counterpart. `a += b` is grammar-desugared
/// at parse time (`shape-ast/parser/expressions/binary_ops.rs:295-307`) to
/// `a = a + b`, so authoring an `impl Add for X` already covers `+=` for
/// user-defined types without a separate `AddAssign::add_assign` body.
/// `AddAssign` is declared here for symmetry with future in-place
/// optimizations (e.g. `Buffer.add_assign(other)` that mutates in-place
/// instead of allocating a fresh value) and so generic bounds
/// `fn f<T: AddAssign>(...)` can be authored today.
///
/// ## Architectural note (W6 imprecision 83 fix, v0.3)
///
/// `AddAssign::add_assign` is declared with an explicit `Self` return type
/// by convention (the in-place op canonically returns `self` for
/// chaining), but trait methods may omit the return type entirely — the
/// grammar treats a trait method without `: ReturnType` as returning
/// `void`. The Phase 4 close-out workaround that forced `: Self` here to
/// sidestep a parse-failure-cascade bug is no longer required.
///
/// ## Known implementations
///
/// | Type        | Dispatch source                                  |
/// |-------------|--------------------------------------------------|
/// | int         | typed `AddInt` opcode (no trait dispatch)        |
/// | number      | typed `AddNumber` opcode (no trait dispatch)     |
/// | decimal     | typed decimal-add opcode (no trait dispatch)     |
/// | bigint      | typed bigint-add opcode (no trait dispatch)      |
/// | string      | typed `StringConcatTyped` opcode (no dispatch)   |
/// | Array<T>    | typed `ArrayConcat` opcode (no trait dispatch)   |
/// | DateTime    | builtin `DATETIME_METHODS::add` PHF entry        |
/// | TimeSpan    | builtin `TIMESPAN_METHODS::add` PHF entry        |
/// | user type X | `impl Add for X { method add(other: X) -> X }`   |

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

/// Operator trait for `+=`. The grammar desugars `a += b` to `a = a + b`,
/// so providing `impl Add for X` already covers `+=` for user-defined
/// types — `AddAssign` is declared here for generic bounds and for the
/// future in-place specialization opt-in.
///
/// The return type is `Self` (the in-place op returns `self` for
/// chaining) to sidestep a pre-existing compiler bug — see the module-
/// level architectural note. Implementations may mutate `self` in place
/// and `return self` from the method body; the desugar at parse time
/// means the return value is unused under current semantics.
trait AddAssign {
    /// Mutate `self` in place by adding `other`. Return `self` for chaining.
    method add_assign(other: Self) -> Self;
}