AST+Eval: Prevent list copy during core function 'rest'
This commit is contained in:
+21
@@ -22,6 +22,11 @@ Collection::Collection(const std::list<ValuePtr>& nodes)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection::Collection(ValueListConstIt begin, ValueListConstIt end)
|
||||||
|
: m_nodes(ValueList(begin, end))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Collection::add(ValuePtr node)
|
void Collection::add(ValuePtr node)
|
||||||
{
|
{
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
@@ -40,6 +45,12 @@ void Collection::addFront(ValuePtr node)
|
|||||||
m_nodes.push_front(node);
|
m_nodes.push_front(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueList Collection::rest() const
|
||||||
|
{
|
||||||
|
auto start = (m_nodes.size() > 0) ? std::next(m_nodes.begin()) : m_nodes.end();
|
||||||
|
return ValueList(start, m_nodes.end());
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
List::List(const std::list<ValuePtr>& nodes)
|
List::List(const std::list<ValuePtr>& nodes)
|
||||||
@@ -47,6 +58,11 @@ List::List(const std::list<ValuePtr>& nodes)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List::List(ValueListConstIt begin, ValueListConstIt end)
|
||||||
|
: Collection(begin, end)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Vector::Vector(const std::list<ValuePtr>& nodes)
|
Vector::Vector(const std::list<ValuePtr>& nodes)
|
||||||
@@ -54,6 +70,11 @@ Vector::Vector(const std::list<ValuePtr>& nodes)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector::Vector(ValueListConstIt begin, ValueListConstIt end)
|
||||||
|
: Collection(begin, end)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
HashMap::HashMap(const Elements& elements)
|
HashMap::HashMap(const Elements& elements)
|
||||||
|
|||||||
@@ -67,11 +67,14 @@ public:
|
|||||||
bool empty() const { return m_nodes.size() == 0; }
|
bool empty() const { return m_nodes.size() == 0; }
|
||||||
|
|
||||||
ValuePtr front() const { return m_nodes.front(); }
|
ValuePtr front() const { return m_nodes.front(); }
|
||||||
const std::list<ValuePtr>& nodes() const { return m_nodes; }
|
ValueList rest() const;
|
||||||
|
|
||||||
|
const ValueList& nodes() const { return m_nodes; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Collection() = default;
|
Collection() = default;
|
||||||
Collection(const std::list<ValuePtr>& nodes);
|
Collection(const ValueList& nodes);
|
||||||
|
Collection(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
Collection(std::shared_ptr<Ts>... nodes)
|
Collection(std::shared_ptr<Ts>... nodes)
|
||||||
@@ -82,7 +85,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
virtual bool isCollection() const override { return true; }
|
virtual bool isCollection() const override { return true; }
|
||||||
|
|
||||||
std::list<ValuePtr> m_nodes;
|
ValueList m_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
@@ -92,6 +95,7 @@ class List final : public Collection {
|
|||||||
public:
|
public:
|
||||||
List() = default;
|
List() = default;
|
||||||
List(const std::list<ValuePtr>& nodes);
|
List(const std::list<ValuePtr>& nodes);
|
||||||
|
List(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
List(std::shared_ptr<Ts>... nodes)
|
List(std::shared_ptr<Ts>... nodes)
|
||||||
@@ -112,6 +116,7 @@ class Vector final : public Collection {
|
|||||||
public:
|
public:
|
||||||
Vector() = default;
|
Vector() = default;
|
||||||
Vector(const std::list<ValuePtr>& nodes);
|
Vector(const std::list<ValuePtr>& nodes);
|
||||||
|
Vector(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
Vector(std::shared_ptr<Ts>... nodes)
|
Vector(std::shared_ptr<Ts>... nodes)
|
||||||
|
|||||||
+9
-16
@@ -79,10 +79,9 @@ ValuePtr Eval::evalImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special forms
|
// Special forms
|
||||||
auto nodes = list->nodes();
|
if (is<Symbol>(list->front().get())) {
|
||||||
if (is<Symbol>(nodes.front().get())) {
|
auto symbol = std::static_pointer_cast<Symbol>(list->front())->symbol();
|
||||||
auto symbol = std::static_pointer_cast<Symbol>(nodes.front())->symbol();
|
const auto& nodes = list->rest();
|
||||||
nodes.pop_front();
|
|
||||||
if (symbol == "def!") {
|
if (symbol == "def!") {
|
||||||
return evalDef(nodes, env);
|
return evalDef(nodes, env);
|
||||||
}
|
}
|
||||||
@@ -131,16 +130,11 @@ ValuePtr Eval::evalImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Regular list
|
// Regular list
|
||||||
if (is<Lambda>(evaluated_list->nodes().front().get())) {
|
if (is<Lambda>(evaluated_list->front().get())) {
|
||||||
auto evaluated_nodes = evaluated_list->nodes();
|
auto lambda = std::static_pointer_cast<Lambda>(evaluated_list->front());
|
||||||
|
|
||||||
// car
|
|
||||||
auto lambda = std::static_pointer_cast<Lambda>(evaluated_nodes.front());
|
|
||||||
// cdr
|
|
||||||
evaluated_nodes.pop_front();
|
|
||||||
|
|
||||||
m_ast_stack.push(lambda->body());
|
m_ast_stack.push(lambda->body());
|
||||||
m_env_stack.push(Environment::create(lambda, evaluated_nodes));
|
m_env_stack.push(Environment::create(lambda, evaluated_list->rest()));
|
||||||
continue; // TCO
|
continue; // TCO
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,13 +223,12 @@ bool Eval::isMacroCall(ValuePtr ast, EnvironmentPtr env)
|
|||||||
ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env)
|
ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
while (isMacroCall(ast, env)) {
|
while (isMacroCall(ast, env)) {
|
||||||
auto nodes = std::static_pointer_cast<List>(ast)->nodes();
|
auto list = std::static_pointer_cast<List>(ast);
|
||||||
auto value = env->get(std::static_pointer_cast<Symbol>(nodes.front())->symbol());
|
auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol());
|
||||||
auto lambda = std::static_pointer_cast<Lambda>(value);
|
auto lambda = std::static_pointer_cast<Lambda>(value);
|
||||||
nodes.pop_front();
|
|
||||||
|
|
||||||
m_ast_stack.push(lambda->body());
|
m_ast_stack.push(lambda->body());
|
||||||
m_env_stack.push(Environment::create(lambda, nodes));
|
m_env_stack.push(Environment::create(lambda, list->rest()));
|
||||||
ast = evalImpl();
|
ast = evalImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include <memory> // std::shared_ptr
|
#include <memory> // std::shared_ptr
|
||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
@@ -15,6 +16,9 @@ namespace blaze {
|
|||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
typedef std::shared_ptr<Value> ValuePtr;
|
typedef std::shared_ptr<Value> ValuePtr;
|
||||||
|
typedef std::list<ValuePtr> ValueList;
|
||||||
|
typedef ValueList::iterator ValueListIt;
|
||||||
|
typedef ValueList::const_iterator ValueListConstIt;
|
||||||
|
|
||||||
class Environment;
|
class Environment;
|
||||||
typedef std::shared_ptr<Environment> EnvironmentPtr;
|
typedef std::shared_ptr<Environment> EnvironmentPtr;
|
||||||
|
|||||||
+1
-5
@@ -500,12 +500,8 @@ ADD_FUNCTION(
|
|||||||
}
|
}
|
||||||
|
|
||||||
VALUE_CAST(collection, Collection, nodes.front());
|
VALUE_CAST(collection, Collection, nodes.front());
|
||||||
auto collection_nodes = collection->nodes();
|
|
||||||
if (collection_nodes.size() > 0) {
|
|
||||||
collection_nodes.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
return makePtr<List>(collection_nodes);
|
return makePtr<List>(collection->rest());
|
||||||
});
|
});
|
||||||
|
|
||||||
// (apply + 1 2 (list 3 4)) -> (+ 1 2 3 4)
|
// (apply + 1 2 (list 3 4)) -> (+ 1 2 3 4)
|
||||||
|
|||||||
Reference in New Issue
Block a user