pattern.cpp 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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/check/pattern.h"
  5. #include "toolchain/check/inst.h"
  6. #include "toolchain/check/type.h"
  7. namespace Carbon::Check {
  8. auto BeginSubpattern(Context& context) -> void {
  9. context.inst_block_stack().Push();
  10. context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd());
  11. }
  12. auto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id)
  13. -> SemIR::ExprRegionId {
  14. if (context.region_stack().PeekRegion().size() > 1) {
  15. // End the exit block with a branch to a successor block, whose contents
  16. // will be determined later.
  17. AddInst(context,
  18. SemIR::LocIdAndInst::NoLoc<SemIR::Branch>(
  19. {.target_id = context.inst_blocks().AddPlaceholder()}));
  20. } else {
  21. // This single-block region will be inserted as a SpliceBlock, so we don't
  22. // need control flow out of it.
  23. }
  24. auto block_id = context.inst_block_stack().Pop();
  25. CARBON_CHECK(block_id == context.region_stack().PeekRegion().back());
  26. // TODO: Is it possible to validate that this region is genuinely
  27. // single-entry, single-exit?
  28. return context.sem_ir().expr_regions().Add(
  29. {.block_ids = context.region_stack().PopRegion(),
  30. .result_id = result_id});
  31. }
  32. auto EndSubpatternAsNonExpr(Context& context) -> void {
  33. auto block_id = context.inst_block_stack().Pop();
  34. CARBON_CHECK(block_id == context.region_stack().PeekRegion().back());
  35. CARBON_CHECK(context.region_stack().PeekRegion().size() == 1);
  36. CARBON_CHECK(context.inst_blocks().Get(block_id).empty());
  37. context.region_stack().PopAndDiscardRegion();
  38. }
  39. auto AddBindingPattern(Context& context, SemIR::LocId name_loc,
  40. SemIR::NameId name_id, SemIR::TypeId type_id,
  41. SemIR::ExprRegionId type_region_id, bool is_generic,
  42. bool is_template) -> BindingPatternInfo {
  43. auto entity_name_id = context.entity_names().AddSymbolicBindingName(
  44. name_id, context.scope_stack().PeekNameScopeId(),
  45. is_generic ? context.scope_stack().AddCompileTimeBinding()
  46. : SemIR::CompileTimeBindIndex::None,
  47. is_template);
  48. auto bind_id = SemIR::InstId::None;
  49. if (is_generic) {
  50. bind_id = AddInstInNoBlock<SemIR::BindSymbolicName>(
  51. context, name_loc,
  52. {.type_id = type_id,
  53. .entity_name_id = entity_name_id,
  54. .value_id = SemIR::InstId::None});
  55. } else {
  56. bind_id =
  57. AddInstInNoBlock<SemIR::BindName>(context, name_loc,
  58. {.type_id = type_id,
  59. .entity_name_id = entity_name_id,
  60. .value_id = SemIR::InstId::None});
  61. }
  62. auto pattern_type_id = GetPatternType(context, type_id);
  63. auto binding_pattern_id = SemIR::InstId::None;
  64. if (is_generic) {
  65. binding_pattern_id = AddPatternInst<SemIR::SymbolicBindingPattern>(
  66. context, name_loc,
  67. {.type_id = pattern_type_id, .entity_name_id = entity_name_id});
  68. } else {
  69. binding_pattern_id = AddPatternInst<SemIR::BindingPattern>(
  70. context, name_loc,
  71. {.type_id = pattern_type_id, .entity_name_id = entity_name_id});
  72. }
  73. if (is_generic) {
  74. context.scope_stack().PushCompileTimeBinding(bind_id);
  75. }
  76. bool inserted =
  77. context.bind_name_map()
  78. .Insert(binding_pattern_id, {.bind_name_id = bind_id,
  79. .type_expr_region_id = type_region_id})
  80. .is_inserted();
  81. CARBON_CHECK(inserted);
  82. return {.pattern_id = binding_pattern_id, .bind_id = bind_id};
  83. }
  84. } // namespace Carbon::Check