Remove ScalarConstructorExpression

Just make Literal an expression. The ScalarConstructorExpression
provides no real value, aside from having a ConstructorExpression base
class that's common between ScalarConstructorExpression and
TypeConstructorExpression. TypeConstructorExpression will be folded into
CallExpression, so this hierarchy will serve no purpose.

First step in resolving the parser ambiguity of type-constructors vs
type-casts vs function calls.

Bug: tint:888
Change-Id: I2585d5ddbf6c0619a8f24c503e61ebf27c182ebe
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68524
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-11-09 09:35:00 +00:00 committed by Ben Clayton
parent f3f8ec3845
commit 575c4efe2f
66 changed files with 384 additions and 934 deletions

View File

@ -286,8 +286,6 @@ libtint_source_set("libtint_core_all_src") {
"ast/sampled_texture.h", "ast/sampled_texture.h",
"ast/sampler.cc", "ast/sampler.cc",
"ast/sampler.h", "ast/sampler.h",
"ast/scalar_constructor_expression.cc",
"ast/scalar_constructor_expression.h",
"ast/sint_literal.cc", "ast/sint_literal.cc",
"ast/sint_literal.h", "ast/sint_literal.h",
"ast/stage_decoration.cc", "ast/stage_decoration.cc",

View File

@ -150,8 +150,6 @@ set(TINT_LIB_SRCS
ast/sampled_texture.h ast/sampled_texture.h
ast/sampler.cc ast/sampler.cc
ast/sampler.h ast/sampler.h
ast/scalar_constructor_expression.cc
ast/scalar_constructor_expression.h
ast/sint_literal.cc ast/sint_literal.cc
ast/sint_literal.h ast/sint_literal.h
ast/stage_decoration.cc ast/stage_decoration.cc
@ -631,7 +629,6 @@ if(${TINT_BUILD_TESTS})
ast/return_statement_test.cc ast/return_statement_test.cc
ast/sampled_texture_test.cc ast/sampled_texture_test.cc
ast/sampler_test.cc ast/sampler_test.cc
ast/scalar_constructor_expression_test.cc
ast/sint_literal_test.cc ast/sint_literal_test.cc
ast/stage_decoration_test.cc ast/stage_decoration_test.cc
ast/storage_texture_test.cc ast/storage_texture_test.cc

View File

@ -30,12 +30,9 @@ std::string SizeExprToString(const Expression* size,
if (auto* ident = size->As<IdentifierExpression>()) { if (auto* ident = size->As<IdentifierExpression>()) {
return symbols.NameFor(ident->symbol); return symbols.NameFor(ident->symbol);
} }
if (auto* scalar = size->As<ScalarConstructorExpression>()) { if (auto* literal = size->As<IntLiteral>()) {
auto* literal = scalar->literal->As<IntLiteral>();
if (literal) {
return std::to_string(literal->ValueAsU32()); return std::to_string(literal->ValueAsU32());
} }
}
// This will never be exposed to the user as the Resolver will reject this // This will never be exposed to the user as the Resolver will reject this
// expression for array size. // expression for array size.
return "<invalid>"; return "<invalid>";

View File

@ -17,13 +17,13 @@
#include <string> #include <string>
#include "src/ast/node.h" #include "src/ast/expression.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
/// Base class for a literal value /// Base class for a literal value expressions
class Literal : public Castable<Literal, Node> { class Literal : public Castable<Literal, Expression> {
public: public:
~Literal() override; ~Literal() override;

View File

@ -1,46 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/scalar_constructor_expression.h"
#include "src/program_builder.h"
TINT_INSTANTIATE_TYPEINFO(tint::ast::ScalarConstructorExpression);
namespace tint {
namespace ast {
ScalarConstructorExpression::ScalarConstructorExpression(ProgramID pid,
const Source& src,
const Literal* lit)
: Base(pid, src), literal(lit) {
TINT_ASSERT(AST, literal);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, literal, program_id);
}
ScalarConstructorExpression::ScalarConstructorExpression(
ScalarConstructorExpression&&) = default;
ScalarConstructorExpression::~ScalarConstructorExpression() = default;
const ScalarConstructorExpression* ScalarConstructorExpression::Clone(
CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source);
auto* lit = ctx->Clone(literal);
return ctx->dst->create<ScalarConstructorExpression>(src, lit);
}
} // namespace ast
} // namespace tint

View File

@ -1,52 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_AST_SCALAR_CONSTRUCTOR_EXPRESSION_H_
#define SRC_AST_SCALAR_CONSTRUCTOR_EXPRESSION_H_
#include "src/ast/constructor_expression.h"
#include "src/ast/literal.h"
namespace tint {
namespace ast {
/// A scalar constructor
class ScalarConstructorExpression
: public Castable<ScalarConstructorExpression, ConstructorExpression> {
public:
/// Constructor
/// @param pid the identifier of the program that owns this node
/// @param src the source of this node
/// @param literal the const literal
ScalarConstructorExpression(ProgramID pid,
const Source& src,
const Literal* literal);
/// Move constructor
ScalarConstructorExpression(ScalarConstructorExpression&&);
~ScalarConstructorExpression() override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const ScalarConstructorExpression* Clone(CloneContext* ctx) const override;
/// The literal value
const Literal* const literal;
};
} // namespace ast
} // namespace tint
#endif // SRC_AST_SCALAR_CONSTRUCTOR_EXPRESSION_H_

View File

@ -1,49 +0,0 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gtest/gtest-spi.h"
#include "src/ast/test_helper.h"
namespace tint {
namespace ast {
namespace {
using ScalarConstructorExpressionTest = TestHelper;
TEST_F(ScalarConstructorExpressionTest, Creation) {
auto* b = create<BoolLiteral>(true);
auto* c = create<ScalarConstructorExpression>(b);
EXPECT_EQ(c->literal, b);
}
TEST_F(ScalarConstructorExpressionTest, Creation_WithSource) {
SetSource(Source{Source::Location{20, 2}});
auto src = Expr(true)->source;
EXPECT_EQ(src.range.begin.line, 20u);
EXPECT_EQ(src.range.begin.column, 2u);
}
TEST_F(ScalarConstructorExpressionTest, Assert_DifferentProgramID_Literal) {
EXPECT_FATAL_FAILURE(
{
ProgramBuilder b1;
ProgramBuilder b2;
b1.create<ScalarConstructorExpression>(b2.create<BoolLiteral>(true));
},
"internal compiler error");
}
} // namespace
} // namespace ast
} // namespace tint

View File

@ -21,9 +21,9 @@
#include "src/ast/binary_expression.h" #include "src/ast/binary_expression.h"
#include "src/ast/bitcast_expression.h" #include "src/ast/bitcast_expression.h"
#include "src/ast/call_expression.h" #include "src/ast/call_expression.h"
#include "src/ast/literal.h"
#include "src/ast/member_accessor_expression.h" #include "src/ast/member_accessor_expression.h"
#include "src/ast/phony_expression.h" #include "src/ast/phony_expression.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/type_constructor_expression.h" #include "src/ast/type_constructor_expression.h"
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
#include "src/utils/reverse.h" #include "src/utils/reverse.h"
@ -122,8 +122,7 @@ bool TraverseExpressions(const ast::Expression* root,
to_visit.push_back(member->structure); to_visit.push_back(member->structure);
} else if (auto* unary = expr->As<ast::UnaryOpExpression>()) { } else if (auto* unary = expr->As<ast::UnaryOpExpression>()) {
to_visit.push_back(unary->expr); to_visit.push_back(unary->expr);
} else if (expr->IsAnyOf<ast::ScalarConstructorExpression, } else if (expr->IsAnyOf<ast::Literal, ast::IdentifierExpression,
ast::IdentifierExpression,
ast::PhonyExpression>()) { ast::PhonyExpression>()) {
// Leaf expression // Leaf expression
} else { } else {

View File

@ -26,11 +26,9 @@ using WorkgroupDecorationTest = TestHelper;
TEST_F(WorkgroupDecorationTest, Creation_1param) { TEST_F(WorkgroupDecorationTest, Creation_1param) {
auto* d = WorkgroupSize(2); auto* d = WorkgroupSize(2);
auto values = d->Values(); auto values = d->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
ASSERT_TRUE(x_scalar); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
EXPECT_EQ(values[1], nullptr); EXPECT_EQ(values[1], nullptr);
EXPECT_EQ(values[2], nullptr); EXPECT_EQ(values[2], nullptr);
@ -38,17 +36,12 @@ TEST_F(WorkgroupDecorationTest, Creation_1param) {
TEST_F(WorkgroupDecorationTest, Creation_2param) { TEST_F(WorkgroupDecorationTest, Creation_2param) {
auto* d = WorkgroupSize(2, 4); auto* d = WorkgroupSize(2, 4);
auto values = d->Values(); auto values = d->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(x_scalar);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(y_scalar);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>()); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
EXPECT_EQ(values[2], nullptr); EXPECT_EQ(values[2], nullptr);
} }
@ -56,42 +49,28 @@ TEST_F(WorkgroupDecorationTest, Creation_2param) {
TEST_F(WorkgroupDecorationTest, Creation_3param) { TEST_F(WorkgroupDecorationTest, Creation_3param) {
auto* d = WorkgroupSize(2, 4, 6); auto* d = WorkgroupSize(2, 4, 6);
auto values = d->Values(); auto values = d->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(x_scalar);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(y_scalar);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(z_scalar);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>()); ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 6u); EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 6u);
} }
TEST_F(WorkgroupDecorationTest, Creation_WithIdentifier) { TEST_F(WorkgroupDecorationTest, Creation_WithIdentifier) {
auto* d = WorkgroupSize(2, 4, "depth"); auto* d = WorkgroupSize(2, 4, "depth");
auto values = d->Values(); auto values = d->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(x_scalar);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(y_scalar);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* z_ident = values[2]->As<ast::IdentifierExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
auto* z_ident = As<ast::IdentifierExpression>(values[2]);
ASSERT_TRUE(z_ident); ASSERT_TRUE(z_ident);
EXPECT_EQ(Symbols().NameFor(z_ident->symbol), "depth"); EXPECT_EQ(Symbols().NameFor(z_ident->symbol), "depth");
} }

View File

@ -24,7 +24,6 @@
#include "src/ast/location_decoration.h" #include "src/ast/location_decoration.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/override_decoration.h" #include "src/ast/override_decoration.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/uint_literal.h" #include "src/ast/uint_literal.h"
#include "src/sem/array.h" #include "src/sem/array.h"
@ -264,23 +263,7 @@ std::map<uint32_t, Scalar> Inspector::GetConstantIDs() {
continue; continue;
} }
auto* expression = var->constructor; auto* literal = var->constructor->As<ast::Literal>();
auto* constructor = expression->As<ast::ConstructorExpression>();
if (constructor == nullptr) {
// This is invalid WGSL, but handling gracefully.
result[constant_id] = Scalar();
continue;
}
auto* scalar_constructor =
constructor->As<ast::ScalarConstructorExpression>();
if (scalar_constructor == nullptr) {
// This is invalid WGSL, but handling gracefully.
result[constant_id] = Scalar();
continue;
}
auto* literal = scalar_constructor->literal;
if (!literal) { if (!literal) {
// This is invalid WGSL, but handling gracefully. // This is invalid WGSL, but handling gracefully.
result[constant_id] = Scalar(); result[constant_id] = Scalar();

View File

@ -114,10 +114,6 @@ const ast::TypeName* ProgramBuilder::TypesBuilder::Of(
ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {} ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}
const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Literal* lit) {
return WrapInStatement(create<ast::ScalarConstructorExpression>(lit));
}
const ast::Statement* ProgramBuilder::WrapInStatement( const ast::Statement* ProgramBuilder::WrapInStatement(
const ast::Expression* expr) { const ast::Expression* expr) {
if (auto* ce = expr->As<ast::CallExpression>()) { if (auto* ce = expr->As<ast::CallExpression>()) {

View File

@ -55,7 +55,6 @@
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/sampled_texture.h" #include "src/ast/sampled_texture.h"
#include "src/ast/sampler.h" #include "src/ast/sampler.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h" #include "src/ast/stage_decoration.h"
#include "src/ast/storage_texture.h" #include "src/ast/storage_texture.h"
@ -1038,57 +1037,53 @@ class ProgramBuilder {
/// @param source the source information /// @param source the source information
/// @param value the boolean value /// @param value the boolean value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source, const ast::Literal* Expr(const Source& source, bool value) {
bool value) { return create<ast::BoolLiteral>(source, value);
return create<ast::ScalarConstructorExpression>(source, Literal(value));
} }
/// @param value the boolean value /// @param value the boolean value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(bool value) { const ast::BoolLiteral* Expr(bool value) {
return create<ast::ScalarConstructorExpression>(Literal(value)); return create<ast::BoolLiteral>(value);
} }
/// @param source the source information /// @param source the source information
/// @param value the float value /// @param value the float value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source, const ast::FloatLiteral* Expr(const Source& source, f32 value) {
f32 value) { return create<ast::FloatLiteral>(source, value);
return create<ast::ScalarConstructorExpression>(source, Literal(value));
} }
/// @param value the float value /// @param value the float value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(f32 value) { const ast::FloatLiteral* Expr(f32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value)); return create<ast::FloatLiteral>(value);
} }
/// @param source the source information /// @param source the source information
/// @param value the integer value /// @param value the integer value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source, const ast::Literal* Expr(const Source& source, i32 value) {
i32 value) { return create<ast::SintLiteral>(source, value);
return create<ast::ScalarConstructorExpression>(source, Literal(value));
} }
/// @param value the integer value /// @param value the integer value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(i32 value) { const ast::SintLiteral* Expr(i32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value)); return create<ast::SintLiteral>(value);
} }
/// @param source the source information /// @param source the source information
/// @param value the unsigned int value /// @param value the unsigned int value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source, const ast::UintLiteral* Expr(const Source& source, u32 value) {
u32 value) { return create<ast::UintLiteral>(source, value);
return create<ast::ScalarConstructorExpression>(source, Literal(value));
} }
/// @param value the unsigned int value /// @param value the unsigned int value
/// @return a Scalar constructor for the given value /// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(u32 value) { const ast::UintLiteral* Expr(u32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value)); return create<ast::UintLiteral>(value);
} }
/// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
@ -2502,12 +2497,6 @@ class ProgramBuilder {
/// the type declaration has no resolved type. /// the type declaration has no resolved type.
const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const; const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const;
/// Wraps the ast::Literal in a statement. This is used by tests that
/// construct a partial AST and require the Resolver to reach these
/// nodes.
/// @param lit the ast::Literal to be wrapped by an ast::Statement
/// @return the ast::Statement that wraps the ast::Statement
const ast::Statement* WrapInStatement(const ast::Literal* lit);
/// Wraps the ast::Expression in a statement. This is used by tests that /// Wraps the ast::Expression in a statement. This is used by tests that
/// construct a partial AST and require the Resolver to reach these /// construct a partial AST and require the Resolver to reach these
/// nodes. /// nodes.

View File

@ -2548,9 +2548,7 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
return source_expr; return source_expr;
} }
case SkipReason::kPointSizeBuiltinValue: { case SkipReason::kPointSizeBuiltinValue: {
return {ty_.F32(), return {ty_.F32(), create<ast::FloatLiteral>(Source{}, 1.0f)};
create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(Source{}, 1.0f))};
} }
case SkipReason::kPointSizeBuiltinPointer: case SkipReason::kPointSizeBuiltinPointer:
Fail() << "unhandled use of a pointer to the PointSize builtin, with ID: " Fail() << "unhandled use of a pointer to the PointSize builtin, with ID: "
@ -4477,8 +4475,7 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition(
auto current_type_id = composite_type_id; auto current_type_id = composite_type_id;
auto make_index = [this](uint32_t literal) { auto make_index = [this](uint32_t literal) {
return create<ast::ScalarConstructorExpression>( return create<ast::UintLiteral>(Source{}, literal);
Source{}, create<ast::UintLiteral>(Source{}, literal));
}; };
// Build up a nested expression for the decomposition by walking down the type // Build up a nested expression for the decomposition by walking down the type
@ -4594,13 +4591,11 @@ TypedExpression FunctionEmitter::MakeCompositeValueDecomposition(
} }
const ast::Expression* FunctionEmitter::MakeTrue(const Source& source) const { const ast::Expression* FunctionEmitter::MakeTrue(const Source& source) const {
return create<ast::ScalarConstructorExpression>( return create<ast::BoolLiteral>(source, true);
source, create<ast::BoolLiteral>(source, true));
} }
const ast::Expression* FunctionEmitter::MakeFalse(const Source& source) const { const ast::Expression* FunctionEmitter::MakeFalse(const Source& source) const {
return create<ast::ScalarConstructorExpression>( return create<ast::BoolLiteral>(source, false);
source, create<ast::BoolLiteral>(source, false));
} }
TypedExpression FunctionEmitter::MakeVectorShuffle( TypedExpression FunctionEmitter::MakeVectorShuffle(

View File

@ -1353,34 +1353,30 @@ bool ParserImpl::EmitScalarSpecConstants() {
for (auto& inst : module_->types_values()) { for (auto& inst : module_->types_values()) {
// These will be populated for a valid scalar spec constant. // These will be populated for a valid scalar spec constant.
const Type* ast_type = nullptr; const Type* ast_type = nullptr;
ast::ScalarConstructorExpression* ast_expr = nullptr; ast::Literal* ast_expr = nullptr;
switch (inst.opcode()) { switch (inst.opcode()) {
case SpvOpSpecConstantTrue: case SpvOpSpecConstantTrue:
case SpvOpSpecConstantFalse: { case SpvOpSpecConstantFalse: {
ast_type = ConvertType(inst.type_id()); ast_type = ConvertType(inst.type_id());
ast_expr = create<ast::ScalarConstructorExpression>( ast_expr = create<ast::BoolLiteral>(
Source{}, create<ast::BoolLiteral>( Source{}, inst.opcode() == SpvOpSpecConstantTrue);
Source{}, inst.opcode() == SpvOpSpecConstantTrue));
break; break;
} }
case SpvOpSpecConstant: { case SpvOpSpecConstant: {
ast_type = ConvertType(inst.type_id()); ast_type = ConvertType(inst.type_id());
const uint32_t literal_value = inst.GetSingleWordInOperand(0); const uint32_t literal_value = inst.GetSingleWordInOperand(0);
if (ast_type->Is<I32>()) { if (ast_type->Is<I32>()) {
ast_expr = create<ast::ScalarConstructorExpression>( ast_expr = create<ast::SintLiteral>(
Source{}, create<ast::SintLiteral>( Source{}, static_cast<int32_t>(literal_value));
Source{}, static_cast<int32_t>(literal_value)));
} else if (ast_type->Is<U32>()) { } else if (ast_type->Is<U32>()) {
ast_expr = create<ast::ScalarConstructorExpression>( ast_expr = create<ast::UintLiteral>(
Source{}, create<ast::UintLiteral>( Source{}, static_cast<uint32_t>(literal_value));
Source{}, static_cast<uint32_t>(literal_value)));
} else if (ast_type->Is<F32>()) { } else if (ast_type->Is<F32>()) {
float float_value; float float_value;
// Copy the bits so we can read them as a float. // Copy the bits so we can read them as a float.
std::memcpy(&float_value, &literal_value, sizeof(float_value)); std::memcpy(&float_value, &literal_value, sizeof(float_value));
ast_expr = create<ast::ScalarConstructorExpression>( ast_expr = create<ast::FloatLiteral>(Source{}, float_value);
Source{}, create<ast::FloatLiteral>(Source{}, float_value));
} else { } else {
return Fail() << " invalid result type for OpSpecConstant " return Fail() << " invalid result type for OpSpecConstant "
<< inst.PrettyPrint(); << inst.PrettyPrint();
@ -1981,26 +1977,20 @@ TypedExpression ParserImpl::MakeConstantExpressionForScalarSpirvConstant(
// Currently "null<type>" is missing from the WGSL parser. // Currently "null<type>" is missing from the WGSL parser.
// See https://bugs.chromium.org/p/tint/issues/detail?id=34 // See https://bugs.chromium.org/p/tint/issues/detail?id=34
if (ast_type->Is<U32>()) { if (ast_type->Is<U32>()) {
return {ty_.U32(), create<ast::ScalarConstructorExpression>( return {ty_.U32(), create<ast::UintLiteral>(source, spirv_const->GetU32())};
Source{}, create<ast::UintLiteral>(
source, spirv_const->GetU32()))};
} }
if (ast_type->Is<I32>()) { if (ast_type->Is<I32>()) {
return {ty_.I32(), create<ast::ScalarConstructorExpression>( return {ty_.I32(), create<ast::SintLiteral>(source, spirv_const->GetS32())};
Source{}, create<ast::SintLiteral>(
source, spirv_const->GetS32()))};
} }
if (ast_type->Is<F32>()) { if (ast_type->Is<F32>()) {
return {ty_.F32(), create<ast::ScalarConstructorExpression>( return {ty_.F32(),
Source{}, create<ast::FloatLiteral>( create<ast::FloatLiteral>(source, spirv_const->GetFloat())};
source, spirv_const->GetFloat()))};
} }
if (ast_type->Is<Bool>()) { if (ast_type->Is<Bool>()) {
const bool value = spirv_const->AsNullConstant() const bool value = spirv_const->AsNullConstant()
? false ? false
: spirv_const->AsBoolConstant()->value(); : spirv_const->AsBoolConstant()->value();
return {ty_.Bool(), create<ast::ScalarConstructorExpression>( return {ty_.Bool(), create<ast::BoolLiteral>(source, value)};
Source{}, create<ast::BoolLiteral>(source, value))};
} }
Fail() << "expected scalar constant"; Fail() << "expected scalar constant";
return {}; return {};
@ -2021,20 +2011,16 @@ const ast::Expression* ParserImpl::MakeNullValue(const Type* type) {
type = type->UnwrapAlias(); type = type->UnwrapAlias();
if (type->Is<Bool>()) { if (type->Is<Bool>()) {
return create<ast::ScalarConstructorExpression>( return create<ast::BoolLiteral>(Source{}, false);
Source{}, create<ast::BoolLiteral>(Source{}, false));
} }
if (type->Is<U32>()) { if (type->Is<U32>()) {
return create<ast::ScalarConstructorExpression>( return create<ast::UintLiteral>(Source{}, 0u);
Source{}, create<ast::UintLiteral>(Source{}, 0u));
} }
if (type->Is<I32>()) { if (type->Is<I32>()) {
return create<ast::ScalarConstructorExpression>( return create<ast::SintLiteral>(Source{}, 0);
Source{}, create<ast::SintLiteral>(Source{}, 0));
} }
if (type->Is<F32>()) { if (type->Is<F32>()) {
return create<ast::ScalarConstructorExpression>( return create<ast::FloatLiteral>(Source{}, 0.0f);
Source{}, create<ast::FloatLiteral>(Source{}, 0.0f));
} }
if (type->Is<Alias>()) { if (type->Is<Alias>()) {
// TODO(amaiorano): No type constructor for TypeName (yet?) // TODO(amaiorano): No type constructor for TypeName (yet?)

View File

@ -521,11 +521,12 @@ Maybe<const ast::Variable*> ParserImpl::global_constant_decl(
if (decl.errored) if (decl.errored)
return Failure::kErrored; return Failure::kErrored;
ast::ConstructorExpression* initializer = nullptr; const ast::Expression* initializer = nullptr;
if (match(Token::Type::kEqual)) { if (match(Token::Type::kEqual)) {
auto init = expect_const_expr(); auto init = expect_const_expr();
if (init.errored) if (init.errored) {
return Failure::kErrored; return Failure::kErrored;
}
initializer = std::move(init.value); initializer = std::move(init.value);
} }
@ -2175,15 +2176,18 @@ Maybe<const ast::Expression*> ParserImpl::primary_expression() {
auto source = t.source(); auto source = t.source();
auto lit = const_literal(); auto lit = const_literal();
if (lit.errored) if (lit.errored) {
return Failure::kErrored; return Failure::kErrored;
if (lit.matched) }
return create<ast::ScalarConstructorExpression>(source, lit.value); if (lit.matched) {
return lit.value;
}
if (t.Is(Token::Type::kParenLeft)) { if (t.Is(Token::Type::kParenLeft)) {
auto paren = expect_paren_rhs_stmt(); auto paren = expect_paren_rhs_stmt();
if (paren.errored) if (paren.errored) {
return Failure::kErrored; return Failure::kErrored;
}
return paren.value; return paren.value;
} }
@ -2869,23 +2873,25 @@ Maybe<const ast::Literal*> ParserImpl::const_literal() {
// const_expr // const_expr
// : type_decl PAREN_LEFT ((const_expr COMMA)? const_expr COMMA?)? PAREN_RIGHT // : type_decl PAREN_LEFT ((const_expr COMMA)? const_expr COMMA?)? PAREN_RIGHT
// | const_literal // | const_literal
Expect<ast::ConstructorExpression*> ParserImpl::expect_const_expr() { Expect<const ast::Expression*> ParserImpl::expect_const_expr() {
auto t = peek(); auto t = peek();
auto source = t.source(); auto source = t.source();
if (t.IsLiteral()) { if (t.IsLiteral()) {
auto lit = const_literal(); auto lit = const_literal();
if (lit.errored) if (lit.errored) {
return Failure::kErrored; return Failure::kErrored;
if (!lit.matched) }
if (!lit.matched) {
return add_error(peek(), "unable to parse constant literal"); return add_error(peek(), "unable to parse constant literal");
}
return create<ast::ScalarConstructorExpression>(source, lit.value); return lit.value;
} else if (!t.IsIdentifier() || get_type(t.to_str())) { } else if (!t.IsIdentifier() || get_type(t.to_str())) {
if (peek_is(Token::Type::kParenLeft, 1) || if (peek_is(Token::Type::kParenLeft, 1) ||
peek_is(Token::Type::kLessThan, 1)) { peek_is(Token::Type::kLessThan, 1)) {
auto type = expect_type("const_expr"); auto type = expect_type("const_expr");
if (type.errored) if (type.errored) {
return Failure::kErrored; return Failure::kErrored;
}
auto params = expect_paren_block( auto params = expect_paren_block(
"type constructor", [&]() -> Expect<ast::ExpressionList> { "type constructor", [&]() -> Expect<ast::ExpressionList> {

View File

@ -571,7 +571,7 @@ class ParserImpl {
Maybe<const ast::Literal*> const_literal(); Maybe<const ast::Literal*> const_literal();
/// Parses a `const_expr` grammar element, erroring on parse failure. /// Parses a `const_expr` grammar element, erroring on parse failure.
/// @returns the parsed constructor expression or nullptr on error /// @returns the parsed constructor expression or nullptr on error
Expect<ast::ConstructorExpression*> expect_const_expr(); Expect<const ast::Expression*> expect_const_expr();
/// Parses a `primary_expression` grammar element /// Parses a `primary_expression` grammar element
/// @returns the parsed expression or nullptr /// @returns the parsed expression or nullptr
Maybe<const ast::Expression*> primary_expression(); Maybe<const ast::Expression*> primary_expression();

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) { TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) { TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, AndExpression_Parses) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, AndExpression_InvalidLHS) { TEST_F(ParserImplTest, AndExpression_InvalidLHS) {

View File

@ -46,7 +46,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
ASSERT_EQ(e.value.size(), 3u); ASSERT_EQ(e.value.size(), 3u);
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>()); ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
ASSERT_TRUE(e.value[1]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(e.value[1]->Is<ast::Literal>());
ASSERT_TRUE(e.value[2]->Is<ast::BinaryExpression>()); ASSERT_TRUE(e.value[2]->Is<ast::BinaryExpression>());
} }
@ -58,7 +58,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_TrailingComma) {
ASSERT_EQ(e.value.size(), 2u); ASSERT_EQ(e.value.size(), 2u);
ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>()); ASSERT_TRUE(e.value[0]->Is<ast::IdentifierExpression>());
ASSERT_TRUE(e.value[1]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(e.value[1]->Is<ast::Literal>());
} }
TEST_F(ParserImplTest, ArgumentExpressionList_HandlesMissingLeftParen) { TEST_F(ParserImplTest, ArgumentExpressionList_HandlesMissingLeftParen) {

View File

@ -35,13 +35,9 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
auto* ident = e->lhs->As<ast::IdentifierExpression>(); auto* ident = e->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(e->rhs->Is<ast::ConstructorExpression>()); ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(e->rhs->Is<ast::SintLiteral>());
EXPECT_EQ(e->rhs->As<ast::SintLiteral>()->value, 123);
auto* init = e->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_NE(init->literal, nullptr);
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 123);
} }
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) { TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
@ -56,12 +52,9 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
ASSERT_NE(e->lhs, nullptr); ASSERT_NE(e->lhs, nullptr);
ASSERT_NE(e->rhs, nullptr); ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::ConstructorExpression>()); ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(e->rhs->Is<ast::SintLiteral>());
auto* init = e->rhs->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(e->rhs->As<ast::SintLiteral>()->value, 123);
ASSERT_NE(init->literal, nullptr);
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 123);
ASSERT_TRUE(e->lhs->Is<ast::MemberAccessorExpression>()); ASSERT_TRUE(e->lhs->Is<ast::MemberAccessorExpression>());
auto* mem = e->lhs->As<ast::MemberAccessorExpression>(); auto* mem = e->lhs->As<ast::MemberAccessorExpression>();
@ -73,12 +66,9 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
ASSERT_TRUE(mem->structure->Is<ast::ArrayAccessorExpression>()); ASSERT_TRUE(mem->structure->Is<ast::ArrayAccessorExpression>());
auto* ary = mem->structure->As<ast::ArrayAccessorExpression>(); auto* ary = mem->structure->As<ast::ArrayAccessorExpression>();
ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>()); ASSERT_NE(ary->index, nullptr);
ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(ary->index->Is<ast::SintLiteral>());
init = ary->index->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(ary->index->As<ast::SintLiteral>()->value, 2);
ASSERT_NE(init->literal, nullptr);
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 2);
ASSERT_TRUE(ary->array->Is<ast::MemberAccessorExpression>()); ASSERT_TRUE(ary->array->Is<ast::MemberAccessorExpression>());
mem = ary->array->As<ast::MemberAccessorExpression>(); mem = ary->array->As<ast::MemberAccessorExpression>();
@ -110,12 +100,9 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToPhony) {
ASSERT_NE(e->lhs, nullptr); ASSERT_NE(e->lhs, nullptr);
ASSERT_NE(e->rhs, nullptr); ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::ConstructorExpression>()); ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(e->rhs->Is<ast::SintLiteral>());
auto* init = e->rhs->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(e->rhs->As<ast::SintLiteral>()->value, 123);
ASSERT_NE(init->literal, nullptr);
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 123);
ASSERT_TRUE(e->lhs->Is<ast::PhonyExpression>()); ASSERT_TRUE(e->lhs->Is<ast::PhonyExpression>());
} }

View File

@ -55,7 +55,7 @@ TEST_F(ParserImplTest, Statement_Call_WithParams) {
EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
EXPECT_EQ(c->args.size(), 3u); EXPECT_EQ(c->args.size(), 3u);
EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>()); EXPECT_TRUE(c->args[0]->Is<ast::IntLiteral>());
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>()); EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>()); EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
} }
@ -74,7 +74,7 @@ TEST_F(ParserImplTest, Statement_Call_WithParams_TrailingComma) {
EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
EXPECT_EQ(c->args.size(), 2u); EXPECT_EQ(c->args.size(), 2u);
EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>()); EXPECT_TRUE(c->args[0]->Is<ast::IntLiteral>());
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>()); EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
} }

View File

@ -34,17 +34,11 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
ASSERT_EQ(t->values.size(), 2u); ASSERT_EQ(t->values.size(), 2u);
auto& v = t->values; auto& v = t->values;
ASSERT_TRUE(v[0]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(v[0]->Is<ast::FloatLiteral>());
ASSERT_TRUE(v[0]->Is<ast::ScalarConstructorExpression>()); EXPECT_FLOAT_EQ(v[0]->As<ast::FloatLiteral>()->value, 1.);
auto* c = v[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::FloatLiteral>());
EXPECT_FLOAT_EQ(c->literal->As<ast::FloatLiteral>()->value, 1.);
ASSERT_TRUE(v[1]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(v[1]->Is<ast::FloatLiteral>());
ASSERT_TRUE(v[1]->Is<ast::ScalarConstructorExpression>()); EXPECT_FLOAT_EQ(v[1]->As<ast::FloatLiteral>()->value, 2.);
c = v[1]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::FloatLiteral>());
EXPECT_FLOAT_EQ(c->literal->As<ast::FloatLiteral>()->value, 2.);
} }
TEST_F(ParserImplTest, ConstExpr_TypeDecl_Empty) { TEST_F(ParserImplTest, ConstExpr_TypeDecl_Empty) {
@ -75,8 +69,8 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl_TrailingComma) {
EXPECT_EQ(t->type->As<ast::Vector>()->width, 2u); EXPECT_EQ(t->type->As<ast::Vector>()->width, 2u);
ASSERT_EQ(t->values.size(), 2u); ASSERT_EQ(t->values.size(), 2u);
ASSERT_TRUE(t->values[0]->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(t->values[0]->Is<ast::Literal>());
ASSERT_TRUE(t->values[1]->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(t->values[1]->Is<ast::Literal>());
} }
TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) { TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
@ -121,11 +115,8 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(e.errored); ASSERT_FALSE(e.errored);
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::ConstructorExpression>()); ASSERT_TRUE(e.value->Is<ast::BoolLiteral>());
ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>()); EXPECT_TRUE(e.value->As<ast::BoolLiteral>()->value);
auto* c = e->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::BoolLiteral>());
EXPECT_TRUE(c->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) { TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) { TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) { TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) { TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {

View File

@ -71,23 +71,14 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values(); auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(z_scalar, nullptr);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
auto* body = f->body; auto* body = f->body;
ASSERT_EQ(body->statements.size(), 1u); ASSERT_EQ(body->statements.size(), 1u);
@ -119,23 +110,14 @@ fn main() { return; })");
ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>()); ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values(); auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(z_scalar, nullptr);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(decorations[1]->Is<ast::StageDecoration>()); ASSERT_TRUE(decorations[1]->Is<ast::StageDecoration>());
EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->stage, EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->stage,
@ -172,23 +154,14 @@ fn main() { return; })");
ASSERT_TRUE(decos[0]->Is<ast::WorkgroupDecoration>()); ASSERT_TRUE(decos[0]->Is<ast::WorkgroupDecoration>());
auto values = decos[0]->As<ast::WorkgroupDecoration>()->Values(); auto values = decos[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(z_scalar, nullptr);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(decos[1]->Is<ast::StageDecoration>()); ASSERT_TRUE(decos[1]->Is<ast::StageDecoration>());
EXPECT_EQ(decos[1]->As<ast::StageDecoration>()->stage, EXPECT_EQ(decos[1]->As<ast::StageDecoration>()->stage,

View File

@ -36,10 +36,10 @@ TEST_F(ParserImplTest, DecorationList_Parses) {
ASSERT_TRUE(deco_0->Is<ast::WorkgroupDecoration>()); ASSERT_TRUE(deco_0->Is<ast::WorkgroupDecoration>());
const ast::Expression* x = deco_0->As<ast::WorkgroupDecoration>()->x; const ast::Expression* x = deco_0->As<ast::WorkgroupDecoration>()->x;
ASSERT_NE(x, nullptr); ASSERT_NE(x, nullptr);
auto* x_scalar = x->As<ast::ScalarConstructorExpression>(); auto* x_literal = x->As<ast::Literal>();
ASSERT_NE(x_scalar, nullptr); ASSERT_NE(x_literal, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>()); ASSERT_TRUE(x_literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u); EXPECT_EQ(x_literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(deco_1->Is<ast::StageDecoration>()); ASSERT_TRUE(deco_1->Is<ast::StageDecoration>());
EXPECT_EQ(deco_1->As<ast::StageDecoration>()->stage, EXPECT_EQ(deco_1->As<ast::StageDecoration>()->stage,

View File

@ -34,11 +34,8 @@ TEST_F(ParserImplTest, Decoration_Workgroup) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values(); auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
EXPECT_EQ(values[1], nullptr); EXPECT_EQ(values[1], nullptr);
EXPECT_EQ(values[2], nullptr); EXPECT_EQ(values[2], nullptr);
@ -57,17 +54,11 @@ TEST_F(ParserImplTest, Decoration_Workgroup_2Param) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values(); auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
EXPECT_EQ(values[2], nullptr); EXPECT_EQ(values[2], nullptr);
} }
@ -85,23 +76,14 @@ TEST_F(ParserImplTest, Decoration_Workgroup_3Param) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values(); auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr); ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_NE(values[2], nullptr); ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 6u);
ASSERT_NE(z_scalar, nullptr);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 6u);
} }
TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) { TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) {
@ -117,11 +99,8 @@ TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values(); auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr); ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr); ASSERT_NE(values[1], nullptr);
auto* y_ident = values[1]->As<ast::IdentifierExpression>(); auto* y_ident = values[1]->As<ast::IdentifierExpression>();

View File

@ -42,7 +42,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
EXPECT_EQ(e->source.range.end.column, 6u); EXPECT_EQ(e->source.range.end.column, 6u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->constructor->Is<ast::Literal>());
EXPECT_FALSE( EXPECT_FALSE(
ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations)); ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations));
@ -69,7 +69,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
EXPECT_EQ(e->source.range.end.column, 6u); EXPECT_EQ(e->source.range.end.column, 6u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->constructor->Is<ast::Literal>());
EXPECT_FALSE( EXPECT_FALSE(
ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations)); ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations));
@ -137,7 +137,7 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
EXPECT_EQ(e->source.range.end.column, 22u); EXPECT_EQ(e->source.range.end.column, 22u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->constructor->Is<ast::Literal>());
auto* override_deco = auto* override_deco =
ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations); ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations);
@ -169,7 +169,7 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
EXPECT_EQ(e->source.range.end.column, 19u); EXPECT_EQ(e->source.range.end.column, 19u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->constructor->Is<ast::Literal>());
auto* override_deco = auto* override_deco =
ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations); ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations);

View File

@ -63,8 +63,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
EXPECT_EQ(e->source.range.end.column, 15u); EXPECT_EQ(e->source.range.end.column, 15u);
ASSERT_NE(e->constructor, nullptr); ASSERT_NE(e->constructor, nullptr);
ASSERT_TRUE(e->constructor->Is<ast::ConstructorExpression>()); ASSERT_TRUE(e->constructor->Is<ast::FloatLiteral>());
ASSERT_TRUE(e->constructor->Is<ast::ScalarConstructorExpression>());
} }
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) { TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) { TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) { TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) { TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) { TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) { TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
@ -81,11 +75,8 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) { TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {

View File

@ -45,29 +45,17 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
ASSERT_EQ(ty->values.size(), 4u); ASSERT_EQ(ty->values.size(), 4u);
const auto& val = ty->values; const auto& val = ty->values;
ASSERT_TRUE(val[0]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(val[0]->Is<ast::SintLiteral>());
ASSERT_TRUE(val[0]->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(val[0]->As<ast::SintLiteral>()->value, 1);
auto* ident = val[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 1);
ASSERT_TRUE(val[1]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(val[1]->Is<ast::SintLiteral>());
ASSERT_TRUE(val[1]->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(val[1]->As<ast::SintLiteral>()->value, 2);
ident = val[1]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 2);
ASSERT_TRUE(val[2]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(val[2]->Is<ast::SintLiteral>());
ASSERT_TRUE(val[2]->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(val[2]->As<ast::SintLiteral>()->value, 3);
ident = val[2]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 3);
ASSERT_TRUE(val[3]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(val[3]->Is<ast::SintLiteral>());
ASSERT_TRUE(val[3]->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(val[3]->As<ast::SintLiteral>()->value, 4);
ident = val[3]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 4);
} }
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) { TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
@ -173,15 +161,11 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
auto values = constructor->values; auto values = constructor->values;
ASSERT_EQ(values.size(), 2u); ASSERT_EQ(values.size(), 2u);
ASSERT_TRUE(values[0]->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(values[0]->Is<ast::UintLiteral>());
auto* val0 = values[0]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[0]->As<ast::UintLiteral>()->value, 1u);
ASSERT_TRUE(val0->literal->Is<ast::UintLiteral>());
EXPECT_EQ(val0->literal->As<ast::UintLiteral>()->value, 1u);
ASSERT_TRUE(values[1]->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(values[1]->Is<ast::FloatLiteral>());
auto* val1 = values[1]->As<ast::ScalarConstructorExpression>(); EXPECT_EQ(values[1]->As<ast::FloatLiteral>()->value, 2.f);
ASSERT_TRUE(val1->literal->Is<ast::FloatLiteral>());
EXPECT_EQ(val1->literal->As<ast::FloatLiteral>()->value, 2.f);
} }
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) { TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
@ -191,11 +175,8 @@ TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
EXPECT_FALSE(e.errored); EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error(); EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr); ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::ConstructorExpression>()); ASSERT_TRUE(e->Is<ast::BoolLiteral>());
ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>()); EXPECT_TRUE(e->As<ast::BoolLiteral>()->value);
auto* init = e->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
EXPECT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) { TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
@ -253,8 +234,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
ASSERT_TRUE(c->type->Is<ast::F32>()); ASSERT_TRUE(c->type->Is<ast::F32>());
ASSERT_EQ(c->values.size(), 1u); ASSERT_EQ(c->values.size(), 1u);
ASSERT_TRUE(c->values[0]->Is<ast::ConstructorExpression>()); ASSERT_TRUE(c->values[0]->Is<ast::IntLiteral>());
ASSERT_TRUE(c->values[0]->Is<ast::ScalarConstructorExpression>());
} }
TEST_F(ParserImplTest, PrimaryExpression_Bitcast) { TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
@ -269,8 +249,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
auto* c = e->As<ast::BitcastExpression>(); auto* c = e->As<ast::BitcastExpression>();
ASSERT_TRUE(c->type->Is<ast::F32>()); ASSERT_TRUE(c->type->Is<ast::F32>());
ASSERT_TRUE(c->expr->Is<ast::ConstructorExpression>()); ASSERT_TRUE(c->expr->Is<ast::IntLiteral>());
ASSERT_TRUE(c->expr->Is<ast::ScalarConstructorExpression>());
} }
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) { TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) { TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) { TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
@ -81,11 +75,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) { TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
@ -104,11 +95,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) { TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {

View File

@ -35,11 +35,8 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) { TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>(); auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>()); ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>()); ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
} }
TEST_F(ParserImplTest, ShiftExpression_InvalidSpaceLeft) { TEST_F(ParserImplTest, ShiftExpression_InvalidSpaceLeft) {

View File

@ -34,11 +34,8 @@ TEST_F(ParserImplTest, SingularExpression_Array_ConstantIndex) {
auto* ident = ary->array->As<ast::IdentifierExpression>(); auto* ident = ary->array->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>()); ASSERT_TRUE(ary->index->Is<ast::SintLiteral>());
ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(ary->index->As<ast::SintLiteral>()->value, 1);
auto* c = ary->index->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::SintLiteral>());
EXPECT_EQ(c->literal->As<ast::SintLiteral>()->value, 1);
} }
TEST_F(ParserImplTest, SingularExpression_Array_ExpressionIndex) { TEST_F(ParserImplTest, SingularExpression_Array_ExpressionIndex) {
@ -119,7 +116,7 @@ TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("test")); EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("test"));
EXPECT_EQ(c->args.size(), 3u); EXPECT_EQ(c->args.size(), 3u);
EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>()); EXPECT_TRUE(c->args[0]->Is<ast::IntLiteral>());
EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>()); EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>()); EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
} }

View File

@ -455,9 +455,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_SintLiteralSize) {
EXPECT_EQ(a->decorations.size(), 0u); EXPECT_EQ(a->decorations.size(), 0u);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 14u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 14u}}));
auto* count_expr = a->count->As<ast::ScalarConstructorExpression>(); auto* size = a->count->As<ast::SintLiteral>();
ASSERT_NE(count_expr, nullptr);
auto* size = count_expr->literal->As<ast::SintLiteral>();
ASSERT_NE(size, nullptr); ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 5); EXPECT_EQ(size->ValueAsI32(), 5);
} }
@ -477,9 +475,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_UintLiteralSize) {
EXPECT_EQ(a->decorations.size(), 0u); EXPECT_EQ(a->decorations.size(), 0u);
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 15u}})); EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 15u}}));
auto* count_expr = a->count->As<ast::ScalarConstructorExpression>(); auto* size = a->count->As<ast::UintLiteral>();
ASSERT_NE(count_expr, nullptr);
auto* size = count_expr->literal->As<ast::UintLiteral>();
ASSERT_NE(size, nullptr); ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsU32(), 5u); EXPECT_EQ(size->ValueAsU32(), 5u);
} }
@ -517,9 +513,7 @@ TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
ASSERT_FALSE(a->IsRuntimeArray()); ASSERT_FALSE(a->IsRuntimeArray());
ASSERT_TRUE(a->type->Is<ast::F32>()); ASSERT_TRUE(a->type->Is<ast::F32>());
auto* count_expr = a->count->As<ast::ScalarConstructorExpression>(); auto* size = a->count->As<ast::SintLiteral>();
ASSERT_NE(count_expr, nullptr);
auto* size = count_expr->literal->As<ast::SintLiteral>();
ASSERT_NE(size, nullptr); ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 5); EXPECT_EQ(size->ValueAsI32(), 5);

View File

@ -34,11 +34,8 @@ TEST_F(ParserImplTest, UnaryExpression_Postix) {
auto* ident = ary->array->As<ast::IdentifierExpression>(); auto* ident = ary->array->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a")); EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>()); ASSERT_TRUE(ary->index->Is<ast::SintLiteral>());
ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>()); ASSERT_EQ(ary->index->As<ast::SintLiteral>()->value, 2);
auto* init = ary->index->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
ASSERT_EQ(init->literal->As<ast::SintLiteral>()->value, 2);
} }
TEST_F(ParserImplTest, UnaryExpression_Minus) { TEST_F(ParserImplTest, UnaryExpression_Minus) {
@ -53,12 +50,8 @@ TEST_F(ParserImplTest, UnaryExpression_Minus) {
auto* u = e->As<ast::UnaryOpExpression>(); auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kNegation); ASSERT_EQ(u->op, ast::UnaryOp::kNegation);
ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>()); ASSERT_TRUE(u->expr->Is<ast::SintLiteral>());
ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(u->expr->As<ast::SintLiteral>()->value, 1);
auto* init = u->expr->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
} }
TEST_F(ParserImplTest, UnaryExpression_AddressOf) { TEST_F(ParserImplTest, UnaryExpression_AddressOf) {
@ -139,12 +132,8 @@ TEST_F(ParserImplTest, UnaryExpression_Bang) {
auto* u = e->As<ast::UnaryOpExpression>(); auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kNot); ASSERT_EQ(u->op, ast::UnaryOp::kNot);
ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>()); ASSERT_TRUE(u->expr->Is<ast::SintLiteral>());
ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(u->expr->As<ast::SintLiteral>()->value, 1);
auto* init = u->expr->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
} }
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) { TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
@ -169,12 +158,8 @@ TEST_F(ParserImplTest, UnaryExpression_Tilde) {
auto* u = e->As<ast::UnaryOpExpression>(); auto* u = e->As<ast::UnaryOpExpression>();
ASSERT_EQ(u->op, ast::UnaryOp::kComplement); ASSERT_EQ(u->op, ast::UnaryOp::kComplement);
ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>()); ASSERT_TRUE(u->expr->Is<ast::SintLiteral>());
ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>()); EXPECT_EQ(u->expr->As<ast::SintLiteral>()->value, 1);
auto* init = u->expr->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
} }
TEST_F(ParserImplTest, UnaryExpression_PrefixPlusPlus) { TEST_F(ParserImplTest, UnaryExpression_PrefixPlusPlus) {

View File

@ -55,7 +55,7 @@ TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
ASSERT_EQ(e->source.range.end.column, 6u); ASSERT_EQ(e->source.range.end.column, 6u);
ASSERT_NE(e->variable->constructor, nullptr); ASSERT_NE(e->variable->constructor, nullptr);
EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->variable->constructor->Is<ast::Literal>());
} }
TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) { TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {

View File

@ -89,8 +89,7 @@ TEST_F(ResolverFunctionValidationTest,
// fn func { var a:i32 = 2; } // fn func { var a:i32 = 2; }
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{}, Func(Source{{12, 34}}, "func", ast::VariableList{}, ty.void_(),
ty.void_(),
ast::StatementList{ ast::StatementList{
Decl(var), Decl(var),
}); });
@ -103,11 +102,11 @@ TEST_F(ResolverFunctionValidationTest,
// var foo:f32 = 3.14; // var foo:f32 = 3.14;
// fn foo() -> void {} // fn foo() -> void {}
auto* global_var = Var(Source{Source::Location{56, 78}}, "foo", ty.f32(), auto* global_var = Var(Source{{56, 78}}, "foo", ty.f32(),
ast::StorageClass::kPrivate, Expr(3.14f)); ast::StorageClass::kPrivate, Expr(3.14f));
AST().AddGlobalVariable(global_var); AST().AddGlobalVariable(global_var);
Func(Source{Source::Location{12, 34}}, "foo", ast::VariableList{}, ty.void_(), Func(Source{{12, 34}}, "foo", ast::VariableList{}, ty.void_(),
ast::StatementList{}, ast::DecorationList{}); ast::StatementList{}, ast::DecorationList{});
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
@ -121,9 +120,9 @@ TEST_F(ResolverFunctionValidationTest,
// fn foo() -> void {} // fn foo() -> void {}
// var<private> foo:f32 = 3.14; // var<private> foo:f32 = 3.14;
Func(Source{Source::Location{12, 34}}, "foo", ast::VariableList{}, ty.void_(), Func(Source{{12, 34}}, "foo", ast::VariableList{}, ty.void_(),
ast::StatementList{}, ast::DecorationList{}); ast::StatementList{}, ast::DecorationList{});
auto* global_var = Var(Source{Source::Location{56, 78}}, "foo", ty.f32(), auto* global_var = Var(Source{{56, 78}}, "foo", ty.f32(),
ast::StorageClass::kPrivate, Expr(3.14f)); ast::StorageClass::kPrivate, Expr(3.14f));
AST().AddGlobalVariable(global_var); AST().AddGlobalVariable(global_var);
@ -143,7 +142,7 @@ TEST_F(ResolverFunctionValidationTest, FunctionUsingSameVariableName_Pass) {
Func("func", ast::VariableList{}, ty.i32(), Func("func", ast::VariableList{}, ty.i32(),
ast::StatementList{ ast::StatementList{
Decl(var), Decl(var),
Return(Source{Source::Location{12, 34}}, Expr("func")), Return(Source{{12, 34}}, Expr("func")),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -162,7 +161,7 @@ TEST_F(ResolverFunctionValidationTest,
}, },
ast::DecorationList{}); ast::DecorationList{});
Func(Source{Source::Location{12, 34}}, "b", ast::VariableList{}, ty.i32(), Func(Source{{12, 34}}, "b", ast::VariableList{}, ty.i32(),
ast::StatementList{ ast::StatementList{
Return(2), Return(2),
}, },
@ -244,7 +243,7 @@ TEST_F(ResolverFunctionValidationTest, FunctionEndWithoutReturnStatement_Fail) {
auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2)); auto* var = Var("a", ty.i32(), ast::StorageClass::kNone, Expr(2));
Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{}, ty.i32(), Func(Source{{12, 34}}, "func", ast::VariableList{}, ty.i32(),
ast::StatementList{ ast::StatementList{
Decl(var), Decl(var),
}, },
@ -259,8 +258,8 @@ TEST_F(ResolverFunctionValidationTest,
VoidFunctionEndWithoutReturnStatementEmptyBody_Pass) { VoidFunctionEndWithoutReturnStatementEmptyBody_Pass) {
// fn func {} // fn func {}
Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{}, Func(Source{{12, 34}}, "func", ast::VariableList{}, ty.void_(),
ty.void_(), ast::StatementList{}); ast::StatementList{});
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -269,7 +268,7 @@ TEST_F(ResolverFunctionValidationTest,
FunctionEndWithoutReturnStatementEmptyBody_Fail) { FunctionEndWithoutReturnStatementEmptyBody_Fail) {
// fn func() -> int {} // fn func() -> int {}
Func(Source{Source::Location{12, 34}}, "func", ast::VariableList{}, ty.i32(), Func(Source{{12, 34}}, "func", ast::VariableList{}, ty.i32(),
ast::StatementList{}, ast::DecorationList{}); ast::StatementList{}, ast::DecorationList{});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -294,7 +293,7 @@ TEST_F(ResolverFunctionValidationTest,
// fn func { return 2; } // fn func { return 2; }
Func("func", ast::VariableList{}, ty.void_(), Func("func", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2)), Return(Source{{12, 34}}, Expr(2)),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -311,7 +310,7 @@ TEST_F(ResolverFunctionValidationTest,
Func("v", {}, ty.void_(), {Return()}); Func("v", {}, ty.void_(), {Return()});
Func("func", {}, ty.void_(), Func("func", {}, ty.void_(),
{ {
Return(Call(Source{Source::Location{12, 34}}, "v")), Return(Call(Source{{12, 34}}, "v")),
}); });
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -323,7 +322,7 @@ TEST_F(ResolverFunctionValidationTest,
// fn func() -> f32 { return; } // fn func() -> f32 { return; }
Func("func", ast::VariableList{}, ty.f32(), Func("func", ast::VariableList{}, ty.f32(),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, nullptr), Return(Source{{12, 34}}, nullptr),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -338,7 +337,7 @@ TEST_F(ResolverFunctionValidationTest,
// fn func() -> f32 { return 2.0; } // fn func() -> f32 { return 2.0; }
Func("func", ast::VariableList{}, ty.f32(), Func("func", ast::VariableList{}, ty.f32(),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2.f)), Return(Source{{12, 34}}, Expr(2.f)),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -350,7 +349,7 @@ TEST_F(ResolverFunctionValidationTest,
// fn func() -> f32 { return 2; } // fn func() -> f32 { return 2; }
Func("func", ast::VariableList{}, ty.f32(), Func("func", ast::VariableList{}, ty.f32(),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2)), Return(Source{{12, 34}}, Expr(2)),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -367,7 +366,7 @@ TEST_F(ResolverFunctionValidationTest,
auto* myf32 = Alias("myf32", ty.f32()); auto* myf32 = Alias("myf32", ty.f32());
Func("func", ast::VariableList{}, ty.Of(myf32), Func("func", ast::VariableList{}, ty.Of(myf32),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2.f)), Return(Source{{12, 34}}, Expr(2.f)),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -381,7 +380,7 @@ TEST_F(ResolverFunctionValidationTest,
auto* myf32 = Alias("myf32", ty.f32()); auto* myf32 = Alias("myf32", ty.f32());
Func("func", ast::VariableList{}, ty.Of(myf32), Func("func", ast::VariableList{}, ty.Of(myf32),
ast::StatementList{ ast::StatementList{
Return(Source{Source::Location{12, 34}}, Expr(2u)), Return(Source{{12, 34}}, Expr(2u)),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -413,8 +412,7 @@ TEST_F(ResolverFunctionValidationTest, PipelineStage_MustBeUnique_Fail) {
// [[stage(fragment)]] // [[stage(fragment)]]
// [[stage(vertex)]] // [[stage(vertex)]]
// fn main() { return; } // fn main() { return; }
Func(Source{Source::Location{12, 34}}, "main", ast::VariableList{}, Func(Source{{12, 34}}, "main", ast::VariableList{}, ty.void_(),
ty.void_(),
ast::StatementList{ ast::StatementList{
Return(), Return(),
}, },
@ -537,7 +535,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Const_TypeMismatch) {
GlobalConst("x", ty.u32(), Expr(64u)); GlobalConst("x", ty.u32(), Expr(64u));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(1), Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(1), Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -554,7 +552,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Const_TypeMismatch2) {
GlobalConst("y", ty.i32(), Expr(32)); GlobalConst("y", ty.i32(), Expr(32));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr("x"), Expr(Source{Source::Location{12, 34}}, "y"))}); WorkgroupSize(Expr("x"), Expr(Source{{12, 34}}, "y"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -570,8 +568,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Mismatch_ConstU32) {
GlobalConst("y", ty.u32(), Expr(8u)); GlobalConst("y", ty.u32(), Expr(8u));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr("x"), Expr("y"), WorkgroupSize(Expr("x"), Expr("y"), Expr(Source{{12, 34}}, 16))});
Expr(Source{Source::Location{12, 34}}, 16))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -585,8 +582,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Literal_BadType) {
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(create<ast::ScalarConstructorExpression>( WorkgroupSize(Literal(Source{{12, 34}}, 64.f))});
Source{Source::Location{12, 34}}, Literal(64.f)))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -600,8 +596,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Literal_Negative) {
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(create<ast::ScalarConstructorExpression>( WorkgroupSize(Literal(Source{{12, 34}}, -2))});
Source{Source::Location{12, 34}}, Literal(-2)))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -614,8 +609,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Literal_Zero) {
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(create<ast::ScalarConstructorExpression>( WorkgroupSize(Literal(Source{{12, 34}}, 0))});
Source{Source::Location{12, 34}}, Literal(0)))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -629,7 +623,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Const_BadType) {
GlobalConst("x", ty.f32(), Expr(64.f)); GlobalConst("x", ty.f32(), Expr(64.f));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -644,7 +638,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Const_Negative) {
GlobalConst("x", ty.i32(), Expr(-2)); GlobalConst("x", ty.i32(), Expr(-2));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -658,7 +652,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_Const_Zero) {
GlobalConst("x", ty.i32(), Expr(0)); GlobalConst("x", ty.i32(), Expr(0));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -674,7 +668,7 @@ TEST_F(ResolverFunctionValidationTest,
Construct(ty.i32(), Construct(ty.i32(), Construct(ty.i32())))); Construct(ty.i32(), Construct(ty.i32(), Construct(ty.i32()))));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -688,7 +682,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_NonConst) {
Global("x", ty.i32(), ast::StorageClass::kPrivate, Expr(64)); Global("x", ty.i32(), ast::StorageClass::kPrivate, Expr(64));
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize(Expr(Source{Source::Location{12, 34}}, "x"))}); WorkgroupSize(Expr(Source{{12, 34}}, "x"))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
@ -701,8 +695,7 @@ TEST_F(ResolverFunctionValidationTest, WorkgroupSize_InvalidExpr) {
// fn main() {} // fn main() {}
Func("main", {}, ty.void_(), {}, Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute), {Stage(ast::PipelineStage::kCompute),
WorkgroupSize( WorkgroupSize(Construct(Source{{12, 34}}, ty.i32(), 1))});
Construct(Source{Source::Location{12, 34}}, ty.i32(), 1))});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),

View File

@ -2015,7 +2015,7 @@ bool Resolver::WorkgroupSizeFor(const ast::Function* func,
ws[i].value = 0; ws[i].value = 0;
continue; continue;
} }
} else if (!expr->Is<ast::ScalarConstructorExpression>()) { } else if (!expr->Is<ast::Literal>()) {
AddError( AddError(
"workgroup_size argument must be either a literal or a " "workgroup_size argument must be either a literal or a "
"module-scope constant", "module-scope constant",
@ -2366,6 +2366,8 @@ sem::Expression* Resolver::Expression(const ast::Expression* root) {
sem_expr = Constructor(ctor); sem_expr = Constructor(ctor);
} else if (auto* ident = expr->As<ast::IdentifierExpression>()) { } else if (auto* ident = expr->As<ast::IdentifierExpression>()) {
sem_expr = Identifier(ident); sem_expr = Identifier(ident);
} else if (auto* literal = expr->As<ast::Literal>()) {
sem_expr = Literal(literal);
} else if (auto* member = expr->As<ast::MemberAccessorExpression>()) { } else if (auto* member = expr->As<ast::MemberAccessorExpression>()) {
sem_expr = MemberAccessor(member); sem_expr = MemberAccessor(member);
} else if (auto* unary = expr->As<ast::UnaryOpExpression>()) { } else if (auto* unary = expr->As<ast::UnaryOpExpression>()) {
@ -2421,8 +2423,7 @@ sem::Expression* Resolver::ArrayAccessor(
if (!parent_raw_ty->Is<sem::Reference>()) { if (!parent_raw_ty->Is<sem::Reference>()) {
// TODO(bclayton): expand this to allow any const_expr expression // TODO(bclayton): expand this to allow any const_expr expression
// https://github.com/gpuweb/gpuweb/issues/1272 // https://github.com/gpuweb/gpuweb/issues/1272
auto* scalar = idx->As<ast::ScalarConstructorExpression>(); if (!idx->As<ast::IntLiteral>()) {
if (!scalar || !scalar->literal->As<ast::IntLiteral>()) {
AddError("index must be signed or unsigned integer literal", AddError("index must be signed or unsigned integer literal",
idx->source); idx->source);
return nullptr; return nullptr;
@ -2615,8 +2616,7 @@ bool Resolver::ValidateTextureIntrinsicFunction(const sem::Call* call) {
bool is_const_expr = true; bool is_const_expr = true;
ast::TraverseExpressions( ast::TraverseExpressions(
arg->Declaration(), diagnostics_, [&](const ast::Expression* e) { arg->Declaration(), diagnostics_, [&](const ast::Expression* e) {
if (e->IsAnyOf<ast::ScalarConstructorExpression, if (e->IsAnyOf<ast::Literal, ast::TypeConstructorExpression>()) {
ast::TypeConstructorExpression>()) {
return ast::TraverseAction::Descend; return ast::TraverseAction::Descend;
} }
is_const_expr = false; is_const_expr = false;
@ -2763,19 +2763,19 @@ sem::Expression* Resolver::Constructor(const ast::ConstructorExpression* expr) {
return builder_->create<sem::Expression>(expr, ty, current_statement_, val); return builder_->create<sem::Expression>(expr, ty, current_statement_, val);
} }
if (auto* scalar_ctor = expr->As<ast::ScalarConstructorExpression>()) { TINT_ICE(Resolver, diagnostics_) << "unexpected constructor expression type";
Mark(scalar_ctor->literal); return nullptr;
auto* ty = TypeOf(scalar_ctor->literal); }
sem::Expression* Resolver::Literal(const ast::Literal* literal) {
auto* ty = TypeOf(literal);
if (!ty) { if (!ty) {
return nullptr; return nullptr;
} }
auto val = EvaluateConstantValue(expr, ty); auto val = EvaluateConstantValue(literal, ty);
return builder_->create<sem::Expression>(expr, ty, current_statement_, val); return builder_->create<sem::Expression>(literal, ty, current_statement_,
} val);
TINT_ICE(Resolver, diagnostics_) << "unexpected constructor expression type";
return nullptr;
} }
bool Resolver::ValidateStructureConstructor( bool Resolver::ValidateStructureConstructor(
@ -3783,7 +3783,7 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
} }
count_expr = var->Declaration()->constructor; count_expr = var->Declaration()->constructor;
} else if (!count_expr->Is<ast::ScalarConstructorExpression>()) { } else if (!count_expr->Is<ast::Literal>()) {
AddError( AddError(
"array size expression must be either a literal or a module-scope " "array size expression must be either a literal or a module-scope "
"constant", "constant",

View File

@ -177,6 +177,7 @@ class Resolver {
sem::Call* FunctionCall(const ast::CallExpression*); sem::Call* FunctionCall(const ast::CallExpression*);
sem::Expression* Identifier(const ast::IdentifierExpression*); sem::Expression* Identifier(const ast::IdentifierExpression*);
sem::Call* IntrinsicCall(const ast::CallExpression*, sem::IntrinsicType); sem::Call* IntrinsicCall(const ast::CallExpression*, sem::IntrinsicType);
sem::Expression* Literal(const ast::Literal*);
sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*); sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*);
sem::Expression* UnaryOp(const ast::UnaryOpExpression*); sem::Expression* UnaryOp(const ast::UnaryOpExpression*);
@ -375,8 +376,7 @@ class Resolver {
sem::Constant EvaluateConstantValue(const ast::Expression* expr, sem::Constant EvaluateConstantValue(const ast::Expression* expr,
const sem::Type* type); const sem::Type* type);
sem::Constant EvaluateConstantValue( sem::Constant EvaluateConstantValue(const ast::Literal* literal,
const ast::ScalarConstructorExpression* scalar_ctor,
const sem::Type* type); const sem::Type* type);
sem::Constant EvaluateConstantValue( sem::Constant EvaluateConstantValue(
const ast::TypeConstructorExpression* type_ctor, const ast::TypeConstructorExpression* type_ctor,

View File

@ -29,7 +29,7 @@ using f32 = ProgramBuilder::f32;
sem::Constant Resolver::EvaluateConstantValue(const ast::Expression* expr, sem::Constant Resolver::EvaluateConstantValue(const ast::Expression* expr,
const sem::Type* type) { const sem::Type* type) {
if (auto* e = expr->As<ast::ScalarConstructorExpression>()) { if (auto* e = expr->As<ast::Literal>()) {
return EvaluateConstantValue(e, type); return EvaluateConstantValue(e, type);
} }
if (auto* e = expr->As<ast::TypeConstructorExpression>()) { if (auto* e = expr->As<ast::TypeConstructorExpression>()) {
@ -38,10 +38,8 @@ sem::Constant Resolver::EvaluateConstantValue(const ast::Expression* expr,
return {}; return {};
} }
sem::Constant Resolver::EvaluateConstantValue( sem::Constant Resolver::EvaluateConstantValue(const ast::Literal* literal,
const ast::ScalarConstructorExpression* scalar_ctor,
const sem::Type* type) { const sem::Type* type) {
auto* literal = scalar_ctor->literal;
if (auto* lit = literal->As<ast::SintLiteral>()) { if (auto* lit = literal->As<ast::SintLiteral>()) {
return {type, {lit->ValueAsI32()}}; return {type, {lit->ValueAsI32()}};
} }

View File

@ -424,10 +424,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_type_match) { Expr_Constructor_Array_type_match) {
// array<u32, 3>(0u, 10u. 20u); // array<u32, 3>(0u, 10u. 20u);
auto* tc = auto* tc = array<u32, 3>(Literal(0u), Literal(10u), Literal(20u));
array<u32, 3>(create<ast::ScalarConstructorExpression>(Literal(0u)),
create<ast::ScalarConstructorExpression>(Literal(10u)),
create<ast::ScalarConstructorExpression>(Literal(20u)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_TRUE(r()->Resolve()); EXPECT_TRUE(r()->Resolve());
@ -436,10 +433,8 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_type_Mismatch_U32F32) { Expr_Constructor_Array_type_Mismatch_U32F32) {
// array<u32, 3>(0u, 1.0f, 20u); // array<u32, 3>(0u, 1.0f, 20u);
auto* tc = array<u32, 3>( auto* tc =
create<ast::ScalarConstructorExpression>(Literal(0u)), array<u32, 3>(Literal(0u), Literal(Source{{12, 34}}, 1.0f), Literal(20u));
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)),
create<ast::ScalarConstructorExpression>(Literal(20u)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -451,8 +446,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_ScalarArgumentTypeMismatch_F32I32) { Expr_Constructor_Array_ScalarArgumentTypeMismatch_F32I32) {
// array<f32, 1>(1); // array<f32, 1>(1);
auto* tc = array<f32, 1>( auto* tc = array<f32, 1>(Literal(Source{{12, 34}}, 1));
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -464,12 +458,8 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_ScalarArgumentTypeMismatch_U32I32) { Expr_Constructor_Array_ScalarArgumentTypeMismatch_U32I32) {
// array<u32, 6>(1, 0u, 0u, 0u, 0u, 0u); // array<u32, 6>(1, 0u, 0u, 0u, 0u, 0u);
auto* tc = array<u32, 1>( auto* tc = array<u32, 1>(Literal(Source{{12, 34}}, 1), Literal(0u),
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)), Literal(0u), Literal(0u), Literal(0u));
create<ast::ScalarConstructorExpression>(Literal(0u)),
create<ast::ScalarConstructorExpression>(Literal(0u)),
create<ast::ScalarConstructorExpression>(Literal(0u)),
create<ast::ScalarConstructorExpression>(Literal(0u)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -481,7 +471,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) { Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) {
// array<i32, 3>(1, vec2<i32>()); // array<i32, 3>(1, vec2<i32>());
auto* tc = array<i32, 3>(create<ast::ScalarConstructorExpression>(Literal(1)), auto* tc = array<i32, 3>(Literal(1),
create<ast::TypeConstructorExpression>( create<ast::TypeConstructorExpression>(
Source{{12, 34}}, ty.vec2<i32>(), ExprList())); Source{{12, 34}}, ty.vec2<i32>(), ExprList()));
WrapInFunction(tc); WrapInFunction(tc);
@ -555,10 +545,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Array_TooFewElements) { Expr_Constructor_Array_TooFewElements) {
// array<i32, 4>(1, 2, 3); // array<i32, 4>(1, 2, 3);
SetSource(Source::Location({12, 34})); SetSource(Source::Location({12, 34}));
auto* tc = auto* tc = array<i32, 4>(Literal(1), Literal(2), Literal(3));
array<i32, 4>(create<ast::ScalarConstructorExpression>(Literal(1)),
create<ast::ScalarConstructorExpression>(Literal(2)),
create<ast::ScalarConstructorExpression>(Literal(3)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -572,11 +559,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
// array<i32, 4>(1, 2, 3, 4, 5); // array<i32, 4>(1, 2, 3, 4, 5);
SetSource(Source::Location({12, 34})); SetSource(Source::Location({12, 34}));
auto* tc = auto* tc =
array<i32, 4>(create<ast::ScalarConstructorExpression>(Literal(1)), array<i32, 4>(Literal(1), Literal(2), Literal(3), Literal(4), Literal(5));
create<ast::ScalarConstructorExpression>(Literal(2)),
create<ast::ScalarConstructorExpression>(Literal(3)),
create<ast::ScalarConstructorExpression>(Literal(4)),
create<ast::ScalarConstructorExpression>(Literal(5)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -588,9 +571,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_Runtime) { TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_Runtime) {
// array<i32>(1); // array<i32>(1);
auto* tc = array( auto* tc = array(ty.i32(), nullptr, Literal(Source{{12, 34}}, 1));
ty.i32(), nullptr,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -613,9 +594,7 @@ namespace VectorConstructor {
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2F32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec2F32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec2<f32>( auto* tc = vec2<f32>(Literal(Source{{12, 34}}, 1), 1.0f);
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
1.0f);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -626,8 +605,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2U32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec2U32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec2<u32>(1u, create<ast::ScalarConstructorExpression>( auto* tc = vec2<u32>(1u, Literal(Source{{12, 34}}, 1));
Source{{12, 34}}, Literal(1)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -638,9 +616,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2I32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec2I32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec2<i32>( auto* tc = vec2<i32>(Literal(Source{{12, 34}}, 1u), 1);
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1u)),
1);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -651,8 +627,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2Bool_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec2Bool_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec2<bool>(true, create<ast::ScalarConstructorExpression>( auto* tc = vec2<bool>(true, Literal(Source{{12, 34}}, 1));
Source{{12, 34}}, Literal(1)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -687,11 +662,9 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2_Error_TooManyArgumentsScalar) { Expr_Constructor_Vec2_Error_TooManyArgumentsScalar) {
auto* tc = vec2<f32>( auto* tc = vec2<f32>(Literal(Source{{12, 34}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 46}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -718,8 +691,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) { Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) {
auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>( auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
Source{{12, 34}}, ty.vec2<f32>(), ExprList()), Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
create<ast::ScalarConstructorExpression>( Literal(Source{{12, 40}}, 1.0f));
Source{{12, 40}}, Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -833,9 +805,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3F32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec3F32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec3<f32>( auto* tc = vec3<f32>(1.0f, 1.0f, Literal(Source{{12, 34}}, 1));
1.0f, 1.0f,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -846,10 +816,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3U32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec3U32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec3<u32>( auto* tc = vec3<u32>(1u, Literal(Source{{12, 34}}, 1), 1u);
1u,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
1u);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -860,10 +827,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3I32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec3I32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec3<i32>( auto* tc = vec3<i32>(1, Literal(Source{{12, 34}}, 1u), 1);
1,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1u)),
1);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -874,10 +838,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3Bool_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec3Bool_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec3<bool>( auto* tc = vec3<bool>(true, Literal(Source{{12, 34}}, 1), false);
true,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
false);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -900,10 +861,8 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3_Error_TooFewArgumentsScalar) { Expr_Constructor_Vec3_Error_TooFewArgumentsScalar) {
auto* tc = vec3<f32>( auto* tc = vec3<f32>(Literal(Source{{12, 34}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)), Literal(Source{{12, 40}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 40}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -915,11 +874,8 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3_Error_TooManyArgumentsScalar) { Expr_Constructor_Vec3_Error_TooManyArgumentsScalar) {
auto* tc = vec3<f32>( auto* tc = vec3<f32>(
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)), Literal(Source{{12, 34}}, 1.0f), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f), Literal(Source{{12, 52}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 46}}, Literal(1.0f)),
create<ast::ScalarConstructorExpression>(Source{{12, 52}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -956,12 +912,10 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) { Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) {
auto* tc = vec3<f32>( auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.vec2<f32>(), Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
ExprList()), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 46}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -974,8 +928,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) { Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) {
auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>( auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
Source{{12, 34}}, ty.vec3<f32>(), ExprList()), Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
create<ast::ScalarConstructorExpression>( Literal(Source{{12, 40}}, 1.0f));
Source{{12, 40}}, Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1115,10 +1068,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4F32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec4F32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec4<f32>( auto* tc = vec4<f32>(1.0f, 1.0f, Literal(Source{{12, 34}}, 1), 1.0f);
1.0f, 1.0f,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
1.0f);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1129,10 +1079,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4U32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec4U32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec4<u32>( auto* tc = vec4<u32>(1u, 1u, Literal(Source{{12, 34}}, 1), 1u);
1u, 1u,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
1u);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1143,10 +1090,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4I32_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec4I32_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec4<i32>( auto* tc = vec4<i32>(1, 1, Literal(Source{{12, 34}}, 1u), 1);
1, 1,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1u)),
1);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1157,10 +1101,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4Bool_Error_ScalarArgumentTypeMismatch) { Expr_Constructor_Vec4Bool_Error_ScalarArgumentTypeMismatch) {
auto* tc = vec4<bool>( auto* tc = vec4<bool>(true, false, Literal(Source{{12, 34}}, 1), true);
true, false,
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1)),
true);
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1171,11 +1112,9 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4_Error_TooFewArgumentsScalar) { Expr_Constructor_Vec4_Error_TooFewArgumentsScalar) {
auto* tc = vec4<f32>( auto* tc = vec4<f32>(Literal(Source{{12, 34}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 46}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1187,12 +1126,9 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4_Error_TooManyArgumentsScalar) { Expr_Constructor_Vec4_Error_TooManyArgumentsScalar) {
auto* tc = vec4<f32>( auto* tc = vec4<f32>(
create<ast::ScalarConstructorExpression>(Source{{12, 34}}, Literal(1.0f)), Literal(Source{{12, 34}}, 1.0f), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f), Literal(Source{{12, 52}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 46}}, Literal(1.0f)), Literal(Source{{12, 58}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 52}}, Literal(1.0f)),
create<ast::ScalarConstructorExpression>(Source{{12, 58}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1205,8 +1141,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) { Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) {
auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>( auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
Source{{12, 34}}, ty.vec2<f32>(), ExprList()), Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
create<ast::ScalarConstructorExpression>( Literal(Source{{12, 40}}, 1.0f));
Source{{12, 40}}, Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1217,13 +1152,11 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) { Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) {
auto* tc = vec4<f32>( auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.vec2<f32>(), Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
ExprList()), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 46}}, Literal(1.0f)), Literal(Source{{12, 52}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 52}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1238,8 +1171,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
Source{{12, 34}}, ty.vec2<f32>(), ExprList()), Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
create<ast::TypeConstructorExpression>( create<ast::TypeConstructorExpression>(
Source{{12, 40}}, ty.vec2<f32>(), ExprList()), Source{{12, 40}}, ty.vec2<f32>(), ExprList()),
create<ast::ScalarConstructorExpression>( Literal(Source{{12, 46}}, 1.0f));
Source{{12, 46}}, Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1278,12 +1210,10 @@ TEST_F(ResolverTypeConstructorValidationTest,
TEST_F(ResolverTypeConstructorValidationTest, TEST_F(ResolverTypeConstructorValidationTest,
Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) { Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) {
auto* tc = vec4<f32>( auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.vec3<f32>(), Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
ExprList()), Literal(Source{{12, 40}}, 1.0f),
create<ast::ScalarConstructorExpression>(Source{{12, 40}}, Literal(1.0f)), Literal(Source{{12, 46}}, 1.0f));
create<ast::ScalarConstructorExpression>(Source{{12, 46}},
Literal(1.0f)));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1576,8 +1506,7 @@ TEST_F(ResolverTypeConstructorValidationTest,
auto* vec_type = ty.vec(ty.Of(f32_alias), 2); auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
auto* tc = create<ast::TypeConstructorExpression>( auto* tc = create<ast::TypeConstructorExpression>(
Source{{12, 34}}, vec_type, Source{{12, 34}}, vec_type,
ExprList(1.0f, create<ast::ScalarConstructorExpression>(Source{{12, 40}}, ExprList(1.0f, Literal(Source{{12, 40}}, 1u)));
Literal(1u))));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -1767,8 +1696,7 @@ TEST_P(MatrixConstructorTest,
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
args.push_back( args.push_back(Literal(Source{{12, i}}, 1u));
create<ast::ScalarConstructorExpression>(Source{{12, i}}, Literal(1u)));
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);

View File

@ -129,9 +129,7 @@ TEST_F(ResolverValidationTest, Stmt_Error_Unknown) {
TEST_F(ResolverValidationTest, Stmt_If_NonBool) { TEST_F(ResolverValidationTest, Stmt_If_NonBool) {
// if (1.23f) {} // if (1.23f) {}
WrapInFunction(If(create<ast::ScalarConstructorExpression>(Source{{12, 34}}, WrapInFunction(If(Literal(Source{{12, 34}}, 1.23f), Block()));
Literal(1.23f)),
Block()));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
@ -142,10 +140,8 @@ TEST_F(ResolverValidationTest, Stmt_If_NonBool) {
TEST_F(ResolverValidationTest, Stmt_Else_NonBool) { TEST_F(ResolverValidationTest, Stmt_Else_NonBool) {
// else (1.23f) {} // else (1.23f) {}
WrapInFunction(If(Expr(true), Block(), WrapInFunction(
Else(create<ast::ScalarConstructorExpression>( If(Expr(true), Block(), Else(Literal(Source{{12, 34}}, 1.23f), Block())));
Source{{12, 34}}, Literal(1.23f)),
Block())));
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());

View File

@ -23,7 +23,6 @@
#include "src/ast/assignment_statement.h" #include "src/ast/assignment_statement.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/disable_validation_decoration.h" #include "src/ast/disable_validation_decoration.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/type_name.h" #include "src/ast/type_name.h"
#include "src/ast/unary_op.h" #include "src/ast/unary_op.h"
#include "src/block_allocator.h" #include "src/block_allocator.h"
@ -331,15 +330,13 @@ struct DecomposeMemoryAccess::State {
/// @param expr the expression to convert to an Offset /// @param expr the expression to convert to an Offset
/// @returns an Offset for the given ast::Expression /// @returns an Offset for the given ast::Expression
const Offset* ToOffset(const ast::Expression* expr) { const Offset* ToOffset(const ast::Expression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) { if (auto* u32 = expr->As<ast::UintLiteral>()) {
if (auto* u32 = scalar->literal->As<ast::UintLiteral>()) {
return offsets_.Create<OffsetLiteral>(u32->value); return offsets_.Create<OffsetLiteral>(u32->value);
} else if (auto* i32 = scalar->literal->As<ast::SintLiteral>()) { } else if (auto* i32 = expr->As<ast::SintLiteral>()) {
if (i32->value > 0) { if (i32->value > 0) {
return offsets_.Create<OffsetLiteral>(i32->value); return offsets_.Create<OffsetLiteral>(i32->value);
} }
} }
}
return offsets_.Create<OffsetExpr>(expr); return offsets_.Create<OffsetExpr>(expr);
} }

View File

@ -81,7 +81,8 @@ void FoldConstants::Run(CloneContext& ctx, const DataMap&, DataMap&) {
} }
if (ty->is_scalar()) { if (ty->is_scalar()) {
return value.WithScalarAt(0, [&](auto&& s) { return ctx.dst->Expr(s); }); return value.WithScalarAt(
0, [&](auto&& s) -> const ast::Literal* { return ctx.dst->Expr(s); });
} }
return nullptr; return nullptr;

View File

@ -37,8 +37,7 @@ const ast::VariableDeclStatement* AsTrivialLetDecl(const ast::Statement* stmt) {
return nullptr; return nullptr;
} }
auto* ctor = var->constructor; auto* ctor = var->constructor;
if (!IsAnyOf<ast::IdentifierExpression, ast::ScalarConstructorExpression>( if (!IsAnyOf<ast::IdentifierExpression, ast::Literal>(ctor)) {
ctor)) {
return nullptr; return nullptr;
} }
return var_decl; return var_decl;

View File

@ -46,7 +46,7 @@ void CollectSavedArrayIndices(const Program* program,
if (auto* a = expr->As<ast::ArrayAccessorExpression>()) { if (auto* a = expr->As<ast::ArrayAccessorExpression>()) {
CollectSavedArrayIndices(program, a->array, cb); CollectSavedArrayIndices(program, a->array, cb);
if (!a->index->Is<ast::ScalarConstructorExpression>()) { if (!a->index->Is<ast::Literal>()) {
cb(a->index); cb(a->index);
} }
return; return;

View File

@ -189,7 +189,9 @@ struct Robustness::State {
// Convert idx to an expression, so we can emit the new accessor. // Convert idx to an expression, so we can emit the new accessor.
if (!idx.expr) { if (!idx.expr) {
idx.expr = idx.is_signed ? b.Expr(idx.i32) : b.Expr(idx.u32); idx.expr = idx.is_signed
? static_cast<const ast::Expression*>(b.Expr(idx.i32))
: static_cast<const ast::Expression*>(b.Expr(idx.u32));
} }
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering

View File

@ -84,10 +84,7 @@ TEST_F(CreateASTTypeForTest, ArrayImplicitStride) {
ASSERT_TRUE(arr->As<ast::Array>()->type->Is<ast::F32>()); ASSERT_TRUE(arr->As<ast::Array>()->type->Is<ast::F32>());
ASSERT_EQ(arr->As<ast::Array>()->decorations.size(), 0u); ASSERT_EQ(arr->As<ast::Array>()->decorations.size(), 0u);
auto* count_expr = auto* size = arr->As<ast::Array>()->count->As<ast::IntLiteral>();
arr->As<ast::Array>()->count->As<ast::ScalarConstructorExpression>();
ASSERT_NE(count_expr, nullptr);
auto* size = count_expr->literal->As<ast::IntLiteral>();
ASSERT_NE(size, nullptr); ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 2); EXPECT_EQ(size->ValueAsI32(), 2);
} }
@ -107,10 +104,7 @@ TEST_F(CreateASTTypeForTest, ArrayNonImplicitStride) {
->stride, ->stride,
64u); 64u);
auto* count_expr = auto* size = arr->As<ast::Array>()->count->As<ast::IntLiteral>();
arr->As<ast::Array>()->count->As<ast::ScalarConstructorExpression>();
ASSERT_NE(count_expr, nullptr);
auto* size = count_expr->literal->As<ast::IntLiteral>();
ASSERT_NE(size, nullptr); ASSERT_NE(size, nullptr);
EXPECT_EQ(size->ValueAsI32(), 2); EXPECT_EQ(size->ValueAsI32(), 2);
} }

View File

@ -85,7 +85,7 @@ const ast::TypeConstructorExpression* AppendVector(
const auto num_supplied = vc->values.size(); const auto num_supplied = vc->values.size();
if (num_supplied == 0) { if (num_supplied == 0) {
// Zero-value vector constructor. Populate with zeros // Zero-value vector constructor. Populate with zeros
auto buildZero = [&]() -> const ast::ScalarConstructorExpression* { auto buildZero = [&]() -> const ast::Literal* {
if (packed_el_sem_ty->Is<sem::I32>()) { if (packed_el_sem_ty->Is<sem::I32>()) {
return b->Expr(0); return b->Expr(0);
} else if (packed_el_sem_ty->Is<sem::U32>()) { } else if (packed_el_sem_ty->Is<sem::U32>()) {

View File

@ -249,9 +249,7 @@ TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
ASSERT_NE(vec_0004, nullptr); ASSERT_NE(vec_0004, nullptr);
ASSERT_EQ(vec_0004->values.size(), 4u); ASSERT_EQ(vec_0004->values.size(), 4u);
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
auto* ctor = vec_0004->values[i]->As<ast::ScalarConstructorExpression>(); auto* literal = As<ast::SintLiteral>(vec_0004->values[i]);
ASSERT_NE(ctor, nullptr);
auto* literal = As<ast::SintLiteral>(ctor->literal);
ASSERT_NE(literal, nullptr); ASSERT_NE(literal, nullptr);
EXPECT_EQ(literal->value, 0); EXPECT_EQ(literal->value, 0);
} }

View File

@ -1387,18 +1387,9 @@ bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
bool GeneratorImpl::EmitConstructor(std::ostream& out, bool GeneratorImpl::EmitConstructor(std::ostream& out,
const ast::ConstructorExpression* expr) { const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>()); return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
} }
bool GeneratorImpl::EmitScalarConstructor(
std::ostream& out,
const ast::ScalarConstructorExpression* expr) {
return EmitLiteral(out, expr->literal);
}
bool GeneratorImpl::EmitTypeConstructor( bool GeneratorImpl::EmitTypeConstructor(
std::ostream& out, std::ostream& out,
const ast::TypeConstructorExpression* expr) { const ast::TypeConstructorExpression* expr) {
@ -1486,6 +1477,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) { if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i); return EmitIdentifier(out, i);
} }
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) { if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return EmitMemberAccessor(out, m); return EmitMemberAccessor(out, m);
} }

View File

@ -198,12 +198,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the discard statement /// @param stmt the discard statement
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
bool EmitDiscard(const ast::DiscardStatement* stmt); bool EmitDiscard(const ast::DiscardStatement* stmt);
/// Handles generating a scalar constructor
/// @param out the output of the expression stream
/// @param expr the scalar constructor expression
/// @returns true if the scalar constructor is emitted
bool EmitScalarConstructor(std::ostream& out,
const ast::ScalarConstructorExpression* expr);
/// Handles emitting a type constructor /// Handles emitting a type constructor
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the type constructor expression /// @param expr the type constructor expression

View File

@ -2114,18 +2114,9 @@ bool GeneratorImpl::EmitCase(const ast::SwitchStatement* s, size_t case_idx) {
bool GeneratorImpl::EmitConstructor(std::ostream& out, bool GeneratorImpl::EmitConstructor(std::ostream& out,
const ast::ConstructorExpression* expr) { const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>()); return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
} }
bool GeneratorImpl::EmitScalarConstructor(
std::ostream& out,
const ast::ScalarConstructorExpression* expr) {
return EmitLiteral(out, expr->literal);
}
bool GeneratorImpl::EmitTypeConstructor( bool GeneratorImpl::EmitTypeConstructor(
std::ostream& out, std::ostream& out,
const ast::TypeConstructorExpression* expr) { const ast::TypeConstructorExpression* expr) {
@ -2218,6 +2209,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) { if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i); return EmitIdentifier(out, i);
} }
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) { if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return EmitMemberAccessor(out, m); return EmitMemberAccessor(out, m);
} }

View File

@ -227,12 +227,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the discard statement /// @param stmt the discard statement
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
bool EmitDiscard(const ast::DiscardStatement* stmt); bool EmitDiscard(const ast::DiscardStatement* stmt);
/// Handles generating a scalar constructor
/// @param out the output of the expression stream
/// @param expr the scalar constructor expression
/// @returns true if the scalar constructor is emitted
bool EmitScalarConstructor(std::ostream& out,
const ast::ScalarConstructorExpression* expr);
/// Handles emitting a type constructor /// Handles emitting a type constructor
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the type constructor expression /// @param expr the type constructor expression

View File

@ -1293,9 +1293,6 @@ bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
bool GeneratorImpl::EmitConstructor(std::ostream& out, bool GeneratorImpl::EmitConstructor(std::ostream& out,
const ast::ConstructorExpression* expr) { const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>()); return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
} }
@ -1387,12 +1384,6 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) {
return true; return true;
} }
bool GeneratorImpl::EmitScalarConstructor(
std::ostream& out,
const ast::ScalarConstructorExpression* expr) {
return EmitLiteral(out, expr->literal);
}
bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::Literal* lit) { bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::Literal* lit) {
if (auto* l = lit->As<ast::BoolLiteral>()) { if (auto* l = lit->As<ast::BoolLiteral>()) {
out << (l->value ? "true" : "false"); out << (l->value ? "true" : "false");
@ -1445,6 +1436,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) { if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i); return EmitIdentifier(out, i);
} }
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) { if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return EmitMemberAccessor(out, m); return EmitMemberAccessor(out, m);
} }

View File

@ -26,12 +26,12 @@
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/expression.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/interpolate_decoration.h" #include "src/ast/interpolate_decoration.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/member_accessor_expression.h" #include "src/ast/member_accessor_expression.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/switch_statement.h" #include "src/ast/switch_statement.h"
#include "src/ast/type_constructor_expression.h" #include "src/ast/type_constructor_expression.h"
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
@ -241,12 +241,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
bool EmitReturn(const ast::ReturnStatement* stmt); bool EmitReturn(const ast::ReturnStatement* stmt);
/// Handles generating a scalar constructor
/// @param out the output of the expression stream
/// @param expr the scalar constructor expression
/// @returns true if the scalar constructor is emitted
bool EmitScalarConstructor(std::ostream& out,
const ast::ScalarConstructorExpression* expr);
/// Handles emitting a pipeline stage name /// Handles emitting a pipeline stage name
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param stage the stage to emit /// @param stage the stage to emit

View File

@ -583,6 +583,9 @@ uint32_t Builder::GenerateExpression(const ast::Expression* expr) {
if (auto* i = expr->As<ast::IdentifierExpression>()) { if (auto* i = expr->As<ast::IdentifierExpression>()) {
return GenerateIdentifierExpression(i); return GenerateIdentifierExpression(i);
} }
if (auto* l = expr->As<ast::Literal>()) {
return GenerateLiteralIfNeeded(nullptr, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) { if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return GenerateAccessorExpression(m); return GenerateAccessorExpression(m);
} }
@ -757,13 +760,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
uint32_t init_id = 0; uint32_t init_id = 0;
if (var->constructor) { if (var->constructor) {
if (!var->constructor->Is<ast::ConstructorExpression>()) { init_id = GenerateConstructorExpression(var, var->constructor);
error_ = "scalar constructor expected";
return false;
}
init_id = GenerateConstructorExpression(
var, var->constructor->As<ast::ConstructorExpression>());
if (init_id == 0) { if (init_id == 0) {
return false; return false;
} }
@ -931,14 +928,7 @@ bool Builder::GenerateArrayAccessor(const ast::ArrayAccessorExpression* expr,
auto extract_id = extract.to_i(); auto extract_id = extract.to_i();
// If the index is a literal, we use OpCompositeExtract. // If the index is a literal, we use OpCompositeExtract.
if (auto* scalar = expr->index->As<ast::ScalarConstructorExpression>()) { if (auto* literal = expr->index->As<ast::IntLiteral>()) {
auto* literal = scalar->literal->As<ast::IntLiteral>();
if (!literal) {
TINT_ICE(Writer, builder_.Diagnostics())
<< "bad literal in array accessor";
return false;
}
if (!push_function_inst(spv::Op::OpCompositeExtract, if (!push_function_inst(spv::Op::OpCompositeExtract,
{Operand::Int(result_type_id), extract, {Operand::Int(result_type_id), extract,
Operand::Int(info->source_id), Operand::Int(info->source_id),
@ -1264,11 +1254,10 @@ uint32_t Builder::GetGLSLstd450Import() {
return id; return id;
} }
uint32_t Builder::GenerateConstructorExpression( uint32_t Builder::GenerateConstructorExpression(const ast::Variable* var,
const ast::Variable* var, const ast::Expression* expr) {
const ast::ConstructorExpression* expr) { if (auto* literal = expr->As<ast::Literal>()) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) { return GenerateLiteralIfNeeded(var, literal);
return GenerateLiteralIfNeeded(var, scalar->literal);
} }
if (auto* type = expr->As<ast::TypeConstructorExpression>()) { if (auto* type = expr->As<ast::TypeConstructorExpression>()) {
return GenerateTypeConstructorExpression(var, type); return GenerateTypeConstructorExpression(var, type);
@ -1280,20 +1269,19 @@ uint32_t Builder::GenerateConstructorExpression(
bool Builder::is_constructor_const(const ast::Expression* expr, bool Builder::is_constructor_const(const ast::Expression* expr,
bool is_global_init) { bool is_global_init) {
auto* constructor = expr->As<ast::ConstructorExpression>(); if (expr->Is<ast::Literal>()) {
if (constructor == nullptr) {
return false;
}
if (constructor->Is<ast::ScalarConstructorExpression>()) {
return true; return true;
} }
auto* tc = constructor->As<ast::TypeConstructorExpression>(); auto* tc = expr->As<ast::TypeConstructorExpression>();
if (!tc) {
return false;
}
auto* result_type = TypeOf(tc)->UnwrapRef(); auto* result_type = TypeOf(tc)->UnwrapRef();
for (size_t i = 0; i < tc->values.size(); ++i) { for (size_t i = 0; i < tc->values.size(); ++i) {
auto* e = tc->values[i]; auto* e = tc->values[i];
if (!e->Is<ast::ConstructorExpression>()) { if (!e->IsAnyOf<ast::TypeConstructorExpression, ast::Literal>()) {
if (is_global_init) { if (is_global_init) {
error_ = "constructor must be a constant expression"; error_ = "constructor must be a constant expression";
return false; return false;
@ -1307,13 +1295,13 @@ bool Builder::is_constructor_const(const ast::Expression* expr,
return false; return false;
} }
auto* sc = e->As<ast::ScalarConstructorExpression>(); auto* lit = e->As<ast::Literal>();
if (result_type->Is<sem::Vector>() && sc == nullptr) { if (result_type->Is<sem::Vector>() && lit == nullptr) {
return false; return false;
} }
// This should all be handled by |is_constructor_const| call above // This should all be handled by |is_constructor_const| call above
if (sc == nullptr) { if (lit == nullptr) {
continue; continue;
} }
@ -1327,7 +1315,7 @@ bool Builder::is_constructor_const(const ast::Expression* expr,
} else if (auto* str = subtype->As<sem::Struct>()) { } else if (auto* str = subtype->As<sem::Struct>()) {
subtype = str->Members()[i]->Type(); subtype = str->Members()[i]->Type();
} }
if (subtype != TypeOf(sc)->UnwrapRef()) { if (subtype != TypeOf(lit)->UnwrapRef()) {
return false; return false;
} }
} }
@ -1409,8 +1397,7 @@ uint32_t Builder::GenerateTypeConstructorExpression(
for (auto* e : values) { for (auto* e : values) {
uint32_t id = 0; uint32_t id = 0;
if (constructor_is_const) { if (constructor_is_const) {
id = GenerateConstructorExpression(nullptr, id = GenerateConstructorExpression(nullptr, e);
e->As<ast::ConstructorExpression>());
} else { } else {
id = GenerateExpression(e); id = GenerateExpression(e);
id = GenerateLoadIfNeeded(TypeOf(e), id); id = GenerateLoadIfNeeded(TypeOf(e), id);

View File

@ -339,9 +339,8 @@ class Builder {
/// @param var the variable generated for, nullptr if no variable associated. /// @param var the variable generated for, nullptr if no variable associated.
/// @param expr the expression to generate /// @param expr the expression to generate
/// @returns the ID of the expression or 0 on failure. /// @returns the ID of the expression or 0 on failure.
uint32_t GenerateConstructorExpression( uint32_t GenerateConstructorExpression(const ast::Variable* var,
const ast::Variable* var, const ast::Expression* expr);
const ast::ConstructorExpression* expr);
/// Generates a type constructor expression /// Generates a type constructor expression
/// @param var the variable generated for, nullptr if no variable associated. /// @param var the variable generated for, nullptr if no variable associated.
/// @param init the expression to generate /// @param init the expression to generate

View File

@ -131,6 +131,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) { if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i); return EmitIdentifier(out, i);
} }
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* c = expr->As<ast::ConstructorExpression>()) { if (auto* c = expr->As<ast::ConstructorExpression>()) {
return EmitConstructor(out, c); return EmitConstructor(out, c);
} }
@ -242,9 +245,6 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
bool GeneratorImpl::EmitConstructor(std::ostream& out, bool GeneratorImpl::EmitConstructor(std::ostream& out,
const ast::ConstructorExpression* expr) { const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>()); return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
} }
@ -273,12 +273,6 @@ bool GeneratorImpl::EmitTypeConstructor(
return true; return true;
} }
bool GeneratorImpl::EmitScalarConstructor(
std::ostream& out,
const ast::ScalarConstructorExpression* expr) {
return EmitLiteral(out, expr->literal);
}
bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::Literal* lit) { bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::Literal* lit) {
if (auto* bl = lit->As<ast::BoolLiteral>()) { if (auto* bl = lit->As<ast::BoolLiteral>()) {
out << (bl->value ? "true" : "false"); out << (bl->value ? "true" : "false");

View File

@ -30,7 +30,6 @@
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/member_accessor_expression.h" #include "src/ast/member_accessor_expression.h"
#include "src/ast/return_statement.h" #include "src/ast/return_statement.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/switch_statement.h" #include "src/ast/switch_statement.h"
#include "src/ast/type_constructor_expression.h" #include "src/ast/type_constructor_expression.h"
#include "src/ast/unary_op_expression.h" #include "src/ast/unary_op_expression.h"
@ -96,12 +95,11 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement /// @param stmt the statement
/// @returns true if the statment was emitted successfully /// @returns true if the statment was emitted successfully
bool EmitCase(const ast::CaseStatement* stmt); bool EmitCase(const ast::CaseStatement* stmt);
/// Handles generating a scalar constructor /// Handles generating a literal expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the scalar constructor expression /// @param expr the literal expression expression
/// @returns true if the scalar constructor is emitted /// @returns true if the literal expression is emitted
bool EmitScalarConstructor(std::ostream& out, bool EmitLiteral(std::ostream& out, const ast::Literal* expr);
const ast::ScalarConstructorExpression* expr);
/// Handles a continue statement /// Handles a continue statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully /// @returns true if the statement was emitted successfully
@ -138,11 +136,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the discard statement /// @param stmt the discard statement
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
bool EmitDiscard(const ast::DiscardStatement* stmt); bool EmitDiscard(const ast::DiscardStatement* stmt);
/// Handles a literal
/// @param out the output of the expression stream
/// @param lit the literal to emit
/// @returns true if the literal was successfully emitted
bool EmitLiteral(std::ostream& out, const ast::Literal* lit);
/// Handles a loop statement /// Handles a loop statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emtited /// @returns true if the statement was emtited

View File

@ -59,7 +59,7 @@ TEST_P(WgslGenerator_FloatLiteralTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; std::stringstream out;
ASSERT_TRUE(gen.EmitScalarConstructor(out, v)) << gen.error(); ASSERT_TRUE(gen.EmitLiteral(out, v)) << gen.error();
EXPECT_EQ(out.str(), GetParam().expected); EXPECT_EQ(out.str(), GetParam().expected);
} }

View File

@ -194,7 +194,6 @@ tint_unittests_source_set("tint_unittests_core_src") {
"../src/ast/return_statement_test.cc", "../src/ast/return_statement_test.cc",
"../src/ast/sampled_texture_test.cc", "../src/ast/sampled_texture_test.cc",
"../src/ast/sampler_test.cc", "../src/ast/sampler_test.cc",
"../src/ast/scalar_constructor_expression_test.cc",
"../src/ast/sint_literal_test.cc", "../src/ast/sint_literal_test.cc",
"../src/ast/stage_decoration_test.cc", "../src/ast/stage_decoration_test.cc",
"../src/ast/storage_texture_test.cc", "../src/ast/storage_texture_test.cc",