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