Browse Source

Everywhere: Put ASTNodes into a smart pointer

master
Riyyi 2 years ago
parent
commit
9bbf238c34
  1. 14
      src/ast.cpp
  2. 44
      src/ast.h
  3. 51
      src/environment.h
  4. 51
      src/eval.cpp
  5. 12
      src/eval.h
  6. 35
      src/printer.cpp
  7. 6
      src/printer.h
  8. 105
      src/reader.cpp
  9. 33
      src/reader.h
  10. 12
      src/step1_read_print.cpp
  11. 6
      src/step2_eval.cpp

14
src/ast.cpp

@ -5,6 +5,7 @@
*/ */
#include <cstdint> // int64_t #include <cstdint> // int64_t
#include <memory>
#include <string> #include <string>
#include "ast.h" #include "ast.h"
@ -13,21 +14,14 @@
namespace blaze { namespace blaze {
Collection::~Collection() void Collection::addNode(ASTNodePtr node)
{
for (auto node : m_nodes) {
delete node;
}
}
void Collection::addNode(ASTNode* node)
{ {
m_nodes.push_back(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); 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; blaze::Printer printer;
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value)); return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));

44
src/ast.h

@ -8,6 +8,7 @@
#include <cstdint> // int64_t #include <cstdint> // int64_t
#include <functional> // std::function #include <functional> // std::function
#include <memory> // std::shared_ptr
#include <span> #include <span>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -19,6 +20,9 @@
namespace blaze { namespace blaze {
class ASTNode;
typedef std::shared_ptr<ASTNode> ASTNodePtr;
class ASTNode { class ASTNode {
public: public:
virtual ~ASTNode() = default; virtual ~ASTNode() = default;
@ -47,13 +51,13 @@ protected:
class Collection : public ASTNode { class Collection : public ASTNode {
public: public:
virtual ~Collection() override; virtual ~Collection() = default;
virtual bool isCollection() const override { return true; } 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(); } size_t size() const { return m_nodes.size(); }
bool empty() const { return m_nodes.size() == 0; } bool empty() const { return m_nodes.size() == 0; }
@ -61,7 +65,7 @@ protected:
Collection() {} Collection() {}
private: private:
std::vector<ASTNode*> m_nodes; std::vector<ASTNodePtr> m_nodes;
}; };
// ----------------------------------------- // -----------------------------------------
@ -98,14 +102,14 @@ public:
virtual bool isHashMap() const override { return true; } 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(); } size_t size() const { return m_elements.size(); }
bool empty() const { return m_elements.size() == 0; } bool empty() const { return m_elements.size() == 0; }
private: private:
std::unordered_map<std::string, ASTNode*> m_elements; std::unordered_map<std::string, ASTNodePtr> m_elements;
}; };
// ----------------------------------------- // -----------------------------------------
@ -113,7 +117,7 @@ private:
// "string" // "string"
class String final : public ASTNode { class String final : public ASTNode {
public: public:
String(const std::string& data); explicit String(const std::string& data);
virtual ~String() = default; virtual ~String() = default;
virtual bool isString() const override { return true; } virtual bool isString() const override { return true; }
@ -129,7 +133,7 @@ private:
// :keyword // :keyword
class Keyword final : public ASTNode { class Keyword final : public ASTNode {
public: public:
Keyword(const std::string& data); explicit Keyword(const std::string& data);
virtual ~Keyword() = default; virtual ~Keyword() = default;
virtual bool isKeyword() const override { return true; } virtual bool isKeyword() const override { return true; }
@ -144,7 +148,7 @@ private:
// 123 // 123
class Number final : public ASTNode { class Number final : public ASTNode {
public: public:
Number(int64_t number); explicit Number(int64_t number);
virtual ~Number() = default; virtual ~Number() = default;
virtual bool isNumber() const override { return true; } virtual bool isNumber() const override { return true; }
@ -160,7 +164,7 @@ private:
// Symbols // Symbols
class Symbol final : public ASTNode { class Symbol final : public ASTNode {
public: public:
Symbol(const std::string& symbol); explicit Symbol(const std::string& symbol);
virtual ~Symbol() = default; virtual ~Symbol() = default;
virtual bool isSymbol() const override { return true; } virtual bool isSymbol() const override { return true; }
@ -176,7 +180,7 @@ private:
// true, false, nil // true, false, nil
class Value final : public ASTNode { class Value final : public ASTNode {
public: public:
Value(const std::string& value); explicit Value(const std::string& value);
virtual ~Value() = default; virtual ~Value() = default;
virtual bool isValue() const override { return true; } 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 { class Function final : public ASTNode {
public: public:
Function(Lambda lambda); explicit Function(Lambda lambda);
virtual ~Function() = default; virtual ~Function() = default;
virtual bool isFunction() const override { return true; } 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 // clang-format off
template<> template<>
inline bool ASTNode::fastIs<Collection>() const { return isCollection(); } inline bool ASTNode::fastIs<Collection>() const { return isCollection(); }
@ -243,6 +255,6 @@ inline bool ASTNode::fastIs<Function>() const { return isFunction(); }
// ----------------------------------------- // -----------------------------------------
template<> template<>
struct ruc::format::Formatter<blaze::ASTNode*> : public Formatter<std::string> { struct ruc::format::Formatter<blaze::ASTNodePtr> : public Formatter<std::string> {
void format(Builder& builder, blaze::ASTNode* value) const; void format(Builder& builder, blaze::ASTNodePtr value) const;
}; };

51
src/environment.h

@ -8,6 +8,7 @@
#include <cstdint> // int64_t #include <cstdint> // int64_t
#include <iostream> #include <iostream>
#include <memory>
#include <span> #include <span>
#include <string_view> #include <string_view>
#include <unordered_map> #include <unordered_map>
@ -27,7 +28,7 @@ public:
Environment() = default; Environment() = default;
virtual ~Environment() = default; virtual ~Environment() = default;
ASTNode* lookup(const std::string& symbol) ASTNodePtr lookup(const std::string& symbol)
{ {
m_current_key = symbol; m_current_key = symbol;
return m_values.find(symbol) != m_values.end() ? m_values[symbol] : nullptr; return m_values.find(symbol) != m_values.end() ? m_values[symbol] : nullptr;
@ -35,7 +36,7 @@ public:
protected: protected:
std::string m_current_key; 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 { class GlobalEnvironment final : public Environment {
@ -44,62 +45,62 @@ public:
{ {
// TODO: Add more native functions // TODO: Add more native functions
// TODO: Move the functions to their own file // 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; int64_t result = 0;
for (auto node : nodes) { 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)); Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
return nullptr; 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; int64_t result = 0;
if (nodes.size() == 0) { if (nodes.size() == 0) {
return new Number(0); return makePtr<Number>(0);
} }
for (auto node : nodes) { 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)); Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
return nullptr; return nullptr;
} }
} }
// Start with the first number // Start with the first number
result += static_cast<Number*>(nodes[0])->number(); result += static_pointer_cast<Number>(nodes[0])->number();
// Skip the first node // Skip the first node
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { 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; int64_t result = 1;
for (auto node : nodes) { 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)); Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
return nullptr; 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; double result = 0;
if (nodes.size() == 0) { if (nodes.size() == 0) {
@ -108,27 +109,27 @@ public:
} }
for (auto node : nodes) { 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)); Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node));
return nullptr; return nullptr;
} }
} }
// Start with the first number // Start with the first number
result += static_cast<Number*>(nodes[0])->number(); result += static_pointer_cast<Number>(nodes[0])->number();
// Skip the first node // Skip the first node
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { 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("+", makePtr<Function>(add));
m_values.emplace("-", new Function(sub)); m_values.emplace("-", makePtr<Function>(sub));
m_values.emplace("*", new Function(mul)); m_values.emplace("*", makePtr<Function>(mul));
m_values.emplace("/", new Function(div)); m_values.emplace("/", makePtr<Function>(div));
} }
virtual ~GlobalEnvironment() = default; virtual ~GlobalEnvironment() = default;
}; };

51
src/eval.cpp

@ -14,7 +14,7 @@
namespace blaze { namespace blaze {
Eval::Eval(ASTNode* ast, Environment* env) Eval::Eval(ASTNodePtr ast, Environment* env)
: m_ast(ast) : m_ast(ast)
, m_env(env) , m_env(env)
{ {
@ -25,46 +25,53 @@ void Eval::eval()
m_ast = evalImpl(m_ast, m_env); 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); return evalAst(ast, env);
} }
if (static_cast<List*>(ast)->empty()) { if (static_cast<List*>(ast.get())->empty()) {
return ast; 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)) { ASTNode* ast_raw_ptr = ast.get();
auto result = env->lookup(static_cast<Symbol*>(ast)->symbol()); if (is<Symbol>(ast_raw_ptr)) {
auto result = env->lookup(static_pointer_cast<Symbol>(ast)->symbol());
if (!result) { 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; return result;
} }
else if (is<List>(ast)) { else if (is<List>(ast_raw_ptr)) {
auto result = new List(); auto result = makePtr<List>();
auto nodes = static_cast<List*>(ast)->nodes(); auto nodes = static_pointer_cast<List>(ast)->nodes();
for (auto node : nodes) { for (auto node : nodes) {
result->addNode(evalImpl(node, env)); result->addNode(evalImpl(node, env));
} }
return result; return result;
} }
else if (is<Vector>(ast)) { else if (is<Vector>(ast_raw_ptr)) {
auto result = new Vector(); auto result = makePtr<Vector>();
auto nodes = static_cast<Vector*>(ast)->nodes(); auto nodes = static_pointer_cast<Vector>(ast)->nodes();
for (auto node : nodes) { for (auto node : nodes) {
result->addNode(evalImpl(node, env)); result->addNode(evalImpl(node, env));
} }
return result; return result;
} }
else if (is<HashMap>(ast)) { else if (is<HashMap>(ast_raw_ptr)) {
auto result = new HashMap(); auto result = makePtr<HashMap>();
auto elements = static_cast<HashMap*>(ast)->elements(); auto elements = static_pointer_cast<HashMap>(ast)->elements();
for (auto& element : elements) { for (auto& element : elements) {
result->addElement(element.first, evalImpl(element.second, env)); result->addElement(element.first, evalImpl(element.second, env));
} }
@ -74,19 +81,19 @@ ASTNode* Eval::evalAst(ASTNode* ast, Environment* env)
return ast; return ast;
} }
ASTNode* Eval::apply(List* evaluated_list) ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
{ {
auto nodes = evaluated_list->nodes(); auto nodes = evaluated_list->nodes();
if (!is<Function>(nodes[0])) { if (!is<Function>(nodes[0].get())) {
Error::the().addError(format("invalid function: {}", nodes[0])); Error::the().addError(format("invalid function: {}", nodes[0]));
return nullptr; return nullptr;
} }
// car // car
auto lambda = static_cast<Function*>(nodes[0])->lambda(); auto lambda = static_pointer_cast<Function>(nodes[0])->lambda();
// cdr // cdr
std::span<ASTNode*> span { nodes.data() + 1, nodes.size() - 1 }; std::span<ASTNodePtr> span { nodes.data() + 1, nodes.size() - 1 };
return lambda(span); return lambda(span);
} }

12
src/eval.h

@ -13,19 +13,19 @@ namespace blaze {
class Eval { class Eval {
public: public:
Eval(ASTNode* ast, Environment* env); Eval(ASTNodePtr ast, Environment* env);
virtual ~Eval() = default; virtual ~Eval() = default;
void eval(); void eval();
ASTNode* ast() const { return m_ast; } ASTNodePtr ast() const { return m_ast; }
private: private:
ASTNode* evalImpl(ASTNode* ast, Environment* env); ASTNodePtr evalImpl(ASTNodePtr ast, Environment* env);
ASTNode* evalAst(ASTNode* ast, Environment* env); ASTNodePtr evalAst(ASTNodePtr ast, Environment* env);
ASTNode* apply(List* evaluated_list); ASTNodePtr apply(std::shared_ptr<List> evaluated_list);
ASTNode* m_ast { nullptr }; ASTNodePtr m_ast { nullptr };
Environment* m_env { nullptr }; Environment* m_env { nullptr };
}; };

35
src/printer.cpp

@ -27,7 +27,7 @@ Printer::~Printer()
// ----------------------------------------- // -----------------------------------------
std::string Printer::print(ASTNode* node) std::string Printer::print(ASTNodePtr node)
{ {
if (Error::the().hasAnyError()) { if (Error::the().hasAnyError()) {
init(); init();
@ -38,7 +38,7 @@ std::string Printer::print(ASTNode* node)
return printNoErrorCheck(node); return printNoErrorCheck(node);
} }
std::string Printer::printNoErrorCheck(ASTNode* node) std::string Printer::printNoErrorCheck(ASTNodePtr node)
{ {
init(); init();
@ -60,7 +60,7 @@ void Printer::init()
m_print = ""; m_print = "";
} }
void Printer::printImpl(ASTNode* node) void Printer::printImpl(ASTNodePtr node)
{ {
auto printSpacing = [this]() -> void { auto printSpacing = [this]() -> void {
if (!m_first_node && !m_previous_node_is_list) { 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(); printSpacing();
m_print += '('; m_print += '(';
m_first_node = false; m_first_node = false;
m_previous_node_is_list = true; 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) { for (size_t i = 0; i < nodes.size(); ++i) {
printImpl(nodes[i]); printImpl(nodes[i]);
m_previous_node_is_list = false; m_previous_node_is_list = false;
} }
m_print += ')'; m_print += ')';
} }
else if (is<Vector>(node)) { else if (is<Vector>(node_raw_ptr)) {
printSpacing(); printSpacing();
m_print += '['; m_print += '[';
m_first_node = false; m_first_node = false;
m_previous_node_is_list = true; 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) { for (size_t i = 0; i < nodes.size(); ++i) {
printImpl(nodes[i]); printImpl(nodes[i]);
m_previous_node_is_list = false; m_previous_node_is_list = false;
} }
m_print += ']'; m_print += ']';
} }
else if (is<HashMap>(node)) { else if (is<HashMap>(node_raw_ptr)) {
printSpacing(); printSpacing();
m_print += "{"; m_print += "{";
m_first_node = false; m_first_node = false;
m_previous_node_is_list = true; 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) { for (auto it = elements.begin(); it != elements.end(); ++it) {
m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127 m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
printImpl(it->second); printImpl(it->second);
@ -109,22 +110,22 @@ void Printer::printImpl(ASTNode* node)
m_previous_node_is_list = false; m_previous_node_is_list = false;
m_print += '}'; m_print += '}';
} }
else if (is<String>(node)) { else if (is<String>(node_raw_ptr)) {
// TODO: Implement string readably printing // TODO: Implement string readably printing
printSpacing(); 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(); 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(); 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(); printSpacing();
m_print += format("{}", static_cast<Symbol*>(node)->symbol()); m_print += format("{}", static_pointer_cast<Symbol>(node)->symbol());
} }
} }

6
src/printer.h

@ -17,12 +17,12 @@ public:
Printer(); Printer();
virtual ~Printer(); virtual ~Printer();
std::string print(ASTNode* node); std::string print(ASTNodePtr node);
std::string printNoErrorCheck(ASTNode* node); std::string printNoErrorCheck(ASTNodePtr node);
private: private:
void init(); void init();
void printImpl(ASTNode* node); void printImpl(ASTNodePtr node);
void printError(); void printError();
bool m_first_node { true }; bool m_first_node { true };

105
src/reader.cpp

@ -7,6 +7,7 @@
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstdint> // uint64_t #include <cstdint> // uint64_t
#include <cstdlib> // std::strtoll #include <cstdlib> // std::strtoll
#include <memory> // makePtr, std::shared_ptr
#include <utility> // std::move #include <utility> // std::move
#include "error.h" #include "error.h"
@ -55,7 +56,7 @@ void Reader::read()
} }
} }
ASTNode* Reader::readImpl() ASTNodePtr Reader::readImpl()
{ {
if (m_tokens.size() == 0) { if (m_tokens.size() == 0) {
return nullptr; return nullptr;
@ -123,7 +124,7 @@ ASTNode* Reader::readImpl()
return nullptr; return nullptr;
} }
ASTNode* Reader::readSpliceUnquote() ASTNodePtr Reader::readSpliceUnquote()
{ {
ignore(); // ~@ ignore(); // ~@
@ -132,18 +133,18 @@ ASTNode* Reader::readSpliceUnquote()
return nullptr; return nullptr;
} }
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("splice-unquote")); list->addNode(makePtr<Symbol>("splice-unquote"));
list->addNode(readImpl()); list->addNode(readImpl());
return list; return list;
} }
ASTNode* Reader::readList() ASTNodePtr Reader::readList()
{ {
ignore(); // ( ignore(); // (
List* list = new List(); auto list = makePtr<List>();
while (!isEOF() && peek().type != Token::Type::ParenClose) { while (!isEOF() && peek().type != Token::Type::ParenClose) {
list->addNode(readImpl()); list->addNode(readImpl());
} }
@ -156,11 +157,11 @@ ASTNode* Reader::readList()
return list; return list;
} }
ASTNode* Reader::readVector() ASTNodePtr Reader::readVector()
{ {
ignore(); // [ ignore(); // [
Vector* vector = new Vector(); auto vector = makePtr<Vector>();
while (!isEOF() && peek().type != Token::Type::BracketClose) { while (!isEOF() && peek().type != Token::Type::BracketClose) {
vector->addNode(readImpl()); vector->addNode(readImpl());
} }
@ -172,30 +173,30 @@ ASTNode* Reader::readVector()
return vector; return vector;
} }
ASTNode* Reader::readHashMap() ASTNodePtr Reader::readHashMap()
{ {
ignore(); // { ignore(); // {
HashMap* hash_map = new HashMap(); auto hash_map = makePtr<HashMap>();
while (!isEOF() && peek().type != Token::Type::BraceClose) { while (!isEOF() && peek().type != Token::Type::BraceClose) {
ASTNode* key = readImpl(); auto key = readImpl();
ASTNode* value = readImpl(); auto value = readImpl();
if (!key && !value) { if (key == nullptr && value == nullptr) {
break; break;
} }
if (!key || !value) { if (key == nullptr || value == nullptr) {
Error::the().addError("hash-map requires an even-sized list"); Error::the().addError("hash-map requires an even-sized list");
return nullptr; 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)); Error::the().addError(format("{} is not a string or keyword", key));
return nullptr; 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); hash_map->addElement(keyString, value);
} }
@ -206,7 +207,7 @@ ASTNode* Reader::readHashMap()
return hash_map; return hash_map;
} }
ASTNode* Reader::readQuote() ASTNodePtr Reader::readQuote()
{ {
ignore(); // ' ignore(); // '
@ -215,14 +216,14 @@ ASTNode* Reader::readQuote()
return nullptr; return nullptr;
} }
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("quote")); list->addNode(makePtr<Symbol>("quote"));
list->addNode(readImpl()); list->addNode(readImpl());
return list; return list;
} }
ASTNode* Reader::readQuasiQuote() ASTNodePtr Reader::readQuasiQuote()
{ {
ignore(); // ` ignore(); // `
@ -231,14 +232,14 @@ ASTNode* Reader::readQuasiQuote()
return nullptr; return nullptr;
} }
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("quasiquote")); list->addNode(makePtr<Symbol>("quasiquote"));
list->addNode(readImpl()); list->addNode(readImpl());
return list; return list;
} }
ASTNode* Reader::readUnquote() ASTNodePtr Reader::readUnquote()
{ {
ignore(); // ~ ignore(); // ~
@ -247,14 +248,14 @@ ASTNode* Reader::readUnquote()
return nullptr; return nullptr;
} }
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("unquote")); list->addNode(makePtr<Symbol>("unquote"));
list->addNode(readImpl()); list->addNode(readImpl());
return list; return list;
} }
ASTNode* Reader::readWithMeta() ASTNodePtr Reader::readWithMeta()
{ {
ignore(); // ^ ignore(); // ^
@ -265,17 +266,17 @@ ASTNode* Reader::readWithMeta()
} }
retreat(); retreat();
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("with-meta")); list->addNode(makePtr<Symbol>("with-meta"));
ASTNode* first = readImpl(); ASTNodePtr first = readImpl();
ASTNode* second = readImpl(); ASTNodePtr second = readImpl();
list->addNode(second); list->addNode(second);
list->addNode(first); list->addNode(first);
return list; return list;
} }
ASTNode* Reader::readDeref() ASTNodePtr Reader::readDeref()
{ {
ignore(); // @ ignore(); // @
@ -284,14 +285,14 @@ ASTNode* Reader::readDeref()
return nullptr; return nullptr;
} }
List* list = new List(); auto list = makePtr<List>();
list->addNode(new Symbol("deref")); list->addNode(makePtr<Symbol>("deref"));
list->addNode(readImpl()); list->addNode(readImpl());
return list; return list;
} }
ASTNode* Reader::readString() ASTNodePtr Reader::readString()
{ {
std::string symbol = consume().symbol; std::string symbol = consume().symbol;
@ -300,24 +301,24 @@ ASTNode* Reader::readString()
Error::the().addError("expected '\"', got EOF"); 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(); Token token = consume();
char* end_ptr = nullptr; char* end_ptr = nullptr;
int64_t result = std::strtoll(token.symbol.c_str(), &end_ptr, 10); int64_t result = std::strtoll(token.symbol.c_str(), &end_ptr, 10);
if (end_ptr == token.symbol.c_str() + token.symbol.size()) { 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); dumpImpl(m_node);
} }
void Reader::dumpImpl(ASTNode* node) void Reader::dumpImpl(ASTNodePtr node)
{ {
std::string indentation = std::string(m_indentation * 2, ' '); std::string indentation = std::string(m_indentation * 2, ' ');
if (is<List>(node)) { ASTNode* node_raw_ptr = node.get();
List* list = static_cast<List*>(node); if (is<List>(node_raw_ptr)) {
List* list = static_cast<List*>(node_raw_ptr);
print("{}", indentation); print("{}", indentation);
print(fg(ruc::format::TerminalColor::Blue), "ListContainer"); print(fg(ruc::format::TerminalColor::Blue), "ListContainer");
print(" <"); print(" <");
@ -384,20 +386,25 @@ void Reader::dumpImpl(ASTNode* node)
m_indentation--; m_indentation--;
return; return;
} }
else if (is<String>(node)) { else if (is<String>(node_raw_ptr)) {
print("{}", indentation); print("{}", indentation);
print(fg(ruc::format::TerminalColor::Yellow), "StringNode"); 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("{}", indentation);
print(fg(ruc::format::TerminalColor::Yellow), "NumberNode"); 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("{}", indentation);
print(fg(ruc::format::TerminalColor::Yellow), "SymbolNode"); print(fg(ruc::format::TerminalColor::Yellow), "SymbolNode");
print(" <{}>", static_cast<Symbol*>(node)->symbol()); print(" <{}>", static_cast<Symbol*>(node_raw_ptr)->symbol());
} }
print("\n"); print("\n");
} }

33
src/reader.h

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <cstddef> // size_t #include <cstddef> // size_t
#include <memory> // std::shared_ptr
#include <vector> #include <vector>
#include "ast.h" #include "ast.h"
@ -24,7 +25,7 @@ public:
void dump(); void dump();
ASTNode* node() { return m_node; } ASTNodePtr node() { return m_node; }
private: private:
bool isEOF() const; bool isEOF() const;
@ -34,21 +35,21 @@ private:
void ignore(); void ignore();
void retreat(); void retreat();
ASTNode* readImpl(); ASTNodePtr readImpl();
ASTNode* readSpliceUnquote(); // ~@ ASTNodePtr readSpliceUnquote(); // ~@
ASTNode* readList(); // () ASTNodePtr readList(); // ()
ASTNode* readVector(); // [] ASTNodePtr readVector(); // []
ASTNode* readHashMap(); // {} ASTNodePtr readHashMap(); // {}
ASTNode* readQuote(); // ' ASTNodePtr readQuote(); // '
ASTNode* readQuasiQuote(); // ` ASTNodePtr readQuasiQuote(); // `
ASTNode* readUnquote(); // ~ ASTNodePtr readUnquote(); // ~
ASTNode* readWithMeta(); // ^ ASTNodePtr readWithMeta(); // ^
ASTNode* readDeref(); // @ ASTNodePtr readDeref(); // @
ASTNode* readString(); // "foobar" ASTNodePtr readString(); // "foobar"
ASTNode* readKeyword(); // :keyword ASTNodePtr readKeyword(); // :keyword
ASTNode* readValue(); // number, "true", "false", "nil", symbol ASTNodePtr readValue(); // number, "true", "false", "nil", symbol
void dumpImpl(ASTNode* node); void dumpImpl(ASTNodePtr node);
size_t m_index { 0 }; size_t m_index { 0 };
size_t m_indentation { 0 }; size_t m_indentation { 0 };
@ -58,7 +59,7 @@ private:
bool m_invalid_syntax { false }; bool m_invalid_syntax { false };
bool m_is_unbalanced { false }; bool m_is_unbalanced { false };
ASTNode* m_node { nullptr }; ASTNodePtr m_node { nullptr };
}; };
} // namespace blaze } // namespace blaze

12
src/step1_read_print.cpp

@ -15,7 +15,7 @@
#include "settings.h" #include "settings.h"
#if 0 #if 0
auto read(std::string_view input) -> blaze::ASTNode* auto read(std::string_view input) -> blaze::ASTNodePtr
{ {
blaze::Lexer lexer(input); blaze::Lexer lexer(input);
lexer.tokenize(); lexer.tokenize();
@ -32,15 +32,15 @@ auto read(std::string_view input) -> blaze::ASTNode*
return reader.node(); return reader.node();
} }
auto eval(blaze::ASTNode* ast) -> blaze::ASTNode* auto eval(blaze::ASTNodePtr ast) -> blaze::ASTNodePtr
{ {
return ast; return ast;
} }
auto print(blaze::ASTNode* exp) -> void auto print(blaze::ASTNodePtr exp) -> std::string
{ {
blaze::Printer printer(exp); blaze::Printer printer;
printer.dump(); return printer.print(exp);
} }
auto rep(std::string_view input) -> void 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().clearErrors();
blaze::Error::the().setInput(input); blaze::Error::the().setInput(input);
print(eval(read(input))); print("{}\n", print(eval(read(input))).c_str());
} }
static auto cleanup(int signal) -> void static auto cleanup(int signal) -> void

6
src/step2_eval.cpp

@ -16,7 +16,7 @@
#include "settings.h" #include "settings.h"
#if 1 #if 1
auto read(std::string_view input) -> blaze::ASTNode* auto read(std::string_view input) -> blaze::ASTNodePtr
{ {
blaze::Lexer lexer(input); blaze::Lexer lexer(input);
lexer.tokenize(); lexer.tokenize();
@ -33,7 +33,7 @@ auto read(std::string_view input) -> blaze::ASTNode*
return reader.node(); return reader.node();
} }
auto eval(blaze::ASTNode* ast) -> blaze::ASTNode* auto eval(blaze::ASTNodePtr ast) -> blaze::ASTNodePtr
{ {
blaze::GlobalEnvironment env; blaze::GlobalEnvironment env;
blaze::Eval eval(ast, &env); blaze::Eval eval(ast, &env);
@ -42,7 +42,7 @@ auto eval(blaze::ASTNode* ast) -> blaze::ASTNode*
return eval.ast(); return eval.ast();
} }
auto print(blaze::ASTNode* exp) -> std::string auto print(blaze::ASTNodePtr exp) -> std::string
{ {
blaze::Printer printer; blaze::Printer printer;

Loading…
Cancel
Save