From da84e7e731de39ff385ae675a023ddcb9c58d06a Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 26 Oct 2021 09:56:18 +0200 Subject: Add support for lambda functions --- src/bytecode/compiler.h | 95 +++++++++++++++++++++++----------------------- src/bytecode/string_view.h | 2 + 2 files changed, 49 insertions(+), 48 deletions(-) (limited to 'src/bytecode') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 9fefd2a..ca187b3 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -248,21 +248,8 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { } 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); +compile_lambda(Chunk *chunk, Compiler *compiler, Token start, StringView name) { + Object fun = make_lambda(name); // FIXME: skipping arguments for now. Assuming nil. next_token(compiler); @@ -285,13 +272,12 @@ compile_fun_op(Chunk *chunk, Compiler *compiler, Token start) { 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_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { +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, @@ -301,7 +287,13 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { }); return; } + parse_tree(chunk, compiler); + compile_lambda(chunk, compiler, start, name.value); + add_code(chunk, OP_DEF, start.line, start.column); +} +void +compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { // FIXME: skipping arguments for now. Assuming nil. // Compile body. @@ -321,9 +313,11 @@ compile_call_op(Chunk *chunk, Compiler *compiler, Token start, Token name) { break; } } - Object obj = make_symbol(name.value); - emit_constant(chunk, start, obj); - add_code(chunk, OP_GET, start.line, start.column); + if (name.type == TOKEN_SYMBOL) { + Object obj = make_symbol(name.value); + emit_constant(chunk, start, obj); + add_code(chunk, OP_GET, start.line, start.column); + } add_code(chunk, OP_CALL, start.line, start.column); } @@ -392,33 +386,38 @@ parse_list(Chunk *chunk, Compiler *compiler, Token start) { }); return; } - Token tok = next_token(compiler); - switch (tok.type) { - case TOKEN_ADD: { compile_list_binary_op(chunk, compiler, start, OP_SUM); } break; - case TOKEN_SUB: { compile_list_binary_op(chunk, compiler, start, OP_SUB); } break; - case TOKEN_MUL: { compile_list_binary_op(chunk, compiler, start, OP_MUL); } break; - case TOKEN_DIV: { compile_list_binary_op(chunk, compiler, start, OP_DIV); } break; - case TOKEN_MOD: { compile_list_binary_op(chunk, compiler, start, OP_MOD); } break; - case TOKEN_NOT: { compile_list_unary_op(chunk, compiler, start, OP_NOT); } break; - case TOKEN_AND: { compile_list_binary_op(chunk, compiler, start, OP_AND); } break; - case TOKEN_OR: { compile_list_binary_op(chunk, compiler, start, OP_OR); } break; - case TOKEN_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_EQUAL); } break; - case TOKEN_LESS: { compile_list_binary_op(chunk, compiler, start, OP_LESS); } break; - case TOKEN_GREATER: { compile_list_binary_op(chunk, compiler, start, OP_GREATER); } break; - case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_LESS_EQUAL); } break; - case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_GREATER_EQUAL); } break; - case TOKEN_PRINT: { compile_list_unary_op(chunk, compiler, start, OP_PRINT); } break; - case TOKEN_DISPLAY: { compile_list_unary_op(chunk, compiler, start, OP_DISPLAY); } break; - 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: { - // TODO: Emit error if compiler knows there hasn't been - // a function delcared with that name. - compile_call_op(chunk, compiler, start, tok); - } break; + while (has_next_token(compiler)) { + Token tok = next_token(compiler); + if (tok.type == TOKEN_LPAREN) { + parse_list(chunk, compiler, tok); + } + switch (tok.type) { + case TOKEN_ADD: { compile_list_binary_op(chunk, compiler, start, OP_SUM); } break; + case TOKEN_SUB: { compile_list_binary_op(chunk, compiler, start, OP_SUB); } break; + case TOKEN_MUL: { compile_list_binary_op(chunk, compiler, start, OP_MUL); } break; + case TOKEN_DIV: { compile_list_binary_op(chunk, compiler, start, OP_DIV); } break; + case TOKEN_MOD: { compile_list_binary_op(chunk, compiler, start, OP_MOD); } break; + case TOKEN_NOT: { compile_list_unary_op(chunk, compiler, start, OP_NOT); } break; + case TOKEN_AND: { compile_list_binary_op(chunk, compiler, start, OP_AND); } break; + case TOKEN_OR: { compile_list_binary_op(chunk, compiler, start, OP_OR); } break; + case TOKEN_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_EQUAL); } break; + case TOKEN_LESS: { compile_list_binary_op(chunk, compiler, start, OP_LESS); } break; + case TOKEN_GREATER: { compile_list_binary_op(chunk, compiler, start, OP_GREATER); } break; + case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_LESS_EQUAL); } break; + case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_GREATER_EQUAL); } break; + case TOKEN_PRINT: { compile_list_unary_op(chunk, compiler, start, OP_PRINT); } break; + case TOKEN_DISPLAY: { compile_list_unary_op(chunk, compiler, start, OP_DISPLAY); } break; + 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_LAMBDA: { compile_lambda(chunk, compiler, start, STRING("lambda")); } break; + case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; + default: { + compile_call_op(chunk, compiler, start, tok); + } break; + } + return; } } diff --git a/src/bytecode/string_view.h b/src/bytecode/string_view.h index 64c8d8e..79d8305 100755 --- a/src/bytecode/string_view.h +++ b/src/bytecode/string_view.h @@ -18,4 +18,6 @@ bool sv_equal(const StringView *a, const StringView *b); // Write a character to the given output stream. void sv_write(const StringView *sv); +#define STRING(STR) (StringView){(STR), sizeof(STR)} + #endif // BDL_STRINGVIEW_H -- cgit v1.2.1