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/sampler.cc",
"ast/sampler.h",
"ast/scalar_constructor_expression.cc",
"ast/scalar_constructor_expression.h",
"ast/sint_literal.cc",
"ast/sint_literal.h",
"ast/stage_decoration.cc",

View File

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

View File

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

View File

@ -17,13 +17,13 @@
#include <string>
#include "src/ast/node.h"
#include "src/ast/expression.h"
namespace tint {
namespace ast {
/// Base class for a literal value
class Literal : public Castable<Literal, Node> {
/// Base class for a literal value expressions
class Literal : public Castable<Literal, Expression> {
public:
~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/bitcast_expression.h"
#include "src/ast/call_expression.h"
#include "src/ast/literal.h"
#include "src/ast/member_accessor_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/unary_op_expression.h"
#include "src/utils/reverse.h"
@ -122,8 +122,7 @@ bool TraverseExpressions(const ast::Expression* root,
to_visit.push_back(member->structure);
} else if (auto* unary = expr->As<ast::UnaryOpExpression>()) {
to_visit.push_back(unary->expr);
} else if (expr->IsAnyOf<ast::ScalarConstructorExpression,
ast::IdentifierExpression,
} else if (expr->IsAnyOf<ast::Literal, ast::IdentifierExpression,
ast::PhonyExpression>()) {
// Leaf expression
} else {

View File

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

View File

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

View File

@ -114,10 +114,6 @@ const ast::TypeName* ProgramBuilder::TypesBuilder::Of(
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::Expression* expr) {
if (auto* ce = expr->As<ast::CallExpression>()) {

View File

@ -55,7 +55,6 @@
#include "src/ast/return_statement.h"
#include "src/ast/sampled_texture.h"
#include "src/ast/sampler.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/storage_texture.h"
@ -1038,57 +1037,53 @@ class ProgramBuilder {
/// @param source the source information
/// @param value the boolean value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source,
bool value) {
return create<ast::ScalarConstructorExpression>(source, Literal(value));
const ast::Literal* Expr(const Source& source, bool value) {
return create<ast::BoolLiteral>(source, value);
}
/// @param value the boolean value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(bool value) {
return create<ast::ScalarConstructorExpression>(Literal(value));
const ast::BoolLiteral* Expr(bool value) {
return create<ast::BoolLiteral>(value);
}
/// @param source the source information
/// @param value the float value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source,
f32 value) {
return create<ast::ScalarConstructorExpression>(source, Literal(value));
const ast::FloatLiteral* Expr(const Source& source, f32 value) {
return create<ast::FloatLiteral>(source, value);
}
/// @param value the float value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(f32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value));
const ast::FloatLiteral* Expr(f32 value) {
return create<ast::FloatLiteral>(value);
}
/// @param source the source information
/// @param value the integer value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source,
i32 value) {
return create<ast::ScalarConstructorExpression>(source, Literal(value));
const ast::Literal* Expr(const Source& source, i32 value) {
return create<ast::SintLiteral>(source, value);
}
/// @param value the integer value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(i32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value));
const ast::SintLiteral* Expr(i32 value) {
return create<ast::SintLiteral>(value);
}
/// @param source the source information
/// @param value the unsigned int value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(const Source& source,
u32 value) {
return create<ast::ScalarConstructorExpression>(source, Literal(value));
const ast::UintLiteral* Expr(const Source& source, u32 value) {
return create<ast::UintLiteral>(source, value);
}
/// @param value the unsigned int value
/// @return a Scalar constructor for the given value
const ast::ScalarConstructorExpression* Expr(u32 value) {
return create<ast::ScalarConstructorExpression>(Literal(value));
const ast::UintLiteral* Expr(u32 value) {
return create<ast::UintLiteral>(value);
}
/// 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.
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
/// construct a partial AST and require the Resolver to reach these
/// nodes.

View File

@ -2548,9 +2548,7 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
return source_expr;
}
case SkipReason::kPointSizeBuiltinValue: {
return {ty_.F32(),
create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(Source{}, 1.0f))};
return {ty_.F32(), create<ast::FloatLiteral>(Source{}, 1.0f)};
}
case SkipReason::kPointSizeBuiltinPointer:
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 make_index = [this](uint32_t literal) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::UintLiteral>(Source{}, literal));
return create<ast::UintLiteral>(Source{}, literal);
};
// 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 {
return create<ast::ScalarConstructorExpression>(
source, create<ast::BoolLiteral>(source, true));
return create<ast::BoolLiteral>(source, true);
}
const ast::Expression* FunctionEmitter::MakeFalse(const Source& source) const {
return create<ast::ScalarConstructorExpression>(
source, create<ast::BoolLiteral>(source, false));
return create<ast::BoolLiteral>(source, false);
}
TypedExpression FunctionEmitter::MakeVectorShuffle(

View File

@ -1353,34 +1353,30 @@ bool ParserImpl::EmitScalarSpecConstants() {
for (auto& inst : module_->types_values()) {
// These will be populated for a valid scalar spec constant.
const Type* ast_type = nullptr;
ast::ScalarConstructorExpression* ast_expr = nullptr;
ast::Literal* ast_expr = nullptr;
switch (inst.opcode()) {
case SpvOpSpecConstantTrue:
case SpvOpSpecConstantFalse: {
ast_type = ConvertType(inst.type_id());
ast_expr = create<ast::ScalarConstructorExpression>(
Source{}, create<ast::BoolLiteral>(
Source{}, inst.opcode() == SpvOpSpecConstantTrue));
ast_expr = create<ast::BoolLiteral>(
Source{}, inst.opcode() == SpvOpSpecConstantTrue);
break;
}
case SpvOpSpecConstant: {
ast_type = ConvertType(inst.type_id());
const uint32_t literal_value = inst.GetSingleWordInOperand(0);
if (ast_type->Is<I32>()) {
ast_expr = create<ast::ScalarConstructorExpression>(
Source{}, create<ast::SintLiteral>(
Source{}, static_cast<int32_t>(literal_value)));
ast_expr = create<ast::SintLiteral>(
Source{}, static_cast<int32_t>(literal_value));
} else if (ast_type->Is<U32>()) {
ast_expr = create<ast::ScalarConstructorExpression>(
Source{}, create<ast::UintLiteral>(
Source{}, static_cast<uint32_t>(literal_value)));
ast_expr = create<ast::UintLiteral>(
Source{}, static_cast<uint32_t>(literal_value));
} else if (ast_type->Is<F32>()) {
float float_value;
// Copy the bits so we can read them as a float.
std::memcpy(&float_value, &literal_value, sizeof(float_value));
ast_expr = create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(Source{}, float_value));
ast_expr = create<ast::FloatLiteral>(Source{}, float_value);
} else {
return Fail() << " invalid result type for OpSpecConstant "
<< inst.PrettyPrint();
@ -1981,26 +1977,20 @@ TypedExpression ParserImpl::MakeConstantExpressionForScalarSpirvConstant(
// Currently "null<type>" is missing from the WGSL parser.
// See https://bugs.chromium.org/p/tint/issues/detail?id=34
if (ast_type->Is<U32>()) {
return {ty_.U32(), create<ast::ScalarConstructorExpression>(
Source{}, create<ast::UintLiteral>(
source, spirv_const->GetU32()))};
return {ty_.U32(), create<ast::UintLiteral>(source, spirv_const->GetU32())};
}
if (ast_type->Is<I32>()) {
return {ty_.I32(), create<ast::ScalarConstructorExpression>(
Source{}, create<ast::SintLiteral>(
source, spirv_const->GetS32()))};
return {ty_.I32(), create<ast::SintLiteral>(source, spirv_const->GetS32())};
}
if (ast_type->Is<F32>()) {
return {ty_.F32(), create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(
source, spirv_const->GetFloat()))};
return {ty_.F32(),
create<ast::FloatLiteral>(source, spirv_const->GetFloat())};
}
if (ast_type->Is<Bool>()) {
const bool value = spirv_const->AsNullConstant()
? false
: spirv_const->AsBoolConstant()->value();
return {ty_.Bool(), create<ast::ScalarConstructorExpression>(
Source{}, create<ast::BoolLiteral>(source, value))};
return {ty_.Bool(), create<ast::BoolLiteral>(source, value)};
}
Fail() << "expected scalar constant";
return {};
@ -2021,20 +2011,16 @@ const ast::Expression* ParserImpl::MakeNullValue(const Type* type) {
type = type->UnwrapAlias();
if (type->Is<Bool>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::BoolLiteral>(Source{}, false));
return create<ast::BoolLiteral>(Source{}, false);
}
if (type->Is<U32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::UintLiteral>(Source{}, 0u));
return create<ast::UintLiteral>(Source{}, 0u);
}
if (type->Is<I32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::SintLiteral>(Source{}, 0));
return create<ast::SintLiteral>(Source{}, 0);
}
if (type->Is<F32>()) {
return create<ast::ScalarConstructorExpression>(
Source{}, create<ast::FloatLiteral>(Source{}, 0.0f));
return create<ast::FloatLiteral>(Source{}, 0.0f);
}
if (type->Is<Alias>()) {
// 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)
return Failure::kErrored;
ast::ConstructorExpression* initializer = nullptr;
const ast::Expression* initializer = nullptr;
if (match(Token::Type::kEqual)) {
auto init = expect_const_expr();
if (init.errored)
if (init.errored) {
return Failure::kErrored;
}
initializer = std::move(init.value);
}
@ -2175,15 +2176,18 @@ Maybe<const ast::Expression*> ParserImpl::primary_expression() {
auto source = t.source();
auto lit = const_literal();
if (lit.errored)
if (lit.errored) {
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)) {
auto paren = expect_paren_rhs_stmt();
if (paren.errored)
if (paren.errored) {
return Failure::kErrored;
}
return paren.value;
}
@ -2869,23 +2873,25 @@ Maybe<const ast::Literal*> ParserImpl::const_literal() {
// const_expr
// : type_decl PAREN_LEFT ((const_expr COMMA)? const_expr COMMA?)? PAREN_RIGHT
// | const_literal
Expect<ast::ConstructorExpression*> ParserImpl::expect_const_expr() {
Expect<const ast::Expression*> ParserImpl::expect_const_expr() {
auto t = peek();
auto source = t.source();
if (t.IsLiteral()) {
auto lit = const_literal();
if (lit.errored)
if (lit.errored) {
return Failure::kErrored;
if (!lit.matched)
}
if (!lit.matched) {
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())) {
if (peek_is(Token::Type::kParenLeft, 1) ||
peek_is(Token::Type::kLessThan, 1)) {
auto type = expect_type("const_expr");
if (type.errored)
if (type.errored) {
return Failure::kErrored;
}
auto params = expect_paren_block(
"type constructor", [&]() -> Expect<ast::ExpressionList> {

View File

@ -571,7 +571,7 @@ class ParserImpl {
Maybe<const ast::Literal*> const_literal();
/// Parses a `const_expr` grammar element, erroring on parse failure.
/// @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
/// @returns the parsed expression or nullptr
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>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {

View File

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

View File

@ -46,7 +46,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
ASSERT_EQ(e.value.size(), 3u);
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>());
}
@ -58,7 +58,7 @@ TEST_F(ParserImplTest, ArgumentExpressionList_TrailingComma) {
ASSERT_EQ(e.value.size(), 2u);
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) {

View File

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

View File

@ -34,17 +34,11 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
ASSERT_EQ(t->values.size(), 2u);
auto& v = t->values;
ASSERT_TRUE(v[0]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(v[0]->Is<ast::ScalarConstructorExpression>());
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[0]->Is<ast::FloatLiteral>());
EXPECT_FLOAT_EQ(v[0]->As<ast::FloatLiteral>()->value, 1.);
ASSERT_TRUE(v[1]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(v[1]->Is<ast::ScalarConstructorExpression>());
c = v[1]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::FloatLiteral>());
EXPECT_FLOAT_EQ(c->literal->As<ast::FloatLiteral>()->value, 2.);
ASSERT_TRUE(v[1]->Is<ast::FloatLiteral>());
EXPECT_FLOAT_EQ(v[1]->As<ast::FloatLiteral>()->value, 2.);
}
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);
ASSERT_EQ(t->values.size(), 2u);
ASSERT_TRUE(t->values[0]->Is<ast::ScalarConstructorExpression>());
ASSERT_TRUE(t->values[1]->Is<ast::ScalarConstructorExpression>());
ASSERT_TRUE(t->values[0]->Is<ast::Literal>());
ASSERT_TRUE(t->values[1]->Is<ast::Literal>());
}
TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
@ -121,11 +115,8 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_FALSE(e.errored);
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>());
auto* c = e->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::BoolLiteral>());
EXPECT_TRUE(c->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(e.value->Is<ast::BoolLiteral>());
EXPECT_TRUE(e.value->As<ast::BoolLiteral>()->value);
}
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>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {

View File

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

View File

@ -71,23 +71,14 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr);
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr);
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
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(values[2]->Is<ast::IntLiteral>());
EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
auto* body = f->body;
ASSERT_EQ(body->statements.size(), 1u);
@ -119,23 +110,14 @@ fn main() { return; })");
ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr);
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr);
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
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(values[2]->Is<ast::IntLiteral>());
EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(decorations[1]->Is<ast::StageDecoration>());
EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->stage,
@ -172,23 +154,14 @@ fn main() { return; })");
ASSERT_TRUE(decos[0]->Is<ast::WorkgroupDecoration>());
auto values = decos[0]->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_NE(values[1], nullptr);
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 3u);
ASSERT_NE(values[2], nullptr);
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
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(values[2]->Is<ast::IntLiteral>());
EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(decos[1]->Is<ast::StageDecoration>());
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>());
const ast::Expression* x = deco_0->As<ast::WorkgroupDecoration>()->x;
ASSERT_NE(x, nullptr);
auto* x_scalar = x->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
auto* x_literal = x->As<ast::Literal>();
ASSERT_NE(x_literal, nullptr);
ASSERT_TRUE(x_literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
ASSERT_TRUE(deco_1->Is<ast::StageDecoration>());
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();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
EXPECT_EQ(values[1], nullptr);
EXPECT_EQ(values[2], nullptr);
@ -57,17 +54,11 @@ TEST_F(ParserImplTest, Decoration_Workgroup_2Param) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr);
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 5u);
EXPECT_EQ(values[2], nullptr);
}
@ -85,23 +76,14 @@ TEST_F(ParserImplTest, Decoration_Workgroup_3Param) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr);
auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(y_scalar, nullptr);
ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_TRUE(values[1]->Is<ast::IntLiteral>());
EXPECT_EQ(values[1]->As<ast::IntLiteral>()->ValueAsU32(), 5u);
ASSERT_NE(values[2], nullptr);
auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(z_scalar, nullptr);
ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 6u);
ASSERT_TRUE(values[2]->Is<ast::IntLiteral>());
EXPECT_EQ(values[2]->As<ast::IntLiteral>()->ValueAsU32(), 6u);
}
TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) {
@ -117,11 +99,8 @@ TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) {
auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
ASSERT_NE(values[0], nullptr);
auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(x_scalar, nullptr);
ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_TRUE(values[0]->Is<ast::IntLiteral>());
EXPECT_EQ(values[0]->As<ast::IntLiteral>()->ValueAsU32(), 4u);
ASSERT_NE(values[1], nullptr);
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);
ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
EXPECT_TRUE(e->constructor->Is<ast::Literal>());
EXPECT_FALSE(
ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations));
@ -69,7 +69,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
EXPECT_EQ(e->source.range.end.column, 6u);
ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
EXPECT_TRUE(e->constructor->Is<ast::Literal>());
EXPECT_FALSE(
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);
ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
EXPECT_TRUE(e->constructor->Is<ast::Literal>());
auto* override_deco =
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);
ASSERT_NE(e->constructor, nullptr);
EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
EXPECT_TRUE(e->constructor->Is<ast::Literal>());
auto* override_deco =
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);
ASSERT_NE(e->constructor, nullptr);
ASSERT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
ASSERT_TRUE(e->constructor->Is<ast::ScalarConstructorExpression>());
ASSERT_TRUE(e->constructor->Is<ast::FloatLiteral>());
}
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {

View File

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

View File

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

View File

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

View File

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

View File

@ -45,29 +45,17 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
ASSERT_EQ(ty->values.size(), 4u);
const auto& val = ty->values;
ASSERT_TRUE(val[0]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(val[0]->Is<ast::ScalarConstructorExpression>());
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[0]->Is<ast::SintLiteral>());
EXPECT_EQ(val[0]->As<ast::SintLiteral>()->value, 1);
ASSERT_TRUE(val[1]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(val[1]->Is<ast::ScalarConstructorExpression>());
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[1]->Is<ast::SintLiteral>());
EXPECT_EQ(val[1]->As<ast::SintLiteral>()->value, 2);
ASSERT_TRUE(val[2]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(val[2]->Is<ast::ScalarConstructorExpression>());
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[2]->Is<ast::SintLiteral>());
EXPECT_EQ(val[2]->As<ast::SintLiteral>()->value, 3);
ASSERT_TRUE(val[3]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(val[3]->Is<ast::ScalarConstructorExpression>());
ident = val[3]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 4);
ASSERT_TRUE(val[3]->Is<ast::SintLiteral>());
EXPECT_EQ(val[3]->As<ast::SintLiteral>()->value, 4);
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
@ -173,15 +161,11 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_StructConstructor_NotEmpty) {
auto values = constructor->values;
ASSERT_EQ(values.size(), 2u);
ASSERT_TRUE(values[0]->Is<ast::ScalarConstructorExpression>());
auto* val0 = values[0]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(val0->literal->Is<ast::UintLiteral>());
EXPECT_EQ(val0->literal->As<ast::UintLiteral>()->value, 1u);
ASSERT_TRUE(values[0]->Is<ast::UintLiteral>());
EXPECT_EQ(values[0]->As<ast::UintLiteral>()->value, 1u);
ASSERT_TRUE(values[1]->Is<ast::ScalarConstructorExpression>());
auto* val1 = values[1]->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(val1->literal->Is<ast::FloatLiteral>());
EXPECT_EQ(val1->literal->As<ast::FloatLiteral>()->value, 2.f);
ASSERT_TRUE(values[1]->Is<ast::FloatLiteral>());
EXPECT_EQ(values[1]->As<ast::FloatLiteral>()->value, 2.f);
}
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
@ -191,11 +175,8 @@ TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>());
auto* init = e->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
EXPECT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(e->Is<ast::BoolLiteral>());
EXPECT_TRUE(e->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
@ -253,8 +234,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
ASSERT_TRUE(c->type->Is<ast::F32>());
ASSERT_EQ(c->values.size(), 1u);
ASSERT_TRUE(c->values[0]->Is<ast::ConstructorExpression>());
ASSERT_TRUE(c->values[0]->Is<ast::ScalarConstructorExpression>());
ASSERT_TRUE(c->values[0]->Is<ast::IntLiteral>());
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
@ -269,8 +249,7 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
auto* c = e->As<ast::BitcastExpression>();
ASSERT_TRUE(c->type->Is<ast::F32>());
ASSERT_TRUE(c->expr->Is<ast::ConstructorExpression>());
ASSERT_TRUE(c->expr->Is<ast::ScalarConstructorExpression>());
ASSERT_TRUE(c->expr->Is<ast::IntLiteral>());
}
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>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
@ -58,11 +55,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
@ -81,11 +75,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
@ -104,11 +95,8 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
auto* ident = rel->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteral>());
ASSERT_TRUE(rel->rhs->As<ast::BoolLiteral>()->value);
}
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {

View File

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

View File

@ -34,11 +34,8 @@ TEST_F(ParserImplTest, SingularExpression_Array_ConstantIndex) {
auto* ident = ary->array->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>());
ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>());
auto* c = ary->index->As<ast::ScalarConstructorExpression>();
ASSERT_TRUE(c->literal->Is<ast::SintLiteral>());
EXPECT_EQ(c->literal->As<ast::SintLiteral>()->value, 1);
ASSERT_TRUE(ary->index->Is<ast::SintLiteral>());
EXPECT_EQ(ary->index->As<ast::SintLiteral>()->value, 1);
}
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->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[2]->Is<ast::BinaryExpression>());
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -81,7 +81,8 @@ void FoldConstants::Run(CloneContext& ctx, const DataMap&, DataMap&) {
}
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;

View File

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

View File

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

View File

@ -189,7 +189,9 @@ struct Robustness::State {
// Convert idx to an expression, so we can emit the new accessor.
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

View File

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

View File

@ -85,7 +85,7 @@ const ast::TypeConstructorExpression* AppendVector(
const auto num_supplied = vc->values.size();
if (num_supplied == 0) {
// 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>()) {
return b->Expr(0);
} 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_EQ(vec_0004->values.size(), 4u);
for (size_t i = 0; i < 3; i++) {
auto* ctor = vec_0004->values[i]->As<ast::ScalarConstructorExpression>();
ASSERT_NE(ctor, nullptr);
auto* literal = As<ast::SintLiteral>(ctor->literal);
auto* literal = As<ast::SintLiteral>(vec_0004->values[i]);
ASSERT_NE(literal, nullptr);
EXPECT_EQ(literal->value, 0);
}

View File

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

View File

@ -198,12 +198,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the discard statement
/// @returns true if the statement was successfully emitted
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
/// @param out the output of the expression stream
/// @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,
const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
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(
std::ostream& out,
const ast::TypeConstructorExpression* expr) {
@ -2218,6 +2209,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i);
}
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return EmitMemberAccessor(out, m);
}

View File

@ -227,12 +227,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the discard statement
/// @returns true if the statement was successfully emitted
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
/// @param out the output of the expression stream
/// @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,
const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
}
@ -1387,12 +1384,6 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) {
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) {
if (auto* l = lit->As<ast::BoolLiteral>()) {
out << (l->value ? "true" : "false");
@ -1445,6 +1436,9 @@ bool GeneratorImpl::EmitExpression(std::ostream& out,
if (auto* i = expr->As<ast::IdentifierExpression>()) {
return EmitIdentifier(out, i);
}
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return EmitMemberAccessor(out, m);
}

View File

@ -26,12 +26,12 @@
#include "src/ast/break_statement.h"
#include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h"
#include "src/ast/expression.h"
#include "src/ast/if_statement.h"
#include "src/ast/interpolate_decoration.h"
#include "src/ast/loop_statement.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/return_statement.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/switch_statement.h"
#include "src/ast/type_constructor_expression.h"
#include "src/ast/unary_op_expression.h"
@ -241,12 +241,6 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
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
/// @param out the output of the expression stream
/// @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>()) {
return GenerateIdentifierExpression(i);
}
if (auto* l = expr->As<ast::Literal>()) {
return GenerateLiteralIfNeeded(nullptr, l);
}
if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
return GenerateAccessorExpression(m);
}
@ -757,13 +760,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
uint32_t init_id = 0;
if (var->constructor) {
if (!var->constructor->Is<ast::ConstructorExpression>()) {
error_ = "scalar constructor expected";
return false;
}
init_id = GenerateConstructorExpression(
var, var->constructor->As<ast::ConstructorExpression>());
init_id = GenerateConstructorExpression(var, var->constructor);
if (init_id == 0) {
return false;
}
@ -931,14 +928,7 @@ bool Builder::GenerateArrayAccessor(const ast::ArrayAccessorExpression* expr,
auto extract_id = extract.to_i();
// If the index is a literal, we use OpCompositeExtract.
if (auto* scalar = expr->index->As<ast::ScalarConstructorExpression>()) {
auto* literal = scalar->literal->As<ast::IntLiteral>();
if (!literal) {
TINT_ICE(Writer, builder_.Diagnostics())
<< "bad literal in array accessor";
return false;
}
if (auto* literal = expr->index->As<ast::IntLiteral>()) {
if (!push_function_inst(spv::Op::OpCompositeExtract,
{Operand::Int(result_type_id), extract,
Operand::Int(info->source_id),
@ -1264,11 +1254,10 @@ uint32_t Builder::GetGLSLstd450Import() {
return id;
}
uint32_t Builder::GenerateConstructorExpression(
const ast::Variable* var,
const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return GenerateLiteralIfNeeded(var, scalar->literal);
uint32_t Builder::GenerateConstructorExpression(const ast::Variable* var,
const ast::Expression* expr) {
if (auto* literal = expr->As<ast::Literal>()) {
return GenerateLiteralIfNeeded(var, literal);
}
if (auto* type = expr->As<ast::TypeConstructorExpression>()) {
return GenerateTypeConstructorExpression(var, type);
@ -1280,20 +1269,19 @@ uint32_t Builder::GenerateConstructorExpression(
bool Builder::is_constructor_const(const ast::Expression* expr,
bool is_global_init) {
auto* constructor = expr->As<ast::ConstructorExpression>();
if (constructor == nullptr) {
return false;
}
if (constructor->Is<ast::ScalarConstructorExpression>()) {
if (expr->Is<ast::Literal>()) {
return true;
}
auto* tc = constructor->As<ast::TypeConstructorExpression>();
auto* tc = expr->As<ast::TypeConstructorExpression>();
if (!tc) {
return false;
}
auto* result_type = TypeOf(tc)->UnwrapRef();
for (size_t i = 0; i < tc->values.size(); ++i) {
auto* e = tc->values[i];
if (!e->Is<ast::ConstructorExpression>()) {
if (!e->IsAnyOf<ast::TypeConstructorExpression, ast::Literal>()) {
if (is_global_init) {
error_ = "constructor must be a constant expression";
return false;
@ -1307,13 +1295,13 @@ bool Builder::is_constructor_const(const ast::Expression* expr,
return false;
}
auto* sc = e->As<ast::ScalarConstructorExpression>();
if (result_type->Is<sem::Vector>() && sc == nullptr) {
auto* lit = e->As<ast::Literal>();
if (result_type->Is<sem::Vector>() && lit == nullptr) {
return false;
}
// This should all be handled by |is_constructor_const| call above
if (sc == nullptr) {
if (lit == nullptr) {
continue;
}
@ -1327,7 +1315,7 @@ bool Builder::is_constructor_const(const ast::Expression* expr,
} else if (auto* str = subtype->As<sem::Struct>()) {
subtype = str->Members()[i]->Type();
}
if (subtype != TypeOf(sc)->UnwrapRef()) {
if (subtype != TypeOf(lit)->UnwrapRef()) {
return false;
}
}
@ -1409,8 +1397,7 @@ uint32_t Builder::GenerateTypeConstructorExpression(
for (auto* e : values) {
uint32_t id = 0;
if (constructor_is_const) {
id = GenerateConstructorExpression(nullptr,
e->As<ast::ConstructorExpression>());
id = GenerateConstructorExpression(nullptr, e);
} else {
id = GenerateExpression(e);
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 expr the expression to generate
/// @returns the ID of the expression or 0 on failure.
uint32_t GenerateConstructorExpression(
const ast::Variable* var,
const ast::ConstructorExpression* expr);
uint32_t GenerateConstructorExpression(const ast::Variable* var,
const ast::Expression* expr);
/// Generates a type constructor expression
/// @param var the variable generated for, nullptr if no variable associated.
/// @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>()) {
return EmitIdentifier(out, i);
}
if (auto* l = expr->As<ast::Literal>()) {
return EmitLiteral(out, l);
}
if (auto* c = expr->As<ast::ConstructorExpression>()) {
return EmitConstructor(out, c);
}
@ -242,9 +245,6 @@ bool GeneratorImpl::EmitCall(std::ostream& out,
bool GeneratorImpl::EmitConstructor(std::ostream& out,
const ast::ConstructorExpression* expr) {
if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
return EmitScalarConstructor(out, scalar);
}
return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
}
@ -273,12 +273,6 @@ bool GeneratorImpl::EmitTypeConstructor(
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) {
if (auto* bl = lit->As<ast::BoolLiteral>()) {
out << (bl->value ? "true" : "false");

View File

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

View File

@ -59,7 +59,7 @@ TEST_P(WgslGenerator_FloatLiteralTest, Emit) {
GeneratorImpl& gen = Build();
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);
}

View File

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