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#ifndef ES2PANDA_EVALUATE_NON_RECURSIVE_IR_CHECKER_H
17#define ES2PANDA_EVALUATE_NON_RECURSIVE_IR_CHECKER_H
18
19#include "libpandabase/mem/arena_allocator.h"
20#include "libpandabase/utils/arena_containers.h"
21
22namespace ark::es2panda::checker {
23class ETSChecker;
24}  // namespace ark::es2panda::checker
25
26namespace ark::es2panda::ir {
27class AstNode;
28}  // namespace ark::es2panda::ir
29
30namespace ark::es2panda::parser {
31class Program;
32}  // namespace ark::es2panda::parser
33
34namespace ark::es2panda::varbinder {
35class ETSBinder;
36class Scope;
37}  // namespace ark::es2panda::varbinder
38
39namespace ark::es2panda::evaluate {
40
41/**
42 * @brief Helper class for running type checks
43 * All newly created IR nodes from debug-info must be checked through this class,
44 * otherwise recursive class creations can lead to varbinder scopes errors.
45 */
46class IrCheckHelper final {
47public:
48    struct ScopedAstNode final {
49        ScopedAstNode(parser::Program *p, varbinder::Scope *s, ir::AstNode *parent, ir::AstNode *n)
50            : program(p), scope(s), parentClass(parent), node(n)
51        {
52        }
53
54        // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
55        parser::Program *program {nullptr};
56        varbinder::Scope *scope {nullptr};
57        ir::AstNode *parentClass {nullptr};
58        ir::AstNode *node {nullptr};
59        // NOLINTEND(misc-non-private-member-variables-in-classes)
60    };
61
62public:
63    explicit IrCheckHelper(checker::ETSChecker *checker, varbinder::ETSBinder *varBinder);
64    NO_COPY_SEMANTIC(IrCheckHelper);
65    NO_MOVE_SEMANTIC(IrCheckHelper);
66    ~IrCheckHelper() noexcept = default;
67
68    /**
69     * @brief Runs scope and type checks on the given IR node
70     * @param node to check, must not be null.
71     * @param scope to which node is relative to - if null, current checker scope is taken.
72     * @param parentClass class to use record table from, might be null.
73     * @param program relative to node - if null, current varbinder program is taken;
74     * either it or `scope` must be non-null.
75     * @returns false if check was delayed until recursion end, true if check was done immediately.
76     */
77    bool CheckNewNode(ir::AstNode *node, varbinder::Scope *scope, ir::AstNode *parentClass, parser::Program *program);
78
79    void PreCheck();
80
81    void CheckGlobalEntity(parser::Program *program, ir::AstNode *node, bool mustCheck = true);
82    void CheckLocalEntity(ir::AstNode *node);
83
84    checker::ETSChecker *GetChecker() const
85    {
86        return checker_;
87    }
88
89private:
90    void HandleCustomNodes();
91    void CheckDecls();
92
93private:
94    checker::ETSChecker *checker_ {nullptr};
95    varbinder::ETSBinder *varBinder_ {nullptr};
96
97    bool isRecursive_ {false};
98    // List is required due to possible push-backs during iteration.
99    ArenaList<ScopedAstNode> recursiveDecls_;
100    // Indicates that PreCheck was called from ETSChecker::StartChecker()
101    bool isPrecheckPassed_ {false};
102};
103
104}  // namespace ark::es2panda::evaluate
105
106#endif  // ES2PANDA_EVALUATE_NON_RECURSIVE_IR_CHECKER_H
107