aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/environment.c59
-rw-r--r--src/bootstrap/environment.h7
-rw-r--r--src/bootstrap/gc.c12
-rw-r--r--src/bootstrap/hashtable.h20
-rwxr-xr-xsrc/bootstrap/main.c553
5 files changed, 280 insertions, 371 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c
index cb9e2f0..dd4a648 100644
--- a/src/bootstrap/environment.c
+++ b/src/bootstrap/environment.c
@@ -7,8 +7,7 @@ env_create(Environment *parent) {
7 Environment *env = alloc_env(); 7 Environment *env = alloc_env();
8 env->parent = parent; 8 env->parent = parent;
9 env->marked = false; 9 env->marked = false;
10 env->entries = NULL; 10 env->table = ht_init();
11 array_init(env->entries, ENV_BUF_CAP);
12 return env; 11 return env;
13} 12}
14 13
@@ -23,18 +22,15 @@ env_add_symbol(Environment *env, Object *symbol, Object *value) {
23 }); 22 });
24 return; 23 return;
25 } 24 }
26 EnvEntry entry = (EnvEntry){symbol, value}; 25 ht_insert(env->table, symbol, value);
27 array_push(env->entries, entry);
28} 26}
29 27
30Object * 28Object *
31env_lookup(Environment *env, Object *symbol) { 29env_lookup(Environment *env, Object *symbol) {
32 while (env != NULL) { 30 while (env != NULL) {
33 for (size_t i = 0; i < array_size(env->entries); i++) { 31 Object *obj = ht_lookup(env->table, symbol);
34 EnvEntry entry = env->entries[i]; 32 if (obj != NULL) {
35 if (obj_eq(symbol, entry.symbol)) { 33 return obj;
36 return entry.value;
37 }
38 } 34 }
39 env = env->parent; 35 env = env->parent;
40 } 36 }
@@ -44,12 +40,10 @@ env_lookup(Environment *env, Object *symbol) {
44Object * 40Object *
45env_update(Environment *env, Object *symbol, Object *value) { 41env_update(Environment *env, Object *symbol, Object *value) {
46 while (env != NULL) { 42 while (env != NULL) {
47 for (size_t i = 0; i < array_size(env->entries); i++) { 43 Object *obj = ht_lookup(env->table, symbol);
48 EnvEntry entry = env->entries[i]; 44 if (obj != NULL) {
49 if (obj_eq(symbol, entry.symbol)) { 45 ht_insert(env->table, symbol, value);
50 env->entries[i].value = value; 46 return obj_nil;
51 return obj_nil;
52 }
53 } 47 }
54 env = env->parent; 48 env = env->parent;
55 } 49 }
@@ -60,43 +54,18 @@ env_update(Environment *env, Object *symbol, Object *value) {
60 return obj_err; 54 return obj_err;
61} 55}
62 56
63ssize_t
64env_index_current(Environment *env, Object *symbol) {
65 for (size_t i = 0; i < array_size(env->entries); i++) {
66 EnvEntry entry = env->entries[i];
67 if (obj_eq(symbol, entry.symbol)) {
68 return i;
69 }
70 }
71 return -1;
72}
73
74void 57void
75env_add_or_update_current(Environment *env, Object *symbol, Object *value) { 58env_add_or_update_current(Environment *env, Object *symbol, Object *value) {
76 ssize_t index = env_index_current(env, symbol); 59 ht_insert(env->table, symbol, value);
77 if (index == -1) {
78 env_add_symbol(env, symbol, value);
79 } else {
80 env->entries[index].value = value;
81 }
82} 60}
83 61
84Environment * 62Environment *
85env_extend(Environment *parent, Environment *extra) { 63env_extend(Environment *parent, Environment *extra) {
86 Environment *env = parent; 64 Environment *env = parent;
87 for (size_t i = 0; i < array_size(extra->entries); i++) { 65 HashTablePair *pairs = extra->table->pairs;
88 EnvEntry entry = extra->entries[i]; 66 for (size_t i = 0; i < array_cap(pairs); i++) {
89 Environment *tmp = env; 67 if (pairs[i].key != NULL) {
90 bool found = false; 68 ht_insert(env->table, pairs[i].key, pairs[i].value);
91 while (tmp != NULL) {
92 if (env_index_current(tmp, entry.symbol) != -1) {
93 found = true;
94 break;
95 }
96 tmp = tmp->parent;
97 }
98 if (!found) {
99 env_add_symbol(env, entry.symbol, entry.value);
100 } 69 }
101 } 70 }
102 return env; 71 return env;
diff --git a/src/bootstrap/environment.h b/src/bootstrap/environment.h
index 2d6a34e..5ee21ad 100644
--- a/src/bootstrap/environment.h
+++ b/src/bootstrap/environment.h
@@ -3,14 +3,9 @@
3 3
4#include "objects.h" 4#include "objects.h"
5 5
6typedef struct EnvEntry {
7 Object *symbol;
8 Object *value;
9} EnvEntry;
10
11typedef struct Environment { 6typedef struct Environment {
12 struct Environment *parent; 7 struct Environment *parent;
13 EnvEntry *entries; 8 HashTable *table;
14 bool marked; 9 bool marked;
15} Environment; 10} Environment;
16 11
diff --git a/src/bootstrap/gc.c b/src/bootstrap/gc.c
index a188279..358a07e 100644
--- a/src/bootstrap/gc.c
+++ b/src/bootstrap/gc.c
@@ -63,10 +63,12 @@ mark_environment(Environment *env) {
63 return; 63 return;
64 } 64 }
65 env->marked = true; 65 env->marked = true;
66 for (size_t i = 0; i < array_size(env->entries); i++) { 66 HashTablePair *pairs = env->table->pairs;
67 EnvEntry *entry = &env->entries[i]; 67 for (size_t i = 0; i < array_cap(pairs); i++) {
68 mark_obj(entry->symbol); 68 if (pairs[i].key != NULL) {
69 mark_obj(entry->value); 69 mark_obj(pairs[i].key);
70 mark_obj(pairs[i].value);
71 }
70 } 72 }
71} 73}
72 74
@@ -120,7 +122,7 @@ mark_and_sweep(void) {
120 for (size_t i = 0; i < array_cap(gc.envs); i++) { 122 for (size_t i = 0; i < array_cap(gc.envs); i++) {
121 Environment *env = &gc.envs[i]; 123 Environment *env = &gc.envs[i];
122 if (!env->marked) { 124 if (!env->marked) {
123 array_free(env->entries); 125 ht_free(env->table);
124 gc.free_envs.offsets[array_head(gc.free_envs.offsets)->size++] = i; 126 gc.free_envs.offsets[array_head(gc.free_envs.offsets)->size++] = i;
125 } 127 }
126 env->marked = false; 128 env->marked = false;
diff --git a/src/bootstrap/hashtable.h b/src/bootstrap/hashtable.h
index ca4ced8..ea24d04 100644
--- a/src/bootstrap/hashtable.h
+++ b/src/bootstrap/hashtable.h
@@ -35,7 +35,6 @@ _xor_shift_hash(const char *key, size_t n) {
35 uint64_t hash = 0x65d9d65f6a19574f; 35 uint64_t hash = 0x65d9d65f6a19574f;
36 char *last = (char *)key + n; 36 char *last = (char *)key + n;
37 while (key != last) { 37 while (key != last) {
38 putchar(*key);
39 hash ^= (uint64_t)*key++; 38 hash ^= (uint64_t)*key++;
40 hash = (hash << 8) | (hash >> (64 - 8)); 39 hash = (hash << 8) | (hash >> (64 - 8));
41 } 40 }
@@ -50,7 +49,7 @@ _fibonacci_hash(uint64_t hash, size_t shift_amount) {
50 49
51uint64_t 50uint64_t
52ht_hash(const HashTable *table, const Object *key) { 51ht_hash(const HashTable *table, const Object *key) {
53 uint64_t hash; 52 uint64_t hash = 0;
54 switch (key->type) { 53 switch (key->type) {
55 case OBJ_TYPE_FIXNUM: { 54 case OBJ_TYPE_FIXNUM: {
56 hash = key->fixnum; 55 hash = key->fixnum;
@@ -178,23 +177,6 @@ ht_lookup(const HashTable *table, const Object *key) {
178} 177}
179 178
180void 179void
181ht_debug(HashTable *table) {
182 HashTablePair *pairs = table->pairs;
183 for (size_t i = 0; i < array_cap(pairs); i++) {
184 printf("i: %ld ", i);
185 if (pairs[i].key == NULL) {
186 printf("EMPTY\n");
187 } else {
188 printf("key: ");
189 display(pairs[i].key);
190 printf(" value: ");
191 display(pairs[i].value);
192 printf("\n");
193 }
194 }
195}
196
197void
198ht_free(HashTable *table) { 180ht_free(HashTable *table) {
199 if (table == NULL) { 181 if (table == NULL) {
200 return; 182 return;
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c
index 1cb7c82..a5888fd 100755
--- a/src/bootstrap/main.c
+++ b/src/bootstrap/main.c
@@ -21,307 +21,268 @@
21#include "read_line.c" 21#include "read_line.c"
22#include "string_view.c" 22#include "string_view.c"
23 23
24int main(void) { 24void
25 // Initialize GC. 25init(void) {
26 // Initialize garbage collector.
26 gc_init(); 27 gc_init();
27 28
28 // Initialize key-value objects. 29 // Initialize singletons.
29 Object *k1 = MAKE_SYM("Alice"); 30 obj_nil = alloc_object(OBJ_TYPE_NIL);
30 Object *k2 = MAKE_SYM("Bob"); 31 obj_true = alloc_object(OBJ_TYPE_BOOL);
31 Object *k3 = MAKE_SYM("Dog"); 32 obj_false = alloc_object(OBJ_TYPE_BOOL);
32 Object *v1 = make_fixnum(10); 33 obj_err = alloc_object(OBJ_TYPE_ERR);
33 Object *v2 = make_fixnum(49); 34 obj_quote = make_symbol((StringView){"quote", 5});
34 Object *v3 = make_fixnum(333); 35 proc_if = alloc_object(OBJ_TYPE_ERR);
35 36 push_root(obj_nil);
36 // Initialize hash table. 37 push_root(obj_true);
37 HashTable *table = ht_init(); 38 push_root(obj_false);
38 39 push_root(obj_err);
39 // Add some key-value pairs. 40 push_root(obj_quote);
40 ht_insert(table, k1, v1); 41 push_root(proc_if);
41 ht_insert(table, k2, v2); 42
42 ht_insert(table, k3, v3); 43 // Global environment.
43 44 global_env = env_create(NULL);
44 // Test lookups. 45 // TODO: make sure we create symbols and strings only once (interning
45 Object *alice_val = ht_lookup(table, k1); 46 // strings?)
46 Object *bob_val = ht_lookup(table, MAKE_SYM("Bob")); 47 push_active_env(global_env);
47 Object *dog_val = ht_lookup(table, k3); 48
48 49 // Primitive symbols.
49 if (v1 == alice_val) { 50 MAKE_ENV_VAR(global_env, "else", obj_true);
50 printf("Alice match!\n"); 51 MAKE_ENV_VAR(global_env, "nil", obj_nil);
52 MAKE_ENV_VAR(global_env, "if", proc_if);
53
54 // Primitive procedures.
55 MAKE_ENV_PROC(global_env, "eval", proc_eval);
56 MAKE_ENV_PROC(global_env, "quote", proc_quote);
57 MAKE_ENV_PROC(global_env, "car", proc_car);
58 MAKE_ENV_PROC(global_env, "cdr", proc_cdr);
59 MAKE_ENV_PROC(global_env, "cons", proc_cons);
60 MAKE_ENV_PROC(global_env, "list", proc_list);
61 MAKE_ENV_PROC(global_env, "+", proc_sum);
62 MAKE_ENV_PROC(global_env, "-", proc_sub);
63 MAKE_ENV_PROC(global_env, "*", proc_mul);
64 MAKE_ENV_PROC(global_env, "/", proc_div);
65 MAKE_ENV_PROC(global_env, "%", proc_mod);
66 MAKE_ENV_PROC(global_env, "print", proc_print);
67 MAKE_ENV_PROC(global_env, "display", proc_display);
68 MAKE_ENV_PROC(global_env, "newline", proc_newline);
69 MAKE_ENV_PROC(global_env, "boolean?", proc_is_boolean);
70 MAKE_ENV_PROC(global_env, "nil?", proc_is_nil);
71 MAKE_ENV_PROC(global_env, "symbol?", proc_is_symbol);
72 MAKE_ENV_PROC(global_env, "string?", proc_is_string);
73 MAKE_ENV_PROC(global_env, "fixnum?", proc_is_fixnum);
74 MAKE_ENV_PROC(global_env, "pair?", proc_is_pair);
75 MAKE_ENV_PROC(global_env, "procedure?", proc_is_procedure);
76 MAKE_ENV_PROC(global_env, "error?", proc_is_error);
77 MAKE_ENV_PROC(global_env, "not", proc_not);
78 MAKE_ENV_PROC(global_env, "and", proc_and);
79 MAKE_ENV_PROC(global_env, "or", proc_or);
80 MAKE_ENV_PROC(global_env, "cond", proc_cond);
81 MAKE_ENV_PROC(global_env, "<", proc_num_less_than);
82 MAKE_ENV_PROC(global_env, "<=", proc_num_lesseq_than);
83 MAKE_ENV_PROC(global_env, ">", proc_num_greater_than);
84 MAKE_ENV_PROC(global_env, ">=", proc_num_greatereq_than);
85 MAKE_ENV_PROC(global_env, "=", proc_num_equal);
86 MAKE_ENV_PROC(global_env, "eq?", proc_equal);
87 MAKE_ENV_PROC(global_env, "def", proc_define);
88 MAKE_ENV_PROC(global_env, "set!", proc_set);
89 MAKE_ENV_PROC(global_env, "lambda", proc_lambda);
90 MAKE_ENV_PROC(global_env, "fun", proc_fun);
91
92 // Runtime procedures.
93 MAKE_ENV_PROC(global_env, "supress-errors", proc_supress_errors);
94}
95
96void
97process_source(const StringView *source) {
98 Token *tokens = tokenize(source);
99 if (errors_n != 0) {
100 if (tokens != NULL) {
101 array_free(tokens);
102 }
103 return;
104 }
105
106 Visitor visitor = (Visitor){
107 .tokens = tokens,
108 .current = 0,
109 };
110 while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) {
111 // Check the root node stack size before parsing
112 size_t root_stack_size = array_size(gc.roots);
113 Object *root = parse_tree(&visitor);
114 array_head(gc.roots)->size = root_stack_size;
115 if (root == obj_err || errors_n != 0) {
116 break;
117 }
118 push_root(root);
119
120 Object *result = eval(global_env, root);
121 if (result != obj_nil) {
122 display(result);
123 printf("\n");
124 }
125 pop_root();
51 } 126 }
52 if (v2 == bob_val) { 127
53 printf("Bob match!\n"); 128 if (tokens != NULL) {
129 array_free(tokens);
130 }
131}
132
133#define REPL_PROMPT "bdl> "
134
135void
136run_repl(void) {
137 printf("BDL REPL (Press Ctrl-D or Ctrl-C to exit)\n");
138 while (true) {
139 printf(REPL_PROMPT);
140 StringView sv = read_line();
141 if (sv.start == NULL) {
142 return;
143 }
144 process_source(&sv);
145
146 // Check if there were any errors.
147 if (errors_n != 0 && !supress_errors) {
148 for (size_t i = 0; i < errors_n; i++) {
149 Error err = errors[i];
150 for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) {
151 putchar(' ');
152 }
153 printf("|\n");
154 for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) {
155 putchar(' ');
156 }
157 printf("%s\n", error_msgs[err.value]);
158 }
159 errors_n = 0;
160 continue;
161 }
162 }
163}
164
165void
166run_file(char *file_name) {
167 FILE *file = fopen(file_name, "r");
168 if (!file) {
169 fprintf(stderr, "error: couldn't open input file: %s\n", file_name);
170 exit(EXIT_FAILURE);
171 }
172
173 // Read entire file into memory.
174 fseek(file, 0, SEEK_END);
175 size_t file_size = ftell(file);
176 fseek(file, 0, SEEK_SET);
177
178 char *source = malloc(file_size + 1);
179 fread(source, 1, file_size, file);
180 source[file_size] = 0;
181
182 StringView sv = (StringView){
183 .start = source,
184 .n = file_size,
185 };
186
187 process_source(&sv);
188
189 // Check if there were any errors.
190 if (errors_n != 0 && !supress_errors) {
191 for (size_t i = 0; i < errors_n; i++) {
192 Error err = errors[i];
193 fprintf(stderr, "%s", file_name);
194 if (err.line != 0) {
195 fprintf(stderr, ":%ld:%ld", err.line, err.col);
196 }
197 fprintf(stderr, ": %s\n", error_msgs[err.value]);
198 }
199 errors_n = 0;
200 }
201
202 free(source);
203 fclose(file);
204}
205
206#define STDIN_BUF_CAP 16
207
208void
209run_stdin(void) {
210 size_t buf_size = 0;
211 char *source = NULL;
212 array_init(source, STDIN_BUF_CAP);
213
214 char c;
215 while ((c = getchar()) != EOF) {
216 array_push(source, c);
217 buf_size++;
54 } 218 }
55 if (v3 == dog_val) { 219
56 printf("Dog match!\n"); 220 StringView sv = (StringView){
221 .start = source,
222 .n = buf_size,
223 };
224
225 process_source(&sv);
226
227 // Check if there were any errors.
228 if (errors_n != 0 && !supress_errors) {
229 for (size_t i = 0; i < errors_n; i++) {
230 Error err = errors[i];
231 fprintf(stderr, "stdin");
232 if (err.line != 0) {
233 fprintf(stderr, ":%ld:%ld", err.line, err.col);
234 }
235 fprintf(stderr, ": %s\n", error_msgs[err.value]);
236 }
237 errors_n = 0;
57 } 238 }
58 239
59 ht_debug(table); 240 array_free(source);
60 return 0; 241}
242
243#ifndef BIN_NAME
244#define BIN_NAME "bdl"
245#endif
246
247void
248print_usage(void) {
249 printf("Usage: %s [options] <filename filename ...>\n", BIN_NAME);
250 printf("\n");
251 printf("\t-i\tInteractive mode (REPL).\n");
252 printf("\n");
61} 253}
62 254
63// void 255int
64// init(void) { 256main(int argc, char *argv[]) {
65// // Initialize garbage collector. 257 init();
66// gc_init(); 258
67 259 int option;
68// // Initialize singletons. 260 while ((option = getopt(argc, argv, "i")) != -1) {
69// obj_nil = alloc_object(OBJ_TYPE_NIL); 261 switch (option) {
70// obj_true = alloc_object(OBJ_TYPE_BOOL); 262 case 'i': {
71// obj_false = alloc_object(OBJ_TYPE_BOOL); 263 // Interactive mode.
72// obj_err = alloc_object(OBJ_TYPE_ERR); 264 run_repl();
73// obj_quote = make_symbol((StringView){"quote", 5}); 265 return EXIT_SUCCESS;
74// proc_if = alloc_object(OBJ_TYPE_ERR); 266 } break;
75// push_root(obj_nil); 267 default: {
76// push_root(obj_true); 268 print_usage();
77// push_root(obj_false); 269 return EXIT_FAILURE;
78// push_root(obj_err); 270 } break;
79// push_root(obj_quote); 271 }
80// push_root(proc_if); 272 }
81 273
82// // Global environment. 274 // Run from stdin.
83// global_env = env_create(NULL); 275 if (optind == argc) {
84// // TODO: make sure we create symbols and strings only once (interning 276 run_stdin();
85// // strings?) 277 return EXIT_SUCCESS;
86// push_active_env(global_env); 278 }
87 279
88// // Primitive symbols. 280 // Run from file.
89// MAKE_ENV_VAR(global_env, "else", obj_true); 281 while (optind < argc) {
90// MAKE_ENV_VAR(global_env, "nil", obj_nil); 282 char *file_name = argv[optind];
91// MAKE_ENV_VAR(global_env, "if", proc_if); 283 run_file(file_name);
92 284 optind++;
93// // Primitive procedures. 285 }
94// MAKE_ENV_PROC(global_env, "eval", proc_eval); 286
95// MAKE_ENV_PROC(global_env, "quote", proc_quote); 287 return EXIT_SUCCESS;
96// MAKE_ENV_PROC(global_env, "car", proc_car); 288}
97// MAKE_ENV_PROC(global_env, "cdr", proc_cdr);
98// MAKE_ENV_PROC(global_env, "cons", proc_cons);
99// MAKE_ENV_PROC(global_env, "list", proc_list);
100// MAKE_ENV_PROC(global_env, "+", proc_sum);
101// MAKE_ENV_PROC(global_env, "-", proc_sub);
102// MAKE_ENV_PROC(global_env, "*", proc_mul);
103// MAKE_ENV_PROC(global_env, "/", proc_div);
104// MAKE_ENV_PROC(global_env, "%", proc_mod);
105// MAKE_ENV_PROC(global_env, "print", proc_print);
106// MAKE_ENV_PROC(global_env, "display", proc_display);
107// MAKE_ENV_PROC(global_env, "newline", proc_newline);
108// MAKE_ENV_PROC(global_env, "boolean?", proc_is_boolean);
109// MAKE_ENV_PROC(global_env, "nil?", proc_is_nil);
110// MAKE_ENV_PROC(global_env, "symbol?", proc_is_symbol);
111// MAKE_ENV_PROC(global_env, "string?", proc_is_string);
112// MAKE_ENV_PROC(global_env, "fixnum?", proc_is_fixnum);
113// MAKE_ENV_PROC(global_env, "pair?", proc_is_pair);
114// MAKE_ENV_PROC(global_env, "procedure?", proc_is_procedure);
115// MAKE_ENV_PROC(global_env, "error?", proc_is_error);
116// MAKE_ENV_PROC(global_env, "not", proc_not);
117// MAKE_ENV_PROC(global_env, "and", proc_and);
118// MAKE_ENV_PROC(global_env, "or", proc_or);
119// MAKE_ENV_PROC(global_env, "cond", proc_cond);
120// MAKE_ENV_PROC(global_env, "<", proc_num_less_than);
121// MAKE_ENV_PROC(global_env, "<=", proc_num_lesseq_than);
122// MAKE_ENV_PROC(global_env, ">", proc_num_greater_than);
123// MAKE_ENV_PROC(global_env, ">=", proc_num_greatereq_than);
124// MAKE_ENV_PROC(global_env, "=", proc_num_equal);
125// MAKE_ENV_PROC(global_env, "eq?", proc_equal);
126// MAKE_ENV_PROC(global_env, "def", proc_define);
127// MAKE_ENV_PROC(global_env, "set!", proc_set);
128// MAKE_ENV_PROC(global_env, "lambda", proc_lambda);
129// MAKE_ENV_PROC(global_env, "fun", proc_fun);
130
131// // Runtime procedures.
132// MAKE_ENV_PROC(global_env, "supress-errors", proc_supress_errors);
133// }
134
135// void
136// process_source(const StringView *source) {
137// Token *tokens = tokenize(source);
138// if (errors_n != 0) {
139// if (tokens != NULL) {
140// array_free(tokens);
141// }
142// return;
143// }
144
145// Visitor visitor = (Visitor){
146// .tokens = tokens,
147// .current = 0,
148// };
149// while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) {
150// // Check the root node stack size before parsing
151// size_t root_stack_size = array_size(gc.roots);
152// Object *root = parse_tree(&visitor);
153// array_head(gc.roots)->size = root_stack_size;
154// if (root == obj_err || errors_n != 0) {
155// break;
156// }
157// push_root(root);
158
159// Object *result = eval(global_env, root);
160// if (result != obj_nil) {
161// display(result);
162// printf("\n");
163// }
164// pop_root();
165// }
166
167// if (tokens != NULL) {
168// array_free(tokens);
169// }
170// }
171
172// #define REPL_PROMPT "bdl> "
173
174// void
175// run_repl(void) {
176// printf("BDL REPL (Press Ctrl-D or Ctrl-C to exit)\n");
177// while (true) {
178// printf(REPL_PROMPT);
179// StringView sv = read_line();
180// if (sv.start == NULL) {
181// return;
182// }
183// process_source(&sv);
184
185// // Check if there were any errors.
186// if (errors_n != 0 && !supress_errors) {
187// for (size_t i = 0; i < errors_n; i++) {
188// Error err = errors[i];
189// for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) {
190// putchar(' ');
191// }
192// printf("|\n");
193// for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) {
194// putchar(' ');
195// }
196// printf("%s\n", error_msgs[err.value]);
197// }
198// errors_n = 0;
199// continue;
200// }
201// }
202// }
203
204// void
205// run_file(char *file_name) {
206// FILE *file = fopen(file_name, "r");
207// if (!file) {
208// fprintf(stderr, "error: couldn't open input file: %s\n", file_name);
209// exit(EXIT_FAILURE);
210// }
211
212// // Read entire file into memory.
213// fseek(file, 0, SEEK_END);
214// size_t file_size = ftell(file);
215// fseek(file, 0, SEEK_SET);
216
217// char *source = malloc(file_size + 1);
218// fread(source, 1, file_size, file);
219// source[file_size] = 0;
220
221// StringView sv = (StringView){
222// .start = source,
223// .n = file_size,
224// };
225
226// process_source(&sv);
227
228// // Check if there were any errors.
229// if (errors_n != 0 && !supress_errors) {
230// for (size_t i = 0; i < errors_n; i++) {
231// Error err = errors[i];
232// fprintf(stderr, "%s", file_name);
233// if (err.line != 0) {
234// fprintf(stderr, ":%ld:%ld", err.line, err.col);
235// }
236// fprintf(stderr, ": %s\n", error_msgs[err.value]);
237// }
238// errors_n = 0;
239// }
240
241// free(source);
242// fclose(file);
243// }
244
245// #define STDIN_BUF_CAP 16
246
247// void
248// run_stdin(void) {
249// size_t buf_size = 0;
250// char *source = NULL;
251// array_init(source, STDIN_BUF_CAP);
252
253// char c;
254// while ((c = getchar()) != EOF) {
255// array_push(source, c);
256// buf_size++;
257// }
258
259// StringView sv = (StringView){
260// .start = source,
261// .n = buf_size,
262// };
263
264// process_source(&sv);
265
266// // Check if there were any errors.
267// if (errors_n != 0 && !supress_errors) {
268// for (size_t i = 0; i < errors_n; i++) {
269// Error err = errors[i];
270// fprintf(stderr, "stdin");
271// if (err.line != 0) {
272// fprintf(stderr, ":%ld:%ld", err.line, err.col);
273// }
274// fprintf(stderr, ": %s\n", error_msgs[err.value]);
275// }
276// errors_n = 0;
277// }
278
279// array_free(source);
280// }
281
282// #ifndef BIN_NAME
283// #define BIN_NAME "bdl"
284// #endif
285
286// void
287// print_usage(void) {
288// printf("Usage: %s [options] <filename filename ...>\n", BIN_NAME);
289// printf("\n");
290// printf("\t-i\tInteractive mode (REPL).\n");
291// printf("\n");
292// }
293
294// int
295// main(int argc, char *argv[]) {
296// init();
297
298// int option;
299// while ((option = getopt(argc, argv, "i")) != -1) {
300// switch (option) {
301// case 'i': {
302// // Interactive mode.
303// run_repl();
304// return EXIT_SUCCESS;
305// } break;
306// default: {
307// print_usage();
308// return EXIT_FAILURE;
309// } break;
310// }
311// }
312
313// // Run from stdin.
314// if (optind == argc) {
315// run_stdin();
316// return EXIT_SUCCESS;
317// }
318
319// // Run from file.
320// while (optind < argc) {
321// char *file_name = argv[optind];
322// run_file(file_name);
323// optind++;
324// }
325
326// return EXIT_SUCCESS;
327// }