From 9c1c5114a97c6d537fdb48e71b1bb3ef79da70c6 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Tue, 28 Mar 2023 20:15:38 +0200 Subject: [PATCH] Env: Add equal function --- src/ast.h | 2 +- src/environment.cpp | 11 +++- src/environment.h | 15 +++-- src/functions.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 169 insertions(+), 10 deletions(-) diff --git a/src/ast.h b/src/ast.h index 75f32f8..5d6bd75 100644 --- a/src/ast.h +++ b/src/ast.h @@ -33,9 +33,9 @@ public: bool fastIs() const = delete; virtual bool isCollection() const { return false; } + virtual bool isList() const { return false; } virtual bool isVector() const { return false; } virtual bool isHashMap() const { return false; } - virtual bool isList() const { return false; } virtual bool isString() const { return false; } virtual bool isKeyword() const { return false; } virtual bool isNumber() const { return false; } diff --git a/src/environment.cpp b/src/environment.cpp index b28e2ed..0b8990e 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -64,9 +64,16 @@ GlobalEnvironment::GlobalEnvironment() gte(); list(); - is_list(); - is_empty(); + isList(); + isEmpty(); count(); + + str(); + prStr(); + prn(); + println(); + + equal(); } } // namespace blaze diff --git a/src/environment.h b/src/environment.h index 7d06552..daf87fd 100644 --- a/src/environment.h +++ b/src/environment.h @@ -48,12 +48,17 @@ private: void gt(); // > void gte(); // >= - void list(); // list - void is_list(); // list? - void is_empty(); // empty? - void count(); // count + void list(); // list + void isList(); // list? + void isEmpty(); // empty? + void count(); // count - // void equal(); // = + void str(); // str + void prStr(); // pr-str + void prn(); // prn + void println(); // println + + void equal(); // = }; } // namespace blaze diff --git a/src/functions.cpp b/src/functions.cpp index ec46e6e..aa02d72 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -5,13 +5,17 @@ */ #include // std::static_pointer_cast +#include +#include "ruc/format/color.h" #include "ruc/format/format.h" #include "ast.h" #include "environment.h" #include "error.h" +#include "printer.h" #include "types.h" +#include "util.h" namespace blaze { @@ -185,7 +189,7 @@ void GlobalEnvironment::list() m_values.emplace("list", makePtr(list)); } -void GlobalEnvironment::is_list() +void GlobalEnvironment::isList() { auto is_list = [](std::span nodes) -> ASTNodePtr { bool result = true; @@ -203,7 +207,7 @@ void GlobalEnvironment::is_list() m_values.emplace("list?", makePtr(is_list)); } -void GlobalEnvironment::is_empty() +void GlobalEnvironment::isEmpty() { auto is_empty = [](std::span nodes) -> ASTNodePtr { bool result = true; @@ -252,4 +256,147 @@ void GlobalEnvironment::count() m_values.emplace("count", makePtr(count)); } +// ----------------------------------------- + +#define PRINTER_STRING(symbol, concatenation, print_readably) \ + auto lambda = [](std::span nodes) -> ASTNodePtr { \ + std::string result; \ + \ + Printer printer; \ + for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ + result += format("{}", printer.printNoErrorCheck(*it, print_readably)); \ + \ + if (!isLast(it, nodes)) { \ + result += concatenation; \ + } \ + } \ + \ + return makePtr(result); \ + }; \ + \ + m_values.emplace(symbol, makePtr(lambda)); + +void GlobalEnvironment::str() +{ + PRINTER_STRING("str", "", false); +} + +void GlobalEnvironment::prStr() +{ + PRINTER_STRING("pr-str", " ", true); +} + +#define PRINTER_PRINT(symbol, print_readably) \ + auto lambda = [](std::span nodes) -> ASTNodePtr { \ + Printer printer; \ + for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ + print("{}", printer.printNoErrorCheck(*it, print_readably)); \ + \ + if (!isLast(it, nodes)) { \ + print(" "); \ + } \ + } \ + print("\n"); \ + \ + return makePtr(Value::Nil); \ + }; \ + \ + m_values.emplace(symbol, makePtr(lambda)); + +void GlobalEnvironment::prn() +{ + PRINTER_PRINT("prn", true); +} + +void GlobalEnvironment::println() +{ + PRINTER_PRINT("println", false); +} + +// ----------------------------------------- + +void GlobalEnvironment::equal() +{ + auto lambda = [this](std::span nodes) -> ASTNodePtr { + if (nodes.size() < 2) { + Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); + return nullptr; + } + + std::function equal = + [&equal](ASTNodePtr lhs, ASTNodePtr rhs) -> bool { + if ((is(lhs.get()) && is(rhs.get())) + || (is(lhs.get()) && is(rhs.get()))) { + auto lhs_nodes = std::static_pointer_cast(lhs)->nodes(); + auto rhs_nodes = std::static_pointer_cast(rhs)->nodes(); + + if (lhs_nodes.size() != rhs_nodes.size()) { + return false; + } + + for (size_t i = 0; i < lhs_nodes.size(); ++i) { + if (!equal(lhs_nodes[i], rhs_nodes[i])) { + return false; + } + } + + return true; + } + + if (is(lhs.get()) && is(rhs.get())) { + auto lhs_nodes = std::static_pointer_cast(lhs)->elements(); + auto rhs_nodes = std::static_pointer_cast(rhs)->elements(); + + if (lhs_nodes.size() != rhs_nodes.size()) { + return false; + } + + for (const auto& [key, value] : lhs_nodes) { + auto it = rhs_nodes.find(key); + if (it == rhs_nodes.end() || !equal(value, it->second)) { + return false; + } + } + + return true; + } + + if (is(lhs.get()) && is(rhs.get()) + && std::static_pointer_cast(lhs)->data() == std::static_pointer_cast(rhs)->data()) { + return true; + } + if (is(lhs.get()) && is(rhs.get()) + && std::static_pointer_cast(lhs)->keyword() == std::static_pointer_cast(rhs)->keyword()) { + return true; + } + if (is(lhs.get()) && is(rhs.get()) + && std::static_pointer_cast(lhs)->number() == std::static_pointer_cast(rhs)->number()) { + return true; + } + if (is(lhs.get()) && is(rhs.get()) + && std::static_pointer_cast(lhs)->state() == std::static_pointer_cast(rhs)->state()) { + return true; + } + if (is(lhs.get()) && is(rhs.get()) + && std::static_pointer_cast(lhs)->symbol() == std::static_pointer_cast(rhs)->symbol()) { + return true; + } + + return false; + }; + + bool result = true; + for (size_t i = 0; i < nodes.size() - 1; ++i) { + if (!equal(nodes[i], nodes[i + 1])) { + result = false; + break; + } + } + + return makePtr((result) ? Value::True : Value::False); + }; + + m_values.emplace("=", makePtr(lambda)); +} + } // namespace blaze