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 *> ¶ms, 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