pattern.cpp 3.0 KB

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