Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aba70beeb3 | ||
|
|
9bbf238c34 | ||
|
|
441fdc0564 | ||
|
|
d772495f1a |
+7
-27
@@ -5,28 +5,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdint> // int64_t
|
#include <cstdint> // int64_t
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
#include "printer.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -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
|
blaze::Printer printer;
|
||||||
if (is<blaze::String>(value)) {
|
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
+26
-25
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
+29
-22
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+71
-53
@@ -5,9 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iterator> // std::next
|
#include <iterator> // std::next
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "ruc/format/print.h"
|
#include "ruc/format/format.h"
|
||||||
|
|
||||||
|
#include "ast.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "printer.h"
|
#include "printer.h"
|
||||||
@@ -15,113 +17,129 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
Printer::Printer(ASTNode* node)
|
Printer::Printer()
|
||||||
: m_node(node)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Printer::~Printer()
|
Printer::~Printer()
|
||||||
{
|
{
|
||||||
delete m_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void Printer::dump()
|
std::string Printer::print(ASTNodePtr node)
|
||||||
{
|
{
|
||||||
if (Error::the().hasAnyError()) {
|
if (Error::the().hasAnyError()) {
|
||||||
dumpError();
|
init();
|
||||||
return;
|
printError();
|
||||||
|
return m_print;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_node == nullptr) {
|
return printNoErrorCheck(node);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpImpl(m_node);
|
std::string Printer::printNoErrorCheck(ASTNodePtr node)
|
||||||
print("\n");
|
{
|
||||||
|
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 {
|
auto printSpacing = [this]() -> void {
|
||||||
if (!m_firstNode && !m_previousNodeIsList) {
|
if (!m_first_node && !m_previous_node_is_list) {
|
||||||
print(" ");
|
m_print += ' ';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (is<List>(node)) {
|
ASTNode* node_raw_ptr = node.get();
|
||||||
|
if (is<List>(node_raw_ptr)) {
|
||||||
printSpacing();
|
printSpacing();
|
||||||
print("(");
|
m_print += '(';
|
||||||
m_firstNode = false;
|
m_first_node = false;
|
||||||
m_previousNodeIsList = 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) {
|
||||||
dumpImpl(nodes[i]);
|
printImpl(nodes[i]);
|
||||||
m_previousNodeIsList = false;
|
m_previous_node_is_list = false;
|
||||||
}
|
}
|
||||||
print(")");
|
m_print += ')';
|
||||||
}
|
}
|
||||||
else if (is<Vector>(node)) {
|
else if (is<Vector>(node_raw_ptr)) {
|
||||||
printSpacing();
|
printSpacing();
|
||||||
print("[");
|
m_print += '[';
|
||||||
m_firstNode = false;
|
m_first_node = false;
|
||||||
m_previousNodeIsList = 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) {
|
||||||
dumpImpl(nodes[i]);
|
printImpl(nodes[i]);
|
||||||
m_previousNodeIsList = false;
|
m_previous_node_is_list = false;
|
||||||
}
|
}
|
||||||
print("]");
|
m_print += ']';
|
||||||
}
|
}
|
||||||
else if (is<HashMap>(node)) {
|
else if (is<HashMap>(node_raw_ptr)) {
|
||||||
printSpacing();
|
printSpacing();
|
||||||
print("{{");
|
m_print += "{";
|
||||||
m_firstNode = false;
|
m_first_node = false;
|
||||||
m_previousNodeIsList = 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) {
|
||||||
print("{} ", 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
|
||||||
dumpImpl(it->second);
|
printImpl(it->second);
|
||||||
|
|
||||||
if (it != elements.end() && std::next(it) != elements.end()) {
|
if (it != elements.end() && std::next(it) != elements.end()) {
|
||||||
print(" ");
|
m_print += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_previousNodeIsList = false;
|
m_previous_node_is_list = false;
|
||||||
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();
|
||||||
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();
|
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();
|
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();
|
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()) {
|
if (Error::the().hasTokenError()) {
|
||||||
Token error = Error::the().tokenError();
|
Token error = Error::the().tokenError();
|
||||||
print("{}", error.symbol);
|
m_print += format("{}", error.symbol);
|
||||||
}
|
}
|
||||||
else if (Error::the().hasOtherError()) {
|
else if (Error::the().hasOtherError()) {
|
||||||
std::string error = Error::the().otherError();
|
std::string error = Error::the().otherError();
|
||||||
print("{}", error);
|
m_print += format("{}", error);
|
||||||
}
|
}
|
||||||
print("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
+10
-7
@@ -7,24 +7,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
// Serializer -> return to string
|
// Serializer -> return to string
|
||||||
class Printer {
|
class Printer {
|
||||||
public:
|
public:
|
||||||
Printer(ASTNode* node);
|
Printer();
|
||||||
virtual ~Printer();
|
virtual ~Printer();
|
||||||
|
|
||||||
void dump();
|
std::string print(ASTNodePtr node);
|
||||||
|
std::string printNoErrorCheck(ASTNodePtr node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void dumpImpl(ASTNode* node);
|
void init();
|
||||||
void dumpError();
|
void printImpl(ASTNodePtr node);
|
||||||
|
void printError();
|
||||||
|
|
||||||
bool m_firstNode { true };
|
bool m_first_node { true };
|
||||||
bool m_previousNodeIsList { false };
|
bool m_previous_node_is_list { false };
|
||||||
ASTNode* m_node { nullptr };
|
std::string m_print;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
+56
-49
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -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
-3
@@ -9,6 +9,8 @@
|
|||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/tilde.h>
|
#include <readline/tilde.h>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "ruc/format/color.h"
|
#include "ruc/format/color.h"
|
||||||
|
|
||||||
@@ -18,7 +20,7 @@ namespace blaze {
|
|||||||
|
|
||||||
Readline::Readline(bool pretty_print, std::string_view history_path)
|
Readline::Readline(bool pretty_print, std::string_view history_path)
|
||||||
: m_pretty_print(pretty_print)
|
: m_pretty_print(pretty_print)
|
||||||
, m_history_path(history_path)
|
, m_history_path(tilde_expand(history_path.data()))
|
||||||
{
|
{
|
||||||
if (!pretty_print) {
|
if (!pretty_print) {
|
||||||
m_prompt = "user> ";
|
m_prompt = "user> ";
|
||||||
@@ -28,9 +30,16 @@ Readline::Readline(bool pretty_print, std::string_view history_path)
|
|||||||
m_prompt += format(" \033[1m");
|
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)
|
bool Readline::get(std::string& output)
|
||||||
{
|
{
|
||||||
char* line = readline(m_prompt.c_str());
|
char* line = readline(m_prompt.c_str());
|
||||||
@@ -40,7 +49,7 @@ bool Readline::get(std::string& output)
|
|||||||
|
|
||||||
// Add input to in-memory history
|
// Add input to in-memory history
|
||||||
add_history(line);
|
add_history(line);
|
||||||
append_history(1, m_history_path.data());
|
append_history(1, m_history_path);
|
||||||
|
|
||||||
output = line;
|
output = line;
|
||||||
std::free(line);
|
std::free(line);
|
||||||
|
|||||||
+2
-2
@@ -16,14 +16,14 @@ namespace blaze {
|
|||||||
class Readline {
|
class Readline {
|
||||||
public:
|
public:
|
||||||
Readline(bool pretty_print, std::string_view history_path);
|
Readline(bool pretty_print, std::string_view history_path);
|
||||||
virtual ~Readline() {}
|
virtual ~Readline();
|
||||||
|
|
||||||
bool get(std::string& output);
|
bool get(std::string& output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_pretty_print { false };
|
bool m_pretty_print { false };
|
||||||
std::string m_prompt;
|
std::string m_prompt;
|
||||||
std::string_view m_history_path;
|
char* m_history_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+11
-11
@@ -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,26 +33,28 @@ 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);
|
||||||
eval.eval();
|
eval.eval();
|
||||||
|
|
||||||
return eval.ast();
|
return eval.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) -> std::string
|
||||||
{
|
{
|
||||||
blaze::Error::the().clearErrors();
|
blaze::Error::the().clearErrors();
|
||||||
blaze::Error::the().setInput(input);
|
blaze::Error::the().setInput(input);
|
||||||
|
|
||||||
print(eval(read(input)));
|
return print(eval(read(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto cleanup(int signal) -> void
|
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_lexer, 'l', "dump-lexer", nullptr, nullptr);
|
||||||
arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr);
|
arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr);
|
||||||
arg_parser.addOption(pretty_print, 'c', "color", 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);
|
arg_parser.parse(argc, argv);
|
||||||
|
|
||||||
// Set settings
|
// Set settings
|
||||||
@@ -92,7 +94,7 @@ auto main(int argc, char* argv[]) -> int
|
|||||||
if (pretty_print) {
|
if (pretty_print) {
|
||||||
print("\033[0m");
|
print("\033[0m");
|
||||||
}
|
}
|
||||||
rep(input);
|
print("{}\n", rep(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pretty_print) {
|
if (pretty_print) {
|
||||||
@@ -102,5 +104,3 @@ auto main(int argc, char* argv[]) -> int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// - Add AST node printing support to ruc::format
|
|
||||||
|
|||||||
Reference in New Issue
Block a user