shape-runtime 0.2.0

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// @module std::core::vec
/// Method definitions for Vec<T> (Array).
///
/// Type-agnostic methods are defined via `extend Vec<T>`.
/// Numeric-only methods are defined via `trait NumericVec` + `impl NumericVec for Vec`.
/// Most methods have pure Shape implementations. Methods that need VM intrinsics
/// (pop, sort, groupBy) delegate to Rust PHF dispatch; the compiler self-call
/// guard prevents infinite recursion. Note: `len`/`isEmpty` are intentionally
/// NOT defined here — they would intercept dispatch and recurse on Vec<T>.

// -- Type-agnostic methods --------------------------------------------------

extend Vec<T> {
    // NOTE: `len()` and `isEmpty()` are intentionally NOT defined here.
    // `arr.len()` dispatches directly to the PHF handler (ARRAY_METHODS::handle_len_v2
    // for Arc arrays; TYPED_INT_ARRAY_METHODS::len / TYPED_NUMBER_ARRAY_METHODS::len
    // for v2 raw-ptr arrays via as_v2_typed_array). Defining `method len() -> int
    // { self.len() }` here causes the extend-method to intercept dispatch and
    // recurse infinitely (or, post self-call guard, produce garbage).
    // Callers needing `isEmpty()` can write `arr.len() == 0` directly.

    // --- Pure Shape implementations ---
    method first() -> T { self[0] }
    method last() -> T { self[self.len() - 1] }

    method push(item: T) { self.push(item) }   // ArrayPushLocal opcode (in-place)
    method pop() -> T { self.pop() }             // keep delegation — pop needs VM support

    method reverse() -> Vec<T> {
        let mut result = []
        let mut i = self.len() - 1
        while i >= 0 {
            result.push(self[i])
            i = i - 1
        }
        result
    }

    method clone() -> Vec<T> { self.slice(0, self.len()) }

    method filter(predicate: (T) => bool) -> Vec<T> {
        let mut result = []
        for item in self {
            if predicate(item) {
                result.push(item)
            }
        }
        result
    }

    method map<U>(f: (T) => U) -> Vec<U> {
        let mut result = []
        for item in self {
            result.push(f(item))
        }
        result
    }

    method reduce<U>(f: (U, T) => U, init: U) -> U {
        let mut acc = init
        for item in self {
            acc = f(acc, item)
        }
        acc
    }

    method find(predicate: (T) => bool) -> T {
        for item in self {
            if predicate(item) { return item }
        }
    }

    method forEach(f: (T) => void) -> void {
        for item in self { f(item) }
    }

    method some(predicate: (T) => bool) -> bool {
        for item in self {
            if predicate(item) { return true }
        }
        false
    }

    method every(predicate: (T) => bool) -> bool {
        for item in self {
            if !predicate(item) { return false }
        }
        true
    }

    method join(separator: string) -> string {
        let mut result = ""
        for i in 0..self.len() {
            if i > 0 { result = result + separator }
            result = result + self[i].toString()
        }
        result
    }

    method slice(start: int, end: int) -> Vec<T> {
        let mut result = []
        let mut i = start
        while i < end && i < self.len() {
            result.push(self[i])
            i = i + 1
        }
        result
    }

    method take(n: int) -> Vec<T> { self.slice(0, n) }

    method drop(n: int) -> Vec<T> { self.slice(n, self.len()) }

    method flatten() -> Vec<T> {
        let mut result = []
        for item in self {
            for sub in item {
                result.push(sub)
            }
        }
        result
    }

    method unique() -> Vec<T> {
        let mut result = []
        for item in self {
            if !result.includes(item) {
                result.push(item)
            }
        }
        result
    }

    method concat(other: Vec<T>) -> Vec<T> {
        let mut result = []
        for item in self { result.push(item) }
        for item in other { result.push(item) }
        result
    }

    method indexOf(value: T) -> int {
        for i in 0..self.len() {
            if self[i] == value { return i }
        }
        -1
    }

    method sort(cmp: (T, T) => number) -> Vec<T> { self.sort(cmp) }  // keep Rust delegation

    method includes(value: T) -> bool {
        for item in self {
            if item == value { return true }
        }
        false
    }

    method findIndex(predicate: (T) => bool) -> int {
        for i in 0..self.len() {
            if predicate(self[i]) { return i }
        }
        -1
    }

    method flatMap<U>(f: (T) => Vec<U>) -> Vec<U> {
        let mut result = []
        for item in self {
            for sub in f(item) {
                result.push(sub)
            }
        }
        result
    }

    method groupBy<K>(key_fn: (T) => K) -> Vec<K> { self.groupBy(key_fn) }  // keep Rust delegation (HashMap needed)

    method sortBy(key_fn: (T) => number) -> Vec<T> {
        self.sort(|a, b| {
            let ka = key_fn(a)
            let kb = key_fn(b)
            if ka < kb { -1 }
            else if ka > kb { 1 }
            else { 0 }
        })
    }
}

// -- Numeric-only methods ---------------------------------------------------

trait NumericVec {
    sum(): number,
    avg(): number,
    mean(): number,
    min(): number,
    max(): number,
    std(): number,
    variance(): number,
    dot(other: Vec<number>): number,
    norm(): number,
    normalize(): Vec<number>,
    cumsum(): Vec<number>,
    diff(): Vec<number>,
    abs(): Vec<number>,
}

impl NumericVec for Vec {
    method sum() -> number { self.sum() }
    method avg() -> number { self.avg() }
    method mean() -> number { self.mean() }
    method min() -> number { self.min() }
    method max() -> number { self.max() }
    method std() -> number { self.std() }
    method variance() -> number { self.variance() }
    method dot(other: Vec<number>) -> number { self.dot(other) }
    method norm() -> number { self.norm() }
    method normalize() -> Vec<number> { self.normalize() }
    method cumsum() -> Vec<number> { self.cumsum() }
    method diff() -> Vec<number> { self.diff() }
    method abs() -> Vec<number> { self.abs() }
}