Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lsp/cxx/lsp/cxx_document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ void CxxDocument::parse(std::string source) {

if (auto classType = type_cast<ClassType>(objectType)) {
auto classSymbol = classType->symbol();
for (auto member : classSymbol->members()) {
for (auto member : classSymbol->scope()->symbols()) {
if (!member->name()) continue;
auto item = d->completionItems.emplace_back();
item.label(to_string(member->name()));
Expand Down
2 changes: 1 addition & 1 deletion src/parser/cxx/name_lookup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ auto Lookup::lookupHelper(Scope* scope, const Name* name,

cache.insert(scope);

for (auto symbol : scope->get(name)) {
for (auto symbol : scope->find(name)) {
return symbol;
}

Expand Down
11 changes: 6 additions & 5 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <cxx/name_printer.h>
#include <cxx/names.h>
#include <cxx/scope.h>
#include <cxx/symbol_chain_view.h>
#include <cxx/symbol_instantiation.h>
#include <cxx/symbols.h>
#include <cxx/token.h>
Expand Down Expand Up @@ -754,7 +755,7 @@ struct Parser::DeclareSymbol {

void operator()(Symbol* symbol) {
if (auto f = symbol_cast<FunctionSymbol>(symbol)) {
for (Symbol* candidate : scope_->get(symbol->name())) {
for (Symbol* candidate : scope_->find(symbol->name())) {
if (auto currentFunction = symbol_cast<FunctionSymbol>(candidate)) {
auto ovl =
control()->newOverloadSetSymbol(candidate->enclosingScope(), {});
Expand Down Expand Up @@ -4561,8 +4562,8 @@ auto Parser::enterOrCreateNamespace(const Identifier* identifier,
if (!identifier) {
namespaceSymbol = parentNamespace->unnamedNamespace();
} else {
auto resolved =
parentScope->get(identifier) | std::views::filter(&Symbol::isNamespace);
auto resolved = parentScope->find(identifier) |
std::views::filter(&Symbol::isNamespace);
if (std::ranges::distance(resolved) == 1) {
namespaceSymbol =
symbol_cast<NamespaceSymbol>(*std::ranges::begin(resolved));
Expand Down Expand Up @@ -9309,7 +9310,7 @@ auto Parser::parse_class_head(ClassHead& classHead) -> bool {

if (id && !isTemplateSpecialization) {
for (auto previous :
scope_->get(id) | std::views::filter(&Symbol::isClass)) {
scope_->find(id) | std::views::filter(&Symbol::isClass)) {
if (auto previousClass = symbol_cast<ClassSymbol>(previous)) {
if (previousClass->isComplete()) {
parse_error(classHead.name->firstSourceLocation(),
Expand Down Expand Up @@ -11272,7 +11273,7 @@ auto Parser::convertName(UnqualifiedIdAST* id) -> const Name* {
}
auto Parser::getFunction(Scope* scope, const Name* name, const Type* type)
-> FunctionSymbol* {
for (auto candidate : scope->get(name)) {
for (auto candidate : scope->find(name)) {
if (auto function = symbol_cast<FunctionSymbol>(candidate)) {
if (control_->is_same(function->type(), type)) {
return function;
Expand Down
26 changes: 6 additions & 20 deletions src/parser/cxx/scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <cxx/names.h>
#include <cxx/scope.h>

// cxx
#include <cxx/names.h>
#include <cxx/symbols.h>

#include <algorithm>
Expand Down Expand Up @@ -70,17 +72,6 @@ struct AddTemplateSymbol {

} // namespace

auto Scope::MemberIterator::operator++() -> MemberIterator& {
symbol_ = symbol_->next();
return *this;
}

auto Scope::MemberIterator::operator++(int) -> MemberIterator {
auto it = *this;
symbol_ = symbol_->next();
return it;
}

Scope::Scope(Scope* parent) : parent_(parent) {}

Scope::~Scope() {}
Expand Down Expand Up @@ -163,25 +154,20 @@ void Scope::replaceSymbol(Symbol* symbol, Symbol* newSymbol) {
}
}

auto Scope::usingDirectives() const -> const std::vector<Scope*>& {
return usingDirectives_;
}

void Scope::addUsingDirective(Scope* scope) {
usingDirectives_.push_back(scope);
}

auto Scope::getHelper(const Name* name) const
-> std::pair<MemberIterator, MemberIterator> {
auto Scope::find(const Name* name) const -> SymbolChainView {
if (!symbols_.empty()) {
const auto h = std::hash<const void*>{}(name) % buckets_.size();
for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) {
if (symbol->name() == name) {
return {MemberIterator{symbol}, MemberIterator{}};
return SymbolChainView{symbol};
}
}
}
return {};
return SymbolChainView{nullptr};
}

} // namespace cxx
87 changes: 51 additions & 36 deletions src/parser/cxx/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,68 +21,46 @@
#pragma once

#include <cxx/names_fwd.h>
#include <cxx/symbol_chain_view.h>
#include <cxx/symbols.h>
#include <cxx/symbols_fwd.h>
#include <cxx/types_fwd.h>

#include <ranges>
#include <vector>

namespace cxx {

class SymbolChainView;

class Scope {
public:
class MemberIterator {
public:
using value_type = Symbol*;
using difference_type = std::ptrdiff_t;

MemberIterator() = default;
explicit MemberIterator(Symbol* symbol) : symbol_(symbol) {}

auto operator<=>(const MemberIterator&) const = default;

auto operator*() const -> Symbol* { return symbol_; }
auto operator++() -> MemberIterator&;
auto operator++(int) -> MemberIterator;

private:
Symbol* symbol_ = nullptr;
};

explicit Scope(Scope* parent);
~Scope();

[[nodiscard]] auto isEnumScope() const -> bool;
[[nodiscard]] auto isTemplateParametersScope() const -> bool;

[[nodiscard]] auto parent() const -> Scope* { return parent_; }
void setParent(Scope* parent) { parent_ = parent; }

[[nodiscard]] auto enclosingNonTemplateParametersScope() const -> Scope*;

[[nodiscard]] auto parent() const -> Scope* { return parent_; }
[[nodiscard]] auto owner() const -> ScopedSymbol* { return owner_; }
void setOwner(ScopedSymbol* owner) { owner_ = owner; }

[[nodiscard]] auto symbols() const -> const std::vector<Symbol*>& {
return symbols_;
}
[[nodiscard]] auto symbols() const { return std::views::all(symbols_); }

[[nodiscard]] auto get(const Name* name) const {
auto [first, last] = getHelper(name);
return std::ranges::subrange(first, last);
[[nodiscard]] auto usingDirectives() const {
return std::views::all(usingDirectives_);
}

void addSymbol(Symbol* symbol);
void replaceSymbol(Symbol* symbol, Symbol* newSymbol);
[[nodiscard]] auto find(const Name* name) const -> SymbolChainView;

[[nodiscard]] auto usingDirectives() const -> const std::vector<Scope*>&;
void setParent(Scope* parent) { parent_ = parent; }
void setOwner(ScopedSymbol* owner) { owner_ = owner; }

void addSymbol(Symbol* symbol);
void addUsingDirective(Scope* scope);

private:
[[nodiscard]] auto getHelper(const Name* name) const
-> std::pair<MemberIterator, MemberIterator>;
void replaceSymbol(Symbol* symbol, Symbol* newSymbol);

private:
void rehash();

private:
Expand All @@ -93,4 +71,41 @@ class Scope {
std::vector<Scope*> usingDirectives_;
};

namespace views {

constexpr auto class_or_namespaces =
std::views::filter(&Symbol::isClassOrNamespace) |
std::views::transform(
[](Symbol* s) { return static_cast<ScopedSymbol*>(s); });

constexpr auto enum_or_scoped_enums =
std::views::filter(&Symbol::isEnumOrScopedEnum) |
std::views::transform(
[](Symbol* s) { return static_cast<ScopedSymbol*>(s); });

constexpr const auto namespaces =
std::views::filter(&Symbol::isNamespace) |
std::views::transform(symbol_cast<NamespaceSymbol>);

constexpr auto concepts = std::views::filter(&Symbol::isConcept) |
std::views::transform(symbol_cast<ConceptSymbol>);

constexpr auto classes = std::views::filter(&Symbol::isClass) |
std::views::transform(symbol_cast<ClassSymbol>);

constexpr auto enums = std::views::filter(&Symbol::isEnum) |
std::views::transform(symbol_cast<EnumSymbol>);

constexpr auto scoped_enums =
std::views::filter(&Symbol::isScopedEnum) |
std::views::transform(symbol_cast<ScopedEnumSymbol>);

constexpr auto functions = std::views::filter(&Symbol::isFunction) |
std::views::transform(symbol_cast<FunctionSymbol>);

constexpr auto variables = std::views::filter(&Symbol::isVariable) |
std::views::transform(symbol_cast<VariableSymbol>);

} // namespace views

} // namespace cxx
31 changes: 31 additions & 0 deletions src/parser/cxx/symbol_chain_view.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2024 Roberto Raggi <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <cxx/symbol_chain_view.h>
#include <cxx/symbols.h>

namespace cxx {

auto SymbolChainView::Generator::operator++() -> Generator& {
symbol_ = symbol_->next();
return *this;
}

} // namespace cxx
66 changes: 66 additions & 0 deletions src/parser/cxx/symbol_chain_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2024 Roberto Raggi <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once

#include <cxx/symbols_fwd.h>

#include <ranges>

namespace cxx {

class SymbolChainView : public std::ranges::view_interface<SymbolChainView> {
public:
explicit SymbolChainView(Symbol* symbol) : symbol_{symbol} {}

auto begin() const { return Generator{symbol_}; }
auto end() const { return std::default_sentinel; }

private:
class Generator {
public:
using difference_type = std::ptrdiff_t;
using value_type = Symbol*;

explicit Generator(Symbol* symbol) : symbol_(symbol) {}

auto operator*() const -> Symbol* { return symbol_; }

auto operator++() -> Generator&;

auto operator++(int) -> Generator {
auto it = *this;
++*this;
return it;
}

auto operator==(const std::default_sentinel_t&) const -> bool {
return symbol_ == nullptr;
}

private:
Symbol* symbol_ = nullptr;
};

private:
Symbol* symbol_;
};

} // namespace cxx
Loading