packages feed

nova-nix-0.2.0.0: cbits/nn_bytecode.h

/*
 * nn_bytecode.h -- Flat bytecode representation for Nix expressions.
 *
 * Compiles the 19-constructor Expr AST into a contiguous instruction
 * array (nn_op_t[]) plus a variable-length data buffer (uint32_t[]).
 * Each Expr node maps to exactly one instruction.  Children are
 * referenced by their index in the instruction array (post-order
 * traversal guarantees children < parent).  Variable-length data
 * (string parts, bindings, formals, capture info, attr paths) is
 * stored in the data buffer, referenced by offset from instructions.
 *
 * Goal: eliminate StablePtr (Expr, Env) in pending thunks.  After
 * compilation, pending thunks hold (bc_idx, nn_env_t*) -- both
 * C-native, zero GHC heap pressure.
 *
 * Lifecycle: nn_bytecode_init() before evaluation, nn_bytecode_destroy()
 * after.  Not thread-safe -- single-threaded evaluation only.
 */

#ifndef NN_BYTECODE_H
#define NN_BYTECODE_H

#include <stdint.h>

/* --- Opcodes (one per Expr constructor) --- */

#define NN_OP_LIT_INT        0
#define NN_OP_LIT_FLOAT      1
#define NN_OP_LIT_BOOL       2
#define NN_OP_LIT_NULL       3
#define NN_OP_LIT_URI        4
#define NN_OP_LIT_PATH       5
#define NN_OP_STR            6
#define NN_OP_IND_STR        7
#define NN_OP_VAR            8
#define NN_OP_WITH_VAR       9
#define NN_OP_RESOLVED_VAR  10
#define NN_OP_ATTRS         11
#define NN_OP_LIST          12
#define NN_OP_SELECT        13
#define NN_OP_HAS_ATTR      14
#define NN_OP_APP           15
#define NN_OP_LAMBDA        16
#define NN_OP_LET           17
#define NN_OP_IF            18
#define NN_OP_WITH          19
#define NN_OP_ASSERT        20
#define NN_OP_UNARY         21
#define NN_OP_BINARY        22
#define NN_OP_SEARCH_PATH   23

/* --- UnaryOp flags (NN_OP_UNARY) --- */

#define NN_UNARY_NOT     0
#define NN_UNARY_NEGATE  1

/* --- BinaryOp flags (NN_OP_BINARY) --- */

#define NN_BINARY_ADD     0
#define NN_BINARY_SUB     1
#define NN_BINARY_MUL     2
#define NN_BINARY_DIV     3
#define NN_BINARY_AND     4
#define NN_BINARY_OR      5
#define NN_BINARY_IMPL    6
#define NN_BINARY_EQ      7
#define NN_BINARY_NEQ     8
#define NN_BINARY_LT      9
#define NN_BINARY_LTE    10
#define NN_BINARY_GT     11
#define NN_BINARY_GTE    12
#define NN_BINARY_CONCAT 13
#define NN_BINARY_UPDATE 14

/* --- Formal type flags (NN_OP_LAMBDA) --- */

#define NN_FORMAL_NAME       0
#define NN_FORMAL_SET        1
#define NN_FORMAL_NAMED_SET  2

/* --- String part tags (data buffer) --- */

#define NN_STRPART_LIT    0
#define NN_STRPART_INTERP 1

/* --- Binding type tags (data buffer) --- */

#define NN_BIND_NAMED    0
#define NN_BIND_INHERIT  1

/* --- CaptureInfo type tags (data buffer) --- */

#define NN_CAPTURE_NONE         0
#define NN_CAPTURE_SLOTS        1
#define NN_CAPTURE_WITH_SCOPES  2

/* --- Attr path element tags (data buffer) --- */

#define NN_ATTRKEY_STATIC  0
#define NN_ATTRKEY_DYNAMIC 1

/* --- Instruction (16 bytes, naturally aligned) --- */

typedef struct nn_op {
    uint8_t  opcode;     /* Which Expr constructor */
    uint8_t  flags;      /* Sub-type: BinaryOp, UnaryOp, formal type, etc. */
    uint16_t short_arg;  /* Small immediate: count, bool flag, etc. */
    uint32_t arg1;       /* Child index, symbol, data offset, lo32, etc. */
    uint32_t arg2;       /* Child index, symbol, hi32, etc. */
    uint32_t arg3;       /* Child index, data offset, etc. */
} nn_op_t;

/* --- Lifecycle --- */

/* Initialize the global bytecode store.  op_capacity is initial
 * instruction slots (0 = default 65536).  data_capacity is initial
 * data buffer slots (0 = default 131072).  Both grow automatically. */
void nn_bytecode_init(uint32_t op_capacity, uint32_t data_capacity);

/* Destroy the global bytecode store, freeing all memory. */
void nn_bytecode_destroy(void);

/* --- Emit --- */

/* Append one instruction.  Returns the instruction index. */
uint32_t nn_bc_emit(uint8_t opcode, uint8_t flags, uint16_t short_arg,
                    uint32_t arg1, uint32_t arg2, uint32_t arg3);

/* Append one uint32 to the data buffer.  Returns the data offset. */
uint32_t nn_bc_emit_data(uint32_t value);

/* --- Read instructions --- */

uint8_t  nn_bc_opcode(uint32_t idx);
uint8_t  nn_bc_flags(uint32_t idx);
uint16_t nn_bc_short_arg(uint32_t idx);
uint32_t nn_bc_arg1(uint32_t idx);
uint32_t nn_bc_arg2(uint32_t idx);
uint32_t nn_bc_arg3(uint32_t idx);

/* --- Read data --- */

uint32_t nn_bc_data(uint32_t offset);

/* --- Diagnostics --- */

uint32_t nn_bc_op_count(void);
uint32_t nn_bc_data_count(void);

#endif /* NN_BYTECODE_H */