Browse Source

AST+Env: Implement stepA

master
Riyyi 1 year ago
parent
commit
f796f9c685
  1. 4
      CMakeLists.txt
  2. 1
      lib
  3. 1
      mal
  4. 62
      src/ast.cpp
  5. 73
      src/ast.h
  6. 177
      src/functions.cpp

4
CMakeLists.txt

@ -119,3 +119,7 @@ add_dependencies(test8 ${PROJECT})
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})
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})

1
lib

@ -0,0 +1 @@
vendor/mal/impls/lib

1
mal

@ -0,0 +1 @@
vendor/mal/impls/mal

62
src/ast.cpp

@ -17,6 +17,18 @@
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)
: 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)
{
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)
: 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)
@ -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)
{
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)
@ -192,12 +231,26 @@ Symbol::Symbol(const std::string& symbol)
// -----------------------------------------
Callable::Callable(ValuePtr meta)
: Value(meta)
{
}
// -----------------------------------------
Function::Function(const std::string& name, FunctionType function)
: m_name(name)
, 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)
@ -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)

73
src/ast.h

@ -24,10 +24,23 @@
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 {
public:
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(); }
template<typename T>
@ -49,8 +62,28 @@ public:
protected:
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>
@ -63,6 +96,7 @@ public:
void add(ValuePtr node);
void addFront(ValuePtr node);
// TODO: rename size -> count
size_t size() const { return m_nodes.size(); }
bool empty() const { return m_nodes.size() == 0; }
@ -75,6 +109,7 @@ protected:
Collection() = default;
Collection(const ValueList& nodes);
Collection(ValueListConstIt begin, ValueListConstIt end);
Collection(const Collection& that, ValuePtr meta);
template<IsValue... Ts>
Collection(std::shared_ptr<Ts>... nodes)
@ -96,6 +131,7 @@ public:
List() = default;
List(const std::list<ValuePtr>& nodes);
List(ValueListConstIt begin, ValueListConstIt end);
List(const List& that, ValuePtr meta);
template<IsValue... Ts>
List(std::shared_ptr<Ts>... nodes)
@ -105,6 +141,8 @@ public:
virtual ~List() = default;
WITH_META(List);
private:
virtual bool isList() const override { return true; }
};
@ -117,6 +155,7 @@ public:
Vector() = default;
Vector(const std::list<ValuePtr>& nodes);
Vector(ValueListConstIt begin, ValueListConstIt end);
Vector(const Vector& that, ValuePtr meta);
template<IsValue... Ts>
Vector(std::shared_ptr<Ts>... nodes)
@ -126,6 +165,8 @@ public:
virtual ~Vector() = default;
WITH_META(Vector);
private:
virtual bool isVector() const override { return true; }
};
@ -139,6 +180,7 @@ public:
HashMap() = default;
HashMap(const Elements& elements);
HashMap(const HashMap& that, ValuePtr meta);
virtual ~HashMap() = default;
void add(const std::string& key, ValuePtr value);
@ -154,6 +196,8 @@ public:
size_t size() const { return m_elements.size(); }
bool empty() const { return m_elements.size() == 0; }
WITH_META(HashMap);
private:
virtual bool isHashMap() const override { return true; }
@ -168,9 +212,13 @@ private:
class String final : public Value {
public:
String(const std::string& data);
String(char character);
virtual ~String() = default;
const std::string& data() const { return m_data; }
bool empty() const { return m_data.empty(); }
WITH_NO_META();
private:
virtual bool isString() const override { return true; }
@ -190,6 +238,8 @@ public:
const std::string& keyword() const { return m_data; }
WITH_NO_META();
private:
const std::string m_data;
};
@ -203,6 +253,8 @@ public:
int64_t number() const { return m_number; }
WITH_NO_META();
private:
virtual bool isNumber() const override { return true; }
@ -227,6 +279,8 @@ public:
State state() const { return m_state; }
WITH_NO_META();
private:
virtual bool isConstant() const override { return true; }
@ -243,6 +297,8 @@ public:
const std::string& symbol() const { return m_symbol; }
WITH_NO_META();
private:
virtual bool isSymbol() const override { return true; }
@ -257,6 +313,7 @@ public:
protected:
Callable() = default;
Callable(ValuePtr meta);
private:
virtual bool isCallable() const override { return true; }
@ -269,11 +326,14 @@ using FunctionType = std::function<ValuePtr(std::list<ValuePtr>)>;
class Function final : public Callable {
public:
Function(const std::string& name, FunctionType function);
Function(const Function& that, ValuePtr meta);
virtual ~Function() = default;
const std::string& name() const { return m_name; }
FunctionType function() const { return m_function; }
WITH_META(Function);
private:
virtual bool isFunction() const override { return true; }
@ -287,6 +347,7 @@ class Lambda final : public Callable {
public:
Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env);
Lambda(std::shared_ptr<Lambda> that, bool is_macro);
Lambda(const Lambda& that, ValuePtr meta);
virtual ~Lambda() = default;
const std::vector<std::string>& bindings() const { return m_bindings; }
@ -294,6 +355,8 @@ public:
EnvironmentPtr env() const { return m_env; }
bool isMacro() const { return m_is_macro; }
WITH_META(Lambda);
private:
virtual bool isLambda() const override { return true; }
@ -314,6 +377,8 @@ public:
ValuePtr reset(ValuePtr value) { return m_value = value; }
ValuePtr deref() const { return m_value; }
WITH_NO_META();
private:
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
template<>
inline bool Value::fastIs<Collection>() const { return isCollection(); }

177
src/functions.cpp

@ -4,6 +4,8 @@
* SPDX-License-Identifier: MIT
*/
#include <chrono> // std::chrono::sytem_clock
#include <cstdint> // int64_t
#include <iterator> // std::advance
#include <memory> // std::static_pointer_cast
#include <string>
@ -616,10 +618,62 @@ ADD_FUNCTION("atom?", IS_TYPE(Atom));
ADD_FUNCTION("keyword?", IS_TYPE(Keyword));
ADD_FUNCTION("list?", IS_TYPE(List));
ADD_FUNCTION("map?", IS_TYPE(HashMap));
ADD_FUNCTION("number?", IS_TYPE(Number));
ADD_FUNCTION("sequential?", IS_TYPE(Collection));
ADD_FUNCTION("string?", IS_TYPE(String));
ADD_FUNCTION("symbol?", IS_TYPE(Symbol));
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) \
@ -790,6 +844,129 @@ ADD_FUNCTION(
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)

Loading…
Cancel
Save