135 lines
3.3 KiB
C
135 lines
3.3 KiB
C
#ifndef GROWL_H
|
|
#define GROWL_H
|
|
|
|
#include <setjmp.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
typedef uintptr_t Growl;
|
|
|
|
#define GROWL_NIL ((Growl)(0))
|
|
#define GROWL_BOX(x) ((Growl)(x))
|
|
#define GROWL_UNBOX(x) ((GrowlObjectHeader *)(x))
|
|
#define GROWL_IMM(x) ((Growl)(x) & (Growl)1)
|
|
#define GROWL_NUM(x) (((Growl)((intptr_t)(x) << 1)) | (Growl)1)
|
|
#define GROWL_ORD(x) ((intptr_t)(x) >> 1)
|
|
|
|
typedef struct GrowlObjectHeader GrowlObjectHeader;
|
|
typedef struct GrowlString GrowlString;
|
|
typedef struct GrowlList GrowlList;
|
|
typedef struct GrowlTuple GrowlTuple;
|
|
typedef struct GrowlQuotation GrowlQuotation;
|
|
typedef struct GrowlCompose GrowlCompose;
|
|
typedef struct GrowlCurry GrowlCurry;
|
|
typedef struct GrowlGCArena GrowlGCArena;
|
|
typedef struct GrowlFrame GrowlFrame;
|
|
typedef struct GrowlVM GrowlVM;
|
|
|
|
enum {
|
|
GROWL_STRING,
|
|
GROWL_LIST,
|
|
GROWL_TUPLE,
|
|
GROWL_QUOTATION,
|
|
GROWL_COMPOSE,
|
|
GROWL_CURRY,
|
|
};
|
|
|
|
struct GrowlObjectHeader {
|
|
size_t size;
|
|
uint32_t type;
|
|
};
|
|
|
|
struct GrowlString {
|
|
size_t len;
|
|
char data[];
|
|
};
|
|
|
|
Growl growl_make_string(GrowlVM *vm, size_t len);
|
|
Growl growl_wrap_string(GrowlVM *vm, const char *cstr);
|
|
GrowlString *growl_unwrap_string(Growl obj);
|
|
|
|
struct GrowlList {
|
|
Growl head, tail;
|
|
};
|
|
|
|
struct GrowlTuple {
|
|
size_t count;
|
|
Growl data[];
|
|
};
|
|
|
|
GrowlTuple *growl_unwrap_tuple(Growl obj);
|
|
|
|
struct GrowlQuotation {
|
|
size_t count;
|
|
Growl constants;
|
|
uint8_t data[];
|
|
};
|
|
|
|
struct GrowlCompose {
|
|
Growl first, second;
|
|
};
|
|
|
|
struct GrowlCurry {
|
|
Growl value, callable;
|
|
};
|
|
|
|
int growl_callable(Growl obj);
|
|
Growl growl_make_quotation(GrowlVM *vm, const uint8_t *code, size_t code_size,
|
|
const Growl *constants, size_t constants_size);
|
|
GrowlQuotation *growl_unwrap_quotation(Growl obj);
|
|
Growl growl_compose(GrowlVM *vm, Growl first, Growl second);
|
|
GrowlCompose *growl_unwrap_compose(Growl obj);
|
|
Growl growl_curry(GrowlVM *vm, Growl value, Growl callable);
|
|
GrowlCurry *growl_unwrap_curry(Growl obj);
|
|
|
|
struct GrowlGCArena {
|
|
uint8_t *start, *end;
|
|
uint8_t *free;
|
|
};
|
|
|
|
void growl_arena_init(GrowlGCArena *arena, size_t size);
|
|
void growl_arena_free(GrowlGCArena *arena);
|
|
void *growl_arena_alloc(GrowlGCArena *arena, size_t size, size_t align,
|
|
size_t count);
|
|
#define growl_arena_new(a, t, n) \
|
|
(t *)growl_arena_alloc(a, sizeof(t), _Alignof(t), n)
|
|
|
|
#define GROWL_STACK_SIZE 128
|
|
#define GROWL_CALL_STACK_SIZE 64
|
|
#define GROWL_HEAP_SIZE (4 * 1024 * 1024)
|
|
#define GROWL_ARENA_SIZE (2 * 1024 * 1024)
|
|
#define GROWL_SCRATCH_SIZE (1024 * 1024)
|
|
|
|
struct GrowlFrame {
|
|
GrowlQuotation *quot;
|
|
uint8_t *ip;
|
|
};
|
|
|
|
struct GrowlVM {
|
|
GrowlGCArena from, to;
|
|
GrowlGCArena arena;
|
|
GrowlGCArena scratch;
|
|
|
|
GrowlQuotation *quotation;
|
|
uint8_t *ip;
|
|
Growl wst[GROWL_STACK_SIZE], *sp;
|
|
Growl rst[GROWL_STACK_SIZE], *rsp;
|
|
GrowlFrame cst[GROWL_CALL_STACK_SIZE], *csp;
|
|
|
|
Growl **roots;
|
|
size_t root_count, root_capacity;
|
|
|
|
jmp_buf error;
|
|
};
|
|
|
|
GrowlVM *growl_vm_init(void);
|
|
void growl_vm_free(GrowlVM *vm);
|
|
GrowlObjectHeader *growl_gc_alloc(GrowlVM *vm, size_t size);
|
|
GrowlObjectHeader *growl_gc_alloc_tenured(GrowlVM *vm, size_t size);
|
|
void growl_gc_collect(GrowlVM *vm);
|
|
void growl_gc_root(GrowlVM *vm, Growl *ptr);
|
|
size_t growl_gc_mark(GrowlVM *vm);
|
|
void growl_gc_reset(GrowlVM *vm, size_t mark);
|
|
int vm_doquot(GrowlVM *vm, GrowlQuotation *quot);
|
|
|
|
#endif // GROWL_H
|