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 "ETSchecker.h"
17
18 #include "es2panda.h"
19 #include "ir/base/classDefinition.h"
20 #include "ir/expression.h"
21 #include "ir/expressions/callExpression.h"
22 #include "ir/ts/tsInterfaceDeclaration.h"
23 #include "ir/statements/blockStatement.h"
24 #include "varbinder/ETSBinder.h"
25 #include "parser/program/program.h"
26 #include "checker/ets/aliveAnalyzer.h"
27
28 #include "ir/base/scriptFunction.h"
29 #include "util/helpers.h"
30
31 namespace panda::es2panda::checker {
InitializeBuiltins(varbinder::ETSBinder * varbinder)32 void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder)
33 {
34 if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) {
35 return;
36 }
37
38 const auto varMap = varbinder->TopScope()->Bindings();
39
40 auto initBuiltin = [varMap](ETSChecker *checker, std::string_view signature) -> util::StringView {
41 const auto iterator = varMap.find(signature);
42 ASSERT(iterator != varMap.end());
43 checker->GetGlobalTypesHolder()->InitializeBuiltin(
44 iterator->first,
45 checker->BuildClassProperties(iterator->second->Declaration()->Node()->AsClassDefinition()));
46 return iterator->first;
47 };
48
49 auto const objectName = initBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS);
50 auto const voidName = initBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS);
51
52 for (const auto &[name, var] : varMap) {
53 if (name == objectName || name == voidName) {
54 continue;
55 }
56
57 if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) {
58 InitializeBuiltin(var, name);
59 }
60 }
61
62 AddStatus(CheckerStatus::BUILTINS_INITIALIZED);
63 }
64
InitializeBuiltin(varbinder::Variable * var,const util::StringView & name)65 void ETSChecker::InitializeBuiltin(varbinder::Variable *var, const util::StringView &name)
66 {
67 Type *type {nullptr};
68 if (var->Declaration()->Node()->IsClassDefinition()) {
69 type = BuildClassProperties(var->Declaration()->Node()->AsClassDefinition());
70 } else {
71 ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration());
72 type = BuildInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration());
73 }
74 GetGlobalTypesHolder()->InitializeBuiltin(name, type);
75 }
76
StartChecker(varbinder::VarBinder * varbinder,const CompilerOptions & options)77 bool ETSChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const CompilerOptions &options)
78 {
79 Initialize(varbinder);
80
81 if (options.dumpAst) {
82 std::cout << Program()->Dump() << std::endl;
83 }
84
85 if (options.opDumpAstOnlySilent) {
86 Program()->DumpSilent();
87 return false;
88 }
89
90 if (options.parseOnly) {
91 return false;
92 }
93
94 varbinder->SetGenStdLib(options.compilationMode == CompilationMode::GEN_STD_LIB);
95 varbinder->IdentifierAnalysis();
96
97 auto *etsBinder = varbinder->AsETSBinder();
98 InitializeBuiltins(etsBinder);
99
100 for (auto &entry : etsBinder->DynamicImportVars()) {
101 auto &data = entry.second;
102 if (data.import->IsPureDynamic()) {
103 data.variable->SetTsType(GlobalBuiltinDynamicType(data.import->Language()));
104 }
105 }
106
107 CheckProgram(Program(), true);
108
109 BuildDynamicCallClass(true);
110 BuildDynamicCallClass(false);
111
112 BuildDynamicImportClass();
113
114 #ifndef NDEBUG
115 for (auto lambda : etsBinder->LambdaObjects()) {
116 ASSERT(!lambda.second.first->TsType()->AsETSObjectType()->AssemblerName().Empty());
117 }
118 for (auto *func : varbinder->Functions()) {
119 ASSERT(!func->Node()->AsScriptFunction()->Scope()->InternalName().Empty());
120 }
121 #endif
122
123 if (options.dumpCheckedAst) {
124 std::cout << Program()->Dump() << std::endl;
125 }
126
127 return true;
128 }
129
CheckProgram(parser::Program * program,bool runAnalysis)130 void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis)
131 {
132 auto *savedProgram = Program();
133 SetProgram(program);
134
135 for (auto &[_, extPrograms] : program->ExternalSources()) {
136 (void)_;
137 for (auto *extProg : extPrograms) {
138 CheckProgram(extProg);
139 }
140 }
141
142 ASSERT(Program()->Ast()->IsProgram());
143 Program()->Ast()->Check(this);
144
145 if (runAnalysis) {
146 AliveAnalyzer(Program()->Ast(), this);
147 }
148
149 ASSERT(VarBinder()->AsETSBinder()->GetExternalRecordTable().find(program)->second);
150
151 SetProgram(savedProgram);
152 }
153
CheckTypeCached(ir::Expression * expr)154 Type *ETSChecker::CheckTypeCached(ir::Expression *expr)
155 {
156 if (expr->TsType() == nullptr) {
157 expr->SetTsType(expr->Check(this));
158 }
159
160 return expr->TsType();
161 }
162
AsETSObjectType(Type * (GlobalTypesHolder::* typeFunctor)()) const163 ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const
164 {
165 auto *ret = (GetGlobalTypesHolder()->*typeFunctor)();
166 return ret != nullptr ? ret->AsETSObjectType() : nullptr;
167 }
168
GlobalByteType() const169 Type *ETSChecker::GlobalByteType() const
170 {
171 return GetGlobalTypesHolder()->GlobalByteType();
172 }
173
GlobalShortType() const174 Type *ETSChecker::GlobalShortType() const
175 {
176 return GetGlobalTypesHolder()->GlobalShortType();
177 }
178
GlobalIntType() const179 Type *ETSChecker::GlobalIntType() const
180 {
181 return GetGlobalTypesHolder()->GlobalIntType();
182 }
183
GlobalLongType() const184 Type *ETSChecker::GlobalLongType() const
185 {
186 return GetGlobalTypesHolder()->GlobalLongType();
187 }
188
GlobalFloatType() const189 Type *ETSChecker::GlobalFloatType() const
190 {
191 return GetGlobalTypesHolder()->GlobalFloatType();
192 }
193
GlobalDoubleType() const194 Type *ETSChecker::GlobalDoubleType() const
195 {
196 return GetGlobalTypesHolder()->GlobalDoubleType();
197 }
198
GlobalCharType() const199 Type *ETSChecker::GlobalCharType() const
200 {
201 return GetGlobalTypesHolder()->GlobalCharType();
202 }
203
GlobalETSBooleanType() const204 Type *ETSChecker::GlobalETSBooleanType() const
205 {
206 return GetGlobalTypesHolder()->GlobalETSBooleanType();
207 }
208
GlobalVoidType() const209 Type *ETSChecker::GlobalVoidType() const
210 {
211 return GetGlobalTypesHolder()->GlobalETSVoidType();
212 }
213
GlobalETSNullType() const214 Type *ETSChecker::GlobalETSNullType() const
215 {
216 return GetGlobalTypesHolder()->GlobalETSNullType();
217 }
218
GlobalETSUndefinedType() const219 Type *ETSChecker::GlobalETSUndefinedType() const
220 {
221 return GetGlobalTypesHolder()->GlobalETSUndefinedType();
222 }
223
GlobalETSStringLiteralType() const224 Type *ETSChecker::GlobalETSStringLiteralType() const
225 {
226 return GetGlobalTypesHolder()->GlobalETSStringLiteralType();
227 }
228
GlobalETSBigIntType() const229 Type *ETSChecker::GlobalETSBigIntType() const
230 {
231 return GetGlobalTypesHolder()->GlobalETSBigIntBuiltinType();
232 }
233
GlobalWildcardType() const234 Type *ETSChecker::GlobalWildcardType() const
235 {
236 return GetGlobalTypesHolder()->GlobalWildcardType();
237 }
238
GlobalETSObjectType() const239 ETSObjectType *ETSChecker::GlobalETSObjectType() const
240 {
241 return AsETSObjectType(&GlobalTypesHolder::GlobalETSObjectType);
242 }
243
GlobalETSNullishObjectType() const244 ETSObjectType *ETSChecker::GlobalETSNullishObjectType() const
245 {
246 return AsETSObjectType(&GlobalTypesHolder::GlobalETSNullishObjectType);
247 }
248
GlobalBuiltinETSStringType() const249 ETSObjectType *ETSChecker::GlobalBuiltinETSStringType() const
250 {
251 return AsETSObjectType(&GlobalTypesHolder::GlobalETSStringBuiltinType);
252 }
253
GlobalBuiltinETSBigIntType() const254 ETSObjectType *ETSChecker::GlobalBuiltinETSBigIntType() const
255 {
256 return AsETSObjectType(&GlobalTypesHolder::GlobalETSBigIntBuiltinType);
257 }
258
GlobalBuiltinTypeType() const259 ETSObjectType *ETSChecker::GlobalBuiltinTypeType() const
260 {
261 return AsETSObjectType(&GlobalTypesHolder::GlobalTypeBuiltinType);
262 }
263
GlobalBuiltinExceptionType() const264 ETSObjectType *ETSChecker::GlobalBuiltinExceptionType() const
265 {
266 return AsETSObjectType(&GlobalTypesHolder::GlobalExceptionBuiltinType);
267 }
268
GlobalBuiltinErrorType() const269 ETSObjectType *ETSChecker::GlobalBuiltinErrorType() const
270 {
271 return AsETSObjectType(&GlobalTypesHolder::GlobalErrorBuiltinType);
272 }
273
GlobalStringBuilderBuiltinType() const274 ETSObjectType *ETSChecker::GlobalStringBuilderBuiltinType() const
275 {
276 return AsETSObjectType(&GlobalTypesHolder::GlobalStringBuilderBuiltinType);
277 }
278
GlobalBuiltinPromiseType() const279 ETSObjectType *ETSChecker::GlobalBuiltinPromiseType() const
280 {
281 return AsETSObjectType(&GlobalTypesHolder::GlobalPromiseBuiltinType);
282 }
283
GlobalBuiltinJSRuntimeType() const284 ETSObjectType *ETSChecker::GlobalBuiltinJSRuntimeType() const
285 {
286 return AsETSObjectType(&GlobalTypesHolder::GlobalJSRuntimeBuiltinType);
287 }
288
GlobalBuiltinJSValueType() const289 ETSObjectType *ETSChecker::GlobalBuiltinJSValueType() const
290 {
291 return AsETSObjectType(&GlobalTypesHolder::GlobalJSValueBuiltinType);
292 }
293
GlobalBuiltinVoidType() const294 ETSObjectType *ETSChecker::GlobalBuiltinVoidType() const
295 {
296 return AsETSObjectType(&GlobalTypesHolder::GlobalBuiltinVoidType);
297 }
298
GlobalBuiltinDynamicType(Language lang) const299 ETSObjectType *ETSChecker::GlobalBuiltinDynamicType(Language lang) const
300 {
301 if (lang.GetId() == Language::Id::JS) {
302 return GlobalBuiltinJSValueType();
303 }
304 return nullptr;
305 }
306
GlobalBuiltinBoxType(const Type * contents) const307 ETSObjectType *ETSChecker::GlobalBuiltinBoxType(const Type *contents) const
308 {
309 switch (TypeKind(contents)) {
310 case TypeFlag::ETS_BOOLEAN:
311 return AsETSObjectType(&GlobalTypesHolder::GlobalBooleanBoxBuiltinType);
312 case TypeFlag::BYTE:
313 return AsETSObjectType(&GlobalTypesHolder::GlobalByteBoxBuiltinType);
314 case TypeFlag::CHAR:
315 return AsETSObjectType(&GlobalTypesHolder::GlobalCharBoxBuiltinType);
316 case TypeFlag::SHORT:
317 return AsETSObjectType(&GlobalTypesHolder::GlobalShortBoxBuiltinType);
318 case TypeFlag::INT:
319 return AsETSObjectType(&GlobalTypesHolder::GlobalIntBoxBuiltinType);
320 case TypeFlag::LONG:
321 return AsETSObjectType(&GlobalTypesHolder::GlobalLongBoxBuiltinType);
322 case TypeFlag::FLOAT:
323 return AsETSObjectType(&GlobalTypesHolder::GlobalFloatBoxBuiltinType);
324 case TypeFlag::DOUBLE:
325 return AsETSObjectType(&GlobalTypesHolder::GlobalDoubleBoxBuiltinType);
326 default:
327 return AsETSObjectType(&GlobalTypesHolder::GlobalBoxBuiltinType);
328 }
329 }
330
PrimitiveWrapper() const331 const checker::WrapperDesc &ETSChecker::PrimitiveWrapper() const
332 {
333 return primitiveWrappers_.Wrappers();
334 }
335
GlobalArrayTypes()336 GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes()
337 {
338 return globalArraySignatures_;
339 }
340
GlobalArrayTypes() const341 const GlobalArraySignatureMap &ETSChecker::GlobalArrayTypes() const
342 {
343 return globalArraySignatures_;
344 }
345
346 // For use in Signature::ToAssemblerType
MaybeBoxedType(Checker * checker,const varbinder::Variable * var)347 const Type *MaybeBoxedType(Checker *checker, const varbinder::Variable *var)
348 {
349 return checker->AsETSChecker()->MaybeBoxedType(var);
350 }
351
HandleUpdatedCallExpressionNode(ir::CallExpression * callExpr)352 void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr)
353 {
354 VarBinder()->AsETSBinder()->HandleCustomNodes(callExpr);
355 }
356
SelectGlobalIntegerTypeForNumeric(Type * type)357 Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type)
358 {
359 switch (ETSType(type)) {
360 case checker::TypeFlag::FLOAT: {
361 return GlobalIntType();
362 }
363 case checker::TypeFlag::DOUBLE: {
364 return GlobalLongType();
365 }
366 default: {
367 return type;
368 }
369 }
370 }
371
372 } // namespace panda::es2panda::checker
373