1/*
2 * Copyright (c) 2021-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 "etsNewClassInstanceExpression.h"
17
18#include "compiler/core/ETSGen.h"
19#include "compiler/core/pandagen.h"
20#include "checker/TSchecker.h"
21#include "ir/astDump.h"
22#include "ir/srcDump.h"
23
24namespace ark::es2panda::ir {
25void ETSNewClassInstanceExpression::TransformChildren(const NodeTransformer &cb, std::string_view transformationName)
26{
27    if (auto *transformedNode = cb(typeReference_); typeReference_ != transformedNode) {
28        typeReference_->SetTransformedNode(transformationName, transformedNode);
29        typeReference_ = transformedNode->AsExpression();
30    }
31
32    for (auto *&arg : arguments_) {
33        if (auto *transformedNode = cb(arg); arg != transformedNode) {
34            arg->SetTransformedNode(transformationName, transformedNode);
35            arg = transformedNode->AsExpression();
36        }
37    }
38
39    if (classDef_ != nullptr) {
40        if (auto *transformedNode = cb(classDef_); classDef_ != transformedNode) {
41            classDef_->SetTransformedNode(transformationName, transformedNode);
42            classDef_ = transformedNode->AsClassDefinition();
43        }
44    }
45}
46
47void ETSNewClassInstanceExpression::Iterate([[maybe_unused]] const NodeTraverser &cb) const
48{
49    cb(typeReference_);
50
51    for (auto *arg : arguments_) {
52        cb(arg);
53    }
54
55    if (classDef_ != nullptr) {
56        cb(classDef_);
57    }
58}
59
60void ETSNewClassInstanceExpression::Dump(ir::AstDumper *dumper) const
61{
62    dumper->Add({{"type", "ETSNewClassInstanceExpression"},
63                 {"typeReference", typeReference_},
64                 {"arguments", arguments_},
65                 {"classBody", AstDumper::Optional(classDef_)}});
66}
67
68void ETSNewClassInstanceExpression::Dump(ir::SrcDumper *dumper) const
69{
70    dumper->Add("new ");
71    if (typeReference_ != nullptr) {
72        typeReference_->Dump(dumper);
73    }
74    dumper->Add("(");
75    for (auto argument : arguments_) {
76        argument->Dump(dumper);
77        if (argument != arguments_.back()) {
78            dumper->Add(", ");
79        }
80    }
81    dumper->Add(")");
82}
83
84void ETSNewClassInstanceExpression::Compile(compiler::PandaGen *pg) const
85{
86    pg->GetAstCompiler()->Compile(this);
87}
88
89void ETSNewClassInstanceExpression::Compile(compiler::ETSGen *etsg) const
90{
91    etsg->GetAstCompiler()->Compile(this);
92}
93
94checker::Type *ETSNewClassInstanceExpression::Check(checker::TSChecker *checker)
95{
96    return checker->GetAnalyzer()->Check(this);
97}
98
99checker::Type *ETSNewClassInstanceExpression::Check(checker::ETSChecker *checker)
100{
101    return checker->GetAnalyzer()->Check(this);
102}
103
104ETSNewClassInstanceExpression::ETSNewClassInstanceExpression(ETSNewClassInstanceExpression const &other,
105                                                             ArenaAllocator *const allocator)
106    : Expression(static_cast<Expression const &>(other)), arguments_(allocator->Adapter()), signature_(other.signature_)
107{
108    typeReference_ =
109        other.typeReference_ != nullptr ? other.typeReference_->Clone(allocator, this)->AsExpression() : nullptr;
110    classDef_ = other.classDef_ != nullptr ? other.classDef_->Clone(allocator, this)->AsClassDefinition() : nullptr;
111
112    for (auto *const argument : other.arguments_) {
113        arguments_.emplace_back(argument->Clone(allocator, this)->AsExpression());
114    }
115}
116
117ETSNewClassInstanceExpression *ETSNewClassInstanceExpression::Clone(ArenaAllocator *const allocator,
118                                                                    AstNode *const parent)
119{
120    if (auto *const clone = allocator->New<ETSNewClassInstanceExpression>(*this, allocator); clone != nullptr) {
121        if (parent != nullptr) {
122            clone->SetParent(parent);
123        }
124        return clone;
125    }
126
127    throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
128}
129}  // namespace ark::es2panda::ir
130