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_STATEMENT_FOR_OF_STATEMENT_H
17#define ES2PANDA_IR_STATEMENT_FOR_OF_STATEMENT_H
18
19#include <checker/types/signature.h>
20#include "ir/statements/loopStatement.h"
21
22namespace ark::es2panda::varbinder {
23class LoopScope;
24}  // namespace ark::es2panda::varbinder
25
26namespace ark::es2panda::checker {
27class ETSAnalyzer;
28class ETSObjectType;
29}  // namespace ark::es2panda::checker
30
31namespace ark::es2panda::ir {
32class Expression;
33
34// NOLINTBEGIN(modernize-avoid-c-arrays)
35inline constexpr char const ITERATOR_INTERFACE_NAME[] = "Iterator";
36inline constexpr char const ITERATOR_INTERFACE_METHOD[] = "next";
37inline constexpr char const ITERATOR_RESULT_NAME[] = "IteratorResult";
38// NOLINTEND(modernize-avoid-c-arrays)
39
40class ForOfStatement final : public LoopStatement {
41    friend class checker::ETSAnalyzer;
42
43public:
44    ForOfStatement() = delete;
45    ~ForOfStatement() override = default;
46
47    NO_COPY_SEMANTIC(ForOfStatement);
48    NO_MOVE_SEMANTIC(ForOfStatement);
49
50    explicit ForOfStatement(AstNode *left, Expression *right, Statement *body, bool const isAwait)
51        : LoopStatement(AstNodeType::FOR_OF_STATEMENT), left_(left), right_(right), body_(body), isAwait_(isAwait)
52    {
53    }
54
55    [[nodiscard]] AstNode *Left() noexcept
56    {
57        return left_;
58    }
59
60    [[nodiscard]] const AstNode *Left() const noexcept
61    {
62        return left_;
63    }
64
65    [[nodiscard]] Expression *Right() noexcept
66    {
67        return right_;
68    }
69
70    [[nodiscard]] const Expression *Right() const noexcept
71    {
72        return right_;
73    }
74
75    [[nodiscard]] Statement *Body() noexcept
76    {
77        return body_;
78    }
79
80    [[nodiscard]] const Statement *Body() const noexcept
81    {
82        return body_;
83    }
84
85    [[nodiscard]] bool IsAwait() const noexcept
86    {
87        return isAwait_;
88    }
89
90    [[nodiscard]] ForOfStatement *Clone(ArenaAllocator *allocator, AstNode *parent) override;
91
92    void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
93
94    void Iterate(const NodeTraverser &cb) const override;
95    void Dump(ir::AstDumper *dumper) const override;
96    void Dump(ir::SrcDumper *dumper) const override;
97    void Compile(compiler::PandaGen *pg) const override;
98    void Compile(compiler::ETSGen *etsg) const override;
99    checker::Type *Check(checker::TSChecker *checker) override;
100    checker::Type *Check(checker::ETSChecker *checker) override;
101
102    void Accept(ASTVisitorT *v) override
103    {
104        v->Accept(this);
105    }
106
107protected:
108    [[nodiscard]] checker::Type *CheckIteratorMethod(checker::ETSChecker *checker);
109    [[nodiscard]] checker::Type *CheckIteratorMethodForObject(checker::ETSChecker *checker,
110                                                              checker::ETSObjectType *sourceType);
111    static bool CheckReturnTypeOfIteratorMethod(checker::ETSChecker *checker, checker::ETSObjectType *sourceType,
112                                                checker::Signature *signature, const lexer::SourcePosition &position);
113    static bool CheckIteratorInterfaceForObject(checker::ETSChecker *checker, checker::ETSObjectType *obj);
114
115private:
116    checker::Type *CreateUnionIteratorTypes(checker::ETSChecker *checker, checker::Type *exprType);
117
118    AstNode *left_;
119    Expression *right_;
120    Statement *body_;
121    bool isAwait_;
122};
123}  // namespace ark::es2panda::ir
124
125#endif
126