From 63c31d7ccfa8e4f68d2712071964c22f6c6508e8 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 1 May 2023 18:22:11 +0200 Subject: [PATCH] Everywhere: Convert List and Vector back to std::vector, ~+20% speed --- src/ast.cpp | 41 ++-- src/ast.h | 10 +- src/environment.cpp | 2 +- src/environment.h | 2 +- src/eval-special-form.cpp | 32 +-- src/eval.cpp | 5 +- src/eval.h | 22 +- src/forward.h | 4 +- src/functions.cpp | 433 ++++++++++++++++++++------------------ 9 files changed, 287 insertions(+), 264 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index 1fc165e..1bc12a6 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -5,8 +5,9 @@ */ #include // int64_t -#include +#include // std::static_pointer_cast #include +#include #include "ast.h" #include "environment.h" @@ -29,11 +30,16 @@ ValuePtr Value::meta() const // ----------------------------------------- -Collection::Collection(const std::list& nodes) +Collection::Collection(const ValueList& nodes) : m_nodes(nodes) { } +Collection::Collection(ValueListIt begin, ValueListIt end) + : m_nodes(ValueList(begin, end)) +{ +} + Collection::Collection(ValueListConstIt begin, ValueListConstIt end) : m_nodes(ValueList(begin, end)) { @@ -54,30 +60,21 @@ void Collection::add(ValuePtr node) m_nodes.push_back(node); } -void Collection::addFront(ValuePtr node) -{ - if (node == nullptr) { - return; - } - - m_nodes.push_front(node); -} - ValueList Collection::rest() const { - auto start = (m_nodes.size() > 0) ? std::next(m_nodes.begin()) : m_nodes.end(); + auto start = (m_nodes.size() > 0) ? m_nodes.begin() + 1 : m_nodes.end(); return ValueList(start, m_nodes.end()); } // ----------------------------------------- -List::List(const List& that, ValuePtr meta) - : Collection(that, meta) +List::List(const ValueList& nodes) + : Collection(nodes) { } -List::List(const std::list& nodes) - : Collection(nodes) +List::List(ValueListIt begin, ValueListIt end) + : Collection(begin, end) { } @@ -86,13 +83,23 @@ List::List(ValueListConstIt begin, ValueListConstIt end) { } +List::List(const List& that, ValuePtr meta) + : Collection(that, meta) +{ +} + // ----------------------------------------- -Vector::Vector(const std::list& nodes) +Vector::Vector(const ValueList& nodes) : Collection(nodes) { } +Vector::Vector(ValueListIt begin, ValueListIt end) + : Collection(begin, end) +{ +} + Vector::Vector(ValueListConstIt begin, ValueListConstIt end) : Collection(begin, end) { diff --git a/src/ast.h b/src/ast.h index cbbfbf0..a643812 100644 --- a/src/ast.h +++ b/src/ast.h @@ -95,7 +95,6 @@ public: virtual ~Collection() = default; void add(ValuePtr node); - void addFront(ValuePtr node); // TODO: rename size -> count size_t size() const { return m_nodes.size(); } @@ -109,6 +108,7 @@ public: protected: Collection() = default; Collection(const ValueList& nodes); + Collection(ValueListIt begin, ValueListIt end); Collection(ValueListConstIt begin, ValueListConstIt end); Collection(const Collection& that, ValuePtr meta); @@ -130,7 +130,8 @@ private: class List final : public Collection { public: List() = default; - List(const std::list& nodes); + List(const ValueList& nodes); + List(ValueListIt begin, ValueListIt end); List(ValueListConstIt begin, ValueListConstIt end); List(const List& that, ValuePtr meta); @@ -154,7 +155,8 @@ private: class Vector final : public Collection { public: Vector() = default; - Vector(const std::list& nodes); + Vector(const ValueList& nodes); + Vector(ValueListIt begin, ValueListIt end); Vector(ValueListConstIt begin, ValueListConstIt end); Vector(const Vector& that, ValuePtr meta); @@ -322,7 +324,7 @@ private: // ----------------------------------------- -using FunctionType = std::function)>; +using FunctionType = std::function; class Function final : public Callable { public: diff --git a/src/environment.cpp b/src/environment.cpp index 3056e93..2c66a07 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -29,7 +29,7 @@ EnvironmentPtr Environment::create(EnvironmentPtr outer) return env; } -EnvironmentPtr Environment::create(const ValuePtr lambda, const std::list& arguments) +EnvironmentPtr Environment::create(const ValuePtr lambda, const ValueList& arguments) { auto lambda_casted = std::static_pointer_cast(lambda); auto env = create(lambda_casted->env()); diff --git a/src/environment.h b/src/environment.h index 531c94a..bb57dc7 100644 --- a/src/environment.h +++ b/src/environment.h @@ -21,7 +21,7 @@ public: // Factory functions instead of constructors because it can fail in the bindings/arguments case static EnvironmentPtr create(); static EnvironmentPtr create(EnvironmentPtr outer); - static EnvironmentPtr create(const ValuePtr lambda, const std::list& arguments); + static EnvironmentPtr create(const ValuePtr lambda, const ValueList& arguments); bool exists(const std::string& symbol); ValuePtr set(const std::string& symbol, ValuePtr value); diff --git a/src/eval-special-form.cpp b/src/eval-special-form.cpp index 7b51c77..08d393d 100644 --- a/src/eval-special-form.cpp +++ b/src/eval-special-form.cpp @@ -22,7 +22,7 @@ namespace blaze { static ValuePtr evalQuasiQuoteImpl(ValuePtr ast); // (def! x 2) -ValuePtr Eval::evalDef(const std::list& nodes, EnvironmentPtr env) +ValuePtr Eval::evalDef(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("def!", nodes.size(), 2); @@ -44,7 +44,7 @@ ValuePtr Eval::evalDef(const std::list& nodes, EnvironmentPtr env) } // (defmacro! x (fn* (x) x)) -ValuePtr Eval::evalDefMacro(const std::list& nodes, EnvironmentPtr env) +ValuePtr Eval::evalDefMacro(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("defmacro!", nodes.size(), 2); @@ -67,15 +67,17 @@ ValuePtr Eval::evalDefMacro(const std::list& nodes, EnvironmentPtr env } // (fn* (x) x) -ValuePtr Eval::evalFn(const std::list& nodes, EnvironmentPtr env) +ValuePtr Eval::evalFn(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("fn*", nodes.size(), 2); // First element needs to be a List or Vector VALUE_CAST(collection, Collection, nodes.front()); + const auto& collection_nodes = collection->nodes(); std::vector bindings; - for (auto node : collection->nodes()) { + bindings.reserve(collection_nodes.size()); + for (const auto& node : collection_nodes) { // All nodes need to be a Symbol VALUE_CAST(symbol, Symbol, node); bindings.push_back(symbol->symbol()); @@ -86,7 +88,7 @@ ValuePtr Eval::evalFn(const std::list& nodes, EnvironmentPtr env) return makePtr(bindings, *std::next(nodes.begin()), env); } -ValuePtr Eval::evalMacroExpand(const std::list& nodes, EnvironmentPtr env) +ValuePtr Eval::evalMacroExpand(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("macroexpand", nodes.size(), 1); @@ -94,7 +96,7 @@ ValuePtr Eval::evalMacroExpand(const std::list& nodes, EnvironmentPtr } // (quasiquoteexpand x) -ValuePtr Eval::evalQuasiQuoteExpand(const std::list& nodes) +ValuePtr Eval::evalQuasiQuoteExpand(const ValueList& nodes) { CHECK_ARG_COUNT_IS("quasiquoteexpand", nodes.size(), 1); @@ -102,7 +104,7 @@ ValuePtr Eval::evalQuasiQuoteExpand(const std::list& nodes) } // (quote x) -ValuePtr Eval::evalQuote(const std::list& nodes) +ValuePtr Eval::evalQuote(const ValueList& nodes) { CHECK_ARG_COUNT_IS("quote", nodes.size(), 1); @@ -110,7 +112,7 @@ ValuePtr Eval::evalQuote(const std::list& nodes) } // (do 1 2 3) -void Eval::evalDo(const std::list& nodes, EnvironmentPtr env) +void Eval::evalDo(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_AT_LEAST("do", nodes.size(), 1, void()); @@ -128,7 +130,7 @@ void Eval::evalDo(const std::list& nodes, EnvironmentPtr env) } // (if x true false) -void Eval::evalIf(const std::list& nodes, EnvironmentPtr env) +void Eval::evalIf(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_BETWEEN("if", nodes.size(), 2, 3, void()); @@ -152,13 +154,13 @@ void Eval::evalIf(const std::list& nodes, EnvironmentPtr env) } // (let* (x 1) x) -void Eval::evalLet(const std::list& nodes, EnvironmentPtr env) +void Eval::evalLet(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("let*", nodes.size(), 2, void()); // First argument needs to be a List or Vector VALUE_CAST(bindings, Collection, nodes.front(), void()); - auto binding_nodes = bindings->nodes(); + const auto& binding_nodes = bindings->nodes(); // List or Vector needs to have an even number of elements CHECK_ARG_COUNT_EVEN("bindings", binding_nodes.size(), void()); @@ -207,7 +209,7 @@ static ValuePtr startsWith(ValuePtr ast, const std::string& symbol) return nullptr; } - auto nodes = std::static_pointer_cast(ast)->nodes(); + const auto& nodes = std::static_pointer_cast(ast)->nodes(); if (nodes.empty() || !isSymbol(nodes.front(), symbol)) { return nullptr; @@ -269,7 +271,7 @@ static ValuePtr evalQuasiQuoteImpl(ValuePtr ast) } // (quasiquote x) -void Eval::evalQuasiQuote(const std::list& nodes, EnvironmentPtr env) +void Eval::evalQuasiQuote(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_IS("quasiquote", nodes.size(), 1, void()); @@ -281,7 +283,7 @@ void Eval::evalQuasiQuote(const std::list& nodes, EnvironmentPtr env) } // (try* x (catch* y z)) -void Eval::evalTry(const std::list& nodes, EnvironmentPtr env) +void Eval::evalTry(const ValueList& nodes, EnvironmentPtr env) { CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1, void()); @@ -299,7 +301,7 @@ void Eval::evalTry(const std::list& nodes, EnvironmentPtr env) Error::the().clearErrors(); VALUE_CAST(catch_list, List, nodes.back(), void()); - auto catch_nodes = catch_list->nodes(); + const auto& catch_nodes = catch_list->nodes(); CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2, void()); VALUE_CAST(catch_symbol, Symbol, catch_nodes.front(), void()); diff --git a/src/eval.cpp b/src/eval.cpp index 20aeffe..318f1d0 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -249,12 +249,9 @@ ValuePtr Eval::apply(std::shared_ptr evaluated_list) return nullptr; } - // car auto function = std::static_pointer_cast(nodes.front())->function(); - // cdr - nodes.pop_front(); - return function(nodes); + return function(nodes.begin() + 1, nodes.end()); } } // namespace blaze diff --git a/src/eval.h b/src/eval.h index b2dcd16..9c9a7e6 100644 --- a/src/eval.h +++ b/src/eval.h @@ -32,17 +32,17 @@ private: bool isMacroCall(ValuePtr ast, EnvironmentPtr env); ValuePtr macroExpand(ValuePtr ast, EnvironmentPtr env); - ValuePtr evalDef(const std::list& nodes, EnvironmentPtr env); - ValuePtr evalDefMacro(const std::list& nodes, EnvironmentPtr env); - ValuePtr evalFn(const std::list& nodes, EnvironmentPtr env); - ValuePtr evalMacroExpand(const std::list& nodes, EnvironmentPtr env); - ValuePtr evalQuasiQuoteExpand(const std::list& nodes); - ValuePtr evalQuote(const std::list& nodes); - void evalDo(const std::list& nodes, EnvironmentPtr env); - void evalIf(const std::list& nodes, EnvironmentPtr env); - void evalLet(const std::list& nodes, EnvironmentPtr env); - void evalQuasiQuote(const std::list& nodes, EnvironmentPtr env); - void evalTry(const std::list& nodes, EnvironmentPtr env); + ValuePtr evalDef(const ValueList& nodes, EnvironmentPtr env); + ValuePtr evalDefMacro(const ValueList& nodes, EnvironmentPtr env); + ValuePtr evalFn(const ValueList& nodes, EnvironmentPtr env); + ValuePtr evalMacroExpand(const ValueList& nodes, EnvironmentPtr env); + ValuePtr evalQuasiQuoteExpand(const ValueList& nodes); + ValuePtr evalQuote(const ValueList& nodes); + void evalDo(const ValueList& nodes, EnvironmentPtr env); + void evalIf(const ValueList& nodes, EnvironmentPtr env); + void evalLet(const ValueList& nodes, EnvironmentPtr env); + void evalQuasiQuote(const ValueList& nodes, EnvironmentPtr env); + void evalTry(const ValueList& nodes, EnvironmentPtr env); ValuePtr apply(std::shared_ptr evaluated_list); diff --git a/src/forward.h b/src/forward.h index 9c40a57..209a7bd 100644 --- a/src/forward.h +++ b/src/forward.h @@ -6,8 +6,8 @@ #pragma once -#include #include // std::shared_ptr +#include namespace blaze { @@ -16,7 +16,7 @@ namespace blaze { class Value; typedef std::shared_ptr ValuePtr; -typedef std::list ValueList; +typedef std::vector ValueList; typedef ValueList::iterator ValueListIt; typedef ValueList::const_iterator ValueListConstIt; diff --git a/src/functions.cpp b/src/functions.cpp index 972e408..4b9ab03 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -4,10 +4,11 @@ * SPDX-License-Identifier: MIT */ -#include // std::chrono::sytem_clock -#include // int64_t -#include // std::advance -#include // std::static_pointer_cast +#include // std::copy, std::reverse_copy +#include // std::chrono::sytem_clock +#include // int64_t +#include // std::advance, std::distance, std::next, std::prev +#include // std::static_pointer_cast #include #include "ruc/file.h" @@ -38,10 +39,12 @@ static struct FUNCTION_STRUCT_NAME(unique) \ FUNCTION_STRUCT_NAME(unique)( \ symbol, \ - [](std::list nodes) -> ValuePtr lambda); + [](ValueListIt begin, ValueListIt end) -> ValuePtr lambda); #define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda); +#define SIZE() std::distance(begin, end) + namespace blaze { static std::unordered_map s_functions; @@ -51,8 +54,8 @@ ADD_FUNCTION( { int64_t result = 0; - for (auto node : nodes) { - VALUE_CAST(number, Number, node); + for (auto it = begin; it != end; ++it) { + VALUE_CAST(number, Number, (*it)); result += number->number(); } @@ -62,16 +65,16 @@ ADD_FUNCTION( ADD_FUNCTION( "-", { - if (nodes.size() == 0) { + if (SIZE() == 0) { return makePtr(0); } // Start with the first number - VALUE_CAST(number, Number, nodes.front()); + VALUE_CAST(number, Number, (*begin)); int64_t result = number->number(); // Skip the first node - for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { + for (auto it = begin + 1; it != end; ++it) { VALUE_CAST(number, Number, (*it)); result -= number->number(); } @@ -84,8 +87,8 @@ ADD_FUNCTION( { int64_t result = 1; - for (auto node : nodes) { - VALUE_CAST(number, Number, node); + for (auto it = begin; it != end; ++it) { + VALUE_CAST(number, Number, (*it)); result *= number->number(); } @@ -95,14 +98,14 @@ ADD_FUNCTION( ADD_FUNCTION( "/", { - CHECK_ARG_COUNT_AT_LEAST("/", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("/", SIZE(), 1); // Start with the first number - VALUE_CAST(number, Number, nodes.front()); + VALUE_CAST(number, Number, (*begin)); double result = number->number(); // Skip the first node - for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { + for (auto it = begin + 1; it != end; ++it) { VALUE_CAST(number, Number, (*it)); result /= number->number(); } @@ -116,14 +119,14 @@ ADD_FUNCTION( { \ bool result = true; \ \ - CHECK_ARG_COUNT_AT_LEAST(#operator, nodes.size(), 2); \ + CHECK_ARG_COUNT_AT_LEAST(#operator, SIZE(), 2); \ \ /* Start with the first number */ \ - VALUE_CAST(number_node, Number, nodes.front()); \ + VALUE_CAST(number_node, Number, (*begin)); \ int64_t number = number_node->number(); \ \ /* Skip the first node */ \ - for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { \ + for (auto it = begin + 1; it != end; ++it) { \ VALUE_CAST(current_number_node, Number, (*it)); \ int64_t current_number = current_number_node->number(); \ if (!(number operator current_number)) { \ @@ -146,7 +149,7 @@ ADD_FUNCTION(">=", NUMBER_COMPARE(>=)); ADD_FUNCTION( "list", { - return makePtr(nodes); + return makePtr(begin, end); }); ADD_FUNCTION( @@ -154,8 +157,8 @@ ADD_FUNCTION( { bool result = true; - for (auto node : nodes) { - VALUE_CAST(collection, Collection, node); + for (auto it = begin; it != end; ++it) { + VALUE_CAST(collection, Collection, (*it)); if (!collection->empty()) { result = false; break; @@ -169,19 +172,17 @@ ADD_FUNCTION( ADD_FUNCTION( "count", { - CHECK_ARG_COUNT_IS("count", nodes.size(), 1); - - auto first_argument = nodes.front(); + CHECK_ARG_COUNT_IS("count", SIZE(), 1); size_t result = 0; - if (is(first_argument.get()) && std::static_pointer_cast(nodes.front())->state() == Constant::Nil) { + if (is(begin->get()) && std::static_pointer_cast(*begin)->state() == Constant::Nil) { // result = 0 } - else if (is(first_argument.get())) { - result = std::static_pointer_cast(first_argument)->size(); + else if (is(begin->get())) { + result = std::static_pointer_cast(*begin)->size(); } else { - Error::the().add(format("wrong argument type: Collection, '{}'", first_argument)); + Error::the().add(format("wrong argument type: Collection, '{}'", *begin)); return nullptr; } @@ -196,10 +197,10 @@ ADD_FUNCTION( std::string result; \ \ Printer printer; \ - for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ + for (auto it = begin; it != end; ++it) { \ result += format("{}", printer.printNoErrorCheck(*it, print_readably)); \ \ - if (!isLast(it, nodes)) { \ + if (it != end && std::next(it) != end) { \ result += concatenation; \ } \ } \ @@ -213,10 +214,10 @@ ADD_FUNCTION("pr-str", PRINTER_STRING(true, " ")); #define PRINTER_PRINT(print_readably) \ { \ Printer printer; \ - for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ + for (auto it = begin; it != end; ++it) { \ print("{}", printer.printNoErrorCheck(*it, print_readably)); \ \ - if (!isLast(it, nodes)) { \ + if (it != end && std::next(it) != end) { \ print(" "); \ } \ } \ @@ -233,7 +234,7 @@ ADD_FUNCTION("println", PRINTER_PRINT(false)); ADD_FUNCTION( "=", { - CHECK_ARG_COUNT_AT_LEAST("=", nodes.size(), 2); + CHECK_ARG_COUNT_AT_LEAST("=", SIZE(), 2); std::function equal = [&equal](ValuePtr lhs, ValuePtr rhs) -> bool { @@ -300,9 +301,9 @@ ADD_FUNCTION( }; bool result = true; - auto it = nodes.begin(); - auto it_next = std::next(nodes.begin()); - for (; it_next != nodes.end(); ++it, ++it_next) { + auto it = begin; + auto it_next = begin + 1; + for (; it_next != end; ++it, ++it_next) { if (!equal(*it, *it_next)) { result = false; break; @@ -315,9 +316,9 @@ ADD_FUNCTION( ADD_FUNCTION( "read-string", { - CHECK_ARG_COUNT_IS("read-string", nodes.size(), 1); + CHECK_ARG_COUNT_IS("read-string", SIZE(), 1); - VALUE_CAST(node, String, nodes.front()); + VALUE_CAST(node, String, (*begin)); std::string input = node->data(); return read(input); @@ -326,9 +327,9 @@ ADD_FUNCTION( ADD_FUNCTION( "slurp", { - CHECK_ARG_COUNT_IS("slurp", nodes.size(), 1); + CHECK_ARG_COUNT_IS("slurp", SIZE(), 1); - VALUE_CAST(node, String, nodes.front()); + VALUE_CAST(node, String, (*begin)); std::string path = node->data(); auto file = ruc::File(path); @@ -339,27 +340,27 @@ ADD_FUNCTION( ADD_FUNCTION( "eval", { - CHECK_ARG_COUNT_IS("eval", nodes.size(), 1); + CHECK_ARG_COUNT_IS("eval", SIZE(), 1); - return eval(nodes.front(), nullptr); + return eval(*begin, nullptr); }); // (atom 1) ADD_FUNCTION( "atom", { - CHECK_ARG_COUNT_IS("atom", nodes.size(), 1); + CHECK_ARG_COUNT_IS("atom", SIZE(), 1); - return makePtr(nodes.front()); + return makePtr(*begin); }); // (deref myatom) ADD_FUNCTION( "deref", { - CHECK_ARG_COUNT_IS("deref", nodes.size(), 1); + CHECK_ARG_COUNT_IS("deref", SIZE(), 1); - VALUE_CAST(atom, Atom, nodes.front()); + VALUE_CAST(atom, Atom, (*begin)); return atom->deref(); }); @@ -368,10 +369,10 @@ ADD_FUNCTION( ADD_FUNCTION( "reset!", { - CHECK_ARG_COUNT_IS("reset!", nodes.size(), 2); + CHECK_ARG_COUNT_IS("reset!", SIZE(), 2); - VALUE_CAST(atom, Atom, nodes.front()); - auto value = *std::next(nodes.begin()); + VALUE_CAST(atom, Atom, (*begin)); + auto value = *(begin + 1); atom->reset(value); @@ -382,83 +383,95 @@ ADD_FUNCTION( ADD_FUNCTION( "swap!", { - CHECK_ARG_COUNT_AT_LEAST("swap!", nodes.size(), 2); + CHECK_ARG_COUNT_AT_LEAST("swap!", SIZE(), 2); - VALUE_CAST(atom, Atom, nodes.front()); + VALUE_CAST(atom, Atom, (*begin)); - VALUE_CAST(callable, Callable, (*std::next(nodes.begin()))); + VALUE_CAST(callable, Callable, (*(begin + 1))); // Remove atom and function from the argument list, add atom value - nodes.pop_front(); - nodes.pop_front(); - nodes.push_front(atom->deref()); + begin += 2; + auto arguments = ValueList(end - begin + 1); + arguments[0] = atom->deref(); + std::copy(begin, end, arguments.begin() + 1); ValuePtr value = nullptr; if (is(callable.get())) { auto function = std::static_pointer_cast(callable)->function(); - value = function(nodes); + value = function(arguments.begin(), arguments.end()); } else { auto lambda = std::static_pointer_cast(callable); - value = eval(lambda->body(), Environment::create(lambda, nodes)); + value = eval(lambda->body(), Environment::create(lambda, arguments)); } return atom->reset(value); }); -// (cons 1 (list 2 3)) -> (1 2 3) +// (cons 1 (list 2 3)) ADD_FUNCTION( "cons", { - CHECK_ARG_COUNT_IS("cons", nodes.size(), 2); + CHECK_ARG_COUNT_IS("cons", SIZE(), 2); - VALUE_CAST(collection, Collection, (*std::next(nodes.begin()))); + ValuePtr first = *begin; + begin++; - auto result = makePtr(collection->nodes()); - result->addFront(nodes.front()); + VALUE_CAST(collection, Collection, (*begin)); + const auto& collection_nodes = collection->nodes(); - return result; + ValueList* result_nodes = new ValueList(collection_nodes.size() + 1); + result_nodes->at(0) = first; + std::copy(collection_nodes.begin(), collection_nodes.end(), result_nodes->begin() + 1); + + return makePtr(*result_nodes); }); // (concat (list 1) (list 2 3)) -> (1 2 3) ADD_FUNCTION( "concat", { - std::list result_nodes; + size_t count = 0; + for (auto it = begin; it != end; ++it) { + VALUE_CAST(collection, Collection, (*it)); + count += collection->size(); + } - for (auto node : nodes) { - VALUE_CAST(collection, Collection, node); - auto argument_nodes = collection->nodes(); - result_nodes.splice(result_nodes.end(), argument_nodes); + auto result_nodes = new ValueList(count); + size_t offset = 0; + for (auto it = begin; it != end; ++it) { + const auto& collection_nodes = std::static_pointer_cast(*it)->nodes(); + std::copy(collection_nodes.begin(), collection_nodes.end(), result_nodes->begin() + offset); + offset += collection_nodes.size(); } - return makePtr(result_nodes); + return makePtr(*result_nodes); }); -// (vec (list 1 2 3)) -> [1 2 3] +// (vec (list 1 2 3)) ADD_FUNCTION( "vec", { - CHECK_ARG_COUNT_IS("vec", nodes.size(), 1); + CHECK_ARG_COUNT_IS("vec", SIZE(), 1); - if (is(nodes.front().get())) { - return nodes.front(); + if (is(begin->get())) { + return *begin; } - VALUE_CAST(collection, Collection, nodes.front()); + VALUE_CAST(collection, Collection, (*begin)); return makePtr(collection->nodes()); }); -// (nth (list 1 2 3) 0) -> 1 +// (nth (list 1 2 3) 0) ADD_FUNCTION( "nth", { - CHECK_ARG_COUNT_IS("nth", nodes.size(), 2); + CHECK_ARG_COUNT_IS("nth", SIZE(), 2); - VALUE_CAST(collection, Collection, nodes.front()); - VALUE_CAST(number_node, Number, (*std::next(nodes.begin()))); - const auto& collection_nodes = collection->nodes(); + VALUE_CAST(collection, Collection, (*begin)); + VALUE_CAST(number_node, Number, (*(begin + 1))); + auto collection_nodes = collection->nodes(); auto index = (size_t)number_node->number(); if (number_node->number() < 0 || index >= collection_nodes.size()) { @@ -466,7 +479,7 @@ ADD_FUNCTION( return nullptr; } - auto result = collection_nodes.cbegin(); + auto result = collection_nodes.begin(); for (size_t i = 0; i < index; ++i) { result++; } @@ -478,30 +491,30 @@ ADD_FUNCTION( ADD_FUNCTION( "first", { - CHECK_ARG_COUNT_IS("first", nodes.size(), 1); + CHECK_ARG_COUNT_IS("first", SIZE(), 1); - if (is(nodes.front().get()) - && std::static_pointer_cast(nodes.front())->state() == Constant::Nil) { + if (is(begin->get()) + && std::static_pointer_cast(*begin)->state() == Constant::Nil) { return makePtr(); } - VALUE_CAST(collection, Collection, nodes.front()); + VALUE_CAST(collection, Collection, (*begin)); return (collection->empty()) ? makePtr() : collection->front(); }); -// (rest (list 1 2 3)) -> (2 3) +// (rest (list 1 2 3)) ADD_FUNCTION( "rest", { - CHECK_ARG_COUNT_IS("rest", nodes.size(), 1); + CHECK_ARG_COUNT_IS("rest", SIZE(), 1); - if (is(nodes.front().get()) - && std::static_pointer_cast(nodes.front())->state() == Constant::Nil) { + if (is(begin->get()) + && std::static_pointer_cast(*begin)->state() == Constant::Nil) { return makePtr(); } - VALUE_CAST(collection, Collection, nodes.front()); + VALUE_CAST(collection, Collection, (*begin)); return makePtr(collection->rest()); }); @@ -510,29 +523,30 @@ ADD_FUNCTION( ADD_FUNCTION( "apply", { - CHECK_ARG_COUNT_AT_LEAST("apply", nodes.size(), 2); + CHECK_ARG_COUNT_AT_LEAST("apply", SIZE(), 2); - auto callable = nodes.front(); + auto callable = *begin; IS_VALUE(Callable, callable); - VALUE_CAST(collection, Collection, nodes.back()); + VALUE_CAST(collection, Collection, (*std::prev(end))); - // Remove function and list from the arguments - nodes.pop_front(); - nodes.pop_back(); + ValueList arguments(begin + 1, end - 1); + arguments.reserve(arguments.size() + collection->size()); // Append list nodes to the argument leftovers - auto collection_nodes = collection->nodes(); - nodes.splice(nodes.end(), collection_nodes); + auto nodes = collection->nodes(); + for (const auto& node : nodes) { + arguments.push_back(node); + } ValuePtr value = nullptr; if (is(callable.get())) { auto function = std::static_pointer_cast(callable)->function(); - value = function(nodes); + value = function(arguments.begin(), arguments.end()); } else { auto lambda = std::static_pointer_cast(callable); - value = eval(lambda->body(), Environment::create(lambda, nodes)); + value = eval(lambda->body(), Environment::create(lambda, arguments)); } return value; @@ -542,10 +556,10 @@ ADD_FUNCTION( ADD_FUNCTION( "map", { - CHECK_ARG_COUNT_IS("map", nodes.size(), 2); + CHECK_ARG_COUNT_IS("map", SIZE(), 2); - VALUE_CAST(callable, Callable, nodes.front()); - VALUE_CAST(collection, Collection, nodes.back()); + VALUE_CAST(callable, Callable, (*begin)); + VALUE_CAST(collection, Collection, (*(begin + 1))); const auto& collection_nodes = collection->nodes(); auto result = makePtr(); @@ -553,7 +567,8 @@ ADD_FUNCTION( if (is(callable.get())) { auto function = std::static_pointer_cast(callable)->function(); for (const auto& node : collection_nodes) { - result->add(function({ node })); + auto arguments = ValueList { node }; + result->add(function(arguments.begin(), arguments.end())); } } else { @@ -570,22 +585,22 @@ ADD_FUNCTION( ADD_FUNCTION( "throw", { - CHECK_ARG_COUNT_IS("throw", nodes.size(), 1); + CHECK_ARG_COUNT_IS("throw", SIZE(), 1); - Error::the().add(nodes.front()); + Error::the().add(*begin); return nullptr; }) // ----------------------------------------- -#define IS_CONSTANT(name, constant) \ - { \ - CHECK_ARG_COUNT_IS(name, nodes.size(), 1); \ - \ - return makePtr( \ - is(nodes.front().get()) \ - && std::static_pointer_cast(nodes.front())->state() == constant); \ +#define IS_CONSTANT(name, constant) \ + { \ + CHECK_ARG_COUNT_IS(name, SIZE(), 1); \ + \ + return makePtr( \ + is(begin->get()) \ + && std::static_pointer_cast(*begin)->state() == constant); \ } // (nil? nil) @@ -595,22 +610,22 @@ ADD_FUNCTION("false?", IS_CONSTANT("false?", Constant::False)); // ----------------------------------------- -#define IS_TYPE(type) \ - { \ - bool result = true; \ - \ - if (nodes.size() == 0) { \ - result = false; \ - } \ - \ - for (auto node : nodes) { \ - if (!is(node.get())) { \ - result = false; \ - break; \ - } \ - } \ - \ - return makePtr(result); \ +#define IS_TYPE(type) \ + { \ + bool result = true; \ + \ + if (SIZE() == 0) { \ + result = false; \ + } \ + \ + for (auto it = begin; it != end; ++it) { \ + if (!is(it->get())) { \ + result = false; \ + break; \ + } \ + } \ + \ + return makePtr(result); \ } // (symbol? 'foo) @@ -629,16 +644,12 @@ ADD_FUNCTION( { bool result = true; - if (nodes.size() == 0) { + if (SIZE() == 0) { result = false; } - for (auto node : nodes) { - if (!is(node.get())) { - result = false; - break; - } - if (is(node.get())) { + for (auto it = begin; it != end; ++it) { + if (!is(it->get()) || is(it->get())) { result = false; break; } @@ -652,12 +663,12 @@ ADD_FUNCTION( { bool result = true; - if (nodes.size() == 0) { + if (SIZE() == 0) { result = false; } - for (auto node : nodes) { - if (!is(node.get())) { + for (auto it = begin; it != end; ++it) { + if (!is(it->get())) { result = false; break; } @@ -668,17 +679,17 @@ ADD_FUNCTION( // ----------------------------------------- -#define STRING_TO_TYPE(name, type) \ - { \ - CHECK_ARG_COUNT_IS(name, nodes.size(), 1); \ - \ - if (is(nodes.front().get())) { \ - return nodes.front(); \ - } \ - \ - VALUE_CAST(stringValue, String, nodes.front()); \ - \ - return makePtr(stringValue->data()); \ +#define STRING_TO_TYPE(name, type) \ + { \ + CHECK_ARG_COUNT_IS(name, SIZE(), 1); \ + \ + if (is(begin->get())) { \ + return *begin; \ + } \ + \ + VALUE_CAST(stringValue, String, (*begin)); \ + \ + return makePtr(stringValue->data()); \ } // (symbol "foo") @@ -692,8 +703,8 @@ ADD_FUNCTION( { auto result = makePtr(); - for (auto node : nodes) { - result->add(node); + for (auto it = begin; it != end; ++it) { + result->add(*it); } return result; @@ -702,11 +713,11 @@ ADD_FUNCTION( ADD_FUNCTION( "hash-map", { - CHECK_ARG_COUNT_EVEN("hash-map", nodes.size()); + CHECK_ARG_COUNT_EVEN("hash-map", SIZE()); auto result = makePtr(); - for (auto it = nodes.begin(); it != nodes.end(); std::advance(it, 2)) { + for (auto it = begin; it != end; std::advance(it, 2)) { result->add(*it, *(std::next(it))); } @@ -717,16 +728,16 @@ ADD_FUNCTION( ADD_FUNCTION( "assoc", { - CHECK_ARG_COUNT_AT_LEAST("assoc", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("assoc", SIZE(), 1); - VALUE_CAST(hash_map, HashMap, nodes.front()); - nodes.pop_front(); + VALUE_CAST(hash_map, HashMap, (*begin)); + begin++; - CHECK_ARG_COUNT_EVEN("assoc", nodes.size()); + CHECK_ARG_COUNT_EVEN("assoc", SIZE()); auto result = makePtr(hash_map->elements()); - for (auto it = nodes.begin(); it != nodes.end(); std::advance(it, 2)) { + for (auto it = begin; it != end; std::advance(it, 2)) { result->add(*it, *(std::next(it))); } @@ -736,63 +747,62 @@ ADD_FUNCTION( ADD_FUNCTION( "dissoc", { - CHECK_ARG_COUNT_AT_LEAST("dissoc", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("dissoc", SIZE(), 1); - VALUE_CAST(hash_map, HashMap, nodes.front()); - nodes.pop_front(); + VALUE_CAST(hash_map, HashMap, (*begin)); + begin++; auto result = makePtr(hash_map->elements()); - for (auto node : nodes) { - result->remove(node); + for (auto it = begin; it != end; ++it) { + result->remove(*it); } return result; }); -// (get {:kw "value"} :kw) +// (get {:kw "value"} :kw) -> "value" ADD_FUNCTION( "get", { - CHECK_ARG_COUNT_AT_LEAST("get", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("get", SIZE(), 1); - if (is(nodes.front().get()) - && std::static_pointer_cast(nodes.front())->state() == Constant::Nil) { + if (is(begin->get()) + && std::static_pointer_cast(*begin)->state() == Constant::Nil) { return makePtr(); } - VALUE_CAST(hash_map, HashMap, nodes.front()); - nodes.pop_front(); + VALUE_CAST(hash_map, HashMap, (*begin)); + begin++; - if (nodes.size() == 0) { + if (SIZE() == 0) { return makePtr(); } - auto result = hash_map->get(nodes.front()); + auto result = hash_map->get(*begin); return (result) ? result : makePtr(); }); ADD_FUNCTION( "contains?", { - CHECK_ARG_COUNT_AT_LEAST("contains?", nodes.size(), 1); + CHECK_ARG_COUNT_IS("contains?", SIZE(), 2); - VALUE_CAST(hash_map, HashMap, nodes.front()); - nodes.pop_front(); + VALUE_CAST(hash_map, HashMap, (*begin)); - if (nodes.size() == 0) { + if (SIZE() == 0) { return makePtr(false); } - return makePtr(hash_map->exists(nodes.front())); + return makePtr(hash_map->exists(*(begin + 1))); }); ADD_FUNCTION( "keys", { - CHECK_ARG_COUNT_AT_LEAST("keys", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("keys", SIZE(), 1); - VALUE_CAST(hash_map, HashMap, nodes.front()); + VALUE_CAST(hash_map, HashMap, (*begin)); auto result = makePtr(); @@ -812,9 +822,9 @@ ADD_FUNCTION( ADD_FUNCTION( "vals", { - CHECK_ARG_COUNT_AT_LEAST("vals", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("vals", SIZE(), 1); - VALUE_CAST(hash_map, HashMap, nodes.front()); + VALUE_CAST(hash_map, HashMap, (*begin)); auto result = makePtr(); @@ -829,31 +839,33 @@ ADD_FUNCTION( ADD_FUNCTION( "readline", { - CHECK_ARG_COUNT_IS("readline", nodes.size(), 1); + CHECK_ARG_COUNT_IS("readline", SIZE(), 1); - VALUE_CAST(prompt, String, nodes.front()); + VALUE_CAST(prompt, String, (*begin)); return readline(prompt->data()); }); -ADD_FUNCTION("time-ms", { - CHECK_ARG_COUNT_IS("time-ms", nodes.size(), 0); +ADD_FUNCTION( + "time-ms", + { + CHECK_ARG_COUNT_IS("time-ms", SIZE(), 0); - int64_t elapsed = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + int64_t elapsed = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); - return makePtr(elapsed); -}); + return makePtr(elapsed); + }); // (meta [1 2 3]) ADD_FUNCTION( "meta", { - CHECK_ARG_COUNT_IS("meta", nodes.size(), 1); + CHECK_ARG_COUNT_IS("meta", SIZE(), 1); - auto front = nodes.front(); - Value* front_raw_ptr = nodes.front().get(); + auto front = *begin; + Value* front_raw_ptr = begin->get(); if (!is(front_raw_ptr) && // List / Vector !is(front_raw_ptr) && // HashMap @@ -869,10 +881,10 @@ ADD_FUNCTION( ADD_FUNCTION( "with-meta", { - CHECK_ARG_COUNT_IS("with-meta", nodes.size(), 2); + CHECK_ARG_COUNT_IS("with-meta", SIZE(), 2); - auto front = nodes.front(); - Value* front_raw_ptr = nodes.front().get(); + auto front = *begin; + Value* front_raw_ptr = begin->get(); if (!is(front_raw_ptr) && // List / Vector !is(front_raw_ptr) && // HashMap @@ -881,7 +893,7 @@ ADD_FUNCTION( return nullptr; } - return front->withMeta(nodes.back()); + return front->withMeta(*(begin + 1)); }); // (conj '(1 2 3) 4 5 6) -> (6 5 4 1 2 3) @@ -889,25 +901,28 @@ ADD_FUNCTION( ADD_FUNCTION( "conj", { - CHECK_ARG_COUNT_AT_LEAST("conj", nodes.size(), 1); + CHECK_ARG_COUNT_AT_LEAST("conj", SIZE(), 1); - VALUE_CAST(collection, Collection, nodes.front()); - nodes.pop_front(); + VALUE_CAST(collection, Collection, (*begin)); + begin++; - auto collection_nodes = collection->nodes(); + const auto& collection_nodes = collection->nodes(); + size_t collection_count = collection_nodes.size(); + size_t argument_count = SIZE(); + + ValueList* nodes = new ValueList(argument_count + collection_count); if (is(collection.get())) { - nodes.reverse(); - nodes.splice(nodes.end(), collection_nodes); - auto result = makePtr(nodes); + std::reverse_copy(begin, end, nodes->begin()); + std::copy(collection_nodes.begin(), collection_nodes.end(), nodes->begin() + argument_count); - return result; + return makePtr(*nodes); } - nodes.splice(nodes.begin(), collection_nodes); - auto result = makePtr(nodes); + std::copy(collection_nodes.begin(), collection_nodes.end(), nodes->begin()); + std::copy(begin, end, nodes->begin() + collection_count); - return result; + return makePtr(*nodes); }); // (seq '(1 2 3)) -> (1 2 3) @@ -916,9 +931,9 @@ ADD_FUNCTION( ADD_FUNCTION( "seq", { - CHECK_ARG_COUNT_IS("seq", nodes.size(), 1); + CHECK_ARG_COUNT_IS("seq", SIZE(), 1); - auto front = nodes.front(); + auto front = *begin; Value* front_raw_ptr = front.get(); if (is(front_raw_ptr) && std::static_pointer_cast(front)->state() == Constant::Nil) {