• 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 ||
24                (node->IsExportNamedDeclaration() && !node->AsExportNamedDeclaration()->Specifiers().empty());
25     };
26     stmts.erase(std::remove_if(stmts.begin(), stmts.end(), isDeclCb), stmts.end());
27 }
28 
TransformStatements(const ArenaVector<ir::Statement * > & stmts,bool addInitializer)29 GlobalDeclTransformer::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 
VisitFunctionDeclaration(ir::FunctionDeclaration * funcDecl)41 void 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 
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     callee->SetReference();
90     return callee;
91 }
92 
InitTopLevelProperty(ir::ClassProperty * classProperty)93 ir::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 
HandleNode(ir::AstNode * node)126 void 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