aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-18 12:31:20 +0200
committerBad Diode <bd@badd10de.dev>2021-10-18 12:31:20 +0200
commit043a96a6b7cf55f7ef58fb5ebf8ad87b7d50b571 (patch)
tree14861de314cfa5587103bd3cf21a761dd0e8248e
parent6f34133b0661849bccf891ea0aa4d04f45ca9a9a (diff)
downloadbdl-043a96a6b7cf55f7ef58fb5ebf8ad87b7d50b571.tar.gz
bdl-043a96a6b7cf55f7ef58fb5ebf8ad87b7d50b571.zip
Add header files for all modules
-rw-r--r--src/bootstrap/environment.c21
-rw-r--r--src/bootstrap/environment.h34
-rw-r--r--src/bootstrap/errors.c31
-rw-r--r--src/bootstrap/errors.h38
-rw-r--r--src/bootstrap/gc.c67
-rw-r--r--src/bootstrap/gc.h69
-rw-r--r--src/bootstrap/lexer.c38
-rw-r--r--src/bootstrap/lexer.h66
-rwxr-xr-xsrc/bootstrap/main.c22
-rw-r--r--src/bootstrap/objects.c66
-rw-r--r--src/bootstrap/objects.h77
-rw-r--r--src/bootstrap/parser.c9
-rw-r--r--src/bootstrap/parser.h22
-rw-r--r--src/bootstrap/primitives.c4
-rw-r--r--src/bootstrap/primitives.h60
-rw-r--r--src/bootstrap/read_line.c3
-rw-r--r--src/bootstrap/read_line.h10
-rw-r--r--src/bootstrap/singletons.c17
-rw-r--r--src/bootstrap/string_view.c5
-rw-r--r--src/bootstrap/string_view.h21
20 files changed, 445 insertions, 235 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c
index d5e954b..3fe8be1 100644
--- a/src/bootstrap/environment.c
+++ b/src/bootstrap/environment.c
@@ -1,21 +1,6 @@
1typedef struct EnvEntry { 1#include "environment.h"
2 Object *symbol; 2#include "gc.h"
3 Object *value; 3#include "errors.h"
4} EnvEntry;
5
6typedef struct Environment {
7 struct Environment *parent;
8 EnvEntry *buf;
9 size_t size;
10 size_t cap;
11 bool marked;
12} Environment;
13
14static Environment *global_env;
15
16#define ENV_BUF_CAP 8
17
18Environment *alloc_env(void);
19 4
20Environment * 5Environment *
21env_create(Environment *parent) { 6env_create(Environment *parent) {
diff --git a/src/bootstrap/environment.h b/src/bootstrap/environment.h
new file mode 100644
index 0000000..cc13921
--- /dev/null
+++ b/src/bootstrap/environment.h
@@ -0,0 +1,34 @@
1#ifndef BDL_ENVIRONMENT_H
2#define BDL_ENVIRONMENT_H
3
4#include "objects.h"
5
6typedef struct EnvEntry {
7 Object *symbol;
8 Object *value;
9} EnvEntry;
10
11typedef struct Environment {
12 struct Environment *parent;
13 EnvEntry *buf;
14 size_t size;
15 size_t cap;
16 bool marked;
17} Environment;
18
19Environment * env_create(Environment *parent);
20void env_add_symbol(Environment *env, Object *symbol, Object *value);
21Object * env_lookup(Environment *env, Object *symbol);
22Object * env_update(Environment *env, Object *symbol, Object *value);
23ssize_t env_index_current(Environment *env, Object *symbol);
24void env_add_or_update_current(Environment *env, Object *symbol, Object *value);
25Environment * env_extend(Environment *parent, Environment *extra);
26
27#define MAKE_ENV_VAR(ENV,STR,VAR) \
28 (env_add_symbol((ENV), MAKE_SYM(STR), (VAR)))
29#define MAKE_ENV_PROC(ENV,STR,FUN) \
30 (env_add_symbol((ENV), MAKE_SYM(STR), make_procedure(FUN)))
31
32#define ENV_BUF_CAP 8
33
34#endif // BDL_ENVIRONMENT_H
diff --git a/src/bootstrap/errors.c b/src/bootstrap/errors.c
index c1d2879..d957cfa 100644
--- a/src/bootstrap/errors.c
+++ b/src/bootstrap/errors.c
@@ -1,32 +1,4 @@
1typedef enum ErrorType { 1#include "errors.h"
2 ERR_TYPE_LEXER,
3 ERR_TYPE_PARSER,
4 ERR_TYPE_RUNTIME,
5} ErrorType;
6
7typedef enum ErrorValue {
8 ERR_UNKNOWN = 0,
9 ERR_UNMATCHED_STRING,
10 ERR_UNBALANCED_PAREN,
11 ERR_NOT_IMPLEMENTED,
12 ERR_EOF_REACHED,
13 ERR_UNKNOWN_TOKEN,
14 ERR_UNKNOWN_OBJ_TYPE,
15 ERR_NOT_A_SYMBOL,
16 ERR_SYMBOL_NOT_FOUND,
17 ERR_OBJ_NOT_CALLABLE,
18 ERR_NOT_ENOUGH_ARGS,
19 ERR_TOO_MANY_ARGS,
20 ERR_WRONG_ARG_TYPE,
21 ERR_DIVISION_BY_ZERO,
22} ErrorValue;
23
24typedef struct Error {
25 ErrorType type;
26 ErrorValue value;
27 size_t line;
28 size_t col;
29} Error;
30 2
31static const char* error_msgs[] = { 3static const char* error_msgs[] = {
32 [ERR_UNKNOWN] = "error: something unexpected happened", 4 [ERR_UNKNOWN] = "error: something unexpected happened",
@@ -45,7 +17,6 @@ static const char* error_msgs[] = {
45 [ERR_DIVISION_BY_ZERO] = "error: division by zero", 17 [ERR_DIVISION_BY_ZERO] = "error: division by zero",
46}; 18};
47 19
48#define ERR_MAX_NUMBER 16
49static Error errors[ERR_MAX_NUMBER]; 20static Error errors[ERR_MAX_NUMBER];
50static size_t errors_n = 0; 21static size_t errors_n = 0;
51static bool supress_errors = false; 22static bool supress_errors = false;
diff --git a/src/bootstrap/errors.h b/src/bootstrap/errors.h
new file mode 100644
index 0000000..7916f4a
--- /dev/null
+++ b/src/bootstrap/errors.h
@@ -0,0 +1,38 @@
1#ifndef BDL_ERRORS_H
2#define BDL_ERRORS_H
3
4typedef enum ErrorType {
5 ERR_TYPE_LEXER,
6 ERR_TYPE_PARSER,
7 ERR_TYPE_RUNTIME,
8} ErrorType;
9
10typedef enum ErrorValue {
11 ERR_UNKNOWN = 0,
12 ERR_UNMATCHED_STRING,
13 ERR_UNBALANCED_PAREN,
14 ERR_NOT_IMPLEMENTED,
15 ERR_EOF_REACHED,
16 ERR_UNKNOWN_TOKEN,
17 ERR_UNKNOWN_OBJ_TYPE,
18 ERR_NOT_A_SYMBOL,
19 ERR_SYMBOL_NOT_FOUND,
20 ERR_OBJ_NOT_CALLABLE,
21 ERR_NOT_ENOUGH_ARGS,
22 ERR_TOO_MANY_ARGS,
23 ERR_WRONG_ARG_TYPE,
24 ERR_DIVISION_BY_ZERO,
25} ErrorValue;
26
27typedef struct Error {
28 ErrorType type;
29 ErrorValue value;
30 size_t line;
31 size_t col;
32} Error;
33
34void error_push(Error error);
35
36#define ERR_MAX_NUMBER 16
37
38#endif // BDL_ERRORS_H
diff --git a/src/bootstrap/gc.c b/src/bootstrap/gc.c
index 11a1f5a..473930a 100644
--- a/src/bootstrap/gc.c
+++ b/src/bootstrap/gc.c
@@ -1,48 +1,4 @@
1// Stack of root nodes. 1#include "gc.h"
2typedef struct RootNodes {
3 Object **buf;
4 size_t size;
5 size_t cap;
6} RootNodes;
7
8// Stack of active environments.
9typedef struct ActiveEnvs {
10 Environment **buf;
11 size_t size;
12 size_t cap;
13} ActiveEnvs;
14
15typedef struct Environments {
16 Environment *buf;
17 size_t size;
18 size_t cap;
19} Environments;
20
21typedef struct FreeList {
22 size_t *buf;
23 size_t size;
24 size_t cap;
25 size_t position;
26} FreeList;
27
28typedef struct GC {
29 RootNodes roots;
30 Environments envs;
31 Object *objects;
32 size_t obj_cap;
33 FreeList free_objects;
34 FreeList free_envs;
35 ActiveEnvs active_envs;
36} GC;
37
38#define GC_OBJS_CAP 1024 * 1024
39#define GC_ROOTS_CAP 1024
40#define GC_ENVS_CAP 1024 * 4
41
42static GC gc;
43
44void mark_and_sweep(void);
45void dump_gc(void);
46 2
47Environment * 3Environment *
48alloc_env(void) { 4alloc_env(void) {
@@ -115,9 +71,9 @@ init_gc(void) {
115 .cap = GC_ENVS_CAP, 71 .cap = GC_ENVS_CAP,
116 }, 72 },
117 .active_envs = (ActiveEnvs){ 73 .active_envs = (ActiveEnvs){
118 .buf = malloc(GC_ROOTS_CAP * sizeof(Environment*)), 74 .buf = malloc(GC_ACTIVE_ENVS_CAP * sizeof(Environment*)),
119 .size = 0, 75 .size = 0,
120 .cap = GC_ROOTS_CAP, 76 .cap = GC_ACTIVE_ENVS_CAP,
121 }, 77 },
122 }; 78 };
123 79
@@ -131,13 +87,6 @@ init_gc(void) {
131 } 87 }
132} 88}
133 89
134Object *
135get_obj(size_t offset) {
136 return &gc.objects[offset];
137}
138
139void mark_obj(Object *obj);
140
141void 90void
142mark_environment(Environment *env) { 91mark_environment(Environment *env) {
143 if (env == NULL || env->marked) { 92 if (env == NULL || env->marked) {
@@ -190,11 +139,15 @@ mark_and_sweep(void) {
190 if (!obj->marked) { 139 if (!obj->marked) {
191 // Free heap allocated memory for this object if needed. 140 // Free heap allocated memory for this object if needed.
192 if (obj->type == OBJ_TYPE_SYMBOL) { 141 if (obj->type == OBJ_TYPE_SYMBOL) {
193 free(obj->symbol); 142 if (obj->symbol != NULL) {
143 free(obj->symbol);
144 }
194 obj->symbol = NULL; 145 obj->symbol = NULL;
195 obj->symbol_n = 0; 146 obj->symbol_n = 0;
196 } else if (obj->type == OBJ_TYPE_STRING) { 147 } else if (obj->type == OBJ_TYPE_STRING) {
197 free(obj->string); 148 if (obj->symbol != NULL) {
149 free(obj->string);
150 }
198 obj->string = NULL; 151 obj->string = NULL;
199 obj->string_n = 0; 152 obj->string_n = 0;
200 } 153 }
@@ -280,7 +233,7 @@ alloc_object(ObjectType type) {
280 } 233 }
281 size_t slot = gc.free_objects.buf[gc.free_objects.position++]; 234 size_t slot = gc.free_objects.buf[gc.free_objects.position++];
282 gc.free_objects.size--; 235 gc.free_objects.size--;
283 Object *obj = get_obj(slot); 236 Object *obj = &gc.objects[slot];
284 obj->type = type; 237 obj->type = type;
285 obj->marked = false; 238 obj->marked = false;
286 return obj; 239 return obj;
diff --git a/src/bootstrap/gc.h b/src/bootstrap/gc.h
new file mode 100644
index 0000000..038c820
--- /dev/null
+++ b/src/bootstrap/gc.h
@@ -0,0 +1,69 @@
1#ifndef BDL_GC_H
2#define BDL_GC_H
3
4#include "objects.h"
5#include "environment.h"
6
7// Stack of root nodes.
8typedef struct RootNodes {
9 Object **buf;
10 size_t size;
11 size_t cap;
12} RootNodes;
13
14// Stack of active environments.
15typedef struct ActiveEnvs {
16 Environment **buf;
17 size_t size;
18 size_t cap;
19} ActiveEnvs;
20
21typedef struct Environments {
22 Environment *buf;
23 size_t size;
24 size_t cap;
25} Environments;
26
27typedef struct FreeList {
28 size_t *buf;
29 size_t size;
30 size_t cap;
31 size_t position;
32} FreeList;
33
34typedef struct GC {
35 RootNodes roots;
36 Environments envs;
37 Object *objects;
38 size_t obj_cap;
39 FreeList free_objects;
40 FreeList free_envs;
41 ActiveEnvs active_envs;
42} GC;
43
44void init_gc(void);
45
46// Allocation functions for objects and environments.
47Object * alloc_object(ObjectType type);
48Environment * alloc_env(void);
49
50// Root and environment protector functions.
51void push_root(Object *obj);
52Object * pop_root(void);
53void push_active_env(Environment *env);
54Environment * pop_active_env(void);
55
56// Mark and sweep algorithm functions.
57void mark_environment(Environment *env);
58void mark_obj(Object *obj);
59void mark_and_sweep(void);
60
61// Debugging function to print out the contentes of some GC fields.
62void dump_gc(void);
63
64#define GC_OBJS_CAP 1024 * 1024
65#define GC_ROOTS_CAP 1024
66#define GC_ACTIVE_ENVS_CAP 2
67#define GC_ENVS_CAP 1024 * 4
68
69#endif // BDL_GC_H
diff --git a/src/bootstrap/lexer.c b/src/bootstrap/lexer.c
index ee387dd..05324eb 100644
--- a/src/bootstrap/lexer.c
+++ b/src/bootstrap/lexer.c
@@ -1,29 +1,4 @@
1typedef enum TokenType { 1#include "lexer.h"
2 TOKEN_UNKNOWN = 0,
3 TOKEN_LPAREN,
4 TOKEN_RPAREN,
5 TOKEN_QUOTE,
6 TOKEN_TRUE,
7 TOKEN_FALSE,
8 TOKEN_NIL,
9 TOKEN_FIXNUM,
10 TOKEN_SYMBOL,
11 TOKEN_STRING,
12 TOKEN_EOF,
13} TokenType;
14
15typedef struct Token {
16 TokenType type;
17 StringView value;
18 size_t line;
19 size_t column;
20} Token;
21
22typedef struct Tokens {
23 Token *buf;
24 size_t size;
25 size_t cap;
26} Tokens;
27 2
28void 3void
29print_token(Token tok) { 4print_token(Token tok) {
@@ -69,8 +44,6 @@ print_token(Token tok) {
69 printf("\n"); 44 printf("\n");
70} 45}
71 46
72#define TOK_BUF_CAP 256
73
74void 47void
75push_token(Tokens *tokens, Token tok) { 48push_token(Tokens *tokens, Token tok) {
76 if (tokens->buf == NULL) { 49 if (tokens->buf == NULL) {
@@ -84,13 +57,6 @@ push_token(Tokens *tokens, Token tok) {
84 tokens->buf[tokens->size++] = tok; 57 tokens->buf[tokens->size++] = tok;
85} 58}
86 59
87typedef struct Scanner {
88 StringView current;
89 size_t line_number;
90 size_t col_number;
91 size_t offset;
92} Scanner;
93
94char 60char
95scan_next(Scanner *scanner) { 61scan_next(Scanner *scanner) {
96 char c = sv_next(&scanner->current); 62 char c = sv_next(&scanner->current);
@@ -157,7 +123,7 @@ is_delimiter(char c) {
157} 123}
158 124
159TokenType 125TokenType
160find_primitive_type(StringView value) { 126find_primitive_type(const StringView value) {
161 bool is_fixnum = true; 127 bool is_fixnum = true;
162 for (size_t i = 0; i < value.n; i++) { 128 for (size_t i = 0; i < value.n; i++) {
163 char c = value.start[i]; 129 char c = value.start[i];
diff --git a/src/bootstrap/lexer.h b/src/bootstrap/lexer.h
new file mode 100644
index 0000000..129fd9a
--- /dev/null
+++ b/src/bootstrap/lexer.h
@@ -0,0 +1,66 @@
1#ifndef BDL_LEXER_H
2#define BDL_LEXER_H
3
4typedef enum TokenType {
5 TOKEN_UNKNOWN = 0,
6 TOKEN_LPAREN,
7 TOKEN_RPAREN,
8 TOKEN_QUOTE,
9 TOKEN_TRUE,
10 TOKEN_FALSE,
11 TOKEN_NIL,
12 TOKEN_FIXNUM,
13 TOKEN_SYMBOL,
14 TOKEN_STRING,
15 TOKEN_EOF,
16} TokenType;
17
18typedef struct Token {
19 TokenType type;
20 StringView value;
21 size_t line;
22 size_t column;
23} Token;
24
25typedef struct Tokens {
26 Token *buf;
27 size_t size;
28 size_t cap;
29} Tokens;
30
31typedef struct Scanner {
32 StringView current;
33 size_t line_number;
34 size_t col_number;
35 size_t offset;
36} Scanner;
37
38// Print a token to standard output for debugging purposes.
39void print_token(Token tok);
40
41// Push a token to the token list.
42void push_token(Tokens *tokens, Token tok);
43
44// Same functionality as the ScanView pairs, but keeping track of line and
45// column numbers.
46char scan_next(Scanner *scanner);
47char scan_peek(const Scanner *scanner);
48
49// Check if the current scanner still have characters left.
50bool scan_has_next(const Scanner *scanner);
51
52// Advance the scanner until we ran out of whitespace.
53void skip_whitespace(Scanner *scanner);
54
55// Check if a given character is a delimiter.
56bool is_delimiter(char c);
57
58// Extract the token type from the current string.
59TokenType find_primitive_type(const StringView value);
60
61// Generate a list of tokens from the given string.
62Tokens tokenize(const StringView *sv);
63
64#define TOK_BUF_CAP 256
65
66#endif // BDL_LEXER_H
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c
index 2d24f92..cfad9f1 100755
--- a/src/bootstrap/main.c
+++ b/src/bootstrap/main.c
@@ -6,25 +6,17 @@
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h> 7#include <string.h>
8 8
9#include "string_view.c" 9#include "singletons.c"
10#include "read_line.c" 10
11#include "environment.c"
11#include "errors.c" 12#include "errors.c"
13#include "gc.c"
12#include "lexer.c" 14#include "lexer.c"
13#include "objects.c" 15#include "objects.c"
14#include "parser.c" 16#include "parser.c"
15#include "environment.c"
16#include "gc.c"
17#include "primitives.c" 17#include "primitives.c"
18 18#include "read_line.c"
19// 19#include "string_view.c"
20// Utility macros.
21//
22
23#define MAKE_SYM(STR) make_symbol((StringView){(STR), sizeof(STR) - 1})
24#define MAKE_ENV_VAR(ENV,STR,VAR) \
25 (env_add_symbol((ENV), MAKE_SYM(STR), (VAR)))
26#define MAKE_ENV_PROC(ENV,STR,FUN) \
27 (env_add_symbol((ENV), MAKE_SYM(STR), make_procedure(FUN)))
28 20
29void 21void
30init(void) { 22init(void) {
@@ -113,7 +105,7 @@ process_source(const StringView *source) {
113 .current = 0, 105 .current = 0,
114 }; 106 };
115 while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { 107 while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) {
116 // check the stack before parsing 108 // Check the root node stack size before parsing
117 size_t root_stack_size = gc.roots.size; 109 size_t root_stack_size = gc.roots.size;
118 Object *root = parse_tree(&visitor); 110 Object *root = parse_tree(&visitor);
119 gc.roots.size = root_stack_size; 111 gc.roots.size = root_stack_size;
diff --git a/src/bootstrap/objects.c b/src/bootstrap/objects.c
index 09076db..359329b 100644
--- a/src/bootstrap/objects.c
+++ b/src/bootstrap/objects.c
@@ -1,70 +1,10 @@
1typedef enum ObjectType { 1#include "gc.h"
2 OBJ_TYPE_FIXNUM, 2#include "objects.h"
3 OBJ_TYPE_BOOL,
4 OBJ_TYPE_NIL,
5 OBJ_TYPE_SYMBOL,
6 OBJ_TYPE_STRING,
7 OBJ_TYPE_PAIR,
8 OBJ_TYPE_PROCEDURE,
9 OBJ_TYPE_LAMBDA,
10 OBJ_TYPE_ERR,
11} ObjectType;
12
13struct Environment;
14
15typedef struct Object {
16 ObjectType type;
17 bool marked;
18 union {
19 // OBJ_TYPE_FIXNUM
20 ssize_t fixnum;
21
22 // OBJ_TYPE_STRING
23 struct {
24 char *string;
25 size_t string_n;
26 };
27
28 // OBJ_TYPE_PAIR
29 struct {
30 struct Object *car;
31 struct Object *cdr;
32 };
33
34 // OBJ_TYPE_SYMBOL
35 struct {
36 char *symbol;
37 size_t symbol_n;
38 };
39
40 // OBJ_TYPE_PROCEDURE
41 struct Object *(*proc)(struct Environment *env, struct Object *args);
42
43 // OBJ_TYPE_LAMBDA
44 struct {
45 struct Object *params;
46 struct Object *body;
47 struct Environment *env;
48 };
49 };
50} Object;
51
52//
53// Singletons.
54//
55
56static Object *obj_nil;
57static Object *obj_true;
58static Object *obj_false;
59static Object *obj_err;
60static Object *obj_quote;
61 3
62// 4//
63// Constructors. 5// Constructors.
64// 6//
65 7
66Object * alloc_object(ObjectType);
67
68Object * 8Object *
69make_fixnum(ssize_t num) { 9make_fixnum(ssize_t num) {
70 Object *obj = alloc_object(OBJ_TYPE_FIXNUM); 10 Object *obj = alloc_object(OBJ_TYPE_FIXNUM);
@@ -116,8 +56,6 @@ append_string(Object *obj, const StringView sv) {
116 obj->string_n += sv.n; 56 obj->string_n += sv.n;
117} 57}
118 58
119void display(Object *root);
120
121void 59void
122display_pair(Object *root) { 60display_pair(Object *root) {
123 display(root->car); 61 display(root->car);
diff --git a/src/bootstrap/objects.h b/src/bootstrap/objects.h
new file mode 100644
index 0000000..56821eb
--- /dev/null
+++ b/src/bootstrap/objects.h
@@ -0,0 +1,77 @@
1#ifndef BDL_OBJECTS_H
2#define BDL_OBJECTS_H
3
4#include "string_view.h"
5
6typedef enum ObjectType {
7 OBJ_TYPE_FIXNUM,
8 OBJ_TYPE_BOOL,
9 OBJ_TYPE_NIL,
10 OBJ_TYPE_SYMBOL,
11 OBJ_TYPE_STRING,
12 OBJ_TYPE_PAIR,
13 OBJ_TYPE_PROCEDURE,
14 OBJ_TYPE_LAMBDA,
15 OBJ_TYPE_ERR,
16} ObjectType;
17
18struct Environment;
19
20typedef struct Object {
21 ObjectType type;
22 bool marked;
23 union {
24 // OBJ_TYPE_FIXNUM
25 ssize_t fixnum;
26
27 // OBJ_TYPE_STRING
28 struct {
29 char *string;
30 size_t string_n;
31 };
32
33 // OBJ_TYPE_PAIR
34 struct {
35 struct Object *car;
36 struct Object *cdr;
37 };
38
39 // OBJ_TYPE_SYMBOL
40 struct {
41 char *symbol;
42 size_t symbol_n;
43 };
44
45 // OBJ_TYPE_PROCEDURE
46 struct Object *(*proc)(struct Environment *env, struct Object *args);
47
48 // OBJ_TYPE_LAMBDA
49 struct {
50 struct Object *params;
51 struct Object *body;
52 struct Environment *env;
53 };
54 };
55} Object;
56
57// Object constructors.
58Object * make_fixnum(ssize_t num);
59Object * make_procedure(Object *(*proc)(struct Environment *, struct Object *args));
60Object * make_pair(Object *car, Object *cdr);
61Object * make_symbol(StringView sv);
62Object * make_string(void);
63void append_string(Object *obj, const StringView sv);
64
65// Object representation.
66void display(Object *root);
67void display_pair(Object *root);
68
69// Object comparison.
70bool obj_eq(Object *a, Object* b);
71
72// Utility macros.
73#define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n");
74#define PRINT_OBJ(OBJ) display(OBJ); printf("\n");
75#define MAKE_SYM(STR) make_symbol((StringView){(STR), sizeof(STR) - 1})
76
77#endif // BDL_OBJECTS_H
diff --git a/src/bootstrap/parser.c b/src/bootstrap/parser.c
index 77ece9d..5b0033a 100644
--- a/src/bootstrap/parser.c
+++ b/src/bootstrap/parser.c
@@ -1,7 +1,4 @@
1typedef struct Visitor { 1#include "parser.h"
2 Tokens tokens;
3 size_t current;
4} Visitor;
5 2
6Token 3Token
7peek_token(const Visitor *visitor) { 4peek_token(const Visitor *visitor) {
@@ -18,8 +15,6 @@ has_next_token(const Visitor *visitor) {
18 return visitor->current < visitor->tokens.size; 15 return visitor->current < visitor->tokens.size;
19} 16}
20 17
21void push_root(Object*);
22
23Object * 18Object *
24parse_fixnum(Token tok) { 19parse_fixnum(Token tok) {
25 ssize_t num = 0; 20 ssize_t num = 0;
@@ -38,8 +33,6 @@ parse_fixnum(Token tok) {
38 return obj; 33 return obj;
39} 34}
40 35
41Object * parse_tree(Visitor *vs);
42
43Object * 36Object *
44parse_list(Visitor *vs) { 37parse_list(Visitor *vs) {
45 Token tok = peek_token(vs); 38 Token tok = peek_token(vs);
diff --git a/src/bootstrap/parser.h b/src/bootstrap/parser.h
new file mode 100644
index 0000000..3bd17ef
--- /dev/null
+++ b/src/bootstrap/parser.h
@@ -0,0 +1,22 @@
1#ifndef BDL_PARSER_H
2#define BDL_PARSER_H
3
4typedef struct Visitor {
5 Tokens tokens;
6 size_t current;
7} Visitor;
8
9// Mimics the functionality in the Scanner functions, but for entire tokens.
10Token next_token(Visitor *visitor);
11Token peek_token(const Visitor *visitor);
12bool has_next_token(const Visitor *visitor);
13
14// Parse a token into a fixnum object.
15Object * parse_fixnum(Token tok);
16
17// Recursive descent parser. If an object is not a list the parsing is handled
18// by the parse_tree function.
19Object * parse_list(Visitor *vs);
20Object * parse_tree(Visitor *vs);
21
22#endif // BDL_PARSER_H
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c
index 0c2a17d..0f1498d 100644
--- a/src/bootstrap/primitives.c
+++ b/src/bootstrap/primitives.c
@@ -1,5 +1,4 @@
1#define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n"); 1#include "primitives.h"
2static Object *proc_if;
3 2
4Object * 3Object *
5eval(Environment *env, Object *root) { 4eval(Environment *env, Object *root) {
@@ -153,6 +152,7 @@ eval_lambda:
153 .value = ERR_UNKNOWN_OBJ_TYPE, 152 .value = ERR_UNKNOWN_OBJ_TYPE,
154 }); 153 });
155 return obj_err; 154 return obj_err;
155
156eval_success: 156eval_success:
157 if (recursion_active) { 157 if (recursion_active) {
158 // Remove stack protector. 158 // Remove stack protector.
diff --git a/src/bootstrap/primitives.h b/src/bootstrap/primitives.h
new file mode 100644
index 0000000..f874b17
--- /dev/null
+++ b/src/bootstrap/primitives.h
@@ -0,0 +1,60 @@
1#ifndef BDL_PRIMITIVES_H
2#define BDL_PRIMITIVES_H
3
4// Function evaluation.
5Object * eval(Environment *env, Object *root);
6
7// Evaluation functions.
8Object * proc_quote(Environment *env, Object *obj);
9Object * proc_eval(Environment *env, Object *obj);
10
11// Arithmetic.
12Object * proc_sum(Environment *env, Object *obj);
13Object * proc_sub(Environment *env, Object *obj);
14Object * proc_mul(Environment *env, Object *obj);
15Object * proc_div(Environment *env, Object *obj);
16Object * proc_mod(Environment *env, Object *obj);
17
18// Printing.
19Object * proc_display(Environment *env, Object *obj);
20Object * proc_print(Environment *env, Object *obj);
21Object * proc_newline(Environment *env, Object *obj);
22
23// Type checking.
24Object * proc_is_boolean(Environment *env, Object *obj);
25Object * proc_is_nil(Environment *env, Object *obj);
26Object * proc_is_symbol(Environment *env, Object *obj);
27Object * proc_is_string(Environment *env, Object *obj);
28Object * proc_is_fixnum(Environment *env, Object *obj);
29Object * proc_is_pair(Environment *env, Object *obj);
30Object * proc_is_procedure(Environment *env, Object *obj);
31Object * proc_is_error(Environment *env, Object *obj);
32
33// Logical operations.
34Object * proc_not(Environment *env, Object *obj);
35Object * proc_and(Environment *env, Object *obj);
36Object * proc_or(Environment *env, Object *obj);
37Object * proc_cond(Environment *env, Object *obj);
38Object * proc_num_less_than(Environment *env, Object *obj);
39Object * proc_num_greater_than(Environment *env, Object *obj);
40Object * proc_num_lesseq_than(Environment *env, Object *obj);
41Object * proc_num_greatereq_than(Environment *env, Object *obj);
42Object * proc_num_equal(Environment *env, Object *obj);
43Object * proc_equal(Environment *env, Object *obj);
44
45// List operations.
46Object * proc_car(Environment *env, Object *obj);
47Object * proc_cdr(Environment *env, Object *obj);
48Object * proc_cons(Environment *env, Object *obj);
49Object * proc_list(Environment *env, Object *obj);
50
51// Environment/variable manipulation.
52Object * proc_define(Environment *env, Object *obj);
53Object * proc_set(Environment *env, Object *obj);
54Object * proc_lambda(Environment *env, Object *obj);
55Object * proc_fun(Environment *env, Object *obj);
56
57// Runtinme configuration.
58Object * proc_supress_errors(Environment *env, Object *obj);
59
60#endif // BDL_PRIMITIVES_H
diff --git a/src/bootstrap/read_line.c b/src/bootstrap/read_line.c
index 603bfee..03146ad 100644
--- a/src/bootstrap/read_line.c
+++ b/src/bootstrap/read_line.c
@@ -1,4 +1,5 @@
1#define RL_BUF_SIZE 1024 1#include "read_line.h"
2
2static char readline_buf[RL_BUF_SIZE]; 3static char readline_buf[RL_BUF_SIZE];
3 4
4StringView 5StringView
diff --git a/src/bootstrap/read_line.h b/src/bootstrap/read_line.h
new file mode 100644
index 0000000..160bce0
--- /dev/null
+++ b/src/bootstrap/read_line.h
@@ -0,0 +1,10 @@
1#ifndef BDL_READ_LINE_H
2#define BDL_READ_LINE_H
3
4#include "string_view.h"
5
6StringView read_line(void);
7
8#define RL_BUF_SIZE 1024
9
10#endif // BDL_READ_LINE_H
diff --git a/src/bootstrap/singletons.c b/src/bootstrap/singletons.c
new file mode 100644
index 0000000..eb9c397
--- /dev/null
+++ b/src/bootstrap/singletons.c
@@ -0,0 +1,17 @@
1#include "environment.h"
2#include "gc.h"
3#include "objects.h"
4
5// Global garbage collector singleton.
6static GC gc;
7
8// Special singleton Objects.
9static Object *obj_nil;
10static Object *obj_true;
11static Object *obj_false;
12static Object *obj_err;
13static Object *obj_quote;
14static Object *proc_if;
15
16// Global environment.
17static Environment *global_env;
diff --git a/src/bootstrap/string_view.c b/src/bootstrap/string_view.c
index 13ba9e0..39fabe9 100644
--- a/src/bootstrap/string_view.c
+++ b/src/bootstrap/string_view.c
@@ -1,7 +1,4 @@
1typedef struct StringView { 1#include "string_view.h"
2 char *start;
3 size_t n;
4} StringView;
5 2
6char 3char
7sv_next(StringView *sv) { 4sv_next(StringView *sv) {
diff --git a/src/bootstrap/string_view.h b/src/bootstrap/string_view.h
new file mode 100644
index 0000000..42273ab
--- /dev/null
+++ b/src/bootstrap/string_view.h
@@ -0,0 +1,21 @@
1#ifndef BDL_STRINGVIEW_H
2#define BDL_STRINGVIEW_H
3
4typedef struct StringView {
5 char *start;
6 size_t n;
7} StringView;
8
9// Consume a character in the stream.
10char sv_next(StringView *sv);
11
12// Check what is the current character in the stream.
13char sv_peek(const StringView *sv);
14
15// Compare if the arguments are the same.
16bool sv_equal(const StringView *a, const StringView *b);
17
18// Write a character to the given output stream.
19void sv_write(const StringView *sv, FILE *file);
20
21#endif // BDL_STRINGVIEW_H