From 8f9a84345c147da5d398331548753d1e350ce846 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 24 Oct 2021 12:04:06 +0200 Subject: Add globals and OP_DEF operation --- src/bytecode/compiler.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ src/bytecode/debug.h | 1 + src/bytecode/main.c | 14 +++++++++----- src/bytecode/objects.h | 16 ++++++++++++++++ src/bytecode/ops.h | 1 + src/bytecode/vm.h | 10 ++++++++++ 6 files changed, 87 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index ec51942..8f3fa81 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -176,6 +176,52 @@ compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { }); } +void +compile_define_op(Chunk *chunk, Visitor *vs, Token start) { + Token name = peek_token(vs); + if (name.type != TOKEN_SYMBOL) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_WRONG_ARG_TYPE, + .line = start.line, + .col = start.column, + }); + return; + } + parse_tree(chunk, vs); + Token expr = peek_token(vs); + if (name.type == TOKEN_EOF || expr.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_UNBALANCED_PAREN, + .line = start.line, + .col = start.column, + }); + return; + } + if (name.type == TOKEN_RPAREN || expr.type == TOKEN_RPAREN) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_NOT_ENOUGH_ARGS, + .line = start.line, + .col = start.column, + }); + return; + } + parse_tree(chunk, vs); + if (peek_token(vs).type != TOKEN_RPAREN) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_TOO_MANY_ARGS, + .line = start.line, + .col = start.column, + }); + return; + } + next_token(vs); + add_code(chunk, OP_DEF, start.line, start.column); +} + void parse_list(Chunk *chunk, Visitor *vs, Token start) { if (!has_next_token(vs)) { @@ -205,6 +251,7 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { case TOKEN_PRINT: { compile_list_unary_op(chunk, vs, start, OP_PRINT); } break; case TOKEN_DISPLAY: { compile_list_unary_op(chunk, vs, start, OP_DISPLAY); } break; case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break; + case TOKEN_DEF: { compile_define_op(chunk, vs, start); } break; default: { error_push((Error){ .type = ERR_TYPE_COMPILER, @@ -219,6 +266,9 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { void parse_tree(Chunk *chunk, Visitor *vs) { Token tok = next_token(vs); + if (errors_n != 0) { + return; + } switch (tok.type) { case TOKEN_FIXNUM: { parse_fixnum(chunk, tok); diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 52cf431..52b237a 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h @@ -9,6 +9,7 @@ size_t disassemble_instruction(Chunk *chunk, size_t offset); static const char* ops_str[] = { // Load/store ops. [OP_CONSTANT] = "OP_CONSTANT", + [OP_DEF] = "OP_DEF", // Arithmetic ops. [OP_SUM] = "OP_SUM", [OP_SUB] = "OP_SUB", diff --git a/src/bytecode/main.c b/src/bytecode/main.c index f7d1f74..85882b3 100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c @@ -8,13 +8,15 @@ // Config. // -// #define DEBUG_TRACE_EXECUTION +#ifdef DEBUG +#define DEBUG_TRACE_EXECUTION +#endif #include "vm.h" +#include "errors.c" #include "compiler.h" #include "ops.h" #include "debug.h" -#include "errors.c" #include "lexer.c" #include "read_line.c" #include "string_view.c" @@ -48,12 +50,14 @@ process_source(const StringView *source) { return; } +#ifdef DEBUG + disassemble_chunk(chunk, "current chunk"); +#endif + // Interpret chunk. vm_interpret(&vm, chunk); - if (errors_n != 0) { - disassemble_chunk(vm.chunk, "current chunk"); - } + // Free resources. chunk_free(chunk); array_free(tokens); } diff --git a/src/bytecode/objects.h b/src/bytecode/objects.h index fc5e069..9744071 100755 --- a/src/bytecode/objects.h +++ b/src/bytecode/objects.h @@ -159,4 +159,20 @@ object_equal(Object a, Object b) { return true; } +Object +object_copy(Object src) { + switch (src.type) { + case OBJ_TYPE_SYMBOL: + case OBJ_TYPE_STRING: { + Object copy = src; + copy.text = NULL; + array_init(copy.text, array_size(src.text)); + array_insert(copy.text, src.text, array_size(src.text)); + return copy; + } break; + default: { break; } break; + } + return src; +} + #endif // BDL_OBJECTS_H diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h index 348df84..63442ac 100755 --- a/src/bytecode/ops.h +++ b/src/bytecode/ops.h @@ -4,6 +4,7 @@ typedef enum Ops { // Load/store ops. OP_CONSTANT, + OP_DEF, // Arithmetic ops. OP_SUM, OP_SUB, diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index f1886ec..23370bb 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h @@ -6,6 +6,7 @@ #include "chunk.h" #include "ops.h" #include "debug.h" +#include "hashtable.h" #define VM_STACK_CAP 1024 @@ -16,6 +17,8 @@ typedef struct VM { u8 *pc; // Stack. Object *stack; + // Global variables. + HashTable *globals; } VM; void vm_init(VM *vm); @@ -27,11 +30,13 @@ void vm_init(VM *vm) { *vm = (VM){0}; array_init(vm->stack, VM_STACK_CAP); + vm->globals = ht_init(); } void vm_free(VM *vm) { array_free(vm->stack); + ht_free(vm->globals); } void @@ -142,6 +147,11 @@ vm_interpret(VM *vm, Chunk *chunk) { Object obj = vm->chunk->constants[constant]; array_push(vm->stack, obj); } break; + case OP_DEF: { + Object value = array_pop(vm->stack); + Object name = array_pop(vm->stack); + ht_insert(vm->globals, name, value); + } break; case OP_SUM: { FIXNUM_ARITHMETIC_OP(+); } break; case OP_SUB: { FIXNUM_ARITHMETIC_OP(-); } break; case OP_MUL: { FIXNUM_ARITHMETIC_OP(*); } break; -- cgit v1.2.1