Compare commits

..
4 Commits
13 changed files with 283 additions and 245 deletions
+7 -27
View File
@@ -5,28 +5,23 @@
*/
#include <cstdint> // int64_t
#include <memory>
#include <string>
#include "ast.h"
#include "printer.h"
#include "types.h"
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);
}
@@ -77,23 +72,8 @@ 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
{
// TODO: Call into Printer::dumpImp(), instead of doing it manually
if (is<blaze::String>(value)) {
return Formatter<std::string>::format(builder, static_cast<blaze::String*>(value)->data());
}
if (is<blaze::Keyword>(value)) {
return Formatter<std::string>::format(builder, ":" + static_cast<blaze::Keyword*>(value)->keyword().substr(1));
}
else if (is<blaze::Number>(value)) {
Formatter<int64_t> formatter { .specifier = specifier };
return formatter.format(builder, static_cast<blaze::Number*>(value)->number());
}
else if (is<blaze::Value>(value)) {
return Formatter<std::string>::format(builder, static_cast<blaze::Value*>(value)->value());
}
else if (is<blaze::Symbol>(value)) {
return Formatter<std::string>::format(builder, static_cast<blaze::Symbol*>(value)->symbol());
}
blaze::Printer printer;
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));
}
+28 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 };
};
+71 -53
View File
@@ -5,9 +5,11 @@
*/
#include <iterator> // std::next
#include <string>
#include "ruc/format/print.h"
#include "ruc/format/format.h"
#include "ast.h"
#include "error.h"
#include "lexer.h"
#include "printer.h"
@@ -15,113 +17,129 @@
namespace blaze {
Printer::Printer(ASTNode* node)
: m_node(node)
Printer::Printer()
{
}
Printer::~Printer()
{
delete m_node;
}
// -----------------------------------------
void Printer::dump()
std::string Printer::print(ASTNodePtr node)
{
if (Error::the().hasAnyError()) {
dumpError();
return;
init();
printError();
return m_print;
}
if (m_node == nullptr) {
return;
return printNoErrorCheck(node);
}
dumpImpl(m_node);
print("\n");
std::string Printer::printNoErrorCheck(ASTNodePtr node)
{
init();
if (node == nullptr) {
return {};
}
void Printer::dumpImpl(ASTNode* node)
printImpl(node);
return m_print;
}
// -----------------------------------------
void Printer::init()
{
m_first_node = true;
m_previous_node_is_list = false;
m_print = "";
}
void Printer::printImpl(ASTNodePtr node)
{
auto printSpacing = [this]() -> void {
if (!m_firstNode && !m_previousNodeIsList) {
print(" ");
if (!m_first_node && !m_previous_node_is_list) {
m_print += ' ';
}
};
if (is<List>(node)) {
ASTNode* node_raw_ptr = node.get();
if (is<List>(node_raw_ptr)) {
printSpacing();
print("(");
m_firstNode = false;
m_previousNodeIsList = true;
auto nodes = static_cast<List*>(node)->nodes();
m_print += '(';
m_first_node = false;
m_previous_node_is_list = true;
auto nodes = static_pointer_cast<List>(node)->nodes();
for (size_t i = 0; i < nodes.size(); ++i) {
dumpImpl(nodes[i]);
m_previousNodeIsList = false;
printImpl(nodes[i]);
m_previous_node_is_list = false;
}
print(")");
m_print += ')';
}
else if (is<Vector>(node)) {
else if (is<Vector>(node_raw_ptr)) {
printSpacing();
print("[");
m_firstNode = false;
m_previousNodeIsList = true;
auto nodes = static_cast<Vector*>(node)->nodes();
m_print += '[';
m_first_node = false;
m_previous_node_is_list = true;
auto nodes = static_pointer_cast<Vector>(node)->nodes();
for (size_t i = 0; i < nodes.size(); ++i) {
dumpImpl(nodes[i]);
m_previousNodeIsList = false;
printImpl(nodes[i]);
m_previous_node_is_list = false;
}
print("]");
m_print += ']';
}
else if (is<HashMap>(node)) {
else if (is<HashMap>(node_raw_ptr)) {
printSpacing();
print("{{");
m_firstNode = false;
m_previousNodeIsList = true;
auto elements = static_cast<HashMap*>(node)->elements();
m_print += "{";
m_first_node = false;
m_previous_node_is_list = true;
auto elements = static_pointer_cast<HashMap>(node)->elements();
for (auto it = elements.begin(); it != elements.end(); ++it) {
print("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
dumpImpl(it->second);
m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
printImpl(it->second);
if (it != elements.end() && std::next(it) != elements.end()) {
print(" ");
m_print += ' ';
}
}
m_previousNodeIsList = false;
print("}}");
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();
print("{}", 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();
print(":{}", 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();
print("{}", 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();
print("{}", static_cast<Symbol*>(node)->symbol());
m_print += format("{}", static_pointer_cast<Symbol>(node)->symbol());
}
}
void Printer::dumpError()
void Printer::printError()
{
print("Error: ");
m_print = "Error: ";
if (Error::the().hasTokenError()) {
Token error = Error::the().tokenError();
print("{}", error.symbol);
m_print += format("{}", error.symbol);
}
else if (Error::the().hasOtherError()) {
std::string error = Error::the().otherError();
print("{}", error);
m_print += format("{}", error);
}
print("\n");
}
} // namespace blaze
+10 -7
View File
@@ -7,24 +7,27 @@
#pragma once
#include "ast.h"
#include <string>
namespace blaze {
// Serializer -> return to string
class Printer {
public:
Printer(ASTNode* node);
Printer();
virtual ~Printer();
void dump();
std::string print(ASTNodePtr node);
std::string printNoErrorCheck(ASTNodePtr node);
private:
void dumpImpl(ASTNode* node);
void dumpError();
void init();
void printImpl(ASTNodePtr node);
void printError();
bool m_firstNode { true };
bool m_previousNodeIsList { false };
ASTNode* m_node { nullptr };
bool m_first_node { true };
bool m_previous_node_is_list { false };
std::string m_print;
};
} // namespace blaze
+56 -49
View File
@@ -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
View File
@@ -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
+12 -3
View File
@@ -9,6 +9,8 @@
#include <readline/history.h>
#include <readline/readline.h>
#include <readline/tilde.h>
#include <string>
#include <string_view>
#include "ruc/format/color.h"
@@ -18,7 +20,7 @@ namespace blaze {
Readline::Readline(bool pretty_print, std::string_view history_path)
: m_pretty_print(pretty_print)
, m_history_path(history_path)
, m_history_path(tilde_expand(history_path.data()))
{
if (!pretty_print) {
m_prompt = "user> ";
@@ -28,9 +30,16 @@ Readline::Readline(bool pretty_print, std::string_view history_path)
m_prompt += format(" \033[1m");
}
read_history(tilde_expand(history_path.data()));
read_history(m_history_path);
}
Readline::~Readline()
{
std::free(m_history_path);
}
// -----------------------------------------
bool Readline::get(std::string& output)
{
char* line = readline(m_prompt.c_str());
@@ -40,7 +49,7 @@ bool Readline::get(std::string& output)
// Add input to in-memory history
add_history(line);
append_history(1, m_history_path.data());
append_history(1, m_history_path);
output = line;
std::free(line);
+2 -2
View File
@@ -16,14 +16,14 @@ namespace blaze {
class Readline {
public:
Readline(bool pretty_print, std::string_view history_path);
virtual ~Readline() {}
virtual ~Readline();
bool get(std::string& output);
private:
bool m_pretty_print { false };
std::string m_prompt;
std::string_view m_history_path;
char* m_history_path;
};
} // namespace blaze
+6 -6
View File
@@ -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
+11 -11
View File
@@ -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,26 +33,28 @@ 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);
eval.eval();
return eval.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
auto rep(std::string_view input) -> std::string
{
blaze::Error::the().clearErrors();
blaze::Error::the().setInput(input);
print(eval(read(input)));
return print(eval(read(input)));
}
static auto cleanup(int signal) -> void
@@ -73,7 +75,7 @@ auto main(int argc, char* argv[]) -> int
arg_parser.addOption(dump_lexer, 'l', "dump-lexer", nullptr, nullptr);
arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr);
arg_parser.addOption(pretty_print, 'c', "color", nullptr, nullptr);
arg_parser.addOption(history_path, 'h', "history", nullptr, nullptr);
arg_parser.addOption(history_path, 'h', "history", nullptr, nullptr, nullptr, ruc::ArgParser::Required::Yes);
arg_parser.parse(argc, argv);
// Set settings
@@ -92,7 +94,7 @@ auto main(int argc, char* argv[]) -> int
if (pretty_print) {
print("\033[0m");
}
rep(input);
print("{}\n", rep(input));
}
if (pretty_print) {
@@ -102,5 +104,3 @@ auto main(int argc, char* argv[]) -> int
return 0;
}
#endif
// - Add AST node printing support to ruc::format