// 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 "executable_semantics/ast/expression.h" #include "executable_semantics/syntax/paren_contents.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "llvm/Support/Casting.h" namespace Carbon { namespace { using llvm::cast; using llvm::isa; using testing::ElementsAre; using testing::IsEmpty; // Matches a TuplePattern::Field named `name` whose `pattern` is an // `AutoPattern`. MATCHER_P(AutoFieldNamed, name, "") { return arg.name == std::string(name) && isa(arg.pattern); } TEST(PatternTest, EmptyAsPattern) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(pattern->LineNumber(), 1); ASSERT_TRUE(isa(pattern)); EXPECT_THAT(cast(pattern)->Fields(), IsEmpty()); } TEST(PatternTest, EmptyAsTuplePattern) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; const TuplePattern* tuple = TuplePatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(tuple->LineNumber(), 1); EXPECT_THAT(tuple->Fields(), IsEmpty()); } TEST(PatternTest, UnaryNoCommaAsPattern) { // Equivalent to a code fragment like // ``` // ( // auto // ) // ``` ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}}, .has_trailing_comma = false}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(pattern->LineNumber(), 2); ASSERT_TRUE(isa(pattern)); } TEST(PatternTest, UnaryNoCommaAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}}, .has_trailing_comma = false}; const TuplePattern* tuple = TuplePatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(tuple->LineNumber(), 1); EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0"))); } TEST(PatternTest, UnaryWithCommaAsPattern) { ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}}, .has_trailing_comma = true}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(pattern->LineNumber(), 1); ASSERT_TRUE(isa(pattern)); EXPECT_THAT(cast(pattern)->Fields(), ElementsAre(AutoFieldNamed("0"))); } TEST(PatternTest, UnaryWithCommaAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}}, .has_trailing_comma = true}; const TuplePattern* tuple = TuplePatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(tuple->LineNumber(), 1); EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0"))); } TEST(PatternTest, BinaryAsPattern) { ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}, {.name = std::nullopt, .term = new AutoPattern(/*line_num=*/3)}}, .has_trailing_comma = true}; const Pattern* pattern = PatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(pattern->LineNumber(), 1); ASSERT_TRUE(isa(pattern)); EXPECT_THAT(cast(pattern)->Fields(), ElementsAre(AutoFieldNamed("0"), AutoFieldNamed("1"))); } TEST(PatternTest, BinaryAsTuplePattern) { ParenContents contents = { .elements = {{.name = std::nullopt, .term = new AutoPattern(/*line_num=*/2)}, {.name = std::nullopt, .term = new AutoPattern(/*line_num=*/3)}}, .has_trailing_comma = true}; const TuplePattern* tuple = TuplePatternFromParenContents(/*line_num=*/1, contents); EXPECT_EQ(tuple->LineNumber(), 1); EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0"), AutoFieldNamed("1"))); } } // namespace } // namespace Carbon