diff options
-rwxr-xr-x[-rw-r--r--] | src/bytecode/chunk.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/compiler.h | 204 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/darray.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/debug.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/errors.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/errors.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/lexer.c | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/lexer.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/main.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/objects.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/ops.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/read_line.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/read_line.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/string_view.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/string_view.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/types.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bytecode/vm.h | 4 |
17 files changed, 207 insertions, 12 deletions
diff --git a/src/bytecode/chunk.h b/src/bytecode/chunk.h index e3c7383..81fc4cc 100644..100755 --- a/src/bytecode/chunk.h +++ b/src/bytecode/chunk.h | |||
@@ -46,6 +46,11 @@ add_code(Chunk *chunk, u8 byte, size_t line, size_t col) { | |||
46 | 46 | ||
47 | size_t | 47 | size_t |
48 | add_constant(Chunk *chunk, Object obj) { | 48 | add_constant(Chunk *chunk, Object obj) { |
49 | // FIXME?: Since we are using a single byte to store constant indices, we | ||
50 | // can only have 256 stored constants. If we need more we may need to add | ||
51 | // another instruction OP_CONSTANT_16 to have at least two bytes for | ||
52 | // constants. Alternatively, we could make that the default. Either way, for | ||
53 | // now it's fine. | ||
49 | size_t pos = array_size(chunk->constants); | 54 | size_t pos = array_size(chunk->constants); |
50 | array_push(chunk->constants, obj); | 55 | array_push(chunk->constants, obj); |
51 | return pos; | 56 | return pos; |
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 6991a86..7ec1ca9 100644..100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h | |||
@@ -31,21 +31,211 @@ has_next_token(const Visitor *visitor) { | |||
31 | return visitor->current < array_size(visitor->tokens); | 31 | return visitor->current < array_size(visitor->tokens); |
32 | } | 32 | } |
33 | 33 | ||
34 | void | ||
35 | emit_constant(Chunk *chunk, Token tok, Object obj) { | ||
36 | // TODO: Should we deduplicate constants? For example why store a number | ||
37 | // more than once instead of reusing the existing index? | ||
38 | size_t num_idx = add_constant(chunk, obj); | ||
39 | add_code(chunk, OP_CONSTANT, tok.line, tok.column); | ||
40 | add_code(chunk, num_idx, tok.line, tok.column); | ||
41 | } | ||
42 | |||
43 | void | ||
44 | parse_fixnum(Chunk *chunk, Token tok) { | ||
45 | ssize_t num = 0; | ||
46 | int sign = 1; | ||
47 | for (size_t i = 0; i < tok.value.n; i++) { | ||
48 | char c = tok.value.start[i]; | ||
49 | if (c == '-') { | ||
50 | sign = -1; | ||
51 | continue; | ||
52 | } | ||
53 | num = num * 10 + (c - '0'); | ||
54 | } | ||
55 | emit_constant(chunk, tok, num); | ||
56 | } | ||
57 | |||
58 | void parse_tree(Chunk *chunk, Visitor *vs); | ||
59 | |||
60 | void | ||
61 | compile_list_primitive(Chunk *chunk, Visitor *vs, Token op_tok) { | ||
62 | Ops op; | ||
63 | switch (op_tok.type) { | ||
64 | case TOKEN_ADD: { | ||
65 | emit_constant(chunk, op_tok, 0); | ||
66 | op = OP_SUM; | ||
67 | } break; | ||
68 | case TOKEN_SUB: { | ||
69 | // TODO: fetch first element. | ||
70 | emit_constant(chunk, op_tok, 0); | ||
71 | op = OP_SUB; | ||
72 | } break; | ||
73 | case TOKEN_MUL: { | ||
74 | emit_constant(chunk, op_tok, 1); | ||
75 | op = OP_MUL; | ||
76 | } break; | ||
77 | case TOKEN_DIV: { | ||
78 | // TODO: fetch first element. | ||
79 | emit_constant(chunk, op_tok, 1); | ||
80 | op = OP_DIV; | ||
81 | } break; | ||
82 | case TOKEN_MOD: { | ||
83 | // TODO: fetch first element. | ||
84 | emit_constant(chunk, op_tok, 1); | ||
85 | op = OP_MOD; | ||
86 | } break; | ||
87 | default: { | ||
88 | } break; | ||
89 | } | ||
90 | while (has_next_token(vs)) { | ||
91 | Token tok = peek_token(vs); | ||
92 | if (tok.type == TOKEN_EOF) { | ||
93 | error_push((Error){ | ||
94 | .type = ERR_TYPE_PARSER, | ||
95 | .value = ERR_UNBALANCED_PAREN, | ||
96 | .line = op_tok.line, | ||
97 | .col = op_tok.column, | ||
98 | }); | ||
99 | return; | ||
100 | } | ||
101 | if (tok.type == TOKEN_RPAREN) { | ||
102 | next_token(vs); | ||
103 | break; | ||
104 | } | ||
105 | parse_tree(chunk, vs); | ||
106 | add_code(chunk, op, tok.line, tok.column); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void | ||
111 | parse_list(Chunk *chunk, Visitor *vs) { | ||
112 | if (has_next_token(vs)) { | ||
113 | Token tok = next_token(vs); | ||
114 | print_token(tok); | ||
115 | // TODO: check if is function call. | ||
116 | switch (tok.type) { | ||
117 | case TOKEN_ADD: | ||
118 | case TOKEN_SUB: | ||
119 | case TOKEN_MUL: | ||
120 | case TOKEN_DIV: | ||
121 | case TOKEN_MOD:{ | ||
122 | compile_list_primitive(chunk, vs, tok); | ||
123 | } break; | ||
124 | default: { | ||
125 | error_push((Error){ | ||
126 | .type = ERR_TYPE_COMPILER, | ||
127 | .value = ERR_OBJ_NOT_CALLABLE, | ||
128 | .line = tok.line, | ||
129 | .line = tok.column, | ||
130 | }); | ||
131 | } break; | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | void | ||
137 | parse_tree(Chunk *chunk, Visitor *vs) { | ||
138 | Token tok = next_token(vs); | ||
139 | switch (tok.type) { | ||
140 | case TOKEN_FIXNUM: { | ||
141 | parse_fixnum(chunk, tok); | ||
142 | return ; | ||
143 | } break; | ||
144 | case TOKEN_TRUE: { | ||
145 | // return obj_true; | ||
146 | return; | ||
147 | } break; | ||
148 | case TOKEN_FALSE: { | ||
149 | // return obj_false; | ||
150 | return; | ||
151 | } break; | ||
152 | case TOKEN_RPAREN: { | ||
153 | error_push((Error){ | ||
154 | .type = ERR_TYPE_PARSER, | ||
155 | .value = ERR_UNBALANCED_PAREN, | ||
156 | .line = tok.line, | ||
157 | .col = tok.column, | ||
158 | }); | ||
159 | return; | ||
160 | } break; | ||
161 | case TOKEN_QUOTE: { | ||
162 | // Object *base = make_pair(obj_quote, obj_nil); | ||
163 | // base->cdr = make_pair(obj_nil, obj_nil); | ||
164 | // push_root(base); | ||
165 | // Object *next_obj = parse_tree(vs); | ||
166 | // if (next_obj == obj_err) { | ||
167 | // return obj_err; | ||
168 | // } | ||
169 | // base->cdr->car = next_obj; | ||
170 | // return base; | ||
171 | return; | ||
172 | } break; | ||
173 | case TOKEN_LPAREN: { | ||
174 | parse_list(chunk, vs); | ||
175 | // Object *obj = parse_list(vs); | ||
176 | // if (obj == obj_err) { | ||
177 | // error_push((Error){ | ||
178 | // .type = ERR_TYPE_PARSER, | ||
179 | // .value = ERR_UNBALANCED_PAREN, | ||
180 | // .line = tok.line, | ||
181 | // .col = tok.column, | ||
182 | // }); | ||
183 | // } | ||
184 | // return obj; | ||
185 | return; | ||
186 | } break; | ||
187 | case TOKEN_STRING: { | ||
188 | // Object *obj = make_string(); | ||
189 | // push_root(obj); | ||
190 | // append_string(obj, tok.value); | ||
191 | // return obj; | ||
192 | return; | ||
193 | } break; | ||
194 | case TOKEN_SYMBOL: { | ||
195 | // Object *obj = make_symbol(tok.value); | ||
196 | // push_root(obj); | ||
197 | // return obj; | ||
198 | return; | ||
199 | } break; | ||
200 | case TOKEN_NIL: { | ||
201 | // return obj_nil; | ||
202 | return; | ||
203 | } break; | ||
204 | default: { | ||
205 | break; | ||
206 | } break; | ||
207 | } | ||
208 | error_push((Error){ | ||
209 | .type = ERR_TYPE_PARSER, | ||
210 | .value = ERR_EOF_REACHED, | ||
211 | .line = tok.line, | ||
212 | .col = tok.column, | ||
213 | }); | ||
214 | return; | ||
215 | } | ||
216 | |||
34 | Chunk * | 217 | Chunk * |
35 | compile(Token *tokens) { | 218 | compile(Token *tokens) { |
36 | Chunk *chunk = NULL; | 219 | Chunk *chunk = NULL; |
37 | chunk = chunk_init(); | 220 | chunk = chunk_init(); |
221 | Visitor visitor = (Visitor){ | ||
222 | .tokens = tokens, | ||
223 | .current = 0, | ||
224 | }; | ||
225 | while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { | ||
226 | parse_tree(chunk, &visitor); | ||
227 | } | ||
38 | // error_push((Error){ | 228 | // error_push((Error){ |
39 | // .type = ERR_TYPE_COMPILER, | 229 | // .type = ERR_TYPE_COMPILER, |
40 | // .value = ERR_UNKNOWN, | 230 | // .value = ERR_UNKNOWN, |
41 | // }); | 231 | // }); |
42 | size_t const_a = add_constant(chunk, 7); | 232 | // size_t const_a = add_constant(chunk, 7); |
43 | add_code(chunk, OP_CONSTANT, 1, 1); | 233 | // add_code(chunk, OP_CONSTANT, 1, 1); |
44 | add_code(chunk, const_a, 1, 1); | 234 | // add_code(chunk, const_a, 1, 1); |
45 | size_t const_b = add_constant(chunk, 2); | 235 | // size_t const_b = add_constant(chunk, 2); |
46 | add_code(chunk, OP_CONSTANT, 1, 2); | 236 | // add_code(chunk, OP_CONSTANT, 1, 2); |
47 | add_code(chunk, const_b, 1, 2); | 237 | // add_code(chunk, const_b, 1, 2); |
48 | add_code(chunk, OP_MOD, 1, 3); | 238 | // add_code(chunk, OP_MOD, 1, 3); |
49 | add_code(chunk, OP_RETURN, 1, 1); | 239 | add_code(chunk, OP_RETURN, 1, 1); |
50 | return chunk; | 240 | return chunk; |
51 | } | 241 | } |
diff --git a/src/bytecode/darray.h b/src/bytecode/darray.h index db6234d..db6234d 100644..100755 --- a/src/bytecode/darray.h +++ b/src/bytecode/darray.h | |||
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 05f9d8e..05f9d8e 100644..100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h | |||
diff --git a/src/bytecode/errors.c b/src/bytecode/errors.c index c2ab77f..c2ab77f 100644..100755 --- a/src/bytecode/errors.c +++ b/src/bytecode/errors.c | |||
diff --git a/src/bytecode/errors.h b/src/bytecode/errors.h index 7b3446e..7b3446e 100644..100755 --- a/src/bytecode/errors.h +++ b/src/bytecode/errors.h | |||
diff --git a/src/bytecode/lexer.c b/src/bytecode/lexer.c index 82cdf22..bc2dd9d 100644..100755 --- a/src/bytecode/lexer.c +++ b/src/bytecode/lexer.c | |||
@@ -17,7 +17,7 @@ static const char* token_str[] = { | |||
17 | [TOKEN_FUN] = "TOKEN_FUN", | 17 | [TOKEN_FUN] = "TOKEN_FUN", |
18 | [TOKEN_LAMBDA] = "TOKEN_LAMBDA", | 18 | [TOKEN_LAMBDA] = "TOKEN_LAMBDA", |
19 | [TOKEN_ADD] = "TOKEN_ADD", | 19 | [TOKEN_ADD] = "TOKEN_ADD", |
20 | [TOKEN_MIN] = "TOKEN_MIN", | 20 | [TOKEN_SUB] = "TOKEN_SUB", |
21 | [TOKEN_MUL] = "TOKEN_MUL", | 21 | [TOKEN_MUL] = "TOKEN_MUL", |
22 | [TOKEN_DIV] = "TOKEN_DIV", | 22 | [TOKEN_DIV] = "TOKEN_DIV", |
23 | [TOKEN_MOD] = "TOKEN_MOD", | 23 | [TOKEN_MOD] = "TOKEN_MOD", |
@@ -147,7 +147,7 @@ find_primitive_type(const StringView value) { | |||
147 | if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } | 147 | if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } |
148 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } | 148 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } |
149 | if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; } | 149 | if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; } |
150 | if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_MIN; } | 150 | if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_SUB; } |
151 | if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; } | 151 | if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; } |
152 | if (TOKEN_IS_KEYWORD(value, "/")) { return TOKEN_DIV; } | 152 | if (TOKEN_IS_KEYWORD(value, "/")) { return TOKEN_DIV; } |
153 | if (TOKEN_IS_KEYWORD(value, "%")) { return TOKEN_MOD; } | 153 | if (TOKEN_IS_KEYWORD(value, "%")) { return TOKEN_MOD; } |
diff --git a/src/bytecode/lexer.h b/src/bytecode/lexer.h index a19ac11..47fd384 100644..100755 --- a/src/bytecode/lexer.h +++ b/src/bytecode/lexer.h | |||
@@ -28,7 +28,7 @@ typedef enum TokenType { | |||
28 | 28 | ||
29 | // Arithmetic. | 29 | // Arithmetic. |
30 | TOKEN_ADD, | 30 | TOKEN_ADD, |
31 | TOKEN_MIN, | 31 | TOKEN_SUB, |
32 | TOKEN_MUL, | 32 | TOKEN_MUL, |
33 | TOKEN_DIV, | 33 | TOKEN_DIV, |
34 | TOKEN_MOD, | 34 | TOKEN_MOD, |
diff --git a/src/bytecode/main.c b/src/bytecode/main.c index d6cb5d3..d6cb5d3 100644..100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c | |||
diff --git a/src/bytecode/objects.h b/src/bytecode/objects.h index 9bfa2cf..9bfa2cf 100644..100755 --- a/src/bytecode/objects.h +++ b/src/bytecode/objects.h | |||
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h index b58631f..b58631f 100644..100755 --- a/src/bytecode/ops.h +++ b/src/bytecode/ops.h | |||
diff --git a/src/bytecode/read_line.c b/src/bytecode/read_line.c index 03146ad..03146ad 100644..100755 --- a/src/bytecode/read_line.c +++ b/src/bytecode/read_line.c | |||
diff --git a/src/bytecode/read_line.h b/src/bytecode/read_line.h index 160bce0..160bce0 100644..100755 --- a/src/bytecode/read_line.h +++ b/src/bytecode/read_line.h | |||
diff --git a/src/bytecode/string_view.c b/src/bytecode/string_view.c index 39fabe9..39fabe9 100644..100755 --- a/src/bytecode/string_view.c +++ b/src/bytecode/string_view.c | |||
diff --git a/src/bytecode/string_view.h b/src/bytecode/string_view.h index 42273ab..42273ab 100644..100755 --- a/src/bytecode/string_view.h +++ b/src/bytecode/string_view.h | |||
diff --git a/src/bytecode/types.h b/src/bytecode/types.h index dc21756..dc21756 100644..100755 --- a/src/bytecode/types.h +++ b/src/bytecode/types.h | |||
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index f9e64d1..3a9b5af 100644..100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -81,7 +81,7 @@ vm_interpret(VM vm, Chunk *chunk) { | |||
81 | case OP_SUB: { | 81 | case OP_SUB: { |
82 | Object a = array_pop(vm.stack); | 82 | Object a = array_pop(vm.stack); |
83 | Object b = array_pop(vm.stack); | 83 | Object b = array_pop(vm.stack); |
84 | array_push(vm.stack, a - b); | 84 | array_push(vm.stack, b - a); |
85 | } break; | 85 | } break; |
86 | case OP_MUL: { | 86 | case OP_MUL: { |
87 | Object a = array_pop(vm.stack); | 87 | Object a = array_pop(vm.stack); |
@@ -91,7 +91,7 @@ vm_interpret(VM vm, Chunk *chunk) { | |||
91 | case OP_DIV: { | 91 | case OP_DIV: { |
92 | Object a = array_pop(vm.stack); | 92 | Object a = array_pop(vm.stack); |
93 | Object b = array_pop(vm.stack); | 93 | Object b = array_pop(vm.stack); |
94 | array_push(vm.stack, a / b); | 94 | array_push(vm.stack, b / a); |
95 | } break; | 95 | } break; |
96 | case OP_MOD: { | 96 | case OP_MOD: { |
97 | Object a = array_pop(vm.stack); | 97 | Object a = array_pop(vm.stack); |