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)
|
||||
{
|
||||
if (node == nullptr) {
|
||||
@@ -40,6 +45,12 @@ void Collection::addFront(ValuePtr 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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -67,11 +67,14 @@ public:
|
||||
bool empty() const { return m_nodes.size() == 0; }
|
||||
|
||||
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:
|
||||
Collection() = default;
|
||||
Collection(const std::list<ValuePtr>& nodes);
|
||||
Collection(const ValueList& nodes);
|
||||
Collection(ValueListConstIt begin, ValueListConstIt end);
|
||||
|
||||
template<IsValue... Ts>
|
||||
Collection(std::shared_ptr<Ts>... nodes)
|
||||
@@ -82,7 +85,7 @@ protected:
|
||||
private:
|
||||
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:
|
||||
List() = default;
|
||||
List(const std::list<ValuePtr>& nodes);
|
||||
List(ValueListConstIt begin, ValueListConstIt end);
|
||||
|
||||
template<IsValue... Ts>
|
||||
List(std::shared_ptr<Ts>... nodes)
|
||||
@@ -112,6 +116,7 @@ class Vector final : public Collection {
|
||||
public:
|
||||
Vector() = default;
|
||||
Vector(const std::list<ValuePtr>& nodes);
|
||||
Vector(ValueListConstIt begin, ValueListConstIt end);
|
||||
|
||||
template<IsValue... Ts>
|
||||
Vector(std::shared_ptr<Ts>... nodes)
|
||||
|
||||
+9
-16
@@ -79,10 +79,9 @@ ValuePtr Eval::evalImpl()
|
||||
}
|
||||
|
||||
// Special forms
|
||||
auto nodes = list->nodes();
|
||||
if (is<Symbol>(nodes.front().get())) {
|
||||
auto symbol = std::static_pointer_cast<Symbol>(nodes.front())->symbol();
|
||||
nodes.pop_front();
|
||||
if (is<Symbol>(list->front().get())) {
|
||||
auto symbol = std::static_pointer_cast<Symbol>(list->front())->symbol();
|
||||
const auto& nodes = list->rest();
|
||||
if (symbol == "def!") {
|
||||
return evalDef(nodes, env);
|
||||
}
|
||||
@@ -131,16 +130,11 @@ ValuePtr Eval::evalImpl()
|
||||
}
|
||||
|
||||
// Regular list
|
||||
if (is<Lambda>(evaluated_list->nodes().front().get())) {
|
||||
auto evaluated_nodes = evaluated_list->nodes();
|
||||
|
||||
// car
|
||||
auto lambda = std::static_pointer_cast<Lambda>(evaluated_nodes.front());
|
||||
// cdr
|
||||
evaluated_nodes.pop_front();
|
||||
if (is<Lambda>(evaluated_list->front().get())) {
|
||||
auto lambda = std::static_pointer_cast<Lambda>(evaluated_list->front());
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -229,13 +223,12 @@ bool Eval::isMacroCall(ValuePtr ast, EnvironmentPtr env)
|
||||
ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env)
|
||||
{
|
||||
while (isMacroCall(ast, env)) {
|
||||
auto nodes = std::static_pointer_cast<List>(ast)->nodes();
|
||||
auto value = env->get(std::static_pointer_cast<Symbol>(nodes.front())->symbol());
|
||||
auto list = std::static_pointer_cast<List>(ast);
|
||||
auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol());
|
||||
auto lambda = std::static_pointer_cast<Lambda>(value);
|
||||
nodes.pop_front();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory> // std::shared_ptr
|
||||
|
||||
namespace blaze {
|
||||
@@ -15,6 +16,9 @@ namespace blaze {
|
||||
|
||||
class Value;
|
||||
typedef std::shared_ptr<Value> ValuePtr;
|
||||
typedef std::list<ValuePtr> ValueList;
|
||||
typedef ValueList::iterator ValueListIt;
|
||||
typedef ValueList::const_iterator ValueListConstIt;
|
||||
|
||||
class Environment;
|
||||
typedef std::shared_ptr<Environment> EnvironmentPtr;
|
||||
|
||||
+1
-5
@@ -500,12 +500,8 @@ ADD_FUNCTION(
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user