semantics_handle_index.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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 <cstdint>
  5. #include "toolchain/semantics/semantics_context.h"
  6. #include "toolchain/semantics/semantics_node.h"
  7. #include "toolchain/semantics/semantics_node_kind.h"
  8. namespace Carbon {
  9. auto SemanticsHandleIndexExpressionStart(SemanticsContext& /*context*/,
  10. ParseTree::Node /*parse_node*/)
  11. -> bool {
  12. // Leave the expression on the stack for IndexExpression.
  13. return true;
  14. }
  15. auto SemanticsHandleIndexExpression(SemanticsContext& context,
  16. ParseTree::Node parse_node) -> bool {
  17. auto index_node_id = context.node_stack().PopExpression();
  18. auto index_node = context.semantics_ir().GetNode(index_node_id);
  19. auto name_node_id = context.node_stack().PopExpression();
  20. auto name_node = context.semantics_ir().GetNode(name_node_id);
  21. auto name_type_id =
  22. context.semantics_ir().GetTypeAllowBuiltinTypes(name_node.type_id());
  23. auto name_type_node = context.semantics_ir().GetNode(name_type_id);
  24. if (name_type_node.kind() == SemanticsNodeKind::TupleType &&
  25. index_node.kind() == SemanticsNodeKind::IntegerLiteral) {
  26. const auto& index_val = context.semantics_ir().GetIntegerLiteral(
  27. index_node.GetAsIntegerLiteral());
  28. auto type_block =
  29. context.semantics_ir().GetTypeBlock(name_type_node.GetAsTupleType());
  30. if (index_val.uge(static_cast<uint64_t>(type_block.size()))) {
  31. CARBON_DIAGNOSTIC(OutOfBoundsAccess, Error,
  32. "Index `{0}` is past the end of `{1}`.", llvm::APSInt,
  33. std::string);
  34. context.emitter().Emit(
  35. parse_node, OutOfBoundsAccess,
  36. llvm::APSInt(index_val, /*isUnsigned=*/true),
  37. context.semantics_ir().StringifyType(name_node.type_id()));
  38. } else {
  39. context.AddNodeAndPush(
  40. parse_node, SemanticsNode::Index::Make(
  41. parse_node, type_block[index_val.getZExtValue()],
  42. name_node_id, index_node_id));
  43. return true;
  44. }
  45. } else if (index_node.kind() != SemanticsNodeKind::IntegerLiteral) {
  46. CARBON_DIAGNOSTIC(NondeterministicType, Error,
  47. "Type cannot be determined at compile time.");
  48. context.emitter().Emit(parse_node, NondeterministicType);
  49. } else if (name_type_node.kind() != SemanticsNodeKind::TupleType &&
  50. name_type_id != SemanticsNodeId::BuiltinError) {
  51. CARBON_DIAGNOSTIC(InvalidIndexExpression, Error,
  52. "Invalid index expression.");
  53. context.emitter().Emit(parse_node, InvalidIndexExpression);
  54. }
  55. context.node_stack().Push(parse_node, SemanticsNodeId::BuiltinError);
  56. return true;
  57. }
  58. } // namespace Carbon