script

script.git
git clone git://git.lenczewski.org/script.git
Log | Files | Refs

libscript_internal.h (5302B)


      1 #ifndef LIBSCRIPT_INTERNAL_H
      2 #define LIBSCRIPT_INTERNAL_H
      3 
      4 #include "libscript.h"
      5 
      6 #include <ctype.h>
      7 #include <inttypes.h>
      8 #include <limits.h>
      9 
     10 #define UNREACHABLE() (*((volatile char *) 0) = 0)
     11 #define PANIC() UNREACHABLE()
     12 
     13 /* utilities
     14  * ===========================================================================
     15  */
     16 
     17 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1))
     18 #define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align))
     19 
     20 struct arena {
     21 	void *ptr;
     22 	size_t cap, len;
     23 };
     24 
     25 static inline void
     26 arena_reset(struct arena *arena)
     27 {
     28 	arena->len = 0;
     29 }
     30 
     31 static inline void *
     32 arena_alloc(struct arena *arena, size_t size, size_t align)
     33 {
     34 	size_t aligned_len = ALIGN_NEXT(arena->len, align);
     35 	if (aligned_len + size > arena->cap)
     36 		return NULL;
     37 
     38 	void *ptr = (void *) ((uintptr_t) arena->ptr + aligned_len);
     39 	arena->len = aligned_len + size;
     40 
     41 	return ptr;
     42 }
     43 
     44 #define ALLOC_ARRAY(arena, T, n) \
     45 	arena_alloc((arena), sizeof(T) * (n), alignof(T))
     46 
     47 #define ALLOC_SIZED(arena, T) ALLOC_ARRAY((arena), T, 1)
     48 
     49 static inline void
     50 list_push_head(struct script_list *restrict list,
     51 	       struct script_list_node *restrict node)
     52 {
     53 	if (!list->tail)
     54 		list->tail = node;
     55 
     56 	if (list->head)
     57 		list->head->prev = node;
     58 
     59 	node->next = list->head;
     60 	list->head = node;
     61 }
     62 
     63 static inline void
     64 list_push_tail(struct script_list *restrict list,
     65 	       struct script_list_node *restrict node)
     66 {
     67 	if (!list->head)
     68 		list->head = node;
     69 
     70 	if (list->tail)
     71 		list->tail->next = node;
     72 
     73 	node->prev = list->tail;
     74 	list->tail = node;
     75 }
     76 
     77 static inline struct script_list_node *
     78 list_pop_head(struct script_list *list)
     79 {
     80 	if (!list->head)
     81 		return NULL;
     82 
     83 	struct script_list_node *node = list->head;
     84 	list->head = node->next;
     85 	return node;
     86 }
     87 
     88 static inline struct script_list_node *
     89 list_pop_tail(struct script_list *list)
     90 {
     91 	if (!list->tail)
     92 		return NULL;
     93 
     94 	struct script_list_node *node = list->tail;
     95 	list->tail = node->prev;
     96 	return node;
     97 }
     98 
     99 struct identifier {
    100 	char *ptr;
    101 	size_t len;
    102 };
    103 
    104 struct ident_pool {
    105 	struct identifier *ptr;
    106 	size_t cap, len;
    107 };
    108 
    109 static inline struct script_flystr
    110 ident_pool_intern(struct ident_pool *pool, char *str, size_t len)
    111 {
    112 	/* TODO: switch to a hash table, or anything better than linear search */
    113 	size_t i;
    114 	for (i = 0; i < pool->len; i++) {
    115 		struct identifier *ident = &pool->ptr[i];
    116 
    117 		if (ident->len == len && strncmp(ident->ptr, str, len) == 0)
    118 			return (struct script_flystr) { .v = i, };
    119 	}
    120 
    121 	assert(i < pool->cap);
    122 
    123 	pool->ptr[i].ptr = str;
    124 	pool->ptr[i].len = len;
    125 	pool->len++;
    126 
    127 	return (struct script_flystr) { .v = i, };
    128 }
    129 
    130 static inline void
    131 ident_pool_get(struct ident_pool *pool, struct script_flystr ident, char **str, size_t *len)
    132 {
    133 	struct identifier *identifier = &pool->ptr[ident.v];
    134 
    135 	*str = identifier->ptr;
    136 	*len = identifier->len;
    137 }
    138 
    139 struct token_stream {
    140 	struct script_token *ptr;
    141 	size_t cap, len, cur;
    142 };
    143 
    144 static inline struct script_token *
    145 token_stream_alloc(struct token_stream *stream)
    146 {
    147 	if (stream->len >= stream->cap)
    148 		return NULL;
    149 
    150 	return &stream->ptr[stream->len++];
    151 }
    152 
    153 struct symbol_table {
    154 	struct script_symbol *ptr;
    155 	size_t cap, len;
    156 
    157 	uintptr_t address;
    158 };
    159 
    160 static inline struct script_symbol *
    161 symbol_table_push(struct symbol_table *symtab)
    162 {
    163 	if (symtab->len >= symtab->cap)
    164 		return NULL;
    165 
    166 	return &symtab->ptr[symtab->len++];
    167 }
    168 
    169 static inline struct script_symbol *
    170 symbol_table_push_scope(struct symbol_table *symtab)
    171 {
    172 	return symbol_table_push(symtab);
    173 }
    174 
    175 static inline void
    176 symbol_table_pop_scope(struct symbol_table *symtab, struct script_symbol *scope)
    177 {
    178 	symtab->len = scope - symtab->ptr;
    179 }
    180 
    181 static inline struct script_symbol *
    182 symbol_table_find(struct symbol_table *symtab, struct script_flystr ident)
    183 {
    184 	for (size_t i = 1; i <= symtab->len; i++) {
    185 		struct script_symbol *sym = &symtab->ptr[symtab->len - i];
    186 		if (sym->ident.v == ident.v) return sym;
    187 	}
    188 
    189 	return NULL;
    190 }
    191 
    192 static inline uintptr_t
    193 symbol_table_next_addr(struct symbol_table *symtab,
    194 		       struct script_typeinfo const *typeinfo)
    195 {
    196 	uintptr_t addr = ALIGN_NEXT(symtab->address, typeinfo->alignment);
    197 	symtab->address = addr + typeinfo->size;
    198 	return addr;
    199 }
    200 
    201 struct ast {
    202 	struct script_list roots;
    203 };
    204 
    205 struct ir {
    206 	struct script_ir_inst *ptr;
    207 	size_t cap, len;
    208 };
    209 
    210 static inline struct script_ir_inst const *
    211 ir_current_inst(struct ir *ir)
    212 {
    213 	return &ir->ptr[ir->len];
    214 }
    215 
    216 static inline struct script_ir_inst *
    217 ir_push(struct ir *ir, struct script_ir_inst *inst)
    218 {
    219 	if (ir->len >= ir->cap)
    220 		return NULL;
    221 
    222 	struct script_ir_inst *instruction = &ir->ptr[ir->len++];
    223 	*instruction = *inst;
    224 
    225 	return instruction;
    226 }
    227 
    228 struct compile_ctx {
    229 	struct arena arena;
    230 	struct arena scratch;
    231 
    232 	FILE *errstream;
    233 	int verbose;
    234 	char *src;
    235 	size_t len;
    236 
    237 	struct ident_pool ident_pool;
    238 
    239 	struct token_stream stream;
    240 
    241 	struct symbol_table symtab;
    242 
    243 	struct ast ast;
    244 
    245 	struct ir ir;
    246 };
    247 
    248 static inline void
    249 dbglog(struct compile_ctx *ctx, char const *fmt, ...)
    250 {
    251 	va_list va;
    252 	va_start(va, fmt);
    253 	vfprintf(ctx->errstream, fmt, va);
    254 	va_end(va);
    255 }
    256 
    257 static int
    258 dump_token(struct script_token *token, char *buf, size_t cap);
    259 
    260 static void
    261 dump_token_stream(struct compile_ctx *ctx);
    262 
    263 static void
    264 dump_symbol_table(struct compile_ctx *ctx);
    265 
    266 static void
    267 dump_ast(struct compile_ctx *ctx);
    268 
    269 static void
    270 dump_ir(struct compile_ctx *ctx);
    271 
    272 #endif /* LIBSCRIPT_INTERNAL_H */