235 lines
5.6 KiB
C
235 lines
5.6 KiB
C
#ifndef GROWL_H
|
|
#define GROWL_H
|
|
|
|
#include <setjmp.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.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 GrowlTable GrowlTable;
|
|
typedef struct GrowlQuotation GrowlQuotation;
|
|
typedef struct GrowlCompose GrowlCompose;
|
|
typedef struct GrowlCurry GrowlCurry;
|
|
typedef struct GrowlAlienType GrowlAlienType;
|
|
typedef struct GrowlAlien GrowlAlien;
|
|
typedef struct GrowlLexer GrowlLexer;
|
|
typedef struct GrowlArena GrowlArena;
|
|
typedef struct GrowlFrame GrowlFrame;
|
|
typedef struct GrowlDictionary GrowlDictionary;
|
|
typedef struct GrowlDefinition GrowlDefinition;
|
|
typedef struct GrowlDefinitionTable GrowlDefinitionTable;
|
|
typedef struct GrowlVM GrowlVM;
|
|
|
|
enum {
|
|
GROWL_TYPE_NIL,
|
|
GROWL_TYPE_NUMBER,
|
|
GROWL_TYPE_STRING,
|
|
GROWL_TYPE_LIST,
|
|
GROWL_TYPE_TUPLE,
|
|
GROWL_TYPE_TABLE,
|
|
GROWL_TYPE_QUOTATION,
|
|
GROWL_TYPE_COMPOSE,
|
|
GROWL_TYPE_CURRY,
|
|
GROWL_TYPE_ALIEN,
|
|
};
|
|
|
|
uint32_t growl_type(Growl obj);
|
|
uint64_t growl_hash_combine(uint64_t a, uint64_t b);
|
|
uint64_t growl_hash_bytes(const uint8_t *data, size_t len);
|
|
uint64_t growl_hash(Growl obj);
|
|
void growl_print_to(FILE *file, Growl value);
|
|
void growl_print(Growl value);
|
|
void growl_println(Growl value);
|
|
|
|
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 GrowlTable {};
|
|
|
|
GrowlTable *growl_unwrap_table(Growl obj);
|
|
GrowlTable *growl_table_upsert(GrowlVM *vm, GrowlTable **table, Growl key);
|
|
|
|
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 GrowlAlienType {
|
|
const char *name;
|
|
void (*finalizer)(void *);
|
|
};
|
|
|
|
struct GrowlAlien {
|
|
GrowlAlienType *type;
|
|
void *data;
|
|
};
|
|
|
|
Growl growl_make_alien(GrowlVM *vm, GrowlAlienType *type, void *data);
|
|
GrowlAlien *growl_unwrap_alien(Growl obj, GrowlAlienType *type);
|
|
|
|
/** Lexer */
|
|
enum {
|
|
GTOK_INVALID = -1,
|
|
GTOK_EOF = 0,
|
|
GTOK_WORD = 'a',
|
|
GTOK_STRING = '"',
|
|
GTOK_SEMICOLON = ';',
|
|
GTOK_LPAREN = '(',
|
|
GTOK_RPAREN = ')',
|
|
GTOK_LBRACKET = '[',
|
|
GTOK_RBRACKET = ']',
|
|
GTOK_LBRACE = '{',
|
|
GTOK_RBRACE = '}',
|
|
};
|
|
|
|
#define GROWL_LEXER_BUFSIZE 256
|
|
|
|
struct GrowlLexer {
|
|
int kind;
|
|
int cursor;
|
|
int current_row, current_col;
|
|
int start_row, start_col;
|
|
FILE *file;
|
|
char buffer[GROWL_LEXER_BUFSIZE];
|
|
};
|
|
|
|
int growl_lexer_next(GrowlLexer *lexer);
|
|
|
|
struct GrowlArena {
|
|
uint8_t *start, *end;
|
|
uint8_t *free;
|
|
};
|
|
|
|
void growl_arena_init(GrowlArena *arena, size_t size);
|
|
void growl_arena_free(GrowlArena *arena);
|
|
void *growl_arena_alloc(GrowlArena *arena, size_t size, size_t align,
|
|
size_t count);
|
|
char *growl_arena_strdup(GrowlArena *ar, const char *str);
|
|
|
|
#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;
|
|
Growl next;
|
|
};
|
|
|
|
struct GrowlDefinition {
|
|
const char *name;
|
|
GrowlQuotation *quotation;
|
|
};
|
|
|
|
struct GrowlDefinitionTable {
|
|
GrowlDefinition *data;
|
|
size_t count, capacity;
|
|
};
|
|
|
|
struct GrowlDictionary {
|
|
GrowlDictionary *child[4];
|
|
const char *name;
|
|
GrowlQuotation *quotation;
|
|
size_t index;
|
|
};
|
|
|
|
GrowlDictionary *growl_dictionary_upsert(GrowlDictionary **dict,
|
|
const char *name, GrowlArena *perm);
|
|
|
|
struct GrowlVM {
|
|
GrowlArena from, to;
|
|
GrowlArena tenured;
|
|
GrowlArena scratch;
|
|
GrowlArena arena;
|
|
|
|
GrowlDictionary *dictionary;
|
|
GrowlDefinitionTable defs;
|
|
|
|
GrowlQuotation *current_quotation;
|
|
uint8_t *ip;
|
|
Growl wst[GROWL_STACK_SIZE], *sp;
|
|
Growl rst[GROWL_STACK_SIZE], *rsp;
|
|
GrowlFrame cst[GROWL_CALL_STACK_SIZE], *csp;
|
|
|
|
GrowlQuotation *compose_trampoline;
|
|
Growl compose_next;
|
|
|
|
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 growl_vm_execute(GrowlVM *vm, GrowlQuotation *quot);
|
|
|
|
/** Compiler */
|
|
Growl growl_compile(GrowlVM *vm, GrowlLexer *lexer);
|
|
void growl_disassemble(GrowlVM *vm, GrowlQuotation *quot);
|
|
|
|
#endif // GROWL_H
|