shape-runtime 0.3.0

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// Mark a function as a cached technical indicator.
///
/// Indicator functions compute technical-analysis values from price data.
/// This annotation registers the function in the indicator registry and enables
/// memoization across repeated calls with the same arguments.
///
/// @note The annotation contributes lifecycle hooks, but the annotated
/// function remains the source of truth for its own API signature and docs.
/// @see std::finance::annotations::warmup::@warmup
/// @example
/// @indicator
/// @warmup(14)
/// pub fn rsi(data: Column<number>, period: number) -> number {
///     let gains = data.diff().map(d => d > 0 ? d : 0)
///     let losses = data.diff().map(d => d < 0 ? abs(d) : 0)
///     let avg_gain = gains.rolling(period).mean()
///     let avg_loss = losses.rolling(period).mean()
///     let rs = avg_gain / avg_loss
///     return 100 - (100 / (1 + rs))
/// }
annotation indicator() {
    // Called when a function with @indicator is defined
    // self = the annotated function
    on_define(ctx) {
        // Register in the indicators registry
        ctx.get("registry").set(self.name, self)
    }

    // Called before each invocation - check cache
    // self = the annotated function
    before(args, ctx) {
        // Generate cache key from function name and arguments
        let key = self.name + ":" + args.toString()

        // Check if we have a cached result
        let cached = ctx.get("cache").get(key)
        if cached != None {
            // Return cached value — wrapper will use self instead of calling impl
            return cached
        }
        // Return None to continue with normal execution
        None
    }

    // Called after each invocation - cache result
    // self = the annotated function
    after(args, result, ctx) {
        // Generate cache key
        let key = self.name + ":" + args.toString()

        // Return state with cache update
        result
    }

    // Return static metadata
    metadata() {
        return {
            is_indicator: true,
            cacheable: true,
            pure: true
        }
    }
}