From 928a58ad7977c0e2e445fd9c16db5726cda789e0 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sat, 23 Oct 2021 13:01:10 +0200 Subject: Add (buggy) initial compilation of arithmetic ops --- src/bytecode/compiler.h | 204 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 197 insertions(+), 7 deletions(-) mode change 100644 => 100755 src/bytecode/compiler.h (limited to 'src/bytecode/compiler.h') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h old mode 100644 new mode 100755 index 6991a86..7ec1ca9 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -31,21 +31,211 @@ has_next_token(const Visitor *visitor) { return visitor->current < array_size(visitor->tokens); } +void +emit_constant(Chunk *chunk, Token tok, Object obj) { + // TODO: Should we deduplicate constants? For example why store a number + // more than once instead of reusing the existing index? + size_t num_idx = add_constant(chunk, obj); + add_code(chunk, OP_CONSTANT, tok.line, tok.column); + add_code(chunk, num_idx, tok.line, tok.column); +} + +void +parse_fixnum(Chunk *chunk, Token tok) { + ssize_t num = 0; + int sign = 1; + for (size_t i = 0; i < tok.value.n; i++) { + char c = tok.value.start[i]; + if (c == '-') { + sign = -1; + continue; + } + num = num * 10 + (c - '0'); + } + emit_constant(chunk, tok, num); +} + +void parse_tree(Chunk *chunk, Visitor *vs); + +void +compile_list_primitive(Chunk *chunk, Visitor *vs, Token op_tok) { + Ops op; + switch (op_tok.type) { + case TOKEN_ADD: { + emit_constant(chunk, op_tok, 0); + op = OP_SUM; + } break; + case TOKEN_SUB: { + // TODO: fetch first element. + emit_constant(chunk, op_tok, 0); + op = OP_SUB; + } break; + case TOKEN_MUL: { + emit_constant(chunk, op_tok, 1); + op = OP_MUL; + } break; + case TOKEN_DIV: { + // TODO: fetch first element. + emit_constant(chunk, op_tok, 1); + op = OP_DIV; + } break; + case TOKEN_MOD: { + // TODO: fetch first element. + emit_constant(chunk, op_tok, 1); + op = OP_MOD; + } break; + default: { + } break; + } + while (has_next_token(vs)) { + Token tok = peek_token(vs); + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_UNBALANCED_PAREN, + .line = op_tok.line, + .col = op_tok.column, + }); + return; + } + if (tok.type == TOKEN_RPAREN) { + next_token(vs); + break; + } + parse_tree(chunk, vs); + add_code(chunk, op, tok.line, tok.column); + } +} + +void +parse_list(Chunk *chunk, Visitor *vs) { + if (has_next_token(vs)) { + Token tok = next_token(vs); + print_token(tok); + // TODO: check if is function call. + switch (tok.type) { + case TOKEN_ADD: + case TOKEN_SUB: + case TOKEN_MUL: + case TOKEN_DIV: + case TOKEN_MOD:{ + compile_list_primitive(chunk, vs, tok); + } break; + default: { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_OBJ_NOT_CALLABLE, + .line = tok.line, + .line = tok.column, + }); + } break; + } + } +} + +void +parse_tree(Chunk *chunk, Visitor *vs) { + Token tok = next_token(vs); + switch (tok.type) { + case TOKEN_FIXNUM: { + parse_fixnum(chunk, tok); + return ; + } break; + case TOKEN_TRUE: { + // return obj_true; + return; + } break; + case TOKEN_FALSE: { + // return obj_false; + return; + } break; + case TOKEN_RPAREN: { + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_UNBALANCED_PAREN, + .line = tok.line, + .col = tok.column, + }); + return; + } break; + case TOKEN_QUOTE: { + // Object *base = make_pair(obj_quote, obj_nil); + // base->cdr = make_pair(obj_nil, obj_nil); + // push_root(base); + // Object *next_obj = parse_tree(vs); + // if (next_obj == obj_err) { + // return obj_err; + // } + // base->cdr->car = next_obj; + // return base; + return; + } break; + case TOKEN_LPAREN: { + parse_list(chunk, vs); + // Object *obj = parse_list(vs); + // if (obj == obj_err) { + // error_push((Error){ + // .type = ERR_TYPE_PARSER, + // .value = ERR_UNBALANCED_PAREN, + // .line = tok.line, + // .col = tok.column, + // }); + // } + // return obj; + return; + } break; + case TOKEN_STRING: { + // Object *obj = make_string(); + // push_root(obj); + // append_string(obj, tok.value); + // return obj; + return; + } break; + case TOKEN_SYMBOL: { + // Object *obj = make_symbol(tok.value); + // push_root(obj); + // return obj; + return; + } break; + case TOKEN_NIL: { + // return obj_nil; + return; + } break; + default: { + break; + } break; + } + error_push((Error){ + .type = ERR_TYPE_PARSER, + .value = ERR_EOF_REACHED, + .line = tok.line, + .col = tok.column, + }); + return; +} + Chunk * compile(Token *tokens) { Chunk *chunk = NULL; chunk = chunk_init(); + Visitor visitor = (Visitor){ + .tokens = tokens, + .current = 0, + }; + while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { + parse_tree(chunk, &visitor); + } // error_push((Error){ // .type = ERR_TYPE_COMPILER, // .value = ERR_UNKNOWN, // }); - size_t const_a = add_constant(chunk, 7); - add_code(chunk, OP_CONSTANT, 1, 1); - add_code(chunk, const_a, 1, 1); - size_t const_b = add_constant(chunk, 2); - add_code(chunk, OP_CONSTANT, 1, 2); - add_code(chunk, const_b, 1, 2); - add_code(chunk, OP_MOD, 1, 3); + // size_t const_a = add_constant(chunk, 7); + // add_code(chunk, OP_CONSTANT, 1, 1); + // add_code(chunk, const_a, 1, 1); + // size_t const_b = add_constant(chunk, 2); + // add_code(chunk, OP_CONSTANT, 1, 2); + // add_code(chunk, const_b, 1, 2); + // add_code(chunk, OP_MOD, 1, 3); add_code(chunk, OP_RETURN, 1, 1); return chunk; } -- cgit v1.2.1