• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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_COMPILER_CORE_SCOPES_INIT_PHASE_H
17 #define ES2PANDA_COMPILER_CORE_SCOPES_INIT_PHASE_H
18 
19 #include "compiler/lowering/phase.h"
20 #include "util/helpers.h"
21 #include "parser/parserFlags.h"
22 #include "varbinder/tsBinding.h"
23 #include "varbinder/ETSBinder.h"
24 #include "compiler/lowering/scopesInit/savedBindingsCtx.h"
25 #include "checker/checker.h"
26 #include "ir/visitor/IterateAstVisitor.h"
27 #include "ir/expressions/literals/undefinedLiteral.h"
28 #include "ir/expressions/blockExpression.h"
29 #include "ir/ets/etsUnionType.h"
30 #include "ir/ets/etsTuple.h"
31 
32 namespace ark::es2panda::compiler {
33 
34 /**
35  * Responsible for initialization of scopes. Should be called right after Parser stage.
36  */
37 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
38 class ScopesInitPhase : public Phase, public ir::visitor::IterateAstVisitor {
39 public:
40     using PhaseContext = public_lib::Context;
41 
42     static constexpr std::string_view NAME = "ScopesInitPhase";
43 
Name()44     std::string_view Name() const override
45     {
46         return NAME;
47     }
48 
49     bool Perform(PhaseContext *ctx, parser::Program *program) override;
50 
51 protected:
52     void SetProgram(parser::Program *program) noexcept;
53 
54     void Prepare(PhaseContext *ctx, parser::Program *program);
55 
56     /**
57      * Should be called at the end of each program perform
58      */
59     void Finalize();
60 
61     /**
62      * Check if there's only one default export and no named export redeclaration,
63      * throw error if so.
64      * Side effect: fill local_exports_
65      */
66     void AnalyzeExports();
67 
68 protected:
69     template <typename T>
CallNode(T * node)70     void CallNode(T *node)
71     {
72         if (node) {
73             node->Accept(this);
74         }
75     }
76 
77     template <typename T>
CallNode(const ArenaVector<T * > & nodes)78     void CallNode(const ArenaVector<T *> &nodes)
79     {
80         for (auto *node : nodes) {
81             CallNode(node);
82         }
83     }
84 
85     void CallFuncParams(const ArenaVector<ir::Expression *> &params);
86     void IterateNoTParams(ir::ClassDefinition *classDef);
87 
88 protected:
89     void LogDiagnostic(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &params,
90                        const lexer::SourcePosition &pos) const;
91 
LogDiagnostic(const diagnostic::DiagnosticKind & kind,const lexer::SourcePosition & pos)92     void LogDiagnostic(const diagnostic::DiagnosticKind &kind, const lexer::SourcePosition &pos) const
93     {
94         LogDiagnostic(kind, util::DiagnosticMessageParams {}, pos);
95     }
96 
97     void VisitFunctionExpression(ir::FunctionExpression *funcExpr) override;
98     void VisitScriptFunction(ir::ScriptFunction *scriptFunction) override;
99     void VisitBlockStatement(ir::BlockStatement *blockStmt) override;
100     void VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) override;
101     void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override;
102     void VisitClassDefinition(ir::ClassDefinition *classDef) override;
103     void VisitMethodDefinition(ir::MethodDefinition *methodDefinition) override;
104     void VisitForUpdateStatement(ir::ForUpdateStatement *forUpdateStmt) override;
105     void VisitForInStatement(ir::ForInStatement *forInStmt) override;
106     void VisitForOfStatement(ir::ForOfStatement *forOfStmt) override;
107     void VisitCatchClause(ir::CatchClause *catchClause) override;
108     void VisitVariableDeclarator(ir::VariableDeclarator *varDecl) override;
109     void VisitSwitchStatement(ir::SwitchStatement *switchStmt) override;
110     void VisitWhileStatement(ir::WhileStatement *whileStmt) override;
111     void VisitETSStructDeclaration(ir::ETSStructDeclaration *structDecl) override;
112     void VisitClassDeclaration(ir::ClassDeclaration *classDecl) override;
113     void VisitDoWhileStatement(ir::DoWhileStatement *doWhileStmt) override;
114     void VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) override;
115     void VisitExportAllDeclaration(ir::ExportAllDeclaration *exportAllDecl) override;
116     void VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) override;
117     void VisitImportSpecifier(ir::ImportSpecifier *importSpec) override;
118     void VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier *importSpec) override;
119     void VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) override;
120     void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override;
121     void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override;
122     void VisitDirectEvalExpression(ir::DirectEvalExpression *directCallExpr) override;
123     void VisitTSFunctionType(ir::TSFunctionType *funcType) override;
124     void VisitAnnotationDeclaration(ir::AnnotationDeclaration *annoDecl) override;
125     void VisitAnnotationUsage(ir::AnnotationUsage *annoUsage) override;
126 
127 protected:
GetScope()128     varbinder::Scope *GetScope()
129     {
130         return VarBinder()->GetScope();
131     }
132 
Allocator()133     ArenaAllocator *Allocator()
134     {
135         return program_->Allocator();
136     }
137 
Program()138     parser::Program *Program()
139     {
140         return program_;
141     }
142 
Program()143     const parser::Program *Program() const
144     {
145         return program_;
146     }
147 
Context()148     PhaseContext *Context()
149     {
150         return ctx_;
151     }
152 
VarBinder()153     [[nodiscard]] varbinder::VarBinder *VarBinder() const
154     {
155         return program_->VarBinder();
156     }
157 
158 protected:
159     virtual void CreateFuncDecl(ir::ScriptFunction *func);
160     virtual util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id);
161     void HandleFunction(ir::ScriptFunction *function);
162     varbinder::FunctionParamScope *HandleFunctionSig(ir::TSTypeParameterDeclaration *typeParams,
163                                                      const ArenaVector<ir::Expression *> &params,
164                                                      ir::TypeNode *returnType);
165 
166     /**
167      * Handle block from existing scope
168      */
169     void HandleBlockStmt(ir::BlockStatement *block, varbinder::Scope *scope);
170 
171     template <typename ForT>
HandleFor(varbinder::LoopDeclarationScope * declScope,varbinder::LoopScope * loopScope,ForT * forStmt)172     void HandleFor(varbinder::LoopDeclarationScope *declScope, varbinder::LoopScope *loopScope, ForT *forStmt)
173     {
174         loopScope->BindDecls(declScope);
175         BindScopeNode(loopScope, forStmt);
176         loopScope->DeclScope()->BindNode(forStmt);
177     }
178 
179 protected:
180     virtual varbinder::Decl *BindClassName(ir::ClassDefinition *classDef);
181 
182     template <class Scope, class Node>
BindScopeNode(Scope * scope,Node * node)183     static void BindScopeNode(Scope *scope, Node *node)
184     {
185         if (node->Scope() == nullptr || node->IsBlockStatement()) {
186             scope->BindNode(node);
187             node->SetScope(scope);
188         }
189     }
190 
191     static void BindFunctionScopes(varbinder::FunctionScope *scope, varbinder::FunctionParamScope *paramScope);
192 
193     void BindClassDefinition(ir::ClassDefinition *classDef);
194 
195     std::tuple<varbinder::Decl *, varbinder::Variable *> AddOrGetVarDecl(ir::VariableDeclaratorFlag flag,
196                                                                          const ir::Identifier *id);
197 
198     virtual void BindVarDecl([[maybe_unused]] ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
199                              [[maybe_unused]] varbinder::Variable *var);
200     virtual void AttachLabelToScope(ir::AstNode *node);
201 
202 private:
203     PhaseContext *ctx_ {};
204     parser::Program *program_ {};
205 };
206 
207 /**
208  * Specialization for typed script languages (typescript, ets)
209  */
210 class ScopeInitTyped : public ScopesInitPhase {
211 protected:
212 public:
213     void VisitTSModuleDeclaration(ir::TSModuleDeclaration *moduleDecl) override;
214 
215     void VisitTSModuleBlock(ir::TSModuleBlock *block) override;
216 
217     void VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAliasDecl) override;
218 
219     util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id) override;
220 
AllowInterfaceRedeclaration()221     virtual bool AllowInterfaceRedeclaration()
222     {
223         return false;
224     }
225 
226     void VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfDecl) override;
227 
228     void VisitTSEnumMember(ir::TSEnumMember *enumMember) override;
229 
230     void VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) override;
231 
232     void VisitTSTypeParameter(ir::TSTypeParameter *typeParam) override;
233 
234     void VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl) override;
235 
236     void VisitClassDefinition(ir::ClassDefinition *classDef) override;
237 };
238 
239 class InitScopesPhaseJs : public ScopesInitPhase {
240 public:
241     InitScopesPhaseJs() = default;
242     NO_COPY_SEMANTIC(InitScopesPhaseJs);
243     NO_MOVE_SEMANTIC(InitScopesPhaseJs);
244 
245     ~InitScopesPhaseJs() override = default;
246 };
247 
248 class InitScopesPhaseTs : public ScopeInitTyped {
249 protected:
AllowInterfaceRedeclaration()250     bool AllowInterfaceRedeclaration() override
251     {
252         return true;
253     }
254 
VisitTSMappedType(ir::TSMappedType * mapped)255     void VisitTSMappedType([[maybe_unused]] ir::TSMappedType *mapped) override {}
VisitTSInferType(ir::TSInferType * infer)256     void VisitTSInferType([[maybe_unused]] ir::TSInferType *infer) override {}
257     void VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) override;
258     void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override;
259     void VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) override;
260     void VisitTSFunctionType(ir::TSFunctionType *constrType) override;
261     void VisitTSConstructorType(ir::TSConstructorType *constrT) override;
262     void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr) override;
263     void VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl) override;
264     void VisitTSMethodSignature(ir::TSMethodSignature *methodSign) override;
265 
266     void CreateFuncDecl(ir::ScriptFunction *func) override;
267 };
268 
269 class InitScopesPhaseETS : public ScopeInitTyped {
270 public:
271     InitScopesPhaseETS() = default;
272     NO_COPY_SEMANTIC(InitScopesPhaseETS);
273     NO_MOVE_SEMANTIC(InitScopesPhaseETS);
274 
275     /**
276      * Set scopes for ast-subtree
277      * @param node ast-subtree, for this node and all children scopes will be initialized.
278      * @param varbinder ref to VarBinder. All varbinder scopes should be set to current context.
279      * Note: It's programmer responsibility to prepare VarBinder (remove previous names, set current scope, etc...)
280      *
281      * Example: // CC-OFF(G.CMT.04) false positive
282      * f<T>(x: Int) :  {
283      *     let y = 0;
284      * }
285      * After ScopesInitPhase scope structure will look something like this:
286      * global_scope:
287      *     [f],
288      *     local_scope:
289      *        [T],
290      *        function_param_scope:
291      *            [x],
292      *            function_scope:
293      *                [y]
294      * Suppose you want to rewrite function body in some lowering later to
295      * {
296      *     let z = 123;
297      * }
298      *
299      * Then you should pass your new created node = ir::BlockStatement() to RunExternalNode,
300      * set varbinder to previous `function_scope` and call RunExternalNode(node, varbinder).
301      * It will update scopes to: // CC-OFF(G.CMT.04) false positive
302      * global_scope:
303      *     [f],
304      *     local_scope:
305      *        [T],
306      *        function_param_scope:
307      *            [x],
308      *            function_scope:
309      *                [z]
310      */
311     static void RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder);
312     /**
313      * Same as previous, just uses varbinder from ctx->VarBinder()
314      */
315     static void RunExternalNode(ir::AstNode *node, parser::Program *ctx);
316 
317     /**
318      * Run scope initialization on program.
319      * It's not same as RunExternalNode(program->Ast()), because there's some specific handling for top scope.
320      * @param ctx
321      * @param program - program you want to set scopes on.
322      * @return true if successful.
323      */
324     bool Perform(PhaseContext *ctx, parser::Program *program) override;
325 
326     ~InitScopesPhaseETS() override = default;
327 
328 private:
329     void HandleProgram(parser::Program *program);
330 
331     void HandleETSModule(ir::BlockStatement *script);
332 
333     void ParseGlobalClass(ir::ClassDefinition *global);
334 
335     void AddGlobalDeclaration(ir::AstNode *node);
336 
BindClassName(ir::ClassDefinition * identNode)337     varbinder::Decl *BindClassName([[maybe_unused]] ir::ClassDefinition *identNode) override
338     {
339         return nullptr;
340     }
341 
342     void BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl,
343                      varbinder::Variable *var) override;
344     void DeclareClassMethod(ir::MethodDefinition *method);
345     void MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName, varbinder::Variable *found,
346                           varbinder::ClassScope *clsScope, varbinder::LocalScope *targetScope);
347 
348     void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override;
349     void VisitBlockExpression(ir::BlockExpression *blockExpr) override;
350     void VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) override;
351     void VisitImportSpecifier([[maybe_unused]] ir::ImportSpecifier *importSpec) override;
VisitImportDefaultSpecifier(ir::ImportDefaultSpecifier * importSpec)352     void VisitImportDefaultSpecifier([[maybe_unused]] ir::ImportDefaultSpecifier *importSpec) override {};
353     void VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport) override;
354     void VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr) override;
355     void VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) override;
356     void VisitTSEnumMember(ir::TSEnumMember *enumMember) override;
357     void VisitMethodDefinition(ir::MethodDefinition *method) override;
358     void VisitETSFunctionType(ir::ETSFunctionType *funcType) override;
359     void VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr) override;
360     void VisitTSTypeParameter(ir::TSTypeParameter *typeParam) override;
361     void VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl) override;
362     void VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) override;
363     void VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias) override;
364     void VisitClassDefinition(ir::ClassDefinition *classDef) override;
365     void VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody) override;
366     void VisitClassProperty(ir::ClassProperty *classProp) override;
367     void VisitBreakStatement(ir::BreakStatement *stmt) override;
368     void VisitContinueStatement(ir::ContinueStatement *stmt) override;
369     void AttachLabelToScope(ir::AstNode *node) override;
VisitArrowFunctionExpression(ir::ArrowFunctionExpression * arrowExpr)370     void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override
371     {
372         Iterate(arrowExpr);
373     }
374 
FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier * id)375     util::StringView FormInterfaceOrEnumDeclarationIdBinding(ir::Identifier *id) override
376     {
377         return id->Name();
378     }
379 
380     static void AddGlobalToBinder(parser::Program *program);
381 
382     void FilterInterfaceOverloads(ArenaVector<ir::AstNode *> &props);
383 
384     void FilterOverloads(ArenaVector<ir::AstNode *> &props);
385 };
386 
387 class InitScopesPhaseAS : public ScopesInitPhase {
388 public:
389     NO_COPY_SEMANTIC(InitScopesPhaseAS);
390     NO_MOVE_SEMANTIC(InitScopesPhaseAS);
391     InitScopesPhaseAS() = default;
392     ~InitScopesPhaseAS() override = default;
393 
394 private:
395     void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override;
396     void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override;
397 };
398 }  // namespace ark::es2panda::compiler
399 
400 #endif
401