diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-23 13:01:10 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-23 13:01:10 +0200 |
commit | 928a58ad7977c0e2e445fd9c16db5726cda789e0 (patch) | |
tree | cfa97b293213550253b268c59100e37f9246b4f1 /src/bytecode/compiler.h | |
parent | 9bb350e99370009a18df3c3b8f512d2c11168978 (diff) | |
download | bdl-928a58ad7977c0e2e445fd9c16db5726cda789e0.tar.gz bdl-928a58ad7977c0e2e445fd9c16db5726cda789e0.zip |
Add (buggy) initial compilation of arithmetic ops
Diffstat (limited to 'src/bytecode/compiler.h')
-rwxr-xr-x[-rw-r--r--] | src/bytecode/compiler.h | 204 |
1 files changed, 197 insertions, 7 deletions
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 | } |