name_scope.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. };
  65. // Provides a ValueStore wrapper for an API specific to name scopes.
  66. class NameScopeStore {
  67. public:
  68. // Adds a name scope, returning an ID to reference it.
  69. auto Add(InstId inst_id, NameId name_id, NameScopeId enclosing_scope_id)
  70. -> NameScopeId {
  71. return values_.Add({.inst_id = inst_id,
  72. .name_id = name_id,
  73. .enclosing_scope_id = enclosing_scope_id});
  74. }
  75. // Returns the requested name scope.
  76. auto Get(NameScopeId scope_id) -> NameScope& { return values_.Get(scope_id); }
  77. // Returns the requested name scope.
  78. auto Get(NameScopeId scope_id) const -> const NameScope& {
  79. return values_.Get(scope_id);
  80. }
  81. auto OutputYaml() const -> Yaml::OutputMapping {
  82. return values_.OutputYaml();
  83. }
  84. private:
  85. ValueStore<NameScopeId> values_;
  86. };
  87. } // namespace Carbon::SemIR
  88. #endif // CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_