/* Embedding-ABI M3 record round-trip C host (own + borrow via a
 * compile-time -DBORROW switch). Frozen value layout
 * (design/contracts/0006-frozen-value-layout.md):
 *   p - 8 .. p   uint64_t refcount header (set to 1 by ailang_rc_alloc)
 *   p + 0        int64_t  constructor tag (single ctor → 0)
 *   p + 8        IEEE-754 double  field 0 = Float acc
 *   p + 16       int64_t          field 1 = Int   n
 * Total payload = 8 + 2*8 = 24.
 *
 * own  : the kernel consumes each `(own (con State))` input (drop at
 *        return); the host must NOT touch/dec it after the call.
 * borrow: the kernel does NOT consume the `(borrow (con State))`
 *        input; the host retains it and dec's it itself each iter.
 * In both modes the return is host-owned and host-freed.
 */
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

typedef struct ailang_ctx ailang_ctx_t;
extern ailang_ctx_t *ailang_ctx_new(void);
extern void          ailang_ctx_free(ailang_ctx_t *);
extern void *ailang_rc_alloc(size_t);
extern void  ailang_rc_dec(void *);
extern void *backtest_step(ailang_ctx_t *ctx, void *st, double sample);

static void *make_state(double acc, int64_t n) {
    void *p = ailang_rc_alloc(8 + 2 * 8);   /* header=1 set by runtime */
    *(int64_t *)((char *)p + 0)  = 0;       /* single-ctor tag = 0     */
    memcpy((char *)p + 8,  &acc, 8);        /* Float acc @ 8           */
    *(int64_t *)((char *)p + 16) = n;       /* Int   n   @ 16          */
    return p;
}

int main(void) {
    ailang_ctx_t *ctx = ailang_ctx_new();
    void *st = make_state(0.0, 0);
    for (int i = 0; i < 1000000; i++) {
        void *next = backtest_step(ctx, st, (double)(i & 7));
#ifdef BORROW
        ailang_rc_dec(st);   /* borrow: host retained input, frees it */
#endif
        /* own: kernel consumed `st`; do NOT touch/dec it here.        */
        st = next;           /* return is host-owned                   */
    }
    double acc; memcpy(&acc, (char *)st + 8, 8);
    int64_t n = *(int64_t *)((char *)st + 16);
    assert(n == 1000000);
    ailang_rc_dec(st);       /* host frees the final return            */
    ailang_ctx_free(ctx);    /* AILANG_RC_STATS readback fires here    */
    return 0;
}
