• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_PARSER_TRANSFORMER_TRANSFORMER_H
17 #define ES2PANDA_PARSER_TRANSFORMER_TRANSFORMER_H
18 
19 #include <macros.h>
20 
21 #include "binder/binder.h"
22 #include "binder/scope.h"
23 #include "ir/astNode.h"
24 #include "ir/base/classDefinition.h"
25 #include "ir/base/methodDefinition.h"
26 #include "parser/module/sourceTextModuleRecord.h"
27 #include "parser/parserFlags.h"
28 #include "parser/program/program.h"
29 
30 namespace panda::es2panda::parser {
31 
32 struct TsModuleInfo {
33     util::StringView name;
34     binder::Scope *scope;
35 };
36 
37 struct TsEnumInfo {
38     util::StringView name;
39     binder::Scope *scope;
40 };
41 
42 using PrivateElementMap = std::unordered_map<util::StringView, util::StringView>;
43 using ComputedPropertyMap = std::unordered_map<ir::Statement *, util::StringView>;
44 
45 struct ClassInfo {
46     util::StringView name;
47     util::StringView aliasName;
48     const ir::ClassDefinition *node;
49     size_t propertyIndex;
50     PrivateElementMap *bindNameMap;
51     ComputedPropertyMap *computedPropertyMap;
52 };
53 
54 struct MethodInfo {
55     ir::Expression *key;
56     util::StringView backupName; // For computed property.
57     ir::MethodDefinitionKind kind;
58     ir::ModifierFlags modifiers;
59     bool isComputed;
60 };
61 
62 class DuringClass {
63 public:
DuringClass(ArenaVector<ClassInfo> * classList,util::StringView name,util::StringView aliasName,ir::ClassDefinition * node)64     explicit DuringClass(ArenaVector<ClassInfo> *classList, util::StringView name,
65                          util::StringView aliasName, ir::ClassDefinition *node)
66     {
67         classList_ = classList;
68         classList_->push_back({name, aliasName, node, 0, &bindNameMap_, &computedPropertyMap_});
69     }
70 
~DuringClass()71     ~DuringClass()
72     {
73         classList_->pop_back();
74     }
75 
76 private:
77     PrivateElementMap bindNameMap_ {};
78     ComputedPropertyMap computedPropertyMap_ {};
79     ArenaVector<ClassInfo> *classList_ {nullptr};
80 };
81 
82 class Transformer {
83 public:
Transformer(panda::ArenaAllocator * allocator)84     explicit Transformer(panda::ArenaAllocator *allocator)
85         : program_(nullptr),
86           tsModuleList_(allocator->Adapter()),
87           tsEnumList_(allocator->Adapter()),
88           classList_(allocator->Adapter())
89     {
90     }
91     NO_COPY_SEMANTIC(Transformer);
92     ~Transformer() = default;
93 
94     void Transform(Program *program);
95     void CheckTransformedAstStructure(const Program *program) const;
96 
97 private:
98     static constexpr std::string_view PRIVATE_PROPERTY_SIGN = "#";
99     static constexpr std::string_view NEW_VAR_PREFIX = "##";
100     static constexpr std::string_view NEW_VAR_HEAD = "var_";
101     static constexpr std::string_view INDEX_DIVISION = "_";
102     static constexpr std::string_view CONSTRUCTOR_NAME = "undefined";
103     static constexpr std::string_view CLASS_PROTOTYPE = "prototype";
104     static constexpr std::string_view OBJECT_VAR_NAME = "Object";
105     static constexpr std::string_view FUNC_NAME_OF_DEFINE_PROPERTY = "defineProperty";
106     static constexpr std::string_view FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR = "getOwnPropertyDescriptor";
107     static constexpr std::string_view AUTO_ACCESSOR_STORAGE_NAME = "auto_accessor_storage";
108 
109     void TransformFromTS();
110 
111     void AddVariableToNearestStatements(util::StringView name);
112     void PushVariablesToNearestStatements(ir::BlockStatement *ast);
113 
114     ir::AstNode *VisitTSNodes(ir::AstNode *parent);
115     ir::UpdateNodes VisitTSNode(ir::AstNode *childNode);
116     ir::UpdateNodes VisitTsModuleDeclaration(ir::TSModuleDeclaration *childNode, bool isExport = false);
117     std::vector<ir::AstNode *> VisitExportNamedVariable(ir::Statement *decl);
118     ir::AstNode *VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node);
119     ir::UpdateNodes VisitClassDeclaration(ir::ClassDeclaration *node);
120     ir::UpdateNodes VisitClassExpression(ir::ClassExpression *node);
121     void VisitTSParameterProperty(ir::ClassDefinition *node);
122     void VisitAutoAccessorProperty(ir::ClassDefinition *node);
123     ir::Expression *CopyClassKeyExpression(ir::Expression *orginalExpr);
124     void ProcessAutoAccessorProperty(ir::ClassProperty *node, ir::ClassDefinition *classDefinition);
125     ir::MethodDefinition* AddMethodToClass(ir::ClassDefinition *classDefinition,
126                                            const MethodInfo &methodInfo,
127                                            ArenaVector<ir::Expression *> &params,
128                                            ArenaVector<ir::Statement *> &statements);
129     /*
130      * Only support for adding generated set&get method to class.
131      */
132     ir::MethodDefinition* AddGeneratedMethodToClass(ir::ClassDefinition *classDefinition,
133                                                     const MethodInfo &methodInfo,
134                                                     util::StringView propName);
135     void AddGeneratedSetOrGetMethodToClass(ir::ClassDefinition *classDefinition,
136                                            ir::ClassProperty *propertyNode,
137                                            const MethodInfo &methodInfo);
138     std::vector<ir::ExpressionStatement *> VisitInstanceProperty(ir::ClassDefinition *node);
139     std::vector<ir::ExpressionStatement *> VisitStaticProperty(ir::ClassDefinition *node,
140                                                                util::StringView name);
141     void VisitPrivateElement(ir::ClassDefinition *node);
142     void VisitComputedProperty(ir::ClassDefinition *node);
143     util::StringView CreateClassAliasName(ir::ClassDeclaration *node);
144     const ir::ClassDefinition *GetClassReference(util::StringView name) const;
145     size_t GetInsertPosForConstructor(ir::ClassDefinition *node);
146     void FindSuperCall(const ir::AstNode *parent, bool *hasSuperCall);
147     void FindSuperCallInCtorChildNode(const ir::AstNode *childNode, bool *hasSuperCall);
148 
149     ir::VariableDeclaration *CreateVariableDeclarationWithIdentify(util::StringView name,
150                                                                    VariableParsingFlags flags,
151                                                                    ir::AstNode *node,
152                                                                    bool isExport,
153                                                                    ir::Expression *init = nullptr,
154                                                                    bool needBinding = true);
155     ir::CallExpression *CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node,
156                                                         util::StringView name,
157                                                         bool isExport = false);
158     ir::Expression *CreateTsModuleParam(util::StringView paramName, bool isExport);
159     ir::ExpressionStatement *CreateTsModuleAssignment(util::StringView name);
160     ir::Expression *CreateMemberExpressionFromQualified(ir::Expression *node);
161     std::vector<ir::AstNode *> CreateClassDecorators(ir::ClassDeclaration *node,
162                                                      const std::vector<ir::AstNode *> &variableDeclarations);
163     std::vector<ir::AstNode *> CreateMethodDecorators(util::StringView className,
164                                                       ir::MethodDefinition *node,
165                                                       const std::vector<ir::AstNode *> &variableDeclarations,
166                                                       bool isStatic);
167     std::vector<ir::AstNode *> CreatePropertyDecorators(util::StringView className,
168                                                         ir::ClassProperty *node,
169                                                         const std::vector<ir::AstNode *> &variableDeclarations,
170                                                         bool isStatic);
171     ir::CallExpression *CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key);
172     ir::CallExpression *CreateDefinePropertyCall(ir::Expression *target, ir::Expression *key, ir::Expression *value);
173     ir::ClassStaticBlock *CreateClassStaticBlock(ir::ClassDeclaration *node, bool hasPrivateIdentifer);
174     bool HasPrivateIdentifierInDecorators(const ir::ClassDefinition *classDefinition);
175     void FindPrivateIdentifierInDecorator(const ir::AstNode *parent, bool *hasprivateIdentifier);
176     void FindPrivateIdentifierInChildNode(const ir::AstNode *childNode, bool *hasprivateIdentifier);
177     std::vector<ir::AstNode *> CreateVariableDeclarationForDecorators(ir::AstNode *node);
178     std::vector<ir::AstNode *> CreateParamDecorators(util::StringView className,
179                                                      ir::MethodDefinition *node,
180                                                      const std::vector<ir::AstNode *> &variableDeclarations,
181                                                      bool isConstructor,
182                                                      bool isStatic);
183     ir::MemberExpression *CreateClassPrototype(util::StringView className);
184     ir::Expression *CreateDecoratorTarget(util::StringView className, bool isStatic);
185     ir::Identifier *CreateReferenceIdentifier(util::StringView name);
186     util::StringView CreatePrivateElementBindName(util::StringView name);
187     util::StringView CreateNewVariable(bool needAddToStatements = true);
188     util::StringView CreateNewVariableName() const;
189     util::StringView CreateUniqueName(const std::string &head, size_t *index = nullptr) const;
190 
191     util::StringView GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const;
192     util::StringView GetParamName(ir::AstNode *node, util::StringView name) const;
193     ir::Expression *GetClassMemberName(ir::Expression *key, bool isComputed,
194                                        ir::Statement *node, bool inDecorator = true);
195     binder::Scope *FindExportVariableInTsModuleScope(util::StringView name) const;
196     binder::Variable *FindTSModuleVariable(const ir::Expression *node, const binder::Scope *scope, bool *isType) const;
197     util::StringView FindPrivateElementBindName(util::StringView name);
198     void AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier);
199     void RemoveDefaultLocalExportEntry();
200     bool IsInstantiatedImportEquals(const ir::TSImportEqualsDeclaration *node, binder::Scope *scope) const;
201     void SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const;
202 
203     ir::UpdateNodes VisitTsEnumDeclaration(ir::TSEnumDeclaration *node, bool isExport = false);
204     ir::AstNode *CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name, ir::AstNode *node, bool isExport);
205     util::StringView GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration *node) const;
206     ir::CallExpression *CreateCallExpressionForTsEnum(ir::TSEnumDeclaration *node, util::StringView name,
207                                                       bool isExport);
208     ir::ExpressionStatement *CreateTsEnumMember(ir::TSEnumMember *node, ir::TSEnumMember *preNode,
209                                                 util::StringView enumLiteralName);
210     ir::ExpressionStatement *CreateTsEnumMemberWithStringInit(ir::TSEnumMember *node,
211                                                               util::StringView enumLiteralName,
212                                                               util::StringView enumMemberName);
213     ir::ExpressionStatement *CreateTsEnumMemberWithNumberInit(ir::TSEnumMember *node,
214                                                               util::StringView enumLiteralName,
215                                                               util::StringView enumMemberName);
216     ir::ExpressionStatement *CreateTsEnumMemberWithoutInit(ir::TSEnumMember *node,
217                                                            ir::TSEnumMember *preNode,
218                                                            util::StringView enumLiteralName,
219                                                            util::StringView enumMemberName);
220     ArenaVector<ir::Expression *> CreateCallExpressionArguments(util::StringView name, bool isExport);
221     bool IsStringInitForEnumMember(const ir::Expression *expr, binder::Scope *scope) const;
222     bool IsStringForMemberExpression(const ir::MemberExpression *memberExpr, binder::Scope *scope) const;
223     bool IsInstantiatedNamespaceVariable(binder::Variable *var) const;
224     ArenaVector<binder::Variable *> FindFrontIdentifierTSVariables(const ir::Identifier *ident,
225                                                                    binder::Scope *scope) const;
226     void FindLocalTSVariables(binder::Scope *scope, const util::StringView name,
227                               const std::vector<binder::TSBindingType> &types,
228                               ArenaVector<binder::Variable *> &findRes) const;
229     void FindExportTSVariables(binder::Scope *scope, const util::StringView name,
230                                const std::vector<binder::TSBindingType> &types,
231                                ArenaVector<binder::Variable *> &findRes) const;
232     bool VerifyMemberExpressionDeque(binder::Variable *currVar, ArenaDeque<const ir::Expression *> members) const;
233     util::StringView GetNameForMemberExpressionItem(const ir::Expression *node) const;
234     util::StringView GetNameFromEnumMember(const ir::TSEnumMember *node) const;
235     binder::Scope *FindEnumMemberScope(const util::StringView name) const;
236     ir::MemberExpression *CreateMemberExpressionFromIdentifier(binder::Scope *scope, ir::Identifier *node);
237 
238     void CheckTransformedAstNodes(const ir::AstNode *parent, bool *passed) const;
239     void CheckTransformedAstNode(const ir::AstNode *parent, ir::AstNode *childNode, bool *passed) const;
240 
241     void ResetParentScope(ir::UpdateNodes res, binder::Scope *parentScope) const;
242     void ResetParentScopeForAstNodes(const ir::AstNode *parent, binder::Scope *parentScope) const;
243     void ResetParentScopeForAstNode(ir::AstNode *childNode, binder::Scope *parentScope) const;
244 
245     template <typename T>
246     ir::UpdateNodes VisitExportClassDeclaration(T *node);
247 
248     template <binder::TSBindingType type>
249     binder::Variable *FindTSVariable(const binder::Scope *scope, const util::StringView &name) const;
250 
251     bool IsValueReference(ir::Identifier *node);
252 
IsTsModule()253     bool IsTsModule() const
254     {
255         return (tsModuleList_.size() != 0);
256     }
257 
IsTsEnum()258     bool IsTsEnum() const
259     {
260         return (tsEnumList_.size() != 0);
261     }
262 
InClass()263     bool InClass() const
264     {
265         return (classList_.size() != 0);
266     }
267 
268     template <typename T, typename... Args>
AllocNode(Args &&...args)269     T *AllocNode(Args &&... args)
270     {
271         auto ret = program_->Allocator()->New<T>(std::forward<Args>(args)...);
272         if (ret == nullptr) {
273             throw Error(ErrorType::GENERIC, "Unsuccessful allocation during parsing");
274         }
275         return ret;
276     }
277 
Allocator()278     ArenaAllocator *Allocator() const
279     {
280         return program_->Allocator();
281     }
282 
Binder()283     binder::Binder *Binder() const
284     {
285         return program_->Binder();
286     }
287 
Scope()288     binder::Scope *Scope() const
289     {
290         return Binder()->GetScope();
291     }
292 
GetCurrentTSModuleName()293     util::StringView GetCurrentTSModuleName() const
294     {
295         return tsModuleList_.back().name;
296     }
297 
FindTSModuleNameByScope(binder::Scope * scope)298     util::StringView FindTSModuleNameByScope(binder::Scope *scope) const
299     {
300         for (auto it : tsModuleList_) {
301             if (it.scope == scope) {
302                 return it.name;
303             }
304         }
305         UNREACHABLE();
306     }
307 
FindTSEnumNameByScope(binder::Scope * scope)308     util::StringView FindTSEnumNameByScope(binder::Scope *scope) const
309     {
310         for (auto it : tsEnumList_) {
311             if (it.scope == scope) {
312                 return it.name;
313             }
314         }
315         UNREACHABLE();
316     }
317 
Extension()318     ScriptExtension Extension() const
319     {
320         return program_->Extension();
321     }
322 
GetSourceTextModuleRecord()323     SourceTextModuleRecord *GetSourceTextModuleRecord()
324     {
325         return program_->ModuleRecord();
326     }
327 
RecordName()328     util::StringView RecordName() const
329     {
330         return program_->RecordName();
331     }
332 
GetCurrentClassInfoPropertyIndex()333     size_t GetCurrentClassInfoPropertyIndex() const
334     {
335         return classList_.back().propertyIndex;
336     }
337 
SetCurrentClassInfoPropertyIndex(size_t newIndex)338     void SetCurrentClassInfoPropertyIndex(size_t newIndex)
339     {
340         classList_.back().propertyIndex = newIndex;
341     }
342 
AddPrivateElementBinding(util::StringView name,util::StringView bindName)343     void AddPrivateElementBinding(util::StringView name, util::StringView bindName)
344     {
345         classList_.back().bindNameMap->insert({name, bindName});
346     }
347 
AddComputedPropertyBinding(ir::Statement * property,util::StringView name)348     void AddComputedPropertyBinding(ir::Statement *property, util::StringView name)
349     {
350         classList_.back().computedPropertyMap->insert({property, name});
351     }
352 
GetComputedPropertyBinding(ir::Statement * property)353     util::StringView GetComputedPropertyBinding(ir::Statement *property)
354     {
355         auto classInfo = classList_.back();
356         auto res = classInfo.computedPropertyMap->find(property);
357         ASSERT(res != classInfo.computedPropertyMap->end());
358         return res->second;
359     }
360 
GetClassAliasName()361     util::StringView GetClassAliasName() const
362     {
363         return classList_.back().aliasName;
364     }
365 
GetClassAliasName(util::StringView originName,const ir::ClassDefinition * node)366     util::StringView GetClassAliasName(util::StringView originName, const ir::ClassDefinition *node) const
367     {
368         if (node == nullptr) {
369             return originName;
370         }
371 
372         for (int i = classList_.size() - 1; i >= 0; i--) {
373             if (classList_[i].node == node) {
374                 return classList_[i].aliasName;
375             }
376         }
377         return originName;
378     }
379 
380     Program *program_;
381     ArenaVector<TsModuleInfo> tsModuleList_;
382     ArenaVector<TsEnumInfo> tsEnumList_;
383     ArenaVector<ClassInfo> classList_;
384     std::unordered_map<util::StringView, binder::Scope *> tempVarDeclStatements_ {};
385 };
386 
387 }  // namespace panda::es2panda::parser
388 
389 #endif
390