diff --git a/src/resolver/type_constructor_validation_test.cc b/src/resolver/type_constructor_validation_test.cc index 44066dd8fb..d363f8c73f 100644 --- a/src/resolver/type_constructor_validation_test.cc +++ b/src/resolver/type_constructor_validation_test.cc @@ -399,6 +399,1785 @@ TEST_F(ResolverTypeConstructorValidationTest, } // namespace ConversionConstructorTest +namespace ArrayConstructor { + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_ZeroValue_Pass) { + // array(); + auto* tc = array(); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_type_match) { + // array(0u, 10u. 20u); + auto* tc = + array(create(Literal(0u)), + create(Literal(10u)), + create(Literal(20u))); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_type_Mismatch_U32F32) { + // array(0u, 1.0f, 20u); + auto* tc = array( + create(Literal(0u)), + create(Source{{12, 34}}, Literal(1.0f)), + create(Literal(20u))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'u32', found 'f32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_ScalarArgumentTypeMismatch_F32I32) { + // array(1); + auto* tc = array( + create(Source{{12, 34}}, Literal(1))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'f32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_ScalarArgumentTypeMismatch_U32I32) { + // array(1, 0u, 0u, 0u, 0u, 0u); + auto* tc = array( + create(Source{{12, 34}}, Literal(1)), + create(Literal(0u)), + create(Literal(0u)), + create(Literal(0u)), + create(Literal(0u))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'u32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) { + // array(1, vec2()); + auto* tc = array(create(Literal(1)), + create( + Source{{12, 34}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'i32', found 'vec2'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32U32) { + // array, 2>(vec3(), vec3()); + auto* e0 = vec3(); + SetSource(Source::Location({12, 34})); + auto* e1 = vec3(); + auto* t = Construct(ty.array(ty.vec3(), 2), e0, e1); + WrapInFunction(t); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'vec3', found 'vec3'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32Bool) { + // array, 2>(vec3(), vec3(true, true, false)); + SetSource(Source::Location({12, 34})); + auto* e0 = vec3(true, true, false); + auto* e1 = vec3(); + auto* t = Construct(ty.array(ty.vec3(), 2), e0, e1); + WrapInFunction(t); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'vec3', found 'vec3'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_ArrayOfArray_SubElemSizeMismatch) { + // array, 2>(array(), array()); + SetSource(Source::Location({12, 34})); + auto* e0 = array(); + auto* e1 = array(); + auto* t = Construct(ty.array(ty.array(), 2), e0, e1); + WrapInFunction(t); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'array', found 'array'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_ArrayOfArray_SubElemTypeMismatch) { + // array, 2>(array(), array()); + auto* e0 = array(); + SetSource(Source::Location({12, 34})); + auto* e1 = array(); + auto* t = Construct(ty.array(ty.array(), 2), e0, e1); + WrapInFunction(t); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in array constructor does not match array type: " + "expected 'array', found 'array'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_TooFewElements) { + // array(1, 2, 3); + SetSource(Source::Location({12, 34})); + auto* tc = + array(create(Literal(1)), + create(Literal(2)), + create(Literal(3))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: array constructor has too few elements: expected 4, " + "found 3"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_TooManyElements) { + // array(1, 2, 3, 4, 5); + SetSource(Source::Location({12, 34})); + auto* tc = + array(create(Literal(1)), + create(Literal(2)), + create(Literal(3)), + create(Literal(4)), + create(Literal(5))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: array constructor has too many " + "elements: expected 4, " + "found 5"); +} + +TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_Runtime) { + // array(1); + auto* tc = array( + create(Source{{12, 34}}, Literal(1))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Array_RuntimeZeroValue) { + // array(); + auto* tc = array(); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array"); +} + +} // namespace ArrayConstructor + +namespace VectorConstructor { + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2F32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec2( + create(Source{{12, 34}}, Literal(1)), + 1.0f); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2U32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec2(1u, create( + Source{{12, 34}}, Literal(1))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'u32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2I32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec2( + create(Source{{12, 34}}, Literal(1u)), + 1); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'i32', found 'u32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2Bool_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec2(true, create( + Source{{12, 34}}, Literal(1))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'bool', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_Vec3ArgumentCardinalityTooLarge) { + auto* tc = vec2(create( + Source{{12, 34}}, ty.vec3(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec2' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_Vec4ArgumentCardinalityTooLarge) { + auto* tc = vec2(create( + Source{{12, 34}}, ty.vec4(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec2' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_TooManyArgumentsScalar) { + auto* tc = vec2( + create(Source{{12, 34}}, Literal(1.0f)), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec2' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_TooManyArgumentsVector) { + auto* tc = vec2(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec2' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) { + auto* tc = vec2(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec2' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_InvalidConversionFromVec2Bool) { + SetSource(Source::Location({12, 34})); + + auto* tc = vec2(create( + Source{{12, 34}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'bool'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Error_InvalidArgumentType) { + auto* tc = vec2(create( + Source{{12, 34}}, ty.mat2x2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: expected vector or scalar type in vector " + "constructor; found: mat2x2"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Success_ZeroValue) { + auto* tc = vec2(); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2F32_Success_Scalar) { + auto* tc = vec2(1.0f, 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2U32_Success_Scalar) { + auto* tc = vec2(1u, 1u); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2I32_Success_Scalar) { + auto* tc = vec2(1, 1); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2Bool_Success_Scalar) { + auto* tc = vec2(true, false); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Success_Identity) { + auto* tc = vec2(vec2()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec2_Success_Vec2TypeConversion) { + auto* tc = vec2(vec2()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3F32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec3( + 1.0f, 1.0f, + create(Source{{12, 34}}, Literal(1))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3U32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec3( + 1u, + create(Source{{12, 34}}, Literal(1)), + 1u); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'u32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3I32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec3( + 1, + create(Source{{12, 34}}, Literal(1u)), + 1); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'i32', found 'u32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3Bool_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec3( + true, + create(Source{{12, 34}}, Literal(1)), + false); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'bool', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_Vec4ArgumentCardinalityTooLarge) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.vec4(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooFewArgumentsScalar) { + auto* tc = vec3( + create(Source{{12, 34}}, Literal(1.0f)), + create(Source{{12, 40}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 2 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooManyArgumentsScalar) { + auto* tc = vec3( + create(Source{{12, 34}}, Literal(1.0f)), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, Literal(1.0f)), + create(Source{{12, 52}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooFewArgumentsVec2) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 2 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooManyArgumentsVec2) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) { + auto* tc = vec3( + create(Source{{12, 34}}, ty.vec2(), + ExprList()), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.vec3(), ExprList()), + create( + Source{{12, 40}}, Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 4 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_InvalidConversionFromVec3Bool) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.vec3(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'bool'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Error_InvalidArgumentType) { + auto* tc = vec3(create( + Source{{12, 34}}, ty.mat2x2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: expected vector or scalar type in vector " + "constructor; found: mat2x2"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Success_ZeroValue) { + auto* tc = vec3(); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3F32_Success_Scalar) { + auto* tc = vec3(1.0f, 1.0f, 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3U32_Success_Scalar) { + auto* tc = vec3(1u, 1u, 1u); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3I32_Success_Scalar) { + auto* tc = vec3(1, 1, 1); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3Bool_Success_Scalar) { + auto* tc = vec3(true, false, true); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Success_Vec2AndScalar) { + auto* tc = vec3(vec2(), 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Success_ScalarAndVec2) { + auto* tc = vec3(1.0f, vec2()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Success_Identity) { + auto* tc = vec3(vec3()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec3_Success_Vec3TypeConversion) { + auto* tc = vec3(vec3()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4F32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec4( + 1.0f, 1.0f, + create(Source{{12, 34}}, Literal(1)), + 1.0f); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4U32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec4( + 1u, 1u, + create(Source{{12, 34}}, Literal(1)), + 1u); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'u32', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4I32_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec4( + 1, 1, + create(Source{{12, 34}}, Literal(1u)), + 1); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'i32', found 'u32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4Bool_Error_ScalarArgumentTypeMismatch) { + auto* tc = vec4( + true, false, + create(Source{{12, 34}}, Literal(1)), + true); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'bool', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooFewArgumentsScalar) { + auto* tc = vec4( + create(Source{{12, 34}}, Literal(1.0f)), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsScalar) { + auto* tc = vec4( + create(Source{{12, 34}}, Literal(1.0f)), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, Literal(1.0f)), + create(Source{{12, 52}}, Literal(1.0f)), + create(Source{{12, 58}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) { + auto* tc = vec4( + create(Source{{12, 34}}, ty.vec2(), + ExprList()), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, Literal(1.0f)), + create(Source{{12, 52}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Scalar) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList()), + create( + Source{{12, 46}}, Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Vec2) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 6 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooFewArgumentsVec3) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec3(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 3 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) { + auto* tc = vec4( + create(Source{{12, 34}}, ty.vec3(), + ExprList()), + create(Source{{12, 40}}, Literal(1.0f)), + create(Source{{12, 46}}, + Literal(1.0f))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec2) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec3(), ExprList()), + create( + Source{{12, 40}}, ty.vec2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndVec3) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec2(), ExprList()), + create( + Source{{12, 40}}, ty.vec3(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 5 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec3) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec3(), ExprList()), + create( + Source{{12, 40}}, ty.vec3(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec4' with 6 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_InvalidConversionFromVec4Bool) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.vec4(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'bool'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Error_InvalidArgumentType) { + auto* tc = vec4(create( + Source{{12, 34}}, ty.mat2x2(), ExprList())); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: expected vector or scalar type in vector " + "constructor; found: mat2x2"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_ZeroValue) { + auto* tc = vec4(); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4F32_Success_Scalar) { + auto* tc = vec4(1.0f, 1.0f, 1.0f, 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4U32_Success_Scalar) { + auto* tc = vec4(1u, 1u, 1u, 1u); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4I32_Success_Scalar) { + auto* tc = vec4(1, 1, 1, 1); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4Bool_Success_Scalar) { + auto* tc = vec4(true, false, true, false); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_Vec2ScalarScalar) { + auto* tc = vec4(vec2(), 1.0f, 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_ScalarVec2Scalar) { + auto* tc = vec4(1.0f, vec2(), 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_ScalarScalarVec2) { + auto* tc = vec4(1.0f, 1.0f, vec2()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_Vec2AndVec2) { + auto* tc = vec4(vec2(), vec2()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_Vec3AndScalar) { + auto* tc = vec4(vec3(), 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_ScalarAndVec3) { + auto* tc = vec4(1.0f, vec3()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_Identity) { + auto* tc = vec4(vec4()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vec4_Success_Vec4TypeConversion) { + auto* tc = vec4(vec4()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_NestedVectorConstructors_InnerError) { + auto* tc = vec4(vec4(1.0f, 1.0f, + vec3(Expr(Source{{12, 34}}, 1.0f), + Expr(Source{{12, 34}}, 1.0f))), + 1.0f); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ( + r()->error(), + "12:34 error: attempted to construct 'vec3' with 2 component(s)"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_NestedVectorConstructors_Success) { + auto* tc = vec4(vec3(vec2(1.0f, 1.0f), 1.0f), 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); + + ASSERT_NE(TypeOf(tc), nullptr); + ASSERT_TRUE(TypeOf(tc)->Is()); + EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); + EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_Alias_Argument_Error) { + auto* alias = Alias("UnsignedInt", ty.u32()); + Global("uint_var", ty.Of(alias), ast::StorageClass::kPrivate); + + auto* tc = vec2(Expr(Source{{12, 34}}, "uint_var")); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'UnsignedInt'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_Alias_Argument_Success) { + auto* f32_alias = Alias("Float32", ty.f32()); + auto* vec2_alias = Alias("VectorFloat2", ty.vec2()); + Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate); + Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate); + + auto* tc = vec3("my_vec2", "my_f32"); + WrapInFunction(tc); + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_ElementTypeAlias_Error) { + auto* f32_alias = Alias("Float32", ty.f32()); + + // vec2(1.0f, 1u) + auto* vec_type = ty.vec(ty.Of(f32_alias), 2); + auto* tc = create( + Source{{12, 34}}, vec_type, + ExprList(1.0f, create(Source{{12, 40}}, + Literal(1u)))); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:40 error: type in vector constructor does not match vector " + "type: expected 'f32', found 'u32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_ElementTypeAlias_Success) { + auto* f32_alias = Alias("Float32", ty.f32()); + + // vec2(1.0f, 1.0f) + auto* vec_type = ty.vec(ty.Of(f32_alias), 2); + auto* tc = create(Source{{12, 34}}, vec_type, + ExprList(1.0f, 1.0f)); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_ArgumentElementTypeAlias_Error) { + auto* f32_alias = Alias("Float32", ty.f32()); + + // vec3(vec(), 1.0f) + auto* vec_type = ty.vec(ty.Of(f32_alias), 2); + auto* tc = vec3(create( + Source{{12, 34}}, vec_type, ExprList()), + 1.0f); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: type in vector constructor does not match vector " + "type: expected 'u32', found 'f32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_Constructor_Vector_ArgumentElementTypeAlias_Success) { + auto* f32_alias = Alias("Float32", ty.f32()); + + // vec3(vec(), 1.0f) + auto* vec_type = ty.vec(ty.Of(f32_alias), 2); + auto* tc = vec3(create( + Source{{12, 34}}, vec_type, ExprList()), + 1.0f); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +} // namespace VectorConstructor + +namespace MatrixConstructor { +struct MatrixDimensions { + uint32_t rows; + uint32_t columns; +}; + +static std::string MatrixStr(const MatrixDimensions& dimensions, + std::string subtype = "f32") { + return "mat" + std::to_string(dimensions.columns) + "x" + + std::to_string(dimensions.rows) + "<" + subtype + ">"; +} + +static std::string VecStr(uint32_t dimensions, std::string subtype = "f32") { + return "vec" + std::to_string(dimensions) + "<" + subtype + ">"; +} + +using MatrixConstructorTest = ResolverTestWithParam; + +TEST_P(MatrixConstructorTest, Expr_Constructor_Error_TooFewArguments) { + // matNxM(vecM(), ...); with N - 1 arguments + + const auto param = GetParam(); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns - 1; i++) { + auto* vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:1 error: expected " + std::to_string(param.columns) + " '" + + VecStr(param.rows) + "' arguments in '" + MatrixStr(param) + + "' constructor, found " + std::to_string(param.columns - 1)); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_Error_TooManyArguments) { + // matNxM(vecM(), ...); with N + 1 arguments + + const auto param = GetParam(); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns + 1; i++) { + auto* vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:1 error: expected " + std::to_string(param.columns) + " '" + + VecStr(param.rows) + "' arguments in '" + MatrixStr(param) + + "' constructor, found " + std::to_string(param.columns + 1)); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_Error_InvalidArgumentType) { + // matNxM(1.0, 1.0, ...); N arguments + + const auto param = GetParam(); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + args.push_back(create(Source{{12, i}}, + Literal(1.0f))); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + + VecStr(param.rows) + "' in '" + MatrixStr(param) + + "' constructor, found 'f32'"); +} + +TEST_P(MatrixConstructorTest, + Expr_Constructor_Error_TooFewRowsInVectorArgument) { + // matNxM(vecM(),...,vecM-1()); + + const auto param = GetParam(); + + // Skip the test if parameters would have resulted in an invalid vec1 type. + if (param.rows == 2) { + return; + } + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns - 1; i++) { + auto* valid_vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, valid_vec_type, ExprList())); + } + const size_t kInvalidLoc = 2 * (param.columns - 1); + auto* invalid_vec_type = ty.vec(param.rows - 1); + args.push_back(create( + Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList())); + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:" + std::to_string(kInvalidLoc) + + " error: expected argument type '" + + VecStr(param.rows) + "' in '" + MatrixStr(param) + + "' constructor, found '" + + VecStr(param.rows - 1) + "'"); +} + +TEST_P(MatrixConstructorTest, + Expr_Constructor_Error_TooManyRowsInVectorArgument) { + // matNxM(vecM(),...,vecM+1()); + + const auto param = GetParam(); + + // Skip the test if parameters would have resuled in an invalid vec5 type. + if (param.rows == 4) { + return; + } + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns - 1; i++) { + auto* valid_vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, valid_vec_type, ExprList())); + } + const size_t kInvalidLoc = 2 * (param.columns - 1); + auto* invalid_vec_type = ty.vec(param.rows + 1); + args.push_back(create( + Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList())); + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:" + std::to_string(kInvalidLoc) + + " error: expected argument type '" + + VecStr(param.rows) + "' in '" + MatrixStr(param) + + "' constructor, found '" + + VecStr(param.rows + 1) + "'"); +} + +TEST_P(MatrixConstructorTest, + Expr_Constructor_Error_ArgumentVectorElementTypeMismatch) { + // matNxM(vecM(), ...); with N arguments + + const auto param = GetParam(); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + + VecStr(param.rows) + "' in '" + MatrixStr(param) + + "' constructor, found '" + + VecStr(param.rows, "u32") + "'"); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_ZeroValue_Success) { + // matNxM(); + + const auto param = GetParam(); + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{{12, 40}}, + matrix_type, ExprList()); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_WithArguments_Success) { + // matNxM(vecM(), ...); with N arguments + + const auto param = GetParam(); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) { + // matNxM(vecM(), ...); with N arguments + + const auto param = GetParam(); + auto* f32_alias = Alias("Float32", ty.f32()); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(ty.u32(), param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:1 error: expected argument type '" + VecStr(param.rows) + + "' in '" + MatrixStr(param, "Float32") + + "' constructor, found '" + VecStr(param.rows, "u32") + "'"); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) { + // matNxM(vecM(), ...); with N arguments + + const auto param = GetParam(); + auto* f32_alias = Alias("Float32", ty.f32()); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverTypeConstructorValidationTest, + Expr_MatrixConstructor_ArgumentTypeAlias_Error) { + auto* alias = Alias("VectorUnsigned2", ty.vec2()); + auto* tc = mat2x2(create( + Source{{12, 34}}, ty.Of(alias), ExprList()), + vec2()); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: expected argument type 'vec2' in 'mat2x2' " + "constructor, found 'VectorUnsigned2'"); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentTypeAlias_Success) { + const auto param = GetParam(); + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* vec_type = ty.vec(param.rows); + auto* vec_alias = Alias("VectorFloat2", vec_type); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + args.push_back(create( + Source{{12, i}}, ty.Of(vec_alias), ExprList())); + } + + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Error) { + const auto param = GetParam(); + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* f32_alias = Alias("UnsignedInt", ty.u32()); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + + VecStr(param.rows) + "' in '" + MatrixStr(param) + + "' constructor, found '" + + VecStr(param.rows, "UnsignedInt") + "'"); +} + +TEST_P(MatrixConstructorTest, + Expr_Constructor_ArgumentElementTypeAlias_Success) { + const auto param = GetParam(); + auto* f32_alias = Alias("Float32", ty.f32()); + + ast::ExpressionList args; + for (uint32_t i = 1; i <= param.columns; i++) { + auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows); + args.push_back(create( + Source{{12, i}}, vec_type, ExprList())); + } + + auto* matrix_type = ty.mat(param.columns, param.rows); + auto* tc = create(Source{}, matrix_type, + std::move(args)); + WrapInFunction(tc); + + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest, + MatrixConstructorTest, + testing::Values(MatrixDimensions{2, 2}, + MatrixDimensions{3, 2}, + MatrixDimensions{4, 2}, + MatrixDimensions{2, 3}, + MatrixDimensions{3, 3}, + MatrixDimensions{4, 3}, + MatrixDimensions{2, 4}, + MatrixDimensions{3, 4}, + MatrixDimensions{4, 4})); +} // namespace MatrixConstructor + +namespace StructConstructor { +using builder::CreatePtrs; +using builder::CreatePtrsFor; +using builder::f32; +using builder::i32; +using builder::mat2x2; +using builder::mat3x3; +using builder::mat4x4; +using builder::u32; +using builder::vec2; +using builder::vec3; +using builder::vec4; + +constexpr CreatePtrs all_types[] = { + CreatePtrsFor(), // + CreatePtrsFor(), // + CreatePtrsFor(), // + CreatePtrsFor(), // + CreatePtrsFor>(), // + CreatePtrsFor>(), // + CreatePtrsFor>(), // + CreatePtrsFor>(), // + CreatePtrsFor>(), // + CreatePtrsFor>(), // + CreatePtrsFor>() // +}; + +auto number_of_members = testing::Values(2u, 32u, 64u); + +using StructConstructorInputsTest = + ResolverTestWithParam>; // number of struct members +TEST_P(StructConstructorInputsTest, TooFew) { + auto& param = GetParam(); + auto& str_params = std::get<0>(param); + uint32_t N = std::get<1>(param); + + ast::StructMemberList members; + ast::ExpressionList values; + for (uint32_t i = 0; i < N; i++) { + auto* struct_type = str_params.ast(*this); + members.push_back(Member("member_" + std::to_string(i), struct_type)); + if (i < N - 1) { + auto* ctor_value_expr = str_params.expr(*this, 0); + values.push_back(ctor_value_expr); + } + } + auto* s = Structure("s", members); + auto* tc = create(Source{{12, 34}}, ty.Of(s), + values); + WrapInFunction(tc); + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: struct constructor has too few inputs: expected " + + std::to_string(N) + ", found " + std::to_string(N - 1)); +} + +TEST_P(StructConstructorInputsTest, TooMany) { + auto& param = GetParam(); + auto& str_params = std::get<0>(param); + uint32_t N = std::get<1>(param); + + ast::StructMemberList members; + ast::ExpressionList values; + for (uint32_t i = 0; i < N + 1; i++) { + if (i < N) { + auto* struct_type = str_params.ast(*this); + members.push_back(Member("member_" + std::to_string(i), struct_type)); + } + auto* ctor_value_expr = str_params.expr(*this, 0); + values.push_back(ctor_value_expr); + } + auto* s = Structure("s", members); + auto* tc = create(Source{{12, 34}}, ty.Of(s), + values); + WrapInFunction(tc); + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error: struct constructor has too many inputs: expected " + + std::to_string(N) + ", found " + std::to_string(N + 1)); +} + +INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest, + StructConstructorInputsTest, + testing::Combine(testing::ValuesIn(all_types), + number_of_members)); +using StructConstructorTypeTest = + ResolverTestWithParam>; // number of struct members +TEST_P(StructConstructorTypeTest, AllTypes) { + auto& param = GetParam(); + auto& str_params = std::get<0>(param); + auto& ctor_params = std::get<1>(param); + uint32_t N = std::get<2>(param); + + if (str_params.ast == ctor_params.ast) { + return; + } + + ast::StructMemberList members; + ast::ExpressionList values; + // make the last value of the constructor to have a different type + uint32_t constructor_value_with_different_type = N - 1; + for (uint32_t i = 0; i < N; i++) { + auto* struct_type = str_params.ast(*this); + members.push_back(Member("member_" + std::to_string(i), struct_type)); + auto* ctor_value_expr = (i == constructor_value_with_different_type) + ? ctor_params.expr(*this, 0) + : str_params.expr(*this, 0); + values.push_back(ctor_value_expr); + } + auto* s = Structure("s", members); + auto* tc = create(ty.Of(s), values); + WrapInFunction(tc); + + std::string found = FriendlyName(ctor_params.ast(*this)); + std::string expected = FriendlyName(str_params.ast(*this)); + std::stringstream err; + err << "error: type in struct constructor does not match struct member "; + err << "type: expected '" << expected << "', found '" << found << "'"; + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), err.str()); +} + +INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest, + StructConstructorTypeTest, + testing::Combine(testing::ValuesIn(all_types), + testing::ValuesIn(all_types), + number_of_members)); + +TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct_Nested) { + auto* inner_m = Member("m", ty.i32()); + auto* inner_s = Structure("inner_s", {inner_m}); + + auto* m0 = Member("m", ty.i32()); + auto* m1 = Member("m", ty.Of(inner_s)); + auto* m2 = Member("m", ty.i32()); + auto* s = Structure("s", {m0, m1, m2}); + + auto* tc = create(Source{{12, 34}}, ty.Of(s), + ExprList(1, 1, 1)); + WrapInFunction(tc); + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "error: type in struct constructor does not match struct member " + "type: expected 'inner_s', found 'i32'"); +} + +TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct) { + auto* m = Member("m", ty.i32()); + auto* s = Structure("MyInputs", {m}); + auto* tc = create(Source{{12, 34}}, ty.Of(s), + ExprList()); + WrapInFunction(tc); + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct_Empty) { + auto* str = Structure("S", { + Member("a", ty.i32()), + Member("b", ty.f32()), + Member("c", ty.vec3()), + }); + + WrapInFunction(Construct(ty.Of(str))); + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} +} // namespace StructConstructor + } // namespace } // namespace resolver } // namespace tint diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc index eaa2d2b793..573629abd2 100644 --- a/src/resolver/validation_test.cc +++ b/src/resolver/validation_test.cc @@ -772,1739 +772,6 @@ TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) { EXPECT_EQ(r()->error(), "12:34 error: cannot cast to a pointer"); } -TEST_F(ResolverValidationTest, Expr_Constructor_Array_ZeroValue_Pass) { - // array(); - auto* tc = array(); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_type_match) { - // array(0u, 10u. 20u); - auto* tc = - array(create(Literal(0u)), - create(Literal(10u)), - create(Literal(20u))); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_type_Mismatch_U32F32) { - // array(0u, 1.0f, 20u); - auto* tc = array( - create(Literal(0u)), - create(Source{{12, 34}}, Literal(1.0f)), - create(Literal(20u))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'u32', found 'f32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Array_ScalarArgumentTypeMismatch_F32I32) { - // array(1); - auto* tc = array( - create(Source{{12, 34}}, Literal(1))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'f32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Array_ScalarArgumentTypeMismatch_U32I32) { - // array(1, 0u, 0u, 0u, 0u, 0u); - auto* tc = array( - create(Source{{12, 34}}, Literal(1)), - create(Literal(0u)), - create(Literal(0u)), - create(Literal(0u)), - create(Literal(0u))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'u32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) { - // array(1, vec2()); - auto* tc = array(create(Literal(1)), - create( - Source{{12, 34}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'i32', found 'vec2'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32U32) { - // array, 2>(vec3(), vec3()); - auto* e0 = vec3(); - SetSource(Source::Location({12, 34})); - auto* e1 = vec3(); - auto* t = Construct(ty.array(ty.vec3(), 2), e0, e1); - WrapInFunction(t); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'vec3', found 'vec3'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32Bool) { - // array, 2>(vec3(), vec3(true, true, false)); - SetSource(Source::Location({12, 34})); - auto* e0 = vec3(true, true, false); - auto* e1 = vec3(); - auto* t = Construct(ty.array(ty.vec3(), 2), e0, e1); - WrapInFunction(t); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'vec3', found 'vec3'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_ArrayOfArray_SubElemSizeMismatch) { - // array, 2>(array(), array()); - SetSource(Source::Location({12, 34})); - auto* e0 = array(); - auto* e1 = array(); - auto* t = Construct(ty.array(ty.array(), 2), e0, e1); - WrapInFunction(t); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'array', found 'array'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_ArrayOfArray_SubElemTypeMismatch) { - // array, 2>(array(), array()); - auto* e0 = array(); - SetSource(Source::Location({12, 34})); - auto* e1 = array(); - auto* t = Construct(ty.array(ty.array(), 2), e0, e1); - WrapInFunction(t); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in array constructor does not match array type: " - "expected 'array', found 'array'"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_TooFewElements) { - // array(1, 2, 3); - SetSource(Source::Location({12, 34})); - auto* tc = - array(create(Literal(1)), - create(Literal(2)), - create(Literal(3))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: array constructor has too few elements: expected 4, " - "found 3"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_TooManyElements) { - // array(1, 2, 3, 4, 5); - SetSource(Source::Location({12, 34})); - auto* tc = - array(create(Literal(1)), - create(Literal(2)), - create(Literal(3)), - create(Literal(4)), - create(Literal(5))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: array constructor has too many " - "elements: expected 4, " - "found 5"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_Runtime) { - // array(1); - auto* tc = array( - create(Source{{12, 34}}, Literal(1))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Array_RuntimeZeroValue) { - // array(); - auto* tc = array(); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2F32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec2( - create(Source{{12, 34}}, Literal(1)), - 1.0f); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2U32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec2(1u, create( - Source{{12, 34}}, Literal(1))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'u32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2I32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec2( - create(Source{{12, 34}}, Literal(1u)), - 1); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'i32', found 'u32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2Bool_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec2(true, create( - Source{{12, 34}}, Literal(1))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'bool', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_Vec3ArgumentCardinalityTooLarge) { - auto* tc = vec2(create( - Source{{12, 34}}, ty.vec3(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec2' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_Vec4ArgumentCardinalityTooLarge) { - auto* tc = vec2(create( - Source{{12, 34}}, ty.vec4(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec2' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_TooManyArgumentsScalar) { - auto* tc = vec2( - create(Source{{12, 34}}, Literal(1.0f)), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec2' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_TooManyArgumentsVector) { - auto* tc = vec2(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec2' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) { - auto* tc = vec2(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec2' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_InvalidConversionFromVec2Bool) { - SetSource(Source::Location({12, 34})); - - auto* tc = vec2(create( - Source{{12, 34}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'bool'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Error_InvalidArgumentType) { - auto* tc = vec2(create( - Source{{12, 34}}, ty.mat2x2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: expected vector or scalar type in vector " - "constructor; found: mat2x2"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2_Success_ZeroValue) { - auto* tc = vec2(); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2F32_Success_Scalar) { - auto* tc = vec2(1.0f, 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2U32_Success_Scalar) { - auto* tc = vec2(1u, 1u); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2I32_Success_Scalar) { - auto* tc = vec2(1, 1); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2Bool_Success_Scalar) { - auto* tc = vec2(true, false); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec2_Success_Identity) { - auto* tc = vec2(vec2()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec2_Success_Vec2TypeConversion) { - auto* tc = vec2(vec2()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 2u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3F32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec3( - 1.0f, 1.0f, - create(Source{{12, 34}}, Literal(1))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3U32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec3( - 1u, - create(Source{{12, 34}}, Literal(1)), - 1u); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'u32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3I32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec3( - 1, - create(Source{{12, 34}}, Literal(1u)), - 1); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'i32', found 'u32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3Bool_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec3( - true, - create(Source{{12, 34}}, Literal(1)), - false); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'bool', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_Vec4ArgumentCardinalityTooLarge) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.vec4(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooFewArgumentsScalar) { - auto* tc = vec3( - create(Source{{12, 34}}, Literal(1.0f)), - create(Source{{12, 40}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 2 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooManyArgumentsScalar) { - auto* tc = vec3( - create(Source{{12, 34}}, Literal(1.0f)), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, Literal(1.0f)), - create(Source{{12, 52}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooFewArgumentsVec2) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 2 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooManyArgumentsVec2) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) { - auto* tc = vec3( - create(Source{{12, 34}}, ty.vec2(), - ExprList()), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.vec3(), ExprList()), - create( - Source{{12, 40}}, Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 4 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_InvalidConversionFromVec3Bool) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.vec3(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'bool'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Error_InvalidArgumentType) { - auto* tc = vec3(create( - Source{{12, 34}}, ty.mat2x2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: expected vector or scalar type in vector " - "constructor; found: mat2x2"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3_Success_ZeroValue) { - auto* tc = vec3(); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3F32_Success_Scalar) { - auto* tc = vec3(1.0f, 1.0f, 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3U32_Success_Scalar) { - auto* tc = vec3(1u, 1u, 1u); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3I32_Success_Scalar) { - auto* tc = vec3(1, 1, 1); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3Bool_Success_Scalar) { - auto* tc = vec3(true, false, true); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3_Success_Vec2AndScalar) { - auto* tc = vec3(vec2(), 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3_Success_ScalarAndVec2) { - auto* tc = vec3(1.0f, vec2()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec3_Success_Identity) { - auto* tc = vec3(vec3()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec3_Success_Vec3TypeConversion) { - auto* tc = vec3(vec3()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 3u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4F32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec4( - 1.0f, 1.0f, - create(Source{{12, 34}}, Literal(1)), - 1.0f); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4U32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec4( - 1u, 1u, - create(Source{{12, 34}}, Literal(1)), - 1u); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'u32', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4I32_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec4( - 1, 1, - create(Source{{12, 34}}, Literal(1u)), - 1); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'i32', found 'u32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4Bool_Error_ScalarArgumentTypeMismatch) { - auto* tc = vec4( - true, false, - create(Source{{12, 34}}, Literal(1)), - true); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'bool', found 'i32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooFewArgumentsScalar) { - auto* tc = vec4( - create(Source{{12, 34}}, Literal(1.0f)), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsScalar) { - auto* tc = vec4( - create(Source{{12, 34}}, Literal(1.0f)), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, Literal(1.0f)), - create(Source{{12, 52}}, Literal(1.0f)), - create(Source{{12, 58}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) { - auto* tc = vec4( - create(Source{{12, 34}}, ty.vec2(), - ExprList()), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, Literal(1.0f)), - create(Source{{12, 52}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Scalar) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList()), - create( - Source{{12, 46}}, Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Vec2) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 6 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooFewArgumentsVec3) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec3(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 3 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) { - auto* tc = vec4( - create(Source{{12, 34}}, ty.vec3(), - ExprList()), - create(Source{{12, 40}}, Literal(1.0f)), - create(Source{{12, 46}}, - Literal(1.0f))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec2) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec3(), ExprList()), - create( - Source{{12, 40}}, ty.vec2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndVec3) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec2(), ExprList()), - create( - Source{{12, 40}}, ty.vec3(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 5 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec3) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec3(), ExprList()), - create( - Source{{12, 40}}, ty.vec3(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec4' with 6 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_InvalidConversionFromVec4Bool) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.vec4(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'bool'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Error_InvalidArgumentType) { - auto* tc = vec4(create( - Source{{12, 34}}, ty.mat2x2(), ExprList())); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: expected vector or scalar type in vector " - "constructor; found: mat2x2"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_ZeroValue) { - auto* tc = vec4(); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4F32_Success_Scalar) { - auto* tc = vec4(1.0f, 1.0f, 1.0f, 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4U32_Success_Scalar) { - auto* tc = vec4(1u, 1u, 1u, 1u); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4I32_Success_Scalar) { - auto* tc = vec4(1, 1, 1, 1); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4Bool_Success_Scalar) { - auto* tc = vec4(true, false, true, false); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_Vec2ScalarScalar) { - auto* tc = vec4(vec2(), 1.0f, 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_ScalarVec2Scalar) { - auto* tc = vec4(1.0f, vec2(), 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_ScalarScalarVec2) { - auto* tc = vec4(1.0f, 1.0f, vec2()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_Vec2AndVec2) { - auto* tc = vec4(vec2(), vec2()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_Vec3AndScalar) { - auto* tc = vec4(vec3(), 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_ScalarAndVec3) { - auto* tc = vec4(1.0f, vec3()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vec4_Success_Identity) { - auto* tc = vec4(vec4()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vec4_Success_Vec4TypeConversion) { - auto* tc = vec4(vec4()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_NestedVectorConstructors_InnerError) { - auto* tc = vec4(vec4(1.0f, 1.0f, - vec3(Expr(Source{{12, 34}}, 1.0f), - Expr(Source{{12, 34}}, 1.0f))), - 1.0f); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ( - r()->error(), - "12:34 error: attempted to construct 'vec3' with 2 component(s)"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_NestedVectorConstructors_Success) { - auto* tc = vec4(vec3(vec2(1.0f, 1.0f), 1.0f), 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); - - ASSERT_NE(TypeOf(tc), nullptr); - ASSERT_TRUE(TypeOf(tc)->Is()); - EXPECT_TRUE(TypeOf(tc)->As()->type()->Is()); - EXPECT_EQ(TypeOf(tc)->As()->size(), 4u); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) { - auto* alias = Alias("UnsignedInt", ty.u32()); - Global("uint_var", ty.Of(alias), ast::StorageClass::kPrivate); - - auto* tc = vec2(Expr(Source{{12, 34}}, "uint_var")); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'UnsignedInt'"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) { - auto* f32_alias = Alias("Float32", ty.f32()); - auto* vec2_alias = Alias("VectorFloat2", ty.vec2()); - Global("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate); - Global("my_vec2", ty.Of(vec2_alias), ast::StorageClass::kPrivate); - - auto* tc = vec3("my_vec2", "my_f32"); - WrapInFunction(tc); - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Vector_ElementTypeAlias_Error) { - auto* f32_alias = Alias("Float32", ty.f32()); - - // vec2(1.0f, 1u) - auto* vec_type = ty.vec(ty.Of(f32_alias), 2); - auto* tc = create( - Source{{12, 34}}, vec_type, - ExprList(1.0f, create(Source{{12, 40}}, - Literal(1u)))); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:40 error: type in vector constructor does not match vector " - "type: expected 'f32', found 'u32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vector_ElementTypeAlias_Success) { - auto* f32_alias = Alias("Float32", ty.f32()); - - // vec2(1.0f, 1.0f) - auto* vec_type = ty.vec(ty.Of(f32_alias), 2); - auto* tc = create(Source{{12, 34}}, vec_type, - ExprList(1.0f, 1.0f)); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vector_ArgumentElementTypeAlias_Error) { - auto* f32_alias = Alias("Float32", ty.f32()); - - // vec3(vec(), 1.0f) - auto* vec_type = ty.vec(ty.Of(f32_alias), 2); - auto* tc = vec3(create( - Source{{12, 34}}, vec_type, ExprList()), - 1.0f); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: type in vector constructor does not match vector " - "type: expected 'u32', found 'f32'"); -} - -TEST_F(ResolverValidationTest, - Expr_Constructor_Vector_ArgumentElementTypeAlias_Success) { - auto* f32_alias = Alias("Float32", ty.f32()); - - // vec3(vec(), 1.0f) - auto* vec_type = ty.vec(ty.Of(f32_alias), 2); - auto* tc = vec3(create( - Source{{12, 34}}, vec_type, ExprList()), - 1.0f); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -struct MatrixDimensions { - uint32_t rows; - uint32_t columns; -}; - -std::string MatrixStr(const MatrixDimensions& dimensions, - std::string subtype = "f32") { - return "mat" + std::to_string(dimensions.columns) + "x" + - std::to_string(dimensions.rows) + "<" + subtype + ">"; -} - -std::string VecStr(uint32_t dimensions, std::string subtype = "f32") { - return "vec" + std::to_string(dimensions) + "<" + subtype + ">"; -} - -using MatrixConstructorTest = ResolverTestWithParam; - -TEST_P(MatrixConstructorTest, Expr_Constructor_Error_TooFewArguments) { - // matNxM(vecM(), ...); with N - 1 arguments - - const auto param = GetParam(); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns - 1; i++) { - auto* vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:1 error: expected " + std::to_string(param.columns) + " '" + - VecStr(param.rows) + "' arguments in '" + MatrixStr(param) + - "' constructor, found " + std::to_string(param.columns - 1)); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_Error_TooManyArguments) { - // matNxM(vecM(), ...); with N + 1 arguments - - const auto param = GetParam(); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns + 1; i++) { - auto* vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:1 error: expected " + std::to_string(param.columns) + " '" + - VecStr(param.rows) + "' arguments in '" + MatrixStr(param) + - "' constructor, found " + std::to_string(param.columns + 1)); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_Error_InvalidArgumentType) { - // matNxM(1.0, 1.0, ...); N arguments - - const auto param = GetParam(); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - args.push_back(create(Source{{12, i}}, - Literal(1.0f))); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + - VecStr(param.rows) + "' in '" + MatrixStr(param) + - "' constructor, found 'f32'"); -} - -TEST_P(MatrixConstructorTest, - Expr_Constructor_Error_TooFewRowsInVectorArgument) { - // matNxM(vecM(),...,vecM-1()); - - const auto param = GetParam(); - - // Skip the test if parameters would have resulted in an invalid vec1 type. - if (param.rows == 2) { - return; - } - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns - 1; i++) { - auto* valid_vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, valid_vec_type, ExprList())); - } - const size_t kInvalidLoc = 2 * (param.columns - 1); - auto* invalid_vec_type = ty.vec(param.rows - 1); - args.push_back(create( - Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList())); - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:" + std::to_string(kInvalidLoc) + - " error: expected argument type '" + - VecStr(param.rows) + "' in '" + MatrixStr(param) + - "' constructor, found '" + - VecStr(param.rows - 1) + "'"); -} - -TEST_P(MatrixConstructorTest, - Expr_Constructor_Error_TooManyRowsInVectorArgument) { - // matNxM(vecM(),...,vecM+1()); - - const auto param = GetParam(); - - // Skip the test if parameters would have resuled in an invalid vec5 type. - if (param.rows == 4) { - return; - } - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns - 1; i++) { - auto* valid_vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, valid_vec_type, ExprList())); - } - const size_t kInvalidLoc = 2 * (param.columns - 1); - auto* invalid_vec_type = ty.vec(param.rows + 1); - args.push_back(create( - Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList())); - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:" + std::to_string(kInvalidLoc) + - " error: expected argument type '" + - VecStr(param.rows) + "' in '" + MatrixStr(param) + - "' constructor, found '" + - VecStr(param.rows + 1) + "'"); -} - -TEST_P(MatrixConstructorTest, - Expr_Constructor_Error_ArgumentVectorElementTypeMismatch) { - // matNxM(vecM(), ...); with N arguments - - const auto param = GetParam(); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + - VecStr(param.rows) + "' in '" + MatrixStr(param) + - "' constructor, found '" + - VecStr(param.rows, "u32") + "'"); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_ZeroValue_Success) { - // matNxM(); - - const auto param = GetParam(); - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{{12, 40}}, - matrix_type, ExprList()); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_WithArguments_Success) { - // matNxM(vecM(), ...); with N arguments - - const auto param = GetParam(); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) { - // matNxM(vecM(), ...); with N arguments - - const auto param = GetParam(); - auto* f32_alias = Alias("Float32", ty.f32()); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(ty.u32(), param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:1 error: expected argument type '" + VecStr(param.rows) + - "' in '" + MatrixStr(param, "Float32") + - "' constructor, found '" + VecStr(param.rows, "u32") + "'"); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) { - // matNxM(vecM(), ...); with N arguments - - const auto param = GetParam(); - auto* f32_alias = Alias("Float32", ty.f32()); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_F(ResolverValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) { - auto* alias = Alias("VectorUnsigned2", ty.vec2()); - auto* tc = mat2x2(create( - Source{{12, 34}}, ty.Of(alias), ExprList()), - vec2()); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: expected argument type 'vec2' in 'mat2x2' " - "constructor, found 'VectorUnsigned2'"); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentTypeAlias_Success) { - const auto param = GetParam(); - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* vec_type = ty.vec(param.rows); - auto* vec_alias = Alias("VectorFloat2", vec_type); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - args.push_back(create( - Source{{12, i}}, ty.Of(vec_alias), ExprList())); - } - - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Error) { - const auto param = GetParam(); - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* f32_alias = Alias("UnsignedInt", ty.u32()); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:1 error: expected argument type '" + - VecStr(param.rows) + "' in '" + MatrixStr(param) + - "' constructor, found '" + - VecStr(param.rows, "UnsignedInt") + "'"); -} - -TEST_P(MatrixConstructorTest, - Expr_Constructor_ArgumentElementTypeAlias_Success) { - const auto param = GetParam(); - auto* f32_alias = Alias("Float32", ty.f32()); - - ast::ExpressionList args; - for (uint32_t i = 1; i <= param.columns; i++) { - auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows); - args.push_back(create( - Source{{12, i}}, vec_type, ExprList())); - } - - auto* matrix_type = ty.mat(param.columns, param.rows); - auto* tc = create(Source{}, matrix_type, - std::move(args)); - WrapInFunction(tc); - - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -INSTANTIATE_TEST_SUITE_P(ResolverValidationTest, - MatrixConstructorTest, - testing::Values(MatrixDimensions{2, 2}, - MatrixDimensions{3, 2}, - MatrixDimensions{4, 2}, - MatrixDimensions{2, 3}, - MatrixDimensions{3, 3}, - MatrixDimensions{4, 3}, - MatrixDimensions{2, 4}, - MatrixDimensions{3, 4}, - MatrixDimensions{4, 4})); - -namespace StructConstructor { -using builder::CreatePtrs; -using builder::CreatePtrsFor; -using builder::f32; -using builder::i32; -using builder::mat2x2; -using builder::mat3x3; -using builder::mat4x4; -using builder::u32; -using builder::vec2; -using builder::vec3; -using builder::vec4; - -constexpr CreatePtrs all_types[] = { - CreatePtrsFor(), // - CreatePtrsFor(), // - CreatePtrsFor(), // - CreatePtrsFor(), // - CreatePtrsFor>(), // - CreatePtrsFor>(), // - CreatePtrsFor>(), // - CreatePtrsFor>(), // - CreatePtrsFor>(), // - CreatePtrsFor>(), // - CreatePtrsFor>() // -}; - -auto number_of_members = testing::Values(2u, 32u, 64u); - -using StructConstructorInputsTest = - ResolverTestWithParam>; // number of struct members -TEST_P(StructConstructorInputsTest, TooFew) { - auto& param = GetParam(); - auto& str_params = std::get<0>(param); - uint32_t N = std::get<1>(param); - - ast::StructMemberList members; - ast::ExpressionList values; - for (uint32_t i = 0; i < N; i++) { - auto* struct_type = str_params.ast(*this); - members.push_back(Member("member_" + std::to_string(i), struct_type)); - if (i < N - 1) { - auto* ctor_value_expr = str_params.expr(*this, 0); - values.push_back(ctor_value_expr); - } - } - auto* s = Structure("s", members); - auto* tc = create(Source{{12, 34}}, ty.Of(s), - values); - WrapInFunction(tc); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: struct constructor has too few inputs: expected " + - std::to_string(N) + ", found " + std::to_string(N - 1)); -} - -TEST_P(StructConstructorInputsTest, TooMany) { - auto& param = GetParam(); - auto& str_params = std::get<0>(param); - uint32_t N = std::get<1>(param); - - ast::StructMemberList members; - ast::ExpressionList values; - for (uint32_t i = 0; i < N + 1; i++) { - if (i < N) { - auto* struct_type = str_params.ast(*this); - members.push_back(Member("member_" + std::to_string(i), struct_type)); - } - auto* ctor_value_expr = str_params.expr(*this, 0); - values.push_back(ctor_value_expr); - } - auto* s = Structure("s", members); - auto* tc = create(Source{{12, 34}}, ty.Of(s), - values); - WrapInFunction(tc); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "12:34 error: struct constructor has too many inputs: expected " + - std::to_string(N) + ", found " + std::to_string(N + 1)); -} - -INSTANTIATE_TEST_SUITE_P(ResolverValidationTest, - StructConstructorInputsTest, - testing::Combine(testing::ValuesIn(all_types), - number_of_members)); -using StructConstructorTypeTest = - ResolverTestWithParam>; // number of struct members -TEST_P(StructConstructorTypeTest, AllTypes) { - auto& param = GetParam(); - auto& str_params = std::get<0>(param); - auto& ctor_params = std::get<1>(param); - uint32_t N = std::get<2>(param); - - if (str_params.ast == ctor_params.ast) { - return; - } - - ast::StructMemberList members; - ast::ExpressionList values; - // make the last value of the constructor to have a different type - uint32_t constructor_value_with_different_type = N - 1; - for (uint32_t i = 0; i < N; i++) { - auto* struct_type = str_params.ast(*this); - members.push_back(Member("member_" + std::to_string(i), struct_type)); - auto* ctor_value_expr = (i == constructor_value_with_different_type) - ? ctor_params.expr(*this, 0) - : str_params.expr(*this, 0); - values.push_back(ctor_value_expr); - } - auto* s = Structure("s", members); - auto* tc = create(ty.Of(s), values); - WrapInFunction(tc); - - std::string found = FriendlyName(ctor_params.ast(*this)); - std::string expected = FriendlyName(str_params.ast(*this)); - std::stringstream err; - err << "error: type in struct constructor does not match struct member "; - err << "type: expected '" << expected << "', found '" << found << "'"; - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), err.str()); -} - -INSTANTIATE_TEST_SUITE_P(ResolverValidationTest, - StructConstructorTypeTest, - testing::Combine(testing::ValuesIn(all_types), - testing::ValuesIn(all_types), - number_of_members)); - -TEST_F(ResolverValidationTest, Expr_Constructor_Struct_Nested) { - auto* inner_m = Member("m", ty.i32()); - auto* inner_s = Structure("inner_s", {inner_m}); - - auto* m0 = Member("m", ty.i32()); - auto* m1 = Member("m", ty.Of(inner_s)); - auto* m2 = Member("m", ty.i32()); - auto* s = Structure("s", {m0, m1, m2}); - - auto* tc = create(Source{{12, 34}}, ty.Of(s), - ExprList(1, 1, 1)); - WrapInFunction(tc); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - "error: type in struct constructor does not match struct member " - "type: expected 'inner_s', found 'i32'"); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Struct) { - auto* m = Member("m", ty.i32()); - auto* s = Structure("MyInputs", {m}); - auto* tc = create(Source{{12, 34}}, ty.Of(s), - ExprList()); - WrapInFunction(tc); - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} - -TEST_F(ResolverValidationTest, Expr_Constructor_Struct_Empty) { - auto* str = Structure("S", { - Member("a", ty.i32()), - Member("b", ty.f32()), - Member("c", ty.vec3()), - }); - - WrapInFunction(Construct(ty.Of(str))); - EXPECT_TRUE(r()->Resolve()) << r()->error(); -} -} // namespace StructConstructor - } // namespace } // namespace resolver } // namespace tint