name_scope.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_
  6. #include "toolchain/sem_ir/ids.h"
  7. namespace Carbon::SemIR {
  8. struct NameScope : Printable<NameScope> {
  9. auto Print(llvm::raw_ostream& out) const -> void {
  10. out << "{inst: " << inst_id << ", enclosing_scope: " << enclosing_scope_id
  11. << ", has_error: " << (has_error ? "true" : "false");
  12. out << ", extended_scopes: [";
  13. llvm::ListSeparator scope_sep;
  14. for (auto id : extended_scopes) {
  15. out << scope_sep << id;
  16. }
  17. out << "]";
  18. out << ", names: {";
  19. // Sort name keys to get stable output.
  20. llvm::SmallVector<NameId> keys;
  21. for (auto [key, _] : names) {
  22. keys.push_back(key);
  23. }
  24. llvm::sort(keys,
  25. [](NameId lhs, NameId rhs) { return lhs.index < rhs.index; });
  26. llvm::ListSeparator key_sep;
  27. for (auto key : keys) {
  28. out << key_sep << key << ": " << names.find(key)->second;
  29. }
  30. out << "}";
  31. out << "}";
  32. }
  33. // Names in the scope.
  34. llvm::DenseMap<NameId, InstId> names = llvm::DenseMap<NameId, InstId>();
  35. // Scopes extended by this scope.
  36. //
  37. // TODO: A `NameScopeId` is currently insufficient to describe an extended
  38. // scope in general. For example:
  39. //
  40. // class A(T:! type) {
  41. // extend base: B(T*);
  42. // }
  43. //
  44. // needs to describe the `T*` argument.
  45. //
  46. // Small vector size is set to 1: we expect that there will rarely be more
  47. // than a single extended scope. Currently the only kind of extended scope is
  48. // a base class, and there can be only one of those per scope.
  49. // TODO: Revisit this once we have more kinds of extended scope and data.
  50. // TODO: Consider using something like `TinyPtrVector` for this.
  51. llvm::SmallVector<NameScopeId, 1> extended_scopes;
  52. // The instruction which owns the scope.
  53. InstId inst_id;
  54. // When the scope is a namespace, the name. Otherwise, invalid.
  55. NameId name_id;
  56. // The scope enclosing this one.
  57. NameScopeId enclosing_scope_id;
  58. // Whether we have diagnosed an error in a construct that would have added
  59. // names to this scope. For example, this can happen if an `import` failed or
  60. // an `extend` declaration was ill-formed. If true, the `names` map is assumed
  61. // to be missing names as a result of the error, and no further errors are
  62. // produced for lookup failures in this scope.
  63. bool has_error = false;
  64. // True if this is a closed namespace created by importing a package.
  65. bool is_closed_import = false;
  66. // Imported IR scopes that compose this namespace. This will be empty for
  67. // scopes that correspond to the current package.
  68. llvm::SmallVector<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>, 0>
  69. import_ir_scopes;
  70. };
  71. // Provides a ValueStore wrapper for an API specific to name scopes.
  72. class NameScopeStore {
  73. public:
  74. // Adds a name scope, returning an ID to reference it.
  75. auto Add(InstId inst_id, NameId name_id, NameScopeId enclosing_scope_id)
  76. -> NameScopeId {
  77. return values_.Add({.inst_id = inst_id,
  78. .name_id = name_id,
  79. .enclosing_scope_id = enclosing_scope_id});
  80. }
  81. // Returns the requested name scope.
  82. auto Get(NameScopeId scope_id) -> NameScope& { return values_.Get(scope_id); }
  83. // Returns the requested name scope.
  84. auto Get(NameScopeId scope_id) const -> const NameScope& {
  85. return values_.Get(scope_id);
  86. }
  87. // Returns the instruction owning the requested name scope, or an invalid
  88. // instruction if the scope is either invalid or has no associated
  89. // instruction.
  90. auto GetInstIdIfValid(NameScopeId scope_id) const -> InstId {
  91. if (!scope_id.is_valid()) {
  92. return InstId::Invalid;
  93. }
  94. return Get(scope_id).inst_id;
  95. }
  96. auto OutputYaml() const -> Yaml::OutputMapping {
  97. return values_.OutputYaml();
  98. }
  99. private:
  100. ValueStore<NameScopeId> values_;
  101. };
  102. } // namespace Carbon::SemIR
  103. #endif // CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_