tint/reader: Parse arrays with no type / size

Bug: tint:1628
Change-Id: Ieb3c07e7dae6fd1e5acf4dd4819312092e5b5bf5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97586
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-08-01 21:42:54 +00:00 committed by Dawn LUCI CQ
parent 86329e286b
commit 6835c8df3e
3 changed files with 40 additions and 34 deletions

View File

@ -1175,33 +1175,40 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_vector(const Token& t) {
Expect<const ast::Type*> ParserImpl::expect_type_decl_array(const Token& t) { Expect<const ast::Type*> ParserImpl::expect_type_decl_array(const Token& t) {
const char* use = "array declaration"; const char* use = "array declaration";
const ast::Expression* size = nullptr; struct TypeAndSize {
const ast::Type* type = nullptr;
const ast::Expression* size = nullptr;
};
auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> { if (!peek_is(Token::Type::kLessThan)) {
return builder_.ty.array(make_source_range_from(t.source()), nullptr, nullptr);
}
auto type_size = expect_lt_gt_block(use, [&]() -> Expect<TypeAndSize> {
auto type = expect_type(use); auto type = expect_type(use);
if (type.errored) { if (type.errored) {
return Failure::kErrored; return Failure::kErrored;
} }
if (match(Token::Type::kComma)) { if (!match(Token::Type::kComma)) {
auto expr = primary_expression(); return TypeAndSize{type.value, nullptr};
if (expr.errored) {
return Failure::kErrored;
} else if (!expr.matched) {
return add_error(peek(), "expected array size expression");
}
size = std::move(expr.value);
} }
return type.value; auto size = primary_expression();
if (size.errored) {
return Failure::kErrored;
} else if (!size.matched) {
return add_error(peek(), "expected array size expression");
}
return TypeAndSize{type.value, size.value};
}); });
if (subtype.errored) { if (type_size.errored) {
return Failure::kErrored; return Failure::kErrored;
} }
return builder_.ty.array(make_source_range_from(t.source()), subtype.value, size); return builder_.ty.array(make_source_range_from(t.source()), type_size->type, type_size->size);
} }
Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(const Token& t) { Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(const Token& t) {

View File

@ -603,8 +603,9 @@ let i : vec2<i32> = vec2<i32>(1., 2.;
} }
TEST_F(ParserImplErrorTest, GlobalDeclLetBadConstLiteral) { TEST_F(ParserImplErrorTest, GlobalDeclLetBadConstLiteral) {
EXPECT("let i : vec2<i32> = vec2<i32>(!);", EXPECT(
R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const' "let i : vec2<i32> = vec2<i32>(!);",
R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const'
let i : vec2<i32> = vec2<i32>(!); let i : vec2<i32> = vec2<i32>(!);
^^^ ^^^
@ -821,14 +822,6 @@ type meow = f32
)"); )");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingLessThan) {
EXPECT("var i : array;",
R"(test.wgsl:1:14 error: expected '<' for array declaration
var i : array;
^
)");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) { TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) {
EXPECT("var i : array<u32, 3;", EXPECT("var i : array<u32, 3;",
R"(test.wgsl:1:21 error: expected '>' for array declaration R"(test.wgsl:1:21 error: expected '>' for array declaration

View File

@ -501,6 +501,22 @@ TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Vec) {
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
} }
TEST_F(ParserImplTest, TypeDecl_Array_InferTypeAndSize) {
auto p = parser("array");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t.value->Is<ast::Array>());
auto* a = t.value->As<ast::Array>();
EXPECT_FALSE(a->IsRuntimeArray());
EXPECT_EQ(a->type, nullptr);
EXPECT_EQ(a->count, nullptr);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 6u}}));
}
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) { TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
auto p = parser("array<f32, !>"); auto p = parser("array<f32, !>");
auto t = p->type_decl(); auto t = p->type_decl();
@ -521,16 +537,6 @@ TEST_F(ParserImplTest, TypeDecl_Array_MissingSize) {
ASSERT_EQ(p->error(), "1:11: expected array size expression"); ASSERT_EQ(p->error(), "1:11: expected array size expression");
} }
TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
auto p = parser("array f32>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration");
}
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) { TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
auto p = parser("array<f32"); auto p = parser("array<f32");
auto t = p->type_decl(); auto t = p->type_decl();