aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/main.c')
-rwxr-xr-xsrc/bootstrap/main.c553
1 files changed, 257 insertions, 296 deletions
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// }