From d54e595644fcaf6756d53d368213ad3129c49327 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 25 Oct 2021 15:46:48 +0200 Subject: Add initial `fun` declaration compilation --- src/bytecode/compiler.h | 57 +++++++++++++++++++++++++++++++++++++++----- src/bytecode/hashtable.h | 4 +--- src/bytecode/main.c | 11 ++++----- src/bytecode/objects.c | 10 ++++++++ src/bytecode/vm.h | 61 +++++++++++++++++++++++++----------------------- 5 files changed, 99 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 4130269..2c7827f 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -14,7 +14,7 @@ Token next_token(Compiler *compiler); Token peek_token(const Compiler *compiler); bool has_next_token(const Compiler *compiler); -Object compile(Token *tokens); +Chunk * compile(Token *tokens); Token peek_token(const Compiler *compiler) { @@ -247,6 +247,49 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { add_code(chunk, op, start.line, start.column); } +void +compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) { + Token name = peek_token(compiler); + 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, compiler); + + // TODO: compile lambda expression. + Object fun = make_lambda(name.value); + // FIXME: skipping arguments for now. Assuming nil. + next_token(compiler); + + // Compile body. + while (has_next_token(compiler)) { + Token tok = peek_token(compiler); + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_UNBALANCED_PAREN, + .line = start.line, + .col = start.column, + }); + return; + } + if (tok.type == TOKEN_RPAREN) { + next_token(compiler); + break; + } + parse_tree(fun.chunk, compiler); + } + add_code(fun.chunk, OP_RETURN, start.line, start.column); + + emit_constant(chunk, start, fun); + add_code(chunk, OP_DEF, start.line, start.column); +} + void compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { Token tok = peek_token(compiler); @@ -332,6 +375,7 @@ parse_list(Chunk *chunk, Compiler *compiler, Token start) { case TOKEN_NEWLINE: { compile_list_simple_op(chunk, compiler, start, OP_NEWLINE); } break; case TOKEN_DEF: { compile_declare_op(chunk, compiler, start, OP_DEF); } break; case TOKEN_SET: { compile_declare_op(chunk, compiler, start, OP_SET); } break; + case TOKEN_FUN: { compile_fun_op(chunk, compiler, start); } break; case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; default: { error_push((Error){ @@ -415,19 +459,20 @@ parse_tree(Chunk *chunk, Compiler *compiler) { return; } -Object +Chunk * compile(Token *tokens) { - Object main = make_lambda((StringView){"main", sizeof("main")}); + Chunk *chunk = NULL; + chunk = NEW_CHUNK("main"); Compiler compiler = (Compiler){ .tokens = tokens, .current = 0, }; Token start_tok = peek_token(&compiler); while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { - parse_tree(main.chunk, &compiler); + parse_tree(chunk, &compiler); } - add_code(main.chunk, OP_RETURN, start_tok.line, start_tok.column); - return main; + add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); + return chunk; } #endif // BDL_COMPILER_H diff --git a/src/bytecode/hashtable.h b/src/bytecode/hashtable.h index 48665d3..1f47666 100644 --- a/src/bytecode/hashtable.h +++ b/src/bytecode/hashtable.h @@ -112,7 +112,7 @@ _ht_insert(HashTable *table, Object key, Object value) { if (!update) { array_push(table->keys, object_copy(key)); - array_push(table->values, object_copy(value)); + array_push(table->values, value); pairs[probe_position].key = &table->keys[array_size(table->keys) - 1]; pairs[probe_position].value = &table->values[array_size(table->values) - 1]; } else { @@ -155,7 +155,6 @@ _ht_maybe_grow(HashTable *table) { Object key = old_keys[i]; Object value = old_values[i]; object_free(key); - object_free(value); } array_free(old_keys); array_free(old_values); @@ -205,7 +204,6 @@ ht_free(HashTable *table) { Object key = table->keys[i]; Object value = table->values[i]; object_free(key); - object_free(value); } array_free(table->keys); array_free(table->values); diff --git a/src/bytecode/main.c b/src/bytecode/main.c index e4cf643..7cb0a2a 100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c @@ -45,27 +45,26 @@ process_source(const StringView *source) { } // Compile chunk. - Object main = compile(tokens); + Chunk *main = compile(tokens); if (errors_n != 0) { - object_free(main); + chunk_free(main); array_free(tokens); return; } #ifdef DEBUG - disassemble_chunk(main.chunk); + disassemble_chunk(main); #endif // Interpret chunk. CallFrame frame = (CallFrame){ - .procedure = main, - .pc = main.chunk->code, + .chunk = main, }; array_push(vm.frames, frame); vm_interpret(&vm); // Free resources. - object_free(main); + chunk_free(main); array_free(tokens); } diff --git a/src/bytecode/objects.c b/src/bytecode/objects.c index 14dc057..e446fb0 100644 --- a/src/bytecode/objects.c +++ b/src/bytecode/objects.c @@ -120,6 +120,16 @@ object_copy(Object src) { array_insert(copy.text, src.text, array_size(src.text)); return copy; } break; + case OBJ_TYPE_LAMBDA: { + Object copy = src; + StringView name = (StringView){ + .start = src.chunk->name, + .n = array_size(src.chunk->name), + }; + // TODO: copy full chunk? + // copy.chunk = chunk_init(name); + return copy; + } break; default: { break; } break; } return src; diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 23c3d89..f7852de 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h @@ -13,17 +13,20 @@ typedef struct CallFrame { // Current code being run. - Object procedure; + Chunk *chunk; // Current program counter for this call. - u8 *pc; // Ref to stack. Is this really needed? - // Object *stack; + // Object *locals; + // Return counter. + u8 *rp; } CallFrame; typedef struct VM { CallFrame *frames; // Stack. Object *stack; + // Program counter. + u8 *pc; // Global variables. HashTable *globals; } VM; @@ -37,9 +40,6 @@ void vm_init(VM *vm) { *vm = (VM){0}; array_init(vm->frames, VM_FRAMES_CAP); - for (size_t i = 0; i < array_cap(vm->frames); i++) { - vm->frames[i] = (CallFrame){0}; - } array_init(vm->stack, VM_STACK_CAP); vm->globals = ht_init(); } @@ -62,16 +62,16 @@ vm_reset(VM *vm) { error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ .value = ERR_WRONG_ARG_TYPE, \ - .line = chunk->lines[frame->pc - chunk->code - 1].line, \ - .col = chunk->lines[frame->pc - chunk->code - 1].col, \ + .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ + .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ }) #define SYMBOL_NOT_FOUND_ERR() \ error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ .value = ERR_SYMBOL_NOT_FOUND, \ - .line = chunk->lines[frame->pc - chunk->code - 1].line, \ - .col = chunk->lines[frame->pc - chunk->code - 1].col, \ + .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ + .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ }) #define FIXNUM_ARITHMETIC_OP(OP) \ @@ -137,9 +137,9 @@ vm_reset(VM *vm) { void vm_interpret(VM *vm) { CallFrame *frame = &vm->frames[array_size(vm->frames) - 1]; - Chunk *chunk = frame->procedure.chunk; + vm->pc = frame->chunk->code; - if (chunk->code == NULL || array_size(chunk->code) == 0) { + if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_EMPTY_CHUNK, @@ -147,8 +147,8 @@ vm_interpret(VM *vm) { return; } - u8 *last = chunk->code + array_size(chunk->code); - while (frame->pc < last) { + u8 *last = frame->chunk->code + array_size(frame->chunk->code); + while (vm->pc < last) { #ifdef DEBUG_TRACE_EXECUTION printf("stack: [ "); for (size_t i = 0; i < array_size(vm->stack); i++) { @@ -158,13 +158,13 @@ vm_interpret(VM *vm) { } } printf(" ]\nop: "); - disassemble_instruction(chunk, (frame->pc - chunk->code)); + disassemble_instruction(frame->chunk, (vm->pc - frame->chunk->code)); #endif - u8 instruction = *frame->pc++; + u8 instruction = *vm->pc++; switch (instruction) { case OP_CONSTANT: { - u8 constant = *frame->pc++; - Object obj = chunk->constants[constant]; + u8 constant = *vm->pc++; + Object obj = frame->chunk->constants[constant]; array_push(vm->stack, obj); } break; case OP_DEF: { @@ -209,17 +209,17 @@ vm_interpret(VM *vm) { case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; case OP_JUMP: { - u16 a = *frame->pc++; - u16 b = *frame->pc++; + u16 a = *vm->pc++; + u16 b = *vm->pc++; s16 offset = (a << 8) | b; - frame->pc += offset; + vm->pc += offset; } break; case OP_JUMP_IF_FALSE: { - u16 a = *frame->pc++; - u16 b = *frame->pc++; + u16 a = *vm->pc++; + u16 b = *vm->pc++; s16 offset = (a << 8) | b; if (IS_FALSE(array_pop(vm->stack))) { - frame->pc += offset; + vm->pc += offset; } } break; case OP_DISPLAY: { @@ -253,15 +253,18 @@ vm_interpret(VM *vm) { printf("\n"); } break; case OP_RETURN: { - printf("\n"); + if (frame->rp != NULL) { + // TODO: restore previous call frame. + vm->pc = frame->rp; + } return; } break; default: { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_NOT_IMPLEMENTED, - .line = chunk->lines[frame->pc - chunk->code - 1].line, - .col = chunk->lines[frame->pc - chunk->code - 1].col, + .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, + .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, }); return; } break; @@ -271,8 +274,8 @@ vm_interpret(VM *vm) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_PC_OOB, - .line = chunk->lines[0].line, - .col = chunk->lines[0].col, + .line = frame->chunk->lines[0].line, + .col = frame->chunk->lines[0].col, }); } -- cgit v1.2.1