pattern.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. #include "toolchain/sem_ir/pattern.h"
  5. #include "toolchain/base/kind_switch.h"
  6. #include "toolchain/sem_ir/ids.h"
  7. #include "toolchain/sem_ir/typed_insts.h"
  8. namespace Carbon::SemIR {
  9. // Returns the pattern instruction corresponding to the given ID, after
  10. // unwrapping any simple pattern operators such as `var`.
  11. static auto GetUnwrapped(const File& sem_ir, InstId pattern_id)
  12. -> std::pair<InstId, Inst> {
  13. auto inst_id = pattern_id;
  14. auto inst = sem_ir.insts().Get(inst_id);
  15. if (auto var_pattern = inst.TryAs<AnyVarPattern>()) {
  16. inst_id = var_pattern->subpattern_id;
  17. inst = sem_ir.insts().Get(inst_id);
  18. }
  19. return {inst_id, inst};
  20. }
  21. // Returns the name and entity name introduced by the given instruction if it is
  22. // a binding pattern, or otherwise `{None, None}`.
  23. static auto GetBoundEntityName(const File& sem_ir, Inst inst)
  24. -> std::pair<NameId, EntityNameId> {
  25. if (auto binding_pattern = inst.TryAs<AnyBindingPattern>()) {
  26. return {sem_ir.entity_names().Get(binding_pattern->entity_name_id).name_id,
  27. binding_pattern->entity_name_id};
  28. }
  29. return {NameId::None, EntityNameId::None};
  30. }
  31. auto IsSelfPattern(const File& sem_ir, InstId pattern_id) -> bool {
  32. auto [_, inst] = GetUnwrapped(sem_ir, pattern_id);
  33. auto [name_id, entity_name_id] = GetBoundEntityName(sem_ir, inst);
  34. return name_id == NameId::SelfValue;
  35. }
  36. auto GetFirstBindingNameFromPatternId(const File& sem_ir, InstId pattern_id)
  37. -> EntityNameId {
  38. llvm::SmallVector<InstId> work_list = {pattern_id};
  39. while (!work_list.empty()) {
  40. auto [_, inst] = GetUnwrapped(sem_ir, work_list.pop_back_val());
  41. if (auto tuple_patt = inst.TryAs<TuplePattern>()) {
  42. auto block = sem_ir.inst_blocks().Get(tuple_patt->elements_id);
  43. work_list.append(block.rbegin(), block.rend());
  44. continue;
  45. }
  46. // TODO: Look through struct patterns.
  47. if (auto form_pattern = inst.TryAs<FormParamPattern>()) {
  48. // TODO: This introduces a name, but we don't model it as a binding.
  49. return EntityNameId::None;
  50. }
  51. auto [name_id, entity_name_id] = GetBoundEntityName(sem_ir, inst);
  52. CARBON_CHECK(entity_name_id.has_value(), "Unhandled pattern inst kind {0}",
  53. inst);
  54. // Skip unnamed bindings.
  55. if (name_id != NameId::Underscore) {
  56. return entity_name_id;
  57. }
  58. }
  59. return EntityNameId::None;
  60. }
  61. auto GetPrettyNameFromPatternId(const File& sem_ir, InstId pattern_id)
  62. -> NameId {
  63. auto [inst_id, inst] = GetUnwrapped(sem_ir, pattern_id);
  64. CARBON_KIND_SWITCH(inst) {
  65. case CARBON_KIND_ANY(SemIR::AnyLeafParamPattern, param_pattern): {
  66. return param_pattern.pretty_name_id;
  67. }
  68. case CARBON_KIND_ANY(SemIR::AnyBindingPattern, _): {
  69. return GetBoundEntityName(sem_ir, inst).first;
  70. }
  71. default:
  72. return NameId::None;
  73. }
  74. }
  75. } // namespace Carbon::SemIR