From f5dc1168eb851ad2f3e1b789a72d7806c19ebb80 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 19 Nov 2023 12:27:52 +0100 Subject: [PATCH] Reader+Env: Add dump function --- src/ast.cpp | 4 +- src/ast.h | 6 +- src/env/functions/format.cpp | 16 +++++ src/eval-special-form.cpp | 4 +- src/reader.cpp | 111 +++++++++++++++++++++++++++++------ src/reader.h | 5 +- 6 files changed, 121 insertions(+), 25 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index 6fd9df4..d92e693 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -225,9 +225,9 @@ Callable::Callable(ValuePtr meta) // ----------------------------------------- -Function::Function(std::string_view name, std::string_view signature, std::string_view documentation, FunctionType function) +Function::Function(std::string_view name, std::string_view bindings, std::string_view documentation, FunctionType function) : m_name(name) - , m_signature(signature) + , m_bindings(bindings) , m_documentation(documentation) , m_function(function) { diff --git a/src/ast.h b/src/ast.h index e39f087..4a93c96 100644 --- a/src/ast.h +++ b/src/ast.h @@ -332,12 +332,12 @@ using FunctionType = std::function // std::next #include +#include "reader.h" #include "ruc/format/print.h" #include "ast.h" @@ -54,6 +55,21 @@ void Environment::loadFormat() ADD_FUNCTION("prn", "", "", PRINTER_PRINT(true)); ADD_FUNCTION("println", "", "", PRINTER_PRINT(false)); + + // ------------------------------------- + + ADD_FUNCTION( + "dump", + "arg", + "Print AST of the value ARG.", + { + CHECK_ARG_COUNT_IS("dump", SIZE(), 1); + + Reader reader; + reader.dump(*begin); + + return nullptr; + }); } } // namespace blaze diff --git a/src/eval-special-form.cpp b/src/eval-special-form.cpp index 766fbc0..15d20ae 100644 --- a/src/eval-special-form.cpp +++ b/src/eval-special-form.cpp @@ -172,8 +172,8 @@ ValuePtr Eval::evalDescribe(const ValueVector& nodes, EnvironmentPtr env) type = "function"; auto function = std::static_pointer_cast(value); - signature += !function->signature().empty() ? " " : ""; - signature += function->signature(); + signature += !function->bindings().empty() ? " " : ""; + signature += function->bindings(); documentation = function->documentation(); } diff --git a/src/reader.cpp b/src/reader.cpp index 37d3751..f54d192 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -16,10 +16,15 @@ #include "ast.h" #include "reader.h" +#include "settings.h" #include "types.h" namespace blaze { +Reader::Reader() +{ +} + Reader::Reader(std::vector&& tokens) noexcept : m_tokens(std::move(tokens)) { @@ -362,55 +367,127 @@ void Reader::retreat() // ----------------------------------------- -void Reader::dump() +void Reader::dump(ValuePtr node) { - dumpImpl(m_node); + m_indentation = 0; + dumpImpl((node != nullptr) ? node : m_node); } void Reader::dumpImpl(ValuePtr node) { - std::string indentation = std::string(m_indentation * 2, ' '); + std::string indentation = std::string(m_indentation * INDENTATION_WIDTH, ' '); + print("{}", indentation); + + bool pretty_print = Settings::the().get("pretty-print") == "1"; + auto blue = fg(ruc::format::TerminalColor::BrightBlue); + auto yellow = fg(ruc::format::TerminalColor::Yellow); Value* node_raw_ptr = node.get(); if (is(node_raw_ptr)) { - auto nodes = std::static_pointer_cast(node)->nodesRead(); - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Blue), "{}Container", (is(node_raw_ptr)) ? "List" : "Vector"); + auto container = (is(node_raw_ptr)) ? "List" : "Vector"; + auto parens = (is(node_raw_ptr)) ? "()" : "[]"; + pretty_print ? print(blue, "{}", container) : print("{}", container); print(" <"); - print(fg(ruc::format::TerminalColor::Blue), "{}", (is(node_raw_ptr)) ? "()" : "{}"); + pretty_print ? print(blue, "{}", parens) : print("{}", parens); print(">\n"); m_indentation++; + auto nodes = std::static_pointer_cast(node)->nodesRead(); for (auto node : nodes) { dumpImpl(node); } m_indentation--; return; } + else if (is(node_raw_ptr)) { + auto hash_map = std::static_pointer_cast(node); + auto elements = hash_map->elements(); + pretty_print ? print(blue, "HashMap") : print("HashMap"); + print(" <"); + pretty_print ? print(blue, "{{}}") : print("{{}}"); + print(">\n"); + m_indentation++; + ValuePtr key_node = nullptr; + for (auto element : elements) { + bool is_keyword = element.first.front() == 0x7f; // 127 + is_keyword + ? dumpImpl(makePtr(element.first.substr(1))) + : dumpImpl(makePtr(element.first)); + m_indentation++; + dumpImpl(element.second); + m_indentation--; + } + m_indentation--; + return; + } else if (is(node_raw_ptr)) { - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Yellow), "StringNode"); + pretty_print ? print(yellow, "StringNode") : print("StringNode"); print(" <{}>", node); } else if (is(node_raw_ptr)) { - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Yellow), "KeywordNode"); + pretty_print ? print(yellow, "KeywordNode") : print("KeywordNode"); print(" <{}>", node); } else if (is(node_raw_ptr)) { - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Yellow), "NumberNode"); + pretty_print ? print(yellow, "NumberNode") : print("NumberNode"); print(" <{}>", node); } else if (is(node_raw_ptr)) { - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Yellow), "ValueNode"); + pretty_print ? print(yellow, "ValueNode") : print("ValueNode"); print(" <{}>", node); } else if (is(node_raw_ptr)) { - print("{}", indentation); - print(fg(ruc::format::TerminalColor::Yellow), "SymbolNode"); + pretty_print ? print(yellow, "SymbolNode") : print("SymbolNode"); print(" <{}>", node); } + else if (is(node_raw_ptr)) { + auto function = std::static_pointer_cast(node); + pretty_print ? print(blue, "Function") : print("Function"); + print(" <"); + pretty_print ? print(blue, "{}", function->name()) : print("{}", function->name()); + print(">\n"); + + m_indentation++; + indentation = std::string(m_indentation * INDENTATION_WIDTH, ' '); + + // bindings + print("{}", indentation); + pretty_print ? print(blue, "Bindings") : print("Bindings"); + print(" <{}>\n", function->bindings()); + + m_indentation--; + return; + } + else if (is(node_raw_ptr) || is(node_raw_ptr)) { + auto container = (is(node_raw_ptr)) ? "Lambda" : "Macro"; + auto lambda = std::static_pointer_cast(node); + pretty_print ? print(blue, "{}", container) : print("{}", container); + print(" <"); + pretty_print ? print(blue, "{:p}", node_raw_ptr) : print("{:p}", node_raw_ptr); + print(">\n"); + + m_indentation++; + indentation = std::string(m_indentation * INDENTATION_WIDTH, ' '); + + // bindings + print("{}", indentation); + pretty_print ? print(blue, "Bindings") : print("Bindings"); + print(" <"); + const auto& bindings = lambda->bindings(); + for (size_t i = 0; i < bindings.size(); ++i) { + print("{}{}", (i > 0) ? " " : "", bindings[i]); + } + print(">\n"); + + // body + dumpImpl(lambda->body()); + + m_indentation--; + return; + } + else if (is(node_raw_ptr)) { + pretty_print ? print(yellow, "AtomNode") : print("AtomNode"); + print(" <{}>", std::static_pointer_cast(node)->deref()); + } print("\n"); } diff --git a/src/reader.h b/src/reader.h index d67ba25..26b01eb 100644 --- a/src/reader.h +++ b/src/reader.h @@ -13,17 +13,20 @@ #include "ast.h" #include "lexer.h" +#define INDENTATION_WIDTH 2 + namespace blaze { // Parsing -> creates AST class Reader { public: + Reader(); Reader(std::vector&& tokens) noexcept; virtual ~Reader(); void read(); - void dump(); + void dump(ValuePtr node = nullptr); ValuePtr node() { return m_node; }