* Copyright (c) 2024-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "lowering_test.h"
#include "compiler/lowering/ets/constantExpressionLowering.h"
namespace ark::es2panda {
template <typename T, T EXPECT_VAL>
static bool CheckNumberLiteral(const ir::AstNode *node)
{
if (node->IsNumberLiteral()) {
auto numNode = node->AsNumberLiteral()->Number();
if (numNode.CanGetValue<T>()) {
return numNode.GetValue<T>() == EXPECT_VAL;
}
}
return false;
}
TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean1)
{
char const *text = R"(
@interface MyAnno {
c : int
d : int
}
@MyAnno({c = "a" ? 5 : 4, d = 12 ? 7 : 6})
function main() {}
)";
int const expectC = 5;
int const expectD = 7;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectC>(node); }));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectD>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean2)
{
char const *text = R"(
@interface MyAnno {
c : int
d : int
}
@MyAnno({c = "" ? 5 : 4, d = 0 ? 7 : 6})
function main() {}
)";
int const expectC = 4;
int const expectD = 6;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectC>(node); }));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectD>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean4)
{
char const *text = R"(
@interface MyAnno {
a : boolean
b : int = "aaa" ? 1 : 2
}
@MyAnno({a = ((("aa" >= "aa") && ("ab" < "aa")) || ("aa" != "bb")) && "aa!" == "aa!"})
function main() {}
)";
bool const expectA = true;
int const expectB = 1;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBooleanLiteral() && node->AsBooleanLiteral()->Value() == expectA;
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectB>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean3)
{
char const *text = R"(
@interface MyAnno {
a : int
b : int
}
@MyAnno({a = !0 ? 10 : 20, b= "test" ? 1 : 2})
function main() {}
)";
int const expectA = 10;
int const expectB = 1;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectA>(node); }));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectB>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcat)
{
char const *text = R"(
@interface MyAnno {
a : int
b : long
c : boolean
d : int
}
@MyAnno({a = 1 + -1, b = 1554.4 ^ 10, c = 12 >= 10, d = 15 != 10 ? 1+4 : 5+1})
function main() {}
)";
int const expectA = 0;
int64_t const expectB = 1560;
bool const expectC = true;
int const expectD = 5;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectA>(node); }));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int64_t, expectB>(node); }));
ASSERT_TRUE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBooleanLiteral() && node->AsBooleanLiteral()->Value() == expectC;
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectD>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatNumeric1)
{
char const *text = R"(
@interface MyAnno {
a : int = 1+1
}
@MyAnno()
function main() {}
)";
int32_t const expectA = 2;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int32_t, expectA>(node); }));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatBoolean)
{
char const *text = R"(
@interface MyAnno {
a : boolean
}
@MyAnno({a = ((20<=10) || true) ? !false && (10==10) && (30 != 10): false})
function main() {}
)";
bool const expectA = true;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBooleanLiteral() && node->AsBooleanLiteral()->Value() == expectA;
}));
}
}
TEST_F(LoweringTest, TestConstantExpressionConcatNumeric)
{
char const *text = R"(
@interface MyAnno {
a : long
}
@MyAnno({a = ((((1 + -1 + 10) * 123 / 5) ^ (~10.2) << 1) >> 2.6 >>> 33 & 141 | 12) % 53})
function main() {}
)";
int64_t const expectA = 35;
CONTEXT(ES2PANDA_STATE_CHECKED, text)
{
const auto *const ast = GetAst();
ASSERT_FALSE(ast->IsAnyChild([](ir::AstNode *const node) {
return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression();
}));
ASSERT_TRUE(
ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral<int64_t, expectA>(node); }));
}
}
}