Everywhere: Put ASTNodes into a smart pointer
This commit is contained in:
+4
-10
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <cstdint> // int64_t
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ast.h"
|
||||
@@ -13,21 +14,14 @@
|
||||
|
||||
namespace blaze {
|
||||
|
||||
Collection::~Collection()
|
||||
{
|
||||
for (auto node : m_nodes) {
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
void Collection::addNode(ASTNode* node)
|
||||
void Collection::addNode(ASTNodePtr node)
|
||||
{
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
void HashMap::addElement(const std::string& key, ASTNode* value)
|
||||
void HashMap::addElement(const std::string& key, ASTNodePtr value)
|
||||
{
|
||||
m_elements.emplace(key, value);
|
||||
}
|
||||
@@ -78,7 +72,7 @@ Function::Function(Lambda lambda)
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
void Formatter<blaze::ASTNode*>::format(Builder& builder, blaze::ASTNode* value) const
|
||||
void Formatter<blaze::ASTNodePtr>::format(Builder& builder, blaze::ASTNodePtr value) const
|
||||
{
|
||||
blaze::Printer printer;
|
||||
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <cstdint> // int64_t
|
||||
#include <functional> // std::function
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -19,6 +20,9 @@
|
||||
|
||||
namespace blaze {
|
||||
|
||||
class ASTNode;
|
||||
typedef std::shared_ptr<ASTNode> ASTNodePtr;
|
||||
|
||||
class ASTNode {
|
||||
public:
|
||||
virtual ~ASTNode() = default;
|
||||
@@ -47,13 +51,13 @@ protected:
|
||||
|
||||
class Collection : public ASTNode {
|
||||
public:
|
||||
virtual ~Collection() override;
|
||||
virtual ~Collection() = default;
|
||||
|
||||
virtual bool isCollection() const override { return true; }
|
||||
|
||||
void addNode(ASTNode* node);
|
||||
void addNode(ASTNodePtr node);
|
||||
|
||||
const std::vector<ASTNode*>& nodes() const { return m_nodes; }
|
||||
const std::vector<ASTNodePtr>& nodes() const { return m_nodes; }
|
||||
size_t size() const { return m_nodes.size(); }
|
||||
bool empty() const { return m_nodes.size() == 0; }
|
||||
|
||||
@@ -61,7 +65,7 @@ protected:
|
||||
Collection() {}
|
||||
|
||||
private:
|
||||
std::vector<ASTNode*> m_nodes;
|
||||
std::vector<ASTNodePtr> m_nodes;
|
||||
};
|
||||
|
||||
// -----------------------------------------
|
||||
@@ -98,14 +102,14 @@ public:
|
||||
|
||||
virtual bool isHashMap() const override { return true; }
|
||||
|
||||
void addElement(const std::string& key, ASTNode* value);
|
||||
void addElement(const std::string& key, ASTNodePtr value);
|
||||
|
||||
const std::unordered_map<std::string, ASTNode*>& elements() const { return m_elements; }
|
||||
const std::unordered_map<std::string, ASTNodePtr>& elements() const { return m_elements; }
|
||||
size_t size() const { return m_elements.size(); }
|
||||
bool empty() const { return m_elements.size() == 0; }
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, ASTNode*> m_elements;
|
||||
std::unordered_map<std::string, ASTNodePtr> m_elements;
|
||||
};
|
||||
|
||||
// -----------------------------------------
|
||||
@@ -113,7 +117,7 @@ private:
|
||||
// "string"
|
||||
class String final : public ASTNode {
|
||||
public:
|
||||
String(const std::string& data);
|
||||
explicit String(const std::string& data);
|
||||
virtual ~String() = default;
|
||||
|
||||
virtual bool isString() const override { return true; }
|
||||
@@ -129,7 +133,7 @@ private:
|
||||
// :keyword
|
||||
class Keyword final : public ASTNode {
|
||||
public:
|
||||
Keyword(const std::string& data);
|
||||
explicit Keyword(const std::string& data);
|
||||
virtual ~Keyword() = default;
|
||||
|
||||
virtual bool isKeyword() const override { return true; }
|
||||
@@ -144,7 +148,7 @@ private:
|
||||
// 123
|
||||
class Number final : public ASTNode {
|
||||
public:
|
||||
Number(int64_t number);
|
||||
explicit Number(int64_t number);
|
||||
virtual ~Number() = default;
|
||||
|
||||
virtual bool isNumber() const override { return true; }
|
||||
@@ -160,7 +164,7 @@ private:
|
||||
// Symbols
|
||||
class Symbol final : public ASTNode {
|
||||
public:
|
||||
Symbol(const std::string& symbol);
|
||||
explicit Symbol(const std::string& symbol);
|
||||
virtual ~Symbol() = default;
|
||||
|
||||
virtual bool isSymbol() const override { return true; }
|
||||
@@ -176,7 +180,7 @@ private:
|
||||
// true, false, nil
|
||||
class Value final : public ASTNode {
|
||||
public:
|
||||
Value(const std::string& value);
|
||||
explicit Value(const std::string& value);
|
||||
virtual ~Value() = default;
|
||||
|
||||
virtual bool isValue() const override { return true; }
|
||||
@@ -189,11 +193,11 @@ private:
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
using Lambda = std::function<ASTNode*(std::span<ASTNode*>)>;
|
||||
using Lambda = std::function<ASTNodePtr(std::span<ASTNodePtr>)>;
|
||||
|
||||
class Function final : public ASTNode {
|
||||
public:
|
||||
Function(Lambda lambda);
|
||||
explicit Function(Lambda lambda);
|
||||
virtual ~Function() = default;
|
||||
|
||||
virtual bool isFunction() const override { return true; }
|
||||
@@ -206,6 +210,14 @@ 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 ASTNode::fastIs<Collection>() const { return isCollection(); }
|
||||
@@ -243,6 +255,6 @@ inline bool ASTNode::fastIs<Function>() const { return isFunction(); }
|
||||
// -----------------------------------------
|
||||
|
||||
template<>
|
||||
struct ruc::format::Formatter<blaze::ASTNode*> : public Formatter<std::string> {
|
||||
void format(Builder& builder, blaze::ASTNode* value) const;
|
||||
struct ruc::format::Formatter<blaze::ASTNodePtr> : public Formatter<std::string> {
|
||||
void format(Builder& builder, blaze::ASTNodePtr value) const;
|
||||
};
|
||||
|
||||
+26
-25
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <cstdint> // int64_t
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
Environment() = default;
|
||||
virtual ~Environment() = default;
|
||||
|
||||
ASTNode* lookup(const std::string& symbol)
|
||||
ASTNodePtr lookup(const std::string& symbol)
|
||||
{
|
||||
m_current_key = symbol;
|
||||
return m_values.find(symbol) != m_values.end() ? m_values[symbol] : nullptr;
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
|
||||
protected:
|
||||
std::string m_current_key;
|
||||
std::unordered_map<std::string, ASTNode*> m_values;
|
||||
std::unordered_map<std::string, ASTNodePtr> m_values;
|
||||
};
|
||||
|
||||
class GlobalEnvironment final : public Environment {
|
||||
@@ -44,62 +45,62 @@ public:
|
||||
{
|
||||
// TODO: Add more native functions
|
||||
// TODO: Move the functions to their own file
|
||||
auto add = [](std::span<ASTNode*> nodes) -> ASTNode* {
|
||||
auto add = [](std::span<ASTNodePtr> nodes) -> ASTNodePtr {
|
||||
int64_t result = 0;
|
||||
|
||||
for (auto node : nodes) {
|
||||
if (!is<Number>(node)) {
|
||||
if (!is<Number>(node.get())) {
|
||||
Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result += static_cast<Number*>(node)->number();
|
||||
result += static_pointer_cast<Number>(node)->number();
|
||||
}
|
||||
|
||||
return new Number(result);
|
||||
return makePtr<Number>(result);
|
||||
};
|
||||
|
||||
auto sub = [](std::span<ASTNode*> nodes) -> ASTNode* {
|
||||
auto sub = [](std::span<ASTNodePtr> nodes) -> ASTNodePtr {
|
||||
int64_t result = 0;
|
||||
|
||||
if (nodes.size() == 0) {
|
||||
return new Number(0);
|
||||
return makePtr<Number>(0);
|
||||
}
|
||||
|
||||
for (auto node : nodes) {
|
||||
if (!is<Number>(node)) {
|
||||
if (!is<Number>(node.get())) {
|
||||
Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Start with the first number
|
||||
result += static_cast<Number*>(nodes[0])->number();
|
||||
result += static_pointer_cast<Number>(nodes[0])->number();
|
||||
|
||||
// Skip the first node
|
||||
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) {
|
||||
result -= static_cast<Number*>(*it)->number();
|
||||
result -= static_pointer_cast<Number>(*it)->number();
|
||||
}
|
||||
|
||||
return new Number(result);
|
||||
return makePtr<Number>(result);
|
||||
};
|
||||
|
||||
auto mul = [](std::span<ASTNode*> nodes) -> ASTNode* {
|
||||
auto mul = [](std::span<ASTNodePtr> nodes) -> ASTNodePtr {
|
||||
int64_t result = 1;
|
||||
|
||||
for (auto node : nodes) {
|
||||
if (!is<Number>(node)) {
|
||||
if (!is<Number>(node.get())) {
|
||||
Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result *= static_cast<Number*>(node)->number();
|
||||
result *= static_pointer_cast<Number>(node)->number();
|
||||
}
|
||||
|
||||
return new Number(result);
|
||||
return makePtr<Number>(result);
|
||||
};
|
||||
|
||||
auto div = [this](std::span<ASTNode*> nodes) -> ASTNode* {
|
||||
auto div = [this](std::span<ASTNodePtr> nodes) -> ASTNodePtr {
|
||||
double result = 0;
|
||||
|
||||
if (nodes.size() == 0) {
|
||||
@@ -108,27 +109,27 @@ public:
|
||||
}
|
||||
|
||||
for (auto node : nodes) {
|
||||
if (!is<Number>(node)) {
|
||||
if (!is<Number>(node.get())) {
|
||||
Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Start with the first number
|
||||
result += static_cast<Number*>(nodes[0])->number();
|
||||
result += static_pointer_cast<Number>(nodes[0])->number();
|
||||
|
||||
// Skip the first node
|
||||
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) {
|
||||
result /= static_cast<Number*>(*it)->number();
|
||||
result /= static_pointer_cast<Number>(*it)->number();
|
||||
}
|
||||
|
||||
return new Number((int64_t)result);
|
||||
return makePtr<Number>((int64_t)result);
|
||||
};
|
||||
|
||||
m_values.emplace("+", new Function(add));
|
||||
m_values.emplace("-", new Function(sub));
|
||||
m_values.emplace("*", new Function(mul));
|
||||
m_values.emplace("/", new Function(div));
|
||||
m_values.emplace("+", makePtr<Function>(add));
|
||||
m_values.emplace("-", makePtr<Function>(sub));
|
||||
m_values.emplace("*", makePtr<Function>(mul));
|
||||
m_values.emplace("/", makePtr<Function>(div));
|
||||
}
|
||||
virtual ~GlobalEnvironment() = default;
|
||||
};
|
||||
|
||||
+29
-22
@@ -14,7 +14,7 @@
|
||||
|
||||
namespace blaze {
|
||||
|
||||
Eval::Eval(ASTNode* ast, Environment* env)
|
||||
Eval::Eval(ASTNodePtr ast, Environment* env)
|
||||
: m_ast(ast)
|
||||
, m_env(env)
|
||||
{
|
||||
@@ -25,46 +25,53 @@ void Eval::eval()
|
||||
m_ast = evalImpl(m_ast, m_env);
|
||||
}
|
||||
|
||||
ASTNode* Eval::evalImpl(ASTNode* ast, Environment* env)
|
||||
ASTNodePtr Eval::evalImpl(ASTNodePtr ast, Environment* env)
|
||||
{
|
||||
if (!is<List>(ast)) {
|
||||
if (!is<List>(ast.get())) {
|
||||
return evalAst(ast, env);
|
||||
}
|
||||
if (static_cast<List*>(ast)->empty()) {
|
||||
if (static_cast<List*>(ast.get())->empty()) {
|
||||
return ast;
|
||||
}
|
||||
|
||||
return apply(static_cast<List*>(evalAst(ast, env)));
|
||||
return apply(static_pointer_cast<List>(evalAst(ast, env)));
|
||||
}
|
||||
|
||||
ASTNode* Eval::evalAst(ASTNode* ast, Environment* env)
|
||||
ASTNodePtr Eval::evalAst(ASTNodePtr ast, Environment* env)
|
||||
{
|
||||
if (is<Symbol>(ast)) {
|
||||
auto result = env->lookup(static_cast<Symbol*>(ast)->symbol());
|
||||
ASTNode* ast_raw_ptr = ast.get();
|
||||
if (is<Symbol>(ast_raw_ptr)) {
|
||||
auto result = env->lookup(static_pointer_cast<Symbol>(ast)->symbol());
|
||||
if (!result) {
|
||||
Error::the().addError(format("symbol's function definition is void: {}", ast));
|
||||
// TODO: Maybe add backlink to parent nodes?
|
||||
if (is<List>(m_ast)) {
|
||||
Error::the().addError(format("symbol's function definition is void: {}", ast_raw_ptr));
|
||||
}
|
||||
else {
|
||||
Error::the().addError(format("symbol's value as variable is void: {}", ast_raw_ptr));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (is<List>(ast)) {
|
||||
auto result = new List();
|
||||
auto nodes = static_cast<List*>(ast)->nodes();
|
||||
else if (is<List>(ast_raw_ptr)) {
|
||||
auto result = makePtr<List>();
|
||||
auto nodes = static_pointer_cast<List>(ast)->nodes();
|
||||
for (auto node : nodes) {
|
||||
result->addNode(evalImpl(node, env));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (is<Vector>(ast)) {
|
||||
auto result = new Vector();
|
||||
auto nodes = static_cast<Vector*>(ast)->nodes();
|
||||
else if (is<Vector>(ast_raw_ptr)) {
|
||||
auto result = makePtr<Vector>();
|
||||
auto nodes = static_pointer_cast<Vector>(ast)->nodes();
|
||||
for (auto node : nodes) {
|
||||
result->addNode(evalImpl(node, env));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (is<HashMap>(ast)) {
|
||||
auto result = new HashMap();
|
||||
auto elements = static_cast<HashMap*>(ast)->elements();
|
||||
else if (is<HashMap>(ast_raw_ptr)) {
|
||||
auto result = makePtr<HashMap>();
|
||||
auto elements = static_pointer_cast<HashMap>(ast)->elements();
|
||||
for (auto& element : elements) {
|
||||
result->addElement(element.first, evalImpl(element.second, env));
|
||||
}
|
||||
@@ -74,19 +81,19 @@ ASTNode* Eval::evalAst(ASTNode* ast, Environment* env)
|
||||
return ast;
|
||||
}
|
||||
|
||||
ASTNode* Eval::apply(List* evaluated_list)
|
||||
ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
|
||||
{
|
||||
auto nodes = evaluated_list->nodes();
|
||||
|
||||
if (!is<Function>(nodes[0])) {
|
||||
if (!is<Function>(nodes[0].get())) {
|
||||
Error::the().addError(format("invalid function: {}", nodes[0]));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// car
|
||||
auto lambda = static_cast<Function*>(nodes[0])->lambda();
|
||||
auto lambda = static_pointer_cast<Function>(nodes[0])->lambda();
|
||||
// cdr
|
||||
std::span<ASTNode*> span { nodes.data() + 1, nodes.size() - 1 };
|
||||
std::span<ASTNodePtr> span { nodes.data() + 1, nodes.size() - 1 };
|
||||
|
||||
return lambda(span);
|
||||
}
|
||||
|
||||
+6
-6
@@ -13,19 +13,19 @@ namespace blaze {
|
||||
|
||||
class Eval {
|
||||
public:
|
||||
Eval(ASTNode* ast, Environment* env);
|
||||
Eval(ASTNodePtr ast, Environment* env);
|
||||
virtual ~Eval() = default;
|
||||
|
||||
void eval();
|
||||
|
||||
ASTNode* ast() const { return m_ast; }
|
||||
ASTNodePtr ast() const { return m_ast; }
|
||||
|
||||
private:
|
||||
ASTNode* evalImpl(ASTNode* ast, Environment* env);
|
||||
ASTNode* evalAst(ASTNode* ast, Environment* env);
|
||||
ASTNode* apply(List* evaluated_list);
|
||||
ASTNodePtr evalImpl(ASTNodePtr ast, Environment* env);
|
||||
ASTNodePtr evalAst(ASTNodePtr ast, Environment* env);
|
||||
ASTNodePtr apply(std::shared_ptr<List> evaluated_list);
|
||||
|
||||
ASTNode* m_ast { nullptr };
|
||||
ASTNodePtr m_ast { nullptr };
|
||||
Environment* m_env { nullptr };
|
||||
};
|
||||
|
||||
|
||||
+18
-17
@@ -27,7 +27,7 @@ Printer::~Printer()
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
std::string Printer::print(ASTNode* node)
|
||||
std::string Printer::print(ASTNodePtr node)
|
||||
{
|
||||
if (Error::the().hasAnyError()) {
|
||||
init();
|
||||
@@ -38,7 +38,7 @@ std::string Printer::print(ASTNode* node)
|
||||
return printNoErrorCheck(node);
|
||||
}
|
||||
|
||||
std::string Printer::printNoErrorCheck(ASTNode* node)
|
||||
std::string Printer::printNoErrorCheck(ASTNodePtr node)
|
||||
{
|
||||
init();
|
||||
|
||||
@@ -60,7 +60,7 @@ void Printer::init()
|
||||
m_print = "";
|
||||
}
|
||||
|
||||
void Printer::printImpl(ASTNode* node)
|
||||
void Printer::printImpl(ASTNodePtr node)
|
||||
{
|
||||
auto printSpacing = [this]() -> void {
|
||||
if (!m_first_node && !m_previous_node_is_list) {
|
||||
@@ -68,36 +68,37 @@ void Printer::printImpl(ASTNode* node)
|
||||
}
|
||||
};
|
||||
|
||||
if (is<List>(node)) {
|
||||
ASTNode* node_raw_ptr = node.get();
|
||||
if (is<List>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += '(';
|
||||
m_first_node = false;
|
||||
m_previous_node_is_list = true;
|
||||
auto nodes = static_cast<List*>(node)->nodes();
|
||||
auto nodes = static_pointer_cast<List>(node)->nodes();
|
||||
for (size_t i = 0; i < nodes.size(); ++i) {
|
||||
printImpl(nodes[i]);
|
||||
m_previous_node_is_list = false;
|
||||
}
|
||||
m_print += ')';
|
||||
}
|
||||
else if (is<Vector>(node)) {
|
||||
else if (is<Vector>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += '[';
|
||||
m_first_node = false;
|
||||
m_previous_node_is_list = true;
|
||||
auto nodes = static_cast<Vector*>(node)->nodes();
|
||||
auto nodes = static_pointer_cast<Vector>(node)->nodes();
|
||||
for (size_t i = 0; i < nodes.size(); ++i) {
|
||||
printImpl(nodes[i]);
|
||||
m_previous_node_is_list = false;
|
||||
}
|
||||
m_print += ']';
|
||||
}
|
||||
else if (is<HashMap>(node)) {
|
||||
else if (is<HashMap>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += "{";
|
||||
m_first_node = false;
|
||||
m_previous_node_is_list = true;
|
||||
auto elements = static_cast<HashMap*>(node)->elements();
|
||||
auto elements = static_pointer_cast<HashMap>(node)->elements();
|
||||
for (auto it = elements.begin(); it != elements.end(); ++it) {
|
||||
m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
|
||||
printImpl(it->second);
|
||||
@@ -109,22 +110,22 @@ void Printer::printImpl(ASTNode* node)
|
||||
m_previous_node_is_list = false;
|
||||
m_print += '}';
|
||||
}
|
||||
else if (is<String>(node)) {
|
||||
else if (is<String>(node_raw_ptr)) {
|
||||
// TODO: Implement string readably printing
|
||||
printSpacing();
|
||||
m_print += format("{}", static_cast<String*>(node)->data());
|
||||
m_print += format("{}", static_pointer_cast<String>(node)->data());
|
||||
}
|
||||
else if (is<Keyword>(node)) {
|
||||
else if (is<Keyword>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += format(":{}", static_cast<Keyword*>(node)->keyword().substr(1));
|
||||
m_print += format(":{}", static_pointer_cast<Keyword>(node)->keyword().substr(1));
|
||||
}
|
||||
else if (is<Number>(node)) {
|
||||
else if (is<Number>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += format("{}", static_cast<Number*>(node)->number());
|
||||
m_print += format("{}", static_pointer_cast<Number>(node)->number());
|
||||
}
|
||||
else if (is<Symbol>(node)) {
|
||||
else if (is<Symbol>(node_raw_ptr)) {
|
||||
printSpacing();
|
||||
m_print += format("{}", static_cast<Symbol*>(node)->symbol());
|
||||
m_print += format("{}", static_pointer_cast<Symbol>(node)->symbol());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -17,12 +17,12 @@ public:
|
||||
Printer();
|
||||
virtual ~Printer();
|
||||
|
||||
std::string print(ASTNode* node);
|
||||
std::string printNoErrorCheck(ASTNode* node);
|
||||
std::string print(ASTNodePtr node);
|
||||
std::string printNoErrorCheck(ASTNodePtr node);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void printImpl(ASTNode* node);
|
||||
void printImpl(ASTNodePtr node);
|
||||
void printError();
|
||||
|
||||
bool m_first_node { true };
|
||||
|
||||
+56
-49
@@ -7,6 +7,7 @@
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint64_t
|
||||
#include <cstdlib> // std::strtoll
|
||||
#include <memory> // makePtr, std::shared_ptr
|
||||
#include <utility> // std::move
|
||||
|
||||
#include "error.h"
|
||||
@@ -55,7 +56,7 @@ void Reader::read()
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode* Reader::readImpl()
|
||||
ASTNodePtr Reader::readImpl()
|
||||
{
|
||||
if (m_tokens.size() == 0) {
|
||||
return nullptr;
|
||||
@@ -123,7 +124,7 @@ ASTNode* Reader::readImpl()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readSpliceUnquote()
|
||||
ASTNodePtr Reader::readSpliceUnquote()
|
||||
{
|
||||
ignore(); // ~@
|
||||
|
||||
@@ -132,18 +133,18 @@ ASTNode* Reader::readSpliceUnquote()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("splice-unquote"));
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("splice-unquote"));
|
||||
list->addNode(readImpl());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readList()
|
||||
ASTNodePtr Reader::readList()
|
||||
{
|
||||
ignore(); // (
|
||||
|
||||
List* list = new List();
|
||||
auto list = makePtr<List>();
|
||||
while (!isEOF() && peek().type != Token::Type::ParenClose) {
|
||||
list->addNode(readImpl());
|
||||
}
|
||||
@@ -156,11 +157,11 @@ ASTNode* Reader::readList()
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readVector()
|
||||
ASTNodePtr Reader::readVector()
|
||||
{
|
||||
ignore(); // [
|
||||
|
||||
Vector* vector = new Vector();
|
||||
auto vector = makePtr<Vector>();
|
||||
while (!isEOF() && peek().type != Token::Type::BracketClose) {
|
||||
vector->addNode(readImpl());
|
||||
}
|
||||
@@ -172,30 +173,30 @@ ASTNode* Reader::readVector()
|
||||
return vector;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readHashMap()
|
||||
ASTNodePtr Reader::readHashMap()
|
||||
{
|
||||
ignore(); // {
|
||||
|
||||
HashMap* hash_map = new HashMap();
|
||||
auto hash_map = makePtr<HashMap>();
|
||||
while (!isEOF() && peek().type != Token::Type::BraceClose) {
|
||||
ASTNode* key = readImpl();
|
||||
ASTNode* value = readImpl();
|
||||
auto key = readImpl();
|
||||
auto value = readImpl();
|
||||
|
||||
if (!key && !value) {
|
||||
if (key == nullptr && value == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key || !value) {
|
||||
if (key == nullptr || value == nullptr) {
|
||||
Error::the().addError("hash-map requires an even-sized list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!is<String>(key) && !is<Keyword>(key)) {
|
||||
if (!is<String>(key.get()) && !is<Keyword>(key.get())) {
|
||||
Error::the().addError(format("{} is not a string or keyword", key));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string keyString = is<String>(key) ? static_cast<String*>(key)->data() : static_cast<Keyword*>(key)->keyword();
|
||||
std::string keyString = is<String>(key.get()) ? static_pointer_cast<String>(key)->data() : static_pointer_cast<Keyword>(key)->keyword();
|
||||
hash_map->addElement(keyString, value);
|
||||
}
|
||||
|
||||
@@ -206,7 +207,7 @@ ASTNode* Reader::readHashMap()
|
||||
return hash_map;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readQuote()
|
||||
ASTNodePtr Reader::readQuote()
|
||||
{
|
||||
ignore(); // '
|
||||
|
||||
@@ -215,14 +216,14 @@ ASTNode* Reader::readQuote()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("quote"));
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("quote"));
|
||||
list->addNode(readImpl());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readQuasiQuote()
|
||||
ASTNodePtr Reader::readQuasiQuote()
|
||||
{
|
||||
ignore(); // `
|
||||
|
||||
@@ -231,14 +232,14 @@ ASTNode* Reader::readQuasiQuote()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("quasiquote"));
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("quasiquote"));
|
||||
list->addNode(readImpl());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readUnquote()
|
||||
ASTNodePtr Reader::readUnquote()
|
||||
{
|
||||
ignore(); // ~
|
||||
|
||||
@@ -247,14 +248,14 @@ ASTNode* Reader::readUnquote()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("unquote"));
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("unquote"));
|
||||
list->addNode(readImpl());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readWithMeta()
|
||||
ASTNodePtr Reader::readWithMeta()
|
||||
{
|
||||
ignore(); // ^
|
||||
|
||||
@@ -265,17 +266,17 @@ ASTNode* Reader::readWithMeta()
|
||||
}
|
||||
retreat();
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("with-meta"));
|
||||
ASTNode* first = readImpl();
|
||||
ASTNode* second = readImpl();
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("with-meta"));
|
||||
ASTNodePtr first = readImpl();
|
||||
ASTNodePtr second = readImpl();
|
||||
list->addNode(second);
|
||||
list->addNode(first);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readDeref()
|
||||
ASTNodePtr Reader::readDeref()
|
||||
{
|
||||
ignore(); // @
|
||||
|
||||
@@ -284,14 +285,14 @@ ASTNode* Reader::readDeref()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List* list = new List();
|
||||
list->addNode(new Symbol("deref"));
|
||||
auto list = makePtr<List>();
|
||||
list->addNode(makePtr<Symbol>("deref"));
|
||||
list->addNode(readImpl());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
ASTNode* Reader::readString()
|
||||
ASTNodePtr Reader::readString()
|
||||
{
|
||||
std::string symbol = consume().symbol;
|
||||
|
||||
@@ -300,24 +301,24 @@ ASTNode* Reader::readString()
|
||||
Error::the().addError("expected '\"', got EOF");
|
||||
}
|
||||
|
||||
return new String(symbol);
|
||||
return makePtr<String>(symbol);
|
||||
}
|
||||
|
||||
ASTNode* Reader::readKeyword()
|
||||
ASTNodePtr Reader::readKeyword()
|
||||
{
|
||||
return new Keyword(consume().symbol);
|
||||
return makePtr<Keyword>(consume().symbol);
|
||||
}
|
||||
|
||||
ASTNode* Reader::readValue()
|
||||
ASTNodePtr Reader::readValue()
|
||||
{
|
||||
Token token = consume();
|
||||
char* end_ptr = nullptr;
|
||||
int64_t result = std::strtoll(token.symbol.c_str(), &end_ptr, 10);
|
||||
if (end_ptr == token.symbol.c_str() + token.symbol.size()) {
|
||||
return new Number(result);
|
||||
return makePtr<Number>(result);
|
||||
}
|
||||
|
||||
return new Symbol(token.symbol);
|
||||
return makePtr<Symbol>(token.symbol);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
@@ -366,12 +367,13 @@ void Reader::dump()
|
||||
dumpImpl(m_node);
|
||||
}
|
||||
|
||||
void Reader::dumpImpl(ASTNode* node)
|
||||
void Reader::dumpImpl(ASTNodePtr node)
|
||||
{
|
||||
std::string indentation = std::string(m_indentation * 2, ' ');
|
||||
|
||||
if (is<List>(node)) {
|
||||
List* list = static_cast<List*>(node);
|
||||
ASTNode* node_raw_ptr = node.get();
|
||||
if (is<List>(node_raw_ptr)) {
|
||||
List* list = static_cast<List*>(node_raw_ptr);
|
||||
print("{}", indentation);
|
||||
print(fg(ruc::format::TerminalColor::Blue), "ListContainer");
|
||||
print(" <");
|
||||
@@ -384,20 +386,25 @@ void Reader::dumpImpl(ASTNode* node)
|
||||
m_indentation--;
|
||||
return;
|
||||
}
|
||||
else if (is<String>(node)) {
|
||||
else if (is<String>(node_raw_ptr)) {
|
||||
print("{}", indentation);
|
||||
print(fg(ruc::format::TerminalColor::Yellow), "StringNode");
|
||||
print(" <{}>", static_cast<String*>(node)->data());
|
||||
print(" <{}>", static_cast<String*>(node_raw_ptr)->data());
|
||||
}
|
||||
else if (is<Number>(node)) {
|
||||
else if (is<Keyword>(node_raw_ptr)) {
|
||||
print("{}", indentation);
|
||||
print(fg(ruc::format::TerminalColor::Yellow), "KeywordNode");
|
||||
print(" <{}>", static_cast<Keyword*>(node_raw_ptr)->keyword());
|
||||
}
|
||||
else if (is<Number>(node_raw_ptr)) {
|
||||
print("{}", indentation);
|
||||
print(fg(ruc::format::TerminalColor::Yellow), "NumberNode");
|
||||
print(" <{}>", static_cast<Number*>(node)->number());
|
||||
print(" <{}>", static_cast<Number*>(node_raw_ptr)->number());
|
||||
}
|
||||
else if (is<Symbol>(node)) {
|
||||
else if (is<Symbol>(node_raw_ptr)) {
|
||||
print("{}", indentation);
|
||||
print(fg(ruc::format::TerminalColor::Yellow), "SymbolNode");
|
||||
print(" <{}>", static_cast<Symbol*>(node)->symbol());
|
||||
print(" <{}>", static_cast<Symbol*>(node_raw_ptr)->symbol());
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
+17
-16
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <vector>
|
||||
|
||||
#include "ast.h"
|
||||
@@ -24,7 +25,7 @@ public:
|
||||
|
||||
void dump();
|
||||
|
||||
ASTNode* node() { return m_node; }
|
||||
ASTNodePtr node() { return m_node; }
|
||||
|
||||
private:
|
||||
bool isEOF() const;
|
||||
@@ -34,21 +35,21 @@ private:
|
||||
void ignore();
|
||||
void retreat();
|
||||
|
||||
ASTNode* readImpl();
|
||||
ASTNode* readSpliceUnquote(); // ~@
|
||||
ASTNode* readList(); // ()
|
||||
ASTNode* readVector(); // []
|
||||
ASTNode* readHashMap(); // {}
|
||||
ASTNode* readQuote(); // '
|
||||
ASTNode* readQuasiQuote(); // `
|
||||
ASTNode* readUnquote(); // ~
|
||||
ASTNode* readWithMeta(); // ^
|
||||
ASTNode* readDeref(); // @
|
||||
ASTNode* readString(); // "foobar"
|
||||
ASTNode* readKeyword(); // :keyword
|
||||
ASTNode* readValue(); // number, "true", "false", "nil", symbol
|
||||
ASTNodePtr readImpl();
|
||||
ASTNodePtr readSpliceUnquote(); // ~@
|
||||
ASTNodePtr readList(); // ()
|
||||
ASTNodePtr readVector(); // []
|
||||
ASTNodePtr readHashMap(); // {}
|
||||
ASTNodePtr readQuote(); // '
|
||||
ASTNodePtr readQuasiQuote(); // `
|
||||
ASTNodePtr readUnquote(); // ~
|
||||
ASTNodePtr readWithMeta(); // ^
|
||||
ASTNodePtr readDeref(); // @
|
||||
ASTNodePtr readString(); // "foobar"
|
||||
ASTNodePtr readKeyword(); // :keyword
|
||||
ASTNodePtr readValue(); // number, "true", "false", "nil", symbol
|
||||
|
||||
void dumpImpl(ASTNode* node);
|
||||
void dumpImpl(ASTNodePtr node);
|
||||
|
||||
size_t m_index { 0 };
|
||||
size_t m_indentation { 0 };
|
||||
@@ -58,7 +59,7 @@ private:
|
||||
bool m_invalid_syntax { false };
|
||||
bool m_is_unbalanced { false };
|
||||
|
||||
ASTNode* m_node { nullptr };
|
||||
ASTNodePtr m_node { nullptr };
|
||||
};
|
||||
|
||||
} // namespace blaze
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#if 0
|
||||
auto read(std::string_view input) -> blaze::ASTNode*
|
||||
auto read(std::string_view input) -> blaze::ASTNodePtr
|
||||
{
|
||||
blaze::Lexer lexer(input);
|
||||
lexer.tokenize();
|
||||
@@ -32,15 +32,15 @@ auto read(std::string_view input) -> blaze::ASTNode*
|
||||
return reader.node();
|
||||
}
|
||||
|
||||
auto eval(blaze::ASTNode* ast) -> blaze::ASTNode*
|
||||
auto eval(blaze::ASTNodePtr ast) -> blaze::ASTNodePtr
|
||||
{
|
||||
return ast;
|
||||
}
|
||||
|
||||
auto print(blaze::ASTNode* exp) -> void
|
||||
auto print(blaze::ASTNodePtr exp) -> std::string
|
||||
{
|
||||
blaze::Printer printer(exp);
|
||||
printer.dump();
|
||||
blaze::Printer printer;
|
||||
return printer.print(exp);
|
||||
}
|
||||
|
||||
auto rep(std::string_view input) -> void
|
||||
@@ -48,7 +48,7 @@ auto rep(std::string_view input) -> void
|
||||
blaze::Error::the().clearErrors();
|
||||
blaze::Error::the().setInput(input);
|
||||
|
||||
print(eval(read(input)));
|
||||
print("{}\n", print(eval(read(input))).c_str());
|
||||
}
|
||||
|
||||
static auto cleanup(int signal) -> void
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#if 1
|
||||
auto read(std::string_view input) -> blaze::ASTNode*
|
||||
auto read(std::string_view input) -> blaze::ASTNodePtr
|
||||
{
|
||||
blaze::Lexer lexer(input);
|
||||
lexer.tokenize();
|
||||
@@ -33,7 +33,7 @@ auto read(std::string_view input) -> blaze::ASTNode*
|
||||
return reader.node();
|
||||
}
|
||||
|
||||
auto eval(blaze::ASTNode* ast) -> blaze::ASTNode*
|
||||
auto eval(blaze::ASTNodePtr ast) -> blaze::ASTNodePtr
|
||||
{
|
||||
blaze::GlobalEnvironment env;
|
||||
blaze::Eval eval(ast, &env);
|
||||
@@ -42,7 +42,7 @@ auto eval(blaze::ASTNode* ast) -> blaze::ASTNode*
|
||||
return eval.ast();
|
||||
}
|
||||
|
||||
auto print(blaze::ASTNode* exp) -> std::string
|
||||
auto print(blaze::ASTNodePtr exp) -> std::string
|
||||
{
|
||||
blaze::Printer printer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user