#pragma once
#include <stdint.h>
#include <stdio.h>
#define TAG_MASK 0xf
#define TAG_IMMED 0x1
#define TAG_STRING 0x3
#define TAG_CLOSURE 0x5
#define TAG_MODULE 0x7
#define TAG_LABELED 0x9
#define TAG_REF 0xb
#define TAG_FILE 0xd
#define SECOND_TAG_LABELED 0x10
#define SECOND_TAG_BOOLEAN 0x20
struct value {
uint32_t bits;
};
struct heap {
uint32_t size;
struct value *values;
uint32_t top;
};
struct closure {
uint8_t num_params;
uint16_t env_size;
int32_t code_offset;
struct value free_values[];
};
struct string {
uint32_t size;
uint8_t bytes[];
};
struct labeled_value {
uint16_t label;
struct value value;
};
struct module {
uint16_t size;
uint16_t index_begin;
struct value entries[];
};
struct ref {
struct value x;
};
struct file {
FILE *stream;
};
extern uint16_t module_indices[];
#define var(i) stack[fp+3+(i)]
#define value(x) (struct value){(uint32_t)(x)}
#define push_var(x) stack[sp++] = (x)
#define pop_vars(n) sp -= (n)
#define push_frame(label) \
do { \
push_var(c); \
push_var(value(fp)); \
push_var(value(&&label - &&entry_0)); \
} while (0)
#define alloc_prim(heap, num_params, label) \
alloc_closure((heap), (num_params), 0, &&label - &&entry_0)
#define empty_tuple value(0 | TAG_IMMED)
#define true_value value(0x100 | SECOND_TAG_BOOLEAN | TAG_IMMED)
#define false_value value(0x200 | SECOND_TAG_BOOLEAN | TAG_IMMED)
_Noreturn void
halt(void);
_Noreturn void
die(const char *s);
_Bool
has_tag(struct value x, uint32_t tag);
void *
address(struct heap *heap, struct value x);
struct value
reference_value(uint32_t offset, uint32_t tag);
struct value
labeled_empty_tuple(uint16_t label);
struct value
alloc_tuple(struct heap *heap, struct value *values, uint16_t size);
struct value
alloc_labeled_value(struct heap *heap, uint16_t label, struct value value);
uint16_t
value_label(struct heap *heap, struct value x);
void
open_labeled_value(struct heap *heap, struct value *frame, struct value x,
int n);
struct value
remove_label(struct heap *heap, struct value x);
void
open_tuple(struct heap *heap, struct value *frame, struct value x, int n);
struct value
alloc_closure(struct heap *heap, int8_t num_params,
uint32_t env_size, int32_t code_offset);
void
closure_store(struct heap *heap, struct value x, uint32_t i,
struct value value);
struct value
alloc_string(struct heap *heap, const char *s);
struct value
number(int32_t n);
int32_t
value_unbox_int32(struct value x);
struct value
prim_die(struct heap *heap, struct value s);
struct value
prim_print_line(struct heap *heap, struct value s);
struct value
prim_string_length(struct heap *heap, struct value s);
struct value
prim_string_fetch(struct heap *heap, struct value s, struct value i);
struct value
prim_string_equal(struct heap *heap, struct value s1, struct value s2);
struct value
prim_string_compare(struct heap *heap, struct value s1, struct value s2);
struct value
prim_string_append(struct heap *heap, struct value s1, struct value s2);
struct value
prim_string_clip(struct heap *heap, struct value s, struct value begin,
struct value end);
struct value
prim_file_create(struct heap *heap, struct value name);
struct value
prim_file_open(struct heap *heap, struct value name);
struct value
prim_file_close(struct heap *heap, struct value file);
struct value
prim_file_read_all(struct heap *heap, struct value file);
struct value
prim_file_write(struct heap *heap, struct value file, struct value str);
struct value
prim_show_integer(struct heap *heap, struct value n);
struct value
prim_bits(struct heap *heap, struct value x);
struct value
prim_multiply(struct heap *heap, struct value a, struct value b);
struct value
prim_add(struct heap *heap, struct value a, struct value b);
struct value
prim_negate(struct heap *heap, struct value n);
struct value
prim_equal(struct heap *heap, struct value a, struct value b);
struct value
prim_less(struct heap *heap, struct value a, struct value b);
struct value
prim_less_or_equal(struct heap *heap, struct value a, struct value b);
struct value
prim_greater(struct heap *heap, struct value a, struct value b);
struct value
prim_greater_or_equal(struct heap *heap, struct value a, struct value b);
struct value
prim_ref_new(struct heap *heap, struct value x);
struct value
prim_ref_store(struct heap *heap, struct value ref, struct value x);
struct value
prim_ref_fetch(struct heap *heap, struct value ref);
struct value
alloc_module(struct heap *heap, struct value *values, uint16_t size,
uint16_t index_begin);
void
module_store(struct heap *heap, struct value x, uint16_t i,
struct value value);
struct value
tuple_fetch(struct heap *heap, struct value x, uint16_t i);
struct value
module_fetch(struct heap *heap, struct value x, uint16_t label);
void *
run_machine(int argc, const char *argv[]);