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