• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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