2#ifndef REDUCT_COMPILE_H
3#define REDUCT_COMPILE_H 1
27typedef struct reduct_expr
41typedef struct reduct_local
51typedef struct reduct_compiler
98#define REDUCT_REG_SET_ALLOCATED(_compiler, _reg) \
101 (_compiler)->regAlloc[(_reg) / 64] |= (1ULL << ((_reg) % 64)); \
102 if ((_reg) + 1 > (_compiler)->function->registerCount) \
104 (_compiler)->function->registerCount = (_reg) + 1; \
114#define REDUCT_REG_CLEAR_ALLOCATED(_compiler, _reg) ((_compiler)->regAlloc[(_reg) / 64] &= ~(1ULL << ((_reg) % 64)))
122#define REDUCT_REG_IS_ALLOCATED(_compiler, _reg) (((_compiler)->regAlloc[(_reg) / 64] & (1ULL << ((_reg) % 64))) != 0)
130#define REDUCT_REG_SET_LOCAL(_compiler, _reg) ((_compiler)->regLocal[(_reg) / 64] |= (1ULL << ((_reg) % 64)))
138#define REDUCT_REG_CLEAR_LOCAL(_compiler, _reg) ((_compiler)->regLocal[(_reg) / 64] &= ~(1ULL << ((_reg) % 64)))
146#define REDUCT_REG_IS_LOCAL(_compiler, _reg) (((_compiler)->regLocal[(_reg) / 64] & (1ULL << ((_reg) % 64))) != 0)
185#define REDUCT_EXPR_NONE() ((reduct_expr_t){.mode = REDUCT_MODE_NONE})
192#define REDUCT_EXPR_REG(_reg) ((reduct_expr_t){.mode = REDUCT_MODE_REG, .reg = (_reg)})
199#define REDUCT_EXPR_CONST(_const) ((reduct_expr_t){.mode = REDUCT_MODE_CONST, .constant = (_const)})
207#define REDUCT_EXPR_CONST_ITEM(_compiler, _item) \
208 REDUCT_EXPR_CONST(reduct_function_lookup_constant((_compiler)->reduct, (_compiler)->function, \
209 &(reduct_const_slot_t){.type = REDUCT_CONST_SLOT_ITEM, .item = (_item)}))
217#define REDUCT_EXPR_CONST_ATOM(_compiler, _atom) \
218 REDUCT_EXPR_CONST(reduct_function_lookup_constant((_compiler)->reduct, (_compiler)->function, \
219 &(reduct_const_slot_t){.type = REDUCT_CONST_SLOT_ITEM, \
220 .item = REDUCT_CONTAINER_OF(_atom, reduct_item_t, atom)}))
227#define REDUCT_EXPR_TARGET(_reg) ((reduct_expr_t){.mode = REDUCT_MODE_TARGET, .reg = (_reg)})
234#define REDUCT_EXPR_TRUE(_compiler) \
235 REDUCT_EXPR_CONST(reduct_function_lookup_constant((_compiler)->reduct, (_compiler)->function, \
236 &(reduct_const_slot_t){.type = REDUCT_CONST_SLOT_ITEM, .item = (_compiler)->reduct->trueItem}))
243#define REDUCT_EXPR_FALSE(_compiler) \
244 REDUCT_EXPR_CONST(reduct_function_lookup_constant((_compiler)->reduct, (_compiler)->function, \
245 &(reduct_const_slot_t){.type = REDUCT_CONST_SLOT_ITEM, .item = (_compiler)->reduct->falseItem}))
252#define REDUCT_EXPR_NIL(_compiler) \
253 REDUCT_EXPR_CONST(reduct_function_lookup_constant((_compiler)->reduct, (_compiler)->function, \
254 &(reduct_const_slot_t){.type = REDUCT_CONST_SLOT_ITEM, .item = (_compiler)->reduct->nilItem}))
262#define REDUCT_EXPR_INT(_compiler, _val) \
263 REDUCT_EXPR_CONST_ATOM(_compiler, reduct_atom_lookup_int((_compiler)->reduct, (_val)))
269#define REDUCT_EXPR_GET_TARGET(_expr) (((_expr)->mode == REDUCT_MODE_TARGET) ? (_expr)->reg : REDUCT_REG_INVALID)
277#define REDUCT_EXPR_FLOAT(_compiler, _val) \
278 REDUCT_EXPR_CONST_ATOM(_compiler, reduct_atom_lookup_float((_compiler)->reduct, (_val)))
347#define REDUCT_LOCAL_IS_DEFINED(_local) ((_local)->expr.mode != REDUCT_MODE_NONE)
559 while (curr < retInstPos)
579 curr = curr + 1 + offset;
588 if (valid && currentReg == retReg && curr == retInstPos)
Core definitions and structures.
reduct_bool_t
Boolean type.
reduct_uint64_t reduct_handle_t
Handle type.
#define REDUCT_ASSERT(_cond)
static void reduct_compile_jump_patch(reduct_compiler_t *compiler, reduct_size_t pos)
Patch a previously emitted jump instruction to point to the current instruction.
reduct_const_t constant
Constant index.
REDUCT_API reduct_local_t * reduct_local_add_arg(reduct_compiler_t *compiler, reduct_atom_t *name)
Add a function argument local to the compiler context.
REDUCT_API void reduct_reg_free(reduct_compiler_t *compiler, reduct_reg_t reg)
Free a register.
reduct_mode_t mode
Expression mode.
static void reduct_compile_capture(reduct_compiler_t *compiler, reduct_reg_t closureReg, reduct_uint32_t slot, reduct_expr_t *expr)
Emits a REDUCT_OPCODE_CAPTURE instruction.
#define REDUCT_EXPR_NIL(_compiler)
Create a REDUCT_MODE_CONST mode expression for the nil constant.
static void reduct_expr_done(reduct_compiler_t *compiler, reduct_expr_t *expr)
Free resources associated with an expression descriptor.
REDUCT_API void reduct_expr_build(reduct_compiler_t *compiler, reduct_item_t *item, reduct_expr_t *out)
Compiles a single Reduct item into an expression descriptor.
reduct_uint16_t localCount
The amount of local variables.
REDUCT_API reduct_function_t * reduct_compile(reduct_t *reduct, reduct_handle_t *ast)
Compiles a Reduct AST into a callable bytecode function.
REDUCT_API reduct_local_t * reduct_local_def(reduct_compiler_t *compiler, reduct_atom_t *name)
Define a new local variable.
static void reduct_compile_jump_patch_list(reduct_compiler_t *compiler, reduct_size_t *jumps, reduct_size_t count)
Patch a list of jump instructions to point to the current instruction.
static void reduct_compile_binary(reduct_compiler_t *compiler, reduct_opcode_t opBase, reduct_reg_t target, reduct_reg_t left, reduct_expr_t *right)
Emits a comparison, arithmetic or bitwise instruction.
REDUCT_API void reduct_local_def_done(reduct_compiler_t *compiler, reduct_local_t *local, reduct_expr_t *expr)
Finalize a local variable definition with its value expression.
static reduct_reg_t reduct_reg_get_base(reduct_compiler_t *compiler)
Get the first unallocated register index.
static void reduct_compile_inst(reduct_compiler_t *compiler, reduct_inst_t inst)
Emits an instruction to the current function.
struct reduct_compiler * enclosing
The enclosing compiler context, or REDUCT_NULL.
static void reduct_compile_return(reduct_compiler_t *compiler, reduct_expr_t *expr)
Emits a REDUCT_OPCODE_RET instruction.
REDUCT_API void reduct_reg_free_range(reduct_compiler_t *compiler, reduct_reg_t start, reduct_uint32_t count)
Free a range of registers.
reduct_expr_t expr
The expression representing the local's value.
reduct_reg_t reg
Register index.
static reduct_size_t reduct_compile_jump(reduct_compiler_t *compiler, reduct_opcode_t op, reduct_reg_t a)
Emits a jump instruction without a target offset.
reduct_atom_t * name
The name of the local variable.
reduct_t * reduct
The Reduct structure.
static void reduct_compile_closure(reduct_compiler_t *compiler, reduct_reg_t target, reduct_const_t funcConst)
Emits a REDUCT_OPCODE_CLOSURE instruction.
static void reduct_compile_call(reduct_compiler_t *compiler, reduct_reg_t target, reduct_expr_t *callable, reduct_uint32_t arity)
Emits a REDUCT_OPCODE_CALL instruction, that returns its result in the target register.
static reduct_reg_t reduct_compile_move_or_alloc(reduct_compiler_t *compiler, reduct_expr_t *expr)
Emits a move instruction or allocates a new register if the expression is not already in a register.
REDUCT_API void reduct_local_pop(reduct_compiler_t *compiler, reduct_uint16_t toCount, reduct_expr_t *result)
Pop local variables from the stack, releasing their registers if they are no longer used.
static void reduct_compile_list(reduct_compiler_t *compiler, reduct_reg_t target)
Emits a REDUCT_OPCODE_LIST instruction, that creates a list in the target register.
reduct_uint16_t value
Raw union value.
reduct_function_t * function
The function being compiled.
REDUCT_API void reduct_compiler_init(reduct_compiler_t *compiler, reduct_t *reduct, reduct_function_t *function, reduct_compiler_t *enclosing)
Initialize a compiler context.
REDUCT_API reduct_reg_t reduct_reg_alloc(reduct_compiler_t *compiler)
Allocate a new register.
REDUCT_API void reduct_compiler_deinit(reduct_compiler_t *compiler)
Deinitialize a compiler context.
static void reduct_compile_move(reduct_compiler_t *compiler, reduct_reg_t target, reduct_expr_t *expr)
Emits a REDUCT_OPCODE_MOVE instruction, that moves the value of the source expression to the target r...
reduct_item_t * lastItem
The last item processed by the compiler, used for error reporting.
static void reduct_compile_append(reduct_compiler_t *compiler, reduct_reg_t target, reduct_expr_t *expr)
Emits an REDUCT_OPCODE_APPEND instruction.
#define REDUCT_REG_IS_ALLOCATED(_compiler, _reg)
Check if a register is allocated.
static reduct_reg_t reduct_expr_get_reg(reduct_compiler_t *compiler, reduct_expr_t *out)
Allocate a new register, favoring the output expression's target if provided.
REDUCT_API reduct_reg_t reduct_reg_alloc_range(reduct_compiler_t *compiler, reduct_uint32_t count)
Allocate a range of registers.
#define REDUCT_EXPR_REG(_reg)
Create a REDUCT_MODE_REG mode expression.
REDUCT_API reduct_local_t * reduct_local_lookup(reduct_compiler_t *compiler, reduct_atom_t *name)
Look up a local by name and return its expression.
reduct_uint16_t reduct_const_t
Constant index type.
static void reduct_function_emit(struct reduct *reduct, reduct_function_t *func, reduct_inst_t inst, reduct_uint32_t position)
Emit an instruction to the function.
#define REDUCT_INST_GET_C(_inst)
Get the C operand from an instruction.
#define REDUCT_INST_MAKE_ASBX(_op, _a, _sbx)
Create an instruction with opcode and A operands, and SBx B operand.
reduct_mode_t
Opcode mode enumeration.
#define REDUCT_INST_GET_A(_inst)
Get the A operand from an instruction.
#define REDUCT_INST_SET_SBX(_inst, _sbx)
Set the SBX operand in an instruction.
#define REDUCT_INST_GET_SBX(_inst)
Get the SBX operand from an instruction.
#define REDUCT_INST_MAKE_ABC(_op, _a, _b, _c)
Create an instruction with opcode, A, B, and C operands.
#define REDUCT_INST_GET_OP(_inst)
Get the opcode from an instruction.
reduct_opcode_t
Opcode enumeration.
reduct_uint32_t reduct_inst_t
Instruction type.
#define REDUCT_INST_MASK_OPCODE
Opcode mask.
#define REDUCT_INST_GET_OP_BASE(_inst)
Get the opcode base (without reduct_mode_t) from an instruction. Mask clears the REDUCT_MODE_CONST bi...
reduct_uint16_t reduct_reg_t
Register type.
#define REDUCT_REGISTER_MAX
The max number of registers per function frame.
@ REDUCT_MODE_REG
Register operand mode.
@ REDUCT_MODE_NONE
Invalid mode.
@ REDUCT_MODE_CONST
Constant operand mode.
@ REDUCT_MODE_TARGET
Compilation target hint mode.
@ REDUCT_OPCODE_APPEND
(A, C) Append value in R/K(C) to the back of the list in R(A).
@ REDUCT_OPCODE_MOV
(A, C) Move value in R/K(C) to R(A).
@ REDUCT_OPCODE_RET
(C) Return value in R/K(C).
@ REDUCT_OPCODE_CALL
(A, B, C) Call callable in R/K(C) with B args starting from R(A). Result in R(A).
@ REDUCT_OPCODE_JMP
(sBx) Unconditional jump by relative offset sBx.
@ REDUCT_OPCODE_CLOSURE
(A, C) Wrap the function prototype in K(C) in a closure and store in R(A).
@ REDUCT_OPCODE_LIST
(A) Create a new list and store it in R(A).
@ REDUCT_OPCODE_TAILCALL
(A, B, C) Tail call callable in R/K(C) with B args starting from R(A).
@ REDUCT_OPCODE_CAPTURE
(A, B, C) Capture R/K(C) into constant slot B in closure R(A).
Bytecode instruction format.
Expression descriptor structure.
Compiled function structure.
reduct_inst_t * insts
An array of instructions.
reduct_uint32_t instCount
Number of instructions.
reduct_uint32_t position
The position in the input buffer where the item was parsed.