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 "evaluate/helpers.h"
17#include "evaluate/irCheckHelper.h"
18#include "compiler/lowering/util.h"
19#include "compiler/lowering/scopesInit/scopesInitPhase.h"
20#include "checker/ETSchecker.h"
21
22namespace ark::es2panda::evaluate {
23
24IrCheckHelper::IrCheckHelper(checker::ETSChecker *checker, varbinder::ETSBinder *varBinder)
25    : checker_(checker), varBinder_(varBinder), recursiveDecls_(checker->Allocator()->Adapter())
26{
27    ASSERT(checker_);
28    ASSERT(varBinder_);
29}
30
31bool IrCheckHelper::CheckNewNode(ir::AstNode *node, varbinder::Scope *scope, ir::AstNode *parentClass,
32                                 parser::Program *program)
33{
34    ASSERT(node);
35
36    if (program == nullptr) {
37        program = varBinder_->Program();
38    }
39    if (scope == nullptr) {
40        scope = checker_->Scope();
41    }
42
43    recursiveDecls_.emplace_back(program, scope, parentClass, node);
44
45    if (isRecursive_) {
46        return false;
47    }
48    isRecursive_ = true;
49
50    if (isPrecheckPassed_) {
51        HandleCustomNodes();
52        CheckDecls();
53    }
54
55    isRecursive_ = false;
56
57    return true;
58}
59
60void IrCheckHelper::PreCheck()
61{
62    HandleCustomNodes();
63    CheckDecls();
64
65    isPrecheckPassed_ = true;
66}
67
68void IrCheckHelper::CheckDecls()
69{
70    // All dependent user-classes must be created at this point, so we can run checker.
71    while (!recursiveDecls_.empty()) {
72        auto [program, scope, parent, node] = recursiveDecls_.front();
73        recursiveDecls_.pop_front();
74        helpers::DoScopedAction(checker_, varBinder_, program, scope, parent, [this, node = node, scope = scope]() {
75            varBinder_->ResolveReferencesForScope(node, scope);
76            node->Check(checker_);
77        });
78    }
79}
80
81void IrCheckHelper::HandleCustomNodes()
82{
83    auto iter = recursiveDecls_.begin();
84    while (iter != recursiveDecls_.end()) {
85        // Can trigger `ETSBinder::BuildClassDefinition`,
86        // which can eventually call debug-info plugin to create another class.
87        // Hence we delay `ETSChecker::Check` until all required classes are built and initialized in varbinder.
88        auto [program, scope, parent, node] = *iter;
89        helpers::DoScopedAction(checker_, varBinder_, program, scope, parent,
90                                [varBinder = varBinder_, node = node]() { varBinder->HandleCustomNodes(node); });
91        ++iter;
92    }
93}
94
95void IrCheckHelper::CheckGlobalEntity(parser::Program *program, ir::AstNode *node, bool mustCheck)
96{
97    ASSERT(program);
98
99    auto *globalClass = program->GlobalClass();
100    auto *globalClassScope = program->GlobalClassScope();
101
102    helpers::DoScopedAction(checker_, varBinder_, program, globalClassScope, globalClass,
103                            [this, globalClassScope, node]() {
104                                compiler::InitScopesPhaseETS::RunExternalNode(node, varBinder_);
105                                varBinder_->ResolveReferencesForScope(node, globalClassScope);
106                            });
107    if (mustCheck) {
108        CheckNewNode(node, globalClassScope, globalClass, program);
109    }
110}
111
112void IrCheckHelper::CheckLocalEntity(ir::AstNode *node)
113{
114    compiler::InitScopesPhaseETS::RunExternalNode(node, varBinder_);
115    CheckNewNode(node, nullptr, nullptr, nullptr);
116}
117
118}  // namespace ark::es2panda::evaluate
119