From 6afb4f1cb7ddb1585283d5a0414a0c18eaabcf9a Mon Sep 17 00:00:00 2001 From: Mattias Ajander <mattias@ajander.se> Date: Wed, 2 Apr 2025 10:55:38 +0200 Subject: [PATCH] Implemented basic scope management --- include/ast/BlockNode.h | 2 ++ include/parser/Parser.h | 1 + include/parser/Scope.h | 32 ++++++++++++++++++++++---- include/utils/Common.h | 5 +++++ source/ast/BlockNode.cc | 4 ++++ source/parser/Scope.cc | 50 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 source/parser/Scope.cc diff --git a/include/ast/BlockNode.h b/include/ast/BlockNode.h index dbb6944..d1ec053 100644 --- a/include/ast/BlockNode.h +++ b/include/ast/BlockNode.h @@ -1,6 +1,7 @@ #pragma once #include "ast/Node.h" +#include "parser/Scope.h" namespace funk { @@ -9,6 +10,7 @@ class BlockNode : public Node { public: BlockNode(const SourceLocation& loc); + BlockNode(const SourceLocation& loc, const Vector<Node*>& statements); ~BlockNode(); void add(Node* statement); diff --git a/include/parser/Parser.h b/include/parser/Parser.h index add438b..48d6d31 100644 --- a/include/parser/Parser.h +++ b/include/parser/Parser.h @@ -7,6 +7,7 @@ #pragma once #include "lexer/Lexer.h" +#include "parser/Scope.h" #include "token/Token.h" #include "utils/Common.h" diff --git a/include/parser/Scope.h b/include/parser/Scope.h index 186f2b0..91ab262 100644 --- a/include/parser/Scope.h +++ b/include/parser/Scope.h @@ -1,4 +1,28 @@ -/* -Create a Scope class with a singleton accesor. See Logger for example of singleton. -Create a global scope with HasMap, some util functions? key string value NodeValue / LiteralNode. -*/ +#pragma once + +#include "ast/Node.h" +#include "logging/LogMacros.h" +#include "utils/Common.h" + +namespace funk +{ + +class Scope +{ +public: + static Scope& instance(); + + void push(); + void pop(); + + void add(const String& name, Node* node); + Node* get(const String& name) const; + +private: + Scope(); + ~Scope(); + Vector<HashMap<String, Node*>> scopes; + int depth{0}; +}; + +} // namespace funk diff --git a/include/utils/Common.h b/include/utils/Common.h index 1abd922..38da432 100644 --- a/include/utils/Common.h +++ b/include/utils/Common.h @@ -46,6 +46,11 @@ template <typename T> using Vector = std::vector<T>; */ template <typename K, typename V> using HashMap = std::unordered_map<K, V>; +/** + * @brief Macro for std::to_string. + */ +#define to_str(x) std::to_string(x) + /** * @brief Stores location information for source code elements. * Used for error reporting and debugging to identify where in the source code an element appears. diff --git a/source/ast/BlockNode.cc b/source/ast/BlockNode.cc index c8cd698..826cdfb 100644 --- a/source/ast/BlockNode.cc +++ b/source/ast/BlockNode.cc @@ -4,6 +4,8 @@ namespace funk { BlockNode::BlockNode(const SourceLocation& loc) : Node(loc), statements{} {} +BlockNode::BlockNode(const SourceLocation& loc, const Vector<Node*>& statements) : Node(loc), statements{statements} {} + BlockNode::~BlockNode() { for (Node* statement : statements) { delete statement; } @@ -21,8 +23,10 @@ Vector<Node*> BlockNode::get_statements() const Node* BlockNode::evaluate() const { + Scope::instance().push(); Node* result{}; for (Node* statement : statements) { result = statement->evaluate(); } + Scope::instance().pop(); return result; } diff --git a/source/parser/Scope.cc b/source/parser/Scope.cc new file mode 100644 index 0000000..bd38505 --- /dev/null +++ b/source/parser/Scope.cc @@ -0,0 +1,50 @@ +#include "parser/Scope.h" + +namespace funk +{ + +Scope::Scope() {} +Scope::~Scope() {} + +Scope& Scope::instance() +{ + static Scope instance; + return instance; +} + +void Scope::push() +{ + LOG_DEBUG("Pushing scope at depth " + to_str(depth) + " -> " + to_str(depth + 1)); + scopes.push_back({}); + depth++; +} + +void Scope::pop() +{ + LOG_DEBUG("Popping scope at depth " + to_str(depth) + " -> " + to_str(depth - 1)); + scopes.pop_back(); + depth--; +} + +void Scope::add(const String& name, Node* node) +{ + LOG_DEBUG("Registering symbol '" + name + "' with node " + node->to_s()); + scopes.back()[name] = node; +} + +Node* Scope::get(const String& name) const +{ + for (int i = scopes.size() - 1; i >= 0; i--) + { + LOG_DEBUG("Searching for symbol '" + name + "' at depth " + to_str(i)); + auto it = scopes[i].find(name); + if (it != scopes[i].end()) + { + LOG_DEBUG("Found symbol '" + name + "' at depth " + to_str(i)); + return it->second; + } + } + return nullptr; +} + +} // namespace funk -- GitLab