action.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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_CHECK_ACTION_H_
  5. #define CARBON_TOOLCHAIN_CHECK_ACTION_H_
  6. #include "toolchain/check/context.h"
  7. #include "toolchain/check/inst.h"
  8. #include "toolchain/sem_ir/ids.h"
  9. #include "toolchain/sem_ir/inst.h"
  10. namespace Carbon::Check {
  11. // Performs a member access action. Defined in member_access.cpp.
  12. auto PerformAction(Context& context, SemIR::LocId loc_id,
  13. SemIR::AccessMemberAction action) -> SemIR::InstId;
  14. auto PerformAction(Context& context, SemIR::LocId loc_id,
  15. SemIR::AccessOptionalMemberAction action) -> SemIR::InstId;
  16. // Performs a conversion action. Defined in convert.cpp.
  17. auto PerformAction(Context& context, SemIR::LocId loc_id,
  18. SemIR::ConvertToValueAction action) -> SemIR::InstId;
  19. // Performs a type refinement action, by creating a conversion from an
  20. // instruction with a template-dependent symbolic type to the corresponding
  21. // instantiated type.
  22. auto PerformAction(Context& context, SemIR::LocId loc_id,
  23. SemIR::RefineTypeAction action) -> SemIR::InstId;
  24. // Determines whether the given action depends on a template parameter in a way
  25. // that means it cannot be performed immediately.
  26. auto ActionIsDependent(Context& context, SemIR::Inst action_inst) -> bool;
  27. // Determines whether the given action operand depends on a template parameter
  28. // in a way that means the action cannot be performed immediately.
  29. auto OperandIsDependent(Context& context, SemIR::InstId inst_id) -> bool;
  30. // Determines whether the given action operand depends on a template parameter
  31. // in a way that means the action cannot be performed immediately.
  32. auto OperandIsDependent(Context& context, SemIR::TypeInstId inst_id) -> bool;
  33. // Determines whether the given type depends on a template parameter
  34. // in a way that means the action cannot be performed immediately.
  35. auto OperandIsDependent(Context& context, SemIR::TypeId type_id) -> bool;
  36. // Adds an instruction to the current block to splice in the result of
  37. // performing a dependent action.
  38. auto AddDependentActionSplice(Context& context, SemIR::LocIdAndInst action,
  39. SemIR::TypeInstId result_type_inst_id)
  40. -> SemIR::InstId;
  41. // Convenience wrapper for `AddDependentActionSplice`.
  42. template <typename LocT, typename InstT>
  43. auto AddDependentActionSplice(Context& context, LocT loc, InstT inst,
  44. SemIR::TypeInstId result_type_inst_id)
  45. -> SemIR::InstId {
  46. return AddDependentActionSplice(context, SemIR::LocIdAndInst(loc, inst),
  47. result_type_inst_id);
  48. }
  49. // Handles a new action. If the action is not dependent, it is performed
  50. // immediately. Otherwise, adds the action to the enclosing template's eval
  51. // block and creates an instruction to splice in the result of the action.
  52. template <typename ActionT>
  53. auto HandleAction(Context& context, SemIR::LocId loc_id, ActionT action_inst,
  54. SemIR::TypeInstId result_type_inst_id =
  55. SemIR::TypeInstId::None) -> SemIR::InstId {
  56. if (ActionIsDependent(context, action_inst) ||
  57. (result_type_inst_id.has_value() &&
  58. OperandIsDependent(context, result_type_inst_id))) {
  59. return AddDependentActionSplice(
  60. context, SemIR::LocIdAndInst(loc_id, action_inst), result_type_inst_id);
  61. }
  62. return PerformAction(context, loc_id, action_inst);
  63. }
  64. namespace Internal {
  65. // Performs setup steps for performing a delayed action. This is an
  66. // implementation detail of PerformDelayedAction and should not be called
  67. // directly.
  68. auto BeginPerformDelayedAction(Context& context) -> void;
  69. // Performs cleanup steps for performing a delayed action. This is an
  70. // implementation detail of PerformDelayedAction and should not be called
  71. // directly.
  72. auto EndPerformDelayedAction(Context& context, SemIR::InstId result_id)
  73. -> SemIR::InstId;
  74. } // namespace Internal
  75. // Performs an action as a result of evaluation of a template's eval block.
  76. template <typename ActionT>
  77. auto PerformDelayedAction(Context& context, SemIR::LocId loc_id,
  78. ActionT action_inst) -> SemIR::InstId {
  79. if (ActionIsDependent(context, action_inst)) {
  80. return SemIR::InstId::None;
  81. }
  82. Internal::BeginPerformDelayedAction(context);
  83. auto inst_id = PerformAction(context, loc_id, action_inst);
  84. return Internal::EndPerformDelayedAction(context, inst_id);
  85. }
  86. } // namespace Carbon::Check
  87. #endif // CARBON_TOOLCHAIN_CHECK_ACTION_H_