289 lines
12 KiB
C
289 lines
12 KiB
C
#ifndef CENT_RUNTIME_H
|
||
#define CENT_RUNTIME_H
|
||
|
||
#include <stddef.h>
|
||
#include <string.h>
|
||
#include <setjmp.h>
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Types */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
typedef enum {
|
||
CENT_INT,
|
||
CENT_STR,
|
||
CENT_BOOL,
|
||
CENT_LIST,
|
||
CENT_FRAC,
|
||
CENT_DICT,
|
||
CENT_FUNC,
|
||
CENT_NULL
|
||
} CentType;
|
||
|
||
typedef struct CentValue CentValue;
|
||
typedef struct CentList CentList;
|
||
typedef struct CentDict CentDict;
|
||
struct CentScope; /* forward declaration */
|
||
|
||
/* First-class function value */
|
||
typedef CentValue (*CentFuncPtr)(struct CentScope);
|
||
|
||
typedef struct {
|
||
CentFuncPtr fn;
|
||
const char **param_names;
|
||
int param_count;
|
||
} CentFuncInfo;
|
||
|
||
/* Duodecimal fraction: num/den stored as exact integers */
|
||
typedef struct {
|
||
long num;
|
||
long den;
|
||
} CentFrac;
|
||
|
||
struct CentList {
|
||
CentValue *items;
|
||
int len;
|
||
int cap;
|
||
};
|
||
|
||
struct CentDict {
|
||
CentValue *keys;
|
||
CentValue *vals;
|
||
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 */
|
||
CentDict dval; /* CENT_DICT */
|
||
CentFuncInfo fnval; /* CENT_FUNC */
|
||
};
|
||
};
|
||
|
||
/* Scope: flat name→value array. Stack-allocated by the caller;
|
||
cent_scope_set uses cent_arena when it needs to grow. */
|
||
typedef struct CentScope {
|
||
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;
|
||
|
||
/* Set to 1 when CVM SVBNVLLA is active; enables negative number display */
|
||
extern int cent_svbnvlla;
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* 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;
|
||
}
|
||
static inline CentValue cent_func_val(CentFuncPtr fn, const char **param_names, int param_count) {
|
||
CentValue r;
|
||
r.type = CENT_FUNC;
|
||
r.fnval.fn = fn;
|
||
r.fnval.param_names = param_names;
|
||
r.fnval.param_count = param_count;
|
||
return r;
|
||
}
|
||
static inline CentValue cent_dict_val(CentValue *keys, CentValue *vals, int len, int cap) {
|
||
CentValue r;
|
||
r.type = CENT_DICT;
|
||
r.dval.keys = keys;
|
||
r.dval.vals = vals;
|
||
r.dval.len = len;
|
||
r.dval.cap = cap;
|
||
return r;
|
||
}
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Error handling */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
#define CENT_TRY_STACK_MAX 64
|
||
extern jmp_buf _cent_try_stack[];
|
||
extern int _cent_try_depth;
|
||
extern const char *_cent_error_msg;
|
||
|
||
void cent_type_error(const char *msg); /* type mismatch → longjmp or exit(1) */
|
||
void cent_runtime_error(const char *msg); /* runtime fault → longjmp or 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_neg(CentValue v); /* unary minus: INT or FRAC */
|
||
CentValue cent_add(CentValue a, CentValue b); /* INT+INT or FRAC+FRAC/INT */
|
||
CentValue cent_array_concat(CentValue a, CentValue b); /* @ operator: concatenate two arrays */
|
||
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_lte(CentValue a, CentValue b); /* HAVD_PLVS → BOOL */
|
||
CentValue cent_gte(CentValue a, CentValue b); /* HAVD_MINVS → BOOL */
|
||
CentValue cent_and(CentValue a, CentValue b); /* ET → BOOL */
|
||
CentValue cent_or (CentValue a, CentValue b); /* AVT → BOOL */
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Builtin functions */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
void cent_dic(CentValue v); /* DIC */
|
||
CentValue cent_avdi(void); /* AVDI */
|
||
CentValue cent_avdi_numerus(void); /* AVDI_NVMERVS */
|
||
CentValue cent_longitudo(CentValue v); /* LONGITVDO */
|
||
CentValue cent_littera(CentValue v); /* LITTERA */
|
||
CentValue cent_maivscvla(CentValue v); /* MAIVSCVLA */
|
||
CentValue cent_minvscvla(CentValue v); /* MINVSCVLA */
|
||
CentValue cent_fortuitus_numerus(CentValue lo, CentValue hi); /* FORTVITVS_NVMERVS */
|
||
CentValue cent_fortuita_electionis(CentValue lst); /* FORTVITA_ELECTIO */
|
||
CentValue cent_decimatio(CentValue lst); /* DECIMATIO */
|
||
void cent_semen(CentValue seed); /* SEMEN */
|
||
void cent_everre(void); /* EVERRE */
|
||
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
||
CentValue cent_typvs(CentValue v); /* TYPVS */
|
||
void cent_dormi(CentValue n); /* DORMI */
|
||
CentValue cent_ordina(CentValue lst); /* ORDINA */
|
||
CentValue cent_ordina_cmp(CentValue lst, CentValue cmp, CentScope scope); /* ORDINA w/ comparator */
|
||
CentValue cent_mvta(CentValue lst, CentValue fn, CentScope scope); /* MVTA */
|
||
CentValue cent_cribra(CentValue lst, CentValue fn, CentScope scope); /* CRIBRA */
|
||
CentValue cent_confla(CentValue lst, CentValue init, CentValue fn, CentScope scope); /* CONFLA */
|
||
CentValue cent_adde(CentValue lst, CentValue v); /* ADDE */
|
||
CentValue cent_tolle(CentValue lst, CentValue idx); /* TOLLE */
|
||
CentValue cent_insere(CentValue lst, CentValue idx, CentValue v); /* INSERE */
|
||
CentValue cent_necte(CentValue a, CentValue b); /* NECTE */
|
||
CentValue cent_ivnge(CentValue keys, CentValue vals); /* IVNGE */
|
||
CentValue cent_lege(CentValue path); /* LEGE */
|
||
void cent_scribe(CentValue path, CentValue content); /* SCRIBE */
|
||
void cent_adivnge(CentValue path, CentValue content); /* ADIVNGE */
|
||
CentValue cent_numerus(CentValue s); /* NVMERVS */
|
||
CentValue cent_qvaere(CentValue pattern, CentValue text); /* QVAERE */
|
||
CentValue cent_svbstitve(CentValue pattern, CentValue replacement, CentValue text); /* SVBSTITVE */
|
||
CentValue cent_scinde(CentValue str, CentValue delim); /* SCINDE */
|
||
CentValue cent_pete(CentValue url); /* PETE */
|
||
void cent_petitvr(CentValue path, CentValue handler, CentScope scope); /* PETITVR */
|
||
void cent_avscvlta(CentValue port); /* AVSCVLTA */
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* 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 */
|
||
CentValue cent_list_slice(CentValue lst, CentValue lo, CentValue hi); /* 1-based, inclusive */
|
||
void cent_list_index_set(CentValue *lst, CentValue idx, CentValue v);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Dict helpers */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
CentValue cent_dict_new(int cap);
|
||
void cent_dict_set(CentValue *dict, CentValue key, CentValue val);
|
||
CentValue cent_dict_get(CentValue dict, CentValue key);
|
||
CentValue cent_dict_keys(CentValue dict);
|
||
|
||
/* ------------------------------------------------------------------ */
|
||
/* Initialisation */
|
||
/* ------------------------------------------------------------------ */
|
||
|
||
/* Call once at program start: sets up arena + seeds RNG */
|
||
void cent_init(void);
|
||
|
||
#endif /* CENT_RUNTIME_H */
|