1/**
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "constStringToCharLowering.h"
17
18#include "checker/ETSchecker.h"
19
20namespace ark::es2panda::compiler {
21
22std::string_view ConstStringToCharLowering::Name() const
23{
24    return "ConstStringToCharLowering";
25}
26
27ir::AstNode *TryConvertToCharLiteral(checker::ETSChecker *checker, ir::AstNode *ast)
28{
29    if (!ast->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOX_TO_CHAR) || !ast->IsExpression() ||
30        ast->AsExpression()->TsType() == nullptr || !ast->AsExpression()->TsType()->IsETSStringType()) {
31        return nullptr;
32    }
33
34    auto type = ast->AsExpression()->TsType()->AsETSStringType();
35    if (!type->IsConstantType() || !type->GetValue().IsConvertibleToChar()) {
36        return nullptr;
37    }
38
39    auto parent = ast->Parent();
40    util::StringView::Iterator it(type->GetValue());
41    auto value = static_cast<char16_t>(it.PeekCp());
42
43    auto newValue = checker->Allocator()->New<ir::CharLiteral>(value);
44    newValue->SetParent(parent);
45    newValue->SetRange(ast->Range());
46    if (parent->IsCallExpression() && parent->AsCallExpression()->Callee()->IsArrowFunctionExpression()) {
47        newValue->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_CHAR);
48    }
49
50    newValue->Check(checker);
51    return newValue;
52}
53
54bool ConstStringToCharLowering::Perform(public_lib::Context *const ctx, parser::Program *const program)
55{
56    for (const auto &[_, ext_programs] : program->ExternalSources()) {
57        (void)_;
58        for (auto *const extProg : ext_programs) {
59            Perform(ctx, extProg);
60        }
61    }
62
63    auto *const checker = ctx->checker->AsETSChecker();
64
65    program->Ast()->TransformChildrenRecursively(
66        [checker](ir::AstNode *ast) -> ir::AstNode * {
67            if (auto newValue = TryConvertToCharLiteral(checker, ast); newValue != nullptr) {
68                return newValue;
69            }
70
71            return ast;
72        },
73        Name());
74
75    return true;
76}
77
78}  // namespace ark::es2panda::compiler
79