AST+Env: Implement stepA
This commit is contained in:
@@ -119,3 +119,7 @@ add_dependencies(test8 ${PROJECT})
|
|||||||
add_custom_target(test9
|
add_custom_target(test9
|
||||||
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/step9_try.mal -- ./${PROJECT})
|
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/step9_try.mal -- ./${PROJECT})
|
||||||
add_dependencies(test9 ${PROJECT})
|
add_dependencies(test9 ${PROJECT})
|
||||||
|
|
||||||
|
add_custom_target(testA
|
||||||
|
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/stepA_mal.mal -- ./${PROJECT})
|
||||||
|
add_dependencies(testA ${PROJECT})
|
||||||
|
|||||||
+62
@@ -17,6 +17,18 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
|
ValuePtr Value::withMeta(ValuePtr meta) const
|
||||||
|
{
|
||||||
|
return withMetaImpl(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValuePtr Value::meta() const
|
||||||
|
{
|
||||||
|
return (m_meta == nullptr) ? makePtr<Constant>() : m_meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
Collection::Collection(const std::list<ValuePtr>& nodes)
|
Collection::Collection(const std::list<ValuePtr>& nodes)
|
||||||
: m_nodes(nodes)
|
: m_nodes(nodes)
|
||||||
{
|
{
|
||||||
@@ -27,6 +39,12 @@ Collection::Collection(ValueListConstIt begin, ValueListConstIt end)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection::Collection(const Collection& that, ValuePtr meta)
|
||||||
|
: Value(meta)
|
||||||
|
, m_nodes(that.m_nodes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Collection::add(ValuePtr node)
|
void Collection::add(ValuePtr node)
|
||||||
{
|
{
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
@@ -53,6 +71,11 @@ ValueList Collection::rest() const
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
|
List::List(const List& that, ValuePtr meta)
|
||||||
|
: Collection(that, meta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
List::List(const std::list<ValuePtr>& nodes)
|
List::List(const std::list<ValuePtr>& nodes)
|
||||||
: Collection(nodes)
|
: Collection(nodes)
|
||||||
{
|
{
|
||||||
@@ -75,6 +98,11 @@ Vector::Vector(ValueListConstIt begin, ValueListConstIt end)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector::Vector(const Vector& that, ValuePtr meta)
|
||||||
|
: Collection(that, meta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
HashMap::HashMap(const Elements& elements)
|
HashMap::HashMap(const Elements& elements)
|
||||||
@@ -82,6 +110,12 @@ HashMap::HashMap(const Elements& elements)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashMap::HashMap(const HashMap& that, ValuePtr meta)
|
||||||
|
: Value(meta)
|
||||||
|
, m_elements(that.m_elements)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void HashMap::add(const std::string& key, ValuePtr value)
|
void HashMap::add(const std::string& key, ValuePtr value)
|
||||||
{
|
{
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
@@ -157,6 +191,11 @@ String::String(const std::string& data)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String::String(char character)
|
||||||
|
: m_data(std::string(1, character))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Keyword::Keyword(const std::string& data)
|
Keyword::Keyword(const std::string& data)
|
||||||
@@ -192,12 +231,26 @@ Symbol::Symbol(const std::string& symbol)
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
|
Callable::Callable(ValuePtr meta)
|
||||||
|
: Value(meta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
Function::Function(const std::string& name, FunctionType function)
|
Function::Function(const std::string& name, FunctionType function)
|
||||||
: m_name(name)
|
: m_name(name)
|
||||||
, m_function(function)
|
, m_function(function)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Function::Function(const Function& that, ValuePtr meta)
|
||||||
|
: Callable(meta)
|
||||||
|
, m_name(that.m_name)
|
||||||
|
, m_function(that.m_function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Lambda::Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env)
|
Lambda::Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env)
|
||||||
@@ -215,6 +268,15 @@ Lambda::Lambda(std::shared_ptr<Lambda> that, bool is_macro)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lambda::Lambda(const Lambda& that, ValuePtr meta)
|
||||||
|
: Callable(meta)
|
||||||
|
, m_bindings(that.m_bindings)
|
||||||
|
, m_body(that.m_body)
|
||||||
|
, m_env(that.m_env)
|
||||||
|
, m_is_macro(that.m_is_macro)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Atom::Atom(ValuePtr pointer)
|
Atom::Atom(ValuePtr pointer)
|
||||||
|
|||||||
@@ -24,10 +24,23 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
std::shared_ptr<T> makePtr(Args&&... args)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
virtual ~Value() = default;
|
virtual ~Value() = default;
|
||||||
|
|
||||||
|
virtual ValuePtr withMetaImpl(ValuePtr meta) const = 0;
|
||||||
|
|
||||||
|
ValuePtr withMeta(ValuePtr meta) const;
|
||||||
|
ValuePtr meta() const;
|
||||||
|
|
||||||
std::string className() const { return typeid(*this).name(); }
|
std::string className() const { return typeid(*this).name(); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -49,8 +62,28 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Value() {}
|
Value() {}
|
||||||
|
|
||||||
|
Value(ValuePtr meta)
|
||||||
|
: m_meta(meta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ValuePtr m_meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define WITH_META(Type) \
|
||||||
|
virtual ValuePtr withMetaImpl(ValuePtr meta) const override \
|
||||||
|
{ \
|
||||||
|
return makePtr<Type>(*this, meta); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WITH_NO_META() \
|
||||||
|
virtual ValuePtr withMetaImpl(ValuePtr meta) const override \
|
||||||
|
{ \
|
||||||
|
(void)meta; \
|
||||||
|
return nullptr; \
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -63,6 +96,7 @@ public:
|
|||||||
void add(ValuePtr node);
|
void add(ValuePtr node);
|
||||||
void addFront(ValuePtr node);
|
void addFront(ValuePtr node);
|
||||||
|
|
||||||
|
// TODO: rename size -> count
|
||||||
size_t size() const { return m_nodes.size(); }
|
size_t size() const { return m_nodes.size(); }
|
||||||
bool empty() const { return m_nodes.size() == 0; }
|
bool empty() const { return m_nodes.size() == 0; }
|
||||||
|
|
||||||
@@ -75,6 +109,7 @@ protected:
|
|||||||
Collection() = default;
|
Collection() = default;
|
||||||
Collection(const ValueList& nodes);
|
Collection(const ValueList& nodes);
|
||||||
Collection(ValueListConstIt begin, ValueListConstIt end);
|
Collection(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
Collection(const Collection& that, ValuePtr meta);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
Collection(std::shared_ptr<Ts>... nodes)
|
Collection(std::shared_ptr<Ts>... nodes)
|
||||||
@@ -96,6 +131,7 @@ public:
|
|||||||
List() = default;
|
List() = default;
|
||||||
List(const std::list<ValuePtr>& nodes);
|
List(const std::list<ValuePtr>& nodes);
|
||||||
List(ValueListConstIt begin, ValueListConstIt end);
|
List(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
List(const List& that, ValuePtr meta);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
List(std::shared_ptr<Ts>... nodes)
|
List(std::shared_ptr<Ts>... nodes)
|
||||||
@@ -105,6 +141,8 @@ public:
|
|||||||
|
|
||||||
virtual ~List() = default;
|
virtual ~List() = default;
|
||||||
|
|
||||||
|
WITH_META(List);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isList() const override { return true; }
|
virtual bool isList() const override { return true; }
|
||||||
};
|
};
|
||||||
@@ -117,6 +155,7 @@ public:
|
|||||||
Vector() = default;
|
Vector() = default;
|
||||||
Vector(const std::list<ValuePtr>& nodes);
|
Vector(const std::list<ValuePtr>& nodes);
|
||||||
Vector(ValueListConstIt begin, ValueListConstIt end);
|
Vector(ValueListConstIt begin, ValueListConstIt end);
|
||||||
|
Vector(const Vector& that, ValuePtr meta);
|
||||||
|
|
||||||
template<IsValue... Ts>
|
template<IsValue... Ts>
|
||||||
Vector(std::shared_ptr<Ts>... nodes)
|
Vector(std::shared_ptr<Ts>... nodes)
|
||||||
@@ -126,6 +165,8 @@ public:
|
|||||||
|
|
||||||
virtual ~Vector() = default;
|
virtual ~Vector() = default;
|
||||||
|
|
||||||
|
WITH_META(Vector);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isVector() const override { return true; }
|
virtual bool isVector() const override { return true; }
|
||||||
};
|
};
|
||||||
@@ -139,6 +180,7 @@ public:
|
|||||||
|
|
||||||
HashMap() = default;
|
HashMap() = default;
|
||||||
HashMap(const Elements& elements);
|
HashMap(const Elements& elements);
|
||||||
|
HashMap(const HashMap& that, ValuePtr meta);
|
||||||
virtual ~HashMap() = default;
|
virtual ~HashMap() = default;
|
||||||
|
|
||||||
void add(const std::string& key, ValuePtr value);
|
void add(const std::string& key, ValuePtr value);
|
||||||
@@ -154,6 +196,8 @@ public:
|
|||||||
size_t size() const { return m_elements.size(); }
|
size_t size() const { return m_elements.size(); }
|
||||||
bool empty() const { return m_elements.size() == 0; }
|
bool empty() const { return m_elements.size() == 0; }
|
||||||
|
|
||||||
|
WITH_META(HashMap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isHashMap() const override { return true; }
|
virtual bool isHashMap() const override { return true; }
|
||||||
|
|
||||||
@@ -168,9 +212,13 @@ private:
|
|||||||
class String final : public Value {
|
class String final : public Value {
|
||||||
public:
|
public:
|
||||||
String(const std::string& data);
|
String(const std::string& data);
|
||||||
|
String(char character);
|
||||||
virtual ~String() = default;
|
virtual ~String() = default;
|
||||||
|
|
||||||
const std::string& data() const { return m_data; }
|
const std::string& data() const { return m_data; }
|
||||||
|
bool empty() const { return m_data.empty(); }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isString() const override { return true; }
|
virtual bool isString() const override { return true; }
|
||||||
@@ -190,6 +238,8 @@ public:
|
|||||||
|
|
||||||
const std::string& keyword() const { return m_data; }
|
const std::string& keyword() const { return m_data; }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_data;
|
const std::string m_data;
|
||||||
};
|
};
|
||||||
@@ -203,6 +253,8 @@ public:
|
|||||||
|
|
||||||
int64_t number() const { return m_number; }
|
int64_t number() const { return m_number; }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isNumber() const override { return true; }
|
virtual bool isNumber() const override { return true; }
|
||||||
|
|
||||||
@@ -227,6 +279,8 @@ public:
|
|||||||
|
|
||||||
State state() const { return m_state; }
|
State state() const { return m_state; }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isConstant() const override { return true; }
|
virtual bool isConstant() const override { return true; }
|
||||||
|
|
||||||
@@ -243,6 +297,8 @@ public:
|
|||||||
|
|
||||||
const std::string& symbol() const { return m_symbol; }
|
const std::string& symbol() const { return m_symbol; }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isSymbol() const override { return true; }
|
virtual bool isSymbol() const override { return true; }
|
||||||
|
|
||||||
@@ -257,6 +313,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Callable() = default;
|
Callable() = default;
|
||||||
|
Callable(ValuePtr meta);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isCallable() const override { return true; }
|
virtual bool isCallable() const override { return true; }
|
||||||
@@ -269,11 +326,14 @@ using FunctionType = std::function<ValuePtr(std::list<ValuePtr>)>;
|
|||||||
class Function final : public Callable {
|
class Function final : public Callable {
|
||||||
public:
|
public:
|
||||||
Function(const std::string& name, FunctionType function);
|
Function(const std::string& name, FunctionType function);
|
||||||
|
Function(const Function& that, ValuePtr meta);
|
||||||
virtual ~Function() = default;
|
virtual ~Function() = default;
|
||||||
|
|
||||||
const std::string& name() const { return m_name; }
|
const std::string& name() const { return m_name; }
|
||||||
FunctionType function() const { return m_function; }
|
FunctionType function() const { return m_function; }
|
||||||
|
|
||||||
|
WITH_META(Function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isFunction() const override { return true; }
|
virtual bool isFunction() const override { return true; }
|
||||||
|
|
||||||
@@ -287,6 +347,7 @@ class Lambda final : public Callable {
|
|||||||
public:
|
public:
|
||||||
Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env);
|
Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env);
|
||||||
Lambda(std::shared_ptr<Lambda> that, bool is_macro);
|
Lambda(std::shared_ptr<Lambda> that, bool is_macro);
|
||||||
|
Lambda(const Lambda& that, ValuePtr meta);
|
||||||
virtual ~Lambda() = default;
|
virtual ~Lambda() = default;
|
||||||
|
|
||||||
const std::vector<std::string>& bindings() const { return m_bindings; }
|
const std::vector<std::string>& bindings() const { return m_bindings; }
|
||||||
@@ -294,6 +355,8 @@ public:
|
|||||||
EnvironmentPtr env() const { return m_env; }
|
EnvironmentPtr env() const { return m_env; }
|
||||||
bool isMacro() const { return m_is_macro; }
|
bool isMacro() const { return m_is_macro; }
|
||||||
|
|
||||||
|
WITH_META(Lambda);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isLambda() const override { return true; }
|
virtual bool isLambda() const override { return true; }
|
||||||
|
|
||||||
@@ -314,6 +377,8 @@ public:
|
|||||||
ValuePtr reset(ValuePtr value) { return m_value = value; }
|
ValuePtr reset(ValuePtr value) { return m_value = value; }
|
||||||
ValuePtr deref() const { return m_value; }
|
ValuePtr deref() const { return m_value; }
|
||||||
|
|
||||||
|
WITH_NO_META();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isAtom() const override { return true; }
|
virtual bool isAtom() const override { return true; }
|
||||||
|
|
||||||
@@ -322,14 +387,6 @@ private:
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
std::shared_ptr<T> makePtr(Args&&... args)
|
|
||||||
{
|
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
template<>
|
template<>
|
||||||
inline bool Value::fastIs<Collection>() const { return isCollection(); }
|
inline bool Value::fastIs<Collection>() const { return isCollection(); }
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <chrono> // std::chrono::sytem_clock
|
||||||
|
#include <cstdint> // int64_t
|
||||||
#include <iterator> // std::advance
|
#include <iterator> // std::advance
|
||||||
#include <memory> // std::static_pointer_cast
|
#include <memory> // std::static_pointer_cast
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -616,10 +618,62 @@ ADD_FUNCTION("atom?", IS_TYPE(Atom));
|
|||||||
ADD_FUNCTION("keyword?", IS_TYPE(Keyword));
|
ADD_FUNCTION("keyword?", IS_TYPE(Keyword));
|
||||||
ADD_FUNCTION("list?", IS_TYPE(List));
|
ADD_FUNCTION("list?", IS_TYPE(List));
|
||||||
ADD_FUNCTION("map?", IS_TYPE(HashMap));
|
ADD_FUNCTION("map?", IS_TYPE(HashMap));
|
||||||
|
ADD_FUNCTION("number?", IS_TYPE(Number));
|
||||||
ADD_FUNCTION("sequential?", IS_TYPE(Collection));
|
ADD_FUNCTION("sequential?", IS_TYPE(Collection));
|
||||||
|
ADD_FUNCTION("string?", IS_TYPE(String));
|
||||||
ADD_FUNCTION("symbol?", IS_TYPE(Symbol));
|
ADD_FUNCTION("symbol?", IS_TYPE(Symbol));
|
||||||
ADD_FUNCTION("vector?", IS_TYPE(Vector));
|
ADD_FUNCTION("vector?", IS_TYPE(Vector));
|
||||||
|
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"fn?",
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto node : nodes) {
|
||||||
|
if (!is<Callable>(node.get())) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is<Lambda>(node.get())) {
|
||||||
|
auto lambda = std::static_pointer_cast<Lambda>(node);
|
||||||
|
if (lambda->isMacro()) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePtr<Constant>(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"macro?",
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto node : nodes) {
|
||||||
|
if (!is<Lambda>(node.get())) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto lambda = std::static_pointer_cast<Lambda>(node);
|
||||||
|
if (!lambda->isMacro()) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePtr<Constant>(result);
|
||||||
|
});
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
#define STRING_TO_TYPE(name, type) \
|
#define STRING_TO_TYPE(name, type) \
|
||||||
@@ -790,6 +844,129 @@ ADD_FUNCTION(
|
|||||||
return readline(prompt->data());
|
return readline(prompt->data());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ADD_FUNCTION("time-ms", {
|
||||||
|
CHECK_ARG_COUNT_IS("time-ms", nodes.size(), 0);
|
||||||
|
|
||||||
|
int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
return makePtr<Number>(elapsed);
|
||||||
|
});
|
||||||
|
|
||||||
|
// (meta [1 2 3])
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"meta",
|
||||||
|
{
|
||||||
|
CHECK_ARG_COUNT_IS("meta", nodes.size(), 1);
|
||||||
|
|
||||||
|
auto front = nodes.front();
|
||||||
|
Value* front_raw_ptr = nodes.front().get();
|
||||||
|
|
||||||
|
if (!is<Collection>(front_raw_ptr) && // List / Vector
|
||||||
|
!is<HashMap>(front_raw_ptr) && // HashMap
|
||||||
|
!is<Callable>(front_raw_ptr)) { // Function / Lambda
|
||||||
|
Error::the().add(format("wrong argument type: Collection, HashMap or Callable, {}", front));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return front->meta();
|
||||||
|
});
|
||||||
|
|
||||||
|
// (with-meta [1 2 3] "some metadata")
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"with-meta",
|
||||||
|
{
|
||||||
|
CHECK_ARG_COUNT_IS("with-meta", nodes.size(), 2);
|
||||||
|
|
||||||
|
auto front = nodes.front();
|
||||||
|
Value* front_raw_ptr = nodes.front().get();
|
||||||
|
|
||||||
|
if (!is<Collection>(front_raw_ptr) && // List / Vector
|
||||||
|
!is<HashMap>(front_raw_ptr) && // HashMap
|
||||||
|
!is<Callable>(front_raw_ptr)) { // Function / Lambda
|
||||||
|
Error::the().add(format("wrong argument type: Collection, HashMap or Callable, {}", front));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return front->withMeta(nodes.back());
|
||||||
|
});
|
||||||
|
|
||||||
|
// (conj '(1 2 3) 4 5 6) -> (6 5 4 1 2 3)
|
||||||
|
// (conj [1 2 3] 4 5 6) -> [1 2 3 4 5 6]
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"conj",
|
||||||
|
{
|
||||||
|
CHECK_ARG_COUNT_AT_LEAST("conj", nodes.size(), 1);
|
||||||
|
|
||||||
|
VALUE_CAST(collection, Collection, nodes.front());
|
||||||
|
nodes.pop_front();
|
||||||
|
|
||||||
|
auto collection_nodes = collection->nodes();
|
||||||
|
|
||||||
|
if (is<List>(collection.get())) {
|
||||||
|
nodes.reverse();
|
||||||
|
nodes.splice(nodes.end(), collection_nodes);
|
||||||
|
auto result = makePtr<List>(nodes);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.splice(nodes.begin(), collection_nodes);
|
||||||
|
auto result = makePtr<Vector>(nodes);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
// (seq '(1 2 3)) -> (1 2 3)
|
||||||
|
// (seq [1 2 3]) -> (1 2 3)
|
||||||
|
// (seq "foo") -> ("f" "o" "o")
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"seq",
|
||||||
|
{
|
||||||
|
CHECK_ARG_COUNT_IS("seq", nodes.size(), 1);
|
||||||
|
|
||||||
|
auto front = nodes.front();
|
||||||
|
Value* front_raw_ptr = front.get();
|
||||||
|
|
||||||
|
if (is<Constant>(front_raw_ptr) && std::static_pointer_cast<Constant>(front)->state() == Constant::Nil) {
|
||||||
|
return makePtr<Constant>();
|
||||||
|
}
|
||||||
|
if (is<Collection>(front_raw_ptr)) {
|
||||||
|
auto collection = std::static_pointer_cast<Collection>(front);
|
||||||
|
|
||||||
|
if (collection->empty()) {
|
||||||
|
return makePtr<Constant>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is<List>(front_raw_ptr)) {
|
||||||
|
return front;
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePtr<List>(collection->nodes());
|
||||||
|
}
|
||||||
|
if (is<String>(front_raw_ptr)) {
|
||||||
|
auto string = std::static_pointer_cast<String>(front);
|
||||||
|
|
||||||
|
if (string->empty()) {
|
||||||
|
return makePtr<Constant>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = makePtr<List>();
|
||||||
|
|
||||||
|
const auto& data = string->data();
|
||||||
|
for (const auto& character : data) {
|
||||||
|
result->add(makePtr<String>(character));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error::the().add(format("wrong argument type: Collection or String, {}", front));
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void installFunctions(EnvironmentPtr env)
|
void installFunctions(EnvironmentPtr env)
|
||||||
|
|||||||
Reference in New Issue
Block a user