From f0b6af9dad131033f1a37b0f52d86cafdf58d15c Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Wed, 25 Jan 2023 09:21:46 +0100 Subject: [PATCH] It compiles things! --- CMakeLists.txt | 2 +- include/molasses/parser_primitives.h | 34 +++--- src/main.cpp | 15 ++- src/molasses/parser_primitives.cpp | 155 +++++++++++++++++---------- 4 files changed, 132 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebdfb74..4205f73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(sugar) -find_package(cppfront REQUIRED) +# find_package(cppfront REQUIRED) set(CMAKE_CXX_STANDARD 20) diff --git a/include/molasses/parser_primitives.h b/include/molasses/parser_primitives.h index a37756c..dd8bb7b 100644 --- a/include/molasses/parser_primitives.h +++ b/include/molasses/parser_primitives.h @@ -42,9 +42,8 @@ namespace molasses { [[nodiscard]] virtual std::string name() const = 0; [[nodiscard]] virtual std::vector argument_types() const = 0; [[nodiscard]] virtual std::vector return_types() const = 0; - [[nodiscard]] virtual std::vector generate(const parser_context&) const = 0; - - // Add generate() -> instruction[] + [[nodiscard]] virtual std::vector generate(const parser_context&, const lexed_output& lexer_data) const = 0; + [[nodiscard]] virtual std::vector emit(const parser_context&) const = 0; }; struct primitive_operation : public operation { @@ -53,10 +52,11 @@ namespace molasses { std::vector _rets; std::vector _instructions; - primitive_operation(std::string name, std::vector args, std::vector rets) + primitive_operation(std::string name, std::vector args, std::vector rets, std::vector body) : _name(std::forward(name)) , _args(std::forward>(args)) - , _rets(std::forward>(rets)) + , _rets(std::forward>(rets)) + , _instructions(std::forward>(body)) {} [[nodiscard]] std::string name() const final { @@ -68,9 +68,12 @@ namespace molasses { [[nodiscard]] std::vector return_types() const final { return _rets; } - [[nodiscard]] std::vector generate(const parser_context&) const final { - return _instructions; - } + [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final { + return {}; + } + [[nodiscard]] std::vector emit(const parser_context&) const final { + return _instructions; + } }; struct procedure_operation : public operation { @@ -95,7 +98,8 @@ namespace molasses { [[nodiscard]] std::vector return_types() const final { return _rets; } - [[nodiscard]] std::vector generate(const parser_context&) const final; + [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final; + [[nodiscard]] std::vector emit(const parser_context&) const final; }; inline auto operator<=>(const operation& lhs, const operation& rhs) { @@ -118,10 +122,14 @@ namespace molasses { UnexpectedTokenError() : std::runtime_error("An unexpected token has been encountered") {} // TODO: Better error message }; - struct ExpectingTokenError : std::runtime_error { - ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {} - // TODO: Better error message - }; + struct ExpectingTokenError : std::runtime_error { + ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {} + // TODO: Better error message + }; + struct UnknownTokenError : std::runtime_error { + UnknownTokenError() : std::runtime_error("An unknown token has not been encountered") {} + // TODO: Better error message + }; std::vector operator>>(std::vector current_stack, const operation& next_op); diff --git a/src/main.cpp b/src/main.cpp index 1779e2b..80c7929 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,20 @@ int main() { molasses::parser_context ctx; ctx = molasses::register_integers(ctx); - ctx.operations.emplace_back(std::make_shared(std::string{"+"}, std::vector({"i32", "i32"}), std::vector({"i32"}))); + ctx.operations.emplace_back( + std::make_shared( + std::string{"+"}, + std::vector({"i32", "i32"}), + std::vector({"i32"}), + std::vector({ + " popq %rax\n", + " popq %rbx\n", + " addl %ebx, %eax\n", + " andl $0xFFFFFFFF, %eax\n", + " pushq %rax\n" + }) + ) + ); molasses::parse(ctx, lexed); } diff --git a/src/molasses/parser_primitives.cpp b/src/molasses/parser_primitives.cpp index 0eee99c..3503ef8 100644 --- a/src/molasses/parser_primitives.cpp +++ b/src/molasses/parser_primitives.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "molasses/parser_primitives.h" namespace molasses { @@ -88,7 +89,27 @@ namespace molasses { return type_stack == execution_output; } - + + std::vector initialize_stack() { + return { + ".bss\n",// TODO: make threadlocal + "stack_instruction:\n", + " .quad 0\n", + ".text\n", + "initialize_callstack:\n", + " movq $9, %rax\n", + " movq $0, %rdi\n", + " movq $8192, %rsi\n", + " movq $3, %rdx\n", + " movq $34, %r10\n", + " movq $-1, %r8\n", + " movq $0, %r9\n", + " syscall\n", + " movq %rax, (stack_instruction)\n", + " retq\n", + }; + } + parser_context parse(parser_context ctx, const lexed_output& lexer_data) { enum op : int { DO_KW = 1, @@ -159,70 +180,86 @@ namespace molasses { return std::make_pair(it, std::make_shared(name, argument_types, return_types, body)); #undef CHECK_FOR_UNEXPECTED_STREAM_END }; - - auto [iterator, procedure] = parse_proc(tokens.symbols.begin()); - ctx.operations.push_back(procedure); - parsed_procedures.emplace_back(std::move(procedure)); - + + auto progress = tokens.symbols.begin(); + + do { + auto [iterator, procedure] = parse_proc(progress); + ctx.operations.push_back(procedure); + parsed_procedures.emplace_back(std::move(procedure)); + progress = iterator; + } while (progress != tokens.symbols.end()); + for(auto& proc : parsed_procedures) { if(not type_check(ctx, tokens, proc->_body, proc->_args, proc->_rets)) { throw ProcedureStackError(); } } + + std::vector generated; + + for(auto instr : initialize_stack()) { + generated.push_back(instr); + } + + for(auto proc : parsed_procedures) { + for(auto instr : proc->generate(ctx, tokens)) { + generated.push_back(instr); + } + } + + for(auto line : generated) { + std::cout << line; + } return ctx; } - - std::vector initialize_stack() { - return { - ".bss\n",// TODO: make threadlocal - "stack_instruction:", - " .quad 0", - ".text\n", - "initialize_callstack:\n", - " movq $9, %rax\n", - " movq $0, %rdi\n", - " movq $8192, %rsi\n", - " movq $3, %rdx\n", - " movq $34, %r10\n", - " movq $-1, %r8\n", - " movq $0, %r9\n", - " syscall\n", - " movq %rax, (stack_instruction)\n", - " retq\n", - }; - } - - std::vector generate_call(std::string target) { - static uint64_t label_count= 0; - return { - "movq return_label_n"+std::to_string(label_count)+", (stack_instruction)\n", - "addq $8, stack_instruction\n", - "jmp "+target+"\n", - "return_label_n"+std::to_string(label_count++)+":" - }; - } - - std::vector procedure_operation::generate(const parser_context& ctx) const { - size_t initial_stack = 0; - size_t final_stack = 0; - for(const auto& elem : argument_types()) { - initial_stack += ctx.lookup_type(elem)->byte_size(); - } - for(const auto& elem : return_types()) { - final_stack += ctx.lookup_type(elem)->byte_size(); - } - std::vector ops; - ops.emplace_back(name()+":\n"); - - - - // Return to caller - ops.emplace_back(" addq $-8, stack_instruction\n"); - ops.emplace_back(" movq (stack_instruction), %rax\n"); - ops.emplace_back(" pushq %rax\n"); - ops.emplace_back(" retq\n"); - - return ops; - } + + std::vector generate_call(std::string target) { + static uint64_t label_count= 0; + return { + " movq return_label_n"+std::to_string(label_count)+", (stack_instruction)\n", + " addq $8, stack_instruction\n", + " jmp "+target+"\n", + " return_label_n"+std::to_string(label_count++)+":" + }; + } + + std::vector generate_push_int32(int32_t target) { + return { + " pushq $" +std::to_string(target)+ "\n" + }; + } + + std::vector procedure_operation::generate(const parser_context& ctx, const lexed_output& lexer_data) const { + std::vector ops; + ops.emplace_back(name()+":\n"); + + for(auto elem : _body) { + auto token = lexer_data.dictionary.at(elem); + if(auto result = try_parse_int32(token); result) { + for(auto&& elem : generate_push_int32(result.value())) { + ops.push_back(elem); + } + } else if(auto op = ctx.lookup_operation(token); op) { + for(auto&& elem : op->emit(ctx)) { + ops.push_back(elem); + } + } else { + throw UnknownTokenError(); + } + } + + ops.emplace_back(" // Return to caller\n"); + ops.emplace_back(" addq $-8, stack_instruction\n"); + ops.emplace_back(" movq (stack_instruction), %rax\n"); + ops.emplace_back(" pushq %rax\n"); + ops.emplace_back(" retq\n"); + + return ops; + } + + std::vector procedure_operation::emit(const parser_context& ctx) const { + return generate_call(name()); + } }