/*
 * xs_jit_builder.h - C API for building C code strings for XS::JIT
 *
 * This header provides a fluent C API for generating C code dynamically.
 * It can be used directly from XS code without Perl overhead, making it
 * ideal for code generation in performance-critical modules like Meow.
 *
 * Example usage:
 *
 *   XS_JIT_Builder* b = xs_jit_builder_new(aTHX);
 *   xs_jit_ro_accessor(aTHX_ b, "MyClass_get_name", "name", 4);
 *   SV* code = xs_jit_builder_code(aTHX_ b);
 *   xs_jit_builder_free(aTHX_ b);
 */

#ifndef XS_JIT_BUILDER_H
#define XS_JIT_BUILDER_H

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

/* ============================================
 * Builder context structure
 * ============================================ */

typedef struct {
    SV* code;           /* The accumulated code (SV*) */
    int indent;         /* Current indentation level */
    int indent_width;   /* Spaces per indent (default 4) */
    int use_tabs;       /* Use tabs instead of spaces (default 0) */
    int in_function;    /* Currently inside a function */
} XS_JIT_Builder;

/* Attribute descriptor for constructors */
typedef struct {
    const char* name;
    STRLEN len;
} XS_JIT_Attr;

/* ============================================
 * Inline op types for cv_set_call_checker
 * ============================================ */

typedef enum {
    XS_JIT_INLINE_NONE      = 0,
    XS_JIT_INLINE_GETTER    = 1,  /* Read-only slot accessor */
    XS_JIT_INLINE_SETTER    = 2,  /* Read-write slot accessor */
    XS_JIT_INLINE_HV_GETTER = 3,  /* Hash-based read-only accessor */
    XS_JIT_INLINE_HV_SETTER = 4   /* Hash-based read-write accessor */
} XS_JIT_InlineType;

/* ============================================
 * Lifecycle
 * ============================================ */

/* Create a new builder */
XS_JIT_Builder* xs_jit_builder_new(pTHX);

/* Free the builder (does NOT free the code SV) */
void xs_jit_builder_free(pTHX_ XS_JIT_Builder* b);

/* Get the accumulated code as SV* (caller owns the reference) */
SV* xs_jit_builder_code(pTHX_ XS_JIT_Builder* b);

/* Get the accumulated code as a C string (pointer into SV, valid until SV is modified) */
const char* xs_jit_builder_cstr(pTHX_ XS_JIT_Builder* b);

/* Reset the builder for reuse (clears code, resets indent) */
void xs_jit_builder_reset(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Low-level output
 * ============================================ */

/* Add a formatted line with current indentation and newline */
void xs_jit_line(pTHX_ XS_JIT_Builder* b, const char* fmt, ...);

/* Add raw formatted text without indentation or newline */
void xs_jit_raw(pTHX_ XS_JIT_Builder* b, const char* fmt, ...);

/* Add a C comment: / * text * / */
void xs_jit_comment(pTHX_ XS_JIT_Builder* b, const char* text);

/* Add a blank line */
void xs_jit_blank(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Indentation control
 * ============================================ */

/* Increase indentation level */
void xs_jit_indent(XS_JIT_Builder* b);

/* Decrease indentation level */
void xs_jit_dedent(XS_JIT_Builder* b);

/* Set spaces per indentation level (default 4) */
void xs_jit_set_indent_width(XS_JIT_Builder* b, int width);

/* Use tabs instead of spaces for indentation */
void xs_jit_set_use_tabs(XS_JIT_Builder* b, int use_tabs);

/* ============================================
 * Blocks and structure
 * ============================================ */

/* Start a block: { with indent increase */
void xs_jit_block_start(pTHX_ XS_JIT_Builder* b);

/* End a block: } with indent decrease */
void xs_jit_block_end(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * XS Function structure
 * ============================================ */

/* Start an XS function: XS_EUPXS(name) { */
void xs_jit_xs_function(pTHX_ XS_JIT_Builder* b, const char* name);

/* Add standard XS preamble: dVAR; dXSARGS; PERL_UNUSED_VAR(cv); */
void xs_jit_xs_preamble(pTHX_ XS_JIT_Builder* b);

/* End XS function (closes brace) */
void xs_jit_xs_end(pTHX_ XS_JIT_Builder* b);

/* XSRETURN(n); */
void xs_jit_xs_return(pTHX_ XS_JIT_Builder* b, int count);

/* ST(0) = &PL_sv_undef; XSRETURN(1); */
void xs_jit_xs_return_undef(pTHX_ XS_JIT_Builder* b);

/* croak_xs_usage(cv, "usage"); */
void xs_jit_croak_usage(pTHX_ XS_JIT_Builder* b, const char* usage);

/* ============================================
 * Control flow
 * ============================================ */

/* if (condition) { */
void xs_jit_if(pTHX_ XS_JIT_Builder* b, const char* cond);

/* } else if (condition) { */
void xs_jit_elsif(pTHX_ XS_JIT_Builder* b, const char* cond);

/* } else { */
void xs_jit_else(pTHX_ XS_JIT_Builder* b);

/* } (close if/else) */
void xs_jit_endif(pTHX_ XS_JIT_Builder* b);

/* for (init; cond; incr) { */
void xs_jit_for(pTHX_ XS_JIT_Builder* b, const char* init, const char* cond, const char* incr);

/* while (condition) { */
void xs_jit_while(pTHX_ XS_JIT_Builder* b, const char* cond);

/* } (close for/while) */
void xs_jit_endloop(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Variable declarations
 * ============================================ */

/* type name; or type name = value; (value can be NULL) */
void xs_jit_declare(pTHX_ XS_JIT_Builder* b, const char* type, const char* name, const char* value);

/* SV* name = value; */
void xs_jit_declare_sv(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* HV* name = value; */
void xs_jit_declare_hv(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* AV* name = value; */
void xs_jit_declare_av(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* int name = value; */
void xs_jit_declare_int(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* IV name = value; */
void xs_jit_declare_iv(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* NV name = value; */
void xs_jit_declare_nv(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* const char* name = value; */
void xs_jit_declare_pv(pTHX_ XS_JIT_Builder* b, const char* name, const char* value);

/* var = value; (assignment) */
void xs_jit_assign(pTHX_ XS_JIT_Builder* b, const char* var, const char* value);

/* ============================================
 * Common XS patterns
 * ============================================ */

/* SV* self = ST(0); */
void xs_jit_get_self(pTHX_ XS_JIT_Builder* b);

/* SV* self = ST(0); HV* hv = (HV*)SvRV(self); */
void xs_jit_get_self_hv(pTHX_ XS_JIT_Builder* b);

/* SV* self = ST(0); AV* av = (AV*)SvRV(self); */
void xs_jit_get_self_av(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Hash operations
 * ============================================ */

/* SV** result_var = hv_fetch(hv, "key", len, 0); - literal key */
void xs_jit_hv_fetch(pTHX_ XS_JIT_Builder* b, const char* hv, const char* key, STRLEN len, const char* result_var);

/* SV** result_var = hv_fetch(hv, key_expr, len_expr, 0); - dynamic key */
void xs_jit_hv_fetch_sv(pTHX_ XS_JIT_Builder* b, const char* hv, const char* key_expr, const char* len_expr, const char* result_var);

/* (void)hv_store(hv, "key", len, value, 0); - literal key */
void xs_jit_hv_store(pTHX_ XS_JIT_Builder* b, const char* hv, const char* key, STRLEN len, const char* value);

/* (void)hv_store(hv, key_expr, len_expr, value, 0); - dynamic key */
void xs_jit_hv_store_sv(pTHX_ XS_JIT_Builder* b, const char* hv, const char* key_expr, const char* len_expr, const char* value);

/* Fetch from hash and return (with undef fallback) - complete pattern */
void xs_jit_hv_fetch_return(pTHX_ XS_JIT_Builder* b, const char* hv, const char* key, STRLEN len);

/* ============================================
 * Array operations
 * ============================================ */

/* SV** result_var = av_fetch(av, index, 0); */
void xs_jit_av_fetch(pTHX_ XS_JIT_Builder* b, const char* av, const char* index, const char* result_var);

/* av_store(av, index, value); */
void xs_jit_av_store(pTHX_ XS_JIT_Builder* b, const char* av, const char* index, const char* value);

/* av_push(av, value); */
void xs_jit_av_push(pTHX_ XS_JIT_Builder* b, const char* av, const char* value);

/* I32 result_var = av_len(av); */
void xs_jit_av_len(pTHX_ XS_JIT_Builder* b, const char* av, const char* result_var);

/* ============================================
 * SV creation
 * ============================================ */

/* SV* result_var = newSViv(value); */
void xs_jit_new_sv_iv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* value);

/* SV* result_var = newSVnv(value); */
void xs_jit_new_sv_nv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* value);

/* SV* result_var = newSVpvn("str", len); */
void xs_jit_new_sv_pv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* str, STRLEN len);

/* sv = sv_2mortal(sv); */
void xs_jit_mortal(pTHX_ XS_JIT_Builder* b, const char* sv);

/* ============================================
 * Type checking
 * ============================================ */

/* Check items count, croak with usage if wrong. max=-1 means no upper limit */
void xs_jit_check_items(pTHX_ XS_JIT_Builder* b, int min, int max, const char* usage);

/* if (!SvOK(sv)) croak(error_msg); */
void xs_jit_check_defined(pTHX_ XS_JIT_Builder* b, const char* sv, const char* error_msg);

/* Check reference type (SVt_PVHV, SVt_PVAV, etc.) */
void xs_jit_check_ref_type(pTHX_ XS_JIT_Builder* b, const char* sv, const char* type, const char* error_msg);

/* Check for hashref */
void xs_jit_check_hashref(pTHX_ XS_JIT_Builder* b, const char* sv, const char* error_msg);

/* Check for arrayref */
void xs_jit_check_arrayref(pTHX_ XS_JIT_Builder* b, const char* sv, const char* error_msg);

/* ============================================
 * SV conversion (extract values from SV)
 * ============================================ */

/* IV result_var = SvIV(sv); */
void xs_jit_sv_to_iv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* sv);

/* UV result_var = SvUV(sv); */
void xs_jit_sv_to_uv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* sv);

/* NV result_var = SvNV(sv); */
void xs_jit_sv_to_nv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* sv);

/* const char* result_var = SvPV(sv, len_var); len_var can be NULL */
void xs_jit_sv_to_pv(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* len_var, const char* sv);

/* int result_var = SvTRUE(sv); */
void xs_jit_sv_to_bool(pTHX_ XS_JIT_Builder* b, const char* result_var, const char* sv);

/* ============================================
 * Return helpers
 * ============================================ */

/* ST(0) = sv_2mortal(newSViv(value)); XSRETURN(1); */
void xs_jit_return_iv(pTHX_ XS_JIT_Builder* b, const char* value);

/* ST(0) = sv_2mortal(newSVuv(value)); XSRETURN(1); */
void xs_jit_return_uv(pTHX_ XS_JIT_Builder* b, const char* value);

/* ST(0) = sv_2mortal(newSVnv(value)); XSRETURN(1); */
void xs_jit_return_nv(pTHX_ XS_JIT_Builder* b, const char* value);

/* ST(0) = sv_2mortal(newSVpvn(str, len)); XSRETURN(1); */
void xs_jit_return_pv(pTHX_ XS_JIT_Builder* b, const char* str, const char* len);

/* ST(0) = sv; XSRETURN(1); */
void xs_jit_return_sv(pTHX_ XS_JIT_Builder* b, const char* sv);

/* ST(0) = &PL_sv_yes; XSRETURN(1); */
void xs_jit_return_yes(pTHX_ XS_JIT_Builder* b);

/* ST(0) = &PL_sv_no; XSRETURN(1); */
void xs_jit_return_no(pTHX_ XS_JIT_Builder* b);

/* ST(0) = self; XSRETURN(1); */
void xs_jit_return_self(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Common method patterns
 * ============================================ */

/* Start a method: xs_function + preamble + items check + get_self_hv */
void xs_jit_method_start(pTHX_ XS_JIT_Builder* b, const char* func_name, int min_args, int max_args, const char* usage);

/* Generate a predicate (has_foo) that returns true/false based on attribute */
void xs_jit_predicate(pTHX_ XS_JIT_Builder* b, const char* func_name, const char* attr_name, STRLEN attr_len);

/* Generate a clearer (clear_foo) that deletes an attribute */
void xs_jit_clearer(pTHX_ XS_JIT_Builder* b, const char* func_name, const char* attr_name, STRLEN attr_len);

/* ============================================
 * Error handling
 * ============================================ */

/* croak("message"); */
void xs_jit_croak(pTHX_ XS_JIT_Builder* b, const char* message);

/* warn("message"); */
void xs_jit_warn(pTHX_ XS_JIT_Builder* b, const char* message);

/* ============================================
 * Prebuilt patterns (generate complete code)
 * ============================================ */

/* Generate a complete read-only accessor function */
void xs_jit_ro_accessor(pTHX_ XS_JIT_Builder* b, const char* func_name, const char* attr_name, STRLEN attr_len);

/* Generate a complete read-write accessor function */
void xs_jit_rw_accessor(pTHX_ XS_JIT_Builder* b, const char* func_name, const char* attr_name, STRLEN attr_len);

/* Generate a constructor (attrs is NULL-terminated array) */
void xs_jit_constructor(pTHX_ XS_JIT_Builder* b, const char* func_name, const char* class_name, XS_JIT_Attr* attrs, int num_attrs);

/* ============================================
 * Op-based accessors (for array-based objects with inline ops)
 * These are faster than hash-based accessors and can be
 * combined with inline ops for compile-time optimization
 * ============================================ */

/* Generate a read-only op accessor: $obj->[slot] */
void xs_jit_op_ro_accessor(pTHX_ XS_JIT_Builder* b, const char* func_name, IV slot);

/* Generate a read-write op accessor: $obj->[slot] with optional setter */
void xs_jit_op_rw_accessor(pTHX_ XS_JIT_Builder* b, const char* func_name, IV slot);

/* ============================================
 * Custom op builder (for defining arbitrary inline ops)
 * 
 * Usage:
 *   xs_jit_pp_start(b, "my_op");
 *   xs_jit_pp_get_self(b);
 *   xs_jit_line(b, "NV result = ...");
 *   xs_jit_pp_return_nv(b, "result");
 *   xs_jit_pp_end(b);
 * ============================================ */

/* Start a pp (push-pop) function - the runtime part of a custom op */
void xs_jit_pp_start(pTHX_ XS_JIT_Builder* b, const char* name);

/* End a pp function */
void xs_jit_pp_end(pTHX_ XS_JIT_Builder* b);

/* pp preamble: dSP; */
void xs_jit_pp_dsp(pTHX_ XS_JIT_Builder* b);

/* Get self from top of stack: SV* self = TOPs; */
void xs_jit_pp_get_self(pTHX_ XS_JIT_Builder* b);

/* Pop self from stack: SV* self = POPs; */
void xs_jit_pp_pop_self(pTHX_ XS_JIT_Builder* b);

/* Pop a value: SV* name = POPs; */
void xs_jit_pp_pop_sv(pTHX_ XS_JIT_Builder* b, const char* name);

/* Pop as NV: NV name = POPn; */
void xs_jit_pp_pop_nv(pTHX_ XS_JIT_Builder* b, const char* name);

/* Pop as IV: IV name = POPi; */
void xs_jit_pp_pop_iv(pTHX_ XS_JIT_Builder* b, const char* name);

/* Get array slots from self: SV** ary = AvARRAY((AV*)SvRV(self)); */
void xs_jit_pp_get_slots(pTHX_ XS_JIT_Builder* b);

/* Get slot value: SV* name = ary[slot] ? ary[slot] : &PL_sv_undef; */
void xs_jit_pp_slot(pTHX_ XS_JIT_Builder* b, const char* name, IV slot);

/* Set result and return: SETs(sv); return NORMAL; */
void xs_jit_pp_return_sv(pTHX_ XS_JIT_Builder* b, const char* sv_expr);

/* Return mortal NV: SETs(sv_2mortal(newSVnv(expr))); return NORMAL; */
void xs_jit_pp_return_nv(pTHX_ XS_JIT_Builder* b, const char* nv_expr);

/* Return mortal IV: SETs(sv_2mortal(newSViv(expr))); return NORMAL; */
void xs_jit_pp_return_iv(pTHX_ XS_JIT_Builder* b, const char* iv_expr);

/* Return mortal PV: SETs(sv_2mortal(newSVpv(expr, 0))); return NORMAL; */
void xs_jit_pp_return_pv(pTHX_ XS_JIT_Builder* b, const char* pv_expr);

/* Just return NORMAL; */
void xs_jit_pp_return(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * Call checker builder (compile-time rewriting)
 * ============================================ */

/* Start a call checker function */
void xs_jit_ck_start(pTHX_ XS_JIT_Builder* b, const char* name);

/* End a call checker function */
void xs_jit_ck_end(pTHX_ XS_JIT_Builder* b);

/* Standard call checker preamble - extract args from entersub */
void xs_jit_ck_preamble(pTHX_ XS_JIT_Builder* b);

/* Build and return a UNOP custom op */
void xs_jit_ck_build_unop(pTHX_ XS_JIT_Builder* b, const char* pp_func, const char* targ_expr);

/* Build and return a BINOP custom op */
void xs_jit_ck_build_binop(pTHX_ XS_JIT_Builder* b, const char* pp_func, const char* targ_expr);

/* Return the original entersubop (fallback, no optimization) */
void xs_jit_ck_fallback(pTHX_ XS_JIT_Builder* b);

/* ============================================
 * XOP registration helpers
 * ============================================ */

/* Generate XOP struct and registration code */
void xs_jit_xop_declare(pTHX_ XS_JIT_Builder* b, const char* name, const char* pp_func, const char* desc);

/* Generate cv_set_call_checker_flags call */
void xs_jit_register_checker(pTHX_ XS_JIT_Builder* b, const char* cv_expr, const char* ck_func, const char* ckobj_expr);

/* ============================================
 * Inline op support (compile-time optimization)
 * 
 * Inline ops replace function calls with custom ops at compile time,
 * bypassing XS call overhead entirely. This provides ~2x speedup.
 * 
 * Usage:
 *   CV* cv = get_cv("MyClass::name", 0);
 *   xs_jit_inline_register(aTHX_ cv, XS_JIT_INLINE_GETTER, 0, NULL, 0);
 * ============================================ */

/* Initialize inline op subsystem (safe to call multiple times) */
void xs_jit_inline_init(pTHX);

/* Register an inline op for a CV */
int xs_jit_inline_register(pTHX_ CV* cv, XS_JIT_InlineType type, 
                           IV slot, const char* key, STRLEN key_len);

/* Check if a CV has an inline op registered */
XS_JIT_InlineType xs_jit_inline_get_type(pTHX_ CV* cv);

/* ============================================
 * Convenience macros
 * Assumes 'b' is the builder variable name
 * ============================================ */

#define JIT_FUNC(name)              xs_jit_xs_function(aTHX_ b, name)
#define JIT_PREAMBLE                xs_jit_xs_preamble(aTHX_ b)
#define JIT_END                     xs_jit_xs_end(aTHX_ b)
#define JIT_LINE(...)               xs_jit_line(aTHX_ b, __VA_ARGS__)
#define JIT_RAW(...)                xs_jit_raw(aTHX_ b, __VA_ARGS__)
#define JIT_COMMENT(text)           xs_jit_comment(aTHX_ b, text)
#define JIT_BLANK                   xs_jit_blank(aTHX_ b)

#define JIT_IF(cond)                xs_jit_if(aTHX_ b, cond)
#define JIT_ELSIF(cond)             xs_jit_elsif(aTHX_ b, cond)
#define JIT_ELSE                    xs_jit_else(aTHX_ b)
#define JIT_ENDIF                   xs_jit_endif(aTHX_ b)
#define JIT_FOR(i, c, n)            xs_jit_for(aTHX_ b, i, c, n)
#define JIT_WHILE(cond)             xs_jit_while(aTHX_ b, cond)
#define JIT_ENDLOOP                 xs_jit_endloop(aTHX_ b)

#define JIT_BLOCK_START             xs_jit_block_start(aTHX_ b)
#define JIT_BLOCK_END               xs_jit_block_end(aTHX_ b)

#define JIT_DECLARE(t, n, v)        xs_jit_declare(aTHX_ b, t, n, v)
#define JIT_DECLARE_SV(n, v)        xs_jit_declare_sv(aTHX_ b, n, v)
#define JIT_DECLARE_HV(n, v)        xs_jit_declare_hv(aTHX_ b, n, v)
#define JIT_DECLARE_AV(n, v)        xs_jit_declare_av(aTHX_ b, n, v)
#define JIT_DECLARE_INT(n, v)       xs_jit_declare_int(aTHX_ b, n, v)

#define JIT_SELF                    xs_jit_get_self(aTHX_ b)
#define JIT_SELF_HV                 xs_jit_get_self_hv(aTHX_ b)
#define JIT_SELF_AV                 xs_jit_get_self_av(aTHX_ b)

#define JIT_HV_FETCH(h, k, l, r)    xs_jit_hv_fetch(aTHX_ b, h, k, l, r)
#define JIT_HV_STORE(h, k, l, v)    xs_jit_hv_store(aTHX_ b, h, k, l, v)
#define JIT_HV_FETCH_RET(h, k, l)   xs_jit_hv_fetch_return(aTHX_ b, h, k, l)

#define JIT_AV_FETCH(a, i, r)       xs_jit_av_fetch(aTHX_ b, a, i, r)
#define JIT_AV_STORE(a, i, v)       xs_jit_av_store(aTHX_ b, a, i, v)
#define JIT_AV_PUSH(a, v)           xs_jit_av_push(aTHX_ b, a, v)
#define JIT_AV_LEN(a, r)            xs_jit_av_len(aTHX_ b, a, r)

#define JIT_CROAK(msg)              xs_jit_croak(aTHX_ b, msg)
#define JIT_WARN(msg)               xs_jit_warn(aTHX_ b, msg)
#define JIT_CROAK_USAGE(usage)      xs_jit_croak_usage(aTHX_ b, usage)

#define JIT_CHECK_ITEMS(min, max, u) xs_jit_check_items(aTHX_ b, min, max, u)
#define JIT_CHECK_DEFINED(sv, msg)  xs_jit_check_defined(aTHX_ b, sv, msg)
#define JIT_CHECK_HASHREF(sv, msg)  xs_jit_check_hashref(aTHX_ b, sv, msg)
#define JIT_CHECK_ARRAYREF(sv, msg) xs_jit_check_arrayref(aTHX_ b, sv, msg)

#define JIT_SV_TO_IV(r, sv)         xs_jit_sv_to_iv(aTHX_ b, r, sv)
#define JIT_SV_TO_UV(r, sv)         xs_jit_sv_to_uv(aTHX_ b, r, sv)
#define JIT_SV_TO_NV(r, sv)         xs_jit_sv_to_nv(aTHX_ b, r, sv)
#define JIT_SV_TO_PV(r, l, sv)      xs_jit_sv_to_pv(aTHX_ b, r, l, sv)
#define JIT_SV_TO_BOOL(r, sv)       xs_jit_sv_to_bool(aTHX_ b, r, sv)

#define JIT_RETURN(n)               xs_jit_xs_return(aTHX_ b, n)
#define JIT_RETURN_UNDEF            xs_jit_xs_return_undef(aTHX_ b)
#define JIT_RETURN_IV(v)            xs_jit_return_iv(aTHX_ b, v)
#define JIT_RETURN_UV(v)            xs_jit_return_uv(aTHX_ b, v)
#define JIT_RETURN_NV(v)            xs_jit_return_nv(aTHX_ b, v)
#define JIT_RETURN_PV(s, l)         xs_jit_return_pv(aTHX_ b, s, l)
#define JIT_RETURN_SV(sv)           xs_jit_return_sv(aTHX_ b, sv)
#define JIT_RETURN_YES              xs_jit_return_yes(aTHX_ b)
#define JIT_RETURN_NO               xs_jit_return_no(aTHX_ b)
#define JIT_RETURN_SELF             xs_jit_return_self(aTHX_ b)

#define JIT_METHOD_START(f, min, max, u) xs_jit_method_start(aTHX_ b, f, min, max, u)
#define JIT_PREDICATE(f, a, l)      xs_jit_predicate(aTHX_ b, f, a, l)
#define JIT_CLEARER(f, a, l)        xs_jit_clearer(aTHX_ b, f, a, l)

#define JIT_RO_ACCESSOR(f, a, l)    xs_jit_ro_accessor(aTHX_ b, f, a, l)
#define JIT_RW_ACCESSOR(f, a, l)    xs_jit_rw_accessor(aTHX_ b, f, a, l)

#define JIT_OP_RO(f, s)             xs_jit_op_ro_accessor(aTHX_ b, f, s)
#define JIT_OP_RW(f, s)             xs_jit_op_rw_accessor(aTHX_ b, f, s)

#endif /* XS_JIT_BUILDER_H */
