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#include "compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h" 17 18namespace ark::es2panda::compiler { 19 20void GlobalDeclTransformer::FilterDeclarations(ArenaVector<ir::Statement *> &stmts) 21{ 22 const auto isDeclCb = [&types = typeDecl_](const ir::AstNode *node) { 23 return types.count(node->Type()) == 0U || 24 (node->IsExportNamedDeclaration() && !node->AsExportNamedDeclaration()->Specifiers().empty()); 25 }; 26 stmts.erase(std::remove_if(stmts.begin(), stmts.end(), isDeclCb), stmts.end()); 27} 28 29GlobalDeclTransformer::ResultT GlobalDeclTransformer::TransformStatements(const ArenaVector<ir::Statement *> &stmts, 30 bool addInitializer) 31{ 32 addInitializer_ = addInitializer; 33 result_.classProperties.clear(); 34 result_.initStatements.clear(); 35 for (auto stmt : stmts) { 36 stmt->Accept(this); 37 } 38 return std::move(result_); 39} 40 41void GlobalDeclTransformer::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) 42{ 43 auto *funcExpr = util::NodeAllocator::ForceSetParent<ir::FunctionExpression>(allocator_, funcDecl->Function()); 44 funcDecl->Function()->SetStart(funcDecl->Function()->Id()->End()); 45 funcExpr->SetRange(funcDecl->Function()->Range()); 46 ir::MethodDefinitionKind methodKind; 47 if (funcDecl->Function()->IsExtensionMethod()) { 48 methodKind = ir::MethodDefinitionKind::EXTENSION_METHOD; 49 } else { 50 methodKind = ir::MethodDefinitionKind::METHOD; 51 } 52 auto *method = util::NodeAllocator::ForceSetParent<ir::MethodDefinition>( 53 allocator_, methodKind, funcDecl->Function()->Id()->Clone(allocator_, nullptr), funcExpr, 54 funcDecl->Function()->Modifiers(), allocator_, false); 55 method->SetRange(funcDecl->Range()); 56 57 if (funcDecl->Function()->IsExported() && funcDecl->Function()->HasExportAlias()) { 58 method->AddAstNodeFlags(ir::AstNodeFlags::HAS_EXPORT_ALIAS); 59 } 60 61 result_.classProperties.emplace_back(method); 62} 63 64void GlobalDeclTransformer::VisitVariableDeclaration(ir::VariableDeclaration *varDecl) 65{ 66 for (auto declarator : varDecl->Declarators()) { 67 auto id = declarator->Id()->AsIdentifier(); 68 auto typeAnn = id->TypeAnnotation(); 69 id->SetTsTypeAnnotation(nullptr); 70 auto *field = util::NodeAllocator::ForceSetParent<ir::ClassProperty>(allocator_, id->Clone(allocator_, nullptr), 71 declarator->Init(), typeAnn, 72 varDecl->Modifiers(), allocator_, false); 73 field->SetRange(declarator->Range()); 74 75 if (varDecl->IsExported() && varDecl->HasExportAlias()) { 76 field->AddAstNodeFlags(ir::AstNodeFlags::HAS_EXPORT_ALIAS); 77 } 78 79 result_.classProperties.emplace_back(field); 80 if (auto stmt = InitTopLevelProperty(field); stmt != nullptr) { 81 result_.initStatements.emplace_back(stmt); 82 } 83 } 84} 85 86ir::Identifier *GlobalDeclTransformer::RefIdent(const util::StringView &name) 87{ 88 auto *const callee = util::NodeAllocator::Alloc<ir::Identifier>(allocator_, name, allocator_); 89 callee->SetReference(); 90 return callee; 91} 92 93ir::ExpressionStatement *GlobalDeclTransformer::InitTopLevelProperty(ir::ClassProperty *classProperty) 94{ 95 ir::ExpressionStatement *initStmt = nullptr; 96 const auto initializer = classProperty->Value(); 97 if (addInitializer_ && !classProperty->IsConst() && initializer != nullptr) { 98 auto *ident = RefIdent(classProperty->Id()->Name()); 99 ident->SetRange(classProperty->Id()->Range()); 100 101 initializer->SetParent(nullptr); 102 auto *assignmentExpression = util::NodeAllocator::Alloc<ir::AssignmentExpression>( 103 allocator_, ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); 104 assignmentExpression->SetRange({ident->Start(), initializer->End()}); 105 assignmentExpression->SetTsType(initializer->TsType()); 106 107 auto expressionStatement = 108 util::NodeAllocator::Alloc<ir::ExpressionStatement>(allocator_, assignmentExpression); 109 expressionStatement->SetRange(classProperty->Range()); 110 111 classProperty->SetRange({ident->Start(), initializer->End()}); 112 113 if (classProperty->TypeAnnotation() != nullptr) { 114 classProperty->SetValue(nullptr); 115 } else { 116 // Code will be ignored, but checker is going to deduce the type. 117 classProperty->SetValue(initializer->Clone(allocator_, classProperty)->AsExpression()); 118 } 119 initStmt = expressionStatement; 120 } else { 121 classProperty->SetStart(classProperty->Id()->Start()); 122 } 123 return initStmt; 124} 125 126void GlobalDeclTransformer::HandleNode(ir::AstNode *node) 127{ 128 ASSERT(node->IsStatement()); 129 if (typeDecl_.count(node->Type()) == 0U) { 130 ASSERT(!propertiesDecl_.count(node->Type())); 131 result_.initStatements.emplace_back(node->AsStatement()); 132 } 133} 134 135} // namespace ark::es2panda::compiler 136