vextoly/cryn

/* generated by the Cryn compiler - do not edit */
/* Cryn source compiled to portable C11 */

#ifndef CRYN_RT_H
#define CRYN_RT_H

/*
 * Minimal runtime support for compiled Cryn programs.
 * Everything here exists only because it cannot be expressed as inline C
 * in generated code (context management, heap headers, threads, output
 * formatting). The language's semantics live in the compiler.
 */

#include <stdint.h>
#include <stdio.h>
#include <pthread.h>

#if defined(__GNUC__) || defined(__clang__)
#define CRN_NORETURN __attribute__((noreturn))
#else
#define CRN_NORETURN
#endif

typedef union Val {
    uint64_t u;   /* unsigned, address (as integer), bool, char */
    int64_t i;    /* signed integers, integer literals */
    double d;     /* float32 (widened) and float64 */
    void* p;      /* focus target / data pointer */
} Val;

/* A transformation reference: function pointer + parameter count.
   Indirect calls and spawns are rejected at runtime unless np == 0. */
typedef struct CrFnRef {
    Val (*fn)(void);
    int np;
} CrFnRef;

#define CR_FH_MAX 1024
#define CR_SPAWN_MAX 256
#define CR_FILES_MAX 256

typedef struct CrCtx {
    Val* stk;        /* value stack */
    uint64_t sp, cap;
    void* fh[CR_FH_MAX]; /* focus history */
    uint64_t fh_sp;
    FILE* in;        /* current input stream (default stdin) */
    FILE* out;       /* current output stream (default stdout) */
    FILE* files[CR_FILES_MAX];      /* open files; slot i has handle i+1 */
    unsigned char fmodes[CR_FILES_MAX]; /* 0 read, 1 write, 2 both, 3 append */
    pthread_t spawned[CR_SPAWN_MAX];
    int nspawned;
} CrCtx;

extern _Thread_local CrCtx cr_ctx;

void crn_init(void);
void crn_die(const char* msg) CRN_NORETURN;
void crn_die_range(uint64_t i, uint64_t n) CRN_NORETURN;

void crn_push(Val v);
Val crn_pop(void);

void crn_focus_push(void* f);
void* crn_focus_pop(void);

void* crn_alloc(uint64_t nbytes);
void crn_free(void* p);
uint64_t crn_block_n(void* data, uint64_t elemsz);
void crn_check_block(void* data, uint64_t i, uint64_t elemsz);
void crn_check_range(uint64_t i, uint64_t n);

/* Relaxed atomic scalar access. Cryn defines a data race on an aligned
   scalar cell (<= 8 bytes) as: the access yields an unspecified value of
   the cell's type and never tears. To keep that promise (and avoid C data
   races, which are undefined behavior), the backend performs every scalar
   load/store through these helpers. Racily accessed transform-reference
   cells (16 bytes) are undefined. No ordering is provided beyond wait. */
uint8_t  crn_ld_u8(const uint8_t* p);
uint16_t crn_ld_u16(const uint16_t* p);
uint32_t crn_ld_u32(const uint32_t* p);
uint64_t crn_ld_u64(const uint64_t* p);
float    crn_ld_f32(const float* p);
double   crn_ld_f64(const double* p);
void crn_st_u8(uint8_t* p, uint8_t v);
void crn_st_u16(uint16_t* p, uint16_t v);
void crn_st_u32(uint32_t* p, uint32_t v);
void crn_st_u64(uint64_t* p, uint64_t v);
void crn_st_f32(float* p, float v);
void crn_st_f64(double* p, double v);

/* Atomic exchange (acquire-release). `exchange` swaps the working value
   with the focused cell in one indivisible step and is the only ordering
   primitive besides wait: an exchange that stores a value releases the
   accesses that preceded it in program order, and one that loads a value
   acquires for the accesses that follow it. It never tears. This is
   enough to build locks (test-and-set). */
uint8_t  crn_xch_u8(uint8_t* p, uint8_t v);
uint16_t crn_xch_u16(uint16_t* p, uint16_t v);
uint32_t crn_xch_u32(uint32_t* p, uint32_t v);
uint64_t crn_xch_u64(uint64_t* p, uint64_t v);
float    crn_xch_f32(float* p, float v);
double   crn_xch_f64(double* p, double v);

int64_t crn_d2i64(double d);
uint64_t crn_d2u64(double d);
int64_t crn_d2i8(double d);
int64_t crn_d2i16(double d);
int64_t crn_d2i32(double d);
uint64_t crn_d2u8(double d);
uint64_t crn_d2u16(double d);
uint64_t crn_d2u32(double d);

void crn_out_i64(int64_t v);
void crn_out_u64(uint64_t v);
void crn_out_f64(double v);
void crn_out_f32(float v);
void crn_out_bool(int b);
void crn_out_char(unsigned c);
void crn_out_addr(uint64_t a);
void crn_out_text(uint8_t* p);

int64_t crn_input(void);
/* open modes: 0 read, 1 write, 2 both, 3 append.
   Returns a handle >= 1, or -1 on failure. A handle is an index into the
   context's file table; closing a handle frees its number for reuse. */
int64_t crn_open(uint8_t* path, int mode);
/* Route this context's streams through a handle: the readable side of the
   file becomes the input stream, the writable side the output stream;
   sides the mode does not support keep their current stream. Handle 0 is
   the standard streams (input: stdin, output: stdout). */
void crn_use(int64_t h);
void crn_flush(void);
/* Position the context's file streams at a byte offset from the start.
   Applies fseek(SEEK_SET) to every current stream that belongs to an
   open handle (both sides of an 'open both' stream are the same file and
   are positioned once). Standard streams are not positionable; if no
   current stream belongs to a handle, it is a runtime error. Returns 0
   on success and -1 if the position could not be set. */
int64_t crn_seek(int64_t off);
int64_t crn_close(int64_t h);
int64_t crn_system(uint8_t* cmd);
void crn_stop(int64_t code) CRN_NORETURN;

void crn_spawn(CrFnRef* f);
void crn_wait(void);

#endif

#include <stdlib.h>
#include <string.h>


#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

_Thread_local CrCtx cr_ctx = {0};

void crn_init(void) {
    memset(&cr_ctx, 0, sizeof cr_ctx);
    cr_ctx.in = stdin;
    cr_ctx.out = stdout;
}

void crn_die(const char* msg) {
    fprintf(stderr, "cryn: runtime error: %s\n", msg);
    exit(1);
}

void crn_die_range(uint64_t i, uint64_t n) {
    fprintf(stderr, "cryn: runtime error: index %llu out of bounds (size %llu)\n",
            (unsigned long long)i, (unsigned long long)n);
    exit(1);
}

/* ---- value stack ---- */

void crn_push(Val v) {
    if (cr_ctx.sp == cr_ctx.cap) {
        cr_ctx.cap = cr_ctx.cap ? cr_ctx.cap * 2 : 64;
        cr_ctx.stk = realloc(cr_ctx.stk, cr_ctx.cap * sizeof(Val));
        if (!cr_ctx.stk) crn_die("out of memory");
    }
    cr_ctx.stk[cr_ctx.sp++] = v;
}

Val crn_pop(void) { return cr_ctx.stk[--cr_ctx.sp]; }

/* ---- focus ---- */

void crn_focus_push(void* f) {
    if (cr_ctx.fh_sp >= CR_FH_MAX) {
        char msg[64];
        snprintf(msg, sizeof msg, "focus history overflow (limit %d)", CR_FH_MAX);
        crn_die(msg);
    }
    cr_ctx.fh[cr_ctx.fh_sp++] = f;
}

void* crn_focus_pop(void) {
    if (cr_ctx.fh_sp == 0) crn_die("focus history underflow");
    return cr_ctx.fh[--cr_ctx.fh_sp];
}

/* ---- heap ---- */

typedef struct CrHdr {
    uint64_t magic;
    uint64_t size; /* data bytes */
} CrHdr;

#define CR_MAGIC 0x4352594E424C4BULL /* "CRYNBLK" */

/* Registry of live block addresses. Validation must not read the header
   of a block that free() may already have returned to the allocator:
   reading freed memory is undefined in C, so stale-address detection
   (double free, indexing through a freed or shifted address) goes
   through this table instead. One global table, mutex protected,
   because blocks can be shared across spawned contexts. */
typedef struct CrReg {
    void** keys;      /* NULL = empty, CR_TOMB = deleted */
    size_t cap;       /* power of two */
    size_t used;      /* live + tombstones */
    pthread_mutex_t mu;
} CrReg;

#define CR_TOMB ((void*)1)

static CrReg cr_reg = {0, 0, 0, PTHREAD_MUTEX_INITIALIZER};
static pthread_once_t cr_reg_once = PTHREAD_ONCE_INIT;

static size_t reg_slot(void* p, size_t cap) {
    uintptr_t x = (uintptr_t)p >> 4; /* malloc blocks are 16-aligned */
    x ^= x >> 17;
    x *= 0x9E3779B97F4A7C15ULL;
    x ^= x >> 29;
    return (size_t)x & (cap - 1);
}

static void reg_init(void) {
    cr_reg.cap = 256;
    cr_reg.keys = malloc(cr_reg.cap * sizeof(void*));
    if (!cr_reg.keys) crn_die("out of memory");
    memset(cr_reg.keys, 0, cr_reg.cap * sizeof(void*));
    cr_reg.used = 0;
}

static void reg_grow_locked(void) {
    size_t ncap = cr_reg.cap * 2;
    void** nk = malloc(ncap * sizeof(void*));
    if (!nk) crn_die("out of memory");
    memset(nk, 0, ncap * sizeof(void*));
    for (size_t i = 0; i < cr_reg.cap; i++) {
        void* k = cr_reg.keys[i];
        if (!k || k == CR_TOMB) continue;
        size_t j = reg_slot(k, ncap);
        while (nk[j]) j = (j + 1) & (ncap - 1);
        nk[j] = k;
    }
    free(cr_reg.keys);
    cr_reg.keys = nk;
    cr_reg.cap = ncap;
}

/* returns the slot of p, or cap when absent (probing stops at NULL) */
static size_t reg_find_locked(void* p) {
    size_t j = reg_slot(p, cr_reg.cap);
    for (;;) {
        void* k = cr_reg.keys[j];
        if (!k) return cr_reg.cap;
        if (k == p) return j;
        j = (j + 1) & (cr_reg.cap - 1);
    }
}

static void reg_add(void* p) {
    pthread_once(&cr_reg_once, reg_init);
    pthread_mutex_lock(&cr_reg.mu);
    if ((cr_reg.used + 1) * 10 >= cr_reg.cap * 7) {
        reg_grow_locked();
        /* collapse tombstones into the new table */
        cr_reg.used = 0;
        for (size_t i = 0; i < cr_reg.cap; i++)
            if (cr_reg.keys[i]) cr_reg.used++;
    }
    size_t j = reg_slot(p, cr_reg.cap);
    while (cr_reg.keys[j] && cr_reg.keys[j] != CR_TOMB) j = (j + 1) & (cr_reg.cap - 1);
    cr_reg.keys[j] = p;
    cr_reg.used++;
    pthread_mutex_unlock(&cr_reg.mu);
}

static int reg_has(void* p) {
    pthread_once(&cr_reg_once, reg_init);
    pthread_mutex_lock(&cr_reg.mu);
    int found = reg_find_locked(p) != cr_reg.cap;
    pthread_mutex_unlock(&cr_reg.mu);
    return found;
}

static int reg_take(void* p) {
    pthread_once(&cr_reg_once, reg_init);
    pthread_mutex_lock(&cr_reg.mu);
    size_t j = reg_find_locked(p);
    if (j == cr_reg.cap) {
        pthread_mutex_unlock(&cr_reg.mu);
        return 0;
    }
    cr_reg.keys[j] = CR_TOMB;
    pthread_mutex_unlock(&cr_reg.mu);
    return 1;
}

void* crn_alloc(uint64_t nbytes) {
    /* the header and padding additions must not wrap */
    if (nbytes > (uint64_t)-32) crn_die("allocation too large");
    CrHdr* h = malloc(sizeof(CrHdr) + (size_t)nbytes + 16);
    if (!h) crn_die("out of memory");
    h->magic = CR_MAGIC;
    h->size = nbytes;
    unsigned char* p = (unsigned char*)h;
    p += sizeof(CrHdr);
    /* keep data 16-aligned: sizeof(CrHdr)==16 on 64-bit */
    memset(p, 0, (size_t)nbytes);
    reg_add(p);
    return p;
}

void crn_free(void* p) {
    if (!p) crn_die("free of the null address");
    if (!reg_take(p)) {
        crn_die("free of an address that is not a heap block "
                "(only live blocks made with 'make <size> of <type>' or anonymous "
                "'make' can be freed)");
    }
    CrHdr* h = (CrHdr*)((unsigned char*)p - sizeof(CrHdr));
    h->magic = 0;
    free(h);
}

uint64_t crn_block_n(void* data, uint64_t elemsz) {
    if (elemsz == 0) elemsz = 1;
    if (!reg_has(data)) {
        crn_die("index into memory that is not a heap block "
                "(only the base address of a live block made with "
                "'make <size> of <type>' is bounds checked)");
    }
    CrHdr* h = (CrHdr*)((unsigned char*)data - sizeof(CrHdr));
    return h->size / elemsz;
}

void crn_check_block(void* data, uint64_t i, uint64_t elemsz) {
    uint64_t n = crn_block_n(data, elemsz);
    if (i >= n) crn_die_range(i, n);
}

void crn_check_range(uint64_t i, uint64_t n) {
    if (i >= n) crn_die_range(i, n);
}

/* ---- relaxed atomic scalar access ---- */

#if defined(__GNUC__) || defined(__clang__)
#define CRN_LD(P) __atomic_load_n((P), __ATOMIC_RELAXED)
#define CRN_ST(P, V) __atomic_store_n((P), (V), __ATOMIC_RELAXED)
#else
/* fallback for hosts without the builtins: plain access (single aligned
   scalar loads/stores do not tear on such hosts in practice) */
#define CRN_LD(P) (*(P))
#define CRN_ST(P, V) (*(P) = (V))
#endif

uint8_t  crn_ld_u8(const uint8_t* p) { return CRN_LD((uint8_t*)p); }
uint16_t crn_ld_u16(const uint16_t* p) { return CRN_LD((uint16_t*)p); }
uint32_t crn_ld_u32(const uint32_t* p) { return CRN_LD((uint32_t*)p); }
uint64_t crn_ld_u64(const uint64_t* p) { return CRN_LD((uint64_t*)p); }
float    crn_ld_f32(const float* p) {
    uint32_t b = crn_ld_u32((const uint32_t*)(const void*)p);
    float v;
    memcpy(&v, &b, sizeof v);
    return v;
}
double   crn_ld_f64(const double* p) {
    uint64_t b = crn_ld_u64((const uint64_t*)(const void*)p);
    double v;
    memcpy(&v, &b, sizeof v);
    return v;
}
void crn_st_u8(uint8_t* p, uint8_t v) { CRN_ST(p, v); }
void crn_st_u16(uint16_t* p, uint16_t v) { CRN_ST(p, v); }
void crn_st_u32(uint32_t* p, uint32_t v) { CRN_ST(p, v); }
void crn_st_u64(uint64_t* p, uint64_t v) { CRN_ST(p, v); }
void crn_st_f32(float* p, float v) {
    uint32_t b;
    memcpy(&b, &v, sizeof b);
    crn_st_u32((uint32_t*)(void*)p, b);
}
void crn_st_f64(double* p, double v) {
    uint64_t b;
    memcpy(&b, &v, sizeof b);
    crn_st_u64((uint64_t*)(void*)p, b);
}

/* ---- atomic exchange (acquire-release) ---- */

uint8_t crn_xch_u8(uint8_t* p, uint8_t v) {
#if defined(__GNUC__) || defined(__clang__)
    return __atomic_exchange_n(p, v, __ATOMIC_ACQ_REL);
#else
    /* fallback for hosts without the builtins: a plain swap (correct for
       a single context; such hosts are not targets for racing programs) */
    uint8_t t = *p;
    *p = v;
    return t;
#endif
}
uint16_t crn_xch_u16(uint16_t* p, uint16_t v) {
#if defined(__GNUC__) || defined(__clang__)
    return __atomic_exchange_n(p, v, __ATOMIC_ACQ_REL);
#else
    uint16_t t = *p;
    *p = v;
    return t;
#endif
}
uint32_t crn_xch_u32(uint32_t* p, uint32_t v) {
#if defined(__GNUC__) || defined(__clang__)
    return __atomic_exchange_n(p, v, __ATOMIC_ACQ_REL);
#else
    uint32_t t = *p;
    *p = v;
    return t;
#endif
}
uint64_t crn_xch_u64(uint64_t* p, uint64_t v) {
#if defined(__GNUC__) || defined(__clang__)
    return __atomic_exchange_n(p, v, __ATOMIC_ACQ_REL);
#else
    uint64_t t = *p;
    *p = v;
    return t;
#endif
}
float crn_xch_f32(float* p, float v) {
    uint32_t b, nv;
    memcpy(&nv, &v, sizeof nv);
    b = crn_xch_u32((uint32_t*)(void*)p, nv);
    float r;
    memcpy(&r, &b, sizeof r);
    return r;
}
double crn_xch_f64(double* p, double v) {
    uint64_t b, nv;
    memcpy(&nv, &v, sizeof nv);
    b = crn_xch_u64((uint64_t*)(void*)p, nv);
    double r;
    memcpy(&r, &b, sizeof r);
    return r;
}

/* ---- conversions ---- */

int64_t crn_d2i64(double d) {
    if (d >= 9223372036854775808.0) return INT64_MAX;
    if (d <= -9223372036854775808.0) return INT64_MIN;
    return (int64_t)d;
}

uint64_t crn_d2u64(double d) {
    if (d >= 18446744073709551616.0) return UINT64_MAX;
    if (d <= 0.0) return 0;
    return (uint64_t)d;
}

int64_t crn_d2i8(double d) {
    if (d >= 127.0) return 127;
    if (d <= -128.0) return -128;
    return (int64_t)(int8_t)d;
}

int64_t crn_d2i16(double d) {
    if (d >= 32767.0) return 32767;
    if (d <= -32768.0) return -32768;
    return (int64_t)(int16_t)d;
}

int64_t crn_d2i32(double d) {
    if (d >= 2147483648.0) return 2147483647;
    if (d <= -2147483649.0) return -2147483648;
    return (int64_t)(int32_t)d;
}

uint64_t crn_d2u8(double d) {
    if (d >= 255.0) return 255;
    if (d <= 0.0) return 0;
    return (uint64_t)(uint8_t)d;
}

uint64_t crn_d2u16(double d) {
    if (d >= 65535.0) return 65535;
    if (d <= 0.0) return 0;
    return (uint64_t)(uint16_t)d;
}

uint64_t crn_d2u32(double d) {
    if (d >= 4294967296.0) return 4294967295ULL;
    if (d <= 0.0) return 0;
    return (uint64_t)(uint32_t)d;
}

/* ---- output ---- */

static void crn_out_str(const char* s) { fputs(s, cr_ctx.out); }

void crn_out_i64(int64_t v) { fprintf(cr_ctx.out, "%lld", (long long)v); }
void crn_out_u64(uint64_t v) { fprintf(cr_ctx.out, "%llu", (unsigned long long)v); }

static void crn_out_f(double v, int maxprec) {
    char buf[64];
    if (v != v) { /* NaN: the sign is meaningless; print one spelling */
        crn_out_str("nan");
        return;
    }
    for (int prec = 1; prec <= maxprec; prec++) {
        snprintf(buf, sizeof buf, "%.*g", prec, v);
        if (strtod(buf, NULL) == v) break;
    }
    crn_out_str(buf);
}

void crn_out_f64(double v) { crn_out_f(v, 17); }
void crn_out_f32(float v) {
    char buf[64];
    if (v != v) {
        crn_out_str("nan");
        return;
    }
    for (int prec = 1; prec <= 9; prec++) {
        snprintf(buf, sizeof buf, "%.*g", prec, v);
        if ((float)strtod(buf, NULL) == v) break;
    }
    crn_out_str(buf);
}
void crn_out_bool(int b) { crn_out_str(b ? "true" : "false"); }
void crn_out_char(unsigned c) { fputc((int)(c & 0xFF), cr_ctx.out); }
void crn_out_addr(uint64_t a) { fprintf(cr_ctx.out, "0x%llx", (unsigned long long)a); }

void crn_out_text(uint8_t* p) {
    FILE* f = cr_ctx.out;
    while (*p) fputc(*p++, f);
}

/* ---- input / files / system ---- */

int64_t crn_input(void) {
    int c = fgetc(cr_ctx.in);
    if (c == EOF) return -1;
    return c;
}

int64_t crn_open(uint8_t* path, int mode) {
    const char* m;
    switch (mode) {
    case 0: m = "rb"; break;
    case 1: m = "wb"; break;
    case 2: m = "w+b"; break;
    case 3: m = "ab"; break;
    default: return -1;
    }
    FILE* f = fopen((const char*)path, m);
    if (!f) return -1;
    /* find a free slot; handles are slot+1 */
    for (int i = 0; i < CR_FILES_MAX; i++) {
        if (cr_ctx.files[i]) continue;
        cr_ctx.files[i] = f;
        cr_ctx.fmodes[i] = (unsigned char)mode;
        return i + 1;
    }
    fclose(f);
    return -1; /* table full */
}

void crn_use(int64_t h) {
    if (h == 0) {
        cr_ctx.in = stdin;
        cr_ctx.out = stdout;
        return;
    }
    if (h < 1 || h > CR_FILES_MAX || !cr_ctx.files[h - 1])
        crn_die("use of a handle that is not open in this context "
                "(handles come from 'open'; 0 means the standard streams)");
    FILE* f = cr_ctx.files[h - 1];
    switch (cr_ctx.fmodes[h - 1]) {
    case 0: cr_ctx.in = f; break;                       /* read */
    case 2: cr_ctx.in = f; cr_ctx.out = f; break;       /* both */
    default: cr_ctx.out = f; break;                     /* write / append */
    }
}

void crn_flush(void) {
    if (fflush(cr_ctx.out) != 0) crn_die("flush failed");
}

int64_t crn_seek(int64_t off) {
    FILE* a = cr_ctx.in;
    FILE* b = cr_ctx.out;
    int any = 0;
    int bad = 0;
    /* standard streams are not positionable; only handle streams are */
    if (a && a != stdin) {
        any = 1;
        if (fseek(a, (long)off, SEEK_SET) != 0) bad = 1;
    }
    if (b && b != a && b != stdout) {
        any = 1;
        if (fseek(b, (long)off, SEEK_SET) != 0) bad = 1;
    }
    if (!any)
        crn_die("seek requires a stream routed through an open handle "
                "('use' a handle from 'open' first)");
    return bad ? -1 : 0;
}

int64_t crn_close(int64_t h) {
    if (h == 0)
        crn_die("close of handle 0 (the standard streams cannot be closed)");
    if (h < 1 || h > CR_FILES_MAX || !cr_ctx.files[h - 1])
        crn_die("close of a handle that is not open in this context "
                "(handles come from 'open' and are closed once)");
    FILE* f = cr_ctx.files[h - 1];
    cr_ctx.files[h - 1] = NULL;
    if (cr_ctx.in == f) cr_ctx.in = stdin;
    if (cr_ctx.out == f) cr_ctx.out = stdout;
    return fclose(f) == 0 ? 0 : -1;
}

int64_t crn_system(uint8_t* cmd) { return (int64_t)system((const char*)cmd); }

void crn_stop(int64_t code) { exit((int)(code & 0xFF)); }

/* ---- concurrency ---- */

typedef struct CrSpawnArg {
    CrFnRef* fn;
} CrSpawnArg;

static void* crn_thread_main(void* argp) {
    CrSpawnArg* a = argp;
    CrFnRef* fn = a->fn;
    free(a);
    crn_init();
    fn->fn();
    return NULL;
}

void crn_spawn(CrFnRef* f) {
    if (f->np != 0)
        crn_die("spawn of a transformation that takes parameters");
    if (cr_ctx.nspawned >= CR_SPAWN_MAX) {
        char msg[80];
        snprintf(msg, sizeof msg,
                 "too many outstanding spawned contexts (limit %d)", CR_SPAWN_MAX);
        crn_die(msg);
    }
    CrSpawnArg* a = malloc(sizeof(CrSpawnArg));
    if (!a) crn_die("out of memory");
    a->fn = f;
    if (pthread_create(&cr_ctx.spawned[cr_ctx.nspawned++], NULL, crn_thread_main, a) != 0)
        crn_die("thread creation failed");
}

void crn_wait(void) {
    for (int i = 0; i < cr_ctx.nspawned; i++)
        pthread_join(cr_ctx.spawned[i], NULL);
    cr_ctx.nspawned = 0;
}


static uint8_t g_nl[2] = {0};
static int8_t g_c8 = 0;
static uint8_t g_u8 = 0;
static int16_t g_c16 = 0;
static uint16_t g_u16 = 0;
static int32_t g_c32 = 0;
static uint32_t g_u32 = 0;
static int64_t g_c64 = 0;
static uint64_t g_u64 = 0;
static uint8_t g_b = 0;
static uint8_t g_ch = 0;
static float g_f32 = 0;
static double g_f64 = 0;
static const uint8_t g_nl_init[] = "\n\000";

static Val cr_fn_newline(void);
static Val cr_fn_main(void);

static CrFnRef cr_ref_newline = {(Val(*)(void))cr_fn_newline, 0};
static CrFnRef cr_ref_main = {(Val(*)(void))cr_fn_main, 0};

static void crn_init_world(void) {
    memcpy(g_nl, g_nl_init, 2);
}

static Val cr_fn_newline(void) {
    uint64_t cr_fh0 = cr_ctx.fh_sp;
    int cr_cmp = 0;
    Val wv; wv.u = 0;
    void* F = 0;
    wv.u = (uint64_t)(uintptr_t)&g_nl;
    crn_out_text((uint8_t*)(uintptr_t)wv.u);
    wv.u = (uint64_t)0ULL;
    cr_ctx.fh_sp = cr_fh0; return wv;
    cr_ctx.fh_sp = cr_fh0; return wv;
}

static Val cr_fn_main(void) {
    uint64_t cr_fh0 = cr_ctx.fh_sp;
    int cr_cmp = 0;
    Val wv; wv.u = 0;
    void* F = 0;
    wv.u = (uint64_t)18446744073709551607ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c8;
    crn_st_u8((uint8_t*)F, (uint8_t)(int64_t)wv.u);
    wv.u = (uint64_t)47ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c8;
    wv.i = (int64_t)(int8_t)wv.u;
    wv.i = (int64_t)(int8_t)crn_xch_u8((uint8_t*)F, (int8_t)wv.i);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    cr_ctx.fh_sp = cr_fh0; F = &g_c8;
    wv.i = (int64_t)(int8_t)crn_ld_u8((const uint8_t*)F);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)200ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u8;
    crn_st_u8((uint8_t*)F, (uint8_t)(int64_t)wv.u);
    wv.u = (uint64_t)1ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u8;
    wv.u = (uint64_t)(uint8_t)wv.u;
    wv.u = (uint64_t)(uint8_t)crn_xch_u8((uint8_t*)F, (uint8_t)wv.u);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    cr_ctx.fh_sp = cr_fh0; F = &g_u8;
    wv.u = (uint64_t)crn_ld_u8((const uint8_t*)F);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)18446744073709550616ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c16;
    crn_st_u16((uint16_t*)F, (uint16_t)(int64_t)wv.u);
    wv.u = (uint64_t)1000ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c16;
    wv.i = (int64_t)(int16_t)wv.u;
    wv.i = (int64_t)(int16_t)crn_xch_u16((uint16_t*)F, (int16_t)wv.i);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)60000ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u16;
    crn_st_u16((uint16_t*)F, (uint16_t)(int64_t)wv.u);
    wv.u = (uint64_t)60001ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u16;
    wv.u = (uint64_t)(uint16_t)wv.u;
    wv.u = (uint64_t)(uint16_t)crn_xch_u16((uint16_t*)F, (uint16_t)wv.u);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)18446744071709551616ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c32;
    crn_st_u32((uint32_t*)F, (uint32_t)(int64_t)wv.u);
    wv.u = (uint64_t)7ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c32;
    wv.i = (int64_t)(int32_t)wv.u;
    wv.i = (int64_t)(int32_t)crn_xch_u32((uint32_t*)F, (int32_t)wv.i);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)4000000000ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u32;
    crn_st_u32((uint32_t*)F, (uint32_t)(int64_t)wv.u);
    wv.u = (uint64_t)8ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u32;
    wv.u = (uint64_t)(uint32_t)wv.u;
    wv.u = (uint64_t)(uint32_t)crn_xch_u32((uint32_t*)F, (uint32_t)wv.u);
    wv.i = (int64_t)(int64_t)wv.u;
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)18446744068709551616ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c64;
    crn_st_u64((uint64_t*)F, (uint64_t)(int64_t)wv.u);
    wv.u = (uint64_t)5000000000ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_c64;
    wv.i = (int64_t)(int64_t)wv.u;
    wv.i = (int64_t)(int64_t)crn_xch_u64((uint64_t*)F, (int64_t)wv.i);
    crn_out_i64((int64_t)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)18000000000000000000ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u64;
    crn_st_u64((uint64_t*)F, (uint64_t)(int64_t)wv.u);
    wv.u = (uint64_t)2ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_u64;
    wv.u = (uint64_t)(uint64_t)wv.u;
    wv.u = (uint64_t)(uint64_t)crn_xch_u64((uint64_t*)F, (uint64_t)wv.u);
    crn_out_u64(wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)0ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_b;
    crn_st_u8((uint8_t*)F, (uint8_t)wv.u);
    wv.u = (uint64_t)1ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_b;
    wv.u = (uint64_t)(uint8_t)crn_xch_u8((uint8_t*)F, (uint8_t)wv.u);
    crn_out_bool((int)wv.u);
    cr_fn_newline();
    cr_ctx.fh_sp = cr_fh0; F = &g_b;
    wv.u = (uint64_t)crn_ld_u8((const uint8_t*)F);
    crn_out_bool((int)wv.u);
    cr_fn_newline();
    wv.u = (uint64_t)81ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_ch;
    crn_st_u8((uint8_t*)F, (uint8_t)wv.u);
    wv.u = (uint64_t)90ULL;
    cr_ctx.fh_sp = cr_fh0; F = &g_ch;
    wv.u = (uint64_t)(uint8_t)crn_xch_u8((uint8_t*)F, (uint8_t)wv.u);
    crn_out_char((unsigned)wv.u);
    cr_fn_newline();
    wv.d = (double)1.5;
    cr_ctx.fh_sp = cr_fh0; F = &g_f32;
    crn_st_f32((float*)F, (float)wv.d);
    wv.d = (double)2.75;
    cr_ctx.fh_sp = cr_fh0; F = &g_f32;
    wv.d = (double)(float)wv.d;
    wv.d = (double)crn_xch_f32((float*)F, (float)wv.d);
    crn_out_f32((float)wv.d);
    cr_fn_newline();
    cr_ctx.fh_sp = cr_fh0; F = &g_f32;
    wv.d = (double)crn_ld_f32((const float*)F);
    crn_out_f32((float)wv.d);
    cr_fn_newline();
    wv.d = (double)0.125;
    cr_ctx.fh_sp = cr_fh0; F = &g_f64;
    crn_st_f64((double*)F, wv.d);
    wv.d = (double)6.5;
    cr_ctx.fh_sp = cr_fh0; F = &g_f64;
    wv.d = crn_xch_f64((double*)F, wv.d);
    crn_out_f64(wv.d);
    cr_fn_newline();
    wv.u = (uint64_t)0ULL;
    cr_ctx.fh_sp = cr_fh0; return wv;
    cr_ctx.fh_sp = cr_fh0; return wv;
}

int main(void) {
    crn_init();
    crn_init_world();
    cr_fn_main();
    fflush(NULL);
    return 0;
}