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