Compare commits

...
7 Commits
13 changed files with 476 additions and 383 deletions
+15 -4
View File
@@ -9,12 +9,14 @@
#include <string> #include <string>
#include "ast.h" #include "ast.h"
#include "environment.h"
#include "forward.h"
#include "printer.h" #include "printer.h"
#include "types.h" #include "types.h"
namespace blaze { namespace blaze {
void Collection::addNode(ASTNodePtr node) void Collection::add(ASTNodePtr node)
{ {
m_nodes.push_back(node); m_nodes.push_back(node);
} }
@@ -63,8 +65,18 @@ Value::Value(State state)
// ----------------------------------------- // -----------------------------------------
Function::Function(Lambda lambda) Function::Function(const std::string& name, FunctionType function)
: m_lambda(lambda) : m_name(name)
, m_function(function)
{
}
// -----------------------------------------
Lambda::Lambda(std::vector<std::string> bindings, ASTNodePtr body, EnvironmentPtr env)
: m_bindings(bindings)
, m_body(body)
, m_env(env)
{ {
} }
@@ -74,7 +86,6 @@ Function::Function(Lambda lambda)
void Formatter<blaze::ASTNodePtr>::format(Builder& builder, blaze::ASTNodePtr value) const void Formatter<blaze::ASTNodePtr>::format(Builder& builder, blaze::ASTNodePtr value) const
{ {
// printf("ASDJASJKDASJKDNAJK\n");
blaze::Printer printer; blaze::Printer printer;
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value)); return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));
} }
+33 -10
View File
@@ -15,13 +15,13 @@
#include <string_view> #include <string_view>
#include <typeinfo> // typeid #include <typeinfo> // typeid
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "ruc/format/formatter.h" #include "ruc/format/formatter.h"
namespace blaze { #include "forward.h"
class ASTNode; namespace blaze {
typedef std::shared_ptr<ASTNode> ASTNodePtr;
class ASTNode { class ASTNode {
public: public:
@@ -42,6 +42,7 @@ public:
virtual bool isValue() const { return false; } virtual bool isValue() const { return false; }
virtual bool isSymbol() const { return false; } virtual bool isSymbol() const { return false; }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
virtual bool isLambda() const { return false; }
protected: protected:
ASTNode() {} ASTNode() {}
@@ -55,7 +56,7 @@ public:
virtual bool isCollection() const override { return true; } virtual bool isCollection() const override { return true; }
void addNode(ASTNodePtr node); void add(ASTNodePtr node);
const std::list<ASTNodePtr>& nodes() const { return m_nodes; } const std::list<ASTNodePtr>& nodes() const { return m_nodes; }
size_t size() const { return m_nodes.size(); } size_t size() const { return m_nodes.size(); }
@@ -76,7 +77,6 @@ public:
List() = default; List() = default;
virtual ~List() = default; virtual ~List() = default;
virtual bool isCollection() const override { return false; }
virtual bool isList() const override { return true; } virtual bool isList() const override { return true; }
}; };
@@ -88,7 +88,6 @@ public:
Vector() = default; Vector() = default;
virtual ~Vector() = default; virtual ~Vector() = default;
virtual bool isCollection() const override { return false; }
virtual bool isVector() const override { return true; } virtual bool isVector() const override { return true; }
}; };
@@ -199,19 +198,40 @@ private:
// ----------------------------------------- // -----------------------------------------
using Lambda = std::function<ASTNodePtr(std::list<ASTNodePtr>)>; using FunctionType = std::function<ASTNodePtr(std::list<ASTNodePtr>)>;
class Function final : public ASTNode { class Function final : public ASTNode {
public: public:
explicit Function(Lambda lambda); explicit Function(const std::string& name, FunctionType function);
virtual ~Function() = default; virtual ~Function() = default;
virtual bool isFunction() const override { return true; } virtual bool isFunction() const override { return true; }
Lambda lambda() const { return m_lambda; } const std::string& name() const { return m_name; }
FunctionType function() const { return m_function; }
private: private:
Lambda m_lambda; const std::string m_name;
FunctionType m_function;
};
// -----------------------------------------
class Lambda final : public ASTNode {
public:
Lambda(std::vector<std::string> bindings, ASTNodePtr body, EnvironmentPtr env);
virtual ~Lambda() = default;
virtual bool isLambda() const override { return true; }
std::vector<std::string> bindings() const { return m_bindings; }
ASTNodePtr body() const { return m_body; }
EnvironmentPtr env() const { return m_env; }
private:
std::vector<std::string> m_bindings;
ASTNodePtr m_body;
EnvironmentPtr m_env;
}; };
// ----------------------------------------- // -----------------------------------------
@@ -254,6 +274,9 @@ inline bool ASTNode::fastIs<Symbol>() const { return isSymbol(); }
template<> template<>
inline bool ASTNode::fastIs<Function>() const { return isFunction(); } inline bool ASTNode::fastIs<Function>() const { return isFunction(); }
template<>
inline bool ASTNode::fastIs<Lambda>() const { return isLambda(); }
// clang-format on // clang-format on
} // namespace blaze } // namespace blaze
+55 -32
View File
@@ -4,16 +4,68 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include "ruc/format/print.h" #include <memory> // std::static_pointer_cast
#include "ruc/format/format.h"
#include "ast.h" #include "ast.h"
#include "environment.h" #include "environment.h"
#include "error.h"
#include "forward.h"
namespace blaze { namespace blaze {
Environment::Environment(EnvironmentPtr outer) EnvironmentPtr Environment::create()
: m_outer(outer)
{ {
return std::shared_ptr<Environment>(new Environment);
}
EnvironmentPtr Environment::create(EnvironmentPtr outer)
{
auto env = create();
env->m_outer = outer;
return env;
}
EnvironmentPtr Environment::create(const ASTNodePtr lambda, std::list<ASTNodePtr> arguments)
{
auto lambda_casted = std::static_pointer_cast<Lambda>(lambda);
auto env = create(lambda_casted->env());
auto bindings = lambda_casted->bindings();
auto it = arguments.begin();
for (size_t i = 0; i < bindings.size(); ++i, ++it) {
if (bindings[i] == "&") {
if (i + 2 != bindings.size()) {
Error::the().add(format("invalid function: {}", lambda));
return nullptr;
}
auto list = makePtr<List>();
for (; it != arguments.end(); ++it) {
list->add(*it);
}
env->set(bindings[i + 1], list);
return env;
}
if (it == arguments.end()) {
Error::the().add(format("wrong number of arguments: {}, {}", lambda, arguments.size()));
return nullptr;
}
env->set(bindings[i], *it);
}
if (it != arguments.end()) {
Error::the().add(format("wrong number of arguments: {}, {}", lambda, arguments.size()));
return nullptr;
}
return env;
} }
// ----------------------------------------- // -----------------------------------------
@@ -36,8 +88,6 @@ ASTNodePtr Environment::set(const std::string& symbol, ASTNodePtr value)
ASTNodePtr Environment::get(const std::string& symbol) ASTNodePtr Environment::get(const std::string& symbol)
{ {
m_current_key = symbol;
if (exists(symbol)) { if (exists(symbol)) {
return m_values[symbol]; return m_values[symbol];
} }
@@ -49,31 +99,4 @@ ASTNodePtr Environment::get(const std::string& symbol)
return nullptr; return nullptr;
} }
// -----------------------------------------
GlobalEnvironment::GlobalEnvironment()
{
add();
sub();
mul();
div();
lt();
lte();
gt();
gte();
list();
isList();
isEmpty();
count();
str();
prStr();
prn();
println();
equal();
}
} // namespace blaze } // namespace blaze
+10 -37
View File
@@ -6,59 +6,32 @@
#pragma once #pragma once
#include <list>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "ast.h" #include "forward.h"
namespace blaze { namespace blaze {
class Environment;
typedef std::shared_ptr<Environment> EnvironmentPtr;
class Environment { class Environment {
public: public:
Environment() = default;
Environment(EnvironmentPtr outer);
virtual ~Environment() = default; virtual ~Environment() = default;
// Factory functions instead of constructors because it can fail in the bindings/arguments case
static EnvironmentPtr create();
static EnvironmentPtr create(EnvironmentPtr outer);
static EnvironmentPtr create(const ASTNodePtr lambda, std::list<ASTNodePtr> arguments);
bool exists(const std::string& symbol); bool exists(const std::string& symbol);
ASTNodePtr set(const std::string& symbol, ASTNodePtr value); ASTNodePtr set(const std::string& symbol, ASTNodePtr value);
ASTNodePtr get(const std::string& symbol); ASTNodePtr get(const std::string& symbol);
protected: protected:
std::string m_current_key; Environment() {}
std::unordered_map<std::string, ASTNodePtr> m_values;
EnvironmentPtr m_outer { nullptr }; EnvironmentPtr m_outer { nullptr };
}; std::unordered_map<std::string, ASTNodePtr> m_values;
class GlobalEnvironment final : public Environment {
public:
GlobalEnvironment();
virtual ~GlobalEnvironment() = default;
private:
void add(); // +
void sub(); // -
void mul(); // *
void div(); // /
void lt(); // <
void lte(); // <=
void gt(); // >
void gte(); // >=
void list(); // list
void isList(); // list?
void isEmpty(); // empty?
void count(); // count
void str(); // str
void prStr(); // pr-str
void prn(); // prn
void println(); // println
void equal(); // =
}; };
} // namespace blaze } // namespace blaze
+2 -2
View File
@@ -24,8 +24,8 @@ public:
m_token_errors.clear(); m_token_errors.clear();
m_other_errors.clear(); m_other_errors.clear();
} }
void addError(Token error) { m_token_errors.push_back(error); } void add(Token error) { m_token_errors.push_back(error); }
void addError(const std::string& error) { m_other_errors.push_back(error); } void add(const std::string& error) { m_other_errors.push_back(error); }
bool hasTokenError() { return m_token_errors.size() > 0; } bool hasTokenError() { return m_token_errors.size() > 0; }
bool hasOtherError() { return m_other_errors.size() > 0; } bool hasOtherError() { return m_other_errors.size() > 0; }
+73 -25
View File
@@ -14,7 +14,7 @@
#include "environment.h" #include "environment.h"
#include "error.h" #include "error.h"
#include "eval.h" #include "eval.h"
#include "ruc/meta/assert.h" #include "forward.h"
#include "types.h" #include "types.h"
namespace blaze { namespace blaze {
@@ -63,6 +63,9 @@ ASTNodePtr Eval::evalImpl(ASTNodePtr ast, EnvironmentPtr env)
if (symbol == "if") { if (symbol == "if") {
return evalIf(nodes, env); return evalIf(nodes, env);
} }
if (symbol == "fn*") {
return evalFn(nodes, env);
}
} }
// Function call // Function call
@@ -79,7 +82,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
if (is<Symbol>(ast_raw_ptr)) { if (is<Symbol>(ast_raw_ptr)) {
auto result = env->get(std::static_pointer_cast<Symbol>(ast)->symbol()); auto result = env->get(std::static_pointer_cast<Symbol>(ast)->symbol());
if (!result) { if (!result) {
Error::the().addError(format("'{}' not found", ast)); Error::the().add(format("'{}' not found", ast));
return nullptr; return nullptr;
} }
return result; return result;
@@ -92,7 +95,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
if (eval_node == nullptr) { if (eval_node == nullptr) {
return nullptr; return nullptr;
} }
result->addNode(eval_node); result->add(eval_node);
} }
return result; return result;
} }
@@ -104,7 +107,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
if (eval_node == nullptr) { if (eval_node == nullptr) {
return nullptr; return nullptr;
} }
result->addNode(eval_node); result->add(eval_node);
} }
return result; return result;
} }
@@ -127,7 +130,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env) ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{ {
if (nodes.size() != 2) { if (nodes.size() != 2) {
Error::the().addError(format("wrong number of arguments: def!, {}", nodes.size())); Error::the().add(format("wrong number of arguments: def!, {}", nodes.size()));
return nullptr; return nullptr;
} }
@@ -136,7 +139,7 @@ ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
// First element needs to be a Symbol // First element needs to be a Symbol
if (!is<Symbol>(first_argument.get())) { if (!is<Symbol>(first_argument.get())) {
Error::the().addError(format("wrong type argument: symbol, {}", first_argument)); Error::the().add(format("wrong argument type: symbol, {}", first_argument));
return nullptr; return nullptr;
} }
@@ -155,7 +158,7 @@ ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
ASTNodePtr Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env) ASTNodePtr Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{ {
if (nodes.size() != 2) { if (nodes.size() != 2) {
Error::the().addError(format("wrong number of arguments: let*, {}", nodes.size())); Error::the().add(format("wrong number of arguments: let*, {}", nodes.size()));
return nullptr; return nullptr;
} }
@@ -163,36 +166,30 @@ ASTNodePtr Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
auto second_argument = *std::next(nodes.begin()); auto second_argument = *std::next(nodes.begin());
// First argument needs to be a List or Vector // First argument needs to be a List or Vector
if (!is<List>(first_argument.get()) && !is<Vector>(first_argument.get())) { if (!is<Collection>(first_argument.get())) {
Error::the().addError(format("wrong argument type: list, '{}'", first_argument)); Error::the().add(format("wrong argument type: collection, '{}'", first_argument));
return nullptr; return nullptr;
} }
// Get the nodes out of the List or Vector // Get the nodes out of the List or Vector
std::list<ASTNodePtr> binding_nodes; std::list<ASTNodePtr> binding_nodes;
if (is<List>(first_argument.get())) { auto bindings = std::static_pointer_cast<Collection>(first_argument);
auto bindings = std::static_pointer_cast<List>(first_argument);
binding_nodes = bindings->nodes(); binding_nodes = bindings->nodes();
}
else {
auto bindings = std::static_pointer_cast<Vector>(first_argument);
binding_nodes = bindings->nodes();
}
// List or Vector needs to have an even number of elements // List or Vector needs to have an even number of elements
size_t count = binding_nodes.size(); size_t count = binding_nodes.size();
if (count % 2 != 0) { if (count % 2 != 0) {
Error::the().addError(format("wrong number of arguments: {}, {}", "let* bindings", count)); Error::the().add(format("wrong number of arguments: {}, {}", "let* bindings", count));
return nullptr; return nullptr;
} }
// Create new environment // Create new environment
auto let_env = makePtr<Environment>(env); auto let_env = Environment::create(env);
for (auto it = binding_nodes.begin(); it != binding_nodes.end(); std::advance(it, 2)) { for (auto it = binding_nodes.begin(); it != binding_nodes.end(); std::advance(it, 2)) {
// First element needs to be a Symbol // First element needs to be a Symbol
if (!is<Symbol>(*it->get())) { if (!is<Symbol>(*it->get())) {
Error::the().addError(format("wrong argument type: symbol, '{}'", *it)); Error::the().add(format("wrong argument type: symbol, '{}'", *it));
return nullptr; return nullptr;
} }
@@ -209,7 +206,7 @@ ASTNodePtr Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
ASTNodePtr Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env) ASTNodePtr Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{ {
if (nodes.size() == 0) { if (nodes.size() == 0) {
Error::the().addError(format("wrong number of arguments: do, {}", nodes.size())); Error::the().add(format("wrong number of arguments: do, {}", nodes.size()));
return nullptr; return nullptr;
} }
@@ -225,7 +222,7 @@ ASTNodePtr Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
ASTNodePtr Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env) ASTNodePtr Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{ {
if (nodes.size() != 2 && nodes.size() != 3) { if (nodes.size() != 2 && nodes.size() != 3) {
Error::the().addError(format("wrong number of arguments: if, {}", nodes.size())); Error::the().add(format("wrong number of arguments: if, {}", nodes.size()));
return nullptr; return nullptr;
} }
@@ -243,6 +240,42 @@ ASTNodePtr Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
} }
} }
#define ARG_COUNT_CHECK(name, size, comparison) \
if (size comparison) { \
Error::the().add(format("wrong number of arguments: {}, {}", name, size)); \
return nullptr; \
}
#define AST_CHECK(type, value) \
if (!is<type>(value.get())) { \
Error::the().add(format("wrong argument type: {}, {}", #type, value)); \
return nullptr; \
}
#define AST_CAST(type, value, variable) \
AST_CHECK(type, value) \
auto variable = std::static_pointer_cast<type>(value);
ASTNodePtr Eval::evalFn(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{
ARG_COUNT_CHECK("fn*", nodes.size(), != 2);
auto first_argument = *nodes.begin();
auto second_argument = *std::next(nodes.begin());
// First element needs to be a List or Vector
AST_CAST(Collection, first_argument, collection);
std::vector<std::string> bindings;
for (auto node : collection->nodes()) {
// All nodes need to be a Symbol
AST_CAST(Symbol, node, symbol);
bindings.push_back(symbol->symbol());
}
return makePtr<Lambda>(bindings, second_argument, env);
}
ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list) ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
{ {
if (evaluated_list == nullptr) { if (evaluated_list == nullptr) {
@@ -251,17 +284,32 @@ ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
auto nodes = evaluated_list->nodes(); auto nodes = evaluated_list->nodes();
if (!is<Function>(nodes.front().get())) { if (!is<Function>(nodes.front().get()) && !is<Lambda>(nodes.front().get())) {
Error::the().addError(format("invalid function: {}", nodes.front())); Error::the().add(format("invalid function: {}", nodes.front()));
return nullptr; return nullptr;
} }
// Function
if (is<Function>(nodes.front().get())) {
// car // car
auto lambda = std::static_pointer_cast<Function>(nodes.front())->lambda(); auto function = std::static_pointer_cast<Function>(nodes.front())->function();
// cdr // cdr
nodes.pop_front(); nodes.pop_front();
return lambda(nodes); return function(nodes);
}
// Lambda
// car
auto lambda = std::static_pointer_cast<Lambda>(nodes.front());
// cdr
nodes.pop_front();
auto lambda_env = Environment::create(lambda, nodes);
return evalImpl(lambda->body(), lambda_env);
} }
} // namespace blaze } // namespace blaze
+4 -1
View File
@@ -8,11 +8,13 @@
#include <list> #include <list>
#include "ast.h"
#include "environment.h" #include "environment.h"
#include "forward.h"
namespace blaze { namespace blaze {
class List;
class Eval { class Eval {
public: public:
Eval(ASTNodePtr ast, EnvironmentPtr env); Eval(ASTNodePtr ast, EnvironmentPtr env);
@@ -29,6 +31,7 @@ private:
ASTNodePtr evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env); ASTNodePtr evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env); ASTNodePtr evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env); ASTNodePtr evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalFn(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr apply(std::shared_ptr<List> evaluated_list); ASTNodePtr apply(std::shared_ptr<List> evaluated_list);
ASTNodePtr m_ast; ASTNodePtr m_ast;
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <memory> // std::shared_ptr
namespace blaze {
// -----------------------------------------
// Types
class ASTNode;
typedef std::shared_ptr<ASTNode> ASTNodePtr;
class Environment;
typedef std::shared_ptr<Environment> EnvironmentPtr;
// -----------------------------------------
// Functions
extern void installFunctions(EnvironmentPtr env);
} // namespace blaze
+107 -140
View File
@@ -7,26 +7,49 @@
#include <memory> // std::static_pointer_cast #include <memory> // std::static_pointer_cast
#include <string> #include <string>
#include "ruc/format/color.h"
#include "ruc/format/format.h" #include "ruc/format/format.h"
#include "ast.h" #include "ast.h"
#include "environment.h" #include "environment.h"
#include "error.h" #include "error.h"
#include "forward.h"
#include "printer.h" #include "printer.h"
#include "types.h" #include "types.h"
#include "util.h" #include "util.h"
// At the top-level you cant invoke any function, but you can create variables.
// Using a struct's constructor you can work around this limitation.
// Also the line number in the file is used to make the struct names unique.
#define FUNCTION_STRUCT_NAME(unique) __functionStruct##unique
#define ADD_FUNCTION_IMPL(unique, symbol, lambda) \
struct FUNCTION_STRUCT_NAME(unique) { \
FUNCTION_STRUCT_NAME(unique) \
(std::string __symbol, FunctionType __lambda) \
{ \
s_functions.emplace(__symbol, __lambda); \
} \
}; \
static struct FUNCTION_STRUCT_NAME(unique) \
FUNCTION_STRUCT_NAME(unique)( \
symbol, \
[](std::list<ASTNodePtr> nodes) -> ASTNodePtr lambda);
#define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda);
namespace blaze { namespace blaze {
void GlobalEnvironment::add() static std::unordered_map<std::string, FunctionType> s_functions;
{
auto add = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr { ADD_FUNCTION(
"+",
{
int64_t result = 0; int64_t result = 0;
for (auto node : nodes) { for (auto node : nodes) {
if (!is<Number>(node.get())) { if (!is<Number>(node.get())) {
Error::the().addError(format("wrong argument type: number, '{}'", node)); Error::the().add(format("wrong argument type: number, '{}'", node));
return nullptr; return nullptr;
} }
@@ -34,21 +57,18 @@ void GlobalEnvironment::add()
} }
return makePtr<Number>(result); return makePtr<Number>(result);
}; });
m_values.emplace("+", makePtr<Function>(add)); ADD_FUNCTION(
} "-",
{
void GlobalEnvironment::sub()
{
auto sub = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
if (nodes.size() == 0) { if (nodes.size() == 0) {
return makePtr<Number>(0); return makePtr<Number>(0);
} }
for (auto node : nodes) { for (auto node : nodes) {
if (!is<Number>(node.get())) { if (!is<Number>(node.get())) {
Error::the().addError(format("wrong argument type: number, '{}'", node)); Error::the().add(format("wrong argument type: number, '{}'", node));
return nullptr; return nullptr;
} }
} }
@@ -62,19 +82,16 @@ void GlobalEnvironment::sub()
} }
return makePtr<Number>(result); return makePtr<Number>(result);
}; });
m_values.emplace("-", makePtr<Function>(sub)); ADD_FUNCTION(
} "*",
{
void GlobalEnvironment::mul()
{
auto mul = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
int64_t result = 1; int64_t result = 1;
for (auto node : nodes) { for (auto node : nodes) {
if (!is<Number>(node.get())) { if (!is<Number>(node.get())) {
Error::the().addError(format("wrong argument type: number, '{}'", node)); Error::the().add(format("wrong argument type: number, '{}'", node));
return nullptr; return nullptr;
} }
@@ -82,22 +99,19 @@ void GlobalEnvironment::mul()
} }
return makePtr<Number>(result); return makePtr<Number>(result);
}; });
m_values.emplace("*", makePtr<Function>(mul)); ADD_FUNCTION(
} "/",
{
void GlobalEnvironment::div()
{
auto div = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
if (nodes.size() == 0) { if (nodes.size() == 0) {
Error::the().addError(format("wrong number of arguments: {}, 0", m_current_key)); Error::the().add(format("wrong number of arguments: /, 0"));
return nullptr; return nullptr;
} }
for (auto node : nodes) { for (auto node : nodes) {
if (!is<Number>(node.get())) { if (!is<Number>(node.get())) {
Error::the().addError(format("wrong type argument: number-or-marker-p, '{}'", node)); Error::the().add(format("wrong argument type: number, '{}'", node));
return nullptr; return nullptr;
} }
} }
@@ -111,25 +125,22 @@ void GlobalEnvironment::div()
} }
return makePtr<Number>((int64_t)result); return makePtr<Number>((int64_t)result);
}; });
m_values.emplace("/", makePtr<Function>(div)); // // -----------------------------------------
}
// ----------------------------------------- #define NUMBER_COMPARE(operator) \
{ \
#define NUMBER_COMPARE(symbol, comparison_symbol) \
auto lambda = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr { \
bool result = true; \ bool result = true; \
\ \
if (nodes.size() < 2) { \ if (nodes.size() < 2) { \
Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); \ Error::the().add(format("wrong number of arguments: {}, {}", #operator, nodes.size() - 1)); \
return nullptr; \ return nullptr; \
} \ } \
\ \
for (auto node : nodes) { \ for (auto node : nodes) { \
if (!is<Number>(node.get())) { \ if (!is<Number>(node.get())) { \
Error::the().addError(format("wrong argument type: number, '{}'", node)); \ Error::the().add(format("wrong argument type: number, '{}'", node)); \
return nullptr; \ return nullptr; \
} \ } \
} \ } \
@@ -140,7 +151,7 @@ void GlobalEnvironment::div()
/* 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) { \
int64_t current_number = std::static_pointer_cast<Number>(*it)->number(); \ int64_t current_number = std::static_pointer_cast<Number>(*it)->number(); \
if (number comparison_symbol current_number) { \ if (!(number operator current_number)) { \
result = false; \ result = false; \
break; \ break; \
} \ } \
@@ -148,50 +159,30 @@ void GlobalEnvironment::div()
} \ } \
\ \
return makePtr<Value>((result) ? Value::True : Value::False); \ return makePtr<Value>((result) ? Value::True : Value::False); \
}; \ }
\
m_values.emplace(symbol, makePtr<Function>(lambda));
void GlobalEnvironment::lt() ADD_FUNCTION("<", NUMBER_COMPARE(<));
{ ADD_FUNCTION("<=", NUMBER_COMPARE(<=));
NUMBER_COMPARE("<", >=); ADD_FUNCTION(">", NUMBER_COMPARE(>));
} ADD_FUNCTION(">=", NUMBER_COMPARE(>=));
void GlobalEnvironment::lte()
{
NUMBER_COMPARE("<=", >);
}
void GlobalEnvironment::gt()
{
NUMBER_COMPARE(">", <=);
}
void GlobalEnvironment::gte()
{
NUMBER_COMPARE(">=", <);
}
// ----------------------------------------- // -----------------------------------------
void GlobalEnvironment::list() ADD_FUNCTION(
{ "list",
auto list = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr { {
auto list = makePtr<List>(); auto list = makePtr<List>();
for (auto node : nodes) { for (auto node : nodes) {
list->addNode(node); list->add(node);
} }
return list; return list;
}; });
m_values.emplace("list", makePtr<Function>(list)); ADD_FUNCTION(
} "list?",
{
void GlobalEnvironment::isList()
{
auto is_list = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
bool result = true; bool result = true;
for (auto node : nodes) { for (auto node : nodes) {
@@ -202,68 +193,58 @@ void GlobalEnvironment::isList()
} }
return makePtr<Value>((result) ? Value::True : Value::False); return makePtr<Value>((result) ? Value::True : Value::False);
}; });
m_values.emplace("list?", makePtr<Function>(is_list)); ADD_FUNCTION(
} "empty?",
{
void GlobalEnvironment::isEmpty()
{
auto is_empty = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
bool result = true; bool result = true;
for (auto node : nodes) { for (auto node : nodes) {
if (!is<List>(node.get())) { if (!is<Collection>(node.get())) {
Error::the().addError(format("wrong argument type: list, '{}'", node)); Error::the().add(format("wrong argument type: collection, '{}'", node));
return nullptr; return nullptr;
} }
if (!std::static_pointer_cast<List>(node)->empty()) { if (!std::static_pointer_cast<Collection>(node)->empty()) {
result = false; result = false;
break; break;
} }
} }
return makePtr<Value>((result) ? Value::True : Value::False); return makePtr<Value>((result) ? Value::True : Value::False);
}; });
m_values.emplace("empty?", makePtr<Function>(is_empty)); ADD_FUNCTION(
} "count",
{
void GlobalEnvironment::count()
{
auto count = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
if (nodes.size() != 1) { if (nodes.size() != 1) {
Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); Error::the().add(format("wrong number of arguments: count, {}", nodes.size() - 1));
return nullptr; return nullptr;
} }
auto first_argument = nodes.front();
size_t result = 0; size_t result = 0;
if (is<Value>(nodes.front().get()) && std::static_pointer_cast<Value>(nodes.front())->state() == Value::Nil) { if (is<Value>(first_argument.get()) && std::static_pointer_cast<Value>(nodes.front())->state() == Value::Nil) {
// result = 0 // result = 0
} }
else if (!is<List>(nodes.front().get())) { else if (is<Collection>(first_argument.get())) {
result = std::static_pointer_cast<List>(nodes.front())->size(); result = std::static_pointer_cast<Collection>(first_argument)->size();
}
else if (!is<Vector>(nodes.front().get())) {
result = std::static_pointer_cast<Vector>(nodes.front())->size();
} }
else { else {
Error::the().addError(format("wrong argument type: list, '{}'", nodes)); Error::the().add(format("wrong argument type: collection, '{}'", first_argument));
return nullptr; return nullptr;
} }
// FIXME: Add numeric_limits check for implicit cast: size_t > int64_t // FIXME: Add numeric_limits check for implicit cast: size_t > int64_t
return makePtr<Number>((int64_t)result); return makePtr<Number>((int64_t)result);
}; });
m_values.emplace("count", makePtr<Function>(count));
}
// ----------------------------------------- // -----------------------------------------
#define PRINTER_STRING(symbol, concatenation, print_readably) \ #define PRINTER_STRING(print_readably, concatenation) \
auto lambda = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr { \ { \
std::string result; \ std::string result; \
\ \
Printer printer; \ Printer printer; \
@@ -276,22 +257,13 @@ void GlobalEnvironment::count()
} \ } \
\ \
return makePtr<String>(result); \ return makePtr<String>(result); \
}; \ }
\
m_values.emplace(symbol, makePtr<Function>(lambda));
void GlobalEnvironment::str() ADD_FUNCTION("str", PRINTER_STRING(false, ""));
{ ADD_FUNCTION("pr-str", PRINTER_STRING(true, " "));
PRINTER_STRING("str", "", false);
}
void GlobalEnvironment::prStr() #define PRINTER_PRINT(print_readably) \
{ { \
PRINTER_STRING("pr-str", " ", true);
}
#define PRINTER_PRINT(symbol, print_readably) \
auto lambda = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr { \
Printer printer; \ Printer printer; \
for (auto it = nodes.begin(); it != nodes.end(); ++it) { \ for (auto it = nodes.begin(); it != nodes.end(); ++it) { \
print("{}", printer.printNoErrorCheck(*it, print_readably)); \ print("{}", printer.printNoErrorCheck(*it, print_readably)); \
@@ -303,36 +275,27 @@ void GlobalEnvironment::prStr()
print("\n"); \ print("\n"); \
\ \
return makePtr<Value>(Value::Nil); \ return makePtr<Value>(Value::Nil); \
}; \ }
\
m_values.emplace(symbol, makePtr<Function>(lambda));
void GlobalEnvironment::prn() ADD_FUNCTION("prn", PRINTER_PRINT(true));
{ ADD_FUNCTION("println", PRINTER_PRINT(false));
PRINTER_PRINT("prn", true);
}
void GlobalEnvironment::println()
{
PRINTER_PRINT("println", false);
}
// ----------------------------------------- // -----------------------------------------
void GlobalEnvironment::equal() ADD_FUNCTION(
{ "=",
auto lambda = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr { {
if (nodes.size() < 2) { if (nodes.size() < 2) {
Error::the().addError(format("wrong number of arguments: {}, {}", m_current_key, nodes.size() - 1)); Error::the().add(format("wrong number of arguments: =, {}", nodes.size() - 1));
return nullptr; return nullptr;
} }
std::function<bool(ASTNodePtr, ASTNodePtr)> equal = std::function<bool(ASTNodePtr, ASTNodePtr)> equal =
[&equal](ASTNodePtr lhs, ASTNodePtr rhs) -> bool { [&equal](ASTNodePtr lhs, ASTNodePtr rhs) -> bool {
if ((is<List>(lhs.get()) && is<List>(rhs.get())) if ((is<List>(lhs.get()) || is<Vector>(lhs.get()))
|| (is<Vector>(lhs.get()) && is<Vector>(rhs.get()))) { && (is<List>(rhs.get()) || is<Vector>(rhs.get()))) {
auto lhs_nodes = std::static_pointer_cast<List>(lhs)->nodes(); auto lhs_nodes = std::static_pointer_cast<Collection>(lhs)->nodes();
auto rhs_nodes = std::static_pointer_cast<List>(rhs)->nodes(); auto rhs_nodes = std::static_pointer_cast<Collection>(rhs)->nodes();
if (lhs_nodes.size() != rhs_nodes.size()) { if (lhs_nodes.size() != rhs_nodes.size()) {
return false; return false;
@@ -402,9 +365,13 @@ void GlobalEnvironment::equal()
} }
return makePtr<Value>((result) ? Value::True : Value::False); return makePtr<Value>((result) ? Value::True : Value::False);
}; });
m_values.emplace("=", makePtr<Function>(lambda)); void installFunctions(EnvironmentPtr env)
{
for (const auto& [name, lambda] : s_functions) {
env->set(name, makePtr<Function>(name, lambda));
}
} }
} // namespace blaze } // namespace blaze
+1 -1
View File
@@ -160,7 +160,7 @@ bool Lexer::consumeString()
} }
if (character != '"') { if (character != '"') {
Error::the().addError({ Token::Type::Error, m_line, column, "expected '\"', got EOF" }); Error::the().add({ Token::Type::Error, m_line, column, "expected '\"', got EOF" });
} }
m_tokens.push_back({ Token::Type::String, m_line, column, text }); m_tokens.push_back({ Token::Type::String, m_line, column, text });
+14 -18
View File
@@ -71,29 +71,17 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
}; };
ASTNode* node_raw_ptr = node.get(); ASTNode* node_raw_ptr = node.get();
if (is<List>(node_raw_ptr)) { if (is<Collection>(node_raw_ptr)) {
printSpacing(); printSpacing();
m_print += '('; m_print += (is<List>(node_raw_ptr)) ? '(' : '[';
m_first_node = false; m_first_node = false;
m_previous_node_is_list = true; m_previous_node_is_list = true;
auto nodes = std::static_pointer_cast<List>(node)->nodes(); auto nodes = std::static_pointer_cast<Collection>(node)->nodes();
for (auto node : nodes) { for (auto node : nodes) {
printImpl(node); printImpl(node, print_readably);
m_previous_node_is_list = false; m_previous_node_is_list = false;
} }
m_print += ')'; m_print += (is<List>(node_raw_ptr)) ? ')' : ']';
}
else if (is<Vector>(node_raw_ptr)) {
printSpacing();
m_print += '[';
m_first_node = false;
m_previous_node_is_list = true;
auto nodes = std::static_pointer_cast<Vector>(node)->nodes();
for (auto node : nodes) {
printImpl(node);
m_previous_node_is_list = false;
}
m_print += ']';
} }
else if (is<HashMap>(node_raw_ptr)) { else if (is<HashMap>(node_raw_ptr)) {
printSpacing(); printSpacing();
@@ -103,7 +91,7 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
auto elements = std::static_pointer_cast<HashMap>(node)->elements(); auto elements = std::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, print_readably);
if (isLast(it, elements)) { if (isLast(it, elements)) {
m_print += ' '; m_print += ' ';
@@ -145,6 +133,14 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
printSpacing(); printSpacing();
m_print += format("{}", std::static_pointer_cast<Symbol>(node)->symbol()); m_print += format("{}", std::static_pointer_cast<Symbol>(node)->symbol());
} }
else if (is<Function>(node_raw_ptr)) {
printSpacing();
m_print += format("#<builtin-function>({})", std::static_pointer_cast<Function>(node)->name());
}
else if (is<Lambda>(node_raw_ptr)) {
printSpacing();
m_print += format("#<user-function>({:p})", node_raw_ptr);
}
} }
void Printer::printError() void Printer::printError()
+33 -33
View File
@@ -50,7 +50,7 @@ void Reader::read()
case Token::Type::Comment: case Token::Type::Comment:
break; break;
default: default:
Error::the().addError("more than one sexp in input"); Error::the().add("more than one sexp in input");
break; break;
}; };
} }
@@ -70,21 +70,21 @@ ASTNodePtr Reader::readImpl()
return readList(); return readList();
break; break;
case Token::Type::ParenClose: // ) case Token::Type::ParenClose: // )
Error::the().addError("invalid read syntax: ')'"); Error::the().add("invalid read syntax: ')'");
return nullptr; return nullptr;
break; break;
case Token::Type::BracketOpen: // [ case Token::Type::BracketOpen: // [
return readVector(); return readVector();
break; break;
case Token::Type::BracketClose: // ] case Token::Type::BracketClose: // ]
Error::the().addError("invalid read syntax: ']'"); Error::the().add("invalid read syntax: ']'");
return nullptr; return nullptr;
break; break;
case Token::Type::BraceOpen: // { case Token::Type::BraceOpen: // {
return readHashMap(); return readHashMap();
break; break;
case Token::Type::BraceClose: // } case Token::Type::BraceClose: // }
Error::the().addError("invalid read syntax: '}'"); Error::the().add("invalid read syntax: '}'");
return nullptr; return nullptr;
break; break;
case Token::Type::Quote: // ' case Token::Type::Quote: // '
@@ -129,13 +129,13 @@ ASTNodePtr Reader::readSpliceUnquote()
ignore(); // ~@ ignore(); // ~@
if (isEOF()) { if (isEOF()) {
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("splice-unquote")); list->add(makePtr<Symbol>("splice-unquote"));
list->addNode(readImpl()); list->add(readImpl());
return list; return list;
} }
@@ -146,11 +146,11 @@ ASTNodePtr Reader::readList()
auto list = makePtr<List>(); auto list = makePtr<List>();
while (!isEOF() && peek().type != Token::Type::ParenClose) { while (!isEOF() && peek().type != Token::Type::ParenClose) {
list->addNode(readImpl()); list->add(readImpl());
} }
if (!consumeSpecific(Token { .type = Token::Type::ParenClose })) { // ) if (!consumeSpecific(Token { .type = Token::Type::ParenClose })) { // )
Error::the().addError("expected ')', got EOF"); Error::the().add("expected ')', got EOF");
return nullptr; return nullptr;
} }
@@ -163,11 +163,11 @@ ASTNodePtr Reader::readVector()
auto vector = makePtr<Vector>(); auto vector = makePtr<Vector>();
while (!isEOF() && peek().type != Token::Type::BracketClose) { while (!isEOF() && peek().type != Token::Type::BracketClose) {
vector->addNode(readImpl()); vector->add(readImpl());
} }
if (!consumeSpecific(Token { .type = Token::Type::BracketClose })) { // ] if (!consumeSpecific(Token { .type = Token::Type::BracketClose })) { // ]
Error::the().addError("expected ']', got EOF"); Error::the().add("expected ']', got EOF");
} }
return vector; return vector;
@@ -187,12 +187,12 @@ ASTNodePtr Reader::readHashMap()
} }
if (key == nullptr || value == nullptr) { if (key == nullptr || value == nullptr) {
Error::the().addError("hash-map requires an even-sized list"); Error::the().add("hash-map requires an even-sized list");
return nullptr; return nullptr;
} }
if (!is<String>(key.get()) && !is<Keyword>(key.get())) { if (!is<String>(key.get()) && !is<Keyword>(key.get())) {
Error::the().addError(format("{} is not a string or keyword", key)); Error::the().add(format("{} is not a string or keyword", key));
return nullptr; return nullptr;
} }
@@ -201,7 +201,7 @@ ASTNodePtr Reader::readHashMap()
} }
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // } if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
Error::the().addError("expected '}', got EOF"); Error::the().add("expected '}', got EOF");
} }
return hash_map; return hash_map;
@@ -212,13 +212,13 @@ ASTNodePtr Reader::readQuote()
ignore(); // ' ignore(); // '
if (isEOF()) { if (isEOF()) {
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("quote")); list->add(makePtr<Symbol>("quote"));
list->addNode(readImpl()); list->add(readImpl());
return list; return list;
} }
@@ -228,13 +228,13 @@ ASTNodePtr Reader::readQuasiQuote()
ignore(); // ` ignore(); // `
if (isEOF()) { if (isEOF()) {
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("quasiquote")); list->add(makePtr<Symbol>("quasiquote"));
list->addNode(readImpl()); list->add(readImpl());
return list; return list;
} }
@@ -244,13 +244,13 @@ ASTNodePtr Reader::readUnquote()
ignore(); // ~ ignore(); // ~
if (isEOF()) { if (isEOF()) {
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("unquote")); list->add(makePtr<Symbol>("unquote"));
list->addNode(readImpl()); list->add(readImpl());
return list; return list;
} }
@@ -261,17 +261,17 @@ ASTNodePtr Reader::readWithMeta()
ignore(); // first token ignore(); // first token
if (isEOF()) { // second token if (isEOF()) { // second token
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
retreat(); retreat();
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("with-meta")); list->add(makePtr<Symbol>("with-meta"));
ASTNodePtr first = readImpl(); ASTNodePtr first = readImpl();
ASTNodePtr second = readImpl(); ASTNodePtr second = readImpl();
list->addNode(second); list->add(second);
list->addNode(first); list->add(first);
return list; return list;
} }
@@ -281,13 +281,13 @@ ASTNodePtr Reader::readDeref()
ignore(); // @ ignore(); // @
if (isEOF()) { if (isEOF()) {
Error::the().addError("expected form, got EOF"); Error::the().add("expected form, got EOF");
return nullptr; return nullptr;
} }
auto list = makePtr<List>(); auto list = makePtr<List>();
list->addNode(makePtr<Symbol>("deref")); list->add(makePtr<Symbol>("deref"));
list->addNode(readImpl()); list->add(readImpl());
return list; return list;
} }
@@ -377,12 +377,12 @@ void Reader::dumpImpl(ASTNodePtr node)
std::string indentation = std::string(m_indentation * 2, ' '); std::string indentation = std::string(m_indentation * 2, ' ');
ASTNode* node_raw_ptr = node.get(); ASTNode* node_raw_ptr = node.get();
if (is<List>(node_raw_ptr)) { if (is<Collection>(node_raw_ptr)) {
auto nodes = std::static_pointer_cast<List>(node)->nodes(); auto nodes = std::static_pointer_cast<List>(node)->nodes();
print("{}", indentation); print("{}", indentation);
print(fg(ruc::format::TerminalColor::Blue), "ListContainer"); print(fg(ruc::format::TerminalColor::Blue), "{}Container", (is<List>(node_raw_ptr)) ? "List" : "Vector");
print(" <"); print(" <");
print(fg(ruc::format::TerminalColor::Blue), "()"); print(fg(ruc::format::TerminalColor::Blue), "{}", (is<List>(node_raw_ptr)) ? "()" : "{}");
print(">\n"); print(">\n");
m_indentation++; m_indentation++;
for (auto node : nodes) { for (auto node : nodes) {
+69 -47
View File
@@ -10,6 +10,7 @@
#include "environment.h" #include "environment.h"
#include "error.h" #include "error.h"
#include "eval.h" #include "eval.h"
#include "forward.h"
#include "lexer.h" #include "lexer.h"
#include "printer.h" #include "printer.h"
#include "reader.h" #include "reader.h"
@@ -17,53 +18,14 @@
#include "settings.h" #include "settings.h"
#if 1 #if 1
static blaze::EnvironmentPtr env = blaze::makePtr<blaze::GlobalEnvironment>(); static blaze::EnvironmentPtr s_outer_env = blaze::Environment::create();
auto read(std::string_view input) -> blaze::ASTNodePtr static auto cleanup(int signal) -> void;
{ static auto installLambdas(blaze::EnvironmentPtr env) -> void;
blaze::Lexer lexer(input); static auto rep(std::string_view input, blaze::EnvironmentPtr env) -> std::string;
lexer.tokenize(); static auto read(std::string_view input) -> blaze::ASTNodePtr;
if (blaze::Settings::the().get("dump-lexer") == "1") { static auto eval(blaze::ASTNodePtr ast, blaze::EnvironmentPtr env) -> blaze::ASTNodePtr;
lexer.dump(); static auto print(blaze::ASTNodePtr exp) -> std::string;
}
blaze::Reader reader(std::move(lexer.tokens()));
reader.read();
if (blaze::Settings::the().get("dump-reader") == "1") {
reader.dump();
}
return reader.node();
}
auto eval(blaze::ASTNodePtr ast) -> blaze::ASTNodePtr
{
blaze::Eval eval(ast, env);
eval.eval();
return eval.ast();
}
auto print(blaze::ASTNodePtr exp) -> std::string
{
blaze::Printer printer;
return printer.print(exp, true);
}
auto rep(std::string_view input) -> std::string
{
blaze::Error::the().clearErrors();
blaze::Error::the().setInput(input);
return print(eval(read(input)));
}
static auto cleanup(int signal) -> void
{
print("\033[0m\n");
std::exit(signal);
}
auto main(int argc, char* argv[]) -> int auto main(int argc, char* argv[]) -> int
{ {
@@ -89,6 +51,9 @@ auto main(int argc, char* argv[]) -> int
std::signal(SIGINT, cleanup); std::signal(SIGINT, cleanup);
std::signal(SIGTERM, cleanup); std::signal(SIGTERM, cleanup);
installFunctions(s_outer_env);
installLambdas(s_outer_env);
blaze::Readline readline(pretty_print, history_path); blaze::Readline readline(pretty_print, history_path);
std::string input; std::string input;
@@ -96,7 +61,7 @@ auto main(int argc, char* argv[]) -> int
if (pretty_print) { if (pretty_print) {
print("\033[0m"); print("\033[0m");
} }
print("{}\n", rep(input)); print("{}\n", rep(input, s_outer_env));
} }
if (pretty_print) { if (pretty_print) {
@@ -105,4 +70,61 @@ auto main(int argc, char* argv[]) -> int
return 0; return 0;
} }
static auto cleanup(int signal) -> void
{
print("\033[0m\n");
std::exit(signal);
}
static std::string_view lambdaTable[] = {
"(def! not (fn* (cond) (if cond false true)))",
};
static auto installLambdas(blaze::EnvironmentPtr env) -> void
{
for (auto function : lambdaTable) {
rep(function, env);
}
}
static auto rep(std::string_view input, blaze::EnvironmentPtr env) -> std::string
{
blaze::Error::the().clearErrors();
blaze::Error::the().setInput(input);
return print(eval(read(input), env));
}
static auto read(std::string_view input) -> blaze::ASTNodePtr
{
blaze::Lexer lexer(input);
lexer.tokenize();
if (blaze::Settings::the().get("dump-lexer") == "1") {
lexer.dump();
}
blaze::Reader reader(std::move(lexer.tokens()));
reader.read();
if (blaze::Settings::the().get("dump-reader") == "1") {
reader.dump();
}
return reader.node();
}
static auto eval(blaze::ASTNodePtr ast, blaze::EnvironmentPtr env) -> blaze::ASTNodePtr
{
blaze::Eval eval(ast, env);
eval.eval();
return eval.ast();
}
static auto print(blaze::ASTNodePtr exp) -> std::string
{
blaze::Printer printer;
return printer.print(exp, true);
}
#endif #endif