microlisp 0.1.0
A small Scheme-subset interpreter in modern C.
Loading...
Searching...
No Matches
microlisp_internal.h
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) 2026 microlisp contributors
4 *
5 * Internal definitions shared across the library's .c files. Not installed,
6 * not part of the public ABI. Identifiers in here use the short `ml_` prefix
7 * because they are file-local to the library and never reach the public
8 * header; the public surface keeps the `microlisp_` prefix unchanged.
9 */
10#ifndef MICROLISP_INTERNAL_H_INCLUDED
11#define MICROLISP_INTERNAL_H_INCLUDED
12
13#include "microlisp/microlisp.h"
14
15#include <stdarg.h>
16#include <stddef.h>
17#include <stdint.h>
18
19/* --------------------------------------------------------------------------
20 * Value representation: tagged pointer in a uintptr_t.
21 *
22 * Low 3 bits of every value encode the type. Heap-object pointers are
23 * 8-byte aligned (the allocator guarantees this with an aligned_alloc
24 * fallback), so they naturally carry tag 0. Fixnums, symbol indices,
25 * and immediate constants pack their payload in the high 61 bits.
26 *
27 * Layout:
28 *
29 * ........ ........ ........ ........ tag (3 bits) meaning
30 * -- 61-bit payload ----------------- 000 heap object *
31 * -- 60-bit signed fixnum ----------- 001 fixnum
32 * -- 60-bit immediate-id ------------ 010 immediate const
33 * -- 60-bit symbol index ------------ 011 interned symbol
34 *
35 * Tags 100-111 are reserved.
36 *
37 * A 64-bit target is required: 32-bit uintptr_t would compress the
38 * fixnum range to 28 bits, which is too small for useful arithmetic.
39 * -------------------------------------------------------------------------- */
40
41_Static_assert(sizeof(uintptr_t) >= 8, "microlisp requires a 64-bit target");
42
43typedef uintptr_t mvalue;
44
45#define M_TAG_MASK ((mvalue)0x7U)
46#define M_TAG_OBJ ((mvalue)0x0U)
47#define M_TAG_FIX ((mvalue)0x1U)
48#define M_TAG_IMM ((mvalue)0x2U)
49#define M_TAG_SYM ((mvalue)0x3U)
50
51/* v14 wants ((v)&M_TAG_MASK), v18+ wants ((v) & M_TAG_MASK); we go with v18+. */
52/* clang-format off */
53#define M_TAG_OF(v) ((v) & M_TAG_MASK)
54/* clang-format on */
55#define M_PAYLOAD(v) ((v) >> 3)
56
57/* -- Immediates: identified by their id in the high bits. ------------------ */
58#define M_IMM_ID_NIL 0U
59#define M_IMM_ID_TRUE 1U
60#define M_IMM_ID_FALSE 2U
61#define M_IMM_ID_EOF 3U
62#define M_IMM_ID_UNDEF 4U /* "no result" / unbound sentinel inside eval */
63
64#define M_MAKE_IMM(id) ((mvalue)(((mvalue)(id) << 3) | M_TAG_IMM))
65#define MV_NIL M_MAKE_IMM(M_IMM_ID_NIL)
66#define MV_TRUE M_MAKE_IMM(M_IMM_ID_TRUE)
67#define MV_FALSE M_MAKE_IMM(M_IMM_ID_FALSE)
68#define MV_EOF M_MAKE_IMM(M_IMM_ID_EOF)
69#define MV_UNDEF M_MAKE_IMM(M_IMM_ID_UNDEF)
70
71/* -- Fixnum range. 60 bits signed: [-(2^59), 2^59 - 1]. -------------------- */
72#define M_FIX_MIN ((int64_t) - ((int64_t)1 << 59))
73#define M_FIX_MAX ((int64_t)(((int64_t)1 << 59) - 1))
74
75/* Encode a signed 60-bit integer (caller must check range). */
76static inline mvalue ml_make_fix(int64_t x) {
77 /* Arithmetic shift in C is implementation-defined for negatives, so
78 * pack/unpack via a 2's-complement reinterpretation that compiles
79 * to a single shift on every mainstream target. */
80 uint64_t u = (uint64_t)x;
81 return (mvalue)((u << 3) | M_TAG_FIX);
82}
83
84/* Decode a fixnum. Undefined if v isn't tagged as a fixnum. */
85static inline int64_t ml_fix_int(mvalue v) {
86 int64_t s = (int64_t)v;
87 return s >> 3; /* arithmetic shift preserves sign on all real targets */
88}
89
90/* -- Predicates ------------------------------------------------------------ */
91static inline int ml_is_obj(mvalue v) {
92 return M_TAG_OF(v) == M_TAG_OBJ && v != 0;
93}
94static inline int ml_is_fix(mvalue v) {
95 return M_TAG_OF(v) == M_TAG_FIX;
96}
97static inline int ml_is_imm(mvalue v) {
98 return M_TAG_OF(v) == M_TAG_IMM;
99}
100static inline int ml_is_sym(mvalue v) {
101 return M_TAG_OF(v) == M_TAG_SYM;
102}
103static inline int ml_is_nil(mvalue v) {
104 return v == MV_NIL;
105}
106static inline int ml_is_bool(mvalue v) {
107 return v == MV_TRUE || v == MV_FALSE;
108}
109static inline int ml_truthy(mvalue v) {
110 return v != MV_FALSE;
111} /* Scheme: only #f is false */
112
113static inline mvalue ml_make_bool(int b) {
114 return b ? MV_TRUE : MV_FALSE;
115}
116static inline mvalue ml_make_sym(uint32_t idx) {
117 return ((mvalue)idx << 3) | M_TAG_SYM;
118}
119static inline uint32_t ml_sym_index(mvalue v) {
120 return (uint32_t)(v >> 3);
121}
122
123/* --------------------------------------------------------------------------
124 * Heap objects.
125 *
126 * Every heap object starts with `struct mobj` so the GC can chain and
127 * mark them uniformly. Concrete object types embed mobj as their
128 * first member; downcasts go through ml_as_<type>(v).
129 * -------------------------------------------------------------------------- */
130
138
139typedef struct mobj {
141 uint8_t marked;
142 struct mobj *next;
144
150
151typedef struct mstring {
153 size_t len;
154 /* Trailing flex array: `bytes` is allocated as part of this struct. */
155 uint8_t bytes[];
157
166
167struct microlisp_state; /* forward */
168
169typedef microlisp_status (*ml_prim_fn)(struct microlisp_state *state, size_t argc,
170 const mvalue *argv, mvalue *out);
171
172typedef struct mprim {
174 const char *name;
176 uint32_t arity_min;
177 uint32_t arity_max;
179
188
189/* -- Heap-object accessors. Undefined if the tag is wrong. ----------------- */
190static inline mobj *ml_as_obj(mvalue v) {
191 return (mobj *)(uintptr_t)v;
192}
193static inline mpair *ml_as_pair(mvalue v) {
194 return (mpair *)(uintptr_t)v;
195}
196static inline mstring *ml_as_string(mvalue v) {
197 return (mstring *)(uintptr_t)v;
198}
199static inline mclosure *ml_as_closure(mvalue v) {
200 return (mclosure *)(uintptr_t)v;
201}
202static inline mprim *ml_as_prim(mvalue v) {
203 return (mprim *)(uintptr_t)v;
204}
205static inline menv *ml_as_env(mvalue v) {
206 return (menv *)(uintptr_t)v;
207}
208
209static inline int ml_is_obj_type(mvalue v, mobj_type t) {
210 return ml_is_obj(v) && ml_as_obj(v)->type == t;
211}
212static inline int ml_is_pair(mvalue v) {
213 return ml_is_obj_type(v, OBJ_PAIR);
214}
215static inline int ml_is_string(mvalue v) {
216 return ml_is_obj_type(v, OBJ_STRING);
217}
218static inline int ml_is_closure(mvalue v) {
219 return ml_is_obj_type(v, OBJ_CLOSURE);
220}
221static inline int ml_is_prim(mvalue v) {
222 return ml_is_obj_type(v, OBJ_PRIMITIVE);
223}
224static inline int ml_is_env(mvalue v) {
225 return ml_is_obj_type(v, OBJ_ENV);
226}
227static inline int ml_is_procedure(mvalue v) {
228 return ml_is_closure(v) || ml_is_prim(v);
229}
230
231/* --------------------------------------------------------------------------
232 * Symbol table.
233 *
234 * Symbols are interned strings identified by a small integer index.
235 * Lookup by name is O(n) for v0.1 -- a hash table is a clear v0.2 win
236 * but adds bucket-rebalance complexity that isn't worth shipping
237 * before the first review round. The whole table is freed on state
238 * destroy; entries are never removed during a state's lifetime, so
239 * symbol indices are stable and can be compared by identity.
240 * -------------------------------------------------------------------------- */
241
242typedef struct ml_symtab_entry {
243 char *name;
244 size_t len;
246
252
253/* --------------------------------------------------------------------------
254 * Error state.
255 * -------------------------------------------------------------------------- */
256
257typedef struct ml_error {
258 char message[256];
259 size_t line;
260 size_t column;
262
263/* --------------------------------------------------------------------------
264 * The state.
265 * -------------------------------------------------------------------------- */
266
271 /* GC ----------------------------------------------------------------- */
276 /* Protect stack: values that must survive the next collection but
277 * aren't yet wired into a tracked structure. Reader/eval push and
278 * pop entries here whenever they hold a heap-object handle in a
279 * local. */
283
284 /* Stress switch: when nonzero, every allocation triggers a full GC
285 * before returning. Used by the gc-stress test to maximize the
286 * chance of catching missing roots. */
288
289 /* Mark worklist: explicit-stack BFS used by ml_gc_collect to walk
290 * the live graph iteratively. A purely recursive mark would
291 * overflow the C stack on a heap-built linked list with several
292 * thousand cons cells (which fuzz_read produces routinely from
293 * tail-recursive accumulator-style programs). The worklist lives
294 * on the state so allocation overhead amortizes across collections. */
298
299 /* Symbol table ------------------------------------------------------- */
301
302 /* Pre-interned symbols for special forms and frequently used names.
303 * Stored once so reader / eval can compare by integer identity
304 * (mvalue equality) without rehashing. */
318
319 /* Top-level environment ---------------------------------------------- */
321
322 /* Reader options ----------------------------------------------------- */
324
325 /* Eval depth limiter. eval_depth is the live counter; max_eval_depth
326 * is the configured ceiling. ml_eval increments on entry and
327 * decrements on exit. Tail-call optimization means a long tail-
328 * recursive program touches this exactly once per non-tail call,
329 * not per loop iteration. */
332
333 /* Printer depth limiter: same shape as eval-depth. print_value
334 * increments on every recursive pair-car descent and bails with
335 * MICROLISP_ERR_PRINT_DEPTH if the limit is exceeded. v0.2 will
336 * replace the recursive walker with an explicit-stack BFS in
337 * the spirit of the GC mark fix in v0.1.1. */
340
341 /* Structural-equality depth limiter: same shape as the printer's.
342 * ml_value_equal / ml_value_eqv walk pair-car chains recursively;
343 * the cap keeps the host C stack bounded when comparing two
344 * deeply-nested structures (a fuzz / DoS surface). */
347
348 /* Output sink used by the `display`, `write`, and `newline`
349 * primitives. Defaults to stdout; microlisp_repl temporarily
350 * swaps in the caller-supplied out_file so REPL output honors
351 * the API contract that everything goes through that FILE *. */
352 FILE *output;
353
354 /* Last error --------------------------------------------------------- */
356};
357
359
360/* --------------------------------------------------------------------------
361 * Allocator helpers.
362 * -------------------------------------------------------------------------- */
363
364void *ml_raw_alloc(ml_state *s, size_t size);
365void ml_raw_free(ml_state *s, void *p);
366
367/* --------------------------------------------------------------------------
368 * GC.
369 * -------------------------------------------------------------------------- */
370
372microlisp_status ml_gc_alloc_string(ml_state *s, const uint8_t *bytes, size_t len, mvalue *out);
374 mvalue *out);
376 uint32_t arity_min, uint32_t arity_max, mvalue *out);
378
379/* Push @p v onto the protect stack. Returns OK or ERR_NOMEM if grow failed. */
381
382/* Pop the most recent N entries from the protect stack. */
383void ml_gc_unprotect(ml_state *s, size_t n);
384
385/* Inspect / restore the protect stack height. Use for early-return paths. */
386static inline size_t ml_gc_savepoint(const ml_state *s) {
387 return s->gc_protect_count;
388}
389void ml_gc_restore(ml_state *s, size_t saved);
390
391/* Force a full collection now. */
392void ml_gc_collect(ml_state *s);
393
394/* Free every heap object (called by microlisp_state_destroy). */
395void ml_gc_free_all(ml_state *s);
396
397/* --------------------------------------------------------------------------
398 * Symbol table.
399 * -------------------------------------------------------------------------- */
400
401microlisp_status ml_sym_intern(ml_state *s, const char *name, size_t len, mvalue *out);
402const char *ml_sym_name(const ml_state *s, mvalue sym, size_t *out_len);
403
404/* --------------------------------------------------------------------------
405 * Environment.
406 * -------------------------------------------------------------------------- */
407
408/* Define a fresh binding in @p env. If @p name already exists, replace it. */
410
411/* Set an existing binding in @p env or any enclosing env. Returns
412 * ERR_UNBOUND if the name doesn't exist. */
414
415/* Look up @p name in @p env or any enclosing env. Returns ERR_UNBOUND
416 * if not found. */
417microlisp_status ml_env_lookup(const ml_state *s, mvalue env, mvalue name, mvalue *out);
418
419/* --------------------------------------------------------------------------
420 * Reader / printer / evaluator (declarations here; impl across files).
421 * -------------------------------------------------------------------------- */
422
423typedef struct ml_reader {
424 const uint8_t *input;
425 size_t len;
426 size_t pos;
427 size_t line;
428 size_t column;
429 size_t depth;
431
432/* Read the next top-level form. Sets @p *out to MV_EOF when input is
433 * exhausted (with status OK). */
435
436/* Printer. write_style=1 prints in read-back form (strings quoted,
437 * escapes escaped); write_style=0 is display form. */
438typedef microlisp_status (*ml_out_fn)(const void *bytes, size_t len, void *user);
439microlisp_status ml_print(ml_state *s, mvalue v, int write_style, ml_out_fn out, void *user);
440
441/* Convenience: print to a freshly allocated NUL-terminated buffer. */
442microlisp_status ml_print_to_alloc(ml_state *s, mvalue v, int write_style, char **out_bytes,
443 size_t *out_len);
444
445/* Evaluator entry point. */
447
448/* Install the built-in primitives into @p env (typically the top-level). */
450
451/* --------------------------------------------------------------------------
452 * Value equality (value.c).
453 * -------------------------------------------------------------------------- */
454
455int ml_value_eq(mvalue a, mvalue b);
456int ml_value_eqv(mvalue a, mvalue b);
457/* Structural equality with bounded recursion depth. Walks pairs
458 * recursively; bails with MICROLISP_ERR_EQUAL_DEPTH if depth exceeds
459 * ml_state::max_equal_depth. Returns the equality result through
460 * @p out_equal on success. */
461microlisp_status ml_value_equal(ml_state *s, mvalue a, mvalue b, int *out_equal);
462
463/* --------------------------------------------------------------------------
464 * Error helpers.
465 * -------------------------------------------------------------------------- */
466
467/* Set @p s->last_error. The position is reported as 0,0 when not known. */
468void ml_set_error(ml_state *s, size_t line, size_t column, const char *fmt, ...)
469 MICROLISP_PRINTF(4, 5);
470
471/* Clear the last error (called at the top of microlisp_eval). */
472void ml_clear_error(ml_state *s);
473
474#endif /* MICROLISP_INTERNAL_H_INCLUDED */
#define MICROLISP_PRINTF(fmt_idx, vararg_idx)
Definition export.h:60
microlisp_status
Error and status codes returned by every fallible API entry point.
Definition microlisp.h:71
static int ml_is_procedure(mvalue v)
Definition microlisp_internal.h:227
static uint32_t ml_sym_index(mvalue v)
Definition microlisp_internal.h:119
microlisp_status ml_gc_alloc_string(ml_state *s, const uint8_t *bytes, size_t len, mvalue *out)
Definition gc.c:92
#define M_TAG_OF(v)
Definition microlisp_internal.h:53
microlisp_status ml_env_define(ml_state *s, mvalue env, mvalue name, mvalue value)
Definition env.c:54
#define MV_TRUE
Definition microlisp_internal.h:66
const char * ml_sym_name(const ml_state *s, mvalue sym, size_t *out_len)
Definition symtab.c:95
static int ml_is_obj_type(mvalue v, mobj_type t)
Definition microlisp_internal.h:209
static int ml_is_pair(mvalue v)
Definition microlisp_internal.h:212
static mpair * ml_as_pair(mvalue v)
Definition microlisp_internal.h:193
mobj_type
Definition microlisp_internal.h:131
@ OBJ_PRIMITIVE
Definition microlisp_internal.h:135
@ OBJ_PAIR
Definition microlisp_internal.h:132
@ OBJ_STRING
Definition microlisp_internal.h:133
@ OBJ_ENV
Definition microlisp_internal.h:136
@ OBJ_CLOSURE
Definition microlisp_internal.h:134
static int ml_is_obj(mvalue v)
Definition microlisp_internal.h:91
static int ml_is_prim(mvalue v)
Definition microlisp_internal.h:221
static int ml_is_sym(mvalue v)
Definition microlisp_internal.h:100
static int ml_is_fix(mvalue v)
Definition microlisp_internal.h:94
microlisp_status ml_value_equal(ml_state *s, mvalue a, mvalue b, int *out_equal)
Definition value.c:35
void * ml_raw_alloc(ml_state *s, size_t size)
Definition gc.c:34
void ml_gc_restore(ml_state *s, size_t saved)
Definition gc.c:203
static int ml_is_imm(mvalue v)
Definition microlisp_internal.h:97
microlisp_status ml_read(ml_state *s, ml_reader *r, mvalue *out)
Definition reader.c:473
void ml_gc_free_all(ml_state *s)
Definition gc.c:391
static mvalue ml_make_sym(uint32_t idx)
Definition microlisp_internal.h:116
void ml_set_error(ml_state *s, size_t line, size_t column, const char *fmt,...) MICROLISP_PRINTF(4
microlisp_status ml_gc_protect(ml_state *s, mvalue v)
Definition gc.c:174
static int ml_is_closure(mvalue v)
Definition microlisp_internal.h:218
microlisp_status ml_primitives_install(ml_state *s, mvalue env)
Definition primitives.c:533
static int ml_is_bool(mvalue v)
Definition microlisp_internal.h:106
static int ml_is_nil(mvalue v)
Definition microlisp_internal.h:103
#define M_TAG_IMM
Definition microlisp_internal.h:48
microlisp_status ml_sym_intern(ml_state *s, const char *name, size_t len, mvalue *out)
Definition symtab.c:34
void ml_raw_free(ml_state *s, void *p)
Definition gc.c:41
void ml_gc_collect(ml_state *s)
Definition gc.c:352
static size_t ml_gc_savepoint(const ml_state *s)
Definition microlisp_internal.h:386
static mvalue ml_make_bool(int b)
Definition microlisp_internal.h:113
uintptr_t mvalue
Definition microlisp_internal.h:43
static int ml_is_string(mvalue v)
Definition microlisp_internal.h:215
void void ml_clear_error(ml_state *s)
Definition state.c:46
microlisp_status ml_gc_alloc_primitive(ml_state *s, const char *name, ml_prim_fn fn, uint32_t arity_min, uint32_t arity_max, mvalue *out)
Definition gc.c:134
int ml_value_eq(mvalue a, mvalue b)
Definition value.c:19
#define MV_NIL
Definition microlisp_internal.h:65
static int64_t ml_fix_int(mvalue v)
Definition microlisp_internal.h:85
microlisp_status ml_gc_alloc_env(ml_state *s, mvalue parent, mvalue *out)
Definition gc.c:152
static menv * ml_as_env(mvalue v)
Definition microlisp_internal.h:205
microlisp_status(* ml_out_fn)(const void *bytes, size_t len, void *user)
Definition microlisp_internal.h:438
static int ml_truthy(mvalue v)
Definition microlisp_internal.h:109
microlisp_status ml_env_lookup(const ml_state *s, mvalue env, mvalue name, mvalue *out)
Definition env.c:102
int ml_value_eqv(mvalue a, mvalue b)
Definition value.c:23
static mobj * ml_as_obj(mvalue v)
Definition microlisp_internal.h:190
static mstring * ml_as_string(mvalue v)
Definition microlisp_internal.h:196
static mclosure * ml_as_closure(mvalue v)
Definition microlisp_internal.h:199
microlisp_status ml_eval(ml_state *s, mvalue form, mvalue env, mvalue *out)
Definition eval.c:670
void ml_gc_unprotect(ml_state *s, size_t n)
Definition gc.c:196
microlisp_status ml_print_to_alloc(ml_state *s, mvalue v, int write_style, char **out_bytes, size_t *out_len)
Definition printer.c:287
microlisp_status ml_env_set(ml_state *s, mvalue env, mvalue name, mvalue value)
Definition env.c:83
#define MV_FALSE
Definition microlisp_internal.h:67
static mvalue ml_make_fix(int64_t x)
Definition microlisp_internal.h:76
#define M_TAG_OBJ
Definition microlisp_internal.h:46
microlisp_status ml_gc_alloc_closure(ml_state *s, mvalue env, mvalue params, mvalue body, mvalue *out)
Definition gc.c:115
#define M_TAG_SYM
Definition microlisp_internal.h:49
microlisp_status ml_gc_alloc_pair(ml_state *s, mvalue car, mvalue cdr, mvalue *out)
Definition gc.c:77
static mprim * ml_as_prim(mvalue v)
Definition microlisp_internal.h:202
static int ml_is_env(mvalue v)
Definition microlisp_internal.h:224
#define M_TAG_FIX
Definition microlisp_internal.h:47
microlisp_status(* ml_prim_fn)(struct microlisp_state *state, size_t argc, const mvalue *argv, mvalue *out)
Definition microlisp_internal.h:169
microlisp_status ml_print(ml_state *s, mvalue v, int write_style, ml_out_fn out, void *user)
Definition printer.c:241
Definition microlisp_internal.h:158
mvalue body
Non-empty list of body forms.
Definition microlisp_internal.h:162
mobj h
Definition microlisp_internal.h:159
mvalue params
Proper or improper list of parameter symbols.
Definition microlisp_internal.h:161
mvalue env
Environment captured at lambda creation.
Definition microlisp_internal.h:160
int variadic
1 if params ends in a dotted rest-arg.
Definition microlisp_internal.h:163
uint32_t arity_min
Required positional params.
Definition microlisp_internal.h:164
Definition microlisp_internal.h:180
mvalue parent
Enclosing env, or MV_NIL for the top-level.
Definition microlisp_internal.h:182
mvalue * values
Parallel array of bound values.
Definition microlisp_internal.h:186
size_t capacity
Definition microlisp_internal.h:184
size_t count
Definition microlisp_internal.h:183
mvalue * names
Allocated array of symbol values (M_TAG_SYM).
Definition microlisp_internal.h:185
mobj h
Definition microlisp_internal.h:181
Caller-supplied allocator.
Definition microlisp.h:163
Definition microlisp_internal.h:267
FILE * output
Definition microlisp_internal.h:352
size_t print_depth
Definition microlisp_internal.h:339
int allocator_provided
1 if user provided one; 0 means malloc.
Definition microlisp_internal.h:269
size_t max_print_depth
Definition microlisp_internal.h:338
size_t max_eval_depth
Definition microlisp_internal.h:330
mvalue sym_set_bang
Definition microlisp_internal.h:309
mvalue sym_else
Definition microlisp_internal.h:317
size_t gc_protect_cap
Definition microlisp_internal.h:282
size_t max_read_depth
Definition microlisp_internal.h:323
mvalue sym_if
Definition microlisp_internal.h:306
size_t max_equal_depth
Definition microlisp_internal.h:345
mvalue sym_quote
Definition microlisp_internal.h:305
ml_error last_error
Definition microlisp_internal.h:355
mobj ** gc_marklist
Definition microlisp_internal.h:295
size_t gc_marklist_cap
Definition microlisp_internal.h:297
mvalue sym_lambda
Definition microlisp_internal.h:308
mvalue sym_or
Definition microlisp_internal.h:315
mvalue sym_letrec
Definition microlisp_internal.h:312
mvalue sym_begin
Definition microlisp_internal.h:313
size_t gc_threshold
Trigger collection when live > threshold.
Definition microlisp_internal.h:274
mobj * gc_head
Head of "every heap object" list.
Definition microlisp_internal.h:272
int gc_stress
Definition microlisp_internal.h:287
size_t eval_depth
Definition microlisp_internal.h:331
mvalue sym_cond
Definition microlisp_internal.h:316
ml_symtab symtab
Definition microlisp_internal.h:300
size_t gc_protect_count
Definition microlisp_internal.h:281
size_t equal_depth
Definition microlisp_internal.h:346
mvalue sym_define
Definition microlisp_internal.h:307
size_t gc_live_objects
Live object count.
Definition microlisp_internal.h:273
mvalue toplevel_env
Definition microlisp_internal.h:320
mvalue sym_let_star
Definition microlisp_internal.h:311
mvalue * gc_protect
Definition microlisp_internal.h:280
microlisp_allocator allocator
Resolved (never partial).
Definition microlisp_internal.h:268
size_t gc_marklist_count
Definition microlisp_internal.h:296
mvalue sym_let
Definition microlisp_internal.h:310
mvalue sym_and
Definition microlisp_internal.h:314
Definition microlisp_internal.h:257
size_t column
1-based; 0 = "no position."
Definition microlisp_internal.h:260
size_t line
1-based; 0 = "no position."
Definition microlisp_internal.h:259
char message[256]
Definition microlisp_internal.h:258
Definition microlisp_internal.h:423
size_t pos
Definition microlisp_internal.h:426
size_t len
Definition microlisp_internal.h:425
size_t depth
Current paren nesting.
Definition microlisp_internal.h:429
size_t column
Definition microlisp_internal.h:428
size_t line
Definition microlisp_internal.h:427
const uint8_t * input
Definition microlisp_internal.h:424
Definition microlisp_internal.h:242
char * name
NUL-terminated, owned.
Definition microlisp_internal.h:243
size_t len
Definition microlisp_internal.h:244
Definition microlisp_internal.h:247
ml_symtab_entry * entries
Definition microlisp_internal.h:248
size_t capacity
Definition microlisp_internal.h:250
size_t count
Definition microlisp_internal.h:249
Definition microlisp_internal.h:139
mobj_type type
Definition microlisp_internal.h:140
struct mobj * next
Linked-list of all live heap objects.
Definition microlisp_internal.h:142
uint8_t marked
Set during GC mark phase.
Definition microlisp_internal.h:141
Definition microlisp_internal.h:145
mobj h
Definition microlisp_internal.h:146
mvalue cdr
Definition microlisp_internal.h:148
mvalue car
Definition microlisp_internal.h:147
Definition microlisp_internal.h:172
uint32_t arity_min
Minimum required args.
Definition microlisp_internal.h:176
mobj h
Definition microlisp_internal.h:173
const char * name
Static string; not owned.
Definition microlisp_internal.h:174
uint32_t arity_max
UINT32_MAX means "variadic".
Definition microlisp_internal.h:177
ml_prim_fn fn
Definition microlisp_internal.h:175
Definition microlisp_internal.h:151
uint8_t bytes[]
Definition microlisp_internal.h:155
size_t len
Definition microlisp_internal.h:153
mobj h
Definition microlisp_internal.h:152