Skip to content

Commit

Permalink
Ancestor iteration for LexicalScopes
Browse files Browse the repository at this point in the history
  • Loading branch information
asoffer committed Nov 17, 2023
1 parent 486a5b9 commit b2d46b5
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
1 change: 1 addition & 0 deletions ir/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ cc_library(
"//parse:node_index",
"//type",
"@asoffer_nth//nth/debug",
"@asoffer_nth//nth/utility:iterator_range",
"@com_google_absl//absl/container:flat_hash_map",
]
)
Expand Down
11 changes: 3 additions & 8 deletions ir/lexical_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ LexicalScope::Index LexicalScope::Index::Invalid() {
return Index(std::numeric_limits<Index::underlying_type>::max());
}

LexicalScope::Index LexicalScope::parent() const { return parent_; }

LexicalScope::DeclarationInfo const *LexicalScope::identifier(
Identifier id) const {
auto iter = identifiers_.find(id);
Expand All @@ -22,7 +20,7 @@ LexicalScope::DeclarationInfo const *LexicalScope::identifier(
LexicalScope::Index LexicalScopeTree::insert_child(
LexicalScope::Index parent_index) {
LexicalScope::Index index(scopes_.size());
scopes_.push_back(LexicalScope(parent_index));
scopes_.push_back(LexicalScope(index.value() - parent_index.value()));
return index;
}

Expand All @@ -42,11 +40,8 @@ LexicalScope const &LexicalScopeTree::operator[](

LexicalScope::DeclarationInfo const *LexicalScopeTree::identifier(
LexicalScope::Index index, Identifier id) const {
while (index != LexicalScope::Index::Invalid()) {
auto const &scope = scopes_[index.value()];
auto const *info = scope.identifier(id);
if (info) { return info; }
index = scope.parent();
for (auto const &scope : ancestors(index)) {
if (auto const *info = scope.identifier(id)) { return info; }
}
return nullptr;
}
Expand Down
67 changes: 61 additions & 6 deletions ir/lexical_scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "common/identifier.h"
#include "common/strong_identifier_type.h"
#include "nth/debug/debug.h"
#include "nth/utility/iterator_range.h"
#include "parse/node_index.h"
#include "type/type.h"

Expand All @@ -22,8 +23,6 @@ struct LexicalScope {
static Index Invalid();
};

Index parent() const;

struct DeclarationInfo {
ParseNodeIndex declaration;
ParseNodeIndex identifier;
Expand All @@ -40,11 +39,12 @@ struct LexicalScope {
private:
friend struct LexicalScopeTree;

explicit LexicalScope(Index parent_index) : parent_(parent_index) {}
explicit LexicalScope(uint32_t distance_to_parent)
: parent_distance_(distance_to_parent) {}

absl::flat_hash_map<Identifier, DeclarationInfo> identifiers_;

Index parent_;
uint32_t parent_distance_;
};

struct LexicalScopeTree {
Expand All @@ -53,16 +53,71 @@ struct LexicalScopeTree {
LexicalScope &root();
LexicalScope const &root() const;

private:
struct ancestor_iterator_base {
friend bool operator==(ancestor_iterator_base,
ancestor_iterator_base) = default;

protected:
explicit ancestor_iterator_base(LexicalScope const *scope)
: scope_(scope) {}

LexicalScope const *scope_;
};

public:
template <typename S>
struct ancestor_iterator_impl : ancestor_iterator_base {
ancestor_iterator_impl &operator++() {
LexicalScopeTree::ReplaceWithParent(scope_);
return *this;
}

ancestor_iterator_impl operator++(int) {
auto copy = *this;
++*this;
return copy;
}

S &operator*() const { return *const_cast<S *>(scope_); }
S *operator->() const { return const_cast<S *>(scope_); }

private:
friend struct LexicalScopeTree;
using ancestor_iterator_base::ancestor_iterator_base;
};

using ancestor_iterator = ancestor_iterator_impl<LexicalScope>;
using const_ancestor_iterator = ancestor_iterator_impl<LexicalScope const>;

auto ancestors(LexicalScope::Index index) const {
return nth::iterator_range(
const_ancestor_iterator(scopes_.data() + index.value()),
const_ancestor_iterator(scopes_.data() - 1));
}

auto ancestors(LexicalScope::Index index) {
return nth::iterator_range(
ancestor_iterator(scopes_.data() + index.value()),
ancestor_iterator(scopes_.data()));
}

LexicalScope &operator[](LexicalScope::Index index);
LexicalScope const &operator[](LexicalScope::Index index) const;

LexicalScope::DeclarationInfo const *identifier(LexicalScope::Index index,
Identifier id) const;

LexicalScopeTree()
: scopes_(1, LexicalScope(LexicalScope::Index::Invalid())) {}
LexicalScopeTree() : scopes_(1, LexicalScope(1)) {}

private:
template <typename>
friend struct ancestor_iterator_impl;

static void ReplaceWithParent(LexicalScope const *&scope) {
scope -= scope->parent_distance_;
}

std::vector<LexicalScope> scopes_;
};

Expand Down

0 comments on commit b2d46b5

Please sign in to comment.