diff --git a/src/ast.h b/src/ast.h index 6cc2533..da35f40 100644 --- a/src/ast.h +++ b/src/ast.h @@ -8,13 +8,13 @@ #include // int64_t, uint8_t #include // std::function -#include // std::shared_ptr +#include +#include // std::shared_ptr #include #include #include #include // typeid #include -#include #include "ruc/format/formatter.h" @@ -57,7 +57,7 @@ public: void addNode(ASTNodePtr node); - const std::vector& nodes() const { return m_nodes; } + const std::list& nodes() const { return m_nodes; } size_t size() const { return m_nodes.size(); } bool empty() const { return m_nodes.size() == 0; } @@ -65,7 +65,7 @@ protected: Collection() {} private: - std::vector m_nodes; + std::list m_nodes; }; // ----------------------------------------- @@ -199,7 +199,7 @@ private: // ----------------------------------------- -using Lambda = std::function)>; +using Lambda = std::function)>; class Function final : public ASTNode { public: diff --git a/src/eval.cpp b/src/eval.cpp index fa2917b..8cd81f9 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -4,10 +4,11 @@ * SPDX-License-Identifier: MIT */ +#include // sd::advance, std::next +#include #include // std::static_pointer_cast #include // std::span #include -#include #include "ast.h" #include "environment.h" @@ -47,8 +48,9 @@ ASTNodePtr Eval::evalImpl(ASTNodePtr ast, EnvironmentPtr env) // Environment auto nodes = list->nodes(); - if (is(nodes[0].get())) { - auto symbol = std::static_pointer_cast(nodes[0])->symbol(); + if (is(nodes.front().get())) { + auto symbol = std::static_pointer_cast(nodes.front())->symbol(); + nodes.pop_front(); if (symbol == "def!") { return evalDef(nodes, env); } @@ -116,21 +118,24 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env) return ast; } -ASTNodePtr Eval::evalDef(const std::vector& nodes, EnvironmentPtr env) +ASTNodePtr Eval::evalDef(const std::list& nodes, EnvironmentPtr env) { - if (nodes.size() != 3) { - Error::the().addError(format("wrong number of arguments: def!, {}", nodes.size() - 1)); + if (nodes.size() != 2) { + Error::the().addError(format("wrong number of arguments: def!, {}", nodes.size())); return nullptr; } + auto first_argument = *nodes.begin(); + auto second_argument = *std::next(nodes.begin()); + // First element needs to be a Symbol - if (!is(nodes[1].get())) { - Error::the().addError(format("wrong type argument: symbol, {}", nodes[1])); + if (!is(first_argument.get())) { + Error::the().addError(format("wrong type argument: symbol, {}", first_argument)); return nullptr; } - std::string symbol = std::static_pointer_cast(nodes[1])->symbol(); - ASTNodePtr value = evalImpl(nodes[2], env); + std::string symbol = std::static_pointer_cast(first_argument)->symbol(); + ASTNodePtr value = evalImpl(second_argument, env); // Dont overwrite symbols after an error if (Error::the().hasAnyError()) { @@ -141,27 +146,30 @@ ASTNodePtr Eval::evalDef(const std::vector& nodes, EnvironmentPtr en return env->set(symbol, value); } -ASTNodePtr Eval::evalLet(const std::vector& nodes, EnvironmentPtr env) +ASTNodePtr Eval::evalLet(const std::list& nodes, EnvironmentPtr env) { - if (nodes.size() != 3) { - Error::the().addError(format("wrong number of arguments: let*, {}", nodes.size() - 1)); + if (nodes.size() != 2) { + Error::the().addError(format("wrong number of arguments: let*, {}", nodes.size())); return nullptr; } + auto first_argument = *nodes.begin(); + auto second_argument = *std::next(nodes.begin()); + // First argument needs to be a List or Vector - if (!is(nodes[1].get()) && !is(nodes[1].get())) { - Error::the().addError(format("wrong argument type: list, '{}'", nodes[1])); + if (!is(first_argument.get()) && !is(first_argument.get())) { + Error::the().addError(format("wrong argument type: list, '{}'", first_argument)); return nullptr; } // Get the nodes out of the List or Vector - std::vector binding_nodes; - if (is(nodes[1].get())) { - auto bindings = std::static_pointer_cast(nodes[1]); + std::list binding_nodes; + if (is(first_argument.get())) { + auto bindings = std::static_pointer_cast(first_argument); binding_nodes = bindings->nodes(); } else { - auto bindings = std::static_pointer_cast(nodes[1]); + auto bindings = std::static_pointer_cast(first_argument); binding_nodes = bindings->nodes(); } @@ -175,21 +183,21 @@ ASTNodePtr Eval::evalLet(const std::vector& nodes, EnvironmentPtr en // Create new environment auto let_env = makePtr(env); - for (size_t i = 0; i < count; i += 2) { + for (auto it = binding_nodes.begin(); it != binding_nodes.end(); std::advance(it, 2)) { // First element needs to be a Symbol - if (!is(binding_nodes[i].get())) { - Error::the().addError(format("wrong argument type: symbol, '{}'", binding_nodes[i])); + if (!is(*it->get())) { + Error::the().addError(format("wrong argument type: symbol, '{}'", *it)); return nullptr; } - std::string key = std::static_pointer_cast(binding_nodes[i])->symbol(); - ASTNodePtr value = evalImpl(binding_nodes[i + 1], let_env); + std::string key = std::static_pointer_cast(*it)->symbol(); + ASTNodePtr value = evalImpl(*std::next(it), let_env); let_env->set(key, value); } // TODO: Remove limitation of 3 arguments // Eval all values in this new env, return last sexp of the result - return evalImpl(nodes[2], let_env); + return evalImpl(second_argument, let_env); } ASTNodePtr Eval::apply(std::shared_ptr evaluated_list) @@ -200,17 +208,17 @@ ASTNodePtr Eval::apply(std::shared_ptr evaluated_list) auto nodes = evaluated_list->nodes(); - if (!is(nodes[0].get())) { - Error::the().addError(format("invalid function: {}", nodes[0])); + if (!is(nodes.front().get())) { + Error::the().addError(format("invalid function: {}", nodes.front())); return nullptr; } // car - auto lambda = std::static_pointer_cast(nodes[0])->lambda(); + auto lambda = std::static_pointer_cast(nodes.front())->lambda(); // cdr - std::span span { nodes.data() + 1, nodes.size() - 1 }; + nodes.pop_front(); - return lambda(span); + return lambda(nodes); } } // namespace blaze diff --git a/src/eval.h b/src/eval.h index 2587321..350dbdd 100644 --- a/src/eval.h +++ b/src/eval.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include "ast.h" #include "environment.h" @@ -25,8 +25,8 @@ public: private: ASTNodePtr evalImpl(ASTNodePtr ast, EnvironmentPtr env); ASTNodePtr evalAst(ASTNodePtr ast, EnvironmentPtr env); - ASTNodePtr evalDef(const std::vector& nodes, EnvironmentPtr env); - ASTNodePtr evalLet(const std::vector& nodes, EnvironmentPtr env); + ASTNodePtr evalDef(const std::list& nodes, EnvironmentPtr env); + ASTNodePtr evalLet(const std::list& nodes, EnvironmentPtr env); ASTNodePtr apply(std::shared_ptr evaluated_list); ASTNodePtr m_ast; diff --git a/src/functions.cpp b/src/functions.cpp index aa02d72..c7c97ab 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -21,7 +21,7 @@ namespace blaze { void GlobalEnvironment::add() { - auto add = [](std::span nodes) -> ASTNodePtr { + auto add = [](std::list nodes) -> ASTNodePtr { int64_t result = 0; for (auto node : nodes) { @@ -41,7 +41,7 @@ void GlobalEnvironment::add() void GlobalEnvironment::sub() { - auto sub = [](std::span nodes) -> ASTNodePtr { + auto sub = [](std::list nodes) -> ASTNodePtr { if (nodes.size() == 0) { return makePtr(0); } @@ -54,7 +54,7 @@ void GlobalEnvironment::sub() } // Start with the first number - int64_t result = std::static_pointer_cast(nodes[0])->number(); + int64_t result = std::static_pointer_cast(nodes.front())->number(); // Skip the first node for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { @@ -69,7 +69,7 @@ void GlobalEnvironment::sub() void GlobalEnvironment::mul() { - auto mul = [](std::span nodes) -> ASTNodePtr { + auto mul = [](std::list nodes) -> ASTNodePtr { int64_t result = 1; for (auto node : nodes) { @@ -89,7 +89,7 @@ void GlobalEnvironment::mul() void GlobalEnvironment::div() { - auto div = [this](std::span nodes) -> ASTNodePtr { + auto div = [this](std::list nodes) -> ASTNodePtr { if (nodes.size() == 0) { Error::the().addError(format("wrong number of arguments: {}, 0", m_current_key)); return nullptr; @@ -103,7 +103,7 @@ void GlobalEnvironment::div() } // Start with the first number - double result = std::static_pointer_cast(nodes[0])->number(); + double result = std::static_pointer_cast(nodes.front())->number(); // Skip the first node for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { @@ -119,7 +119,7 @@ void GlobalEnvironment::div() // ----------------------------------------- #define NUMBER_COMPARE(symbol, comparison_symbol) \ - auto lambda = [this](std::span nodes) -> ASTNodePtr { \ + auto lambda = [this](std::list nodes) -> ASTNodePtr { \ bool result = true; \ \ if (nodes.size() < 2) { \ @@ -135,7 +135,7 @@ void GlobalEnvironment::div() } \ \ /* Start with the first number */ \ - int64_t number = std::static_pointer_cast(nodes[0])->number(); \ + int64_t number = std::static_pointer_cast(nodes.front())->number(); \ \ /* Skip the first node */ \ for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { \ @@ -176,7 +176,7 @@ void GlobalEnvironment::gte() void GlobalEnvironment::list() { - auto list = [](std::span nodes) -> ASTNodePtr { + auto list = [](std::list nodes) -> ASTNodePtr { auto list = makePtr(); for (auto node : nodes) { @@ -191,7 +191,7 @@ void GlobalEnvironment::list() void GlobalEnvironment::isList() { - auto is_list = [](std::span nodes) -> ASTNodePtr { + auto is_list = [](std::list nodes) -> ASTNodePtr { bool result = true; for (auto node : nodes) { @@ -209,7 +209,7 @@ void GlobalEnvironment::isList() void GlobalEnvironment::isEmpty() { - auto is_empty = [](std::span nodes) -> ASTNodePtr { + auto is_empty = [](std::list nodes) -> ASTNodePtr { bool result = true; for (auto node : nodes) { @@ -232,7 +232,7 @@ void GlobalEnvironment::isEmpty() void GlobalEnvironment::count() { - auto count = [this](std::span nodes) -> ASTNodePtr { + auto count = [this](std::list nodes) -> ASTNodePtr { if (nodes.size() > 1) { Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); return nullptr; @@ -259,7 +259,7 @@ void GlobalEnvironment::count() // ----------------------------------------- #define PRINTER_STRING(symbol, concatenation, print_readably) \ - auto lambda = [](std::span nodes) -> ASTNodePtr { \ + auto lambda = [](std::list nodes) -> ASTNodePtr { \ std::string result; \ \ Printer printer; \ @@ -287,7 +287,7 @@ void GlobalEnvironment::prStr() } #define PRINTER_PRINT(symbol, print_readably) \ - auto lambda = [](std::span nodes) -> ASTNodePtr { \ + auto lambda = [](std::list nodes) -> ASTNodePtr { \ Printer printer; \ for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ print("{}", printer.printNoErrorCheck(*it, print_readably)); \ @@ -317,7 +317,7 @@ void GlobalEnvironment::println() void GlobalEnvironment::equal() { - auto lambda = [this](std::span nodes) -> ASTNodePtr { + auto lambda = [this](std::list nodes) -> ASTNodePtr { if (nodes.size() < 2) { Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); return nullptr; @@ -334,8 +334,10 @@ void GlobalEnvironment::equal() return false; } - for (size_t i = 0; i < lhs_nodes.size(); ++i) { - if (!equal(lhs_nodes[i], rhs_nodes[i])) { + auto lhs_it = lhs_nodes.begin(); + auto rhs_it = rhs_nodes.begin(); + for (; lhs_it != lhs_nodes.end(); ++lhs_it, ++rhs_it) { + if (!equal(*lhs_it, *rhs_it)) { return false; } } @@ -386,8 +388,10 @@ void GlobalEnvironment::equal() }; bool result = true; - for (size_t i = 0; i < nodes.size() - 1; ++i) { - if (!equal(nodes[i], nodes[i + 1])) { + auto it = nodes.begin(); + auto it_next = std::next(nodes.begin()); + for (; it_next != nodes.end(); ++it, ++it_next) { + if (!equal(*it, *it_next)) { result = false; break; } diff --git a/src/printer.cpp b/src/printer.cpp index 711f7e1..8e7c195 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -77,8 +77,8 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably) m_first_node = false; m_previous_node_is_list = true; auto nodes = std::static_pointer_cast(node)->nodes(); - for (size_t i = 0; i < nodes.size(); ++i) { - printImpl(nodes[i]); + for (auto node : nodes) { + printImpl(node); m_previous_node_is_list = false; } m_print += ')'; @@ -89,8 +89,8 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably) m_first_node = false; m_previous_node_is_list = true; auto nodes = std::static_pointer_cast(node)->nodes(); - for (size_t i = 0; i < nodes.size(); ++i) { - printImpl(nodes[i]); + for (auto node : nodes) { + printImpl(node); m_previous_node_is_list = false; } m_print += ']'; diff --git a/src/reader.cpp b/src/reader.cpp index d649bac..d62048c 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -378,15 +378,15 @@ void Reader::dumpImpl(ASTNodePtr node) ASTNode* node_raw_ptr = node.get(); if (is(node_raw_ptr)) { - auto list = std::static_pointer_cast(node); + auto nodes = std::static_pointer_cast(node)->nodes(); print("{}", indentation); print(fg(ruc::format::TerminalColor::Blue), "ListContainer"); print(" <"); print(fg(ruc::format::TerminalColor::Blue), "()"); print(">\n"); m_indentation++; - for (size_t i = 0; i < list->nodes().size(); ++i) { - dumpImpl(list->nodes()[i]); + for (auto node : nodes) { + dumpImpl(node); } m_indentation--; return;