From ec04e05b7bbc093ddbecdf35a84db7a7f4cfa4c5 Mon Sep 17 00:00:00 2001 From: programsnail Date: Sun, 21 Apr 2024 18:00:12 +0300 Subject: [PATCH] better test formatting, etc. --- include/parsing_tree.hpp | 11 ++++-- include/printers.hpp | 76 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 65 +++++++++++++++++++++------------- 3 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 include/printers.hpp diff --git a/include/parsing_tree.hpp b/include/parsing_tree.hpp index 0abb6fb..77cad37 100644 --- a/include/parsing_tree.hpp +++ b/include/parsing_tree.hpp @@ -1,13 +1,14 @@ #pragma once +#include #include #include #include #include #include -#include "utils.hpp" #include "types.hpp" +#include "utils.hpp" namespace nodes { @@ -22,10 +23,10 @@ using ExprPtr = shared_ptr; using ExprPtrV = std::vector; struct Arg : public NodeInfo { - Arg(string name, types::Mode mode_hint = {}) : name(std::move(name)), mode_hint(mode_hint) {} + Arg(string name, types::Mode mode_hint = {}) + : name(std::move(name)), mode_hint(mode_hint) {} string name; - types::Mode mode_hint; }; @@ -110,6 +111,10 @@ inline ExprPtr lambda1(Arg var, ExprPtr expr) { return make_expr(vector{var}, std::move(expr)); } +inline ExprPtr lambda2(Arg var1, Arg var2, ExprPtr expr) { + return make_expr(vector{var1, var2}, std::move(expr)); +} + inline ExprPtr operator_call(string name, ExprPtr left, ExprPtr right) { return make_expr(make_expr(name), ExprPtrV{left, right}); } diff --git a/include/printers.hpp b/include/printers.hpp new file mode 100644 index 0000000..c59d9bd --- /dev/null +++ b/include/printers.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include "parsing_tree.hpp" + +using namespace nodes; + +inline std::ostream &operator<<(std::ostream &, const Expr &); + +inline std::ostream &operator<<(std::ostream &out, const Arg &expr) { + out << expr.name << (expr.mode_hint.uniq == types::Mode::Uniq::UNIQUE ? "" : ""); // TODO: all modes + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Const &expr) { + out << expr.value; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Var &expr) { + out << expr.name; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Let &expr) { + out << "let " << expr.name << " = " << *expr.body << " in " << *expr.where; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Lambda &expr) { + out << "\\"; + for (const auto &arg : expr.args) { + out << arg << " "; + } + out << "-> " << *expr.expr; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Call &expr) { + out << *expr.func; + for (const auto &arg : expr.args) { + out << " " << *arg; + } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Condition &expr) { + out << "if " << *expr.condition << " then " << *expr.then_case << " else " + << *expr.else_case; + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const Expr &expr) { + switch (expr.value.index()) { + case 0: // Const + out << std::get<0>(expr.value); + break; + case 1: // Var + out << std::get<1>(expr.value); + break; + case 2: // Let + out << std::get<2>(expr.value); + break; + case 3: // Lambda + out << std::get<3>(expr.value); + break; + case 4: // Call + out << std::get<4>(expr.value); + break; + case 5: // Condition + out << std::get<5>(expr.value); + break; + default: + utils::unreachable(); + } + return out; +} diff --git a/src/main.cpp b/src/main.cpp index abfce2a..79ee770 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,28 +1,41 @@ #include "mode_check.hpp" #include "parsing_tree.hpp" +#include "printers.hpp" #include "type_check.hpp" #include -auto make_program(bool uniq) { +auto make_program_1(bool uniq) { using namespace nodes; return make_expr( Arg("f"), - lambda1(Arg("x", uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), + lambda1(Arg("x", uniq ? types::Mode(types::Mode::Uniq::UNIQUE) + : types::Mode()), operator_call("+", make_expr("x"), make_expr("x"))), make_expr("f")); } +auto make_program_2(bool uniq) { + using namespace nodes; + return make_expr( + Arg("f"), + lambda2(Arg("x", uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), Arg("y"), + operator_call("+", make_expr("x"), make_expr("y"))), + make_expr("f")); +} + void add_builtin_functions_types(type_check::State &state, bool uniq) { auto sum_type = state.type_storage.add(types::make_operator( - state.type_storage.get_int_type(uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), - state.type_storage.get_int_type(uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), + state.type_storage.get_int_type( + uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), + state.type_storage.get_int_type( + uniq ? types::Mode(types::Mode::Uniq::UNIQUE) : types::Mode()), state.type_storage.get_int_type())); state.manager.add_var("+", sum_type); } void add_builtin_functions_modes(mode_check::State &state) { - state.add_var("+"); // mode ?? + state.add_var("+"); } void print_error(const std::string &general_message, @@ -30,12 +43,22 @@ void print_error(const std::string &general_message, std::cerr << general_message << " " << "file: " << error.location.file_name() << "(" << error.location.line() << ":" << error.location.column() << ") `" - << error.location.function_name() << "`: " << error.message << std::endl; + << error.location.function_name() << "`: " << error.message + << std::endl; } -int run_example(bool arg_uniq, bool sum_uniq) { +void run_example(const auto& make_program, bool arg_uniq, bool sum_uniq) { const auto program = make_program(arg_uniq); + std::cout << "\x1b[1;34mPROGRAM:\x1b[0m \x1b[1;90m" << *program + << "\x1b[0m\n"; + if (sum_uniq) { + std::cout << "+: int -> int -> int\n"; + } else { + std::cout << "+: int -> int -> int\n"; + } + std::cout << "\n"; + try { type_check::State state; @@ -44,8 +67,8 @@ int run_example(bool arg_uniq, bool sum_uniq) { type_check::check_expr(program, state); } catch (utils::Error error) { - print_error("TYPE CHECK ERROR:", error); - return 1; + print_error("\x1b[1;31mTYPE CHECK ERROR:\x1b[0m", error); + return; } try { @@ -55,26 +78,18 @@ int run_example(bool arg_uniq, bool sum_uniq) { mode_check::check_expr(program, state); } catch (utils::Error error) { - print_error("MODE CHECK ERROR:", error); - return 1; + print_error("\x1b[1;31mMODE CHECK ERROR:\x1b[0m", error); + return; } - std::cout << "CHECK DONE\n"; - - return 0; + std::cout << "\x1b[1;92mPROGRAM IS CORRECT\x1b[0m\n"; + return; } int main() { - int n = 0; - - while(true) { - std::cout << "--- START TEST ---\n"; - std::cout << "TEST ID (0 - 3): "; - std::cin >> n; - if (n < 0 or n >= 4) { - break; - } - run_example(n % 2 == 1, n / 4 == 1); - std::cout << "--- END TEST ---\n"; + for (size_t n = 0; n < 8; ++n) { + std::cout << "\n\x1b[1;34m--- START TEST ---\x1b[0m\n"; + run_example(n / 4 == 0 ? &make_program_1 : &make_program_2, n % 2 == 1, (n / 2) % 2 ==1); + std::cout << "\n\x1b[1;34m--- END TEST ---\x1b[0m\n"; } }