Browse Source

Everywhere: Convert List and Vector back to std::vector, ~+20% speed

master
Riyyi 2 years ago
parent
commit
63c31d7ccf
  1. 41
      src/ast.cpp
  2. 10
      src/ast.h
  3. 2
      src/environment.cpp
  4. 2
      src/environment.h
  5. 32
      src/eval-special-form.cpp
  6. 5
      src/eval.cpp
  7. 22
      src/eval.h
  8. 4
      src/forward.h
  9. 369
      src/functions.cpp

41
src/ast.cpp

@ -5,8 +5,9 @@
*/ */
#include <cstdint> // int64_t #include <cstdint> // int64_t
#include <memory> #include <memory> // std::static_pointer_cast
#include <string> #include <string>
#include <vector>
#include "ast.h" #include "ast.h"
#include "environment.h" #include "environment.h"
@ -29,11 +30,16 @@ ValuePtr Value::meta() const
// ----------------------------------------- // -----------------------------------------
Collection::Collection(const std::list<ValuePtr>& nodes) Collection::Collection(const ValueList& nodes)
: m_nodes(nodes) : m_nodes(nodes)
{ {
} }
Collection::Collection(ValueListIt begin, ValueListIt end)
: m_nodes(ValueList(begin, end))
{
}
Collection::Collection(ValueListConstIt begin, ValueListConstIt end) Collection::Collection(ValueListConstIt begin, ValueListConstIt end)
: m_nodes(ValueList(begin, end)) : m_nodes(ValueList(begin, end))
{ {
@ -54,30 +60,21 @@ void Collection::add(ValuePtr node)
m_nodes.push_back(node); m_nodes.push_back(node);
} }
void Collection::addFront(ValuePtr node)
{
if (node == nullptr) {
return;
}
m_nodes.push_front(node);
}
ValueList Collection::rest() const 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()); return ValueList(start, m_nodes.end());
} }
// ----------------------------------------- // -----------------------------------------
List::List(const List& that, ValuePtr meta) List::List(const ValueList& nodes)
: Collection(that, meta) : Collection(nodes)
{ {
} }
List::List(const std::list<ValuePtr>& nodes) List::List(ValueListIt begin, ValueListIt end)
: Collection(nodes) : 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<ValuePtr>& nodes) Vector::Vector(const ValueList& nodes)
: Collection(nodes) : Collection(nodes)
{ {
} }
Vector::Vector(ValueListIt begin, ValueListIt end)
: Collection(begin, end)
{
}
Vector::Vector(ValueListConstIt begin, ValueListConstIt end) Vector::Vector(ValueListConstIt begin, ValueListConstIt end)
: Collection(begin, end) : Collection(begin, end)
{ {

10
src/ast.h

@ -95,7 +95,6 @@ public:
virtual ~Collection() = default; virtual ~Collection() = default;
void add(ValuePtr node); void add(ValuePtr node);
void addFront(ValuePtr node);
// TODO: rename size -> count // TODO: rename size -> count
size_t size() const { return m_nodes.size(); } size_t size() const { return m_nodes.size(); }
@ -109,6 +108,7 @@ public:
protected: protected:
Collection() = default; Collection() = default;
Collection(const ValueList& nodes); Collection(const ValueList& nodes);
Collection(ValueListIt begin, ValueListIt end);
Collection(ValueListConstIt begin, ValueListConstIt end); Collection(ValueListConstIt begin, ValueListConstIt end);
Collection(const Collection& that, ValuePtr meta); Collection(const Collection& that, ValuePtr meta);
@ -130,7 +130,8 @@ private:
class List final : public Collection { class List final : public Collection {
public: public:
List() = default; List() = default;
List(const std::list<ValuePtr>& nodes); List(const ValueList& nodes);
List(ValueListIt begin, ValueListIt end);
List(ValueListConstIt begin, ValueListConstIt end); List(ValueListConstIt begin, ValueListConstIt end);
List(const List& that, ValuePtr meta); List(const List& that, ValuePtr meta);
@ -154,7 +155,8 @@ private:
class Vector final : public Collection { class Vector final : public Collection {
public: public:
Vector() = default; Vector() = default;
Vector(const std::list<ValuePtr>& nodes); Vector(const ValueList& nodes);
Vector(ValueListIt begin, ValueListIt end);
Vector(ValueListConstIt begin, ValueListConstIt end); Vector(ValueListConstIt begin, ValueListConstIt end);
Vector(const Vector& that, ValuePtr meta); Vector(const Vector& that, ValuePtr meta);
@ -322,7 +324,7 @@ private:
// ----------------------------------------- // -----------------------------------------
using FunctionType = std::function<ValuePtr(std::list<ValuePtr>)>; using FunctionType = std::function<ValuePtr(ValueListIt, ValueListIt)>;
class Function final : public Callable { class Function final : public Callable {
public: public:

2
src/environment.cpp

@ -29,7 +29,7 @@ EnvironmentPtr Environment::create(EnvironmentPtr outer)
return env; return env;
} }
EnvironmentPtr Environment::create(const ValuePtr lambda, const std::list<ValuePtr>& arguments) EnvironmentPtr Environment::create(const ValuePtr lambda, const ValueList& arguments)
{ {
auto lambda_casted = std::static_pointer_cast<Lambda>(lambda); auto lambda_casted = std::static_pointer_cast<Lambda>(lambda);
auto env = create(lambda_casted->env()); auto env = create(lambda_casted->env());

2
src/environment.h

@ -21,7 +21,7 @@ public:
// Factory functions instead of constructors because it can fail in the bindings/arguments case // Factory functions instead of constructors because it can fail in the bindings/arguments case
static EnvironmentPtr create(); static EnvironmentPtr create();
static EnvironmentPtr create(EnvironmentPtr outer); static EnvironmentPtr create(EnvironmentPtr outer);
static EnvironmentPtr create(const ValuePtr lambda, const std::list<ValuePtr>& arguments); static EnvironmentPtr create(const ValuePtr lambda, const ValueList& arguments);
bool exists(const std::string& symbol); bool exists(const std::string& symbol);
ValuePtr set(const std::string& symbol, ValuePtr value); ValuePtr set(const std::string& symbol, ValuePtr value);

32
src/eval-special-form.cpp

@ -22,7 +22,7 @@ namespace blaze {
static ValuePtr evalQuasiQuoteImpl(ValuePtr ast); static ValuePtr evalQuasiQuoteImpl(ValuePtr ast);
// (def! x 2) // (def! x 2)
ValuePtr Eval::evalDef(const std::list<ValuePtr>& nodes, EnvironmentPtr env) ValuePtr Eval::evalDef(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("def!", nodes.size(), 2); CHECK_ARG_COUNT_IS("def!", nodes.size(), 2);
@ -44,7 +44,7 @@ ValuePtr Eval::evalDef(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
} }
// (defmacro! x (fn* (x) x)) // (defmacro! x (fn* (x) x))
ValuePtr Eval::evalDefMacro(const std::list<ValuePtr>& nodes, EnvironmentPtr env) ValuePtr Eval::evalDefMacro(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("defmacro!", nodes.size(), 2); CHECK_ARG_COUNT_IS("defmacro!", nodes.size(), 2);
@ -67,15 +67,17 @@ ValuePtr Eval::evalDefMacro(const std::list<ValuePtr>& nodes, EnvironmentPtr env
} }
// (fn* (x) x) // (fn* (x) x)
ValuePtr Eval::evalFn(const std::list<ValuePtr>& nodes, EnvironmentPtr env) ValuePtr Eval::evalFn(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("fn*", nodes.size(), 2); CHECK_ARG_COUNT_IS("fn*", nodes.size(), 2);
// First element needs to be a List or Vector // First element needs to be a List or Vector
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, nodes.front());
const auto& collection_nodes = collection->nodes();
std::vector<std::string> bindings; std::vector<std::string> bindings;
for (auto node : collection->nodes()) { bindings.reserve(collection_nodes.size());
for (const auto& node : collection_nodes) {
// All nodes need to be a Symbol // All nodes need to be a Symbol
VALUE_CAST(symbol, Symbol, node); VALUE_CAST(symbol, Symbol, node);
bindings.push_back(symbol->symbol()); bindings.push_back(symbol->symbol());
@ -86,7 +88,7 @@ ValuePtr Eval::evalFn(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
return makePtr<Lambda>(bindings, *std::next(nodes.begin()), env); return makePtr<Lambda>(bindings, *std::next(nodes.begin()), env);
} }
ValuePtr Eval::evalMacroExpand(const std::list<ValuePtr>& nodes, EnvironmentPtr env) ValuePtr Eval::evalMacroExpand(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("macroexpand", nodes.size(), 1); CHECK_ARG_COUNT_IS("macroexpand", nodes.size(), 1);
@ -94,7 +96,7 @@ ValuePtr Eval::evalMacroExpand(const std::list<ValuePtr>& nodes, EnvironmentPtr
} }
// (quasiquoteexpand x) // (quasiquoteexpand x)
ValuePtr Eval::evalQuasiQuoteExpand(const std::list<ValuePtr>& nodes) ValuePtr Eval::evalQuasiQuoteExpand(const ValueList& nodes)
{ {
CHECK_ARG_COUNT_IS("quasiquoteexpand", nodes.size(), 1); CHECK_ARG_COUNT_IS("quasiquoteexpand", nodes.size(), 1);
@ -102,7 +104,7 @@ ValuePtr Eval::evalQuasiQuoteExpand(const std::list<ValuePtr>& nodes)
} }
// (quote x) // (quote x)
ValuePtr Eval::evalQuote(const std::list<ValuePtr>& nodes) ValuePtr Eval::evalQuote(const ValueList& nodes)
{ {
CHECK_ARG_COUNT_IS("quote", nodes.size(), 1); CHECK_ARG_COUNT_IS("quote", nodes.size(), 1);
@ -110,7 +112,7 @@ ValuePtr Eval::evalQuote(const std::list<ValuePtr>& nodes)
} }
// (do 1 2 3) // (do 1 2 3)
void Eval::evalDo(const std::list<ValuePtr>& nodes, EnvironmentPtr env) void Eval::evalDo(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_AT_LEAST("do", nodes.size(), 1, void()); CHECK_ARG_COUNT_AT_LEAST("do", nodes.size(), 1, void());
@ -128,7 +130,7 @@ void Eval::evalDo(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
} }
// (if x true false) // (if x true false)
void Eval::evalIf(const std::list<ValuePtr>& nodes, EnvironmentPtr env) void Eval::evalIf(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_BETWEEN("if", nodes.size(), 2, 3, void()); CHECK_ARG_COUNT_BETWEEN("if", nodes.size(), 2, 3, void());
@ -152,13 +154,13 @@ void Eval::evalIf(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
} }
// (let* (x 1) x) // (let* (x 1) x)
void Eval::evalLet(const std::list<ValuePtr>& nodes, EnvironmentPtr env) void Eval::evalLet(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("let*", nodes.size(), 2, void()); CHECK_ARG_COUNT_IS("let*", nodes.size(), 2, void());
// First argument needs to be a List or Vector // First argument needs to be a List or Vector
VALUE_CAST(bindings, Collection, nodes.front(), void()); 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 // List or Vector needs to have an even number of elements
CHECK_ARG_COUNT_EVEN("bindings", binding_nodes.size(), void()); CHECK_ARG_COUNT_EVEN("bindings", binding_nodes.size(), void());
@ -207,7 +209,7 @@ static ValuePtr startsWith(ValuePtr ast, const std::string& symbol)
return nullptr; return nullptr;
} }
auto nodes = std::static_pointer_cast<List>(ast)->nodes(); const auto& nodes = std::static_pointer_cast<List>(ast)->nodes();
if (nodes.empty() || !isSymbol(nodes.front(), symbol)) { if (nodes.empty() || !isSymbol(nodes.front(), symbol)) {
return nullptr; return nullptr;
@ -269,7 +271,7 @@ static ValuePtr evalQuasiQuoteImpl(ValuePtr ast)
} }
// (quasiquote x) // (quasiquote x)
void Eval::evalQuasiQuote(const std::list<ValuePtr>& nodes, EnvironmentPtr env) void Eval::evalQuasiQuote(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_IS("quasiquote", nodes.size(), 1, void()); CHECK_ARG_COUNT_IS("quasiquote", nodes.size(), 1, void());
@ -281,7 +283,7 @@ void Eval::evalQuasiQuote(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
} }
// (try* x (catch* y z)) // (try* x (catch* y z))
void Eval::evalTry(const std::list<ValuePtr>& nodes, EnvironmentPtr env) void Eval::evalTry(const ValueList& nodes, EnvironmentPtr env)
{ {
CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1, void()); CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1, void());
@ -299,7 +301,7 @@ void Eval::evalTry(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
Error::the().clearErrors(); Error::the().clearErrors();
VALUE_CAST(catch_list, List, nodes.back(), void()); 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()); CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2, void());
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front(), void()); VALUE_CAST(catch_symbol, Symbol, catch_nodes.front(), void());

5
src/eval.cpp

@ -249,12 +249,9 @@ ValuePtr Eval::apply(std::shared_ptr<List> evaluated_list)
return nullptr; return nullptr;
} }
// car
auto function = std::static_pointer_cast<Function>(nodes.front())->function(); auto function = std::static_pointer_cast<Function>(nodes.front())->function();
// cdr
nodes.pop_front();
return function(nodes); return function(nodes.begin() + 1, nodes.end());
} }
} // namespace blaze } // namespace blaze

22
src/eval.h

@ -32,17 +32,17 @@ private:
bool isMacroCall(ValuePtr ast, EnvironmentPtr env); bool isMacroCall(ValuePtr ast, EnvironmentPtr env);
ValuePtr macroExpand(ValuePtr ast, EnvironmentPtr env); ValuePtr macroExpand(ValuePtr ast, EnvironmentPtr env);
ValuePtr evalDef(const std::list<ValuePtr>& nodes, EnvironmentPtr env); ValuePtr evalDef(const ValueList& nodes, EnvironmentPtr env);
ValuePtr evalDefMacro(const std::list<ValuePtr>& nodes, EnvironmentPtr env); ValuePtr evalDefMacro(const ValueList& nodes, EnvironmentPtr env);
ValuePtr evalFn(const std::list<ValuePtr>& nodes, EnvironmentPtr env); ValuePtr evalFn(const ValueList& nodes, EnvironmentPtr env);
ValuePtr evalMacroExpand(const std::list<ValuePtr>& nodes, EnvironmentPtr env); ValuePtr evalMacroExpand(const ValueList& nodes, EnvironmentPtr env);
ValuePtr evalQuasiQuoteExpand(const std::list<ValuePtr>& nodes); ValuePtr evalQuasiQuoteExpand(const ValueList& nodes);
ValuePtr evalQuote(const std::list<ValuePtr>& nodes); ValuePtr evalQuote(const ValueList& nodes);
void evalDo(const std::list<ValuePtr>& nodes, EnvironmentPtr env); void evalDo(const ValueList& nodes, EnvironmentPtr env);
void evalIf(const std::list<ValuePtr>& nodes, EnvironmentPtr env); void evalIf(const ValueList& nodes, EnvironmentPtr env);
void evalLet(const std::list<ValuePtr>& nodes, EnvironmentPtr env); void evalLet(const ValueList& nodes, EnvironmentPtr env);
void evalQuasiQuote(const std::list<ValuePtr>& nodes, EnvironmentPtr env); void evalQuasiQuote(const ValueList& nodes, EnvironmentPtr env);
void evalTry(const std::list<ValuePtr>& nodes, EnvironmentPtr env); void evalTry(const ValueList& nodes, EnvironmentPtr env);
ValuePtr apply(std::shared_ptr<List> evaluated_list); ValuePtr apply(std::shared_ptr<List> evaluated_list);

4
src/forward.h

@ -6,8 +6,8 @@
#pragma once #pragma once
#include <list>
#include <memory> // std::shared_ptr #include <memory> // std::shared_ptr
#include <vector>
namespace blaze { namespace blaze {
@ -16,7 +16,7 @@ namespace blaze {
class Value; class Value;
typedef std::shared_ptr<Value> ValuePtr; typedef std::shared_ptr<Value> ValuePtr;
typedef std::list<ValuePtr> ValueList; typedef std::vector<ValuePtr> ValueList;
typedef ValueList::iterator ValueListIt; typedef ValueList::iterator ValueListIt;
typedef ValueList::const_iterator ValueListConstIt; typedef ValueList::const_iterator ValueListConstIt;

369
src/functions.cpp

@ -4,9 +4,10 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <algorithm> // std::copy, std::reverse_copy
#include <chrono> // std::chrono::sytem_clock #include <chrono> // std::chrono::sytem_clock
#include <cstdint> // int64_t #include <cstdint> // int64_t
#include <iterator> // std::advance #include <iterator> // std::advance, std::distance, std::next, std::prev
#include <memory> // std::static_pointer_cast #include <memory> // std::static_pointer_cast
#include <string> #include <string>
@ -38,10 +39,12 @@
static struct FUNCTION_STRUCT_NAME(unique) \ static struct FUNCTION_STRUCT_NAME(unique) \
FUNCTION_STRUCT_NAME(unique)( \ FUNCTION_STRUCT_NAME(unique)( \
symbol, \ symbol, \
[](std::list<ValuePtr> nodes) -> ValuePtr lambda); [](ValueListIt begin, ValueListIt end) -> ValuePtr lambda);
#define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda); #define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda);
#define SIZE() std::distance(begin, end)
namespace blaze { namespace blaze {
static std::unordered_map<std::string, FunctionType> s_functions; static std::unordered_map<std::string, FunctionType> s_functions;
@ -51,8 +54,8 @@ ADD_FUNCTION(
{ {
int64_t result = 0; int64_t result = 0;
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
VALUE_CAST(number, Number, node); VALUE_CAST(number, Number, (*it));
result += number->number(); result += number->number();
} }
@ -62,16 +65,16 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"-", "-",
{ {
if (nodes.size() == 0) { if (SIZE() == 0) {
return makePtr<Number>(0); return makePtr<Number>(0);
} }
// Start with the first number // Start with the first number
VALUE_CAST(number, Number, nodes.front()); VALUE_CAST(number, Number, (*begin));
int64_t result = number->number(); int64_t result = number->number();
// Skip the first node // 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)); VALUE_CAST(number, Number, (*it));
result -= number->number(); result -= number->number();
} }
@ -84,8 +87,8 @@ ADD_FUNCTION(
{ {
int64_t result = 1; int64_t result = 1;
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
VALUE_CAST(number, Number, node); VALUE_CAST(number, Number, (*it));
result *= number->number(); result *= number->number();
} }
@ -95,14 +98,14 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"/", "/",
{ {
CHECK_ARG_COUNT_AT_LEAST("/", nodes.size(), 1); CHECK_ARG_COUNT_AT_LEAST("/", SIZE(), 1);
// Start with the first number // Start with the first number
VALUE_CAST(number, Number, nodes.front()); VALUE_CAST(number, Number, (*begin));
double result = number->number(); double result = number->number();
// Skip the first node // 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)); VALUE_CAST(number, Number, (*it));
result /= number->number(); result /= number->number();
} }
@ -116,14 +119,14 @@ ADD_FUNCTION(
{ \ { \
bool result = true; \ 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 */ \ /* Start with the first number */ \
VALUE_CAST(number_node, Number, nodes.front()); \ VALUE_CAST(number_node, Number, (*begin)); \
int64_t number = number_node->number(); \ int64_t number = number_node->number(); \
\ \
/* Skip the first node */ \ /* 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)); \ VALUE_CAST(current_number_node, Number, (*it)); \
int64_t current_number = current_number_node->number(); \ int64_t current_number = current_number_node->number(); \
if (!(number operator current_number)) { \ if (!(number operator current_number)) { \
@ -146,7 +149,7 @@ ADD_FUNCTION(">=", NUMBER_COMPARE(>=));
ADD_FUNCTION( ADD_FUNCTION(
"list", "list",
{ {
return makePtr<List>(nodes); return makePtr<List>(begin, end);
}); });
ADD_FUNCTION( ADD_FUNCTION(
@ -154,8 +157,8 @@ ADD_FUNCTION(
{ {
bool result = true; bool result = true;
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
VALUE_CAST(collection, Collection, node); VALUE_CAST(collection, Collection, (*it));
if (!collection->empty()) { if (!collection->empty()) {
result = false; result = false;
break; break;
@ -169,19 +172,17 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"count", "count",
{ {
CHECK_ARG_COUNT_IS("count", nodes.size(), 1); CHECK_ARG_COUNT_IS("count", SIZE(), 1);
auto first_argument = nodes.front();
size_t result = 0; size_t result = 0;
if (is<Constant>(first_argument.get()) && std::static_pointer_cast<Constant>(nodes.front())->state() == Constant::Nil) { if (is<Constant>(begin->get()) && std::static_pointer_cast<Constant>(*begin)->state() == Constant::Nil) {
// result = 0 // result = 0
} }
else if (is<Collection>(first_argument.get())) { else if (is<Collection>(begin->get())) {
result = std::static_pointer_cast<Collection>(first_argument)->size(); result = std::static_pointer_cast<Collection>(*begin)->size();
} }
else { else {
Error::the().add(format("wrong argument type: Collection, '{}'", first_argument)); Error::the().add(format("wrong argument type: Collection, '{}'", *begin));
return nullptr; return nullptr;
} }
@ -196,10 +197,10 @@ ADD_FUNCTION(
std::string result; \ std::string result; \
\ \
Printer printer; \ 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)); \ result += format("{}", printer.printNoErrorCheck(*it, print_readably)); \
\ \
if (!isLast(it, nodes)) { \ if (it != end && std::next(it) != end) { \
result += concatenation; \ result += concatenation; \
} \ } \
} \ } \
@ -213,10 +214,10 @@ ADD_FUNCTION("pr-str", PRINTER_STRING(true, " "));
#define PRINTER_PRINT(print_readably) \ #define PRINTER_PRINT(print_readably) \
{ \ { \
Printer printer; \ Printer printer; \
for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ for (auto it = begin; it != end; ++it) { \
print("{}", printer.printNoErrorCheck(*it, print_readably)); \ print("{}", printer.printNoErrorCheck(*it, print_readably)); \
\ \
if (!isLast(it, nodes)) { \ if (it != end && std::next(it) != end) { \
print(" "); \ print(" "); \
} \ } \
} \ } \
@ -233,7 +234,7 @@ ADD_FUNCTION("println", PRINTER_PRINT(false));
ADD_FUNCTION( ADD_FUNCTION(
"=", "=",
{ {
CHECK_ARG_COUNT_AT_LEAST("=", nodes.size(), 2); CHECK_ARG_COUNT_AT_LEAST("=", SIZE(), 2);
std::function<bool(ValuePtr, ValuePtr)> equal = std::function<bool(ValuePtr, ValuePtr)> equal =
[&equal](ValuePtr lhs, ValuePtr rhs) -> bool { [&equal](ValuePtr lhs, ValuePtr rhs) -> bool {
@ -300,9 +301,9 @@ ADD_FUNCTION(
}; };
bool result = true; bool result = true;
auto it = nodes.begin(); auto it = begin;
auto it_next = std::next(nodes.begin()); auto it_next = begin + 1;
for (; it_next != nodes.end(); ++it, ++it_next) { for (; it_next != end; ++it, ++it_next) {
if (!equal(*it, *it_next)) { if (!equal(*it, *it_next)) {
result = false; result = false;
break; break;
@ -315,9 +316,9 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"read-string", "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(); std::string input = node->data();
return read(input); return read(input);
@ -326,9 +327,9 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"slurp", "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(); std::string path = node->data();
auto file = ruc::File(path); auto file = ruc::File(path);
@ -339,27 +340,27 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"eval", "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) // (atom 1)
ADD_FUNCTION( ADD_FUNCTION(
"atom", "atom",
{ {
CHECK_ARG_COUNT_IS("atom", nodes.size(), 1); CHECK_ARG_COUNT_IS("atom", SIZE(), 1);
return makePtr<Atom>(nodes.front()); return makePtr<Atom>(*begin);
}); });
// (deref myatom) // (deref myatom)
ADD_FUNCTION( ADD_FUNCTION(
"deref", "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(); return atom->deref();
}); });
@ -368,10 +369,10 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"reset!", "reset!",
{ {
CHECK_ARG_COUNT_IS("reset!", nodes.size(), 2); CHECK_ARG_COUNT_IS("reset!", SIZE(), 2);
VALUE_CAST(atom, Atom, nodes.front()); VALUE_CAST(atom, Atom, (*begin));
auto value = *std::next(nodes.begin()); auto value = *(begin + 1);
atom->reset(value); atom->reset(value);
@ -382,83 +383,95 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"swap!", "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 // Remove atom and function from the argument list, add atom value
nodes.pop_front(); begin += 2;
nodes.pop_front(); auto arguments = ValueList(end - begin + 1);
nodes.push_front(atom->deref()); arguments[0] = atom->deref();
std::copy(begin, end, arguments.begin() + 1);
ValuePtr value = nullptr; ValuePtr value = nullptr;
if (is<Function>(callable.get())) { if (is<Function>(callable.get())) {
auto function = std::static_pointer_cast<Function>(callable)->function(); auto function = std::static_pointer_cast<Function>(callable)->function();
value = function(nodes); value = function(arguments.begin(), arguments.end());
} }
else { else {
auto lambda = std::static_pointer_cast<Lambda>(callable); auto lambda = std::static_pointer_cast<Lambda>(callable);
value = eval(lambda->body(), Environment::create(lambda, nodes)); value = eval(lambda->body(), Environment::create(lambda, arguments));
} }
return atom->reset(value); return atom->reset(value);
}); });
// (cons 1 (list 2 3)) -> (1 2 3) // (cons 1 (list 2 3))
ADD_FUNCTION( ADD_FUNCTION(
"cons", "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<List>(collection->nodes()); VALUE_CAST(collection, Collection, (*begin));
result->addFront(nodes.front()); 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<List>(*result_nodes);
}); });
// (concat (list 1) (list 2 3)) -> (1 2 3) // (concat (list 1) (list 2 3)) -> (1 2 3)
ADD_FUNCTION( ADD_FUNCTION(
"concat", "concat",
{ {
std::list<ValuePtr> 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) { auto result_nodes = new ValueList(count);
VALUE_CAST(collection, Collection, node); size_t offset = 0;
auto argument_nodes = collection->nodes(); for (auto it = begin; it != end; ++it) {
result_nodes.splice(result_nodes.end(), argument_nodes); const auto& collection_nodes = std::static_pointer_cast<Collection>(*it)->nodes();
std::copy(collection_nodes.begin(), collection_nodes.end(), result_nodes->begin() + offset);
offset += collection_nodes.size();
} }
return makePtr<List>(result_nodes); return makePtr<List>(*result_nodes);
}); });
// (vec (list 1 2 3)) -> [1 2 3] // (vec (list 1 2 3))
ADD_FUNCTION( ADD_FUNCTION(
"vec", "vec",
{ {
CHECK_ARG_COUNT_IS("vec", nodes.size(), 1); CHECK_ARG_COUNT_IS("vec", SIZE(), 1);
if (is<Vector>(nodes.front().get())) { if (is<Vector>(begin->get())) {
return nodes.front(); return *begin;
} }
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, (*begin));
return makePtr<Vector>(collection->nodes()); return makePtr<Vector>(collection->nodes());
}); });
// (nth (list 1 2 3) 0) -> 1 // (nth (list 1 2 3) 0)
ADD_FUNCTION( ADD_FUNCTION(
"nth", "nth",
{ {
CHECK_ARG_COUNT_IS("nth", nodes.size(), 2); CHECK_ARG_COUNT_IS("nth", SIZE(), 2);
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, (*begin));
VALUE_CAST(number_node, Number, (*std::next(nodes.begin()))); VALUE_CAST(number_node, Number, (*(begin + 1)));
const auto& collection_nodes = collection->nodes(); auto collection_nodes = collection->nodes();
auto index = (size_t)number_node->number(); auto index = (size_t)number_node->number();
if (number_node->number() < 0 || index >= collection_nodes.size()) { if (number_node->number() < 0 || index >= collection_nodes.size()) {
@ -466,7 +479,7 @@ ADD_FUNCTION(
return nullptr; return nullptr;
} }
auto result = collection_nodes.cbegin(); auto result = collection_nodes.begin();
for (size_t i = 0; i < index; ++i) { for (size_t i = 0; i < index; ++i) {
result++; result++;
} }
@ -478,30 +491,30 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"first", "first",
{ {
CHECK_ARG_COUNT_IS("first", nodes.size(), 1); CHECK_ARG_COUNT_IS("first", SIZE(), 1);
if (is<Constant>(nodes.front().get()) if (is<Constant>(begin->get())
&& std::static_pointer_cast<Constant>(nodes.front())->state() == Constant::Nil) { && std::static_pointer_cast<Constant>(*begin)->state() == Constant::Nil) {
return makePtr<Constant>(); return makePtr<Constant>();
} }
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, (*begin));
return (collection->empty()) ? makePtr<Constant>() : collection->front(); return (collection->empty()) ? makePtr<Constant>() : collection->front();
}); });
// (rest (list 1 2 3)) -> (2 3) // (rest (list 1 2 3))
ADD_FUNCTION( ADD_FUNCTION(
"rest", "rest",
{ {
CHECK_ARG_COUNT_IS("rest", nodes.size(), 1); CHECK_ARG_COUNT_IS("rest", SIZE(), 1);
if (is<Constant>(nodes.front().get()) if (is<Constant>(begin->get())
&& std::static_pointer_cast<Constant>(nodes.front())->state() == Constant::Nil) { && std::static_pointer_cast<Constant>(*begin)->state() == Constant::Nil) {
return makePtr<List>(); return makePtr<List>();
} }
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, (*begin));
return makePtr<List>(collection->rest()); return makePtr<List>(collection->rest());
}); });
@ -510,29 +523,30 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"apply", "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); IS_VALUE(Callable, callable);
VALUE_CAST(collection, Collection, nodes.back()); VALUE_CAST(collection, Collection, (*std::prev(end)));
// Remove function and list from the arguments ValueList arguments(begin + 1, end - 1);
nodes.pop_front(); arguments.reserve(arguments.size() + collection->size());
nodes.pop_back();
// Append list nodes to the argument leftovers // Append list nodes to the argument leftovers
auto collection_nodes = collection->nodes(); auto nodes = collection->nodes();
nodes.splice(nodes.end(), collection_nodes); for (const auto& node : nodes) {
arguments.push_back(node);
}
ValuePtr value = nullptr; ValuePtr value = nullptr;
if (is<Function>(callable.get())) { if (is<Function>(callable.get())) {
auto function = std::static_pointer_cast<Function>(callable)->function(); auto function = std::static_pointer_cast<Function>(callable)->function();
value = function(nodes); value = function(arguments.begin(), arguments.end());
} }
else { else {
auto lambda = std::static_pointer_cast<Lambda>(callable); auto lambda = std::static_pointer_cast<Lambda>(callable);
value = eval(lambda->body(), Environment::create(lambda, nodes)); value = eval(lambda->body(), Environment::create(lambda, arguments));
} }
return value; return value;
@ -542,10 +556,10 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"map", "map",
{ {
CHECK_ARG_COUNT_IS("map", nodes.size(), 2); CHECK_ARG_COUNT_IS("map", SIZE(), 2);
VALUE_CAST(callable, Callable, nodes.front()); VALUE_CAST(callable, Callable, (*begin));
VALUE_CAST(collection, Collection, nodes.back()); VALUE_CAST(collection, Collection, (*(begin + 1)));
const auto& collection_nodes = collection->nodes(); const auto& collection_nodes = collection->nodes();
auto result = makePtr<List>(); auto result = makePtr<List>();
@ -553,7 +567,8 @@ ADD_FUNCTION(
if (is<Function>(callable.get())) { if (is<Function>(callable.get())) {
auto function = std::static_pointer_cast<Function>(callable)->function(); auto function = std::static_pointer_cast<Function>(callable)->function();
for (const auto& node : collection_nodes) { for (const auto& node : collection_nodes) {
result->add(function({ node })); auto arguments = ValueList { node };
result->add(function(arguments.begin(), arguments.end()));
} }
} }
else { else {
@ -570,9 +585,9 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"throw", "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; return nullptr;
}) })
@ -581,11 +596,11 @@ ADD_FUNCTION(
#define IS_CONSTANT(name, constant) \ #define IS_CONSTANT(name, constant) \
{ \ { \
CHECK_ARG_COUNT_IS(name, nodes.size(), 1); \ CHECK_ARG_COUNT_IS(name, SIZE(), 1); \
\ \
return makePtr<Constant>( \ return makePtr<Constant>( \
is<Constant>(nodes.front().get()) \ is<Constant>(begin->get()) \
&& std::static_pointer_cast<Constant>(nodes.front())->state() == constant); \ && std::static_pointer_cast<Constant>(*begin)->state() == constant); \
} }
// (nil? nil) // (nil? nil)
@ -599,12 +614,12 @@ ADD_FUNCTION("false?", IS_CONSTANT("false?", Constant::False));
{ \ { \
bool result = true; \ bool result = true; \
\ \
if (nodes.size() == 0) { \ if (SIZE() == 0) { \
result = false; \ result = false; \
} \ } \
\ \
for (auto node : nodes) { \ for (auto it = begin; it != end; ++it) { \
if (!is<type>(node.get())) { \ if (!is<type>(it->get())) { \
result = false; \ result = false; \
break; \ break; \
} \ } \
@ -629,16 +644,12 @@ ADD_FUNCTION(
{ {
bool result = true; bool result = true;
if (nodes.size() == 0) { if (SIZE() == 0) {
result = false; result = false;
} }
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
if (!is<Callable>(node.get())) { if (!is<Callable>(it->get()) || is<Macro>(it->get())) {
result = false;
break;
}
if (is<Macro>(node.get())) {
result = false; result = false;
break; break;
} }
@ -652,12 +663,12 @@ ADD_FUNCTION(
{ {
bool result = true; bool result = true;
if (nodes.size() == 0) { if (SIZE() == 0) {
result = false; result = false;
} }
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
if (!is<Macro>(node.get())) { if (!is<Macro>(it->get())) {
result = false; result = false;
break; break;
} }
@ -670,13 +681,13 @@ ADD_FUNCTION(
#define STRING_TO_TYPE(name, type) \ #define STRING_TO_TYPE(name, type) \
{ \ { \
CHECK_ARG_COUNT_IS(name, nodes.size(), 1); \ CHECK_ARG_COUNT_IS(name, SIZE(), 1); \
\ \
if (is<type>(nodes.front().get())) { \ if (is<type>(begin->get())) { \
return nodes.front(); \ return *begin; \
} \ } \
\ \
VALUE_CAST(stringValue, String, nodes.front()); \ VALUE_CAST(stringValue, String, (*begin)); \
\ \
return makePtr<type>(stringValue->data()); \ return makePtr<type>(stringValue->data()); \
} }
@ -692,8 +703,8 @@ ADD_FUNCTION(
{ {
auto result = makePtr<Vector>(); auto result = makePtr<Vector>();
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
result->add(node); result->add(*it);
} }
return result; return result;
@ -702,11 +713,11 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"hash-map", "hash-map",
{ {
CHECK_ARG_COUNT_EVEN("hash-map", nodes.size()); CHECK_ARG_COUNT_EVEN("hash-map", SIZE());
auto result = makePtr<HashMap>(); auto result = makePtr<HashMap>();
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))); result->add(*it, *(std::next(it)));
} }
@ -717,16 +728,16 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"assoc", "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()); VALUE_CAST(hash_map, HashMap, (*begin));
nodes.pop_front(); begin++;
CHECK_ARG_COUNT_EVEN("assoc", nodes.size()); CHECK_ARG_COUNT_EVEN("assoc", SIZE());
auto result = makePtr<HashMap>(hash_map->elements()); auto result = makePtr<HashMap>(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))); result->add(*it, *(std::next(it)));
} }
@ -736,63 +747,62 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"dissoc", "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()); VALUE_CAST(hash_map, HashMap, (*begin));
nodes.pop_front(); begin++;
auto result = makePtr<HashMap>(hash_map->elements()); auto result = makePtr<HashMap>(hash_map->elements());
for (auto node : nodes) { for (auto it = begin; it != end; ++it) {
result->remove(node); result->remove(*it);
} }
return result; return result;
}); });
// (get {:kw "value"} :kw) // (get {:kw "value"} :kw) -> "value"
ADD_FUNCTION( ADD_FUNCTION(
"get", "get",
{ {
CHECK_ARG_COUNT_AT_LEAST("get", nodes.size(), 1); CHECK_ARG_COUNT_AT_LEAST("get", SIZE(), 1);
if (is<Constant>(nodes.front().get()) if (is<Constant>(begin->get())
&& std::static_pointer_cast<Constant>(nodes.front())->state() == Constant::Nil) { && std::static_pointer_cast<Constant>(*begin)->state() == Constant::Nil) {
return makePtr<Constant>(); return makePtr<Constant>();
} }
VALUE_CAST(hash_map, HashMap, nodes.front()); VALUE_CAST(hash_map, HashMap, (*begin));
nodes.pop_front(); begin++;
if (nodes.size() == 0) { if (SIZE() == 0) {
return makePtr<Constant>(); return makePtr<Constant>();
} }
auto result = hash_map->get(nodes.front()); auto result = hash_map->get(*begin);
return (result) ? result : makePtr<Constant>(); return (result) ? result : makePtr<Constant>();
}); });
ADD_FUNCTION( ADD_FUNCTION(
"contains?", "contains?",
{ {
CHECK_ARG_COUNT_AT_LEAST("contains?", nodes.size(), 1); CHECK_ARG_COUNT_IS("contains?", SIZE(), 2);
VALUE_CAST(hash_map, HashMap, nodes.front()); VALUE_CAST(hash_map, HashMap, (*begin));
nodes.pop_front();
if (nodes.size() == 0) { if (SIZE() == 0) {
return makePtr<Constant>(false); return makePtr<Constant>(false);
} }
return makePtr<Constant>(hash_map->exists(nodes.front())); return makePtr<Constant>(hash_map->exists(*(begin + 1)));
}); });
ADD_FUNCTION( ADD_FUNCTION(
"keys", "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<List>(); auto result = makePtr<List>();
@ -812,9 +822,9 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"vals", "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<List>(); auto result = makePtr<List>();
@ -829,15 +839,17 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"readline", "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()); return readline(prompt->data());
}); });
ADD_FUNCTION("time-ms", { ADD_FUNCTION(
CHECK_ARG_COUNT_IS("time-ms", nodes.size(), 0); "time-ms",
{
CHECK_ARG_COUNT_IS("time-ms", SIZE(), 0);
int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
@ -850,10 +862,10 @@ ADD_FUNCTION("time-ms", {
ADD_FUNCTION( ADD_FUNCTION(
"meta", "meta",
{ {
CHECK_ARG_COUNT_IS("meta", nodes.size(), 1); CHECK_ARG_COUNT_IS("meta", SIZE(), 1);
auto front = nodes.front(); auto front = *begin;
Value* front_raw_ptr = nodes.front().get(); Value* front_raw_ptr = begin->get();
if (!is<Collection>(front_raw_ptr) && // List / Vector if (!is<Collection>(front_raw_ptr) && // List / Vector
!is<HashMap>(front_raw_ptr) && // HashMap !is<HashMap>(front_raw_ptr) && // HashMap
@ -869,10 +881,10 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"with-meta", "with-meta",
{ {
CHECK_ARG_COUNT_IS("with-meta", nodes.size(), 2); CHECK_ARG_COUNT_IS("with-meta", SIZE(), 2);
auto front = nodes.front(); auto front = *begin;
Value* front_raw_ptr = nodes.front().get(); Value* front_raw_ptr = begin->get();
if (!is<Collection>(front_raw_ptr) && // List / Vector if (!is<Collection>(front_raw_ptr) && // List / Vector
!is<HashMap>(front_raw_ptr) && // HashMap !is<HashMap>(front_raw_ptr) && // HashMap
@ -881,7 +893,7 @@ ADD_FUNCTION(
return nullptr; 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) // (conj '(1 2 3) 4 5 6) -> (6 5 4 1 2 3)
@ -889,25 +901,28 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"conj", "conj",
{ {
CHECK_ARG_COUNT_AT_LEAST("conj", nodes.size(), 1); CHECK_ARG_COUNT_AT_LEAST("conj", SIZE(), 1);
VALUE_CAST(collection, Collection, nodes.front()); VALUE_CAST(collection, Collection, (*begin));
nodes.pop_front(); 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<List>(collection.get())) { if (is<List>(collection.get())) {
nodes.reverse(); std::reverse_copy(begin, end, nodes->begin());
nodes.splice(nodes.end(), collection_nodes); std::copy(collection_nodes.begin(), collection_nodes.end(), nodes->begin() + argument_count);
auto result = makePtr<List>(nodes);
return result; return makePtr<List>(*nodes);
} }
nodes.splice(nodes.begin(), collection_nodes); std::copy(collection_nodes.begin(), collection_nodes.end(), nodes->begin());
auto result = makePtr<Vector>(nodes); std::copy(begin, end, nodes->begin() + collection_count);
return result; return makePtr<Vector>(*nodes);
}); });
// (seq '(1 2 3)) -> (1 2 3) // (seq '(1 2 3)) -> (1 2 3)
@ -916,9 +931,9 @@ ADD_FUNCTION(
ADD_FUNCTION( ADD_FUNCTION(
"seq", "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(); Value* front_raw_ptr = front.get();
if (is<Constant>(front_raw_ptr) && std::static_pointer_cast<Constant>(front)->state() == Constant::Nil) { if (is<Constant>(front_raw_ptr) && std::static_pointer_cast<Constant>(front)->state() == Constant::Nil) {

Loading…
Cancel
Save