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