1 /*
2 * Copyright (c) 2021-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 "ETSfunction.h"
17
18 #include "varbinder/varbinder.h"
19 #include "varbinder/ETSBinder.h"
20 #include "util/helpers.h"
21 #include "varbinder/scope.h"
22 #include "varbinder/variable.h"
23 #include "compiler/base/lreference.h"
24 #include "compiler/core/ETSGen.h"
25 #include "compiler/core/envScope.h"
26 #include "ir/base/spreadElement.h"
27 #include "ir/base/scriptFunction.h"
28 #include "ir/base/classDefinition.h"
29 #include "ir/base/classProperty.h"
30 #include "ir/ets/etsParameterExpression.h"
31 #include "ir/expressions/identifier.h"
32 #include "ir/statements/blockStatement.h"
33 #include "ir/ts/tsEnumDeclaration.h"
34 #include "ir/ts/tsEnumMember.h"
35 #include "checker/types/ets/types.h"
36
37 namespace ark::es2panda::compiler {
CallImplicitCtor(ETSGen * etsg)38 void ETSFunction::CallImplicitCtor(ETSGen *etsg)
39 {
40 RegScope rs(etsg);
41 auto *superType = etsg->ContainingObjectType()->SuperType();
42
43 if (superType == nullptr) {
44 etsg->CallExact(etsg->RootNode(), Signatures::BUILTIN_OBJECT_CTOR, etsg->GetThisReg());
45
46 return;
47 }
48
49 auto res = std::find_if(superType->ConstructSignatures().cbegin(), superType->ConstructSignatures().cend(),
50 [](const checker::Signature *sig) { return sig->Params().empty(); });
51 if (res == superType->ConstructSignatures().cend()) {
52 return;
53 }
54
55 etsg->CallExact(etsg->RootNode(), (*res)->InternalName(), etsg->GetThisReg());
56 }
57
CompileSourceBlock(ETSGen * etsg,const ir::BlockStatement * block)58 void ETSFunction::CompileSourceBlock(ETSGen *etsg, const ir::BlockStatement *block)
59 {
60 auto *scriptFunc = etsg->RootNode()->AsScriptFunction();
61
62 if (scriptFunc->IsEnum()) {
63 // NOTE: add enum methods
64 } else if (scriptFunc->IsStaticBlock()) {
65 CompileAsStaticBlock(etsg);
66 } else if (scriptFunc->IsConstructor()) {
67 CompileAsConstructor(etsg, scriptFunc);
68 }
69
70 const auto &statements = block->Statements();
71
72 if (statements.empty()) {
73 etsg->SetFirstStmt(block);
74 ExtendWithDefaultReturn(etsg, block, scriptFunc);
75 return;
76 }
77
78 etsg->SetFirstStmt(statements.front());
79
80 etsg->CompileStatements(statements);
81
82 if (!statements.back()->IsReturnStatement()) {
83 ExtendWithDefaultReturn(etsg, statements.back(), scriptFunc);
84 }
85 }
86
ExtendWithDefaultReturn(ETSGen * etsg,const ir::AstNode * node,const ir::ScriptFunction * scriptFunc)87 void ETSFunction::ExtendWithDefaultReturn(ETSGen *etsg, const ir::AstNode *node, const ir::ScriptFunction *scriptFunc)
88 {
89 if (etsg->ReturnType()->IsETSVoidType()) {
90 etsg->EmitReturnVoid(node);
91 return;
92 }
93
94 if (scriptFunc->ReturnTypeAnnotation() != nullptr && scriptFunc->ReturnTypeAnnotation()->TsType() != nullptr &&
95 scriptFunc->ReturnTypeAnnotation()->TsType()->IsETSAsyncFuncReturnType()) {
96 etsg->LoadDefaultValue(node, scriptFunc->ReturnTypeAnnotation()->TsType());
97 } else {
98 etsg->LoadDefaultValue(node, scriptFunc->Signature()->ReturnType());
99 }
100 etsg->ReturnAcc(node);
101 }
102
CompileAsStaticBlock(ETSGen * etsg)103 void ETSFunction::CompileAsStaticBlock(ETSGen *etsg)
104 {
105 const auto *classDef = etsg->ContainingObjectType()->GetDeclNode()->AsClassDefinition();
106
107 auto const checkInitializer = [](ArenaVector<ir::AstNode *> const &nodes) -> bool {
108 for (auto const *const node : nodes) {
109 if (node->IsMethodDefinition() && node->AsClassElement()->Key()->IsIdentifier() &&
110 node->AsClassElement()->Id()->Name() == compiler::Signatures::INIT_METHOD) {
111 return false;
112 }
113 }
114 return true;
115 };
116
117 // Check if it is the Global class static constructor and the special '_$init$_" method exists
118 bool const compileInitializer = classDef->IsGlobal() ? checkInitializer(classDef->Body()) : true;
119
120 for (const auto *prop : classDef->Body()) {
121 if (!prop->IsClassProperty() || !prop->IsStatic()) {
122 continue;
123 }
124
125 // Don't compile variable initializers if they present in '_$init$_" method
126 auto *const item = prop->AsClassProperty();
127 if (item->Value() != nullptr &&
128 (compileInitializer || item->IsConst() || item->Value()->IsArrowFunctionExpression())) {
129 item->Compile(etsg);
130 }
131 }
132 }
133
CompileAsConstructor(ETSGen * etsg,const ir::ScriptFunction * scriptFunc)134 void ETSFunction::CompileAsConstructor(ETSGen *etsg, const ir::ScriptFunction *scriptFunc)
135 {
136 if (scriptFunc->IsImplicitSuperCallNeeded()) {
137 CallImplicitCtor(etsg);
138 }
139
140 const auto *classDef = etsg->ContainingObjectType()->GetDeclNode()->AsClassDefinition();
141
142 for (const auto *prop : classDef->Body()) {
143 if (prop->IsClassProperty() && !prop->IsStatic()) {
144 prop->AsClassProperty()->Compile(etsg);
145 }
146 }
147 }
148
CompileFunction(ETSGen * etsg)149 void ETSFunction::CompileFunction(ETSGen *etsg)
150 {
151 if (const auto *decl = etsg->RootNode()->AsScriptFunction(); !decl->IsDeclare() && !decl->IsExternal()) {
152 if (auto *const body = decl->Body(); body != nullptr && body->IsBlockStatement()) {
153 CompileSourceBlock(etsg, body->AsBlockStatement());
154 }
155 }
156 }
157
Compile(ETSGen * etsg)158 void ETSFunction::Compile(ETSGen *etsg)
159 {
160 FunctionRegScope lrs(etsg);
161 auto *topScope = etsg->TopScope();
162
163 if (topScope->IsFunctionScope()) {
164 CompileFunction(etsg);
165 } else {
166 ASSERT(topScope->IsGlobalScope());
167 CompileSourceBlock(etsg, etsg->RootNode()->AsBlockStatement());
168 }
169
170 etsg->SortCatchTables();
171 }
172
173 } // namespace ark::es2panda::compiler
174