aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-21 18:20:35 +0200
committerBad Diode <bd@badd10de.dev>2024-06-21 18:20:35 +0200
commit835f4d9f23f55a973d76ae9384b7b9d75da5472b (patch)
tree8e817452f8437db07688cb6e63a1a73bcce543eb /src
parent5a25eeefd13b0e1988ecaf7e497ebde81e71bb2e (diff)
downloadbdl-835f4d9f23f55a973d76ae9384b7b9d75da5472b.tar.gz
bdl-835f4d9f23f55a973d76ae9384b7b9d75da5472b.zip
Remove old files no longer needed as reference
Diffstat (limited to 'src')
-rw-r--r--src/common.h31
-rw-r--r--src/darray.h81
-rw-r--r--src/errors.c68
-rw-r--r--src/errors.h54
-rw-r--r--src/hashtable.h180
-rw-r--r--src/main.c95
-rw-r--r--src/nodes.c133
-rw-r--r--src/nodes.h88
-rw-r--r--src/string_view.c49
-rw-r--r--src/string_view.h28
-rw-r--r--src/viz.c350
-rw-r--r--src/x86asm_compiler.h (renamed from src/compiler.h)0
12 files changed, 89 insertions, 1068 deletions
diff --git a/src/common.h b/src/common.h
deleted file mode 100644
index 08e78a8..0000000
--- a/src/common.h
+++ /dev/null
@@ -1,31 +0,0 @@
1#ifndef BDL_COMMON_H
2#define BDL_COMMON_H
3
4#include <assert.h>
5#include <stdbool.h>
6#include <stddef.h>
7#include <stdint.h>
8
9typedef uint8_t u8;
10typedef uint16_t u16;
11typedef uint32_t u32;
12typedef uint64_t u64;
13typedef int8_t s8;
14typedef int16_t s16;
15typedef int32_t s32;
16typedef int64_t s64;
17typedef volatile u8 vu8;
18typedef volatile u16 vu16;
19typedef volatile u32 vu32;
20typedef volatile u64 vu64;
21typedef volatile s8 vs8;
22typedef volatile s16 vs16;
23typedef volatile s32 vs32;
24typedef volatile s64 vs64;
25
26#define KB(N) ((u64)(N) * 1024)
27#define MB(N) ((u64)KB(N) * 1024)
28#define GB(N) ((u64)MB(N) * 1024)
29#define TB(N) ((u64)GB(N) * 1024)
30
31#endif // BDL_COMMON_H
diff --git a/src/darray.h b/src/darray.h
deleted file mode 100644
index fa4e293..0000000
--- a/src/darray.h
+++ /dev/null
@@ -1,81 +0,0 @@
1#ifndef BDL_DARRAY_H
2#define BDL_DARRAY_H
3
4#include <string.h>
5
6typedef struct ArrayHeader {
7 size_t size;
8 size_t cap;
9} ArrayHeader;
10
11// Header/Size/capacity accessors.
12#define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader)))
13#define array_size(ARR) ((ARR) ? array_head(ARR)->size : 0)
14#define array_cap(ARR) ((ARR) ? array_head(ARR)->cap : 0)
15
16// Initialize a dynamic array ARR with N elements. The initialization doesn't
17// zero out the data, so thread carefully..
18#define array_init(ARR,N) ((ARR) = _array_reserve(N, sizeof(*(ARR))))
19
20// Push a given element T to the dynamic array ARR.
21#define array_push(ARR, T) \
22 ((ARR) = _array_maybe_grow(ARR, sizeof(T)), \
23 (ARR)[array_head(ARR)->size++] = (T))
24
25// Return the last element of the array. Can be used to build stacks.
26#define array_pop(ARR) (ARR)[--array_head(ARR)->size]
27
28// Return the value stored at the OFFSET position from the tail of the array.
29#define array_peek(ARR, OFFSET) (ARR)[array_head(ARR)->size - 1 - (OFFSET)]
30
31// Insert N bytes from the SRC array into the ARR dynamic array.
32#define array_insert(ARR, SRC, N) \
33 ((ARR) = _array_insert(ARR, SRC, N, sizeof(*(ARR))))
34
35// Free the memory from the original allocated position.
36#define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0)
37
38static inline void *
39_array_reserve(size_t num_elem, size_t type_size) {
40 char *p = malloc(num_elem * type_size + sizeof(ArrayHeader));
41 p += sizeof(ArrayHeader);
42 array_head(p)->size = 0;
43 array_head(p)->cap = num_elem;
44 return p;
45}
46
47static inline void *
48_array_maybe_grow(void *arr, size_t type_size) {
49 ArrayHeader *head = array_head(arr);
50 if (head->cap == head->size) {
51 if (head->cap == 0) {
52 head->cap++;
53 } else {
54 head->cap *= 2;
55 }
56 head = realloc(head, head->cap * type_size + sizeof(ArrayHeader));
57 }
58 arr = (char *)head + sizeof(ArrayHeader);
59 return arr;
60}
61
62static inline
63char * _array_insert(char *arr, const char *src, size_t n_bytes, size_t type_size) {
64 ArrayHeader *head = array_head(arr);
65 size_t new_size = n_bytes + head->size;
66 if (new_size > head->cap * type_size) {
67 if (head->cap == 0) {
68 head->cap = 1;
69 }
70 while (new_size >= head->cap * type_size) {
71 head->cap *= 2;
72 }
73 head = realloc(head, head->cap * type_size + sizeof(ArrayHeader));
74 }
75 arr = (char *)head + sizeof(ArrayHeader);
76 memcpy((arr + head->size), src, n_bytes);
77 head->size = new_size;
78 return arr;
79}
80
81#endif // BDL_DARRAY_H
diff --git a/src/errors.c b/src/errors.c
deleted file mode 100644
index e854cf0..0000000
--- a/src/errors.c
+++ /dev/null
@@ -1,68 +0,0 @@
1#include "errors.h"
2
3static const char* error_msgs[] = {
4 [ERR_UNKNOWN] = "error: something unexpected happened",
5 [ERR_UNMATCHED_STRING] = "error: unmatched string delimiter",
6 [ERR_UNMATCHED_PAREN] = "error: unbalanced parentheses",
7 [ERR_UNKNOWN_TOK_TYPE] = "error: unknown token type",
8 [ERR_MALFORMED_NUMBER] = "error: malformed number token",
9 [ERR_MALFORMED_EXPR] = "error: malformed expression",
10 [ERR_UNIMPLEMENTED] = "error: not implemented",
11 [ERR_NOT_A_NUMBER] = "error: expected a number",
12 [ERR_NOT_A_SYMBOL] = "error: expected a symbol",
13 [ERR_NOT_A_STRING] = "error: expected a string",
14 [ERR_NOT_A_TYPE] = "error: expected a type",
15 [ERR_NOT_A_BOOL] = "error: expected a bool",
16 [ERR_NOT_A_LPAREN] = "error: expected opening parentheses (lparen)",
17 [ERR_NOT_A_RPAREN] = "error: expected closing parentheses (rparen)",
18 [ERR_SYMBOL_REDEF] = "error: symbol redefinition",
19 [ERR_UNKNOWN_SYMBOL] = "error: unknown symbol",
20 [ERR_TYPE_REDEF] = "error: type redefinition",
21 [ERR_UNKNOWN_TYPE] = "error: unknown type",
22 [ERR_WRONG_RET_TYPE] = "error: return type don't match type signature",
23 [ERR_WRONG_COND_TYPE] = "error: conditional expression is not boolean",
24 [ERR_WRONG_TYPE_T_F] = "error: unmatched types between true and false expression",
25 [ERR_WRONG_TYPE_NUM] = "error: non numeric argument types",
26 [ERR_WRONG_TYPE_BOOL] = "error: non bool argument types",
27 [ERR_WRONG_TYPE_FUN] = "error: not a function",
28 [ERR_BAD_ARGS] = "error: arguments don't match expected types",
29 [ERR_TYPE_MISMATCH] = "error: type mismatch",
30};
31
32static Error current_error = {.value = ERR_OK};
33
34void
35push_error(ErrorType type, ErrorValue value, size_t line, size_t col) {
36 if (has_errors()) {
37 return;
38 }
39 current_error.type = type;
40 current_error.value = value;
41 current_error.line = line;
42 current_error.col = col;
43}
44
45bool
46has_errors(void) {
47 return current_error.value != ERR_OK;
48}
49
50void
51check_errors(const char *file_name) {
52 if (!has_errors()) {
53 return;
54 }
55 fprintf(stderr, "%s", file_name);
56 if (current_error.line != 0) {
57 fprintf(stderr, ":%ld:%ld", current_error.line, current_error.col);
58 }
59 switch (current_error.type) {
60 case ERR_TYPE_LEXER: { fprintf(stderr, ": [lexer] "); } break;
61 case ERR_TYPE_PARSER: { fprintf(stderr, ": [parser] "); } break;
62 case ERR_TYPE_SEMANTIC: { fprintf(stderr, ": [semantic] "); } break;
63 case ERR_TYPE_BASM: { fprintf(stderr, ": [basm] "); } break;
64 default: break;
65 }
66 fprintf(stderr, "%s\n", error_msgs[current_error.value]);
67 exit(EXIT_FAILURE);
68}
diff --git a/src/errors.h b/src/errors.h
deleted file mode 100644
index 8ddba25..0000000
--- a/src/errors.h
+++ /dev/null
@@ -1,54 +0,0 @@
1#ifndef BDL_ERRORS_H
2#define BDL_ERRORS_H
3
4#include "common.h"
5
6typedef enum ErrorType {
7 ERR_TYPE_LEXER,
8 ERR_TYPE_PARSER,
9 ERR_TYPE_SEMANTIC,
10 ERR_TYPE_BASM,
11} ErrorType;
12
13typedef enum ErrorValue {
14 ERR_UNKNOWN = 0,
15 ERR_UNMATCHED_STRING,
16 ERR_UNKNOWN_TOK_TYPE,
17 ERR_UNMATCHED_PAREN,
18 ERR_MALFORMED_NUMBER,
19 ERR_MALFORMED_EXPR,
20 ERR_UNIMPLEMENTED,
21 ERR_NOT_A_NUMBER,
22 ERR_NOT_A_SYMBOL,
23 ERR_NOT_A_STRING,
24 ERR_NOT_A_TYPE,
25 ERR_NOT_A_BOOL,
26 ERR_NOT_A_LPAREN,
27 ERR_NOT_A_RPAREN,
28 ERR_SYMBOL_REDEF,
29 ERR_UNKNOWN_SYMBOL,
30 ERR_TYPE_REDEF,
31 ERR_UNKNOWN_TYPE,
32 ERR_WRONG_RET_TYPE,
33 ERR_WRONG_COND_TYPE,
34 ERR_WRONG_TYPE_T_F,
35 ERR_WRONG_TYPE_NUM,
36 ERR_WRONG_TYPE_BOOL,
37 ERR_WRONG_TYPE_FUN,
38 ERR_TYPE_MISMATCH,
39 ERR_BAD_ARGS,
40 ERR_OK,
41} ErrorValue;
42
43typedef struct Error {
44 ErrorType type;
45 ErrorValue value;
46 size_t line;
47 size_t col;
48} Error;
49
50void push_error(ErrorType type, ErrorValue value, size_t line, size_t col);
51void check_errors(const char *file_name);
52bool has_errors(void);
53
54#endif // BDL_ERRORS_H
diff --git a/src/hashtable.h b/src/hashtable.h
deleted file mode 100644
index faa8591..0000000
--- a/src/hashtable.h
+++ /dev/null
@@ -1,180 +0,0 @@
1#ifndef BDL_HASHTABLE_H
2#define BDL_HASHTABLE_H
3
4#include "darray.h"
5
6// Minimum table capacity.
7#define HT_MIN_CAP 4
8#define HT_MIN_SHIFT 2
9
10// Adjust the load factor threshold at which the table will grow on insertion.
11#define HT_LOAD_THRESHOLD 0.8
12
13typedef struct HashTablePair {
14 void *key;
15 void *value;
16} HashTablePair;
17
18struct HashTable;
19typedef uint64_t (HashFunction)(const struct HashTable *table, void *bytes);
20typedef bool (EqFunc)(void *a, void *b);
21
22typedef struct HashTable {
23 // All available key-value pairs as a dynamic array.
24 HashTablePair *pairs;
25
26 // Hash function.
27 HashFunction *hash_func;
28
29 // Equality function.
30 EqFunc *eq_func;
31
32 // This table expects the number of buckets to grow in powers of two. To
33 // speedup the default hashing, we memoize the number of bits equivalent to
34 // that power of 2:
35 //
36 // cap := 1024 = 2 ^ 10, shift_amount := 10
37 //
38 uint8_t shift_amount;
39} HashTable;
40
41// Hash a byte stream using a circular shift + XOR hash function.
42static inline uint64_t
43_xor_shift_hash(const char *key, size_t n) {
44 uint64_t hash = 0x65d9d65f6a19574f;
45 char *last = (char *)key + n;
46 while (key != last) {
47 hash ^= (uint64_t)*key++;
48 hash = (hash << 8) | (hash >> (64 - 8));
49 }
50 return hash;
51}
52
53// Use Fibonacci hashing to map a hash to a value in range of the table.
54static inline uint64_t
55_fibonacci_hash(uint64_t hash, size_t shift_amount) {
56 return (hash * UINT64_C(11400714819323198485)) >> (64 - shift_amount);
57}
58
59static inline float
60ht_load_factor(const HashTable *table) {
61 return (float)array_size(table->pairs) / (float)array_cap(table->pairs);
62}
63
64HashTable *
65ht_init(HashFunction *hash_func, EqFunc *eq_func) {
66 HashTable *table = malloc(sizeof(HashTable));
67 *table = (HashTable){0};
68 array_init(table->pairs, HT_MIN_CAP);
69 for (size_t i = 0; i < array_cap(table->pairs); i++) {
70 table->pairs[i] = (HashTablePair){NULL, NULL};
71 }
72 table->shift_amount = HT_MIN_SHIFT;
73 table->hash_func = hash_func;
74 table->eq_func = eq_func;
75 return table;
76}
77
78void
79_ht_insert(HashTable *table, void *key, void *value) {
80 size_t position = table->hash_func(table, key);
81 size_t probe_position = position;
82
83 // Verify the key in that position is free. If not, use linear probing to
84 // find the next free slot.
85 HashTablePair *pairs = table->pairs;
86 bool update = false;
87 while (true) {
88 if (pairs[probe_position].key == NULL) {
89 array_head(pairs)->size++;
90 break;
91 }
92 if (table->eq_func(pairs[probe_position].key, key)) {
93 update = true;
94 break;
95 }
96 if (probe_position == array_cap(pairs) - 1) {
97 probe_position = 0;
98 } else {
99 probe_position++;
100 }
101 }
102
103 if (!update) {
104 pairs[probe_position].key = key;
105 pairs[probe_position].value = value;
106 } else {
107 pairs[probe_position].value = value;
108 }
109}
110
111void
112_ht_maybe_grow(HashTable *table) {
113 if (ht_load_factor(table) < HT_LOAD_THRESHOLD) {
114 return;
115 }
116
117 // Create a new array with 2x capacity.
118 HashTablePair *old_pairs = table->pairs;
119 table->pairs = NULL;
120 array_init(table->pairs, array_cap(old_pairs) * 2);
121 for (size_t i = 0; i < array_cap(table->pairs); i++) {
122 table->pairs[i] = (HashTablePair){NULL, NULL};
123 }
124 table->shift_amount++;
125
126 // Hash everything in the table for the new array capacity.
127 for (size_t i = 0; i < array_cap(old_pairs); i++) {
128 if (old_pairs[i].key != NULL) {
129 _ht_insert(table, old_pairs[i].key, old_pairs[i].value);
130 }
131 }
132
133 // Free old arrays.
134 array_free(old_pairs);
135}
136
137void
138ht_insert(HashTable *table, void *key, void *value) {
139 _ht_maybe_grow(table);
140 _ht_insert(table, key, value);
141 return;
142}
143
144void *
145ht_lookup(const HashTable *table, void *key) {
146 size_t position = table->hash_func(table, key);
147 size_t probe_position = position;
148
149 // Verify the key in that position is the same. If not perform linear
150 // probing to find it.
151 HashTablePair *pairs = table->pairs;
152 while (true) {
153 if (pairs[probe_position].key == NULL) {
154 return NULL;
155 }
156 if (table->eq_func(pairs[probe_position].key, key)) {
157 break;
158 }
159 if (probe_position == array_cap(pairs) - 1) {
160 probe_position = 0;
161 } else {
162 probe_position++;
163 }
164 if (probe_position == position) {
165 return NULL;
166 }
167 }
168 return pairs[probe_position].value;
169}
170
171void
172ht_free(HashTable *table) {
173 if (table == NULL) {
174 return;
175 }
176 array_free(table->pairs);
177 free(table);
178}
179
180#endif // BDL_HASHTABLE_H
diff --git a/src/main.c b/src/main.c
index 2bcbf39..60203d5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,13 +30,20 @@ typedef enum {
30 SYM_PARAM, 30 SYM_PARAM,
31 SYM_ENUM, 31 SYM_ENUM,
32 SYM_ENUM_FIELD, 32 SYM_ENUM_FIELD,
33 SYM_STRUCT,
34 SYM_STRUCT_FIELD,
33} SymbolKind; 35} SymbolKind;
34 36
35Str sym_kind_str[] = { 37Str sym_kind_str[] = {
36 [SYM_UNKNOWN] = cstr("UNKNOWN "), [SYM_BUILTIN] = cstr("BUILTIN "), 38 [SYM_UNKNOWN] = cstr("UNKNOWN "),
37 [SYM_FUN] = cstr("FUNCTION "), [SYM_VAR] = cstr("VARIABLE "), 39 [SYM_BUILTIN] = cstr("BUILTIN "),
38 [SYM_PARAM] = cstr("PARAMETER "), [SYM_ENUM] = cstr("ENUM "), 40 [SYM_FUN] = cstr("FUNCTION "),
39 [SYM_ENUM_FIELD] = cstr("ENUM FIELD"), 41 [SYM_VAR] = cstr("VARIABLE "),
42 [SYM_PARAM] = cstr("PARAMETER "),
43 [SYM_ENUM] = cstr("ENUM "),
44 [SYM_ENUM_FIELD] = cstr("ENUM FIELD "),
45 [SYM_STRUCT] = cstr("STRUCT "),
46 [SYM_STRUCT_FIELD] = cstr("STRUCT FIELD "),
40}; 47};
41 48
42typedef struct Symbol { 49typedef struct Symbol {
@@ -85,6 +92,69 @@ find_symbol(Scope *scope, Str symbol) {
85} 92}
86 93
87void 94void
95graph_scope(Scope *scope, Arena a) {
96 if (!scope->symbols) {
97 return;
98 }
99 SymbolMapIter iter = symmap_iterator(scope->symbols, &a);
100 SymbolMap *sym = symmap_next(&iter, &a);
101 print(
102 "%d[shape=\"none\" label=<\
103<TABLE ALIGN=\"left\" STYLE=\"rounded\" BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" COLUMNS=\"*\">\
104 <TR style=\"rounded\" ><TD COLSPAN=\"2\">ID: %d</TD></TR>",
105 scope->id, scope->id);
106 print(
107 "<TR ><TD ALIGN=\"left\" > NAME</TD><TD ALIGN=\"left\" > "
108 "KIND</TD></TR>");
109 while (sym) {
110 print(
111 "<TR><TD ALIGN=\"left\"> %s </TD><TD ALIGN=\"left\"> %s </TD></TR>",
112 sym->val.name, sym_kind_str[sym->val.kind]);
113 SymbolMapIter field_iter = symmap_iterator(sym->val.fields, &a);
114 SymbolMap *field = symmap_next(&field_iter, &a);
115 while (field) {
116 print(
117 "<TR><TD ALIGN=\"left\"> %s.%s </TD><TD ALIGN=\"left\"> %s "
118 "</TD></TR>",
119 sym->val.name, field->val.name, sym_kind_str[field->val.kind]);
120 field = symmap_next(&field_iter, &a);
121 }
122 sym = symmap_next(&iter, &a);
123 }
124 println("</TABLE>>];");
125 sz this_id = scope->id;
126 while (scope->parent) {
127 if (scope->parent->symbols) {
128 println("%d:n->%d:s;", this_id, scope->parent->id);
129 break;
130 } else {
131 scope = scope->parent;
132 }
133 }
134}
135
136void
137graph_symbols(Scope **scopes, Arena a) {
138 if (scopes == NULL) return;
139 println("digraph symbols {");
140 println("rankdir=BT;");
141 println("ranksep=\"0.95 equally\";");
142 println("nodesep=\"0.5 equally\";");
143 println("overlap=scale;");
144 println("bgcolor=\"transparent\";");
145 for (sz i = 0; i < array_size(scopes); i++) {
146 Scope *scope = scopes[i];
147 if (!scope) {
148 continue;
149 }
150 println("subgraph %d {", i);
151 graph_scope(scope, a);
152 println("}");
153 }
154 println("}");
155}
156
157void
88analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { 158analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
89 assert(a); 159 assert(a);
90 assert(scope); 160 assert(scope);
@@ -158,6 +228,7 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
158 analyzer_symbols(a, expr, next); 228 analyzer_symbols(a, expr, next);
159 } 229 }
160 } break; 230 } break;
231 case NODE_STRUCT:
161 case NODE_ENUM: { 232 case NODE_ENUM: {
162 Str symbol = node->value.str; 233 Str symbol = node->value.str;
163 if (symmap_lookup(&scope->symbols, symbol) != NULL) { 234 if (symmap_lookup(&scope->symbols, symbol) != NULL) {
@@ -168,7 +239,10 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
168 } 239 }
169 SymbolMap *map = symmap_insert( 240 SymbolMap *map = symmap_insert(
170 &scope->symbols, symbol, 241 &scope->symbols, symbol,
171 (Symbol){.kind = SYM_ENUM, .name = symbol}, a->storage); 242 (Symbol){
243 .kind = node->kind == NODE_ENUM ? SYM_ENUM : SYM_STRUCT,
244 .name = symbol},
245 a->storage);
172 // TODO: symcheck the value expression? 246 // TODO: symcheck the value expression?
173 for (sz i = 0; i < array_size(node->struct_field); i++) { 247 for (sz i = 0; i < array_size(node->struct_field); i++) {
174 Node *field = node->struct_field[i]; 248 Node *field = node->struct_field[i];
@@ -179,7 +253,10 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
179 a->file_name, field->line, field->col, symbol, 253 a->file_name, field->line, field->col, symbol,
180 field_name); 254 field_name);
181 } 255 }
182 Symbol s = (Symbol){.kind = SYM_ENUM_FIELD, .name = field_name}; 256 Symbol s =
257 (Symbol){.kind = node->kind == NODE_ENUM ? SYM_ENUM_FIELD
258 : SYM_STRUCT_FIELD,
259 .name = field_name};
183 symmap_insert(&map->val.fields, field_name, s, a->storage); 260 symmap_insert(&map->val.fields, field_name, s, a->storage);
184 } 261 }
185 } break; 262 } break;
@@ -404,6 +481,11 @@ process_file(Str path) {
404 symbolic_analysis(&analyzer, &parser); 481 symbolic_analysis(&analyzer, &parser);
405 482
406 // Printing symbol tables. 483 // Printing symbol tables.
484 if (mode == PRINT_SYMTABLES) {
485 graph_symbols(analyzer.scopes, lexer_arena);
486 }
487
488#if DEBUG == 1
407 for (sz i = 0; i < array_size(analyzer.scopes); i++) { 489 for (sz i = 0; i < array_size(analyzer.scopes); i++) {
408 Arena scratch = lexer_arena; 490 Arena scratch = lexer_arena;
409 Scope *scope = analyzer.scopes[i]; 491 Scope *scope = analyzer.scopes[i];
@@ -424,6 +506,7 @@ process_file(Str path) {
424 sym = symmap_next(&iter, &lexer_arena); 506 sym = symmap_next(&iter, &lexer_arena);
425 } 507 }
426 } 508 }
509#endif
427 510
428 // TODO: Type checking. 511 // TODO: Type checking.
429 512
diff --git a/src/nodes.c b/src/nodes.c
deleted file mode 100644
index 6978acc..0000000
--- a/src/nodes.c
+++ /dev/null
@@ -1,133 +0,0 @@
1#include "nodes.h"
2
3static size_t node_gen_id = 0;
4
5Node *
6alloc_node(NodeType type) {
7 // TODO: Use a bump allocator?
8 // TODO: Free memory!
9 Node *node = malloc(sizeof(Node));
10 node->id = node_gen_id++;
11 node->type = type;
12 node->line = 0;
13 node->col = 0;
14 node->expr_type = NULL;
15 return node;
16}
17
18void
19print_node(Node *node) {
20 if (node == NULL) {
21 return;
22 }
23 switch (node->type) {
24 case NODE_NUMBER: {
25 if (node->number.negative) {
26 printf("-");
27 }
28 if (node->number.fractional != 0) {
29 printf("%zu.%zu", node->number.integral, node->number.fractional);
30 } else {
31 printf("%zu", node->number.integral);
32 }
33 } break;
34 case NODE_SYMBOL:
35 case NODE_TYPE:
36 case NODE_STRING: {
37 sv_write(&node->string);
38 } break;
39 case NODE_BOOL: {
40 if (node->boolean) {
41 printf("true");
42 } else {
43 printf("false");
44 }
45 } break;
46 case NODE_BUILTIN: {
47 printf("({%s}", token_str[node->builtin.type]);
48 size_t n_args = array_size(node->builtin.args);
49 if (n_args != 0) {
50 printf(" ");
51 }
52 for (size_t i = 0; i < n_args; ++i) {
53 print_node(node->builtin.args[i]);
54 if (i < n_args - 1) {
55 printf(" ");
56 }
57 }
58 printf(")");
59 } break;
60 case NODE_DEF: {
61 printf("(def ");
62 print_node(node->def.symbol);
63 printf(":");
64 print_node(node->def.type);
65 printf(" ");
66 print_node(node->def.value);
67 printf(")");
68 } break;
69 case NODE_SET: {
70 printf("(set ");
71 print_node(node->def.symbol);
72 printf(" ");
73 print_node(node->def.value);
74 printf(")");
75 } break;
76 case NODE_BLOCK: {
77 size_t n_expr = array_size(node->block.expr);
78 printf("{");
79 for (size_t i = 0; i < n_expr; ++i) {
80 printf(" ");
81 print_node(node->block.expr[i]);
82 }
83 printf(" }");
84 } break;
85 case NODE_IF: {
86 printf("(if ");
87 print_node(node->ifexpr.cond);
88 printf(" ");
89 print_node(node->ifexpr.expr_true);
90 if (node->ifexpr.expr_false != NULL) {
91 printf(" ");
92 print_node(node->ifexpr.expr_false);
93 }
94 printf(")");
95 } break;
96 case NODE_FUN: {
97 printf("(fun ");
98 print_node(node->fun.name);
99 printf(" (");
100 size_t n_params = array_size(node->fun.param_names);
101 for (size_t i = 0; i < n_params; ++i) {
102 print_node(node->fun.param_names[i]);
103 printf(":");
104 print_node(node->fun.param_types[i]);
105 if (i < n_params - 1) {
106 printf(" ");
107 }
108 }
109 printf(")");
110 printf(": ");
111 print_node(node->fun.return_type);
112 printf(" ");
113 print_node(node->fun.body);
114 printf(")");
115 } break;
116 case NODE_FUNCALL: {
117 printf("(");
118 print_node(node->funcall.name);
119 size_t n_args = array_size(node->funcall.args);
120 if (n_args != 0) {
121 printf(" ");
122 }
123 for (size_t i = 0; i < n_args; ++i) {
124 print_node(node->funcall.args[i]);
125 if (i < n_args - 1) {
126 printf(" ");
127 }
128 }
129 printf(")");
130 } break;
131 default: { printf("{#unknown#}"); } break;
132 }
133}
diff --git a/src/nodes.h b/src/nodes.h
deleted file mode 100644
index af10573..0000000
--- a/src/nodes.h
+++ /dev/null
@@ -1,88 +0,0 @@
1#ifndef BDL_NODES_H
2#define BDL_NODES_H
3
4typedef enum NodeType {
5 NODE_BUILTIN,
6 NODE_NUMBER,
7 NODE_BOOL,
8 NODE_STRING,
9 NODE_SYMBOL,
10 NODE_TYPE,
11 NODE_DEF,
12 NODE_SET,
13 NODE_FUN,
14 NODE_BLOCK,
15 NODE_IF,
16 NODE_FUNCALL,
17} NodeType;
18
19typedef struct Node {
20 size_t id;
21 NodeType type;
22 size_t line;
23 size_t col;
24 struct Type *expr_type;
25
26 union {
27 // Numbers.
28 struct {
29 bool negative;
30 size_t integral;
31 size_t fractional;
32 } number;
33
34 // String/symbol/type.
35 StringView string;
36
37 // Boolean.
38 bool boolean;
39
40 // Builtin primitive.
41 struct {
42 TokenType type;
43 struct Node **args;
44 } builtin;
45
46 // Function call.
47 struct {
48 struct Node *name;
49 struct Node **args;
50 } funcall;
51
52 // Variable definition.
53 struct {
54 struct Node *symbol;
55 struct Node *value;
56 struct Node *type;
57 } def;
58
59 // Variable assignment.
60 struct {
61 struct Node *symbol;
62 struct Node *value;
63 } set;
64
65 // Function definition.
66 struct {
67 struct Node *name;
68 struct Node **param_names;
69 struct Node **param_types;
70 struct Node *return_type;
71 struct Node *body;
72 } fun;
73
74 // Block statements.
75 struct {
76 struct Node **expr;
77 } block;
78
79 // If statement.
80 struct {
81 struct Node *cond;
82 struct Node *expr_true;
83 struct Node *expr_false;
84 } ifexpr;
85 };
86} Node;
87
88#endif // BDL_NODES_H
diff --git a/src/string_view.c b/src/string_view.c
deleted file mode 100644
index 4e9df5c..0000000
--- a/src/string_view.c
+++ /dev/null
@@ -1,49 +0,0 @@
1#include "string_view.h"
2
3char
4sv_next(StringView *sv) {
5 if (sv->n == 0) {
6 return '\0';
7 }
8 char c = sv->start[0];
9 sv->start++;
10 sv->n--;
11 return c;
12}
13
14void
15sv_rewind(StringView *sv) {
16 if (sv->start == 0) {
17 return;
18 }
19 sv->start--;
20 sv->n++;
21}
22
23char
24sv_peek(const StringView *sv) {
25 if (sv->n == 0) {
26 return '\0';
27 }
28 return sv->start[0];
29}
30
31bool
32sv_equal(const StringView *a, const StringView *b) {
33 if (a->n != b->n) {
34 return false;
35 }
36 for (size_t i = 0; i < a->n; i++) {
37 if (a->start[i] != b->start[i]) {
38 return false;
39 }
40 }
41 return true;
42}
43
44void
45sv_write(const StringView *sv) {
46 for (size_t i = 0; i < sv->n; i++) {
47 putchar(sv->start[i]);
48 }
49}
diff --git a/src/string_view.h b/src/string_view.h
deleted file mode 100644
index cb0f488..0000000
--- a/src/string_view.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#ifndef BDL_STRINGVIEW_H
2#define BDL_STRINGVIEW_H
3
4#include "common.h"
5
6typedef struct StringView {
7 char *start;
8 size_t n;
9} StringView;
10
11// Consume a character in the stream.
12char sv_next(StringView *sv);
13
14// Rewind a character in the stream.
15void sv_rewind(StringView *sv);
16
17// Check what is the current character in the stream.
18char sv_peek(const StringView *sv);
19
20// Compare if the arguments are the same.
21bool sv_equal(const StringView *a, const StringView *b);
22
23// Write a character to the given output stream.
24void sv_write(const StringView *sv);
25
26#define STRING(STR) (StringView){(STR), sizeof(STR) - 1}
27
28#endif // BDL_STRINGVIEW_H
diff --git a/src/viz.c b/src/viz.c
deleted file mode 100644
index ebe1a4c..0000000
--- a/src/viz.c
+++ /dev/null
@@ -1,350 +0,0 @@
1static const char* node_str[] = {
2 [NODE_BUILTIN] = "BUILTIN",
3 [NODE_NUMBER] = "NUMBER",
4 [NODE_BOOL] = "BOOL",
5 [NODE_STRING] = "STRING",
6 [NODE_SYMBOL] = "SYMBOL",
7 [NODE_TYPE] = "TYPE",
8 [NODE_DEF] = "DEF",
9 [NODE_SET] = "SET",
10 [NODE_FUN] = "FUN",
11 [NODE_BLOCK] = "BLOCK",
12 [NODE_IF] = "IF",
13 [NODE_FUNCALL] = "FUNCALL",
14};
15
16void
17viz_node(Node *node) {
18 if (node == NULL) {
19 return;
20 }
21 printf("%zu [width=2.5,shape=Mrecord,label=\"", node->id);
22 printf("<top> %s -- [%4ld:%-4ld] ", node_str[node->type], node->line, node->col);
23 if (node->expr_type != NULL) {
24 printf("| T: ");
25 sv_write(&node->expr_type->name);
26 }
27 switch (node->type) {
28 case NODE_NUMBER: {
29 printf("| Value: ");
30 if (node->number.negative) {
31 printf("-");
32 }
33 if (node->number.fractional != 0) {
34 printf("%zu.%zu", node->number.integral, node->number.fractional);
35 } else {
36 printf("%zu", node->number.integral);
37 }
38 printf("\"];\n");
39 } break;
40 case NODE_SYMBOL:
41 case NODE_TYPE:
42 case NODE_STRING: {
43 printf(" | Value: ");
44 sv_write(&node->string);
45 printf("\"];\n");
46 } break;
47 case NODE_BOOL: {
48 printf(" | Value: ");
49 if (node->boolean) {
50 printf("true");
51 } else {
52 printf("false");
53 }
54 printf("\"];\n");
55 } break;
56 case NODE_BUILTIN: {
57 printf(" | Name: %s", token_str[node->builtin.type]);
58 printf(" | <args> Args: ");
59 printf("\"];\n");
60 size_t n_args = array_size(node->builtin.args);
61 for (size_t i = 0; i < n_args; ++i) {
62 viz_node(node->builtin.args[i]);
63 printf("%zu:args:e->%zu:top:w;\n", node->id, node->builtin.args[i]->id);
64 }
65 } break;
66 case NODE_DEF: {
67 printf(" | Name: ");
68 sv_write(&node->def.symbol->string);
69 printf(" | Type: ");
70 sv_write(&node->def.type->string);
71 printf(" | <val> Expr: ");
72 printf("\"];\n");
73 viz_node(node->def.value);
74 printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
75 } break;
76 case NODE_SET: {
77 printf(" | Name: ");
78 sv_write(&node->set.symbol->string);
79 printf(" | <val> Expr: ");
80 printf("\"];\n");
81 viz_node(node->set.value);
82 printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
83 } break;
84 case NODE_BLOCK: {
85 printf(" | <expr> Exprs: ");
86 printf("\"];\n");
87 size_t n_expr = array_size(node->block.expr);
88 for (size_t i = 0; i < n_expr; ++i) {
89 viz_node(node->block.expr[i]);
90 printf("%zu:expr:e->%zu:top:w;\n", node->id, node->block.expr[i]->id);
91 }
92 } break;
93 case NODE_IF: {
94 printf(" | <cond> Cond: ");
95 printf(" | <t> ExprTrue:");
96 if (node->ifexpr.expr_false != NULL) {
97 printf(" | <f> ExprFalse: ");
98 }
99 printf("\"];\n");
100 viz_node(node->ifexpr.cond);
101 printf("%zu:cond:e->%zu:top:w;\n", node->id, node->ifexpr.cond->id);
102 viz_node(node->ifexpr.expr_true);
103 printf("%zu:t:e->%zu:top:w;\n", node->id, node->ifexpr.expr_true->id);
104 if (node->ifexpr.expr_false != NULL) {
105 viz_node(node->ifexpr.expr_false);
106 printf("%zu:f:e->%zu:top:w;\n", node->id, node->ifexpr.expr_false->id);
107 }
108 } break;
109 case NODE_FUN: {
110 printf(" | Name: ");
111 sv_write(&node->fun.name->string);
112 printf(" | Type: ");
113 printf("(");
114 size_t n_params = array_size(node->fun.param_names);
115 for (size_t i = 0; i < n_params; ++i) {
116 printf(":");
117 sv_write(&node->fun.param_types[i]->string);
118 if (i < n_params - 1) {
119 printf(" ");
120 }
121 }
122 printf("):");
123 sv_write(&node->fun.return_type->string);
124 if (n_params > 0) {
125 printf(" | Parameters: (");
126 for (size_t i = 0; i < n_params; ++i) {
127 sv_write(&node->fun.param_names[i]->string);
128 if (i < n_params - 1) {
129 printf(" ");
130 }
131 }
132 printf(")");
133 }
134 printf(" | <bod> Body: ");
135 printf("\"];\n");
136 viz_node(node->fun.body);
137 printf("%zu:bod:e->%zu:top:w;\n", node->id, node->fun.body->id);
138 } break;
139 case NODE_FUNCALL: {
140 printf(" | Name: ");
141 sv_write(&node->funcall.name->string);
142 printf(" | <args> Args: ");
143 printf("\"];\n");
144 size_t n_args = array_size(node->funcall.args);
145 for (size_t i = 0; i < n_args; ++i) {
146 viz_node(node->funcall.args[i]);
147 printf("%zu:args:e->%zu:top:w;\n", node->id,
148 node->funcall.args[i]->id);
149 }
150 } break;
151 }
152}
153
154void
155viz_ast(Root *roots) {
156 if (roots == NULL) {
157 return;
158 }
159 printf("digraph ast {\n");
160 printf("rankdir=LR;\n");
161 printf("ranksep=\"0.95 equally\";\n");
162 printf("nodesep=\"0.5 equally\";\n");
163 printf("overlap=scale;\n");
164 printf("bgcolor=\"transparent\";\n");
165 for (size_t i = 0; i < array_size(roots); ++i) {
166 printf("subgraph %zu {\n", i);
167 Node *root = roots[array_size(roots) - 1 - i];
168 viz_node(root);
169 printf("}\n");
170 }
171 printf("}\n");
172}
173
174void
175viz_symtables(Scope **scopes) {
176 printf("digraph symtables {\n");
177 printf("rankdir=RL;\n");
178 printf("bgcolor=\"transparent\";\n");
179 for (size_t i = 0; i < array_size(scopes); ++i) {
180 Scope *scope = scopes[i];
181 if (array_size(scope->symbols->pairs) == 0) {
182 continue;
183 }
184 printf("%zu [shape=none,label=<", scope->id);
185 printf("<table border=\"1\" cellborder=\"0\">\n");
186 printf("<tr><td>NAME</td><td>KIND</td><td>TYPE</td></tr>");
187 for (size_t j = 0; j < array_cap(scope->symbols->pairs); ++j) {
188 HashTablePair pair = scope->symbols->pairs[j];
189 if (pair.key == NULL) {
190 continue;
191 }
192 Symbol *sym = pair.value;
193 printf("<tr>");
194 printf("<td>");
195 print_node(sym->name);
196 printf("</td>");
197 switch (sym->type) {
198 case SYMBOL_PAR: {
199 printf("<td>par</td>");
200 printf("<td>");
201 print_node(sym->var.type);
202 printf("</td>");
203 } break;
204 case SYMBOL_VAR: {
205 printf("<td>var</td>");
206 printf("<td>");
207 print_node(sym->var.type);
208 printf("</td>");
209 } break;
210 case SYMBOL_FUN: {
211 printf("<td>fun</td>");
212 printf("<td>");
213 printf("(");
214 size_t n_params = array_size(sym->fun.param_types);
215 for (size_t k = 0; k < n_params; ++k) {
216 print_node(sym->fun.param_types[k]);
217 if (k < n_params - 1) {
218 printf(" ");
219 }
220 }
221 printf(")");
222 printf(":");
223 print_node(sym->fun.return_type);
224 printf("</td>");
225 } break;
226 }
227 printf("</tr>\n");
228 }
229 printf("</table>\n");
230 printf(">];\n");
231
232 if (scope->parent != NULL) {
233 printf("%zu -> %zu\n", scope->id, scope->parent->id);
234 }
235 }
236 printf("}\n");
237}
238
239static const char* basm_op_str[] = {
240 [OP_ADD] = "add ",
241 [OP_SUB] = "sub ",
242 [OP_MUL] = "mul ",
243 [OP_DIV] = "div ",
244 [OP_MOD] = "mod ",
245 [OP_LD8] = "ld8 ",
246 [OP_LD16] = "ld16 ",
247 [OP_LD32] = "ld32 ",
248 [OP_LD64] = "ld64 ",
249 [OP_ST8] = "st8 ",
250 [OP_ST16] = "st16 ",
251 [OP_ST32] = "st32 ",
252 [OP_ST64] = "st64 ",
253 [OP_CP8] = "cp8 ",
254 [OP_CP16] = "cp16 ",
255 [OP_CP32] = "cp32 ",
256 [OP_CP64] = "cp64 ",
257 [OP_NOT] = "not ",
258 [OP_AND] = "and ",
259 [OP_OR] = "or ",
260 [OP_XOR] = "xor ",
261 [OP_LSHIFT] = "lshift",
262 [OP_RSHIFT] = "rshift",
263 [OP_LROT] = "lrot ",
264 [OP_RROT] = "rrot ",
265 [OP_LABEL] = "lab ",
266 [OP_JMP] = "jmp ",
267 [OP_JMP_TRUE] = "jt ",
268 [OP_JMP_FALSE] = "jf ",
269 [OP_JMP_EQ] = "jeq ",
270 [OP_JMP_NEQ] = "jne ",
271 [OP_JMP_GT] = "jgt ",
272 [OP_JMP_LT] = "jlt ",
273 [OP_JMP_GE] = "jge ",
274 [OP_JMP_LE] = "jle ",
275 [OP_RETURN] = "ret ",
276};
277
278void
279viz_operand(Operand op) {
280 switch (op.type) {
281 case OP_TYPE_LABEL: {
282 printf("l%zu", op.id);
283 } break;
284 case OP_TYPE_REG: {
285 printf("r%zu", op.id);
286 } break;
287 case OP_TYPE_CONST: {
288 printf("%lld", op.constant.uval);
289 } break;
290 }
291}
292
293void
294viz_instruction(Instruction *inst, LineInfo *line) {
295 printf("[%6ld:%-6ld] ", line->line, line->col);
296 printf("%s", basm_op_str[inst->op]);
297 switch (inst->op) {
298 case OP_ST8:
299 case OP_ST16:
300 case OP_ST32:
301 case OP_ST64:
302 case OP_LD8:
303 case OP_LD16:
304 case OP_LD32:
305 case OP_LD64: {
306 printf(" ");
307 viz_operand(inst->dst);
308 printf(", ");
309 viz_operand(inst->src_a);
310 if (inst->src_a.type != OP_TYPE_CONST) {
311 printf(", ");
312 viz_operand(inst->src_b);
313 }
314 } break;
315 case OP_RETURN:
316 case OP_JMP:
317 case OP_LABEL: {
318 printf(" ");
319 viz_operand(inst->dst);
320 } break;
321 case OP_CP8:
322 case OP_CP16:
323 case OP_CP32:
324 case OP_CP64:
325 case OP_JMP_TRUE:
326 case OP_JMP_FALSE: {
327 printf(" ");
328 viz_operand(inst->dst);
329 printf(", ");
330 viz_operand(inst->src_a);
331 } break;
332 default: {
333 printf(" ");
334 viz_operand(inst->dst);
335 printf(", ");
336 viz_operand(inst->src_a);
337 printf(", ");
338 viz_operand(inst->src_b);
339 } break;
340 }
341 printf("\n");
342}
343
344void
345viz_basm(ProgramBASM *program) {
346 for (size_t i = 0; i < array_size(program->inst); ++i) {
347 viz_instruction(&program->inst[i], &program->lines[i]);
348 }
349
350}
diff --git a/src/compiler.h b/src/x86asm_compiler.h
index 6ca4467..6ca4467 100644
--- a/src/compiler.h
+++ b/src/x86asm_compiler.h