diff --git a/src/ast.cpp b/src/ast.cpp index 803a627..eb4b37f 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -26,6 +26,13 @@ void Collection::addNode(ASTNode* node) // ----------------------------------------- +void HashMap::addElement(const std::string& key, ASTNode* value) +{ + m_elements.emplace(key, value); +} + +// ----------------------------------------- + String::String(const std::string& data) : m_data(data) { diff --git a/src/ast.h b/src/ast.h index 0fcd2d0..f00e1a0 100644 --- a/src/ast.h +++ b/src/ast.h @@ -12,6 +12,7 @@ #include #include #include // typeid +#include #include #include "ruc/format/formatter.h" @@ -90,13 +91,21 @@ public: // ----------------------------------------- // {} -class HashMap final : public Collection { +class HashMap final : public ASTNode { public: HashMap() = default; virtual ~HashMap() = default; - virtual bool isCollection() const override { return false; } virtual bool isHashMap() const override { return true; } + + void addElement(const std::string& key, ASTNode* value); + + const std::unordered_map& elements() const { return m_elements; } + size_t size() const { return m_elements.size(); } + bool empty() const { return m_elements.size() == 0; } + +private: + std::unordered_map m_elements; }; // ----------------------------------------- diff --git a/src/eval.cpp b/src/eval.cpp index 85a43f0..23bd708 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -63,9 +63,12 @@ ASTNode* Eval::evalAst(ASTNode* ast, Environment* env) return result; } else if (is(ast)) { - // TODO - VERIFY_NOT_REACHED(); - return nullptr; + auto result = new HashMap(); + auto elements = static_cast(ast)->elements(); + for (auto& element : elements) { + result->addElement(element.first, evalImpl(element.second, env)); + } + return result; } return ast; diff --git a/src/lexer.cpp b/src/lexer.cpp index 71e970b..91053d4 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -216,7 +216,7 @@ bool Lexer::consumeKeyword() bool Lexer::consumeValue() { size_t column = m_column; - std::string value = ""; + std::string value; static std::unordered_set exit = { '[', @@ -259,7 +259,7 @@ bool Lexer::consumeValue() bool Lexer::consumeComment() { size_t column = m_column; - std::string comment = ""; + std::string comment; ignore(); // ; diff --git a/src/printer.cpp b/src/printer.cpp index 8e17355..753d6c3 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -78,8 +78,9 @@ void Printer::dumpImpl(ASTNode* node) m_firstNode = false; m_previousNodeIsList = true; HashMap* hash_map = static_cast(node); - for (size_t i = 0; i < hash_map->nodes().size(); ++i) { - dumpImpl(hash_map->nodes()[i]); + for (auto element : hash_map->elements()) { + print("{} ", element.first.front() == 0x7f ? ":" + element.first.substr(1) : element.first); // 127 + dumpImpl(element.second); m_previousNodeIsList = false; } print("}}"); diff --git a/src/reader.cpp b/src/reader.cpp index d896a5f..97751c8 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -193,9 +193,27 @@ ASTNode* Reader::readHashMap() { ignore(); // { - HashMap* vector = new HashMap(); + HashMap* hash_map = new HashMap(); while (!isEOF() && peek().type != Token::Type::BraceClose) { - vector->addNode(readImpl()); + ASTNode* key = readImpl(); + ASTNode* value = readImpl(); + + if (!key && !value) { + break; + } + + if (!key || !value) { + Error::the().addError("hash-map requires an even-sized list"); + return nullptr; + } + + if (!is(key) && !is(key)) { + Error::the().addError(format("{} is not a string or keyword", key)); + return nullptr; + } + + std::string keyString = is(key) ? static_cast(key)->data() : static_cast(key)->keyword(); + hash_map->addElement(keyString, value); } if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // } @@ -203,7 +221,7 @@ ASTNode* Reader::readHashMap() m_is_unbalanced = true; } - return vector; + return hash_map; } ASTNode* Reader::readQuote()