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_SCOPED_DEBUG_INFO_PLUGIN_H
17#define ES2PANDA_EVALUATE_SCOPED_DEBUG_INFO_PLUGIN_H
18
19#include "evaluate/debugInfoStorage.h"
20#include "evaluate/evaluateContext.h"
21#include "evaluate/helpers.h"
22#include "evaluate/irCheckHelper.h"
23#include "evaluate/proxyProgramsCache.h"
24#include "evaluate/pathResolver.h"
25#include "evaluate/entityDeclarator.h"
26#include "evaluate/debugInfoDeserialization/debugInfoDeserializer.h"
27
28namespace ark::es2panda::ir {
29class BlockStatement;
30class Statement;
31}  // namespace ark::es2panda::ir
32
33namespace ark::es2panda::varbinder {
34class ETSBinder;
35class Variable;
36}  // namespace ark::es2panda::varbinder
37
38namespace ark::es2panda::evaluate {
39
40/// @brief Context-dependent debug info plugin. Must be created before parsing phase.
41class ScopedDebugInfoPlugin final {
42public:
43    explicit ScopedDebugInfoPlugin(parser::Program *globalProgram, checker::ETSChecker *checker,
44                                   const CompilerOptions &options);
45
46    NO_COPY_SEMANTIC(ScopedDebugInfoPlugin);
47    NO_MOVE_SEMANTIC(ScopedDebugInfoPlugin);
48
49    ~ScopedDebugInfoPlugin() = default;
50
51    /**
52     * @brief Searches debug-info for the given identifier
53     * @param ident node with name of either a local or global variable or a class
54     */
55    varbinder::Variable *FindIdentifier(ir::Identifier *ident);
56
57    /**
58     * @brief Searches debug-info for the given class
59     * On success creates IR for this and all dependencies.
60     */
61    varbinder::Variable *FindClass(ir::Identifier *ident);
62
63    /**
64     * @brief Adds collected prologue and epilogue statements in the block
65     * In effect, previously collected prologue-epilogue statements are dropped.
66     */
67    void AddPrologueEpilogue(ir::BlockStatement *block);
68
69    /**
70     * @brief Save \p stmt node to be pushed later at the beginning or end of the \p block depending on the IS_PROLOGUE
71     * parameter
72     */
73    template <bool IS_PROLOGUE>
74    void RegisterPrologueEpilogue(ir::BlockStatement *block, ir::Statement *stmt);
75
76    /**
77     * @brief Initialization before ETSChecker starts checking AST
78     * Since we can resolve references like `new A()`, that resolved before ETSChecker was started,
79     * we need such a precheck call.
80     */
81    void PreCheck();
82
83    /**
84     * @brief Finalization after ETSChecker checks the main program
85     */
86    void PostCheck();
87
88    PathResolver *GetPathResolver()
89    {
90        return &pathResolver_;
91    }
92
93    const PathResolver *GetPathResolver() const
94    {
95        return &pathResolver_;
96    }
97
98    IrCheckHelper *GetIrCheckHelper()
99    {
100        return &irCheckHelper_;
101    }
102
103    const IrCheckHelper *GetIrCheckHelper() const
104    {
105        return &irCheckHelper_;
106    }
107
108    DebugInfoStorage *GetDebugInfoStorage()
109    {
110        return &debugInfoStorage_;
111    }
112
113    const DebugInfoStorage *GetDebugInfoStorage() const
114    {
115        return &debugInfoStorage_;
116    }
117
118    ProxyProgramsCache *GetProxyProgramsCache()
119    {
120        return &proxyProgramsCache_;
121    }
122
123    const ProxyProgramsCache *GetProxyProgramsCache() const
124    {
125        return &proxyProgramsCache_;
126    }
127
128    EntityDeclarator *GetEntityDeclarator()
129    {
130        return &entityDeclarator_;
131    }
132
133    const EntityDeclarator *GetEntityDeclarator() const
134    {
135        return &entityDeclarator_;
136    }
137
138    DebugInfoDeserializer *GetDebugInfoDeserializer()
139    {
140        return &debugInfoDeserializer_;
141    }
142
143    const DebugInfoDeserializer *GetDebugInfoDeserializer() const
144    {
145        return &debugInfoDeserializer_;
146    }
147
148    varbinder::ETSBinder *GetETSBinder();
149
150private:
151    using PrologueEpiloguePair = std::pair<ArenaVector<ir::Statement *>, ArenaVector<ir::Statement *>>;
152    using PrologueEpilogueMap = ArenaUnorderedMap<ir::BlockStatement *, PrologueEpiloguePair>;
153
154private:
155    /**
156     * @brief Asserts correctness of input options.
157     */
158    void ValidateEvaluationOptions(const CompilerOptions &options);
159
160    /**
161     * @brief Creates `Program` instances for each input context .abc file.
162     */
163    void CreateContextPrograms();
164
165    /**
166     * @brief Creates a program with the given package name and adds it as external for the given global program.
167     * This method must be called once and before running any compiler phases.
168     * @param sourceFilePath corresponding to source code of one of the provided .abc files.
169     * @param moduleName of source file, extracted from .abc file encoding.
170     * @returns pointer to initialized program.
171     */
172    parser::Program *CreateEmptyProgram(std::string_view sourceFilePath, std::string_view moduleName);
173
174    /**
175     * @brief Returns non-null program for the given source file path.
176     */
177    parser::Program *GetProgram(util::StringView fileName);
178
179    parser::Program *GetEvaluatedExpressionProgram();
180
181    /// Search methods.
182    varbinder::Variable *FindGlobalVariable(ir::Identifier *ident);
183    varbinder::Variable *FindGlobalFunction(ir::Identifier *ident);
184    varbinder::Variable *FindLocalVariable(ir::Identifier *ident);
185
186    /**
187     * @brief Pushes back return statement into the evaluation method
188     * if its last statement potentially returns a primitive value.
189     * @returns true if insertion took place, false otherwise.
190     */
191    bool InsertReturnStatement();
192
193    ArenaAllocator *Allocator();
194
195private:
196    parser::Program *globalProgram_ {nullptr};
197    checker::ETSChecker *checker_ {nullptr};
198
199    EvaluateContext context_;
200
201    IrCheckHelper irCheckHelper_;
202    DebugInfoStorage debugInfoStorage_;
203    DebugInfoDeserializer debugInfoDeserializer_;
204    PathResolver pathResolver_;
205    PrologueEpilogueMap prologueEpilogueMap_;
206    ProxyProgramsCache proxyProgramsCache_;
207    EntityDeclarator entityDeclarator_;
208};
209
210}  // namespace ark::es2panda::evaluate
211
212#endif  // ES2PANDA_EVALUATE_SCOPED_DEBUG_INFO_PLUGIN_H
213