pattern.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. #ifndef EXECUTABLE_SEMANTICS_AST_PATTERN_H_
  5. #define EXECUTABLE_SEMANTICS_AST_PATTERN_H_
  6. #include <optional>
  7. #include <string>
  8. #include <vector>
  9. #include "common/ostream.h"
  10. #include "executable_semantics/ast/expression.h"
  11. #include "executable_semantics/ast/source_location.h"
  12. namespace Carbon {
  13. // Abstract base class of all AST nodes representing patterns.
  14. //
  15. // Pattern and its derived classes support LLVM-style RTTI, including
  16. // llvm::isa, llvm::cast, and llvm::dyn_cast. To support this, every
  17. // class derived from Pattern must provide a `classof` operation, and
  18. // every concrete derived class must have a corresponding enumerator
  19. // in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
  20. // details.
  21. class Pattern {
  22. public:
  23. enum class Kind {
  24. AutoPattern,
  25. BindingPattern,
  26. TuplePattern,
  27. AlternativePattern,
  28. ExpressionPattern,
  29. };
  30. Pattern(const Pattern&) = delete;
  31. Pattern& operator=(const Pattern&) = delete;
  32. // Returns the enumerator corresponding to the most-derived type of this
  33. // object.
  34. auto Tag() const -> Kind { return tag; }
  35. auto SourceLoc() const -> SourceLocation { return loc; }
  36. void Print(llvm::raw_ostream& out) const;
  37. LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
  38. protected:
  39. // Constructs a Pattern representing syntax at the given line number.
  40. // `tag` must be the enumerator corresponding to the most-derived type being
  41. // constructed.
  42. Pattern(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {}
  43. private:
  44. const Kind tag;
  45. SourceLocation loc;
  46. };
  47. // A pattern consisting of the `auto` keyword.
  48. class AutoPattern : public Pattern {
  49. public:
  50. explicit AutoPattern(SourceLocation loc) : Pattern(Kind::AutoPattern, loc) {}
  51. static auto classof(const Pattern* pattern) -> bool {
  52. return pattern->Tag() == Kind::AutoPattern;
  53. }
  54. };
  55. // A pattern that matches a value of a specified type, and optionally binds
  56. // a name to it.
  57. class BindingPattern : public Pattern {
  58. public:
  59. BindingPattern(SourceLocation loc, std::optional<std::string> name,
  60. Nonnull<const Pattern*> type)
  61. : Pattern(Kind::BindingPattern, loc), name(std::move(name)), type(type) {}
  62. static auto classof(const Pattern* pattern) -> bool {
  63. return pattern->Tag() == Kind::BindingPattern;
  64. }
  65. // The name this pattern binds, if any.
  66. auto Name() const -> const std::optional<std::string>& { return name; }
  67. // The pattern specifying the type of values that this pattern matches.
  68. auto Type() const -> Nonnull<const Pattern*> { return type; }
  69. private:
  70. std::optional<std::string> name;
  71. Nonnull<const Pattern*> type;
  72. };
  73. // A pattern that matches a tuple value field-wise.
  74. class TuplePattern : public Pattern {
  75. public:
  76. // Represents a portion of a tuple pattern corresponding to a single field.
  77. struct Field {
  78. Field(std::string name, Nonnull<const Pattern*> pattern)
  79. : name(std::move(name)), pattern(pattern) {}
  80. // The field name. Cannot be empty
  81. std::string name;
  82. // The pattern the field must match.
  83. Nonnull<const Pattern*> pattern;
  84. };
  85. TuplePattern(SourceLocation loc, std::vector<Field> fields)
  86. : Pattern(Kind::TuplePattern, loc), fields(std::move(fields)) {}
  87. // Converts tuple_literal to a TuplePattern, by wrapping each field in an
  88. // ExpressionPattern.
  89. //
  90. // REQUIRES: tuple_literal->Tag() == Expression::Kind::TupleLiteral
  91. TuplePattern(Nonnull<Arena*> arena, Nonnull<const Expression*> tuple_literal);
  92. static auto classof(const Pattern* pattern) -> bool {
  93. return pattern->Tag() == Kind::TuplePattern;
  94. }
  95. auto Fields() const -> const std::vector<Field>& { return fields; }
  96. private:
  97. std::vector<Field> fields;
  98. };
  99. // Converts paren_contents to a Pattern, interpreting the parentheses as
  100. // grouping if their contents permit that interpretation, or as forming a
  101. // tuple otherwise.
  102. auto PatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
  103. const ParenContents<Pattern>& paren_contents)
  104. -> Nonnull<const Pattern*>;
  105. // Converts paren_contents to a TuplePattern, interpreting the parentheses as
  106. // forming a tuple.
  107. auto TuplePatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
  108. const ParenContents<Pattern>& paren_contents)
  109. -> Nonnull<const TuplePattern*>;
  110. // Converts `contents` to ParenContents<Pattern> by replacing each Expression
  111. // with an ExpressionPattern.
  112. auto ParenExpressionToParenPattern(Nonnull<Arena*> arena,
  113. const ParenContents<Expression>& contents)
  114. -> ParenContents<Pattern>;
  115. // A pattern that matches an alternative of a choice type.
  116. class AlternativePattern : public Pattern {
  117. public:
  118. // Constructs an AlternativePattern that matches a value of the type
  119. // specified by choice_type if it represents an alternative named
  120. // alternative_name, and its arguments match `arguments`.
  121. AlternativePattern(SourceLocation loc, Nonnull<const Expression*> choice_type,
  122. std::string alternative_name,
  123. Nonnull<const TuplePattern*> arguments)
  124. : Pattern(Kind::AlternativePattern, loc),
  125. choice_type(choice_type),
  126. alternative_name(std::move(alternative_name)),
  127. arguments(arguments) {}
  128. // Constructs an AlternativePattern that matches the alternative specified
  129. // by `alternative`, if its arguments match `arguments`.
  130. AlternativePattern(SourceLocation loc, Nonnull<const Expression*> alternative,
  131. Nonnull<const TuplePattern*> arguments);
  132. static auto classof(const Pattern* pattern) -> bool {
  133. return pattern->Tag() == Kind::AlternativePattern;
  134. }
  135. auto ChoiceType() const -> Nonnull<const Expression*> { return choice_type; }
  136. auto AlternativeName() const -> const std::string& {
  137. return alternative_name;
  138. }
  139. auto Arguments() const -> Nonnull<const TuplePattern*> { return arguments; }
  140. private:
  141. Nonnull<const Expression*> choice_type;
  142. std::string alternative_name;
  143. Nonnull<const TuplePattern*> arguments;
  144. };
  145. // A pattern that matches a value if it is equal to the value of a given
  146. // expression.
  147. class ExpressionPattern : public Pattern {
  148. public:
  149. ExpressionPattern(Nonnull<const Expression*> expression)
  150. : Pattern(Kind::ExpressionPattern, expression->SourceLoc()),
  151. expression(expression) {}
  152. static auto classof(const Pattern* pattern) -> bool {
  153. return pattern->Tag() == Kind::ExpressionPattern;
  154. }
  155. auto Expression() const -> Nonnull<const Expression*> { return expression; }
  156. private:
  157. Nonnull<const Carbon::Expression*> expression;
  158. };
  159. } // namespace Carbon
  160. #endif // EXECUTABLE_SEMANTICS_AST_PATTERN_H_