handle_variable.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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/context.h"
  5. #include "toolchain/check/convert.h"
  6. #include "toolchain/sem_ir/inst.h"
  7. namespace Carbon::Check {
  8. auto HandleVariableIntroducer(Context& context, Parse::NodeId parse_node)
  9. -> bool {
  10. // No action, just a bracketing node.
  11. context.node_stack().Push(parse_node);
  12. return true;
  13. }
  14. auto HandleReturnedModifier(Context& context, Parse::NodeId parse_node)
  15. -> bool {
  16. // No action, just a bracketing node.
  17. context.node_stack().Push(parse_node);
  18. return true;
  19. }
  20. auto HandleVariableInitializer(Context& context, Parse::NodeId parse_node)
  21. -> bool {
  22. // No action, just a bracketing node.
  23. context.node_stack().Push(parse_node);
  24. return true;
  25. }
  26. auto HandleVariableDecl(Context& context, Parse::NodeId parse_node) -> bool {
  27. // Handle the optional initializer.
  28. auto init_id = SemIR::InstId::Invalid;
  29. bool has_init =
  30. context.parse_tree().node_kind(context.node_stack().PeekParseNode()) !=
  31. Parse::NodeKind::BindingPattern;
  32. if (has_init) {
  33. init_id = context.node_stack().PopExpr();
  34. context.node_stack()
  35. .PopAndDiscardSoloParseNode<Parse::NodeKind::VariableInitializer>();
  36. }
  37. // Extract the name binding.
  38. auto value_id = context.node_stack().Pop<Parse::NodeKind::BindingPattern>();
  39. if (auto bind_name = context.insts().Get(value_id).TryAs<SemIR::BindName>()) {
  40. // Form a corresponding name in the current context, and bind the name to
  41. // the variable.
  42. context.decl_name_stack().AddNameToLookup(
  43. context.decl_name_stack().MakeUnqualifiedName(bind_name->parse_node,
  44. bind_name->name_id),
  45. value_id);
  46. value_id = bind_name->value_id;
  47. }
  48. // Pop the `returned` specifier if present.
  49. context.node_stack()
  50. .PopAndDiscardSoloParseNodeIf<Parse::NodeKind::ReturnedModifier>();
  51. // If there was an initializer, assign it to the storage.
  52. if (has_init) {
  53. if (context.GetCurrentScopeAs<SemIR::ClassDecl>()) {
  54. // TODO: In a class scope, we should instead save the initializer
  55. // somewhere so that we can use it as a default.
  56. context.TODO(parse_node, "Field initializer");
  57. } else {
  58. init_id = Initialize(context, parse_node, value_id, init_id);
  59. // TODO: Consider using different instruction kinds for assignment versus
  60. // initialization.
  61. context.AddInst(SemIR::Assign{parse_node, value_id, init_id});
  62. }
  63. }
  64. context.node_stack()
  65. .PopAndDiscardSoloParseNode<Parse::NodeKind::VariableIntroducer>();
  66. return true;
  67. }
  68. } // namespace Carbon::Check