// 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 #include "executable_semantics/ast/pattern.h" #include #include "common/ostream.h" #include "executable_semantics/ast/expression.h" #include "executable_semantics/common/arena.h" #include "executable_semantics/common/error.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" namespace Carbon { using llvm::cast; Pattern::~Pattern() = default; void Pattern::Print(llvm::raw_ostream& out) const { switch (kind()) { case PatternKind::AutoPattern: out << "auto"; break; case PatternKind::BindingPattern: { const auto& binding = cast(*this); out << binding.name() << ": " << binding.type(); break; } case PatternKind::TuplePattern: { const auto& tuple = cast(*this); out << "("; llvm::ListSeparator sep; for (Nonnull field : tuple.fields()) { out << sep << *field; } out << ")"; break; } case PatternKind::AlternativePattern: { const auto& alternative = cast(*this); out << alternative.choice_type() << "." << alternative.alternative_name() << alternative.arguments(); break; } case PatternKind::ExpressionPattern: out << cast(*this).expression(); break; } } auto PatternFromParenContents(Nonnull arena, SourceLocation source_loc, const ParenContents& paren_contents) -> Nonnull { std::optional> single_term = paren_contents.SingleTerm(); if (single_term.has_value()) { return *single_term; } else { return TuplePatternFromParenContents(arena, source_loc, paren_contents); } } auto TuplePatternFromParenContents(Nonnull arena, SourceLocation source_loc, const ParenContents& paren_contents) -> Nonnull { return arena->New(source_loc, paren_contents.elements); } // Used by AlternativePattern for constructor initialization. Produces a helpful // error for incorrect expressions, rather than letting a default cast error // apply. static auto RequireFieldAccess(Nonnull alternative) -> FieldAccessExpression& { if (alternative->kind() != ExpressionKind::FieldAccessExpression) { FATAL_PROGRAM_ERROR(alternative->source_loc()) << "Alternative pattern must have the form of a field access."; } return cast(*alternative); } AlternativePattern::AlternativePattern(SourceLocation source_loc, Nonnull alternative, Nonnull arguments) : Pattern(AstNodeKind::AlternativePattern, source_loc), choice_type_(&RequireFieldAccess(alternative).aggregate()), alternative_name_(RequireFieldAccess(alternative).field()), arguments_(arguments) {} auto ParenExpressionToParenPattern(Nonnull arena, const ParenContents& contents) -> ParenContents { ParenContents result = { .elements = {}, .has_trailing_comma = contents.has_trailing_comma}; for (const auto& element : contents.elements) { result.elements.push_back(arena->New(element)); } return result; } } // namespace Carbon