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