diff options
Diffstat (limited to 'src/bootstrap/main.c')
-rwxr-xr-x | src/bootstrap/main.c | 124 |
1 files changed, 17 insertions, 107 deletions
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 66c3780..c98f60c 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -1,151 +1,59 @@ | |||
1 | #include <ctype.h> | ||
2 | #include <getopt.h> | 1 | #include <getopt.h> |
2 | #include <stdbool.h> | ||
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <string.h> | ||
6 | |||
7 | #include "shorthand.h" | ||
8 | #include "string_view.c" | ||
9 | #include "readline.c" | ||
10 | #include "lexer.c" | ||
11 | #include "objects.c" | ||
12 | #include "parser.c" | ||
13 | #include "environment.c" | ||
14 | #include "primitives.c" | ||
15 | |||
16 | // FIXME: We are not worried right now about freeing memory, but we should in | ||
17 | // the future. | ||
18 | // TODO: Better error messages. | ||
19 | |||
20 | #define REPL_PROMPT "bdl> " | ||
21 | 5 | ||
22 | void | 6 | void |
23 | init(void) { | 7 | process_input(FILE *file) { |
24 | // Clear env. | 8 | // TODO: Implement. |
25 | for (size_t i = 0; i < ENV_SIZE; i++) { | 9 | getchar(); |
26 | environment[i] = (EnvSymbol){0}; | 10 | (void)file; |
27 | } | ||
28 | |||
29 | // Initialize singletons. | ||
30 | obj_nil = make_empty_list(); | ||
31 | obj_true = make_boolean(true); | ||
32 | obj_false = make_boolean(false); | ||
33 | |||
34 | // Add primitive functions. | ||
35 | environment[env_n++] = (EnvSymbol){MAKE_SYM("+"), make_procedure(proc_add)}; | ||
36 | environment[env_n++] = (EnvSymbol){MAKE_SYM("-"), make_procedure(proc_sub)}; | ||
37 | environment[env_n++] = (EnvSymbol){MAKE_SYM("*"), make_procedure(proc_mul)}; | ||
38 | environment[env_n++] = (EnvSymbol){MAKE_SYM("/"), make_procedure(proc_div)}; | ||
39 | environment[env_n++] = (EnvSymbol){MAKE_SYM("%"), make_procedure(proc_mod)}; | ||
40 | environment[env_n++] = (EnvSymbol){MAKE_SYM("<"), make_procedure(proc_num_less_than)}; | ||
41 | environment[env_n++] = (EnvSymbol){MAKE_SYM(">"), make_procedure(proc_num_greater_than)}; | ||
42 | environment[env_n++] = (EnvSymbol){MAKE_SYM("="), make_procedure(proc_num_equal)}; | ||
43 | environment[env_n++] = (EnvSymbol){MAKE_SYM("<="), make_procedure(proc_num_lesseq_than)}; | ||
44 | environment[env_n++] = (EnvSymbol){MAKE_SYM(">="), make_procedure(proc_num_greatereq_than)}; | ||
45 | environment[env_n++] = (EnvSymbol){MAKE_SYM("null?"), make_procedure(proc_is_null)}; | ||
46 | environment[env_n++] = (EnvSymbol){MAKE_SYM("boolean?"), make_procedure(proc_is_boolean)}; | ||
47 | environment[env_n++] = (EnvSymbol){MAKE_SYM("symbol?"), make_procedure(proc_is_symbol)}; | ||
48 | environment[env_n++] = (EnvSymbol){MAKE_SYM("string?"), make_procedure(proc_is_string)}; | ||
49 | environment[env_n++] = (EnvSymbol){MAKE_SYM("fixnum?"), make_procedure(proc_is_fixnum)}; | ||
50 | environment[env_n++] = (EnvSymbol){MAKE_SYM("pair?"), make_procedure(proc_is_pair)}; | ||
51 | environment[env_n++] = (EnvSymbol){MAKE_SYM("procedure?"), make_procedure(proc_is_procedure)}; | ||
52 | environment[env_n++] = (EnvSymbol){MAKE_SYM("not"), make_procedure(proc_not)}; | ||
53 | environment[env_n++] = (EnvSymbol){MAKE_SYM("and"), make_procedure(proc_and)}; | ||
54 | environment[env_n++] = (EnvSymbol){MAKE_SYM("or"), make_procedure(proc_or)}; | ||
55 | environment[env_n++] = (EnvSymbol){MAKE_SYM("if"), make_procedure(proc_if)}; | ||
56 | environment[env_n++] = (EnvSymbol){MAKE_SYM("else"), obj_true}; | ||
57 | environment[env_n++] = (EnvSymbol){MAKE_SYM("true"), obj_true}; | ||
58 | environment[env_n++] = (EnvSymbol){MAKE_SYM("false"), obj_false}; | ||
59 | environment[env_n++] = (EnvSymbol){MAKE_SYM("nil"), obj_nil}; | ||
60 | environment[env_n++] = (EnvSymbol){MAKE_SYM("cond"), make_procedure(proc_cond)}; | ||
61 | environment[env_n++] = (EnvSymbol){MAKE_SYM("car"), make_procedure(proc_car)}; | ||
62 | environment[env_n++] = (EnvSymbol){MAKE_SYM("cdr"), make_procedure(proc_cdr)}; | ||
63 | environment[env_n++] = (EnvSymbol){MAKE_SYM("cons"), make_procedure(proc_cons)}; | ||
64 | environment[env_n++] = (EnvSymbol){MAKE_SYM("list"), make_procedure(proc_list)}; | ||
65 | environment[env_n++] = (EnvSymbol){MAKE_SYM("eq?"), make_procedure(proc_equal)}; | ||
66 | environment[env_n++] = (EnvSymbol){MAKE_SYM("display"), make_procedure(proc_display)}; | ||
67 | environment[env_n++] = (EnvSymbol){MAKE_SYM("print"), make_procedure(proc_print)}; | ||
68 | } | 11 | } |
69 | 12 | ||
70 | void | 13 | #define REPL_PROMPT "bdl> " |
71 | eval_line(FILE *fd, char delimiter) { | ||
72 | StringView line = read_line(fd, delimiter); | ||
73 | Tokens tokens = tokenize(line); | ||
74 | #if DEBUG | ||
75 | printf("N_TOKENS: %ld\n", tokens.n); | ||
76 | for (size_t i = 0; i < tokens.n; i++) { | ||
77 | printf("\tTYPE: %3d ", tokens.start[i].type); | ||
78 | printf("N: %3ld ", tokens.start[i].value.n); | ||
79 | printf("VALUE: "); | ||
80 | sv_write(tokens.start[i].value); | ||
81 | printf("\n"); | ||
82 | } | ||
83 | #endif | ||
84 | while (tokens.n > 0) { | ||
85 | Object *ast = parse(&tokens); | ||
86 | if (ast) { | ||
87 | #if DEBUG | ||
88 | printf("AST: "); | ||
89 | display(ast); | ||
90 | printf("\n"); | ||
91 | printf("EVAL: "); | ||
92 | #endif | ||
93 | if (display(eval(ast))) { | ||
94 | printf("\n"); | ||
95 | }; | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | 14 | ||
100 | void | 15 | void |
101 | run_repl(void) { | 16 | run_repl(void) { |
102 | printf("BDL REPL (Press Ctrl-C to exit)\n"); | 17 | printf("BDL REPL (Press Ctrl-C to exit)\n"); |
103 | while (true) { | 18 | while (true) { |
104 | printf(REPL_PROMPT); | 19 | printf(REPL_PROMPT); |
105 | eval_line(stdin, '\n'); | 20 | process_input(stdin); |
106 | } | 21 | } |
107 | } | 22 | } |
108 | 23 | ||
109 | void | 24 | void |
110 | run_file(char *file_name) { | 25 | run_file(char *file_name) { |
111 | #if DEBUG | ||
112 | printf("Executing file: %s\n", file_name); | ||
113 | #endif | ||
114 | FILE *fd = fopen(file_name, "r"); | 26 | FILE *fd = fopen(file_name, "r"); |
115 | if (!fd) { | 27 | if (!fd) { |
116 | fprintf(stderr, "couldn't open file: %s\n", file_name); | 28 | fprintf(stderr, "error: couldn't open input file: %s\n", file_name); |
117 | exit(EXIT_FAILURE); | 29 | exit(EXIT_FAILURE); |
118 | } | 30 | } |
119 | eval_line(fd, EOF); | 31 | process_input(fd); |
120 | fclose(fd); | 32 | fclose(fd); |
121 | } | 33 | } |
122 | 34 | ||
35 | #ifndef BIN_NAME | ||
36 | #define BIN_NAME "bdl" | ||
37 | #endif | ||
38 | |||
123 | void | 39 | void |
124 | print_usage(void) { | 40 | print_usage(void) { |
125 | printf("Usage: %s [options] <filename>\n", BIN_NAME); | 41 | printf("Usage: %s [options] <filename filename ...>\n", BIN_NAME); |
126 | printf("\n"); | 42 | printf("\n"); |
127 | printf("\t-i\tInteractive mode (REPL).\n"); | 43 | printf("\t-i\tInteractive mode (REPL).\n"); |
128 | printf("\t-x\tExecute expression from stdin.\n"); | ||
129 | printf("\n"); | 44 | printf("\n"); |
130 | } | 45 | } |
131 | 46 | ||
132 | int | 47 | int |
133 | main(int argc, char *argv[]) { | 48 | main(int argc, char *argv[]) { |
134 | init(); | ||
135 | |||
136 | int option; | 49 | int option; |
137 | while ((option = getopt(argc, argv, "ix")) != -1) { | 50 | while ((option = getopt(argc, argv, "i")) != -1) { |
138 | switch (option) { | 51 | switch (option) { |
139 | case 'i': { | 52 | case 'i': { |
140 | // Interactive mode. | 53 | // Interactive mode. |
141 | run_repl(); | 54 | run_repl(); |
142 | return EXIT_SUCCESS; | 55 | return EXIT_SUCCESS; |
143 | } break; | 56 | } break; |
144 | case 'x': { | ||
145 | // Execute expression from stdin. | ||
146 | eval_line(stdin, EOF); | ||
147 | return EXIT_SUCCESS; | ||
148 | } break; | ||
149 | default: { | 57 | default: { |
150 | print_usage(); | 58 | print_usage(); |
151 | return EXIT_FAILURE; | 59 | return EXIT_FAILURE; |
@@ -153,6 +61,8 @@ main(int argc, char *argv[]) { | |||
153 | } | 61 | } |
154 | } | 62 | } |
155 | 63 | ||
64 | // TODO: Run from stdin if no file is given. | ||
65 | |||
156 | // Run from file. | 66 | // Run from file. |
157 | if (optind != argc - 1) { | 67 | if (optind != argc - 1) { |
158 | fprintf(stderr, "%s: No input file given.\n", BIN_NAME); | 68 | fprintf(stderr, "%s: No input file given.\n", BIN_NAME); |