201 lines
7.8 KiB
C
201 lines
7.8 KiB
C
#ifndef CENT_RUNTIME_H
|
||
#define CENT_RUNTIME_H
|
||
|
||
#include <stddef.h>
|
||
#include <string.h>
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Types */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
typedef enum {
|
||
CENT_INT,
|
||
CENT_STR,
|
||
CENT_BOOL,
|
||
CENT_LIST,
|
||
CENT_FRAC,
|
||
CENT_NULL
|
||
} CentType;
|
||
|
||
typedef struct CentValue CentValue;
|
||
typedef struct CentList CentList;
|
||
|
||
/* Duodecimal fraction: num/den stored as exact integers */
|
||
typedef struct {
|
||
long num;
|
||
long den;
|
||
} CentFrac;
|
||
|
||
struct CentList {
|
||
CentValue *items;
|
||
int len;
|
||
int cap;
|
||
};
|
||
|
||
struct CentValue {
|
||
CentType type;
|
||
union {
|
||
long ival; /* CENT_INT */
|
||
char *sval; /* CENT_STR */
|
||
int bval; /* CENT_BOOL */
|
||
CentList lval; /* CENT_LIST */
|
||
CentFrac fval; /* CENT_FRAC */
|
||
};
|
||
};
|
||
|
||
/* Scope: flat name→value array. Stack-allocated by the caller;
|
||
cent_scope_set uses cent_arena when it needs to grow. */
|
||
typedef struct {
|
||
const char **names;
|
||
CentValue *vals;
|
||
int len;
|
||
int cap;
|
||
} CentScope;
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Arena allocator — no free() during a program run */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
typedef struct CentArena CentArena;
|
||
|
||
struct CentArena {
|
||
char *buf;
|
||
size_t used;
|
||
size_t cap;
|
||
CentArena *next; /* overflow chain */
|
||
};
|
||
|
||
CentArena *cent_arena_new(size_t cap);
|
||
void *cent_arena_alloc(CentArena *a, size_t n);
|
||
|
||
/* Global arena; initialised in cent_runtime.c main() setup */
|
||
extern CentArena *cent_arena;
|
||
|
||
/* Set to 1 when CVM MAGNVM is active; enables extended numeral display */
|
||
extern int cent_magnvm;
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Value constructors */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
static inline CentValue cent_int(long v) {
|
||
CentValue r; r.type = CENT_INT; r.ival = v; return r;
|
||
}
|
||
static inline CentValue cent_str(const char *s) {
|
||
CentValue r; r.type = CENT_STR; r.sval = (char *)s; return r;
|
||
}
|
||
static inline CentValue cent_bool(int v) {
|
||
CentValue r; r.type = CENT_BOOL; r.bval = !!v; return r;
|
||
}
|
||
static inline CentValue cent_null(void) {
|
||
CentValue r; r.type = CENT_NULL; r.ival = 0; return r;
|
||
}
|
||
static inline CentValue cent_frac(long num, long den) {
|
||
CentValue r; r.type = CENT_FRAC; r.fval.num = num; r.fval.den = den; return r;
|
||
}
|
||
static inline CentValue cent_list(CentValue *items, int len, int cap) {
|
||
CentValue r;
|
||
r.type = CENT_LIST;
|
||
r.lval.items = items;
|
||
r.lval.len = len;
|
||
r.lval.cap = cap;
|
||
return r;
|
||
}
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Error handling */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
void cent_type_error(const char *msg); /* type mismatch → exit(1) */
|
||
void cent_runtime_error(const char *msg); /* runtime fault → exit(1) */
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Truthiness — conditions must be booleans; anything else is a fault */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
static inline int cent_truthy(CentValue v) {
|
||
if (v.type != CENT_BOOL)
|
||
cent_type_error("condition must be a boolean (VERITAS/FALSITAS)");
|
||
return v.bval;
|
||
}
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Scope operations */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
/* Look up name; returns cent_null() if not found */
|
||
CentValue cent_scope_get(CentScope *s, const char *name);
|
||
|
||
/* Insert or update name→v; grows via cent_arena if needed */
|
||
void cent_scope_set(CentScope *s, const char *name, CentValue v);
|
||
|
||
/* Shallow copy of a scope (matches vtable.copy() semantics) */
|
||
CentScope cent_scope_copy(CentScope *s);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Roman numeral conversion */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
/* int → Roman numeral string (1–3999, or any positive int if cent_magnvm set) */
|
||
void cent_int_to_roman(long n, char *buf, size_t bufsz);
|
||
/* Roman numeral string → int; exits on invalid input */
|
||
long cent_roman_to_int(const char *s);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Display */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
/* Returns arena-allocated string mirroring Python make_string() */
|
||
char *cent_make_string(CentValue v);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Arithmetic and comparison operators */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
CentValue cent_add(CentValue a, CentValue b); /* INT+INT or FRAC+FRAC/INT */
|
||
CentValue cent_concat(CentValue a, CentValue b); /* & operator: coerce all types to str */
|
||
CentValue cent_sub(CentValue a, CentValue b); /* INT-INT or FRAC-FRAC/INT */
|
||
CentValue cent_mul(CentValue a, CentValue b); /* INT*INT or FRAC*FRAC/INT */
|
||
CentValue cent_div(CentValue a, CentValue b); /* INT/INT integer div */
|
||
CentValue cent_div_frac(CentValue a, CentValue b); /* FRACTIO: exact div → FRAC */
|
||
CentValue cent_mod(CentValue a, CentValue b); /* INT%INT integer modulo */
|
||
CentValue cent_mod_frac(CentValue a, CentValue b); /* FRACTIO: floored mod → FRAC */
|
||
CentValue cent_eq (CentValue a, CentValue b); /* EST → BOOL */
|
||
CentValue cent_neq(CentValue a, CentValue b); /* DISPAR → BOOL */
|
||
CentValue cent_lt (CentValue a, CentValue b); /* MINVS → BOOL */
|
||
CentValue cent_gt (CentValue a, CentValue b); /* PLVS → BOOL */
|
||
CentValue cent_and(CentValue a, CentValue b); /* ET → BOOL */
|
||
CentValue cent_or (CentValue a, CentValue b); /* AVT → BOOL */
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Builtin functions */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
void cent_dice(CentValue v); /* DICE */
|
||
CentValue cent_avdi(void); /* AVDI */
|
||
CentValue cent_avdi_numerus(void); /* AVDI_NVMERVS */
|
||
CentValue cent_longitudo(CentValue v); /* LONGITVDO */
|
||
CentValue cent_fortis_numerus(CentValue lo, CentValue hi); /* FORTIS_NVMERVS */
|
||
CentValue cent_fortis_electionis(CentValue lst); /* FORTIS_ELECTIONIS */
|
||
CentValue cent_decimatio(CentValue lst); /* DECIMATIO */
|
||
void cent_semen(CentValue seed); /* SEMEN */
|
||
void cent_everro(void); /* EVERRO */
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Array helpers */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
CentValue cent_list_new(int cap);
|
||
void cent_list_push(CentValue *lst, CentValue v);
|
||
CentValue cent_list_index(CentValue lst, CentValue idx); /* 1-based */
|
||
void cent_list_index_set(CentValue *lst, CentValue idx, CentValue v);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Initialisation */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
/* Call once at program start: sets up arena + seeds RNG */
|
||
void cent_init(void);
|
||
|
||
#endif /* CENT_RUNTIME_H */
|