pattern.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. auto [name_id, entity_name_id] = GetBoundEntityName(sem_ir, inst);
  48. CARBON_CHECK(entity_name_id.has_value(), "Unhandled pattern inst kind {0}",
  49. inst);
  50. // Skip unnamed bindings.
  51. if (name_id != NameId::Underscore) {
  52. return entity_name_id;
  53. }
  54. }
  55. return EntityNameId::None;
  56. }
  57. auto GetPrettyNameFromPatternId(const File& sem_ir, InstId pattern_id)
  58. -> NameId {
  59. auto [inst_id, inst] = GetUnwrapped(sem_ir, pattern_id);
  60. CARBON_KIND_SWITCH(inst) {
  61. case CARBON_KIND_ANY(SemIR::AnyLeafParamPattern, param_pattern): {
  62. return param_pattern.pretty_name_id;
  63. }
  64. case CARBON_KIND_ANY(SemIR::AnyBindingPattern, _): {
  65. return GetBoundEntityName(sem_ir, inst).first;
  66. }
  67. default:
  68. return NameId::None;
  69. }
  70. }
  71. } // namespace Carbon::SemIR