docs/examples/log-watcher (1285 lines, 7 files) now compiles clean: 0 diagnostics, a 35KB .wob written. corpus 71/0, woc runtest 565/0, every wovm unit gate green (both dispatch flavors). - .wob v2: each class row gains three u32 per-field arrays — the field's NAME constant, the CLASS it refers to (or the json-raw marker), and a container field's ELEMENT kinds. json is then a runtime service driven by metadata instead of per-type generated code. loader/emitter/disassembler/test assembler all read and write v2; field-name constants are interned with the rest of the pool (interning during serialization silently loses them) - runtime/src/json.c (new): encode by static kind + object headers + class table (nested records need no static knowledge); decode parses and BINDS straight into the target class — keys matched to field names, nested objects built as the field's class, arrays as a multi of the field's element kind, unknown keys skipped, absent keys nil. Malformed input is nil, never a trap - `as`: `json.decode(text) as T` is the one cast this language has (WO-E403 for any other `as`, and for a bare json.decode with no target type). Its result is `?T`, which is why the decode and the target are one instruction - json.Value: a reserved type name for a value the source does not inspect — the raw JSON slice, kind TEXT, re-emitted verbatim by encode - docs: 00-wob-format.md is now the v2 reference (class metadata, TRY/ENDTRY, the whole builtin surface, WO_T_IO); 08-builtin-surface.md documents the text/container builtins, the OS modules with their predeclared records, and json's two documented limits (Bool encodes 0/1, floats truncate) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
73 lines
2.5 KiB
C
73 lines
2.5 KiB
C
/* loader.h — .wob loading + the full static-validation contract.
|
|
* The "no UB on any input" constraint lives here: everything is parsed
|
|
* through a bounds-checked cursor and COPIED OUT into aligned, malloc'd
|
|
* structures (misaligned files and input-buffer lifetimes are non-issues);
|
|
* text constants intern as const-flagged strings. What the loader accepts,
|
|
* the interpreter trusts forever — the validation list is in loader.c.
|
|
* Field indexes on GETF/SETF stay runtime checks (registers are untyped):
|
|
* the spec's residual-check doctrine. */
|
|
#ifndef WO_LOADER_H
|
|
#define WO_LOADER_H
|
|
|
|
#include "obj.h"
|
|
|
|
typedef struct wo_lineent {
|
|
uint32_t pc, line;
|
|
} wo_lineent;
|
|
|
|
typedef struct wo_dropent {
|
|
uint32_t pc;
|
|
uint64_t owned; /* register bitmask: live owned values at pc */
|
|
uint64_t gc; /* register bitmask: live @gc references at pc */
|
|
} wo_dropent;
|
|
|
|
typedef struct wo_methodrec {
|
|
uint32_t name; /* constant index of a text constant */
|
|
uint32_t class_id; /* WOB_NONE = free fn */
|
|
uint8_t arg_cnt, reg_cnt;
|
|
uint32_t *code; /* aligned owned copy */
|
|
uint32_t ninstr;
|
|
wo_lineent *lines;
|
|
uint32_t line_cnt;
|
|
wo_dropent *drops;
|
|
uint32_t drop_cnt;
|
|
} wo_methodrec;
|
|
|
|
typedef struct wo_const {
|
|
uint8_t tag; /* WOB_K_INT / WOB_K_TEXT */
|
|
int64_t i; /* tag INT */
|
|
wo_str *s; /* tag TEXT: interned, WO_F_CONST, module-owned */
|
|
} wo_const;
|
|
|
|
/* vtable rows expanded flat and sorted by (class_id, slot) for binary
|
|
* search at ICALL time */
|
|
typedef struct wo_vtabent {
|
|
uint32_t class_id, slot, method;
|
|
} wo_vtabent;
|
|
|
|
typedef struct wo_module {
|
|
wo_const *consts;
|
|
uint32_t const_cnt;
|
|
wo_classdesc *classes;
|
|
uint32_t class_cnt;
|
|
uint8_t *kindpool; /* pooled field-kind bytes the classes point into */
|
|
/* pooled per-field metadata (v2): names, referenced class ids, element
|
|
kinds — see wob.h's "class-table field metadata" note */
|
|
uint32_t *metapool;
|
|
uint32_t slot_cnt; /* total interface slots across all interfaces */
|
|
wo_vtabent *vtabs;
|
|
uint32_t vtab_cnt;
|
|
wo_methodrec *methods;
|
|
uint32_t method_cnt;
|
|
uint32_t entry; /* WOB_NONE = none */
|
|
} wo_module;
|
|
|
|
/* 0 ok; -1 reject with a human-readable reason in err (never empty) and
|
|
* everything parsed so far freed. */
|
|
int wo_load_buf(wo_module *m, const uint8_t *buf, size_t len, char *err,
|
|
size_t errlen);
|
|
/* mmap -> parse -> munmap */
|
|
int wo_load_file(wo_module *m, const char *path, char *err, size_t errlen);
|
|
void wo_module_free(wo_module *m);
|
|
|
|
#endif /* WO_LOADER_H */
|