dol 0.8.1

DOL (Design Ontology Language) - A declarative specification language for ontology-first development
// Effect System Test: Complex Pure Computation
// =============================================
//
// What this test validates:
//   - Complex pure computations with multiple branches remain pure
//   - Conditional logic does not introduce effects
//   - Helper functions composed together maintain purity
//   - Sign, absolute value, min/max, clamp operations
//
// Expected effect inference results:
//   - min(a, b) -> Pure
//   - max(a, b) -> Pure
//   - clamp(value, lo, hi) -> Pure
//   - abs(x) -> Pure
//   - sign(x) -> Pure
//   - in_range(x, lo, hi) -> Pure

gene Math.Complex @0.1.0 {
    """
    Complex pure computations involving multiple operations
    and branching logic. All remain pure as they only
    transform data without side effects.
    """

    // Pure: minimum of two values
    fn min(a: Int, b: Int) -> Int {
        if a < b {
            a
        } else {
            b
        }
    }

    // Pure: maximum of two values
    fn max(a: Int, b: Int) -> Int {
        if a > b {
            a
        } else {
            b
        }
    }

    // Pure: clamp value to range [lo, hi]
    // Composes min and max
    fn clamp(value: Int, lo: Int, hi: Int) -> Int {
        max(lo, min(value, hi))
    }

    // Pure: absolute value
    fn abs(x: Int) -> Int {
        if x < 0 {
            -x
        } else {
            x
        }
    }

    // Pure: sign function (-1, 0, or 1)
    fn sign(x: Int) -> Int {
        if x < 0 {
            -1
        } else if x > 0 {
            1
        } else {
            0
        }
    }

    // Pure: check if value is in range [lo, hi]
    fn in_range(x: Int, lo: Int, hi: Int) -> Bool {
        x >= lo && x <= hi
    }

    // Pure: distance between two points (1D)
    fn distance(a: Int, b: Int) -> Int {
        abs(a - b)
    }

    // Pure: midpoint between two values
    fn midpoint(a: Int, b: Int) -> Int {
        (a + b) / 2
    }

    // Pure: linear interpolation factor
    fn lerp_factor(value: Int, start: Int, end: Int) -> Int {
        if start == end {
            0
        } else {
            (value - start) * 100 / (end - start)
        }
    }

    // Pure: map value from one range to another
    fn map_range(value: Int, in_lo: Int, in_hi: Int, out_lo: Int, out_hi: Int) -> Int {
        let factor = lerp_factor(value, in_lo, in_hi);
        out_lo + (out_hi - out_lo) * factor / 100
    }

    // Pure: three-way comparison
    fn compare(a: Int, b: Int) -> Int {
        if a < b {
            -1
        } else if a > b {
            1
        } else {
            0
        }
    }
}

// Test assertions for effect inference
test effects {
    assert_pure(Math.Complex.min);
    assert_pure(Math.Complex.max);
    assert_pure(Math.Complex.clamp);
    assert_pure(Math.Complex.abs);
    assert_pure(Math.Complex.sign);
    assert_pure(Math.Complex.in_range);
    assert_pure(Math.Complex.distance);
    assert_pure(Math.Complex.midpoint);
    assert_pure(Math.Complex.lerp_factor);
    assert_pure(Math.Complex.map_range);
    assert_pure(Math.Complex.compare);
}