diff --git a/backend/riscv.cpp b/backend/riscv.cpp index 9bedb84..33ee410 100644 --- a/backend/riscv.cpp +++ b/backend/riscv.cpp @@ -157,6 +157,8 @@ namespace elna::riscv void visitor::prologue() { + this->variable_counter = 1; + this->instructions.push_back(instruction(base_opcode::opImm)); this->instructions.push_back(instruction(base_opcode::store)); this->instructions.push_back(instruction(base_opcode::store)); @@ -195,7 +197,7 @@ namespace elna::riscv this->instructions.push_back(instruction(base_opcode::op) .r(x_register::a0, funct3_t::_and, x_register::zero, x_register::zero)); - epilogue(static_cast(variable_counter * 4 + 8 + main_symbol->stack_size())); + epilogue(static_cast(this->variable_counter * 4 + 8 + main_symbol->stack_size())); this->writer->sink(definition->identifier(), reinterpret_cast(this->instructions.data()), this->instructions.size() * sizeof(instruction)); @@ -224,7 +226,7 @@ namespace elna::riscv this->instructions.push_back(instruction(base_opcode::op) .r(x_register::a0, funct3_t::_and, x_register::zero, x_register::zero)); - epilogue(static_cast(variable_counter * 4 + 8 + main_symbol->stack_size())); + epilogue(static_cast(this->variable_counter * 4 + 8 + main_symbol->stack_size())); this->writer->sink("main", reinterpret_cast(this->instructions.data()), this->instructions.size() * sizeof(instruction)); } diff --git a/cli/cl.cpp b/cli/cl.cpp index d2799c0..61dfeed 100644 --- a/cli/cl.cpp +++ b/cli/cl.cpp @@ -38,7 +38,7 @@ namespace elna::cli { for (const auto& compile_error : lex_result.errors()) { - std::cout << compile_error->line() << ':' << compile_error->column() + std::cerr << compile_error->line() << ':' << compile_error->column() << ": " << compile_error->what() << std::endl; } return 1; @@ -49,7 +49,7 @@ namespace elna::cli { for (const auto& compile_error : parser.errors()) { - std::cout << compile_error->line() << ':' << compile_error->column() + std::cerr << compile_error->line() << ':' << compile_error->column() << ": " << compile_error->what() << std::endl; } return 2; diff --git a/include/elna/tester.hpp b/include/elna/tester.hpp index e031ac6..a9b7fd1 100644 --- a/include/elna/tester.hpp +++ b/include/elna/tester.hpp @@ -44,8 +44,10 @@ namespace elna void add_exit_code(const test_status result) noexcept; }; - test_result run_for_output(boost::asio::io_context& context, const std::filesystem::path& binary, - std::initializer_list arguments); + boost::process::v2::process_stdio get_output_streams(const std::uint8_t stream_number, + boost::asio::readable_pipe& read_pipe); + test_result run_for_output(boost::asio::io_context& context, const std::uint8_t stream_number, + const std::filesystem::path& binary, std::initializer_list arguments); test_result build_test(boost::asio::io_context& context, const std::filesystem::directory_entry& test_entry); test_result run_test(boost::asio::io_context& context, const std::filesystem::directory_entry& test_entry); void print_result(const std::filesystem::directory_entry& test_entry, const test_result& result); diff --git a/source/parser.cpp b/source/parser.cpp index 8db99c4..d47e4df 100644 --- a/source/parser.cpp +++ b/source/parser.cpp @@ -516,18 +516,43 @@ namespace elna::source } auto definition_identifier = iterator.advance(token::type::identifier); - if (!definition_identifier.has_value() || !iterator.skip(token::type::semicolon)) + if (!definition_identifier.has_value() || !iterator.skip(token::type::left_paren)) { return nullptr; } + std::vector> declarations; + while (!iterator.current(token::type::right_paren)) + { + std::unique_ptr parsed_declaration = parse_declaration(); + if (parsed_declaration == nullptr) + { + return nullptr; + } + declarations.push_back(std::move(parsed_declaration)); + + if (iterator->of() == token::type::comma) + { + ++iterator; + continue; + } + else if (iterator->of() != token::type::right_paren) + { + iterator.add_error(*iterator); + return nullptr; + } + } + iterator.skip(token::type::right_paren); auto definition_body = parse_block(); if (definition_body == nullptr || !iterator.skip(token::type::semicolon)) { return nullptr; } - return std::make_unique(definition_identifier->get().identifier(), + auto procedure = std::make_unique(definition_identifier->get().identifier(), std::move(definition_body)); + procedure->parameters() = std::move(declarations); + + return procedure; } std::unique_ptr parser::parse_declaration() diff --git a/tests/expectations/procedure_2_statements.txt b/tests/expectations/procedure_2_statements.txt new file mode 100644 index 0000000..7c1a169 --- /dev/null +++ b/tests/expectations/procedure_2_statements.txt @@ -0,0 +1,2 @@ +5 +3 diff --git a/tests/expectations/procedure_print_argument.txt b/tests/expectations/procedure_print_argument.txt new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/tests/expectations/procedure_print_argument.txt @@ -0,0 +1 @@ +5 diff --git a/tests/procedure_2_statements.eln b/tests/procedure_2_statements.eln new file mode 100644 index 0000000..447a9a1 --- /dev/null +++ b/tests/procedure_2_statements.eln @@ -0,0 +1,9 @@ +proc g() +begin + writei(5); + writei(3) +end; + +begin + g() +end. diff --git a/tests/procedure_definition.eln b/tests/procedure_definition.eln index 94bbe85..fe500f5 100644 --- a/tests/procedure_definition.eln +++ b/tests/procedure_definition.eln @@ -1,4 +1,4 @@ -proc f; writei(5); +proc f() writei(5); begin f() diff --git a/tests/procedure_print_argument.eln b/tests/procedure_print_argument.eln new file mode 100644 index 0000000..92ab218 --- /dev/null +++ b/tests/procedure_print_argument.eln @@ -0,0 +1,5 @@ +proc f(a: Int) writei(a); + +begin + f(5) +end. diff --git a/tests/tester.cpp b/tests/tester.cpp index 6376aaa..284a67d 100755 --- a/tests/tester.cpp +++ b/tests/tester.cpp @@ -43,17 +43,33 @@ namespace elna return in_build_directory() / path; } - test_result run_for_output(boost::asio::io_context& context, const std::filesystem::path& binary, - std::initializer_list arguments) + boost::process::v2::process_stdio get_output_streams(const std::uint8_t stream_number, + boost::asio::readable_pipe& read_pipe) + { + if (stream_number == 1) + { + return boost::process::v2::process_stdio{ nullptr, read_pipe }; + } + if (stream_number == 2) + { + return boost::process::v2::process_stdio{ nullptr, {}, read_pipe }; + } + return boost::process::v2::process_stdio{ nullptr, read_pipe, read_pipe }; + } + + test_result run_for_output(boost::asio::io_context& context, const std::uint8_t stream_number, + const std::filesystem::path& binary, std::initializer_list arguments) { boost::asio::readable_pipe read_pipe{ context }; test_result result{}; std::string output; boost::asio::dynamic_string_buffer buffer = boost::asio::dynamic_buffer(output); boost::system::error_code ec; + + boost::process::v2::process_stdio process_stdio; boost::process::v2::process elna_child(context, binary, arguments, - boost::process::v2::process_stdio{ nullptr, read_pipe, read_pipe }); + get_output_streams(stream_number, read_pipe)); do { std::size_t transferred = read_pipe.read_some(buffer.prepare(512), ec); @@ -84,7 +100,7 @@ namespace elna std::filesystem::remove(test_binary); std::filesystem::remove(test_object); - test_result result = run_for_output(context, "./build/bin/elna", + test_result result = run_for_output(context, 2, "./build/bin/elna", { "-o", test_object.string(), test_entry.path().string() }); if (result.code != 0) @@ -157,7 +173,7 @@ namespace elna std::filesystem::path test_binary = in_build_directory(test_filename); test_binary.replace_extension(); - return run_for_output(context, + return run_for_output(context, 1, boost::process::search_path("qemu-riscv32"), { test_binary.string() }); }