Everywhere: Pass step2 tests by supporting hash-maps
This commit is contained in:
@@ -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)
|
String::String(const std::string& data)
|
||||||
: m_data(data)
|
: m_data(data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <typeinfo> // typeid
|
#include <typeinfo> // typeid
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ruc/format/formatter.h"
|
#include "ruc/format/formatter.h"
|
||||||
@@ -90,13 +91,21 @@ public:
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// {}
|
// {}
|
||||||
class HashMap final : public Collection {
|
class HashMap final : public ASTNode {
|
||||||
public:
|
public:
|
||||||
HashMap() = default;
|
HashMap() = default;
|
||||||
virtual ~HashMap() = default;
|
virtual ~HashMap() = default;
|
||||||
|
|
||||||
virtual bool isCollection() const override { return false; }
|
|
||||||
virtual bool isHashMap() const override { return true; }
|
virtual bool isHashMap() const override { return true; }
|
||||||
|
|
||||||
|
void addElement(const std::string& key, ASTNode* value);
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, ASTNode*>& 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<std::string, ASTNode*> m_elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|||||||
+6
-3
@@ -63,9 +63,12 @@ ASTNode* Eval::evalAst(ASTNode* ast, Environment* env)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if (is<HashMap>(ast)) {
|
else if (is<HashMap>(ast)) {
|
||||||
// TODO
|
auto result = new HashMap();
|
||||||
VERIFY_NOT_REACHED();
|
auto elements = static_cast<HashMap*>(ast)->elements();
|
||||||
return nullptr;
|
for (auto& element : elements) {
|
||||||
|
result->addElement(element.first, evalImpl(element.second, env));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ast;
|
return ast;
|
||||||
|
|||||||
+2
-2
@@ -216,7 +216,7 @@ bool Lexer::consumeKeyword()
|
|||||||
bool Lexer::consumeValue()
|
bool Lexer::consumeValue()
|
||||||
{
|
{
|
||||||
size_t column = m_column;
|
size_t column = m_column;
|
||||||
std::string value = "";
|
std::string value;
|
||||||
|
|
||||||
static std::unordered_set<char> exit = {
|
static std::unordered_set<char> exit = {
|
||||||
'[',
|
'[',
|
||||||
@@ -259,7 +259,7 @@ bool Lexer::consumeValue()
|
|||||||
bool Lexer::consumeComment()
|
bool Lexer::consumeComment()
|
||||||
{
|
{
|
||||||
size_t column = m_column;
|
size_t column = m_column;
|
||||||
std::string comment = "";
|
std::string comment;
|
||||||
|
|
||||||
ignore(); // ;
|
ignore(); // ;
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -78,8 +78,9 @@ void Printer::dumpImpl(ASTNode* node)
|
|||||||
m_firstNode = false;
|
m_firstNode = false;
|
||||||
m_previousNodeIsList = true;
|
m_previousNodeIsList = true;
|
||||||
HashMap* hash_map = static_cast<HashMap*>(node);
|
HashMap* hash_map = static_cast<HashMap*>(node);
|
||||||
for (size_t i = 0; i < hash_map->nodes().size(); ++i) {
|
for (auto element : hash_map->elements()) {
|
||||||
dumpImpl(hash_map->nodes()[i]);
|
print("{} ", element.first.front() == 0x7f ? ":" + element.first.substr(1) : element.first); // 127
|
||||||
|
dumpImpl(element.second);
|
||||||
m_previousNodeIsList = false;
|
m_previousNodeIsList = false;
|
||||||
}
|
}
|
||||||
print("}}");
|
print("}}");
|
||||||
|
|||||||
+21
-3
@@ -193,9 +193,27 @@ ASTNode* Reader::readHashMap()
|
|||||||
{
|
{
|
||||||
ignore(); // {
|
ignore(); // {
|
||||||
|
|
||||||
HashMap* vector = new HashMap();
|
HashMap* hash_map = new HashMap();
|
||||||
while (!isEOF() && peek().type != Token::Type::BraceClose) {
|
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<String>(key) && !is<Keyword>(key)) {
|
||||||
|
Error::the().addError(format("{} is not a string or keyword", key));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string keyString = is<String>(key) ? static_cast<String*>(key)->data() : static_cast<Keyword*>(key)->keyword();
|
||||||
|
hash_map->addElement(keyString, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
|
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
|
||||||
@@ -203,7 +221,7 @@ ASTNode* Reader::readHashMap()
|
|||||||
m_is_unbalanced = true;
|
m_is_unbalanced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vector;
|
return hash_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode* Reader::readQuote()
|
ASTNode* Reader::readQuote()
|
||||||
|
|||||||
Reference in New Issue
Block a user