Everywhere: Convert List and Vector back to std::vector, ~+20% speed
This commit is contained in:
+24
-17
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
+1
-1
@@ -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());
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
|
|||||||
+17
-15
@@ -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());
|
||||||
|
|||||||
+1
-4
@@ -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
|
||||||
|
|||||||
+11
-11
@@ -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);
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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;
|
||||||
|
|
||||||
|
|||||||
+193
-178
@@ -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) {
|
||||||
for (auto node : nodes) {
|
VALUE_CAST(collection, Collection, (*it));
|
||||||
VALUE_CAST(collection, Collection, node);
|
count += collection->size();
|
||||||
auto argument_nodes = collection->nodes();
|
|
||||||
result_nodes.splice(result_nodes.end(), argument_nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return makePtr<List>(result_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<Collection>(*it)->nodes();
|
||||||
|
std::copy(collection_nodes.begin(), collection_nodes.end(), result_nodes->begin() + offset);
|
||||||
|
offset += collection_nodes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user