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