aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/main.c')
-rwxr-xr-xsrc/bootstrap/main.c124
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
22void 6void
23init(void) { 7process_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
70void 13#define REPL_PROMPT "bdl> "
71eval_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
100void 15void
101run_repl(void) { 16run_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
109void 24void
110run_file(char *file_name) { 25run_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
123void 39void
124print_usage(void) { 40print_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
132int 47int
133main(int argc, char *argv[]) { 48main(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);