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#ifndef ES2PANDA_IR_EXPRESSION_CALL_EXPRESSION_H
17#define ES2PANDA_IR_EXPRESSION_CALL_EXPRESSION_H
18
19#include "varbinder/variable.h"
20#include "ir/expression.h"
21
22namespace ark::es2panda::checker {
23class ETSAnalyzer;
24class TSAnalyzer;
25class Signature;
26}  // namespace ark::es2panda::checker
27
28namespace ark::es2panda::compiler {
29class JSCompiler;
30class ETSCompiler;
31}  // namespace ark::es2panda::compiler
32
33namespace ark::es2panda::ir {
34class TSTypeParameterInstantiation;
35
36class CallExpression : public MaybeOptionalExpression {
37public:
38    CallExpression() = delete;
39    ~CallExpression() override = default;
40
41    NO_COPY_SEMANTIC(CallExpression);
42    NO_MOVE_SEMANTIC(CallExpression);
43
44    explicit CallExpression(Expression *const callee, ArenaVector<Expression *> &&arguments,
45                            TSTypeParameterInstantiation *const typeParams, bool const optional,
46                            bool const trailingComma = false)
47        : MaybeOptionalExpression(AstNodeType::CALL_EXPRESSION, optional),
48          callee_(callee),
49          arguments_(std::move(arguments)),
50          typeParams_(typeParams),
51          trailingComma_(trailingComma)
52    {
53    }
54
55    explicit CallExpression(CallExpression const &other, ArenaAllocator *allocator);
56
57    // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields
58    friend class checker::TSAnalyzer;
59    friend class checker::ETSAnalyzer;
60    friend class compiler::JSCompiler;
61    friend class compiler::ETSCompiler;
62
63    const Expression *Callee() const
64    {
65        return callee_;
66    }
67
68    [[nodiscard]] Expression *Callee() noexcept
69    {
70        return callee_;
71    }
72
73    void SetCallee(Expression *callee) noexcept
74    {
75        callee_ = callee;
76        callee_->SetParent(this);
77    }
78
79    [[nodiscard]] const TSTypeParameterInstantiation *TypeParams() const noexcept
80    {
81        return typeParams_;
82    }
83
84    [[nodiscard]] TSTypeParameterInstantiation *TypeParams() noexcept
85    {
86        return typeParams_;
87    }
88
89    [[nodiscard]] const ArenaVector<Expression *> &Arguments() const noexcept
90    {
91        return arguments_;
92    }
93
94    [[nodiscard]] ArenaVector<Expression *> &Arguments() noexcept
95    {
96        return arguments_;
97    }
98
99    [[nodiscard]] bool HasTrailingComma() const noexcept
100    {
101        return trailingComma_;
102    }
103
104    [[nodiscard]] checker::Signature *Signature() noexcept
105    {
106        return signature_;
107    }
108
109    [[nodiscard]] checker::Signature *Signature() const noexcept
110    {
111        return signature_;
112    }
113
114    void SetSignature(checker::Signature *const signature) noexcept
115    {
116        signature_ = signature;
117    }
118
119    void SetTypeParams(TSTypeParameterInstantiation *typeParams) noexcept;
120
121    [[nodiscard]] checker::Type *UncheckedType() const noexcept
122    {
123        return uncheckedType_;
124    }
125
126    void SetUncheckedType(checker::Type *type) noexcept
127    {
128        uncheckedType_ = type;
129    }
130
131    void SetTrailingBlock(ir::BlockStatement *const block) noexcept;
132
133    [[nodiscard]] ir::BlockStatement *TrailingBlock() const noexcept
134    {
135        return trailingBlock_;
136    }
137
138    void SetIsTrailingBlockInNewLine(bool const isNewLine) noexcept
139    {
140        isTrailingBlockInNewLine_ = isNewLine;
141    }
142
143    [[nodiscard]] bool IsTrailingBlockInNewLine() const noexcept
144    {
145        return isTrailingBlockInNewLine_;
146    }
147
148    [[nodiscard]] CallExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override;
149
150    void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
151    void Iterate(const NodeTraverser &cb) const override;
152
153    void Dump(ir::AstDumper *dumper) const override;
154    void Dump(ir::SrcDumper *dumper) const override;
155    void Compile(compiler::PandaGen *pg) const override;
156    void Compile(compiler::ETSGen *etsg) const override;
157    checker::Type *Check(checker::TSChecker *checker) override;
158    checker::Type *Check(checker::ETSChecker *checker) override;
159
160    void Accept(ASTVisitorT *v) override
161    {
162        v->Accept(this);
163    }
164
165protected:
166    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
167    Expression *callee_;
168    ArenaVector<Expression *> arguments_;
169    TSTypeParameterInstantiation *typeParams_;
170    checker::Signature *signature_ {};
171    bool trailingComma_;
172    // for trailing lambda feature in ets
173    ir::BlockStatement *trailingBlock_ {};
174    bool isTrailingBlockInNewLine_ {false};
175    checker::Type *uncheckedType_ {};
176    // NOLINTEND(misc-non-private-member-variables-in-classes)
177
178private:
179    bool IsETSConstructorCall() const;
180    checker::Type *InitAnonymousLambdaCallee(checker::ETSChecker *checker, Expression *callee,
181                                             checker::Type *calleeType);
182};
183}  // namespace ark::es2panda::ir
184
185#endif
186