pattern.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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 EXPLORER_AST_PATTERN_H_
  5. #define EXPLORER_AST_PATTERN_H_
  6. #include <optional>
  7. #include <string>
  8. #include <vector>
  9. #include "common/ostream.h"
  10. #include "explorer/ast/ast_node.h"
  11. #include "explorer/ast/ast_rtti.h"
  12. #include "explorer/ast/expression.h"
  13. #include "explorer/ast/static_scope.h"
  14. #include "explorer/ast/value_category.h"
  15. #include "explorer/common/source_location.h"
  16. #include "llvm/ADT/ArrayRef.h"
  17. namespace Carbon {
  18. class Value;
  19. // Abstract base class of all AST nodes representing patterns.
  20. //
  21. // Pattern and its derived classes support LLVM-style RTTI, including
  22. // llvm::isa, llvm::cast, and llvm::dyn_cast. To support this, every
  23. // class derived from Pattern must provide a `classof` operation, and
  24. // every concrete derived class must have a corresponding enumerator
  25. // in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
  26. // details.
  27. class Pattern : public AstNode {
  28. public:
  29. Pattern(const Pattern&) = delete;
  30. auto operator=(const Pattern&) -> Pattern& = delete;
  31. ~Pattern() override = 0;
  32. void Print(llvm::raw_ostream& out) const override;
  33. void PrintID(llvm::raw_ostream& out) const override;
  34. static auto classof(const AstNode* node) -> bool {
  35. return InheritsFromPattern(node->kind());
  36. }
  37. // Returns the enumerator corresponding to the most-derived type of this
  38. // object.
  39. auto kind() const -> PatternKind {
  40. return static_cast<PatternKind>(root_kind());
  41. }
  42. // The static type of this pattern. Cannot be called before typechecking.
  43. auto static_type() const -> const Value& {
  44. CARBON_CHECK(static_type_.has_value());
  45. return **static_type_;
  46. }
  47. // Sets the static type of this expression. Can only be called once, during
  48. // typechecking.
  49. void set_static_type(Nonnull<const Value*> type) {
  50. CARBON_CHECK(!static_type_.has_value());
  51. static_type_ = type;
  52. }
  53. // The value of this pattern. Cannot be called before typechecking.
  54. // TODO rename to avoid confusion with BindingPattern::constant_value
  55. auto value() const -> const Value& { return **value_; }
  56. // Sets the value of this pattern. Can only be called once, during
  57. // typechecking.
  58. void set_value(Nonnull<const Value*> value) { value_ = value; }
  59. // Returns whether the value has been set. Should only be called
  60. // during typechecking: before typechecking it's guaranteed to be false,
  61. // and after typechecking it's guaranteed to be true.
  62. auto has_value() const -> bool { return value_.has_value(); }
  63. protected:
  64. // Constructs a Pattern representing syntax at the given line number.
  65. // `kind` must be the enumerator corresponding to the most-derived type being
  66. // constructed.
  67. Pattern(AstNodeKind kind, SourceLocation source_loc)
  68. : AstNode(kind, source_loc) {}
  69. private:
  70. std::optional<Nonnull<const Value*>> static_type_;
  71. std::optional<Nonnull<const Value*>> value_;
  72. };
  73. class BindingPattern;
  74. // Returns all `BindingPattern`s in the AST subtree rooted at `pattern`.
  75. auto GetBindings(const Pattern& pattern)
  76. -> std::vector<Nonnull<const BindingPattern*>>;
  77. // A pattern consisting of the `auto` keyword.
  78. class AutoPattern : public Pattern {
  79. public:
  80. explicit AutoPattern(SourceLocation source_loc)
  81. : Pattern(AstNodeKind::AutoPattern, source_loc) {}
  82. static auto classof(const AstNode* node) -> bool {
  83. return InheritsFromAutoPattern(node->kind());
  84. }
  85. };
  86. class VarPattern : public Pattern {
  87. public:
  88. explicit VarPattern(SourceLocation source_loc, Nonnull<Pattern*> pattern)
  89. : Pattern(AstNodeKind::VarPattern, source_loc), pattern_(pattern) {}
  90. static auto classof(const AstNode* node) -> bool {
  91. return InheritsFromVarPattern(node->kind());
  92. }
  93. auto pattern() const -> const Pattern& { return *pattern_; }
  94. auto pattern() -> Pattern& { return *pattern_; }
  95. auto value_category() const -> ValueCategory { return ValueCategory::Var; }
  96. private:
  97. Nonnull<Pattern*> pattern_;
  98. };
  99. // A pattern that matches a value of a specified type, and optionally binds
  100. // a name to it.
  101. class BindingPattern : public Pattern {
  102. public:
  103. using ImplementsCarbonValueNode = void;
  104. BindingPattern(SourceLocation source_loc, std::string name,
  105. Nonnull<Pattern*> type,
  106. std::optional<ValueCategory> value_category)
  107. : Pattern(AstNodeKind::BindingPattern, source_loc),
  108. name_(std::move(name)),
  109. type_(type),
  110. value_category_(value_category) {}
  111. static auto classof(const AstNode* node) -> bool {
  112. return InheritsFromBindingPattern(node->kind());
  113. }
  114. // The name this pattern binds, if any. If equal to AnonymousName, indicates
  115. // that this BindingPattern does not bind a name, which in turn means it
  116. // should not be used as a ValueNode.
  117. auto name() const -> const std::string& { return name_; }
  118. // The pattern specifying the type of values that this pattern matches.
  119. auto type() const -> const Pattern& { return *type_; }
  120. auto type() -> Pattern& { return *type_; }
  121. // Returns the value category of this pattern. Can only be called after
  122. // typechecking.
  123. auto value_category() const -> ValueCategory {
  124. return value_category_.value();
  125. }
  126. // Returns whether the value category has been set. Should only be called
  127. // during typechecking.
  128. auto has_value_category() const -> bool {
  129. return value_category_.has_value();
  130. }
  131. // Sets the value category of the variable being bound. Can only be called
  132. // once during typechecking
  133. void set_value_category(ValueCategory vc) {
  134. CARBON_CHECK(!value_category_.has_value());
  135. value_category_ = vc;
  136. }
  137. auto constant_value() const -> std::optional<Nonnull<const Value*>> {
  138. return std::nullopt;
  139. }
  140. auto symbolic_identity() const -> std::optional<Nonnull<const Value*>> {
  141. return std::nullopt;
  142. }
  143. private:
  144. std::string name_;
  145. Nonnull<Pattern*> type_;
  146. std::optional<ValueCategory> value_category_;
  147. };
  148. // A pattern that matches a tuple value field-wise.
  149. class TuplePattern : public Pattern {
  150. public:
  151. TuplePattern(SourceLocation source_loc, std::vector<Nonnull<Pattern*>> fields)
  152. : Pattern(AstNodeKind::TuplePattern, source_loc),
  153. fields_(std::move(fields)) {}
  154. static auto classof(const AstNode* node) -> bool {
  155. return InheritsFromTuplePattern(node->kind());
  156. }
  157. auto fields() const -> llvm::ArrayRef<Nonnull<const Pattern*>> {
  158. return fields_;
  159. }
  160. auto fields() -> llvm::ArrayRef<Nonnull<Pattern*>> { return fields_; }
  161. private:
  162. std::vector<Nonnull<Pattern*>> fields_;
  163. };
  164. class GenericBinding : public Pattern {
  165. public:
  166. using ImplementsCarbonValueNode = void;
  167. GenericBinding(SourceLocation source_loc, std::string name,
  168. Nonnull<Expression*> type)
  169. : Pattern(AstNodeKind::GenericBinding, source_loc),
  170. name_(std::move(name)),
  171. type_(type) {}
  172. void Print(llvm::raw_ostream& out) const override;
  173. void PrintID(llvm::raw_ostream& out) const override;
  174. static auto classof(const AstNode* node) -> bool {
  175. return InheritsFromGenericBinding(node->kind());
  176. }
  177. auto name() const -> const std::string& { return name_; }
  178. auto type() const -> const Expression& { return *type_; }
  179. auto type() -> Expression& { return *type_; }
  180. auto value_category() const -> ValueCategory { return ValueCategory::Let; }
  181. auto constant_value() const -> std::optional<Nonnull<const Value*>> {
  182. return std::nullopt;
  183. }
  184. auto symbolic_identity() const -> std::optional<Nonnull<const Value*>> {
  185. return symbolic_identity_;
  186. }
  187. void set_symbolic_identity(Nonnull<const Value*> value) {
  188. CARBON_CHECK(!symbolic_identity_.has_value());
  189. symbolic_identity_ = value;
  190. }
  191. // The impl binding associated with this type variable.
  192. auto impl_binding() const -> std::optional<Nonnull<const ImplBinding*>> {
  193. return impl_binding_;
  194. }
  195. // Set the impl binding.
  196. void set_impl_binding(Nonnull<const ImplBinding*> binding) {
  197. CARBON_CHECK(!impl_binding_.has_value());
  198. impl_binding_ = binding;
  199. }
  200. private:
  201. std::string name_;
  202. Nonnull<Expression*> type_;
  203. std::optional<Nonnull<const Value*>> symbolic_identity_;
  204. std::optional<Nonnull<const ImplBinding*>> impl_binding_;
  205. };
  206. // Converts paren_contents to a Pattern, interpreting the parentheses as
  207. // grouping if their contents permit that interpretation, or as forming a
  208. // tuple otherwise.
  209. auto PatternFromParenContents(Nonnull<Arena*> arena, SourceLocation source_loc,
  210. const ParenContents<Pattern>& paren_contents)
  211. -> Nonnull<Pattern*>;
  212. // Converts paren_contents to a TuplePattern, interpreting the parentheses as
  213. // forming a tuple.
  214. auto TuplePatternFromParenContents(Nonnull<Arena*> arena,
  215. SourceLocation source_loc,
  216. const ParenContents<Pattern>& paren_contents)
  217. -> Nonnull<TuplePattern*>;
  218. // Converts `contents` to ParenContents<Pattern> by replacing each Expression
  219. // with an ExpressionPattern.
  220. auto ParenExpressionToParenPattern(Nonnull<Arena*> arena,
  221. const ParenContents<Expression>& contents)
  222. -> ParenContents<Pattern>;
  223. // A pattern that matches an alternative of a choice type.
  224. class AlternativePattern : public Pattern {
  225. public:
  226. // Constructs an AlternativePattern that matches the alternative specified
  227. // by `alternative`, if its arguments match `arguments`.
  228. static auto Create(Nonnull<Arena*> arena, SourceLocation source_loc,
  229. Nonnull<Expression*> alternative,
  230. Nonnull<TuplePattern*> arguments)
  231. -> ErrorOr<Nonnull<AlternativePattern*>> {
  232. CARBON_ASSIGN_OR_RETURN(Nonnull<FieldAccessExpression*> field_access,
  233. RequireFieldAccess(alternative));
  234. return arena->New<AlternativePattern>(source_loc,
  235. &field_access->aggregate(),
  236. field_access->field(), arguments);
  237. }
  238. // Constructs an AlternativePattern that matches a value of the type
  239. // specified by choice_type if it represents an alternative named
  240. // alternative_name, and its arguments match `arguments`.
  241. AlternativePattern(SourceLocation source_loc,
  242. Nonnull<Expression*> choice_type,
  243. std::string alternative_name,
  244. Nonnull<TuplePattern*> arguments)
  245. : Pattern(AstNodeKind::AlternativePattern, source_loc),
  246. choice_type_(choice_type),
  247. alternative_name_(std::move(alternative_name)),
  248. arguments_(arguments) {}
  249. static auto classof(const AstNode* node) -> bool {
  250. return InheritsFromAlternativePattern(node->kind());
  251. }
  252. auto choice_type() const -> const Expression& { return *choice_type_; }
  253. auto choice_type() -> Expression& { return *choice_type_; }
  254. auto alternative_name() const -> const std::string& {
  255. return alternative_name_;
  256. }
  257. auto arguments() const -> const TuplePattern& { return *arguments_; }
  258. auto arguments() -> TuplePattern& { return *arguments_; }
  259. private:
  260. static auto RequireFieldAccess(Nonnull<Expression*> alternative)
  261. -> ErrorOr<Nonnull<FieldAccessExpression*>>;
  262. Nonnull<Expression*> choice_type_;
  263. std::string alternative_name_;
  264. Nonnull<TuplePattern*> arguments_;
  265. };
  266. // A pattern that matches a value if it is equal to the value of a given
  267. // expression.
  268. class ExpressionPattern : public Pattern {
  269. public:
  270. explicit ExpressionPattern(Nonnull<Expression*> expression)
  271. : Pattern(AstNodeKind::ExpressionPattern, expression->source_loc()),
  272. expression_(expression) {}
  273. static auto classof(const AstNode* node) -> bool {
  274. return InheritsFromExpressionPattern(node->kind());
  275. }
  276. auto expression() const -> const Expression& { return *expression_; }
  277. auto expression() -> Expression& { return *expression_; }
  278. private:
  279. Nonnull<Expression*> expression_;
  280. };
  281. } // namespace Carbon
  282. #endif // EXPLORER_AST_PATTERN_H_