handle_call_expression.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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/sem_ir/node.h"
  6. namespace Carbon::Check {
  7. auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
  8. // Process the final explicit call argument, but leave the arguments block on
  9. // the stack until we add the return slot argument.
  10. context.ParamOrArgEndNoPop(Parse::NodeKind::CallExpressionStart);
  11. // TODO: Convert to call expression.
  12. auto [call_expr_parse_node, name_id] =
  13. context.node_stack()
  14. .PopWithParseNode<Parse::NodeKind::CallExpressionStart>();
  15. auto name_node = context.semantics_ir().GetNode(name_id);
  16. if (name_node.kind() != SemIR::NodeKind::FunctionDeclaration) {
  17. // TODO: Work on error.
  18. context.TODO(parse_node, "Not a callable name");
  19. context.node_stack().Push(parse_node, name_id);
  20. context.ParamOrArgPop();
  21. return true;
  22. }
  23. auto function_id = name_node.GetAsFunctionDeclaration();
  24. const auto& callable = context.semantics_ir().GetFunction(function_id);
  25. // For functions with an implicit return type, the return type is the empty
  26. // tuple type.
  27. SemIR::TypeId type_id = callable.return_type_id;
  28. if (!type_id.is_valid()) {
  29. type_id = context.CanonicalizeTupleType(call_expr_parse_node, {});
  30. }
  31. // If there is a return slot, add a corresponding argument.
  32. if (callable.return_slot_id.is_valid()) {
  33. // Tentatively put storage for a temporary in the function's return slot.
  34. // This will be replaced if necessary when we perform initialization.
  35. auto temp_id = context.AddNode(SemIR::Node::TemporaryStorage::Make(
  36. call_expr_parse_node, callable.return_type_id));
  37. context.ParamOrArgSave(temp_id);
  38. }
  39. // Convert the arguments to match the parameters.
  40. auto refs_id = context.ParamOrArgPop();
  41. if (!context.ImplicitAsForArgs(call_expr_parse_node, refs_id,
  42. name_node.parse_node(), callable.param_refs_id,
  43. callable.return_slot_id.is_valid())) {
  44. context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
  45. return true;
  46. }
  47. auto call_node_id = context.AddNode(SemIR::Node::Call::Make(
  48. call_expr_parse_node, type_id, refs_id, function_id));
  49. context.node_stack().Push(parse_node, call_node_id);
  50. return true;
  51. }
  52. auto HandleCallExpressionComma(Context& context, Parse::Node /*parse_node*/)
  53. -> bool {
  54. context.ParamOrArgComma();
  55. return true;
  56. }
  57. auto HandleCallExpressionStart(Context& context, Parse::Node parse_node)
  58. -> bool {
  59. auto name_id = context.node_stack().PopExpression();
  60. context.node_stack().Push(parse_node, name_id);
  61. context.ParamOrArgStart();
  62. return true;
  63. }
  64. } // namespace Carbon::Check