pattern.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 "executable_semantics/ast/static_scope.h"
  13. #include "llvm/ADT/ArrayRef.h"
  14. namespace Carbon {
  15. class Value;
  16. // Abstract base class of all AST nodes representing patterns.
  17. //
  18. // Pattern and its derived classes support LLVM-style RTTI, including
  19. // llvm::isa, llvm::cast, and llvm::dyn_cast. To support this, every
  20. // class derived from Pattern must provide a `classof` operation, and
  21. // every concrete derived class must have a corresponding enumerator
  22. // in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
  23. // details.
  24. class Pattern {
  25. public:
  26. enum class Kind {
  27. AutoPattern,
  28. BindingPattern,
  29. TuplePattern,
  30. AlternativePattern,
  31. ExpressionPattern,
  32. };
  33. Pattern(const Pattern&) = delete;
  34. auto operator=(const Pattern&) -> Pattern& = delete;
  35. void Print(llvm::raw_ostream& out) const;
  36. LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
  37. // Returns the enumerator corresponding to the most-derived type of this
  38. // object.
  39. auto kind() const -> Kind { return kind_; }
  40. auto source_loc() const -> SourceLocation { return source_loc_; }
  41. // The static type of this pattern. Cannot be called before typechecking.
  42. auto static_type() const -> const Value& { return **static_type_; }
  43. // Sets the static type of this expression. Can only be called once, during
  44. // typechecking.
  45. void set_static_type(Nonnull<const Value*> type) { static_type_ = type; }
  46. // Returns whether the static type has been set. Should only be called
  47. // during typechecking: before typechecking it's guaranteed to be false,
  48. // and after typechecking it's guaranteed to be true.
  49. auto has_static_type() const -> bool { return static_type_.has_value(); }
  50. // The value of this pattern. Cannot be called before typechecking.
  51. auto value() const -> const Value& { return **value_; }
  52. // Sets the value of this pattern. Can only be called once, during
  53. // typechecking.
  54. void set_value(Nonnull<const Value*> value) { value_ = value; }
  55. // Returns whether the value has been set. Should only be called
  56. // during typechecking: before typechecking it's guaranteed to be false,
  57. // and after typechecking it's guaranteed to be true.
  58. auto has_value() const -> bool { return value_.has_value(); }
  59. protected:
  60. // Constructs a Pattern representing syntax at the given line number.
  61. // `kind` must be the enumerator corresponding to the most-derived type being
  62. // constructed.
  63. Pattern(Kind kind, SourceLocation source_loc)
  64. : kind_(kind), source_loc_(source_loc) {}
  65. private:
  66. const Kind kind_;
  67. SourceLocation source_loc_;
  68. std::optional<Nonnull<const Value*>> static_type_;
  69. std::optional<Nonnull<const Value*>> value_;
  70. };
  71. // A pattern consisting of the `auto` keyword.
  72. class AutoPattern : public Pattern {
  73. public:
  74. explicit AutoPattern(SourceLocation source_loc)
  75. : Pattern(Kind::AutoPattern, source_loc) {}
  76. static auto classof(const Pattern* pattern) -> bool {
  77. return pattern->kind() == Kind::AutoPattern;
  78. }
  79. };
  80. // A pattern that matches a value of a specified type, and optionally binds
  81. // a name to it.
  82. class BindingPattern : public Pattern, public NamedEntityInterface {
  83. public:
  84. BindingPattern(SourceLocation source_loc, std::optional<std::string> name,
  85. Nonnull<Pattern*> type)
  86. : Pattern(Kind::BindingPattern, source_loc),
  87. name_(std::move(name)),
  88. type_(type) {}
  89. auto named_entity_kind() const -> NamedEntityKind override {
  90. return NamedEntityKind::BindingPattern;
  91. }
  92. auto source_loc() const -> SourceLocation override {
  93. return Pattern::source_loc();
  94. }
  95. static auto classof(const Pattern* pattern) -> bool {
  96. return pattern->kind() == Kind::BindingPattern;
  97. }
  98. // The name this pattern binds, if any.
  99. auto name() const -> const std::optional<std::string>& { return name_; }
  100. // The pattern specifying the type of values that this pattern matches.
  101. auto type() const -> const Pattern& { return *type_; }
  102. auto type() -> Pattern& { return *type_; }
  103. private:
  104. std::optional<std::string> name_;
  105. Nonnull<Pattern*> type_;
  106. };
  107. // A pattern that matches a tuple value field-wise.
  108. class TuplePattern : public Pattern {
  109. public:
  110. TuplePattern(SourceLocation source_loc, std::vector<Nonnull<Pattern*>> fields)
  111. : Pattern(Kind::TuplePattern, source_loc), fields_(std::move(fields)) {}
  112. static auto classof(const Pattern* pattern) -> bool {
  113. return pattern->kind() == Kind::TuplePattern;
  114. }
  115. auto fields() const -> llvm::ArrayRef<Nonnull<const Pattern*>> {
  116. return fields_;
  117. }
  118. auto fields() -> llvm::ArrayRef<Nonnull<Pattern*>> { return fields_; }
  119. private:
  120. std::vector<Nonnull<Pattern*>> fields_;
  121. };
  122. // Converts paren_contents to a Pattern, interpreting the parentheses as
  123. // grouping if their contents permit that interpretation, or as forming a
  124. // tuple otherwise.
  125. auto PatternFromParenContents(Nonnull<Arena*> arena, SourceLocation source_loc,
  126. const ParenContents<Pattern>& paren_contents)
  127. -> Nonnull<Pattern*>;
  128. // Converts paren_contents to a TuplePattern, interpreting the parentheses as
  129. // forming a tuple.
  130. auto TuplePatternFromParenContents(Nonnull<Arena*> arena,
  131. SourceLocation source_loc,
  132. const ParenContents<Pattern>& paren_contents)
  133. -> Nonnull<TuplePattern*>;
  134. // Converts `contents` to ParenContents<Pattern> by replacing each Expression
  135. // with an ExpressionPattern.
  136. auto ParenExpressionToParenPattern(Nonnull<Arena*> arena,
  137. const ParenContents<Expression>& contents)
  138. -> ParenContents<Pattern>;
  139. // A pattern that matches an alternative of a choice type.
  140. class AlternativePattern : public Pattern {
  141. public:
  142. // Constructs an AlternativePattern that matches a value of the type
  143. // specified by choice_type if it represents an alternative named
  144. // alternative_name, and its arguments match `arguments`.
  145. AlternativePattern(SourceLocation source_loc,
  146. Nonnull<Expression*> choice_type,
  147. std::string alternative_name,
  148. Nonnull<TuplePattern*> arguments)
  149. : Pattern(Kind::AlternativePattern, source_loc),
  150. choice_type_(choice_type),
  151. alternative_name_(std::move(alternative_name)),
  152. arguments_(arguments) {}
  153. // Constructs an AlternativePattern that matches the alternative specified
  154. // by `alternative`, if its arguments match `arguments`.
  155. AlternativePattern(SourceLocation source_loc,
  156. Nonnull<Expression*> alternative,
  157. Nonnull<TuplePattern*> arguments);
  158. static auto classof(const Pattern* pattern) -> bool {
  159. return pattern->kind() == Kind::AlternativePattern;
  160. }
  161. auto choice_type() const -> const Expression& { return *choice_type_; }
  162. auto choice_type() -> Expression& { return *choice_type_; }
  163. auto alternative_name() const -> const std::string& {
  164. return alternative_name_;
  165. }
  166. auto arguments() const -> const TuplePattern& { return *arguments_; }
  167. auto arguments() -> TuplePattern& { return *arguments_; }
  168. private:
  169. Nonnull<Expression*> choice_type_;
  170. std::string alternative_name_;
  171. Nonnull<TuplePattern*> arguments_;
  172. };
  173. // A pattern that matches a value if it is equal to the value of a given
  174. // expression.
  175. class ExpressionPattern : public Pattern {
  176. public:
  177. explicit ExpressionPattern(Nonnull<Expression*> expression)
  178. : Pattern(Kind::ExpressionPattern, expression->source_loc()),
  179. expression_(expression) {}
  180. static auto classof(const Pattern* pattern) -> bool {
  181. return pattern->kind() == Kind::ExpressionPattern;
  182. }
  183. auto expression() const -> const Expression& { return *expression_; }
  184. auto expression() -> Expression& { return *expression_; }
  185. private:
  186. Nonnull<Expression*> expression_;
  187. };
  188. } // namespace Carbon
  189. #endif // EXECUTABLE_SEMANTICS_AST_PATTERN_H_