diff --git a/src/frontend/cxx/frontend.cc b/src/frontend/cxx/frontend.cc index ea0b0ec5..ece5608a 100644 --- a/src/frontend/cxx/frontend.cc +++ b/src/frontend/cxx/frontend.cc @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -439,7 +438,7 @@ void Frontend::Private::dumpTokens(std::ostream& out) { void Frontend::Private::dumpSymbols(std::ostream& out) { if (!cli.opt_dump_symbols) return; auto globalScope = unit_->globalScope(); - auto globalNamespace = globalScope->owner(); + auto globalNamespace = globalScope; cxx::dump(out, globalNamespace); } diff --git a/src/lsp/cxx/lsp/cxx_document.cc b/src/lsp/cxx/lsp/cxx_document.cc index 19c5232d..5c582555 100644 --- a/src/lsp/cxx/lsp/cxx_document.cc +++ b/src/lsp/cxx/lsp/cxx_document.cc @@ -28,10 +28,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff --git a/src/mlir/cxx/mlir/codegen.cc b/src/mlir/cxx/mlir/codegen.cc index fc694c7e..6cf16c2e 100644 --- a/src/mlir/cxx/mlir/codegen.cc +++ b/src/mlir/cxx/mlir/codegen.cc @@ -109,12 +109,10 @@ auto Codegen::findOrCreateFunction(FunctionSymbol* functionSymbol) std::vector inputTypes; std::vector resultTypes; - if (!functionSymbol->isStatic() && - functionSymbol->enclosingSymbol()->isClass()) { + if (!functionSymbol->isStatic() && functionSymbol->parent()->isClass()) { // if it is a non static member function, we need to add the `this` pointer - auto classSymbol = - symbol_cast(functionSymbol->enclosingSymbol()); + auto classSymbol = symbol_cast(functionSymbol->parent()); inputTypes.push_back(builder_.getType( convertType(classSymbol->type()))); diff --git a/src/mlir/cxx/mlir/codegen_declarations.cc b/src/mlir/cxx/mlir/codegen_declarations.cc index a193d3f9..ff7f43e8 100644 --- a/src/mlir/cxx/mlir/codegen_declarations.cc +++ b/src/mlir/cxx/mlir/codegen_declarations.cc @@ -24,10 +24,10 @@ #include #include #include -#include #include #include #include +#include // mlir #include @@ -40,7 +40,7 @@ namespace cxx { struct Codegen::DeclarationVisitor { Codegen& gen; - void allocateLocals(ScopedSymbol* block); + void allocateLocals(ScopeSymbol* block); auto operator()(SimpleDeclarationAST* ast) -> DeclarationResult; auto operator()(AsmDeclarationAST* ast) -> DeclarationResult; @@ -142,8 +142,8 @@ auto Codegen::lambdaSpecifier(LambdaSpecifierAST* ast) return {}; } -void Codegen::DeclarationVisitor::allocateLocals(ScopedSymbol* block) { - for (auto symbol : block->scope()->symbols()) { +void Codegen::DeclarationVisitor::allocateLocals(ScopeSymbol* block) { + for (auto symbol : views::members(block)) { if (auto nestedBlock = symbol_cast(symbol)) { allocateLocals(nestedBlock); continue; @@ -380,10 +380,8 @@ auto Codegen::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) mlir::Value thisValue; // if this is a non static member function, we need to allocate the `this` - if (!functionSymbol->isStatic() && - functionSymbol->enclosingSymbol()->isClass()) { - auto classSymbol = - symbol_cast(functionSymbol->enclosingSymbol()); + if (!functionSymbol->isStatic() && functionSymbol->parent()->isClass()) { + auto classSymbol = symbol_cast(functionSymbol->parent()); auto thisType = gen.convertType(classSymbol->type()); auto ptrType = gen.builder_.getType(thisType); @@ -396,13 +394,13 @@ auto Codegen::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) } FunctionParametersSymbol* params = nullptr; - for (auto member : ast->symbol->scope()->symbols()) { + for (auto member : views::members(ast->symbol)) { params = symbol_cast(member); if (!params) continue; int argc = 0; auto args = gen.entryBlock_->getArguments(); - for (auto param : params->scope()->symbols()) { + for (auto param : views::members(params)) { auto arg = symbol_cast(param); if (!arg) continue; diff --git a/src/mlir/cxx/mlir/codegen_expressions.cc b/src/mlir/cxx/mlir/codegen_expressions.cc index 560d9e98..8b3fad25 100644 --- a/src/mlir/cxx/mlir/codegen_expressions.cc +++ b/src/mlir/cxx/mlir/codegen_expressions.cc @@ -26,10 +26,10 @@ #include #include #include -#include #include #include #include +#include // mlir #include @@ -645,8 +645,8 @@ auto Codegen::ExpressionVisitor::operator()(MemberExpressionAST* ast) // todo: introduce ClassLayout to avoid linear searches and support c++ // class layout int fieldIndex = 0; - auto classSymbol = symbol_cast(field->enclosingSymbol()); - for (auto member : classSymbol->scope()->symbols()) { + auto classSymbol = symbol_cast(field->parent()); + for (auto member : cxx::views::members(classSymbol)) { auto f = symbol_cast(member); if (!f) continue; if (f->isStatic()) continue; diff --git a/src/mlir/cxx/mlir/codegen_units.cc b/src/mlir/cxx/mlir/codegen_units.cc index cb7a79e7..d9a35523 100644 --- a/src/mlir/cxx/mlir/codegen_units.cc +++ b/src/mlir/cxx/mlir/codegen_units.cc @@ -25,9 +25,9 @@ #include #include #include -#include #include #include +#include // mlir #include @@ -69,7 +69,7 @@ struct Codegen::UnitVisitor { UnitVisitor& p; void operator()(NamespaceSymbol* symbol) { - for (auto member : symbol->scope()->symbols()) { + for (auto member : views::members(symbol)) { visit(*this, member); } } @@ -86,7 +86,7 @@ struct Codegen::UnitVisitor { } if (!symbol->templateParameters()) { - for (auto member : symbol->scope()->symbols()) { + for (auto member : views::members(symbol)) { visit(*this, member); } } @@ -149,7 +149,7 @@ auto Codegen::UnitVisitor::operator()(TranslationUnitAST* ast) -> UnitResult { std::swap(gen.module_, module); - visit(visitor, gen.unit_->globalScope()->owner()); + visit(visitor, gen.unit_->globalScope()); #if false ForEachExternalDefinition forEachExternalDefinition; diff --git a/src/mlir/cxx/mlir/convert_type.cc b/src/mlir/cxx/mlir/convert_type.cc index 392eb2e8..b1f50706 100644 --- a/src/mlir/cxx/mlir/convert_type.cc +++ b/src/mlir/cxx/mlir/convert_type.cc @@ -26,10 +26,10 @@ #include #include #include -#include #include #include #include +#include #include @@ -294,7 +294,7 @@ auto Codegen::ConvertType::operator()(const ClassType* type) -> mlir::Type { std::vector memberTypes; - for (auto member : classSymbol->scope()->symbols()) { + for (auto member : views::members(classSymbol)) { auto field = symbol_cast(member); if (!field) continue; if (field->isStatic()) continue; diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index cfec9b11..840c70b6 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -58,7 +58,6 @@ add_library(cxx-parser cxx/parser.cc cxx/path.cc cxx/preprocessor.cc - cxx/scope.cc cxx/source_location.cc cxx/symbol_chain_view.cc cxx/symbol_printer.cc diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index 2c67e47d..58752ac0 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -228,7 +228,7 @@ class MemInitializerAST : public AST { class NestedNameSpecifierAST : public AST { public: using AST::AST; - ScopedSymbol* symbol = nullptr; + ScopeSymbol* symbol = nullptr; }; class NewInitializerAST : public AST { diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 23fff81e..6c44ade8 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -34,46 +34,7 @@ namespace cxx { -auto ASTRewriter::make_substitution( - TranslationUnit* unit, TemplateDeclarationAST* templateDecl, - List* templateArgumentList) - -> std::vector { - auto control = unit->control(); - auto interp = ASTInterpreter{unit}; - - std::vector templateArguments; - - for (auto arg : ListView{templateArgumentList}) { - if (auto exprArg = ast_cast(arg)) { - auto expr = exprArg->expression; - auto value = interp.evaluate(expr); - if (!value.has_value()) { -#if false - unit->error(arg->firstSourceLocation(), - "template argument is not a constant expression"); -#endif - continue; - } - - // ### need to set scope and location - auto templArg = control->newVariableSymbol(nullptr, {}); - templArg->setInitializer(expr); - templArg->setType(control->add_const(expr->type)); - templArg->setConstValue(value); - templateArguments.push_back(templArg); - } else if (auto typeArg = ast_cast(arg)) { - auto type = typeArg->typeId->type; - // ### need to set scope and location - auto templArg = control->newTypeAliasSymbol(nullptr, {}); - templArg->setType(type); - templateArguments.push_back(templArg); - } - } - - return templateArguments; -} - -ASTRewriter::ASTRewriter(TranslationUnit* unit, Scope* scope, +ASTRewriter::ASTRewriter(TranslationUnit* unit, ScopeSymbol* scope, const std::vector& templateArguments) : unit_(unit), templateArguments_(templateArguments), binder_(unit_) { binder_.setScope(scope); @@ -167,7 +128,7 @@ auto ASTRewriter::instantiateClassTemplate( return subst; } - auto parentScope = classSymbol->enclosingSymbol()->scope(); + auto parentScope = classSymbol->enclosingNonTemplateParametersScope(); auto rewriter = ASTRewriter{unit, parentScope, templateArguments}; @@ -222,7 +183,10 @@ auto ASTRewriter::instantiateTypeAliasTemplate( } #endif - auto parentScope = typeAliasSymbol->enclosingSymbol()->scope(); + auto parentScope = typeAliasSymbol->parent(); + while (parentScope->isTemplateParameters()) { + parentScope = parentScope->parent(); + } auto rewriter = ASTRewriter{unit, parentScope, templateArguments}; @@ -236,4 +200,43 @@ auto ASTRewriter::instantiateTypeAliasTemplate( return instance->symbol; } +auto ASTRewriter::make_substitution( + TranslationUnit* unit, TemplateDeclarationAST* templateDecl, + List* templateArgumentList) + -> std::vector { + auto control = unit->control(); + auto interp = ASTInterpreter{unit}; + + std::vector templateArguments; + + for (auto arg : ListView{templateArgumentList}) { + if (auto exprArg = ast_cast(arg)) { + auto expr = exprArg->expression; + auto value = interp.evaluate(expr); + if (!value.has_value()) { +#if false + unit->error(arg->firstSourceLocation(), + "template argument is not a constant expression"); +#endif + continue; + } + + // ### need to set scope and location + auto templArg = control->newVariableSymbol(nullptr, {}); + templArg->setInitializer(expr); + templArg->setType(control->add_const(expr->type)); + templArg->setConstValue(value); + templateArguments.push_back(templArg); + } else if (auto typeArg = ast_cast(arg)) { + auto type = typeArg->typeId->type; + // ### need to set scope and location + auto templArg = control->newTypeAliasSymbol(nullptr, {}); + templArg->setType(type); + templateArguments.push_back(templArg); + } + } + + return templateArguments; +} + } // namespace cxx diff --git a/src/parser/cxx/ast_rewriter.h b/src/parser/cxx/ast_rewriter.h index d9cd38bf..aa2aed3e 100644 --- a/src/parser/cxx/ast_rewriter.h +++ b/src/parser/cxx/ast_rewriter.h @@ -42,12 +42,7 @@ class ASTRewriter { TranslationUnit* unit, List* templateArgumentList, TypeAliasSymbol* typeAliasSymbol) -> TypeAliasSymbol*; - [[nodiscard]] static auto make_substitution( - TranslationUnit* unit, TemplateDeclarationAST* templateDecl, - List* templateArgumentList) - -> std::vector; - - explicit ASTRewriter(TranslationUnit* unit, Scope* scope, + explicit ASTRewriter(TranslationUnit* unit, ScopeSymbol* scope, const std::vector& templateArguments); ~ASTRewriter(); @@ -55,7 +50,9 @@ class ASTRewriter { return unit_; } - [[nodiscard]] auto declaration(DeclarationAST* ast) -> DeclarationAST*; + [[nodiscard]] auto declaration(DeclarationAST* ast, + TemplateDeclarationAST* templateHead = nullptr) + -> DeclarationAST*; private: [[nodiscard]] auto templateArguments() const @@ -76,6 +73,11 @@ class ASTRewriter { [[nodiscard]] auto restrictedToDeclarations() const -> bool; void setRestrictedToDeclarations(bool restrictedToDeclarations); + [[nodiscard]] static auto make_substitution( + TranslationUnit* unit, TemplateDeclarationAST* templateDecl, + List* templateArgumentList) + -> std::vector; + // run on the base nodes [[nodiscard]] auto unit(UnitAST* ast) -> UnitAST*; [[nodiscard]] auto statement(StatementAST* ast) -> StatementAST*; @@ -85,7 +87,9 @@ class ASTRewriter { [[nodiscard]] auto designator(DesignatorAST* ast) -> DesignatorAST*; [[nodiscard]] auto templateParameter(TemplateParameterAST* ast) -> TemplateParameterAST*; - [[nodiscard]] auto specifier(SpecifierAST* ast) -> SpecifierAST*; + [[nodiscard]] auto specifier(SpecifierAST* ast, + TemplateDeclarationAST* templateHead = nullptr) + -> SpecifierAST*; [[nodiscard]] auto ptrOperator(PtrOperatorAST* ast) -> PtrOperatorAST*; [[nodiscard]] auto coreDeclarator(CoreDeclaratorAST* ast) -> CoreDeclaratorAST*; diff --git a/src/parser/cxx/ast_rewriter_declarations.cc b/src/parser/cxx/ast_rewriter_declarations.cc index 7c157012..dc697759 100644 --- a/src/parser/cxx/ast_rewriter_declarations.cc +++ b/src/parser/cxx/ast_rewriter_declarations.cc @@ -23,6 +23,7 @@ // cxx #include #include +#include #include #include #include @@ -31,6 +32,11 @@ namespace cxx { struct ASTRewriter::DeclarationVisitor { ASTRewriter& rewrite; + TemplateDeclarationAST* templateHead = nullptr; + + DeclarationVisitor(ASTRewriter& rewrite, TemplateDeclarationAST* templateHead) + : rewrite(rewrite), templateHead(templateHead) {} + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; } @@ -169,9 +175,11 @@ struct ASTRewriter::RequirementVisitor { [[nodiscard]] auto operator()(NestedRequirementAST* ast) -> RequirementAST*; }; -auto ASTRewriter::declaration(DeclarationAST* ast) -> DeclarationAST* { +auto ASTRewriter::declaration(DeclarationAST* ast, + TemplateDeclarationAST* templateHead) + -> DeclarationAST* { if (!ast) return {}; - return visit(DeclarationVisitor{*this}, ast); + return visit(DeclarationVisitor{*this, templateHead}, ast); } auto ASTRewriter::templateParameter(TemplateParameterAST* ast) @@ -257,7 +265,7 @@ auto ASTRewriter::DeclarationVisitor::operator()(SimpleDeclarationAST* ast) auto declSpecifierListCtx = DeclSpecs{rewriter()}; for (auto declSpecifierList = ©->declSpecifierList; auto node : ListView{ast->declSpecifierList}) { - auto value = rewrite.specifier(node); + auto value = rewrite.specifier(node, templateHead); *declSpecifierList = make_list_node(arena(), value); declSpecifierList = &(*declSpecifierList)->next; declSpecifierListCtx.accept(value); @@ -550,6 +558,15 @@ auto ASTRewriter::DeclarationVisitor::operator()(TemplateDeclarationAST* ast) copy->templateLoc = ast->templateLoc; copy->lessLoc = ast->lessLoc; + auto _ = Binder::ScopeGuard{binder()}; + + auto templateParametersSymbol = control()->newTemplateParametersSymbol( + binder()->scope(), ast->symbol->location()); + + copy->symbol = templateParametersSymbol; + + binder()->setScope(templateParametersSymbol); + for (auto templateParameterList = ©->templateParameterList; auto node : ListView{ast->templateParameterList}) { auto value = rewrite.templateParameter(node); @@ -558,9 +575,9 @@ auto ASTRewriter::DeclarationVisitor::operator()(TemplateDeclarationAST* ast) } copy->greaterLoc = ast->greaterLoc; + copy->requiresClause = rewrite.requiresClause(ast->requiresClause); - copy->declaration = rewrite.declaration(ast->declaration); - copy->symbol = ast->symbol; + copy->declaration = rewrite.declaration(ast->declaration, copy); return copy; } @@ -892,7 +909,6 @@ auto ASTRewriter::TemplateParameterVisitor::operator()( TypenameTypeParameterAST* ast) -> TemplateParameterAST* { auto copy = make_node(arena()); - copy->symbol = ast->symbol; copy->depth = ast->depth; copy->index = ast->index; copy->classKeyLoc = ast->classKeyLoc; @@ -903,6 +919,8 @@ auto ASTRewriter::TemplateParameterVisitor::operator()( copy->identifier = ast->identifier; copy->isPack = ast->isPack; + binder()->bind(copy, copy->index, copy->depth); + return copy; } diff --git a/src/parser/cxx/ast_rewriter_declarators.cc b/src/parser/cxx/ast_rewriter_declarators.cc index 3a88109a..b4e28e1e 100644 --- a/src/parser/cxx/ast_rewriter_declarators.cc +++ b/src/parser/cxx/ast_rewriter_declarators.cc @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -208,7 +207,7 @@ auto ASTRewriter::initDeclarator(InitDeclaratorAST* ast, getDeclaratorType(translationUnit(), copy->declarator, declSpecs.type()); // ### fix scope - if (binder_.scope()->isClassScope()) { + if (binder_.scope()->isClass()) { auto symbol = binder_.declareMemberSymbol(copy->declarator, decl); copy->symbol = symbol; } else { diff --git a/src/parser/cxx/ast_rewriter_specifiers.cc b/src/parser/cxx/ast_rewriter_specifiers.cc index ecb0ece0..f70ffa3c 100644 --- a/src/parser/cxx/ast_rewriter_specifiers.cc +++ b/src/parser/cxx/ast_rewriter_specifiers.cc @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -36,6 +35,11 @@ namespace cxx { struct ASTRewriter::SpecifierVisitor { ASTRewriter& rewrite; + TemplateDeclarationAST* templateHead = nullptr; + + SpecifierVisitor(ASTRewriter& rewrite, TemplateDeclarationAST* templateHead) + : rewrite(rewrite), templateHead(templateHead) {} + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; } @@ -171,9 +175,11 @@ struct ASTRewriter::AttributeTokenVisitor { -> AttributeTokenAST*; }; -auto ASTRewriter::specifier(SpecifierAST* ast) -> SpecifierAST* { +auto ASTRewriter::specifier(SpecifierAST* ast, + TemplateDeclarationAST* templateHead) + -> SpecifierAST* { if (!ast) return {}; - auto specifier = visit(SpecifierVisitor{*this}, ast); + auto specifier = visit(SpecifierVisitor{*this, templateHead}, ast); return specifier; } @@ -779,13 +785,18 @@ auto ASTRewriter::SpecifierVisitor::operator()(ClassSpecifierAST* ast) classSymbol->setIsUnion(ast->symbol->isUnion()); classSymbol->setFinal(ast->isFinal); classSymbol->setDeclaration(copy); + classSymbol->setTemplateDeclaration(templateHead); + + if (templateHead) { + classSymbol->setTemplateParameters(binder()->currentTemplateParameters()); + } - if (ast->symbol != rewrite.binder().instantiatingSymbol()) { + if (ast->symbol == rewrite.binder().instantiatingSymbol()) { + ast->symbol->addSpecialization(rewrite.templateArguments(), classSymbol); + } else { // If we are not instantiating a template, we can add the class symbol to // the scope. binder()->declaringScope()->addSymbol(classSymbol); - } else { - ast->symbol->addSpecialization(rewrite.templateArguments(), classSymbol); } // enter the class scope diff --git a/src/parser/cxx/binder.cc b/src/parser/cxx/binder.cc index 3cb554f5..84a830cc 100644 --- a/src/parser/cxx/binder.cc +++ b/src/parser/cxx/binder.cc @@ -30,11 +30,11 @@ #include #include #include -#include #include #include #include #include +#include #include @@ -79,9 +79,7 @@ void Binder::warning(SourceLocation loc, std::string message) { auto Binder::inTemplate() const -> bool { return inTemplate_; } auto Binder::currentTemplateParameters() const -> TemplateParametersSymbol* { - auto templateParameters = - symbol_cast(scope()->owner()); - + auto templateParameters = symbol_cast(scope()); return templateParameters; } @@ -97,32 +95,30 @@ void Binder::setInstantiatingSymbol(Symbol* symbol) { instantiatingSymbol_ = symbol; } -auto Binder::declaringScope() const -> Scope* { +auto Binder::declaringScope() const -> ScopeSymbol* { if (!scope_) return nullptr; - if (!scope_->isTemplateParametersScope()) return scope_; + if (!scope_->isTemplateParameters()) return scope_; return scope_->enclosingNonTemplateParametersScope(); } -auto Binder::scope() const -> Scope* { return scope_; } +auto Binder::scope() const -> ScopeSymbol* { return scope_; } -void Binder::setScope(Scope* scope) { +void Binder::setScope(ScopeSymbol* scope) { scope_ = scope; inTemplate_ = false; for (auto current = scope_; current; current = current->parent()) { - if (current->isTemplateParametersScope()) { + if (current->isTemplateParameters()) { inTemplate_ = true; break; } } } -void Binder::setScope(ScopedSymbol* symbol) { setScope(symbol->scope()); } - auto Binder::enterBlock(SourceLocation loc) -> BlockSymbol* { auto blockSymbol = control()->newBlockSymbol(scope_, loc); scope_->addSymbol(blockSymbol); - setScope(blockSymbol->scope()); + setScope(blockSymbol); return blockSymbol; } @@ -176,7 +172,7 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs, auto parent = ast->nestedNameSpecifier->symbol; if (parent && parent->isClassOrNamespace()) { - setScope(static_cast(parent)); + setScope(static_cast(parent)); } } @@ -203,16 +199,11 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs, auto classSymbol = symbol_cast(candidate); - if (classSymbol) { - // validate the resolved class symbol - - if (isDeclaration) { - // if the class is already declared, we need to check if the - if (classSymbol->enclosingScope() != declaringScope()) { - // the class is declared in a different scope - classSymbol = nullptr; - } - } + if (classSymbol && isDeclaration && + classSymbol->enclosingNonTemplateParametersScope() != + declaringScope()) { + // the class is declared in a different scope + classSymbol = nullptr; } if (!classSymbol) { @@ -245,7 +236,7 @@ void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) { auto parent = ast->nestedNameSpecifier->symbol; if (parent && parent->isClassOrNamespace()) { - setScope(static_cast(parent)); + setScope(static_cast(parent)); } } @@ -264,7 +255,7 @@ void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) { ClassSymbol* primaryTemplate = nullptr; - if (templateId && scope()->isTemplateParametersScope()) { + if (templateId && scope()->isTemplateParameters()) { for (auto candidate : declaringScope()->find(className) | views::classes) { primaryTemplate = candidate; break; @@ -388,8 +379,8 @@ void Binder::bind(EnumeratorAST* ast, const Type* type, ast->symbol->setValue(value); scope()->addSymbol(symbol); - if (auto enumSymbol = symbol_cast(scope()->owner())) { - auto parentScope = enumSymbol->enclosingScope(); + if (auto enumSymbol = symbol_cast(scope())) { + auto parentScope = enumSymbol->parent(); auto u = control()->newUsingDeclarationSymbol(parentScope, ast->identifierLoc); @@ -403,8 +394,8 @@ void Binder::bind(EnumeratorAST* ast, const Type* type, // in C mode - if (auto enumSymbol = symbol_cast(scope()->owner())) { - auto parentScope = enumSymbol->enclosingScope(); + if (auto enumSymbol = symbol_cast(scope())) { + auto parentScope = enumSymbol->parent(); auto enumeratorSymbol = control()->newEnumeratorSymbol(parentScope, ast->identifierLoc); @@ -589,14 +580,14 @@ void Binder::bind(LambdaExpressionAST* ast) { void Binder::complete(LambdaExpressionAST* ast) { if (auto params = ast->parameterDeclarationClause) { - auto lambdaScope = ast->symbol->scope(); + auto lambdaScope = ast->symbol; lambdaScope->addSymbol(params->functionParametersSymbol); setScope(params->functionParametersSymbol); } else { setScope(ast->symbol); } - auto parentScope = ast->symbol->enclosingScope(); + auto parentScope = ast->symbol->parent(); parentScope->addSymbol(ast->symbol); const Type* returnType = control()->getAutoType(); @@ -649,11 +640,11 @@ void Binder::bind(ParameterDeclarationClauseAST* ast) { void Binder::bind(UsingDirectiveAST* ast) { auto id = ast->unqualifiedId->identifier; - NamespaceSymbol* namespaceSymbol = + auto namespaceSymbol = Lookup{scope()}.lookupNamespace(ast->nestedNameSpecifier, id); if (namespaceSymbol) { - scope()->addUsingDirective(namespaceSymbol->scope()); + scope()->addUsingDirective(namespaceSymbol); } else { error(ast->unqualifiedId->firstSourceLocation(), std::format("'{}' is not a namespace name", id->name())); @@ -704,8 +695,8 @@ auto Binder::declareFunction(DeclaratorAST* declarator, const Decl& decl) auto parentScope = scope(); - if (parentScope->isBlockScope()) { - parentScope = parentScope->enclosingNamespaceScope(); + if (parentScope->isBlock()) { + parentScope = parentScope->enclosingNamespace(); } auto functionSymbol = control()->newFunctionSymbol(scope(), decl.location()); @@ -720,7 +711,7 @@ auto Binder::declareFunction(DeclaratorAST* declarator, const Decl& decl) functionSymbol->setTemplateParameters(currentTemplateParameters()); if (isConstructor(functionSymbol)) { - auto enclosingClass = symbol_cast(scope()->owner()); + auto enclosingClass = symbol_cast(scope()); if (enclosingClass) { enclosingClass->addConstructor(functionSymbol); @@ -830,15 +821,14 @@ void Binder::applySpecifiers(FieldSymbol* symbol, const DeclSpecs& specs) { auto Binder::isConstructor(Symbol* symbol) const -> bool { auto functionSymbol = symbol_cast(symbol); if (!functionSymbol) return false; - if (!functionSymbol->enclosingScope()) return false; - auto classSymbol = - symbol_cast(functionSymbol->enclosingScope()->owner()); + if (!functionSymbol->parent()) return false; + auto classSymbol = symbol_cast(functionSymbol->parent()); if (!classSymbol) return false; if (classSymbol->name() != functionSymbol->name()) return false; return true; } -auto Binder::resolveNestedNameSpecifier(Symbol* symbol) -> ScopedSymbol* { +auto Binder::resolveNestedNameSpecifier(Symbol* symbol) -> ScopeSymbol* { if (auto classSymbol = symbol_cast(symbol)) return classSymbol; if (auto namespaceSymbol = symbol_cast(symbol)) @@ -909,7 +899,7 @@ void Binder::bind(IdExpressionAST* ast) { } } -auto Binder::getFunction(Scope* scope, const Name* name, const Type* type) +auto Binder::getFunction(ScopeSymbol* scope, const Name* name, const Type* type) -> FunctionSymbol* { auto parentScope = scope; @@ -917,7 +907,7 @@ auto Binder::getFunction(Scope* scope, const Name* name, const Type* type) parentScope = parentScope->parent(); } - if (auto parentClass = symbol_cast(parentScope->owner()); + if (auto parentClass = symbol_cast(parentScope); parentClass && parentClass->name() == name) { for (auto ctor : parentClass->constructors()) { if (control()->is_same(ctor->type(), type)) { diff --git a/src/parser/cxx/binder.h b/src/parser/cxx/binder.h index 3a1022e7..f648c8f9 100644 --- a/src/parser/cxx/binder.h +++ b/src/parser/cxx/binder.h @@ -51,15 +51,14 @@ class Binder { void error(SourceLocation loc, std::string message); void warning(SourceLocation loc, std::string message); - [[nodiscard]] auto scope() const -> Scope*; - void setScope(Scope* scope); - void setScope(ScopedSymbol* symbol); + [[nodiscard]] auto scope() const -> ScopeSymbol*; + void setScope(ScopeSymbol* scope); [[nodiscard]] auto isInstantiating() const -> bool; [[nodiscard]] auto instantiatingSymbol() const -> Symbol*; void setInstantiatingSymbol(Symbol* symbol); - [[nodiscard]] auto declaringScope() const -> Scope*; + [[nodiscard]] auto declaringScope() const -> ScopeSymbol*; [[nodiscard]] auto currentTemplateParameters() const -> TemplateParametersSymbol*; @@ -141,23 +140,22 @@ class Binder { UnqualifiedIdAST* unqualifiedId, bool checkTemplates) -> Symbol*; - [[nodiscard]] auto resolveNestedNameSpecifier(Symbol* symbol) - -> ScopedSymbol*; + [[nodiscard]] auto resolveNestedNameSpecifier(Symbol* symbol) -> ScopeSymbol*; - [[nodiscard]] auto getFunction(Scope* scope, const Name* name, + [[nodiscard]] auto getFunction(ScopeSymbol* scope, const Name* name, const Type* type) -> FunctionSymbol*; class ScopeGuard { public: Binder* p = nullptr; - Scope* savedScope = nullptr; + ScopeSymbol* savedScope = nullptr; ScopeGuard(const ScopeGuard&) = delete; auto operator=(const ScopeGuard&) -> ScopeGuard& = delete; ScopeGuard() = default; - explicit ScopeGuard(Binder* p, Scope* scope = nullptr) + explicit ScopeGuard(Binder* p, ScopeSymbol* scope = nullptr) : p(p), savedScope(p->scope_) { if (scope) p->setScope(scope); } @@ -170,7 +168,7 @@ class Binder { private: TranslationUnit* unit_ = nullptr; - Scope* scope_ = nullptr; + ScopeSymbol* scope_ = nullptr; Symbol* instantiatingSymbol_ = nullptr; bool inTemplate_ = false; bool reportErrors_ = true; diff --git a/src/parser/cxx/control.cc b/src/parser/cxx/control.cc index 5649624e..91c04669 100644 --- a/src/parser/cxx/control.cc +++ b/src/parser/cxx/control.cc @@ -482,29 +482,29 @@ auto Control::getScopedEnumType(ScopedEnumSymbol* symbol) return &*d->scopedEnumTypes.emplace(symbol).first; } -auto Control::newNamespaceSymbol(Scope* enclosingScope, SourceLocation loc) - -> NamespaceSymbol* { +auto Control::newNamespaceSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> NamespaceSymbol* { auto symbol = &d->namespaceSymbols.emplace_front(enclosingScope); symbol->setType(getNamespaceType(symbol)); symbol->setLocation(loc); return symbol; } -auto Control::newConceptSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newConceptSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> ConceptSymbol* { auto symbol = &d->conceptSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newBaseClassSymbol(Scope* enclosingScope, SourceLocation loc) - -> BaseClassSymbol* { +auto Control::newBaseClassSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> BaseClassSymbol* { auto symbol = &d->baseClassSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newClassSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newClassSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> ClassSymbol* { auto symbol = &d->classSymbols.emplace_front(enclosingScope); symbol->setType(getClassType(symbol)); @@ -512,7 +512,7 @@ auto Control::newClassSymbol(Scope* enclosingScope, SourceLocation loc) return symbol; } -auto Control::newEnumSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newEnumSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> EnumSymbol* { auto symbol = &d->enumSymbols.emplace_front(enclosingScope); symbol->setType(getEnumType(symbol)); @@ -520,37 +520,37 @@ auto Control::newEnumSymbol(Scope* enclosingScope, SourceLocation loc) return symbol; } -auto Control::newScopedEnumSymbol(Scope* enclosingScope, SourceLocation loc) - -> ScopedEnumSymbol* { +auto Control::newScopedEnumSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> ScopedEnumSymbol* { auto symbol = &d->scopedEnumSymbols.emplace_front(enclosingScope); symbol->setType(getScopedEnumType(symbol)); symbol->setLocation(loc); return symbol; } -auto Control::newOverloadSetSymbol(Scope* enclosingScope, SourceLocation loc) - -> OverloadSetSymbol* { +auto Control::newOverloadSetSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> OverloadSetSymbol* { auto symbol = &d->overloadSetSymbols.emplace_front(enclosingScope); symbol->setType(getOverloadSetType(symbol)); symbol->setLocation(loc); return symbol; } -auto Control::newFunctionSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newFunctionSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> FunctionSymbol* { auto symbol = &d->functionSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newLambdaSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newLambdaSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> LambdaSymbol* { auto symbol = &d->lambdaSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newFunctionParametersSymbol(Scope* enclosingScope, +auto Control::newFunctionParametersSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> FunctionParametersSymbol* { auto symbol = &d->functionParametersSymbol.emplace_front(enclosingScope); @@ -558,7 +558,7 @@ auto Control::newFunctionParametersSymbol(Scope* enclosingScope, return symbol; } -auto Control::newTemplateParametersSymbol(Scope* enclosingScope, +auto Control::newTemplateParametersSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> TemplateParametersSymbol* { auto symbol = &d->templateParametersSymbol.emplace_front(enclosingScope); @@ -566,50 +566,52 @@ auto Control::newTemplateParametersSymbol(Scope* enclosingScope, return symbol; } -auto Control::newBlockSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newBlockSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> BlockSymbol* { auto symbol = &d->blockSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newTypeAliasSymbol(Scope* enclosingScope, SourceLocation loc) - -> TypeAliasSymbol* { +auto Control::newTypeAliasSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> TypeAliasSymbol* { auto symbol = &d->typeAliasSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newVariableSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newVariableSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> VariableSymbol* { auto symbol = &d->variableSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newFieldSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newFieldSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> FieldSymbol* { auto symbol = &d->fieldSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newParameterSymbol(Scope* enclosingScope, SourceLocation loc) - -> ParameterSymbol* { +auto Control::newParameterSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> ParameterSymbol* { auto symbol = &d->parameterSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newParameterPackSymbol(Scope* enclosingScope, SourceLocation loc) +auto Control::newParameterPackSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> ParameterPackSymbol* { auto symbol = &d->parameterPackSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newTypeParameterSymbol(Scope* enclosingScope, SourceLocation loc, - int index, int depth, bool isParameterPack) +auto Control::newTypeParameterSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc, int index, int depth, + bool isParameterPack) -> TypeParameterSymbol* { auto symbol = &d->typeParameterSymbols.emplace_front(enclosingScope); symbol->setType(getTypeParameterType(index, depth, isParameterPack)); @@ -618,7 +620,7 @@ auto Control::newTypeParameterSymbol(Scope* enclosingScope, SourceLocation loc, } auto Control::newTemplateTypeParameterSymbol( - Scope* enclosingScope, SourceLocation loc, int index, int depth, + ScopeSymbol* enclosingScope, SourceLocation loc, int index, int depth, bool isPack, std::vector parameters) -> TemplateTypeParameterSymbol* { auto symbol = &d->templateTypeParameterSymbols.emplace_front(enclosingScope); @@ -628,7 +630,7 @@ auto Control::newTemplateTypeParameterSymbol( return symbol; } -auto Control::newNonTypeParameterSymbol(Scope* enclosingScope, +auto Control::newNonTypeParameterSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> NonTypeParameterSymbol* { auto symbol = &d->nonTypeParameterSymbols.emplace_front(enclosingScope); @@ -636,7 +638,7 @@ auto Control::newNonTypeParameterSymbol(Scope* enclosingScope, return symbol; } -auto Control::newConstraintTypeParameterSymbol(Scope* enclosingScope, +auto Control::newConstraintTypeParameterSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> ConstraintTypeParameterSymbol* { auto symbol = @@ -645,14 +647,14 @@ auto Control::newConstraintTypeParameterSymbol(Scope* enclosingScope, return symbol; } -auto Control::newEnumeratorSymbol(Scope* enclosingScope, SourceLocation loc) - -> EnumeratorSymbol* { +auto Control::newEnumeratorSymbol(ScopeSymbol* enclosingScope, + SourceLocation loc) -> EnumeratorSymbol* { auto symbol = &d->enumeratorSymbols.emplace_front(enclosingScope); symbol->setLocation(loc); return symbol; } -auto Control::newUsingDeclarationSymbol(Scope* enclosingScope, +auto Control::newUsingDeclarationSymbol(ScopeSymbol* enclosingScope, SourceLocation loc) -> UsingDeclarationSymbol* { auto symbol = &d->usingDeclarationSymbols.emplace_front(enclosingScope); diff --git a/src/parser/cxx/control.h b/src/parser/cxx/control.h index fdd8750e..2e2cf5f7 100644 --- a/src/parser/cxx/control.h +++ b/src/parser/cxx/control.h @@ -158,76 +158,76 @@ class Control { [[nodiscard]] auto getScopedEnumType(ScopedEnumSymbol* symbol) -> const ScopedEnumType*; - [[nodiscard]] auto newNamespaceSymbol(Scope* enclosingScope, + [[nodiscard]] auto newNamespaceSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> NamespaceSymbol*; - [[nodiscard]] auto newConceptSymbol(Scope* enclosingScope, + [[nodiscard]] auto newConceptSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ConceptSymbol*; - [[nodiscard]] auto newBaseClassSymbol(Scope* enclosingScope, + [[nodiscard]] auto newBaseClassSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> BaseClassSymbol*; - [[nodiscard]] auto newClassSymbol(Scope* enclosingScope, + [[nodiscard]] auto newClassSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ClassSymbol*; - [[nodiscard]] auto newEnumSymbol(Scope* enclosingScope, + [[nodiscard]] auto newEnumSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> EnumSymbol*; - [[nodiscard]] auto newScopedEnumSymbol(Scope* enclosingScope, + [[nodiscard]] auto newScopedEnumSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ScopedEnumSymbol*; - [[nodiscard]] auto newOverloadSetSymbol(Scope* enclosingScope, + [[nodiscard]] auto newOverloadSetSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> OverloadSetSymbol*; - [[nodiscard]] auto newFunctionSymbol(Scope* enclosingScope, + [[nodiscard]] auto newFunctionSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> FunctionSymbol*; - [[nodiscard]] auto newLambdaSymbol(Scope* enclosingScope, + [[nodiscard]] auto newLambdaSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> LambdaSymbol*; - [[nodiscard]] auto newFunctionParametersSymbol(Scope* enclosingScope, + [[nodiscard]] auto newFunctionParametersSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> FunctionParametersSymbol*; - [[nodiscard]] auto newTemplateParametersSymbol(Scope* enclosingScope, + [[nodiscard]] auto newTemplateParametersSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> TemplateParametersSymbol*; - [[nodiscard]] auto newBlockSymbol(Scope* enclosingScope, + [[nodiscard]] auto newBlockSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> BlockSymbol*; - [[nodiscard]] auto newTypeAliasSymbol(Scope* enclosingScope, + [[nodiscard]] auto newTypeAliasSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> TypeAliasSymbol*; - [[nodiscard]] auto newVariableSymbol(Scope* enclosingScope, + [[nodiscard]] auto newVariableSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> VariableSymbol*; - [[nodiscard]] auto newFieldSymbol(Scope* enclosingScope, + [[nodiscard]] auto newFieldSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> FieldSymbol*; - [[nodiscard]] auto newParameterSymbol(Scope* enclosingScope, + [[nodiscard]] auto newParameterSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ParameterSymbol*; - [[nodiscard]] auto newParameterPackSymbol(Scope* enclosingScope, + [[nodiscard]] auto newParameterPackSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ParameterPackSymbol*; - [[nodiscard]] auto newTypeParameterSymbol(Scope* enclosingScope, + [[nodiscard]] auto newTypeParameterSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation, int index, int depth, bool isParameterPack) -> TypeParameterSymbol*; - [[nodiscard]] auto newNonTypeParameterSymbol(Scope* enclosingScope, + [[nodiscard]] auto newNonTypeParameterSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> NonTypeParameterSymbol*; [[nodiscard]] auto newTemplateTypeParameterSymbol( - Scope* enclosingScope, SourceLocation sourceLocation, int index, + ScopeSymbol* enclosingScope, SourceLocation sourceLocation, int index, int depth, bool isPack, std::vector parameters) -> TemplateTypeParameterSymbol*; [[nodiscard]] auto newConstraintTypeParameterSymbol( - Scope* enclosingScope, SourceLocation sourceLocation) + ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> ConstraintTypeParameterSymbol*; - [[nodiscard]] auto newEnumeratorSymbol(Scope* enclosingScope, + [[nodiscard]] auto newEnumeratorSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> EnumeratorSymbol*; - [[nodiscard]] auto newUsingDeclarationSymbol(Scope* enclosingScope, + [[nodiscard]] auto newUsingDeclarationSymbol(ScopeSymbol* enclosingScope, SourceLocation sourceLocation) -> UsingDeclarationSymbol*; diff --git a/src/parser/cxx/decl.cc b/src/parser/cxx/decl.cc index a20904bc..77500929 100644 --- a/src/parser/cxx/decl.cc +++ b/src/parser/cxx/decl.cc @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -366,7 +365,7 @@ auto Decl::getNestedNameSpecifier() const -> NestedNameSpecifierAST* { return declaratorId->nestedNameSpecifier; } -auto Decl::getScope() const -> Scope* { +auto Decl::getScope() const -> ScopeSymbol* { auto nestedNameSpecifier = getNestedNameSpecifier(); if (!nestedNameSpecifier) return nullptr; @@ -379,11 +378,10 @@ auto Decl::getScope() const -> Scope* { } } - if (auto classSymbol = symbol_cast(symbol)) - return classSymbol->scope(); + if (auto classSymbol = symbol_cast(symbol)) return classSymbol; if (auto namespaceSymbol = symbol_cast(symbol)) - return namespaceSymbol->scope(); + return namespaceSymbol; return nullptr; } diff --git a/src/parser/cxx/decl.h b/src/parser/cxx/decl.h index ce50b3e3..cb8dbf7e 100644 --- a/src/parser/cxx/decl.h +++ b/src/parser/cxx/decl.h @@ -43,7 +43,7 @@ class Decl { [[nodiscard]] auto location() const -> SourceLocation; [[nodiscard]] auto getName() const -> const Name*; [[nodiscard]] auto getNestedNameSpecifier() const -> NestedNameSpecifierAST*; - [[nodiscard]] auto getScope() const -> Scope*; + [[nodiscard]] auto getScope() const -> ScopeSymbol*; }; [[nodiscard]] auto getDeclaratorId(DeclaratorAST* declarator) diff --git a/src/parser/cxx/external_name_encoder.cc b/src/parser/cxx/external_name_encoder.cc index 3b23a845..dbb96251 100644 --- a/src/parser/cxx/external_name_encoder.cc +++ b/src/parser/cxx/external_name_encoder.cc @@ -32,13 +32,13 @@ namespace { [[nodiscard]] auto is_global_namespace(Symbol* symbol) -> bool { if (!symbol) return false; if (!symbol->isNamespace()) return false; - if (symbol->enclosingSymbol()) return false; + if (symbol->parent()) return false; return true; } [[nodiscard]] auto enclosing_class_or_namespace(Symbol* symbol) -> Symbol* { if (!symbol) return nullptr; - auto parent = symbol->enclosingSymbol(); + auto parent = symbol->parent(); if (!parent) return nullptr; if (!parent->isClassOrNamespace()) return nullptr; return parent; @@ -365,7 +365,7 @@ struct ExternalNameEncoder::EncodeUnqualifiedName { auto argc = functionType->parameterTypes().size(); if (argc == 0) unary = true; - else if (argc == 1 && !function->enclosingSymbol()->isClass()) + else if (argc == 1 && !function->parent()->isClass()) unary = true; break; } @@ -581,9 +581,9 @@ auto ExternalNameEncoder::encodeFunction(FunctionSymbol* function) const auto id = name_cast(function->name()); - if (id && (function->hasCLinkage() || - (id->name() == "main" && - is_global_namespace(function->enclosingSymbol())))) { + if (id && + (function->hasCLinkage() || + (id->name() == "main" && is_global_namespace(function->parent())))) { out(id->name()); } else { out("_Z"); diff --git a/src/parser/cxx/name_lookup.cc b/src/parser/cxx/name_lookup.cc index 2d4b5475..54bad1ed 100644 --- a/src/parser/cxx/name_lookup.cc +++ b/src/parser/cxx/name_lookup.cc @@ -23,13 +23,13 @@ // cxx #include #include -#include #include #include +#include namespace cxx { -Lookup::Lookup(Scope* scope) : scope_(scope) {} +Lookup::Lookup(ScopeSymbol* scope) : scope_(scope) {} auto Lookup::operator()(const Name* name, const std::function& accept) const @@ -47,7 +47,7 @@ auto Lookup::operator()(NestedNameSpecifierAST* nestedNameSpecifier, auto Lookup::unqualifiedLookup(const Name* name, const std::function& accept) const -> Symbol* { - std::unordered_set cache; + std::unordered_set cache; for (auto current = scope_; current; current = current->parent()) { if (auto symbol = lookupHelper(current, name, cache, accept)) { return symbol; @@ -56,50 +56,50 @@ auto Lookup::unqualifiedLookup(const Name* name, return nullptr; } -auto Lookup::qualifiedLookup(Scope* scope, const Name* name, +auto Lookup::qualifiedLookup(ScopeSymbol* scope, const Name* name, const std::function& accept) const -> Symbol* { - std::unordered_set cache; + std::unordered_set cache; return lookupHelper(scope, name, cache, accept); } -auto Lookup::qualifiedLookup(Symbol* scopedSymbol, const Name* name, +auto Lookup::qualifiedLookup(Symbol* scopeSymbol, const Name* name, const std::function& accept) const -> Symbol* { - if (!scopedSymbol) return nullptr; - switch (scopedSymbol->kind()) { + if (!scopeSymbol) return nullptr; + switch (scopeSymbol->kind()) { case SymbolKind::kNamespace: - return qualifiedLookup( - symbol_cast(scopedSymbol)->scope(), name, accept); + return qualifiedLookup(symbol_cast(scopeSymbol), name, + accept); case SymbolKind::kClass: - return qualifiedLookup(symbol_cast(scopedSymbol)->scope(), - name, accept); + return qualifiedLookup(symbol_cast(scopeSymbol), name, + accept); case SymbolKind::kEnum: - return qualifiedLookup(symbol_cast(scopedSymbol)->scope(), - name, accept); + return qualifiedLookup(symbol_cast(scopeSymbol), name, + accept); case SymbolKind::kScopedEnum: - return qualifiedLookup( - symbol_cast(scopedSymbol)->scope(), name, accept); + return qualifiedLookup(symbol_cast(scopeSymbol), name, + accept); case SymbolKind::kTypeAlias: { - auto alias = symbol_cast(scopedSymbol); + auto alias = symbol_cast(scopeSymbol); if (auto classType = type_cast(alias->type())) { auto classSymbol = classType->symbol(); - return qualifiedLookup(classSymbol->scope(), name, accept); + return qualifiedLookup(classSymbol, name, accept); } if (auto enumType = type_cast(alias->type())) { auto enumSymbol = enumType->symbol(); - return qualifiedLookup(enumSymbol->scope(), name, accept); + return qualifiedLookup(enumSymbol, name, accept); } if (auto scopedEnumType = type_cast(alias->type())) { auto scopedEnumSymbol = scopedEnumType->symbol(); - return qualifiedLookup(scopedEnumSymbol->scope(), name, accept); + return qualifiedLookup(scopedEnumSymbol, name, accept); } return nullptr; @@ -120,8 +120,8 @@ auto Lookup::lookup(NestedNameSpecifierAST* nestedNameSpecifier, return qualifiedLookup(nestedNameSpecifier->symbol, name, accept); } -auto Lookup::lookupHelper(Scope* scope, const Name* name, - std::unordered_set& cache, +auto Lookup::lookupHelper(ScopeSymbol* scope, const Name* name, + std::unordered_set& cache, const std::function& accept) const -> Symbol* { if (cache.contains(scope)) { @@ -143,13 +143,13 @@ auto Lookup::lookupHelper(Scope* scope, const Name* name, } } - if (auto classSymbol = symbol_cast(scope->owner())) { + if (auto classSymbol = symbol_cast(scope)) { // iterate over the annonymous symbols - for (auto member : classSymbol->scope()->find(/*unnamed=*/nullptr)) { + for (auto member : classSymbol->find(/*unnamed=*/nullptr)) { auto nestedClass = symbol_cast(member); if (!nestedClass) continue; - auto symbol = lookupHelper(nestedClass->scope(), name, cache, accept); + auto symbol = lookupHelper(nestedClass, name, cache, accept); if (symbol) { // found a match in an anonymous nested class return symbol; @@ -159,7 +159,7 @@ auto Lookup::lookupHelper(Scope* scope, const Name* name, for (const auto& base : classSymbol->baseClasses()) { auto baseClass = symbol_cast(base->symbol()); if (!baseClass) continue; - if (auto symbol = lookupHelper(baseClass->scope(), name, cache, accept)) { + if (auto symbol = lookupHelper(baseClass, name, cache, accept)) { return symbol; } } @@ -176,7 +176,7 @@ auto Lookup::lookupHelper(Scope* scope, const Name* name, auto Lookup::lookupNamespace(NestedNameSpecifierAST* nestedNameSpecifier, const Identifier* id) const -> NamespaceSymbol* { - std::unordered_set set; + std::unordered_set set; if (!nestedNameSpecifier) { // unqualified lookup, start with the current scope and go up. @@ -193,11 +193,11 @@ auto Lookup::lookupNamespace(NestedNameSpecifierAST* nestedNameSpecifier, if (!base) return nullptr; - return lookupNamespaceHelper(base->scope(), id, set); + return lookupNamespaceHelper(base, id, set); } -auto Lookup::lookupNamespaceHelper(Scope* scope, const Identifier* id, - std::unordered_set& set) const +auto Lookup::lookupNamespaceHelper(ScopeSymbol* scope, const Identifier* id, + std::unordered_set& set) const -> NamespaceSymbol* { if (!set.insert(scope).second) { return nullptr; @@ -218,13 +218,13 @@ auto Lookup::lookupNamespaceHelper(Scope* scope, const Identifier* id, auto Lookup::lookupType(NestedNameSpecifierAST* nestedNameSpecifier, const Identifier* id) const -> Symbol* { - std::unordered_set set; + std::unordered_set set; if (!nestedNameSpecifier) { // unqualified lookup, start with the current scope and go up. for (auto scope = scope_; scope; scope = scope->parent()) { - if (auto ns = lookupTypeHelper(scope, id, set)) { - return ns; + if (auto symbol = lookupTypeHelper(scope, id, set)) { + return symbol; } } @@ -238,9 +238,8 @@ auto Lookup::lookupType(NestedNameSpecifierAST* nestedNameSpecifier, case SymbolKind::kClass: case SymbolKind::kEnum: case SymbolKind::kScopedEnum: { - auto scopedSymbol = - static_cast(nestedNameSpecifier->symbol); - return lookupTypeHelper(scopedSymbol->scope(), id, set); + auto scopeSymbol = static_cast(nestedNameSpecifier->symbol); + return lookupTypeHelper(scopeSymbol, id, set); } case SymbolKind::kTypeAlias: { @@ -248,7 +247,7 @@ auto Lookup::lookupType(NestedNameSpecifierAST* nestedNameSpecifier, auto classType = type_cast(alias->type()); if (classType) { auto classSymbol = classType->symbol(); - return lookupTypeHelper(classSymbol->scope(), id, set); + return lookupTypeHelper(classSymbol, id, set); } return nullptr; } @@ -261,17 +260,17 @@ auto Lookup::lookupType(NestedNameSpecifierAST* nestedNameSpecifier, if (auto classSymbol = symbol_cast(usingDeclaration->target())) { - return lookupTypeHelper(classSymbol->scope(), id, set); + return lookupTypeHelper(classSymbol, id, set); } if (auto enumSymbol = symbol_cast(usingDeclaration->target())) { - return lookupTypeHelper(enumSymbol->scope(), id, set); + return lookupTypeHelper(enumSymbol, id, set); } if (auto scopedEnumSymbol = symbol_cast(usingDeclaration->target())) { - return lookupTypeHelper(scopedEnumSymbol->scope(), id, set); + return lookupTypeHelper(scopedEnumSymbol, id, set); } return nullptr; @@ -282,8 +281,8 @@ auto Lookup::lookupType(NestedNameSpecifierAST* nestedNameSpecifier, } // swotch } -auto Lookup::lookupTypeHelper(Scope* scope, const Identifier* id, - std::unordered_set& set) const +auto Lookup::lookupTypeHelper(ScopeSymbol* scope, const Identifier* id, + std::unordered_set& set) const -> Symbol* { if (!set.insert(scope).second) { return nullptr; @@ -300,11 +299,11 @@ auto Lookup::lookupTypeHelper(Scope* scope, const Identifier* id, } } - if (auto classSymbol = symbol_cast(scope->owner())) { + if (auto classSymbol = symbol_cast(scope)) { for (const auto& base : classSymbol->baseClasses()) { auto baseClass = symbol_cast(base->symbol()); if (!baseClass) continue; - if (auto ns = lookupTypeHelper(baseClass->scope(), id, set)) { + if (auto ns = lookupTypeHelper(baseClass, id, set)) { return ns; } } diff --git a/src/parser/cxx/name_lookup.h b/src/parser/cxx/name_lookup.h index c6e06700..10b90117 100644 --- a/src/parser/cxx/name_lookup.h +++ b/src/parser/cxx/name_lookup.h @@ -31,7 +31,7 @@ namespace cxx { class Lookup { public: - explicit Lookup(Scope* scope); + explicit Lookup(ScopeSymbol* scope); [[nodiscard]] auto operator()( const Name* name, const std::function& accept = {}) const @@ -46,7 +46,7 @@ class Lookup { const std::function& accept = {}) const -> Symbol*; [[nodiscard]] auto qualifiedLookup( - Scope* scope, const Name* name, + ScopeSymbol* scope, const Name* name, const std::function& accept = {}) const -> Symbol*; [[nodiscard]] auto lookupNamespace( @@ -62,23 +62,24 @@ class Lookup { -> Symbol*; [[nodiscard]] auto qualifiedLookup( - Symbol* scopedSymbol, const Name* name, + Symbol* scopeSymbol, const Name* name, const std::function& accept) const -> Symbol*; [[nodiscard]] auto lookupHelper( - Scope* scope, const Name* name, std::unordered_set& cache, + ScopeSymbol* scope, const Name* name, + std::unordered_set& cache, const std::function& accept) const -> Symbol*; [[nodiscard]] auto lookupNamespaceHelper( - Scope* scope, const Identifier* id, std::unordered_set& set) const - -> NamespaceSymbol*; + ScopeSymbol* scope, const Identifier* id, + std::unordered_set& set) const -> NamespaceSymbol*; - [[nodiscard]] auto lookupTypeHelper(Scope* scope, const Identifier* id, - std::unordered_set& set) const - -> Symbol*; + [[nodiscard]] auto lookupTypeHelper( + ScopeSymbol* scope, const Identifier* id, + std::unordered_set& set) const -> Symbol*; private: - Scope* scope_ = nullptr; + ScopeSymbol* scope_ = nullptr; }; } // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 85147ab1..b1387b5c 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -31,13 +31,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include @@ -1083,7 +1083,7 @@ auto Parser::parse_nested_name_specifier(NestedNameSpecifierAST*& yyast, auto ast = make_node(pool_); yyast = ast; ast->scopeLoc = scopeLoc; - ast->symbol = globalScope_->owner(); + ast->symbol = globalScope_; } else if (parse_decltype_nested_name_specifier(yyast, ctx)) { // } @@ -3264,7 +3264,7 @@ void Parser::parse_init_statement(StatementAST*& yyast) { LookaheadParser lookahead{this}; DeclarationAST* declaration = nullptr; - if (!scope()->isBlockScope()) { + if (!scope()->isBlock()) { cxx_runtime_error("not a block scope"); } @@ -3446,12 +3446,10 @@ auto Parser::parse_compound_statement(CompoundStatementAST*& yyast, bool skip) if (!match(TokenKind::T_LBRACE, lbraceLoc)) return false; - FunctionSymbol* functionSymbol = - symbol_cast(scope()->owner()); + FunctionSymbol* functionSymbol = symbol_cast(scope()); - if (!functionSymbol && scope()->isFunctionParametersScope()) { - functionSymbol = - symbol_cast(scope()->owner()->enclosingSymbol()); + if (!functionSymbol && scope()->isFunctionParameters()) { + functionSymbol = symbol_cast(scope()->parent()); } auto _ = Binder::ScopeGuard{&binder_}; @@ -4038,7 +4036,7 @@ auto Parser::enterOrCreateNamespace(const Identifier* identifier, SourceLocation identifierLoc, bool isInline) -> NamespaceSymbol* { auto parentScope = scope(); - auto parentNamespace = symbol_cast(parentScope->owner()); + auto parentNamespace = symbol_cast(parentScope); NamespaceSymbol* namespaceSymbol = nullptr; @@ -4068,7 +4066,7 @@ auto Parser::enterOrCreateNamespace(const Identifier* identifier, parentScope->addSymbol(namespaceSymbol); if (isInline || !namespaceSymbol->name()) { - parentNamespace->scope()->addUsingDirective(namespaceSymbol->scope()); + parentNamespace->addUsingDirective(namespaceSymbol); } } @@ -4321,7 +4319,7 @@ auto Parser::parse_simple_declaration( } if (auto params = functionDeclarator->parameterDeclarationClause) { - auto functionScope = functionSymbol->scope(); + auto functionScope = functionSymbol; functionScope->addSymbol(params->functionParametersSymbol); setScope(params->functionParametersSymbol); } else { @@ -4486,7 +4484,7 @@ auto Parser::parse_notypespec_function_definition( functionSymbol->setDefined(true); if (auto params = functionDeclarator->parameterDeclarationClause) { - auto functionScope = functionSymbol->scope(); + auto functionScope = functionSymbol; functionScope->addSymbol(params->functionParametersSymbol); setScope(params->functionParametersSymbol); } else { @@ -7977,7 +7975,7 @@ auto Parser::parse_class_specifier(ClassSpecifierAST*& yyast, DeclSpecs& specs) ast->isFinal = true; } - if (scope()->isTemplateParametersScope()) { + if (scope()->isTemplateParameters()) { mark_maybe_template_name(unqualifiedId); } @@ -8167,7 +8165,7 @@ auto Parser::parse_member_declaration_helper(DeclarationAST*& yyast) -> bool { auto _ = Binder::ScopeGuard{&binder_}; if (auto params = functionDeclarator->parameterDeclarationClause) { - auto functionScope = functionSymbol->scope(); + auto functionScope = functionSymbol; functionScope->addSymbol(params->functionParametersSymbol); setScope(params->functionParametersSymbol); } else { @@ -9094,7 +9092,7 @@ void Parser::parse_template_type_parameter(TemplateParameterAST*& yyast) { expect(TokenKind::T_GREATER, ast->greaterLoc); - setScope(parameters->enclosingScope()); + setScope(parameters->parent()); } (void)parse_requires_clause(ast->requiresClause); @@ -9878,20 +9876,18 @@ void Parser::completePendingFunctionDefinitions() { } } -auto Parser::getCurrentNonClassScope() const -> Scope* { +auto Parser::getCurrentNonClassScope() const -> ScopeSymbol* { for (auto current = scope(); current; current = current->parent()) { - if (current->isClassOrNamespaceScope()) continue; + if (current->isClassOrNamespace()) continue; return current; } return globalScope_; } -auto Parser::scope() const -> Scope* { return binder_.scope(); } +auto Parser::scope() const -> ScopeSymbol* { return binder_.scope(); } -void Parser::setScope(Scope* scope) { binder_.setScope(scope); } - -void Parser::setScope(ScopedSymbol* symbol) { setScope(symbol->scope()); } +void Parser::setScope(ScopeSymbol* scope) { binder_.setScope(scope); } void Parser::completeFunctionDefinition(FunctionDefinitionAST* ast) { if (!ast->functionBody) return; diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 0e25aa9c..9cfdfbcd 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -782,11 +782,10 @@ class Parser final { void completePendingFunctionDefinitions(); void completeFunctionDefinition(FunctionDefinitionAST* ast); - [[nodiscard]] auto getCurrentNonClassScope() const -> Scope*; + [[nodiscard]] auto getCurrentNonClassScope() const -> ScopeSymbol*; - [[nodiscard]] auto scope() const -> Scope*; - void setScope(Scope* scope); - void setScope(ScopedSymbol* symbol); + [[nodiscard]] auto scope() const -> ScopeSymbol*; + void setScope(ScopeSymbol* scope); void check(ExpressionAST* ast); void check(StatementAST* ast); @@ -829,7 +828,7 @@ class Parser final { Arena* pool_ = nullptr; Control* control_ = nullptr; DiagnosticsClient* diagnosticClient_ = nullptr; - Scope* globalScope_ = nullptr; + ScopeSymbol* globalScope_ = nullptr; Binder binder_; LanguageKind lang_ = LanguageKind::kCXX; bool skipFunctionBody_ = false; diff --git a/src/parser/cxx/parser_fwd.h b/src/parser/cxx/parser_fwd.h index 671ed47b..b6d5c877 100644 --- a/src/parser/cxx/parser_fwd.h +++ b/src/parser/cxx/parser_fwd.h @@ -33,7 +33,7 @@ namespace cxx { class Parser; struct UnqualifiedCompletionContext { - Scope* scope = nullptr; + ScopeSymbol* scope = nullptr; }; struct MemberCompletionContext { diff --git a/src/parser/cxx/scope.cc b/src/parser/cxx/scope.cc deleted file mode 100644 index 67a68a43..00000000 --- a/src/parser/cxx/scope.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2025 Roberto Raggi -// -// 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 -#include -#include - -#include -#include - -namespace cxx { - -Scope::Scope(Scope* parent) : parent_(parent) {} - -Scope::~Scope() {} - -void Scope::reset() { - for (auto symbol : symbols_) { - symbol->link_ = nullptr; - symbol->setEnclosingScope(nullptr); - } - symbols_.clear(); - buckets_.clear(); - usingDirectives_.clear(); -} - -auto Scope::isTransparent() const -> bool { - if (!owner_) return true; - if (owner_->isTemplateParameters()) return true; - if (owner_->isFunctionParameters()) return true; - return false; -} - -auto Scope::isNamespaceScope() const -> bool { - return owner_ && owner_->isNamespace(); -} - -auto Scope::isClassScope() const -> bool { return owner_ && owner_->isClass(); } - -auto Scope::isClassOrNamespaceScope() const -> bool { - return isClassScope() || isNamespaceScope(); -} - -auto Scope::isFunctionScope() const -> bool { - return owner_ && owner_->isFunction(); -} - -auto Scope::isBlockScope() const -> bool { return owner_ && owner_->isBlock(); } - -auto Scope::isEnumScope() const -> bool { - return owner_ && (owner_->isEnum() || owner_->isScopedEnum()); -} - -auto Scope::isTemplateParametersScope() const -> bool { - return owner_ && owner_->isTemplateParameters(); -} - -auto Scope::isFunctionParametersScope() const -> bool { - return owner_ && owner_->isFunctionParameters(); -} - -auto Scope::enclosingNamespaceScope() const -> Scope* { - for (auto scope = parent_; scope; scope = scope->parent()) { - if (scope->isNamespaceScope()) { - return scope; - } - } - return nullptr; -} - -auto Scope::enclosingNonTemplateParametersScope() const -> Scope* { - auto scope = parent_; - - while (scope && scope->isTemplateParametersScope()) { - scope = scope->parent(); - } - - return scope; -} - -void Scope::addSymbol(Symbol* symbol) { - if (symbol->isTemplateParameters()) { - cxx_runtime_error("trying to add a template parameters symbol to a scope"); - return; - } - - if (isTemplateParametersScope()) { - if (!(symbol->isTypeParameter() || symbol->isTemplateTypeParameter() || - symbol->isNonTypeParameter() || - symbol->isConstraintTypeParameter())) { - cxx_runtime_error("invalid symbol in template parameters scope"); - } - } - - if (auto params = symbol_cast(symbol); - params && owner_) { - if (owner_->isFunction() || owner_->isLambda()) { - params->scope()->setParent(this); - } - } - - symbol->setEnclosingScope(this); - symbols_.push_back(symbol); - - if (name_cast(symbol->name())) { - if (auto functionSymbol = symbol_cast(symbol)) { - if (auto classSymbol = symbol_cast(owner_)) { - classSymbol->addConversionFunction(functionSymbol); - } - } - } - - if (3 * symbols_.size() >= 2 * buckets_.size()) { - rehash(); - } else { - auto h = symbol->name() ? symbol->name()->hashValue() : 0; - h = h % buckets_.size(); - symbol->link_ = buckets_[h]; - buckets_[h] = symbol; - } -} - -void Scope::rehash() { - const auto newSize = std::max(std::size_t(8), buckets_.size() * 2); - - buckets_ = std::vector(newSize); - - for (auto symbol : symbols_) { - auto h = symbol->name() ? symbol->name()->hashValue() : 0; - auto index = h % newSize; - symbol->link_ = buckets_[index]; - buckets_[index] = symbol; - } -} - -void Scope::replaceSymbol(Symbol* symbol, Symbol* newSymbol) { - if (symbol == newSymbol) return; - - assert(symbol->name() == newSymbol->name()); - - auto it = std::find(symbols_.begin(), symbols_.end(), symbol); - assert(it != symbols_.end()); - - if (it == symbols_.end()) return; - - *it = newSymbol; - - newSymbol->link_ = symbol->link_; - - auto h = newSymbol->name() ? newSymbol->name()->hashValue() : 0; - h = h % buckets_.size(); - - if (buckets_[h] == symbol) { - buckets_[h] = newSymbol; - } else { - for (auto p = buckets_[h]; p; p = p->link_) { - if (p->link_ == symbol) { - p->link_ = newSymbol; - break; - } - } - } - - symbol->link_ = nullptr; -} - -void Scope::addUsingDirective(Scope* scope) { - usingDirectives_.push_back(scope); -} - -auto Scope::find(const Name* name) const -> SymbolChainView { - if (!symbols_.empty()) { - auto h = name ? name->hashValue() : 0; - h = h % buckets_.size(); - for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { - if (symbol->name() == name) { - return SymbolChainView{symbol}; - } - } - } - return SymbolChainView{nullptr}; -} - -auto Scope::find(TokenKind op) const -> SymbolChainView { - if (!symbols_.empty()) { - const auto h = OperatorId::hash(op) % buckets_.size(); - for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { - auto id = name_cast(symbol->name()); - if (id && id->op() == op) return SymbolChainView{symbol}; - } - } - return SymbolChainView{nullptr}; -} - -auto Scope::find(const std::string_view& name) const -> SymbolChainView { - if (!symbols_.empty()) { - const auto h = Identifier::hash(name) % buckets_.size(); - for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { - auto id = name_cast(symbol->name()); - if (id && id->name() == name) return SymbolChainView{symbol}; - } - } - return SymbolChainView{nullptr}; -} - -} // namespace cxx diff --git a/src/parser/cxx/symbol_printer.cc b/src/parser/cxx/symbol_printer.cc index c33b184a..e0d69845 100644 --- a/src/parser/cxx/symbol_printer.cc +++ b/src/parser/cxx/symbol_printer.cc @@ -20,9 +20,9 @@ // cxx #include -#include #include #include +#include #include #include @@ -48,12 +48,12 @@ struct DumpSymbols { std::ostream& out; int depth = 0; - auto dumpScope(Scope* scope) { + auto dumpScope(ScopeSymbol* scope) { if (!scope) return; ++depth; - auto symbols = scope->symbols(); + auto symbols = scope->members(); std::vector sortedSymbols(begin(symbols), end(symbols)); @@ -84,7 +84,7 @@ struct DumpSymbols { out << "namespace"; if (symbol->name()) out << std::format(" {}", to_string(symbol->name())); out << "\n"; - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(BaseClassSymbol* symbol) { @@ -101,8 +101,7 @@ struct DumpSymbols { out << '<'; std::string_view sep = ""; - for (const auto& param : - symbol->templateParameters()->scope()->symbols()) { + for (const auto& param : views::members(symbol->templateParameters())) { out << std::format("{}{}", sep, to_string(param->type())); sep = ", "; } @@ -110,7 +109,7 @@ struct DumpSymbols { out << "\n"; - dumpScope(symbol->templateParameters()->scope()); + dumpScope(symbol->templateParameters()); } else if (symbol->isSpecialization()) { out << std::format("{} {}", classKey, to_string(symbol->name())); out << "<"; @@ -138,15 +137,14 @@ struct DumpSymbols { } --depth; } - dumpScope(symbol->scope()); + dumpScope(symbol); dumpSpecializations(symbol->specializations()); } void operator()(ConceptSymbol* symbol) { indent(); out << std::format("concept {}\n", to_string(symbol->name())); - if (symbol->templateParameters()) - dumpScope(symbol->templateParameters()->scope()); + if (symbol->templateParameters()) dumpScope(symbol->templateParameters()); } void operator()(EnumSymbol* symbol) { @@ -159,7 +157,7 @@ struct DumpSymbols { out << std::format("\n"); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(ScopedEnumSymbol* symbol) { @@ -172,7 +170,7 @@ struct DumpSymbols { out << std::format("\n"); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(OverloadSetSymbol* symbol) { @@ -208,10 +206,10 @@ struct DumpSymbols { out << std::format(" {}\n", to_string(symbol->type(), symbol->name())); if (symbol->templateParameters()) { - dumpScope(symbol->templateParameters()->scope()); + dumpScope(symbol->templateParameters()); } - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(LambdaSymbol* symbol) { @@ -226,25 +224,25 @@ struct DumpSymbols { out << std::format("{}\n", to_string(symbol->type(), symbol->name())); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(TemplateParametersSymbol* symbol) { indent(); out << std::format("template parameters\n"); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(FunctionParametersSymbol* symbol) { indent(); out << std::format("parameters\n"); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(BlockSymbol* symbol) { indent(); out << std::format("block\n"); - dumpScope(symbol->scope()); + dumpScope(symbol); } void operator()(TypeAliasSymbol* symbol) { @@ -252,7 +250,7 @@ struct DumpSymbols { if (symbol->templateParameters()) { out << std::format("template typealias {}\n", to_string(symbol->type(), symbol->name())); - dumpScope(symbol->templateParameters()->scope()); + dumpScope(symbol->templateParameters()); } else { out << std::format("typealias {}\n", to_string(symbol->type(), symbol->name())); @@ -276,7 +274,7 @@ struct DumpSymbols { out << std::format(" {}\n", to_string(symbol->type(), symbol->name())); if (symbol->templateParameters()) { - dumpScope(symbol->templateParameters()->scope()); + dumpScope(symbol->templateParameters()); } } diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index c5e0ffa2..027ddbec 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -24,9 +24,10 @@ #include #include #include -#include +#include #include #include +#include #include @@ -55,14 +56,14 @@ auto compare_args(const std::vector& args1, }; auto Symbol::EnclosingSymbolIterator::operator++() -> EnclosingSymbolIterator& { - symbol_ = symbol_->enclosingSymbol(); + symbol_ = symbol_->parent(); return *this; } auto Symbol::EnclosingSymbolIterator::operator++(int) -> EnclosingSymbolIterator { auto it = *this; - symbol_ = symbol_->enclosingSymbol(); + symbol_ = symbol_->parent(); return it; } @@ -87,10 +88,10 @@ auto Symbol::location() const -> SourceLocation { return location_; } void Symbol::setLocation(SourceLocation location) { location_ = location; } -auto Symbol::enclosingScope() const -> Scope* { return enclosingScope_; } +auto Symbol::parent() const -> ScopeSymbol* { return parent_; } -void Symbol::setEnclosingScope(Scope* enclosingScope) { - enclosingScope_ = enclosingScope; +void Symbol::setParent(ScopeSymbol* enclosingScope) { + parent_ = enclosingScope; } auto Symbol::next() const -> Symbol* { @@ -100,25 +101,172 @@ auto Symbol::next() const -> Symbol* { return nullptr; } -auto Symbol::enclosingSymbol() const -> ScopedSymbol* { - if (!enclosingScope_) return nullptr; - return enclosingScope_->owner(); +auto Symbol::enclosingNamespace() const -> NamespaceSymbol* { + for (auto scope = parent(); scope; scope = scope->parent()) { + if (auto ns = symbol_cast(scope)) { + return ns; + } + } + return nullptr; +} + +auto Symbol::enclosingNonTemplateParametersScope() const -> ScopeSymbol* { + auto scope = parent(); + + while (scope && scope->isTemplateParameters()) { + scope = scope->parent(); + } + + return scope; +} + +ScopeSymbol::ScopeSymbol(SymbolKind kind, ScopeSymbol* enclosingScope) + : Symbol(kind, enclosingScope) {} + +ScopeSymbol::~ScopeSymbol() {} + +void ScopeSymbol::addMember(Symbol* symbol) { addSymbol(symbol); } + +auto ScopeSymbol::members() const -> const std::vector& { + return members_; +} + +void ScopeSymbol::reset() { + for (auto symbol : members_) { + symbol->link_ = nullptr; + symbol->setParent(nullptr); + } + members_.clear(); + buckets_.clear(); + usingDirectives_.clear(); +} + +auto ScopeSymbol::isTransparent() const -> bool { + if (isTemplateParameters()) return true; + if (isFunctionParameters()) return true; + return false; +} + +void ScopeSymbol::addSymbol(Symbol* symbol) { + if (symbol->isTemplateParameters()) { + cxx_runtime_error("trying to add a template parameters symbol to a scope"); + return; + } + + if (isTemplateParameters()) { + if (!(symbol->isTypeParameter() || symbol->isTemplateTypeParameter() || + symbol->isNonTypeParameter() || + symbol->isConstraintTypeParameter())) { + cxx_runtime_error("invalid symbol in template parameters scope"); + } + } + + if (!symbol->parent_ || symbol->isFunctionParameters()) { + symbol->setParent(this); + } + + members_.push_back(symbol); + + if (name_cast(symbol->name())) { + if (auto functionSymbol = symbol_cast(symbol)) { + if (auto classSymbol = symbol_cast(this)) { + classSymbol->addConversionFunction(functionSymbol); + } + } + } + + if (3 * members_.size() >= 2 * buckets_.size()) { + rehash(); + } else { + auto h = symbol->name() ? symbol->name()->hashValue() : 0; + h = h % buckets_.size(); + symbol->link_ = buckets_[h]; + buckets_[h] = symbol; + } } -ScopedSymbol::ScopedSymbol(SymbolKind kind, Scope* enclosingScope) - : Symbol(kind, enclosingScope) { - scope_ = std::make_unique(enclosingScope); - scope_->setOwner(this); +void ScopeSymbol::rehash() { + const auto newSize = std::max(std::size_t(8), buckets_.size() * 2); + + buckets_ = std::vector(newSize); + + for (auto symbol : members_) { + auto h = symbol->name() ? symbol->name()->hashValue() : 0; + auto index = h % newSize; + symbol->link_ = buckets_[index]; + buckets_[index] = symbol; + } } -ScopedSymbol::~ScopedSymbol() {} +void ScopeSymbol::replaceSymbol(Symbol* symbol, Symbol* newSymbol) { + if (symbol == newSymbol) return; + + auto it = std::find(members_.begin(), members_.end(), symbol); -auto ScopedSymbol::scope() const -> Scope* { return scope_.get(); } + if (it == members_.end()) return; -void ScopedSymbol::addMember(Symbol* symbol) { scope_->addSymbol(symbol); } + *it = newSymbol; + + newSymbol->link_ = symbol->link_; + + auto h = newSymbol->name() ? newSymbol->name()->hashValue() : 0; + h = h % buckets_.size(); + + if (buckets_[h] == symbol) { + buckets_[h] = newSymbol; + } else { + for (auto p = buckets_[h]; p; p = p->link_) { + if (p->link_ == symbol) { + p->link_ = newSymbol; + break; + } + } + } + + symbol->link_ = nullptr; +} + +void ScopeSymbol::addUsingDirective(ScopeSymbol* scope) { + usingDirectives_.push_back(scope); +} + +auto ScopeSymbol::find(const Name* name) const -> SymbolChainView { + if (!members_.empty()) { + auto h = name ? name->hashValue() : 0; + h = h % buckets_.size(); + for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { + if (symbol->name() == name) { + return SymbolChainView{symbol}; + } + } + } + return SymbolChainView{nullptr}; +} + +auto ScopeSymbol::find(TokenKind op) const -> SymbolChainView { + if (!members_.empty()) { + const auto h = OperatorId::hash(op) % buckets_.size(); + for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { + auto id = name_cast(symbol->name()); + if (id && id->op() == op) return SymbolChainView{symbol}; + } + } + return SymbolChainView{nullptr}; +} + +auto ScopeSymbol::find(const std::string_view& name) const -> SymbolChainView { + if (!members_.empty()) { + const auto h = Identifier::hash(name) % buckets_.size(); + for (auto symbol = buckets_[h]; symbol; symbol = symbol->link_) { + auto id = name_cast(symbol->name()); + if (id && id->name() == name) return SymbolChainView{symbol}; + } + } + return SymbolChainView{nullptr}; +} -NamespaceSymbol::NamespaceSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +NamespaceSymbol::NamespaceSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} NamespaceSymbol::~NamespaceSymbol() {} @@ -143,7 +291,7 @@ void NamespaceSymbol::setAnonNamespaceIndex(int index) { anonNamespaceIndex_ = index; } -ConceptSymbol::ConceptSymbol(Scope* enclosingScope) +ConceptSymbol::ConceptSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} ConceptSymbol::~ConceptSymbol() {} @@ -157,7 +305,7 @@ void ConceptSymbol::setTemplateParameters( templateParameters_ = templateParameters; } -BaseClassSymbol::BaseClassSymbol(Scope* enclosingScope) +BaseClassSymbol::BaseClassSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} BaseClassSymbol::~BaseClassSymbol() {} @@ -178,8 +326,8 @@ auto BaseClassSymbol::symbol() const -> Symbol* { return symbol_; } void BaseClassSymbol::setSymbol(Symbol* symbol) { symbol_ = symbol; } -ClassSymbol::ClassSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +ClassSymbol::ClassSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} ClassSymbol::~ClassSymbol() {} @@ -324,7 +472,7 @@ auto ClassSymbol::buildClassLayout(Control* control) FieldSymbol* lastField = nullptr; - for (auto member : scope()->symbols()) { + for (auto member : members()) { auto field = symbol_cast(member); if (!field) continue; if (field->isStatic()) continue; @@ -378,8 +526,8 @@ auto ClassSymbol::buildClassLayout(Control* control) return true; } -EnumSymbol::EnumSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +EnumSymbol::EnumSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} EnumSymbol::~EnumSymbol() {} @@ -399,8 +547,8 @@ void EnumSymbol::setUnderlyingType(const Type* underlyingType) { underlyingType_ = underlyingType; } -ScopedEnumSymbol::ScopedEnumSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +ScopedEnumSymbol::ScopedEnumSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} ScopedEnumSymbol::~ScopedEnumSymbol() {} @@ -412,8 +560,8 @@ void ScopedEnumSymbol::setUnderlyingType(const Type* underlyingType) { underlyingType_ = underlyingType; } -FunctionSymbol::FunctionSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +FunctionSymbol::FunctionSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} FunctionSymbol::~FunctionSymbol() {} @@ -485,8 +633,8 @@ void FunctionSymbol::setDefaulted(bool isDefaulted) { } auto FunctionSymbol::isConstructor() const -> bool { - auto parent = symbol_cast(enclosingSymbol()); - if (!parent) return false; + auto p = symbol_cast(parent()); + if (!p) return false; auto functionType = type_cast(type()); if (functionType->returnType()) { @@ -494,7 +642,7 @@ auto FunctionSymbol::isConstructor() const -> bool { return false; } - if (name() != parent->name()) { + if (name() != p->name()) { // constructors have the same name as the class return false; } @@ -510,7 +658,7 @@ void FunctionSymbol::setHasCxxLinkage(bool hasCxxLinkage) { isExternC_ = !hasCxxLinkage; } -OverloadSetSymbol::OverloadSetSymbol(Scope* enclosingScope) +OverloadSetSymbol::OverloadSetSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} OverloadSetSymbol::~OverloadSetSymbol() {} @@ -528,8 +676,8 @@ void OverloadSetSymbol::addFunction(FunctionSymbol* function) { functions_.push_back(function); } -LambdaSymbol::LambdaSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +LambdaSymbol::LambdaSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} LambdaSymbol::~LambdaSymbol() {} @@ -562,22 +710,22 @@ auto LambdaSymbol::isStatic() const -> bool { return isStatic_; } void LambdaSymbol::setStatic(bool isStatic) { isStatic_ = isStatic; } -FunctionParametersSymbol::FunctionParametersSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +FunctionParametersSymbol::FunctionParametersSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} FunctionParametersSymbol::~FunctionParametersSymbol() {} -TemplateParametersSymbol::TemplateParametersSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +TemplateParametersSymbol::TemplateParametersSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} TemplateParametersSymbol::~TemplateParametersSymbol() {} -BlockSymbol::BlockSymbol(Scope* enclosingScope) - : ScopedSymbol(Kind, enclosingScope) {} +BlockSymbol::BlockSymbol(ScopeSymbol* enclosingScope) + : ScopeSymbol(Kind, enclosingScope) {} BlockSymbol::~BlockSymbol() {} -TypeAliasSymbol::TypeAliasSymbol(Scope* enclosingScope) +TypeAliasSymbol::TypeAliasSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} TypeAliasSymbol::~TypeAliasSymbol() {} @@ -600,7 +748,7 @@ void TypeAliasSymbol::setTemplateDeclaration( templateDeclaration_ = declaration; } -VariableSymbol::VariableSymbol(Scope* enclosingScope) +VariableSymbol::VariableSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} VariableSymbol::~VariableSymbol() {} @@ -669,7 +817,7 @@ void VariableSymbol::setConstValue(std::optional value) { constValue_ = std::move(value); } -FieldSymbol::FieldSymbol(Scope* enclosingScope) +FieldSymbol::FieldSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} FieldSymbol::~FieldSymbol() {} @@ -726,12 +874,12 @@ auto FieldSymbol::alignment() const -> int { return alignment_; } void FieldSymbol::setAlignment(int alignment) { alignment_ = alignment; } -ParameterSymbol::ParameterSymbol(Scope* enclosingScope) +ParameterSymbol::ParameterSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} ParameterSymbol::~ParameterSymbol() {} -ParameterPackSymbol::ParameterPackSymbol(Scope* enclosingScope) +ParameterPackSymbol::ParameterPackSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} ParameterPackSymbol::~ParameterPackSymbol() {} @@ -744,12 +892,12 @@ void ParameterPackSymbol::addElement(Symbol* element) { elements_.push_back(element); } -TypeParameterSymbol::TypeParameterSymbol(Scope* enclosingScope) +TypeParameterSymbol::TypeParameterSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} TypeParameterSymbol::~TypeParameterSymbol() {} -NonTypeParameterSymbol::NonTypeParameterSymbol(Scope* enclosingScope) +NonTypeParameterSymbol::NonTypeParameterSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} NonTypeParameterSymbol::~NonTypeParameterSymbol() {} @@ -778,13 +926,14 @@ void NonTypeParameterSymbol::setParameterPack(bool isParameterPack) { isParameterPack_ = isParameterPack; } -TemplateTypeParameterSymbol::TemplateTypeParameterSymbol(Scope* enclosingScope) +TemplateTypeParameterSymbol::TemplateTypeParameterSymbol( + ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} TemplateTypeParameterSymbol::~TemplateTypeParameterSymbol() {} ConstraintTypeParameterSymbol::ConstraintTypeParameterSymbol( - Scope* enclosingScope) + ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} ConstraintTypeParameterSymbol::~ConstraintTypeParameterSymbol() {} @@ -805,7 +954,7 @@ void ConstraintTypeParameterSymbol::setParameterPack(bool isParameterPack) { isParameterPack_ = isParameterPack; } -EnumeratorSymbol::EnumeratorSymbol(Scope* enclosingScope) +EnumeratorSymbol::EnumeratorSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} EnumeratorSymbol::~EnumeratorSymbol() {} @@ -818,7 +967,7 @@ void EnumeratorSymbol::setValue(const std::optional& value) { value_ = value; } -UsingDeclarationSymbol::UsingDeclarationSymbol(Scope* enclosingScope) +UsingDeclarationSymbol::UsingDeclarationSymbol(ScopeSymbol* enclosingScope) : Symbol(Kind, enclosingScope) {} UsingDeclarationSymbol::~UsingDeclarationSymbol() {} diff --git a/src/parser/cxx/symbols.h b/src/parser/cxx/symbols.h index b6fb26f8..b2957dd1 100644 --- a/src/parser/cxx/symbols.h +++ b/src/parser/cxx/symbols.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,8 @@ namespace cxx { +class SymbolChainView; + template struct TemplateSpecialization { S* templateSymbol = nullptr; @@ -103,23 +106,25 @@ class Symbol { using difference_type = std::ptrdiff_t; EnclosingSymbolIterator() = default; - explicit EnclosingSymbolIterator(ScopedSymbol* symbol) : symbol_(symbol) {} + explicit EnclosingSymbolIterator(ScopeSymbol* symbol) : symbol_(symbol) {} auto operator<=>(const EnclosingSymbolIterator&) const = default; - auto operator*() const -> ScopedSymbol* { return symbol_; } + auto operator*() const -> ScopeSymbol* { return symbol_; } auto operator++() -> EnclosingSymbolIterator&; auto operator++(int) -> EnclosingSymbolIterator; private: - ScopedSymbol* symbol_ = nullptr; + ScopeSymbol* symbol_ = nullptr; }; - Symbol(SymbolKind kind, Scope* enclosingScope) - : kind_(kind), enclosingScope_(enclosingScope) {} + Symbol(SymbolKind kind, ScopeSymbol* enclosingScope) + : kind_(kind), parent_(enclosingScope) {} virtual ~Symbol() = default; + [[nodiscard]] virtual auto asScopeSymbol() -> ScopeSymbol* { return nullptr; } + [[nodiscard]] auto kind() const -> SymbolKind; [[nodiscard]] auto name() const -> const Name*; @@ -131,13 +136,16 @@ class Symbol { [[nodiscard]] auto location() const -> SourceLocation; void setLocation(SourceLocation location); - [[nodiscard]] auto enclosingScope() const -> Scope*; - void setEnclosingScope(Scope* enclosingScope); + [[nodiscard]] auto parent() const -> ScopeSymbol*; + void setParent(ScopeSymbol* parent); + + [[nodiscard]] auto enclosingNamespace() const -> NamespaceSymbol*; - [[nodiscard]] auto enclosingSymbol() const -> ScopedSymbol*; + [[nodiscard]] auto enclosingNonTemplateParametersScope() const + -> ScopeSymbol*; [[nodiscard]] auto enclosingSymbols() const { - return std::ranges::subrange(EnclosingSymbolIterator{enclosingSymbol()}, + return std::ranges::subrange(EnclosingSymbolIterator{parent()}, EnclosingSymbolIterator{}); } @@ -159,34 +167,62 @@ class Symbol { } private: - friend class Scope; + friend class ScopeSymbol; SymbolKind kind_; const Name* name_ = nullptr; const Type* type_ = nullptr; - Scope* enclosingScope_ = nullptr; + ScopeSymbol* parent_ = nullptr; Symbol* link_ = nullptr; SourceLocation location_; }; -class ScopedSymbol : public Symbol { +class ScopeSymbol : public Symbol { public: - ScopedSymbol(SymbolKind kind, Scope* enclosingScope); - ~ScopedSymbol() override; + ScopeSymbol(SymbolKind kind, ScopeSymbol* enclosingScope); + ~ScopeSymbol() override; - [[nodiscard]] auto scope() const -> Scope*; + [[nodiscard]] auto asScopeSymbol() -> ScopeSymbol* override { return this; } + [[nodiscard]] auto empty() const -> bool { return members_.empty(); } + + [[nodiscard]] auto members() const -> const std::vector&; void addMember(Symbol* member); + [[nodiscard]] auto usingDirectives() const { + return std::views::all(usingDirectives_); + } + + [[nodiscard]] auto find(const Name* name) const -> SymbolChainView; + + [[nodiscard]] auto find(const std::string_view& name) const + -> SymbolChainView; + + [[nodiscard]] auto find(TokenKind op) const -> SymbolChainView; + + void addSymbol(Symbol* symbol); + void addUsingDirective(ScopeSymbol* scope); + + [[nodiscard]] auto isTransparent() const -> bool; + + // internal + void replaceSymbol(Symbol* symbol, Symbol* newSymbol); + void reset(); + + private: + void rehash(); + private: - std::unique_ptr scope_; + std::vector members_; + std::vector buckets_; + std::vector usingDirectives_; }; -class NamespaceSymbol final : public ScopedSymbol { +class NamespaceSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kNamespace; - explicit NamespaceSymbol(Scope* enclosingScope); + explicit NamespaceSymbol(ScopeSymbol* enclosingScope); ~NamespaceSymbol() override; [[nodiscard]] auto isInline() const -> bool; @@ -208,7 +244,7 @@ class ConceptSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kConcept; - explicit ConceptSymbol(Scope* enclosingScope); + explicit ConceptSymbol(ScopeSymbol* enclosingScope); ~ConceptSymbol() override; [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; @@ -222,7 +258,7 @@ class BaseClassSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kBaseClass; - explicit BaseClassSymbol(Scope* enclosingScope); + explicit BaseClassSymbol(ScopeSymbol* enclosingScope); ~BaseClassSymbol() override; [[nodiscard]] auto isVirtual() const -> bool; @@ -240,11 +276,11 @@ class BaseClassSymbol final : public Symbol { bool isVirtual_ = false; }; -class ClassSymbol final : public ScopedSymbol { +class ClassSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kClass; - explicit ClassSymbol(Scope* enclosingScope); + explicit ClassSymbol(ScopeSymbol* enclosingScope); ~ClassSymbol() override; [[nodiscard]] auto isUnion() const -> bool; @@ -353,11 +389,11 @@ class ClassSymbol final : public ScopedSymbol { }; }; -class EnumSymbol final : public ScopedSymbol { +class EnumSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kEnum; - explicit EnumSymbol(Scope* enclosingScope); + explicit EnumSymbol(ScopeSymbol* enclosingScope); ~EnumSymbol() override; [[nodiscard]] bool hasFixedUnderlyingType() const; @@ -371,11 +407,11 @@ class EnumSymbol final : public ScopedSymbol { bool hasFixedUnderlyingType_ = false; }; -class ScopedEnumSymbol final : public ScopedSymbol { +class ScopedEnumSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kScopedEnum; - explicit ScopedEnumSymbol(Scope* enclosingScope); + explicit ScopedEnumSymbol(ScopeSymbol* enclosingScope); ~ScopedEnumSymbol() override; [[nodiscard]] auto underlyingType() const -> const Type*; @@ -385,11 +421,11 @@ class ScopedEnumSymbol final : public ScopedSymbol { const Type* underlyingType_ = nullptr; }; -class FunctionSymbol final : public ScopedSymbol { +class FunctionSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kFunction; - explicit FunctionSymbol(Scope* enclosingScope); + explicit FunctionSymbol(ScopeSymbol* enclosingScope); ~FunctionSymbol() override; [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; @@ -464,7 +500,7 @@ class OverloadSetSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kOverloadSet; - explicit OverloadSetSymbol(Scope* enclosingScope); + explicit OverloadSetSymbol(ScopeSymbol* enclosingScope); ~OverloadSetSymbol() override; [[nodiscard]] auto functions() const -> const std::vector&; @@ -476,11 +512,11 @@ class OverloadSetSymbol final : public Symbol { std::vector functions_; }; -class LambdaSymbol final : public ScopedSymbol { +class LambdaSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kLambda; - explicit LambdaSymbol(Scope* enclosingScope); + explicit LambdaSymbol(ScopeSymbol* enclosingScope); ~LambdaSymbol() override; [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; @@ -512,27 +548,27 @@ class LambdaSymbol final : public ScopedSymbol { }; }; -class FunctionParametersSymbol final : public ScopedSymbol { +class FunctionParametersSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kFunctionParameters; - explicit FunctionParametersSymbol(Scope* enclosingScope); + explicit FunctionParametersSymbol(ScopeSymbol* enclosingScope); ~FunctionParametersSymbol() override; }; -class TemplateParametersSymbol final : public ScopedSymbol { +class TemplateParametersSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kTemplateParameters; - explicit TemplateParametersSymbol(Scope* enclosingScope); + explicit TemplateParametersSymbol(ScopeSymbol* enclosingScope); ~TemplateParametersSymbol() override; }; -class BlockSymbol final : public ScopedSymbol { +class BlockSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kBlock; - explicit BlockSymbol(Scope* enclosingScope); + explicit BlockSymbol(ScopeSymbol* enclosingScope); ~BlockSymbol() override; }; @@ -540,7 +576,7 @@ class TypeAliasSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kTypeAlias; - explicit TypeAliasSymbol(Scope* enclosingScope); + explicit TypeAliasSymbol(ScopeSymbol* enclosingScope); ~TypeAliasSymbol() override; [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; @@ -558,7 +594,7 @@ class VariableSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kVariable; - explicit VariableSymbol(Scope* enclosingScope); + explicit VariableSymbol(ScopeSymbol* enclosingScope); ~VariableSymbol() override; [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; @@ -614,7 +650,7 @@ class FieldSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kField; - explicit FieldSymbol(Scope* enclosingScope); + explicit FieldSymbol(ScopeSymbol* enclosingScope); ~FieldSymbol() override; [[nodiscard]] bool isBitField() const; @@ -675,7 +711,7 @@ class ParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kParameter; - explicit ParameterSymbol(Scope* enclosingScope); + explicit ParameterSymbol(ScopeSymbol* enclosingScope); ~ParameterSymbol() override; }; @@ -683,7 +719,7 @@ class ParameterPackSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kParameterPack; - explicit ParameterPackSymbol(Scope* enclosingScope); + explicit ParameterPackSymbol(ScopeSymbol* enclosingScope); ~ParameterPackSymbol() override; [[nodiscard]] auto elements() const -> const std::vector&; @@ -697,7 +733,7 @@ class TypeParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kTypeParameter; - explicit TypeParameterSymbol(Scope* enclosingScope); + explicit TypeParameterSymbol(ScopeSymbol* enclosingScope); ~TypeParameterSymbol() override; }; @@ -705,7 +741,7 @@ class NonTypeParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kNonTypeParameter; - explicit NonTypeParameterSymbol(Scope* enclosingScope); + explicit NonTypeParameterSymbol(ScopeSymbol* enclosingScope); ~NonTypeParameterSymbol() override; [[nodiscard]] auto index() const -> int; @@ -731,7 +767,7 @@ class TemplateTypeParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kTemplateTypeParameter; - explicit TemplateTypeParameterSymbol(Scope* enclosingScope); + explicit TemplateTypeParameterSymbol(ScopeSymbol* enclosingScope); ~TemplateTypeParameterSymbol() override; }; @@ -739,7 +775,7 @@ class ConstraintTypeParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kConstraintTypeParameter; - explicit ConstraintTypeParameterSymbol(Scope* enclosingScope); + explicit ConstraintTypeParameterSymbol(ScopeSymbol* enclosingScope); ~ConstraintTypeParameterSymbol() override; [[nodiscard]] auto index() const -> int; @@ -761,7 +797,7 @@ class EnumeratorSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kEnumerator; - explicit EnumeratorSymbol(Scope* enclosingScope); + explicit EnumeratorSymbol(ScopeSymbol* enclosingScope); ~EnumeratorSymbol() override; [[nodiscard]] auto value() const -> const std::optional&; @@ -775,7 +811,7 @@ class UsingDeclarationSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kUsingDeclaration; - explicit UsingDeclarationSymbol(Scope* enclosingScope); + explicit UsingDeclarationSymbol(ScopeSymbol* enclosingScope); ~UsingDeclarationSymbol() override; [[nodiscard]] auto declarator() const -> UsingDeclaratorAST*; @@ -821,6 +857,12 @@ auto symbol_cast(Symbol* symbol) -> T* { return nullptr; } +template <> +inline auto symbol_cast(Symbol* symbol) -> ScopeSymbol* { + if (symbol) return symbol->asScopeSymbol(); + return nullptr; +} + struct GetTemplateParameters { auto operator()(Symbol* symbol) const -> TemplateParametersSymbol* { if (!symbol) return nullptr; diff --git a/src/parser/cxx/symbols_fwd.h b/src/parser/cxx/symbols_fwd.h index ac48c868..0709635f 100644 --- a/src/parser/cxx/symbols_fwd.h +++ b/src/parser/cxx/symbols_fwd.h @@ -52,8 +52,8 @@ namespace cxx { V(UsingDeclaration) class Symbol; -class ScopedSymbol; -class Scope; +class ScopeSymbol; +class ScopeSymbol; template struct TemplateSpecialization; diff --git a/src/parser/cxx/translation_unit.cc b/src/parser/cxx/translation_unit.cc index d70c1034..991ff71e 100644 --- a/src/parser/cxx/translation_unit.cc +++ b/src/parser/cxx/translation_unit.cc @@ -182,9 +182,9 @@ auto TranslationUnit::config() const -> const ParserConfiguration& { return config_; } -auto TranslationUnit::globalScope() const -> Scope* { +auto TranslationUnit::globalScope() const -> ScopeSymbol* { if (!globalNamespace_) return nullptr; - return globalNamespace_->scope(); + return globalNamespace_; } auto TranslationUnit::fileName() const -> const std::string& { diff --git a/src/parser/cxx/translation_unit.h b/src/parser/cxx/translation_unit.h index 9165d404..2c70ea7e 100644 --- a/src/parser/cxx/translation_unit.h +++ b/src/parser/cxx/translation_unit.h @@ -58,7 +58,7 @@ class TranslationUnit { void setAST(UnitAST* ast) { ast_ = ast; } - [[nodiscard]] auto globalScope() const -> Scope*; + [[nodiscard]] auto globalScope() const -> ScopeSymbol*; [[nodiscard]] auto fileName() const -> const std::string&; diff --git a/src/parser/cxx/type_checker.cc b/src/parser/cxx/type_checker.cc index 906a4215..80f6140c 100644 --- a/src/parser/cxx/type_checker.cc +++ b/src/parser/cxx/type_checker.cc @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,11 @@ struct TypeChecker::Visitor { [[nodiscard]] auto arena() const -> Arena* { return check.unit_->arena(); } - [[nodiscard]] auto globalScope() const -> Scope* { + [[nodiscard]] auto globalScope() const -> ScopeSymbol* { return check.unit_->globalScope(); } - [[nodiscard]] auto scope() const -> Scope* { return check.scope_; } + [[nodiscard]] auto scope() const -> ScopeSymbol* { return check.scope_; } [[nodiscard]] auto control() const -> Control* { return check.unit_->control(); @@ -246,15 +245,15 @@ void TypeChecker::Visitor::operator()(ThisExpressionAST* ast) { auto scope_ = check.scope_; for (auto current = scope_; current; current = current->parent()) { - if (auto classSymbol = symbol_cast(current->owner())) { + if (auto classSymbol = symbol_cast(current)) { // maybe a this expression in a field initializer ast->type = control()->getPointerType(classSymbol->type()); break; } - if (auto functionSymbol = symbol_cast(current->owner())) { + if (auto functionSymbol = symbol_cast(current)) { if (auto classSymbol = - symbol_cast(functionSymbol->enclosingSymbol())) { + symbol_cast(functionSymbol->parent())) { auto functionType = type_cast(functionSymbol->type()); const auto cv = functionType->cvQualifiers(); if (cv != CvQualifiers::kNone) { @@ -766,8 +765,7 @@ void TypeChecker::Visitor::operator()(BuiltinOffsetofExpressionAST* ast) { } auto symbol = classType->symbol(); - auto member = - Lookup{scope()}.qualifiedLookup(symbol->scope(), ast->identifier); + auto member = Lookup{scope()}.qualifiedLookup(symbol, ast->identifier); auto field = symbol_cast(member); if (!field) { @@ -790,8 +788,8 @@ void TypeChecker::Visitor::operator()(BuiltinOffsetofExpressionAST* ast) { break; } - auto member = Lookup{scope()}.qualifiedLookup( - currentClass->symbol()->scope(), dot->identifier); + auto member = Lookup{scope()}.qualifiedLookup(currentClass->symbol(), + dot->identifier); auto field = symbol_cast(member); @@ -880,7 +878,7 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) { auto symbol = idExpr->symbol; if (auto field = symbol_cast(symbol); field && !field->isStatic()) { - auto parentClass = field->enclosingSymbol(); + auto parentClass = field->parent(); auto classType = type_cast(parentClass->type()); ast->type = @@ -894,7 +892,7 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) { if (auto function = symbol_cast(symbol); function && !function->isStatic()) { auto functionType = type_cast(function->type()); - auto parentClass = function->enclosingSymbol(); + auto parentClass = function->parent(); auto classType = type_cast(parentClass->type()); ast->type = @@ -2454,8 +2452,7 @@ auto TypeChecker::Visitor::check_member_access(MemberExpressionAST* ast) auto classSymbol = classType->symbol(); - auto symbol = - Lookup{scope()}.qualifiedLookup(classSymbol->scope(), memberName); + auto symbol = Lookup{scope()}.qualifiedLookup(classSymbol, memberName); ast->symbol = symbol; @@ -2534,10 +2531,9 @@ auto TypeChecker::Visitor::check_pseudo_destructor_access( void TypeChecker::checkReturnStatement(ReturnStatementAST* ast) { const Type* targetType = nullptr; for (auto current = scope_; current; current = current->parent()) { - auto owner = current->owner(); - if (!owner) continue; - if (owner->isFunction() || owner->isLambda()) { - if (auto functionType = type_cast(owner->type())) { + if (!current) continue; + if (current->isFunction() || current->isLambda()) { + if (auto functionType = type_cast(current->type())) { targetType = functionType->returnType(); break; } diff --git a/src/parser/cxx/type_checker.h b/src/parser/cxx/type_checker.h index 2d844453..e0de83c5 100644 --- a/src/parser/cxx/type_checker.h +++ b/src/parser/cxx/type_checker.h @@ -39,7 +39,7 @@ class TypeChecker { [[nodiscard]] auto reportErrors() const -> bool { return reportErrors_; } void setReportErrors(bool reportErrors) { reportErrors_ = reportErrors; } - void setScope(Scope* scope) { scope_ = scope; } + void setScope(ScopeSymbol* scope) { scope_ = scope; } void operator()(ExpressionAST* ast); @@ -58,7 +58,7 @@ class TypeChecker { struct Visitor; TranslationUnit* unit_; - Scope* scope_ = nullptr; + ScopeSymbol* scope_ = nullptr; bool reportErrors_ = false; }; diff --git a/src/parser/cxx/type_printer.cc b/src/parser/cxx/type_printer.cc index b4fd140d..d57433c3 100644 --- a/src/parser/cxx/type_printer.cc +++ b/src/parser/cxx/type_printer.cc @@ -21,10 +21,10 @@ // cxx #include #include -#include #include #include #include +#include #include @@ -303,7 +303,10 @@ class TypePrinter { void operator()(const ClassType* type) { std::string out; - if (auto parent = type->symbol()->enclosingSymbol()) { + if (auto parent = type->symbol()->parent()) { + while (symbol_cast(parent)) { + parent = parent->parent(); + } accept(parent->type()); out += "::"; } @@ -324,7 +327,7 @@ class TypePrinter { out += '<'; std::string_view sep = ""; for (const auto& param : - templDecl->templateParameters()->scope()->symbols()) { + views::members(templDecl->templateParameters())) { out += std::format("{}{}", sep, to_string(param->type())); sep = ", "; } diff --git a/src/parser/cxx/scope.h b/src/parser/cxx/views/symbols.h similarity index 56% rename from src/parser/cxx/scope.h rename to src/parser/cxx/views/symbols.h index bb65462a..9529d807 100644 --- a/src/parser/cxx/scope.h +++ b/src/parser/cxx/views/symbols.h @@ -27,80 +27,21 @@ #include #include -#include - namespace cxx { class SymbolChainView; -class Scope { - public: - explicit Scope(Scope* parent); - ~Scope(); - - [[nodiscard]] auto isTransparent() const -> bool; - [[nodiscard]] auto isNamespaceScope() const -> bool; - [[nodiscard]] auto isClassScope() const -> bool; - [[nodiscard]] auto isClassOrNamespaceScope() const -> bool; - [[nodiscard]] auto isFunctionScope() const -> bool; - [[nodiscard]] auto isBlockScope() const -> bool; - [[nodiscard]] auto isEnumScope() const -> bool; - [[nodiscard]] auto isTemplateParametersScope() const -> bool; - [[nodiscard]] auto isFunctionParametersScope() const -> bool; - - [[nodiscard]] auto enclosingNamespaceScope() const -> Scope*; - [[nodiscard]] auto enclosingNonTemplateParametersScope() const -> Scope*; - - [[nodiscard]] auto parent() const -> Scope* { return parent_; } - [[nodiscard]] auto owner() const -> ScopedSymbol* { return owner_; } - - [[nodiscard]] auto empty() const -> bool { return symbols_.empty(); } - - [[nodiscard]] auto symbols() const { return std::views::all(symbols_); } - - [[nodiscard]] auto usingDirectives() const { - return std::views::all(usingDirectives_); - } - - [[nodiscard]] auto find(const Name* name) const -> SymbolChainView; - - [[nodiscard]] auto find(const std::string_view& name) const - -> SymbolChainView; - - [[nodiscard]] auto find(TokenKind op) const -> SymbolChainView; - - void setParent(Scope* parent) { parent_ = parent; } - void setOwner(ScopedSymbol* owner) { owner_ = owner; } - - void addSymbol(Symbol* symbol); - void addUsingDirective(Scope* scope); - - void replaceSymbol(Symbol* symbol, Symbol* newSymbol); - - void reset(); - - private: - void rehash(); - - private: - Scope* parent_ = nullptr; - ScopedSymbol* owner_ = nullptr; - std::vector symbols_; - std::vector buckets_; - std::vector usingDirectives_; -}; - namespace views { constexpr auto class_or_namespaces = std::views::filter(&Symbol::isClassOrNamespace) | std::views::transform( - [](Symbol* s) { return static_cast(s); }); + [](Symbol* s) { return static_cast(s); }); constexpr auto enum_or_scoped_enums = std::views::filter(&Symbol::isEnumOrScopedEnum) | std::views::transform( - [](Symbol* s) { return static_cast(s); }); + [](Symbol* s) { return static_cast(s); }); constexpr const auto namespaces = std::views::filter(&Symbol::isNamespace) | @@ -125,13 +66,11 @@ constexpr auto functions = std::views::filter(&Symbol::isFunction) | constexpr auto variables = std::views::filter(&Symbol::isVariable) | std::views::transform(symbol_cast); -inline auto members(Scope* scope) { return std::views::all(scope->symbols()); } - -inline auto members(ScopedSymbol* symbol) { - return std::views::all(symbol->scope()->symbols()); +inline auto members(ScopeSymbol* symbol) { + return std::views::all(symbol->members()); } -inline auto find(Scope* scope, const Name* name) { +inline auto find(ScopeSymbol* scope, const Name* name) { return scope ? scope->find(name) : SymbolChainView{nullptr}; } diff --git a/tests/api_tests/test_utils.h b/tests/api_tests/test_utils.h index 9b8dc548..284e755c 100644 --- a/tests/api_tests/test_utils.h +++ b/tests/api_tests/test_utils.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -63,7 +62,7 @@ struct Source { auto control() -> Control* { return unit.control(); } auto ast() -> UnitAST* { return unit.ast(); } - auto scope() -> Scope* { return unit.globalScope(); } + auto scope() -> ScopeSymbol* { return unit.globalScope(); } auto get(std::string_view name) -> Symbol* { Symbol* symbol = nullptr; @@ -97,7 +96,7 @@ inline auto operator""_cxx_no_templates(const char* source, std::size_t size) struct LookupMember { Source& source; - auto operator()(Scope* scope, std::string_view name) -> Symbol* { + auto operator()(ScopeSymbol* scope, std::string_view name) -> Symbol* { auto id = source.control()->getIdentifier(name); for (auto candidate : scope->find(id)) { return candidate; diff --git a/tests/unit_tests/sema/template_alias_02.cc b/tests/unit_tests/sema/template_alias_02.cc index c8415556..0a4e2b26 100644 --- a/tests/unit_tests/sema/template_alias_02.cc +++ b/tests/unit_tests/sema/template_alias_02.cc @@ -8,7 +8,7 @@ struct HashMap { struct Name; struct Symbol; -struct Scope { +struct ScopeSymbol { using Table = HashMap; using MemberIterator = Table::iterator; }; @@ -24,6 +24,6 @@ struct Scope { // CHECK-NEXT: typealias ::Symbol** iterator // CHECK-NEXT: class Name // CHECK-NEXT: class Symbol -// CHECK-NEXT: class Scope +// CHECK-NEXT: class ScopeSymbol // CHECK-NEXT: typealias ::HashMap Table // CHECK-NEXT: typealias ::Symbol** MemberIterator