semantics_handle_if_statement.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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/semantics/semantics_context.h"
  5. #include "toolchain/semantics/semantics_node.h"
  6. namespace Carbon::Check {
  7. auto HandleIfConditionStart(Context& /*context*/,
  8. ParseTree::Node /*parse_node*/) -> bool {
  9. return true;
  10. }
  11. auto HandleIfCondition(Context& context, ParseTree::Node parse_node) -> bool {
  12. // Convert the condition to `bool`.
  13. auto cond_value_id = context.node_stack().PopExpression();
  14. cond_value_id = context.ImplicitAsBool(parse_node, cond_value_id);
  15. // Create the then block and the else block, and branch to the right one. If
  16. // there is no `else`, the then block will terminate with a branch to the
  17. // else block, which will be reused as the resumption block.
  18. auto then_block_id =
  19. context.AddDominatedBlockAndBranchIf(parse_node, cond_value_id);
  20. auto else_block_id = context.AddDominatedBlockAndBranch(parse_node);
  21. // Push the else and then blocks, and start emitting code in the then block.
  22. context.node_block_stack().Pop();
  23. context.node_block_stack().Push(else_block_id);
  24. context.node_block_stack().Push(then_block_id);
  25. context.AddCurrentCodeBlockToFunction();
  26. context.node_stack().Push(parse_node);
  27. return true;
  28. }
  29. auto HandleIfStatementElse(Context& context, ParseTree::Node parse_node)
  30. -> bool {
  31. context.node_stack().PopAndDiscardSoloParseNode<ParseNodeKind::IfCondition>();
  32. // Switch to emitting the else block.
  33. auto then_block_id = context.node_block_stack().PopForAdd();
  34. context.node_stack().Push(parse_node, then_block_id);
  35. context.AddCurrentCodeBlockToFunction();
  36. return true;
  37. }
  38. auto HandleIfStatement(Context& context, ParseTree::Node parse_node) -> bool {
  39. // Either the then or else block, depending on whether there's an `else` node
  40. // on the top of the node stack.
  41. auto sub_block_id = context.node_block_stack().PopForAdd();
  42. switch (auto kind = context.parse_tree().node_kind(
  43. context.node_stack().PeekParseNode())) {
  44. case ParseNodeKind::IfCondition: {
  45. // Branch from then block to else block.
  46. context.node_stack()
  47. .PopAndDiscardSoloParseNode<ParseNodeKind::IfCondition>();
  48. context.AddNodeToBlock(
  49. sub_block_id,
  50. SemIR::Node::Branch::Make(parse_node,
  51. context.node_block_stack().PeekForAdd()));
  52. break;
  53. }
  54. case ParseNodeKind::IfStatementElse: {
  55. // Branch from the then and else blocks to a new resumption block.
  56. SemIR::NodeBlockId then_block_id =
  57. context.node_stack().Pop<ParseNodeKind::IfStatementElse>();
  58. context.AddConvergenceBlockAndPush(parse_node,
  59. {then_block_id, sub_block_id});
  60. break;
  61. }
  62. default: {
  63. CARBON_FATAL() << "Unexpected parse node at start of `if`: " << kind;
  64. }
  65. }
  66. context.AddCurrentCodeBlockToFunction();
  67. return true;
  68. }
  69. } // namespace Carbon::Check