#ifndef CVM_CORE_H
#define CVM_CORE_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
* cvmruntime — 米特-木卫三协议状态机运行时
* 协议状态机 (ProtoState) 扩展: 为 XL-MD-001 演习 / 六万旅级节点网络
* 提供事件驱动的状态转换能力
* ========================================================================= */
typedef struct Runtime Runtime;
#define CVM_MAX_LOAD_DEPTH 48
#define CVM_MAX_LOAD_PATH 768
#define CVM_MAX_CALL_DEPTH 2048
* cvmruntime — 一门 C 风格脚本语言的纯 C 解释器运行时
* 架构: lexer -> parser -> AST -> 树遍历解释器 + 环境帧 + 宿主API + FFI
* 零外部依赖 (仅标准库 + 平台动态库 API), 编译: gcc -Wall -Werror -std=c11
* ========================================================================= */
typedef struct ArenaBlock {
unsigned char *data;
size_t size;
size_t used;
struct ArenaBlock *next;
} ArenaBlock;
typedef struct {
ArenaBlock *head;
size_t block_size;
size_t gc_bytes;
size_t gc_threshold;
} Arena;
void arena_init(Arena *a);
void arena_destroy(Arena *a);
void *arena_alloc(Arena *a, size_t n);
char *arena_strndup(Arena *a, const char *s, size_t n);
char *arena_strdup(Arena *a, const char *s);
void arena_reset(Arena *a);
void gc_collect(Runtime *rt);
#define VAL_NUM 1
#define VAL_STR 2
#define VAL_BOOL 3
#define VAL_NIL 4
#define VAL_INT 5
#define VAL_ARRAY 6
#define VAL_FUNC 7
#define VAL_PTR 8
#define VAL_MODULE 9
#define VAL_CLOSURE 10
typedef struct {
int type;
union {
double num;
char *str;
int boolean;
int64_t i;
void *arr;
char *funcname;
void *mod;
void *closure;
void *ptr;
} as;
} Value;
static inline Value val_num(double n) { Value v; v.type = VAL_NUM; v.as.num = n; return v; }
static inline Value val_str(char *s) { Value v; v.type = VAL_STR; v.as.str = s; return v; }
static inline Value val_bool(int b) { Value v; v.type = VAL_BOOL; v.as.boolean = b ? 1 : 0; return v; }
static inline Value val_nil(void) { Value v; v.type = VAL_NIL; return v; }
static inline Value val_module(void *m) { Value v; v.type = VAL_MODULE; v.as.mod = m; return v; }
static inline Value val_func(char *name) { Value v; v.type = VAL_FUNC; v.as.funcname = name; return v; }
static inline Value val_array(void *arr) { Value v; v.type = VAL_ARRAY; v.as.arr = arr; return v; }
static inline Value val_closure(void *cl) { Value v; v.type = VAL_CLOSURE; v.as.closure = cl; return v; }
static inline Value val_ptr(void *p) { Value v; v.type = VAL_PTR; v.as.ptr = p; return v; }
static inline Value val_int(int64_t n) { Value v; v.type = VAL_INT; v.as.i = n; return v; }
static inline int v_is_int(Value v) { return v.type == VAL_INT; }
static inline int v_is_num(Value v) { return v.type == VAL_NUM; }
static inline int v_is_nil(Value v) { return v.type == VAL_NIL; }
static inline int v_is_bool(Value v) { return v.type == VAL_BOOL; }
static inline int v_is_str(Value v) { return v.type == VAL_STR; }
static inline int v_is_array(Value v) { return v.type == VAL_ARRAY; }
static inline int v_is_func(Value v) { return v.type == VAL_FUNC; }
static inline int v_is_ptr(Value v) { return v.type == VAL_PTR; }
static inline int v_is_closure(Value v){ return v.type == VAL_CLOSURE; }
static inline int v_is_module(Value v) { return v.type == VAL_MODULE; }
static inline double v_as_double(Value v) { return v.as.num; }
static inline int64_t v_as_int(Value v) { return v.as.i; }
static inline int v_as_bool(Value v) { return v.as.boolean; }
static inline char *v_as_str(Value v) { return v.as.str; }
static inline void *v_as_ptr(Value v) { return v.as.ptr; }
static inline int v_type(Value v) { return v.type; }
static inline Value val_ptr_obj(void *p) { Value v; v.type = VAL_PTR; v.as.ptr = p; return v; }
int val_truthy(Value v);
int value_equal(Value a, Value b, int depth);
const char *val_type_name(Value v);
char *val_to_str(Arena *a, Value v);
* 约定: 非法/截断字节一律按单字节处理, 不抛出、不越界读。 */
static inline int utf8_seq_len(unsigned char c) {
if (c < 0x80) return 1;
if ((c & 0xE0) == 0xC0) return 2;
if ((c & 0xF0) == 0xE0) return 3;
if ((c & 0xF8) == 0xF0) return 4;
return 1;
}
* 硬化: 多字节首字节承诺 len 字节, 但只计入真正连续且合法的续延字节,
* 遇到 NUL 或非法续延字节即止。对合法 UTF-8 结果不变; 截断/损坏串不再越过 NUL。 */
static inline long utf8_count_codepoints(const char *s) {
if (!s) return 0;
long n = 0;
const unsigned char *p = (const unsigned char *)s;
while (*p) {
int len = utf8_seq_len(*p);
int actual = 1;
for (int k = 1; k < len; k++) {
if (p[k] == '\0' || (p[k] & 0xC0) != 0x80) break;
actual = k + 1;
}
p += actual; n++;
}
return n;
}
* idx 越界返回 NULL, 并通过 outlen 写出该码点"实际有效"字节长(越界时 0)。
* 硬化: outlen = 真正连续的合法字节数(截断串为其实际长度, 而非承诺长度),
* 调用方据此复制不会越过 NUL 读垃圾字节。 */
static inline const char *utf8_char_at_ptr(const char *s, long idx, int *outlen) {
if (outlen) *outlen = 0;
if (!s || idx < 0) return NULL;
const unsigned char *p = (const unsigned char *)s;
long i = 0;
while (*p) {
int len = utf8_seq_len(*p);
int actual = 1;
for (int k = 1; k < len; k++) {
if (p[k] == '\0' || (p[k] & 0xC0) != 0x80) break;
actual = k + 1;
}
if (i == idx) { if (outlen) *outlen = actual; return (const char *)p; }
p += actual; i++;
}
return NULL;
}
* 硬化: 若序列被截断/损坏(实际字节 < 承诺长度), 降级返回首字节原值,
* 而非越界拼出乱码; 完整序列仍按 UTF-8 精确解码。 */
static inline int64_t utf8_codepoint_at(const char *s, long idx) {
int len;
const char *p = utf8_char_at_ptr(s, idx, &len);
if (!p) return -1;
const unsigned char *u = (const unsigned char *)p;
if (len < utf8_seq_len(u[0])) return (int64_t)u[0];
switch (len) {
case 1: return (int64_t)u[0];
case 2: return (int64_t)(((u[0] & 0x1F) << 6) | (u[1] & 0x3F));
case 3: return (int64_t)(((u[0] & 0x0F) << 12) | ((u[1] & 0x3F) << 6) | (u[2] & 0x3F));
case 4: return (int64_t)(((u[0] & 0x07) << 18) | ((u[1] & 0x3F) << 12) | ((u[2] & 0x3F) << 6) | (u[3] & 0x3F));
default: return -1;
}
}
static inline int utf8_encode(int64_t cp, char out[4]) {
if (cp < 0x80) { out[0] = (char)cp; return 1; }
if (cp < 0x800) { out[0] = (char)(0xC0 | (cp >> 6));
out[1] = (char)(0x80 | (cp & 0x3F)); return 2; }
if (cp < 0x10000) { out[0] = (char)(0xE0 | (cp >> 12));
out[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
out[2] = (char)(0x80 | (cp & 0x3F)); return 3; }
out[0] = (char)(0xF0 | (cp >> 18));
out[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
out[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
out[3] = (char)(0x80 | (cp & 0x3F));
return 4;
}
* to_upper=1 则返回大写, =0 则返回小写; 未知字符返回原值 */
static inline int64_t unicode_casefold(int64_t cp, int to_upper) {
if (cp <= 0x7F) {
if (to_upper) { if (cp >= 'a' && cp <= 'z') return cp - 32; }
else { if (cp >= 'A' && cp <= 'Z') return cp + 32; }
return cp;
}
if (to_upper) {
if (cp >= 0xE0 && cp <= 0xF6) return cp - 0x20;
if (cp >= 0xF8 && cp <= 0xFE) return cp - 0x20;
if (cp == 0xFF) return 0x178;
if (cp >= 0x3B1 && cp <= 0x3C1) return cp - 0x20;
if (cp >= 0x3C3 && cp <= 0x3CB) return cp - 0x20;
if (cp == 0x3C2) return 0x3A3;
switch (cp) {
case 0x3AC: return 0x386;
case 0x3AD: return 0x388;
case 0x3AE: return 0x389;
case 0x3AF: return 0x38A;
case 0x3CC: return 0x38C;
case 0x3CD: return 0x38E;
case 0x3CE: return 0x38F;
}
if (cp >= 0x430 && cp <= 0x44F) return cp - 0x20;
if (cp >= 0x450 && cp <= 0x45F) return cp - 0x50;
} else {
if (cp >= 0xC0 && cp <= 0xD6) return cp + 0x20;
if (cp >= 0xD8 && cp <= 0xDE) return cp + 0x20;
if (cp == 0x178) return 0xFF;
if (cp >= 0x391 && cp <= 0x3A1) return cp + 0x20;
if (cp >= 0x3A3 && cp <= 0x3AB) return cp + 0x20;
switch (cp) {
case 0x386: return 0x3AC;
case 0x388: return 0x3AD;
case 0x389: return 0x3AE;
case 0x38A: return 0x3AF;
case 0x38C: return 0x3CC;
case 0x38E: return 0x3CD;
case 0x38F: return 0x3CE;
}
if (cp >= 0x410 && cp <= 0x42F) return cp + 0x20;
if (cp >= 0x400 && cp <= 0x40F) return cp + 0x50;
}
return cp;
}
typedef struct MapNode {
char *key;
void *value;
struct MapNode *next;
} MapNode;
typedef struct {
MapNode **buckets;
int cap;
int count;
} Map;
void map_init(Map *m);
void map_destroy(Map *m);
void map_set(Map *m, const char *key, void *value);
void *map_get(Map *m, const char *key);
* 数组按引用语义共享(类似 Lua table / Python list)。数据分配在 arena,
* 随运行时销毁, 运行期不单独释放。 */
typedef struct ArrEntry {
int is_str;
char *skey;
int64_t ikey;
Value value;
struct ArrEntry *hnext;
} ArrEntry;
typedef struct {
ArrEntry **buckets;
int cap;
int count;
ArrEntry **order;
int order_cap;
int64_t next_ikey;
} Arr;
void arr_init(Arena *a, Arr *arr);
void arr_set(Arena *a, Arr *arr, int is_str, const char *skey, int64_t ikey, Value v);
void arr_append(Arena *a, Arr *arr, Value v);
void arr_set_from_key(Runtime *rt, Arr *arr, Value key, Value v);
ArrEntry *arr_lookup(Runtime *rt, Arr *arr, Value key);
ArrEntry *arr_find(int is_str, const char *skey, int64_t ikey, const Arr *arr);
int arr_del(Arr *arr, Value key);
int arr_len(const Arr *arr);
ArrEntry *arr_at(const Arr *arr, int idx);
Arr *arr_copy(Arena *a, const Arr *src);
Arr *arr_keys(Arena *a, const Arr *src);
Arr *arr_values(Arena *a, const Arr *src);
int arr_equal(const Arr *x, const Arr *y);
typedef struct Env Env;
struct Env { Env *parent; Map vars; };
typedef struct Runtime Runtime;
Env *env_new(Env *parent, Arena *a);
void env_free(Env *e);
Value *env_get(Env *e, const char *name);
void env_define(Env *e, const char *name, Value v, Arena *a);
void env_assign(Env *e, const char *name, Value v, Arena *a);
Env *env_get_owner(Env *e, const char *name, Value **out);
Env *env_root(Env *e);
void env_link(Env *e, const char *name, Value *slot);
enum {
TK_EOF = 0,
TK_NUM, TK_STR, TK_IDENT,
TK_LET, TK_IF, TK_ELSE, TK_WHILE, TK_FOR, TK_FUNC, TK_RETURN,
TK_BREAK, TK_CONTINUE,
TK_TRUE, TK_FALSE, TK_NIL,
TK_AND, TK_OR, TK_NOT,
TK_EQEQ, TK_NOTEQ, TK_LE, TK_GE, TK_LT, TK_GT,
TK_ASSIGN,
TK_PLUS, TK_MINUS, TK_STAR, TK_SLASH, TK_PERCENT,
TK_LPAREN, TK_RPAREN, TK_LBRACE, TK_RBRACE, TK_SEMI, TK_COMMA,
TK_LBRACKET, TK_RBRACKET, TK_COLON,
TK_DOT,
TK_IN,
TK_TRY, TK_CATCH, TK_FINALLY, TK_THROW
};
typedef struct {
int type;
char *text;
double num;
int is_int;
int64_t inum;
int line;
} Token;
typedef struct {
Token *tokens;
int count;
int cap;
} TokenList;
TokenList lex(Arena *a, const char *src, char *err, size_t errsz);
typedef struct Expr Expr;
typedef struct Stmt Stmt;
enum {
EXPR_NUM, EXPR_STR, EXPR_BOOL, EXPR_NIL,
EXPR_VAR, EXPR_UNARY, EXPR_BINARY, EXPR_CALL, EXPR_ASSIGN, EXPR_MEMBER,
EXPR_INDEX, EXPR_INDEX_ASSIGN, EXPR_ARRAY, EXPR_LAMBDA
};
enum {
STMT_LET, STMT_ASSIGN, STMT_IF, STMT_WHILE, STMT_FOR, STMT_FOR_IN,
STMT_RETURN, STMT_BREAK, STMT_CONTINUE,
STMT_BLOCK, STMT_FUNC, STMT_EXPR,
STMT_TRY, STMT_THROW
};
struct Expr {
int kind;
int line;
union {
struct { int is_int; int64_t ival; double fval; } numlit;
char *str;
int boolean;
char *name;
struct { int op; Expr *inner; } unary;
struct { int op; Expr *left; Expr *right; } binary;
struct { Expr *callee; Expr **args; int argc; } call;
struct { char *name; Expr *value; } assign;
struct { Expr *obj; char *name; } member;
struct { Expr *obj; Expr *index; } idx;
struct { Expr *target; Expr *value; } index_assign;
struct { Expr **keys; Expr **vals; int *haskey; int count; } array;
Stmt *lambda;
} u;
};
struct Stmt {
int kind;
int line;
union {
struct { char *name; Expr *init; } let;
struct { char *name; Expr *value; } assign;
struct { Expr *cond; Stmt *then_b; Stmt *else_b; } ifs;
struct { Expr *cond; Stmt *body; } whiles;
struct { Stmt *init; Expr *cond; Expr *step; Stmt *body; } fors;
struct { char *iter_var; Expr *iterable; Stmt *body; } for_in;
struct { Expr *value; } returns;
struct { Stmt **stmts; int count; } block;
struct { char *name; char **params; int pcount; char **freevars; int freecount; Stmt *body; } func;
struct { Stmt *body; char *catchvar; Stmt *catchbody; Stmt *finallybody; } trys;
struct { Expr *value; } throws;
Expr *expr;
} u;
};
Expr *expr_num(Arena *a, int is_int, int64_t ival, double fval, int line);
Expr *expr_str(Arena *a, char *s, int line);
Expr *expr_bool(Arena *a, int b, int line);
Expr *expr_nil(Arena *a, int line);
Expr *expr_var(Arena *a, char *name, int line);
Expr *expr_unary(Arena *a, int op, Expr *inner, int line);
Expr *expr_binary(Arena *a, int op, Expr *l, Expr *r, int line);
Expr *expr_call(Arena *a, Expr *callee, Expr **args, int argc, int line);
Expr *expr_member(Arena *a, Expr *obj, char *name, int line);
Expr *expr_assign(Arena *a, char *name, Expr *value, int line);
Expr *expr_index(Arena *a, Expr *obj, Expr *index, int line);
Expr *expr_index_assign(Arena *a, Expr *target, Expr *value, int line);
Expr *expr_array(Arena *a, Expr **keys, Expr **vals, int *haskey, int count, int line);
Expr *expr_lambda(Arena *a, Stmt *funcDef, int line);
Stmt *stmt_let(Arena *a, char *name, Expr *init, int line);
Stmt *stmt_assign(Arena *a, char *name, Expr *value, int line);
Stmt *stmt_if(Arena *a, Expr *cond, Stmt *thenb, Stmt *elseb, int line);
Stmt *stmt_while(Arena *a, Expr *cond, Stmt *body, int line);
Stmt *stmt_for(Arena *a, Stmt *init, Expr *cond, Expr *step, Stmt *body, int line);
Stmt *stmt_for_in(Arena *a, char *var, Expr *iterable, Stmt *body, int line);
Stmt *stmt_break(Arena *a, int line);
Stmt *stmt_continue(Arena *a, int line);
Stmt *stmt_return(Arena *a, Expr *value, int line);
Stmt *stmt_block(Arena *a, Stmt **stmts, int count, int line);
Stmt *stmt_func(Arena *a, char *name, char **params, int pcount, Stmt *body, int line);
Stmt *stmt_expr(Arena *a, Expr *e, int line);
Stmt *stmt_try(Arena *a, Stmt *body, char *catchvar, Stmt *catchbody, Stmt *finallybody, int line);
Stmt *stmt_throw(Arena *a, Expr *value, int line);
typedef struct {
Stmt **stmts;
int count;
int cap;
char err[256];
int has_error;
} Program;
Program parse(Arena *a, TokenList *tl);
Program cvm_compile(Runtime *rt, const char *source, const char *name);
void cvm_collect_freevars(Arena *a, Program *p);
void cvm_exec_program(Runtime *rt, Program *p, Env *env);
Map *load_module(Runtime *rt, const char *spec);
typedef Value (*BuiltinFunc)(Runtime *rt, int argc, Value *args);
typedef struct {
void *lib;
char path[256];
} FFILib;
struct Runtime {
Arena arena;
Env *global;
Map funcs;
Map builtins;
Map modules;
FFILib ffi_libs[16];
int ffi_count;
Map ffi_syms;
int ffi_enabled;
Map ffi_sigs;
Map ffi_allow;
Map ffi_allow_sym;
int return_flag;
Value return_value;
int break_flag;
int continue_flag;
int call_depth;
char errbuf[512];
int has_error;
int has_throw;
Value thrown;
char current_file[512];
char loading_paths[CVM_MAX_LOAD_DEPTH][CVM_MAX_LOAD_PATH];
int loading_n;
int timer_count;
int64_t timer_epoch;
struct {
char name[256];
int64_t deadline_ms;
int repeat_ms;
int active;
} timers[64];
};
typedef enum {
OP_PUSH_CONST, OP_PUSH_NIL, OP_PUSH_TRUE, OP_PUSH_FALSE,
OP_PUSH_INT,
OP_LOAD, OP_STORE, OP_DEFINE, OP_DUP,
OP_POP,
OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD,
OP_NEG, OP_NOT,
OP_EQ, OP_NE, OP_LT, OP_GT, OP_LE, OP_GE,
OP_JMP, OP_JMP_FALSE, OP_JMP_TRUE,
OP_CALL, OP_RET,
OP_INDEX, OP_ARRAY_NEW, OP_ARRAY_PUSH, OP_ARRAY_KV,
OP_HALT
} OpCode;
typedef struct ByteFunc {
int32_t *code;
int clen;
Value *consts;
int nconsts;
char **names;
int nnames;
int nlocals;
int nargs;
int max_args;
int unsupported;
char *name;
} ByteFunc;
Runtime *rt_new(void);
void rt_free(Runtime *rt);
void rt_register_builtin(Runtime *rt, const char *name, BuiltinFunc f);
void host_register_all(Runtime *rt);
int rt_run(Runtime *rt, const char *source, const char *name);
int rt_run_file(Runtime *rt, const char *path);
ByteFunc *cvm_bc_compile_all(Runtime *rt, Program *program, int *out_count);
int cvm_bc_run(Runtime *rt, ByteFunc *main_bf, ByteFunc *bfs, int nbfs);
void cvm_bc_free(ByteFunc *bfs, int count);
int cvm_bc_supported(Program *program);
int64_t rt_now_ms(Runtime *rt);
int rt_timer_add(Runtime *rt, const char *func_name, int delay_ms, int repeat_ms);
int rt_process_timers(Runtime *rt);
int ffi_load(Runtime *rt, const char *path);
void *ffi_resolve(Runtime *rt, const char *name);
void *ffi_resolve_allowed(Runtime *rt, const char *name);
int rt_load_ffi_allowfile(Runtime *rt, const char *filename);
void ffi_close(void *lib);
typedef struct Closure {
Stmt *fn;
Env *capenv;
} Closure;
#define PROTO_MAX_STATES 64
#define PROTO_MAX_EVENTS 256
#define PROTO_MAX_ACTIONS 256
#define PROTO_NAME_LEN 64
#define PROTO_LABEL_LEN 64
#define PROTO_EVENT_LEN 64
#define PROTO_ACTION_LEN 128
typedef struct {
int id;
char label[PROTO_LABEL_LEN];
int level;
} PState;
typedef struct {
int from;
char event[PROTO_EVENT_LEN];
int to;
char action[PROTO_ACTION_LEN];
} PTransition;
typedef struct ProtoState {
char name[PROTO_NAME_LEN];
PState states[PROTO_MAX_STATES];
int nstates;
PTransition trans[PROTO_MAX_EVENTS];
int ntrans;
int current;
int64_t enter_time_ms;
int running;
} ProtoState;
ProtoState *proto_new(const char *name);
int proto_state_add(ProtoState *ps, int id, const char *label, int level);
int proto_transition_add(ProtoState *ps, int from, const char *event, int to, const char *action);
int proto_event(ProtoState *ps, const char *event);
const char *proto_current_label(ProtoState *ps);
int proto_current_id(ProtoState *ps);
int proto_current_level(ProtoState *ps);
const char *proto_level_name(int level);
#endif