From b743e03fc6042e3e2d55cfa0387c092824de64c5 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 24 Oct 2021 09:52:09 +0200 Subject: Add print/display/newline ops --- src/bytecode/compiler.h | 103 ++++++++++++++++++++++++++++++++---------------- src/bytecode/debug.h | 35 ++++++++++++---- src/bytecode/lexer.c | 6 +++ src/bytecode/lexer.h | 3 ++ src/bytecode/main.c | 2 +- src/bytecode/ops.h | 9 +++++ src/bytecode/vm.h | 31 ++++++++++++++- 7 files changed, 147 insertions(+), 42 deletions(-) (limited to 'src/bytecode') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 02d938f..d404a5a 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -58,7 +58,7 @@ parse_fixnum(Chunk *chunk, Token tok) { void parse_tree(Chunk *chunk, Visitor *vs); void -compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { +compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { size_t n = 0; while (has_next_token(vs)) { Token tok = peek_token(vs); @@ -66,8 +66,8 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_UNBALANCED_PAREN, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); return; } @@ -77,8 +77,8 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_NOT_ENOUGH_ARGS, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); return; } @@ -87,12 +87,12 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { parse_tree(chunk, vs); n++; } - emit_constant(chunk, list_start, FIXNUM_VAL(n)); - add_code(chunk, op, list_start.line, list_start.column); + emit_constant(chunk, start, FIXNUM_VAL(n)); + add_code(chunk, op, start.line, start.column); } void -compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { +compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { size_t n = 0; while (has_next_token(vs)) { Token tok = peek_token(vs); @@ -100,8 +100,8 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_UNBALANCED_PAREN, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); return; } @@ -111,57 +111,94 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_NOT_ENOUGH_ARGS, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); } return; } parse_tree(chunk, vs); - add_code(chunk, op, list_start.line, list_start.column); + add_code(chunk, op, start.line, start.column); n++; if (n > 1) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_TOO_MANY_ARGS, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); } } error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_UNBALANCED_PAREN, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); } void -parse_list(Chunk *chunk, Visitor *vs, Token list_start) { +compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { + if (has_next_token(vs)) { + Token tok = peek_token(vs); + 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) { + 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, start.line, start.column); + return; + } + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_UNBALANCED_PAREN, + .line = start.line, + .col = start.column, + }); +} + +void +parse_list(Chunk *chunk, Visitor *vs, Token start) { if (!has_next_token(vs)) { error_push((Error){ .type = ERR_TYPE_COMPILER, .value = ERR_UNBALANCED_PAREN, - .line = list_start.line, - .col = list_start.column, + .line = start.line, + .col = start.column, }); } Token tok = next_token(vs); switch (tok.type) { - case TOKEN_ADD: { compile_list_binary_op(chunk, vs, list_start, OP_SUM); } break; - case TOKEN_SUB: { compile_list_binary_op(chunk, vs, list_start, OP_SUB); } break; - case TOKEN_MUL: { compile_list_binary_op(chunk, vs, list_start, OP_MUL); } break; - case TOKEN_DIV: { compile_list_binary_op(chunk, vs, list_start, OP_DIV); } break; - case TOKEN_MOD: { compile_list_binary_op(chunk, vs, list_start, OP_MOD); } break; - case TOKEN_NOT: { compile_list_unary_op(chunk, vs, list_start, OP_NOT); } break; - case TOKEN_AND: { compile_list_binary_op(chunk, vs, list_start, OP_AND); } break; - case TOKEN_OR: { compile_list_binary_op(chunk, vs, list_start, OP_OR); } break; - case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_EQUAL); } break; - case TOKEN_LESS: { compile_list_binary_op(chunk, vs, list_start, OP_LESS); } break; - case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER); } break; - case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_LESS_EQUAL); } break; - case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER_EQUAL); } break; + case TOKEN_ADD: { compile_list_binary_op(chunk, vs, start, OP_SUM); } break; + case TOKEN_SUB: { compile_list_binary_op(chunk, vs, start, OP_SUB); } break; + case TOKEN_MUL: { compile_list_binary_op(chunk, vs, start, OP_MUL); } break; + case TOKEN_DIV: { compile_list_binary_op(chunk, vs, start, OP_DIV); } break; + case TOKEN_MOD: { compile_list_binary_op(chunk, vs, start, OP_MOD); } break; + case TOKEN_NOT: { compile_list_unary_op(chunk, vs, start, OP_NOT); } break; + case TOKEN_AND: { compile_list_binary_op(chunk, vs, start, OP_AND); } break; + case TOKEN_OR: { compile_list_binary_op(chunk, vs, start, OP_OR); } break; + case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_EQUAL); } break; + case TOKEN_LESS: { compile_list_binary_op(chunk, vs, start, OP_LESS); } break; + case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, start, OP_GREATER); } break; + case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_LESS_EQUAL); } break; + case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_GREATER_EQUAL); } break; + 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; default: { error_push((Error){ .type = ERR_TYPE_COMPILER, diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 42b5b93..52cf431 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h @@ -6,6 +6,33 @@ void disassemble_chunk(Chunk *chunk, const char *name); size_t disassemble_instruction(Chunk *chunk, size_t offset); +static const char* ops_str[] = { + // Load/store ops. + [OP_CONSTANT] = "OP_CONSTANT", + // Arithmetic ops. + [OP_SUM] = "OP_SUM", + [OP_SUB] = "OP_SUB", + [OP_MUL] = "OP_MUL", + [OP_DIV] = "OP_DIV", + [OP_MOD] = "OP_MOD", + // Logic ops. + [OP_NOT] = "OP_NOT", + [OP_AND] = "OP_AND", + [OP_OR] = "OP_OR", + // Numerical comparison ops. + [OP_EQUAL] = "OP_EQUAL", + [OP_LESS] = "OP_LESS", + [OP_GREATER] = "OP_GREATER", + [OP_LESS_EQUAL] = "OP_LESS_EQUAL", + [OP_GREATER_EQUAL] = "OP_GREATER_EQUAL", + // Display ops. + [OP_DISPLAY] = "OP_DISPLAY", + [OP_PRINT] = "OP_PRINT", + [OP_NEWLINE] = "OP_NEWLINE", + // Return. + [OP_RETURN] = "OP_RETURN", +}; + void disassemble_chunk(Chunk *chunk, const char *name) { printf("== %s ==\n", name); @@ -43,14 +70,8 @@ disassemble_instruction(Chunk *chunk, size_t offset) { printf("\n"); return offset + 2; } break; - case OP_SUM: { printf("OP_SUM\n"); return offset + 1; } break; - case OP_SUB: { printf("OP_SUB\n"); return offset + 1; } break; - case OP_MUL: { printf("OP_MUL\n"); return offset + 1; } break; - case OP_DIV: { printf("OP_DIV\n"); return offset + 1; } break; - case OP_MOD: { printf("OP_MOD\n"); return offset + 1; } break; - case OP_RETURN: { printf("OP_RETURN\n"); return offset + 1; } break; default: { - printf("Unknown OP: %d\n", instruction); + printf("%s\n", ops_str[instruction]); return offset + 1; } break; } diff --git a/src/bytecode/lexer.c b/src/bytecode/lexer.c index 207cebb..d157111 100755 --- a/src/bytecode/lexer.c +++ b/src/bytecode/lexer.c @@ -16,6 +16,9 @@ static const char* token_str[] = { [TOKEN_DEF] = "TOKEN_DEF", [TOKEN_FUN] = "TOKEN_FUN", [TOKEN_LAMBDA] = "TOKEN_LAMBDA", + [TOKEN_DISPLAY] = "TOKEN_DISPLAY", + [TOKEN_PRINT] = "TOKEN_PRINT", + [TOKEN_NEWLINE] = "TOKEN_NEWLINE", [TOKEN_ADD] = "TOKEN_ADD", [TOKEN_SUB] = "TOKEN_SUB", [TOKEN_MUL] = "TOKEN_MUL", @@ -146,6 +149,9 @@ find_primitive_type(const StringView value) { if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; } if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } + if (TOKEN_IS_KEYWORD(value, "display")) { return TOKEN_DISPLAY; } + if (TOKEN_IS_KEYWORD(value, "print")) { return TOKEN_PRINT; } + if (TOKEN_IS_KEYWORD(value, "newline")) { return TOKEN_NEWLINE; } if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; } if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_SUB; } if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; } diff --git a/src/bytecode/lexer.h b/src/bytecode/lexer.h index cee2915..7f9eb24 100755 --- a/src/bytecode/lexer.h +++ b/src/bytecode/lexer.h @@ -25,6 +25,9 @@ typedef enum TokenType { TOKEN_DEF, TOKEN_FUN, TOKEN_LAMBDA, + TOKEN_DISPLAY, + TOKEN_PRINT, + TOKEN_NEWLINE, // Arithmetic. TOKEN_ADD, diff --git a/src/bytecode/main.c b/src/bytecode/main.c index bad150c..f7d1f74 100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c @@ -8,7 +8,7 @@ // Config. // -#define DEBUG_TRACE_EXECUTION +// #define DEBUG_TRACE_EXECUTION #include "vm.h" #include "compiler.h" diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h index b59d65a..348df84 100755 --- a/src/bytecode/ops.h +++ b/src/bytecode/ops.h @@ -2,20 +2,29 @@ #define BDL_OPS_H typedef enum Ops { + // Load/store ops. OP_CONSTANT, + // Arithmetic ops. OP_SUM, OP_SUB, OP_MUL, OP_DIV, OP_MOD, + // Logic ops. OP_NOT, OP_AND, OP_OR, + // Numerical comparison ops. OP_EQUAL, OP_LESS, OP_GREATER, OP_LESS_EQUAL, OP_GREATER_EQUAL, + // Display ops. + OP_DISPLAY, + OP_PRINT, + OP_NEWLINE, + // Return. OP_RETURN, } Ops; diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index b3dd8c3..f1886ec 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h @@ -159,8 +159,37 @@ vm_interpret(VM *vm, Chunk *chunk) { case OP_GREATER: { FIXNUM_COMPARE_OP(>); } break; case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; - case OP_RETURN: { + case OP_DISPLAY: { display(array_pop(vm->stack)); + } break; + case OP_PRINT: { + Object obj = array_pop(vm->stack); + if (!IS_STRING(obj)) { + WRONG_ARG_ERR(); + } + StringView scanner = (StringView) { + .start = obj.text, + .n = array_size(obj.text), + }; + while (scanner.n != 0) { + char c = sv_next(&scanner); + if (c == '\\' && sv_peek(&scanner) == 'n') { + putchar('\n'); + sv_next(&scanner); + continue; + } + if (c == '\\' && sv_peek(&scanner) == '"') { + putchar('"'); + sv_next(&scanner); + continue; + } + putchar(c); + } + } break; + case OP_NEWLINE: { + printf("\n"); + } break; + case OP_RETURN: { printf("\n"); return; } break; -- cgit v1.2.1