#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[]);