Browse Source

Main+Env+Printer: Remove the GlobalEnvironment subclass

master
Riyyi 2 years ago
parent
commit
826af24561
  1. 5
      src/ast.cpp
  2. 4
      src/ast.h
  3. 31
      src/environment.cpp
  4. 34
      src/environment.h
  5. 8
      src/forward.h
  6. 183
      src/functions.cpp
  7. 4
      src/printer.cpp
  8. 115
      src/step4_if_fn_do.cpp

5
src/ast.cpp

@ -65,8 +65,9 @@ Value::Value(State state)
// ----------------------------------------- // -----------------------------------------
Function::Function(FunctionType function) Function::Function(const std::string& name, FunctionType function)
: m_function(function) : m_name(name)
, m_function(function)
{ {
} }

4
src/ast.h

@ -202,14 +202,16 @@ using FunctionType = std::function<ASTNodePtr(std::list<ASTNodePtr>)>;
class Function final : public ASTNode { class Function final : public ASTNode {
public: public:
explicit Function(FunctionType function); 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; }
const std::string& name() const { return m_name; }
FunctionType function() const { return m_function; } FunctionType function() const { return m_function; }
private: private:
const std::string m_name;
FunctionType m_function; FunctionType m_function;
}; };

31
src/environment.cpp

@ -6,7 +6,7 @@
#include <memory> // std::static_pointer_cast #include <memory> // std::static_pointer_cast
#include "ruc/format/print.h" #include "ruc/format/format.h"
#include "ast.h" #include "ast.h"
#include "environment.h" #include "environment.h"
@ -88,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];
} }
@ -101,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

34
src/environment.h

@ -9,9 +9,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "badge.h"
#include "forward.h" #include "forward.h"
namespace blaze { namespace blaze {
@ -32,38 +30,8 @@ public:
protected: protected:
Environment() {} Environment() {}
std::string m_current_key;
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

8
src/forward.h

@ -10,10 +10,18 @@
namespace blaze { namespace blaze {
// -----------------------------------------
// Types
class ASTNode; class ASTNode;
typedef std::shared_ptr<ASTNode> ASTNodePtr; typedef std::shared_ptr<ASTNode> ASTNodePtr;
class Environment; class Environment;
typedef std::shared_ptr<Environment> EnvironmentPtr; typedef std::shared_ptr<Environment> EnvironmentPtr;
// -----------------------------------------
// Functions
extern void installFunctions(EnvironmentPtr env);
} // namespace blaze } // namespace blaze

183
src/functions.cpp

@ -7,7 +7,6 @@
#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"
@ -18,11 +17,34 @@
#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;
ADD_FUNCTION(
"+",
{ {
auto add = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
int64_t result = 0; int64_t result = 0;
for (auto node : nodes) { for (auto node : nodes) {
@ -35,14 +57,11 @@ 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);
} }
@ -63,14 +82,11 @@ 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) {
@ -83,16 +99,13 @@ void GlobalEnvironment::mul()
} }
return makePtr<Number>(result); return makePtr<Number>(result);
}; });
m_values.emplace("*", makePtr<Function>(mul));
}
void GlobalEnvironment::div() ADD_FUNCTION(
"/",
{ {
auto div = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
if (nodes.size() == 0) { if (nodes.size() == 0) {
Error::the().add(format("wrong number of arguments: {}, 0", m_current_key)); Error::the().add(format("wrong number of arguments: /, 0"));
return nullptr; return nullptr;
} }
@ -112,19 +125,16 @@ void GlobalEnvironment::div()
} }
return makePtr<Number>((int64_t)result); return makePtr<Number>((int64_t)result);
}; });
m_values.emplace("/", makePtr<Function>(div));
}
// ----------------------------------------- // // -----------------------------------------
#define NUMBER_COMPARE(symbol, comparison_symbol) \ #define NUMBER_COMPARE(operator) \
auto lambda = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr { \ { \
bool result = true; \ bool result = true; \
\ \
if (nodes.size() < 2) { \ if (nodes.size() < 2) { \
Error::the().add(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; \
} \ } \
\ \
@ -141,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; \
} \ } \
@ -149,35 +159,18 @@ 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()
{
NUMBER_COMPARE("<", >=);
} }
void GlobalEnvironment::lte() ADD_FUNCTION("<", NUMBER_COMPARE(<));
{ ADD_FUNCTION("<=", NUMBER_COMPARE(<=));
NUMBER_COMPARE("<=", >); ADD_FUNCTION(">", NUMBER_COMPARE(>));
} ADD_FUNCTION(">=", 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) {
@ -185,14 +178,11 @@ void GlobalEnvironment::list()
} }
return list; return list;
}; });
m_values.emplace("list", makePtr<Function>(list));
}
void GlobalEnvironment::isList() ADD_FUNCTION(
"list?",
{ {
auto is_list = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
bool result = true; bool result = true;
for (auto node : nodes) { for (auto node : nodes) {
@ -203,14 +193,11 @@ 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));
}
void GlobalEnvironment::isEmpty() ADD_FUNCTION(
"empty?",
{ {
auto is_empty = [](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
bool result = true; bool result = true;
for (auto node : nodes) { for (auto node : nodes) {
@ -226,16 +213,13 @@ void GlobalEnvironment::isEmpty()
} }
return makePtr<Value>((result) ? Value::True : Value::False); return makePtr<Value>((result) ? Value::True : Value::False);
}; });
m_values.emplace("empty?", makePtr<Function>(is_empty));
}
void GlobalEnvironment::count() ADD_FUNCTION(
"count",
{ {
auto count = [this](std::list<ASTNodePtr> nodes) -> ASTNodePtr {
if (nodes.size() != 1) { if (nodes.size() != 1) {
Error::the().add(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;
} }
@ -255,15 +239,12 @@ void GlobalEnvironment::count()
// 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()
{
PRINTER_STRING("str", "", false);
} }
void GlobalEnvironment::prStr() ADD_FUNCTION("str", PRINTER_STRING(false, ""));
{ ADD_FUNCTION("pr-str", PRINTER_STRING(true, " "));
PRINTER_STRING("pr-str", " ", true);
}
#define PRINTER_PRINT(symbol, print_readably) \ #define PRINTER_PRINT(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,27 +275,18 @@ 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()
{
PRINTER_PRINT("prn", true);
} }
void GlobalEnvironment::println() ADD_FUNCTION("prn", PRINTER_PRINT(true));
{ ADD_FUNCTION("println", PRINTER_PRINT(false));
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().add(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;
} }
@ -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

4
src/printer.cpp

@ -135,11 +135,11 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
} }
else if (is<Function>(node_raw_ptr)) { else if (is<Function>(node_raw_ptr)) {
printSpacing(); printSpacing();
m_print += format("#<builtin-function>"); m_print += format("#<builtin-function>({})", std::static_pointer_cast<Function>(node)->name());
} }
else if (is<Lambda>(node_raw_ptr)) { else if (is<Lambda>(node_raw_ptr)) {
printSpacing(); printSpacing();
m_print += format("#<user-function>"); m_print += format("#<user-function>({:p})", node_raw_ptr);
} }
} }

115
src/step4_if_fn_do.cpp

@ -18,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
{ {
@ -90,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;
@ -97,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) {
@ -106,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

Loading…
Cancel
Save