// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef EXECUTABLE_SEMANTICS_AST_PATTERN_H_ #define EXECUTABLE_SEMANTICS_AST_PATTERN_H_ #include #include #include #include "common/ostream.h" #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/source_location.h" #include "llvm/ADT/ArrayRef.h" namespace Carbon { // Abstract base class of all AST nodes representing patterns. // // Pattern and its derived classes support LLVM-style RTTI, including // llvm::isa, llvm::cast, and llvm::dyn_cast. To support this, every // class derived from Pattern must provide a `classof` operation, and // every concrete derived class must have a corresponding enumerator // in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for // details. class Pattern { public: enum class Kind { AutoPattern, BindingPattern, TuplePattern, AlternativePattern, ExpressionPattern, }; Pattern(const Pattern&) = delete; Pattern& operator=(const Pattern&) = delete; void Print(llvm::raw_ostream& out) const; LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } // Returns the enumerator corresponding to the most-derived type of this // object. auto kind() const -> Kind { return kind_; } auto source_loc() const -> SourceLocation { return source_loc_; } protected: // Constructs a Pattern representing syntax at the given line number. // `kind` must be the enumerator corresponding to the most-derived type being // constructed. Pattern(Kind kind, SourceLocation source_loc) : kind_(kind), source_loc_(source_loc) {} private: const Kind kind_; SourceLocation source_loc_; }; // A pattern consisting of the `auto` keyword. class AutoPattern : public Pattern { public: explicit AutoPattern(SourceLocation source_loc) : Pattern(Kind::AutoPattern, source_loc) {} static auto classof(const Pattern* pattern) -> bool { return pattern->kind() == Kind::AutoPattern; } }; // A pattern that matches a value of a specified type, and optionally binds // a name to it. class BindingPattern : public Pattern { public: BindingPattern(SourceLocation source_loc, std::optional name, Nonnull type) : Pattern(Kind::BindingPattern, source_loc), name(std::move(name)), type(type) {} static auto classof(const Pattern* pattern) -> bool { return pattern->kind() == Kind::BindingPattern; } // The name this pattern binds, if any. auto Name() const -> const std::optional& { return name; } // The pattern specifying the type of values that this pattern matches. auto Type() const -> Nonnull { return type; } auto Type() -> Nonnull { return type; } private: std::optional name; Nonnull type; }; // A pattern that matches a tuple value field-wise. class TuplePattern : public Pattern { public: // Represents a portion of a tuple pattern corresponding to a single field. struct Field { Field(std::string name, Nonnull pattern) : name(std::move(name)), pattern(pattern) {} // The field name. Cannot be empty std::string name; // The pattern the field must match. Nonnull pattern; }; TuplePattern(SourceLocation source_loc, std::vector fields) : Pattern(Kind::TuplePattern, source_loc), fields(std::move(fields)) {} static auto classof(const Pattern* pattern) -> bool { return pattern->kind() == Kind::TuplePattern; } auto Fields() const -> llvm::ArrayRef { return fields; } auto Fields() -> llvm::MutableArrayRef { return fields; } private: std::vector fields; }; // Converts paren_contents to a Pattern, interpreting the parentheses as // grouping if their contents permit that interpretation, or as forming a // tuple otherwise. auto PatternFromParenContents(Nonnull arena, SourceLocation source_loc, const ParenContents& paren_contents) -> Nonnull; // Converts paren_contents to a TuplePattern, interpreting the parentheses as // forming a tuple. auto TuplePatternFromParenContents(Nonnull arena, SourceLocation source_loc, const ParenContents& paren_contents) -> Nonnull; // Converts `contents` to ParenContents by replacing each Expression // with an ExpressionPattern. auto ParenExpressionToParenPattern(Nonnull arena, const ParenContents& contents) -> ParenContents; // A pattern that matches an alternative of a choice type. class AlternativePattern : public Pattern { public: // Constructs an AlternativePattern that matches a value of the type // specified by choice_type if it represents an alternative named // alternative_name, and its arguments match `arguments`. AlternativePattern(SourceLocation source_loc, Nonnull choice_type, std::string alternative_name, Nonnull arguments) : Pattern(Kind::AlternativePattern, source_loc), choice_type(choice_type), alternative_name(std::move(alternative_name)), arguments(arguments) {} // Constructs an AlternativePattern that matches the alternative specified // by `alternative`, if its arguments match `arguments`. AlternativePattern(SourceLocation source_loc, Nonnull alternative, Nonnull arguments); static auto classof(const Pattern* pattern) -> bool { return pattern->kind() == Kind::AlternativePattern; } auto ChoiceType() const -> Nonnull { return choice_type; } auto ChoiceType() -> Nonnull { return choice_type; } auto AlternativeName() const -> const std::string& { return alternative_name; } auto Arguments() const -> Nonnull { return arguments; } auto Arguments() -> Nonnull { return arguments; } private: Nonnull choice_type; std::string alternative_name; Nonnull arguments; }; // A pattern that matches a value if it is equal to the value of a given // expression. class ExpressionPattern : public Pattern { public: ExpressionPattern(Nonnull expression) : Pattern(Kind::ExpressionPattern, expression->source_loc()), expression(expression) {} static auto classof(const Pattern* pattern) -> bool { return pattern->kind() == Kind::ExpressionPattern; } auto Expression() const -> Nonnull { return expression; } auto Expression() -> Nonnull { return expression; } private: Nonnull expression; }; } // namespace Carbon #endif // EXECUTABLE_SEMANTICS_AST_PATTERN_H_