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