#ifndef GROWL_H #define GROWL_H #include #include #include #include #include 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 GrowlModule GrowlModule; typedef struct GrowlCompileContext GrowlCompileContext; 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, }; struct GrowlObjectHeader { size_t size; uint32_t type; }; uint32_t growl_type(Growl obj); int growl_equals(Growl a, Growl b); 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 GrowlString { size_t len; char data[]; }; Growl growl_make_string(GrowlVM *vm, size_t len); Growl growl_wrap_string(GrowlVM *vm, const char *cstr); Growl growl_wrap_string_tenured(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); 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 (*call)(GrowlVM *, void *); void (*finalizer)(void *); }; struct GrowlAlien { GrowlAlienType *type; void *data; }; Growl growl_make_alien(GrowlVM *vm, GrowlAlienType *type, void *data); Growl growl_make_alien_tenured(GrowlVM *vm, GrowlAlienType *type, void *data); GrowlAlien *growl_unwrap_alien(Growl obj, GrowlAlienType *type); void growl_register_native(GrowlVM *vm, const char *name, void (*fn)(GrowlVM *)); /** 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; Growl callable; }; struct GrowlDefinitionTable { GrowlDefinition *data; size_t count, capacity; }; struct GrowlDictionary { GrowlDictionary *child[4]; const char *name; Growl callable; size_t index; }; struct GrowlModule { char *resolved_path; GrowlModule *next; }; struct GrowlCompileContext { GrowlCompileContext *parent; const char *file_path, *file_dir; }; 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; GrowlQuotation *return_trampoline; GrowlQuotation *dip_trampoline; Growl 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); void growl_push(GrowlVM *vm, Growl obj); Growl growl_peek(GrowlVM *vm, size_t depth); Growl growl_pop(GrowlVM *vm); void growl_rpush(GrowlVM *vm, Growl obj); Growl growl_rpop(GrowlVM *vm); noreturn void growl_vm_error(GrowlVM *vm, const char *fmt, ...); int growl_vm_execute(GrowlVM *vm, GrowlQuotation *quot); /** Compiler */ Growl growl_compile(GrowlVM *vm, GrowlLexer *lexer); void growl_disassemble(GrowlVM *vm, GrowlQuotation *quot); /** Extra libraries */ void growl_register_file_library(GrowlVM *vm); #endif // GROWL_H