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