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 <functional>
17 #include "checker/ETSchecker.h"
18
19 #include "checker/types/globalTypesHolder.h"
20 #include "checker/types/ets/byteType.h"
21 #include "checker/types/ets/charType.h"
22 #include "checker/types/ets/etsDynamicFunctionType.h"
23 #include "checker/types/ets/etsDynamicType.h"
24 #include "checker/types/ets/etsStringType.h"
25 #include "checker/types/ets/etsUnionType.h"
26 #include "checker/types/ets/shortType.h"
27 #include "compiler/lowering/ets/enumLowering.h"
28 #include "generated/signatures.h"
29 #include "ir/base/classDefinition.h"
30 #include "ir/statements/classDeclaration.h"
31 #include "ir/base/scriptFunction.h"
32 #include "ir/ets/etsScript.h"
33 #include "ir/expressions/identifier.h"
34 #include "ir/ts/tsEnumDeclaration.h"
35 #include "ir/ts/tsEnumMember.h"
36 #include "ir/ts/tsInterfaceDeclaration.h"
37 #include "checker/ets/boxingConverter.h"
38 #include "util/helpers.h"
39 #include "checker/types/ts/bigintType.h"
40
41 namespace ark::es2panda::checker {
CreateByteType(int8_t value)42 ByteType *ETSChecker::CreateByteType(int8_t value)
43 {
44 return Allocator()->New<ByteType>(value);
45 }
46
CreateETSBooleanType(bool value)47 ETSBooleanType *ETSChecker::CreateETSBooleanType(bool value)
48 {
49 return Allocator()->New<ETSBooleanType>(value);
50 }
51
CreateDoubleType(double value)52 DoubleType *ETSChecker::CreateDoubleType(double value)
53 {
54 return Allocator()->New<DoubleType>(value);
55 }
56
CreateFloatType(float value)57 FloatType *ETSChecker::CreateFloatType(float value)
58 {
59 return Allocator()->New<FloatType>(value);
60 }
61
CreateIntType(int32_t value)62 IntType *ETSChecker::CreateIntType(int32_t value)
63 {
64 return Allocator()->New<IntType>(value);
65 }
66
CreateIntTypeFromType(Type * type)67 IntType *ETSChecker::CreateIntTypeFromType(Type *type)
68 {
69 if (!type->HasTypeFlag(TypeFlag::CONSTANT)) {
70 return GlobalIntType()->AsIntType();
71 }
72
73 if (type->IsIntType()) {
74 return type->AsIntType();
75 }
76
77 switch (ETSType(type)) {
78 case TypeFlag::CHAR: {
79 return CreateIntType(static_cast<int32_t>(type->AsCharType()->GetValue()));
80 }
81 case TypeFlag::BYTE: {
82 return CreateIntType(static_cast<int32_t>(type->AsByteType()->GetValue()));
83 }
84 case TypeFlag::SHORT: {
85 return CreateIntType(static_cast<int32_t>(type->AsShortType()->GetValue()));
86 }
87 default: {
88 return nullptr;
89 }
90 }
91 }
92
CreateLongType(int64_t value)93 LongType *ETSChecker::CreateLongType(int64_t value)
94 {
95 return Allocator()->New<LongType>(value);
96 }
97
CreateShortType(int16_t value)98 ShortType *ETSChecker::CreateShortType(int16_t value)
99 {
100 return Allocator()->New<ShortType>(value);
101 }
102
CreateCharType(char16_t value)103 CharType *ETSChecker::CreateCharType(char16_t value)
104 {
105 return Allocator()->New<CharType>(value);
106 }
107
CreateETSBigIntLiteralType(util::StringView value)108 ETSBigIntType *ETSChecker::CreateETSBigIntLiteralType(util::StringView value)
109 {
110 return Allocator()->New<ETSBigIntType>(Allocator(), GlobalBuiltinETSBigIntType(), Relation(), value);
111 }
112
CreateETSStringLiteralType(util::StringView value)113 ETSStringType *ETSChecker::CreateETSStringLiteralType(util::StringView value)
114 {
115 return Allocator()->New<ETSStringType>(Allocator(), GlobalBuiltinETSStringType(), Relation(), value);
116 }
117
CreateETSArrayType(Type * elementType)118 ETSArrayType *ETSChecker::CreateETSArrayType(Type *elementType)
119 {
120 auto res = arrayTypes_.find(elementType);
121 if (res != arrayTypes_.end()) {
122 return res->second;
123 }
124
125 auto *arrayType = Allocator()->New<ETSArrayType>(elementType);
126
127 std::stringstream ss;
128 arrayType->ToAssemblerTypeWithRank(ss);
129 arrayType->SetAssemblerName(util::UString(ss.str(), Allocator()).View());
130
131 auto it = arrayTypes_.insert({elementType, arrayType});
132 if (it.second && (!elementType->IsTypeParameter() || !elementType->IsETSTypeParameter())) {
133 CreateBuiltinArraySignature(arrayType, arrayType->Rank());
134 }
135
136 return arrayType;
137 }
138
139 namespace {
MakeProxyFunctionType(checker::ETSChecker * const checker,const util::StringView & name,const std::initializer_list<varbinder::LocalVariable * > & params,ir::ScriptFunction * const globalFunction,checker::Type * const returnType)140 [[nodiscard]] checker::ETSFunctionType *MakeProxyFunctionType(
141 checker::ETSChecker *const checker, const util::StringView &name,
142 const std::initializer_list<varbinder::LocalVariable *> ¶ms, ir::ScriptFunction *const globalFunction,
143 checker::Type *const returnType)
144 {
145 auto *const signatureInfo = checker->CreateSignatureInfo();
146 signatureInfo->params.insert(signatureInfo->params.end(), params);
147 signatureInfo->minArgCount = signatureInfo->params.size();
148
149 auto *const signature = checker->CreateSignature(signatureInfo, returnType, name);
150 signature->SetFunction(globalFunction);
151 signature->AddSignatureFlag(checker::SignatureFlags::PROXY);
152
153 return checker->CreateETSFunctionType(signature, name);
154 }
155
MakeGlobalSignature(checker::ETSChecker * const checker,ir::ScriptFunction * const function,checker::Type * const returnType)156 [[nodiscard]] checker::Signature *MakeGlobalSignature(checker::ETSChecker *const checker,
157 ir::ScriptFunction *const function,
158 checker::Type *const returnType)
159 {
160 auto *const signatureInfo = checker->CreateSignatureInfo();
161 signatureInfo->params.reserve(function->Params().size());
162 for (const auto *const param : function->Params()) {
163 signatureInfo->params.push_back(param->AsETSParameterExpression()->Variable()->AsLocalVariable());
164 }
165 signatureInfo->minArgCount = signatureInfo->params.size();
166
167 auto *const signature = checker->CreateSignature(signatureInfo, returnType, function);
168 signature->AddSignatureFlag(checker::SignatureFlags::PUBLIC | checker::SignatureFlags::STATIC);
169 function->SetSignature(signature);
170
171 return signature;
172 }
173
SetTypesForScriptFunction(checker::ETSChecker * const checker,ir::ScriptFunction * function)174 void SetTypesForScriptFunction(checker::ETSChecker *const checker, ir::ScriptFunction *function)
175 {
176 for (auto param : function->Params()) {
177 ASSERT(param->IsETSParameterExpression());
178 auto paramType = param->AsETSParameterExpression()->TypeAnnotation()->Check(checker);
179 param->AsETSParameterExpression()->Ident()->SetTsType(paramType);
180 param->AsETSParameterExpression()->Ident()->Variable()->SetTsType(paramType);
181 param->SetTsType(paramType);
182 }
183 }
184
185 } // namespace
186
MakeMethod(ir::TSEnumDeclaration const * const enumDecl,const std::string_view & name,bool buildPorxyParam,Type * returnType,bool buildProxy)187 ETSEnumType::Method ETSChecker::MakeMethod(ir::TSEnumDeclaration const *const enumDecl, const std::string_view &name,
188 bool buildPorxyParam, Type *returnType, bool buildProxy)
189 {
190 auto function = FindFunction(enumDecl, name);
191 if (function == nullptr) {
192 return {};
193 }
194
195 SetTypesForScriptFunction(this, function);
196
197 if (buildPorxyParam) {
198 return {MakeGlobalSignature(this, function, returnType),
199 MakeProxyFunctionType(
200 this, name, {function->Params()[0]->AsETSParameterExpression()->Variable()->AsLocalVariable()},
201 function, returnType)};
202 }
203 return {MakeGlobalSignature(this, function, returnType),
204 buildProxy ? MakeProxyFunctionType(this, name, {}, function, returnType) : nullptr};
205 }
206
FindFunction(ir::TSEnumDeclaration const * const enumDecl,const std::string_view & name)207 [[nodiscard]] ir::ScriptFunction *ETSChecker::FindFunction(ir::TSEnumDeclaration const *const enumDecl,
208 const std::string_view &name)
209 {
210 if (enumDecl->BoxedClass() == nullptr) {
211 return nullptr;
212 }
213
214 for (auto m : enumDecl->BoxedClass()->Body()) {
215 if (m->IsMethodDefinition()) {
216 if (m->AsMethodDefinition()->Id()->Name() == name) {
217 return m->AsMethodDefinition()->Function();
218 }
219 }
220 }
221 return nullptr;
222 }
223
224 template <typename EnumType>
CreateEnumTypeFromEnumDeclaration(ir::TSEnumDeclaration const * const enumDecl)225 EnumType *ETSChecker::CreateEnumTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl)
226 {
227 static_assert(std::is_same_v<EnumType, ETSIntEnumType> || std::is_same_v<EnumType, ETSStringEnumType>);
228 SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass(),
229 Context().ContainingSignature());
230
231 varbinder::Variable *enumVar = enumDecl->Key()->Variable();
232 ASSERT(enumVar != nullptr);
233
234 checker::ETSEnumType::UType ordinal = -1;
235 auto *const enumType = Allocator()->New<EnumType>(enumDecl, ordinal++);
236 auto *const boxedEnumType = enumDecl->BoxedClass()->TsType();
237
238 enumType->SetVariable(enumVar);
239 enumVar->SetTsType(enumType);
240
241 auto const getNameMethod =
242 MakeMethod(enumDecl, ETSEnumType::GET_NAME_METHOD_NAME, false, GlobalETSStringLiteralType());
243 enumType->SetGetNameMethod(getNameMethod);
244
245 auto getValueOfMethod = MakeMethod(enumDecl, ETSEnumType::GET_VALUE_OF_METHOD_NAME, true, enumType);
246 enumType->SetGetValueOfMethod(getValueOfMethod);
247
248 auto const fromIntMethod = MakeMethod(enumDecl, ETSEnumType::FROM_INT_METHOD_NAME, false, enumType, false);
249 enumType->SetFromIntMethod(fromIntMethod);
250
251 auto const boxedFromIntMethod =
252 MakeMethod(enumDecl, ETSEnumType::BOXED_FROM_INT_METHOD_NAME, false, boxedEnumType, false);
253 enumType->SetBoxedFromIntMethod(boxedFromIntMethod);
254
255 auto const unboxMethod = MakeMethod(enumDecl, ETSEnumType::UNBOX_METHOD_NAME, false, enumType, false);
256 enumType->SetUnboxMethod(unboxMethod);
257
258 auto const toStringMethod =
259 MakeMethod(enumDecl, ETSEnumType::TO_STRING_METHOD_NAME, false, GlobalETSStringLiteralType());
260 enumType->SetToStringMethod(toStringMethod);
261
262 ETSEnumType::Method valueOfMethod = toStringMethod;
263 if (std::is_same_v<EnumType, ETSIntEnumType>) {
264 valueOfMethod = MakeMethod(enumDecl, ETSEnumType::VALUE_OF_METHOD_NAME, false, GlobalIntType());
265 }
266 enumType->SetValueOfMethod(valueOfMethod);
267
268 auto const valuesMethod =
269 MakeMethod(enumDecl, ETSEnumType::VALUES_METHOD_NAME, false, CreateETSArrayType(enumType));
270 enumType->SetValuesMethod(valuesMethod);
271
272 for (auto *const member : enumType->GetMembers()) {
273 auto *const memberVar = member->AsTSEnumMember()->Key()->AsIdentifier()->Variable();
274 auto *const enumLiteralType = Allocator()->New<EnumType>(enumDecl, ordinal++, member->AsTSEnumMember());
275 enumLiteralType->SetVariable(memberVar);
276 memberVar->SetTsType(enumLiteralType);
277
278 enumLiteralType->SetGetNameMethod(getNameMethod);
279 enumLiteralType->SetGetValueOfMethod(getValueOfMethod);
280 enumLiteralType->SetFromIntMethod(fromIntMethod);
281 enumLiteralType->SetBoxedFromIntMethod(boxedFromIntMethod);
282 enumLiteralType->SetUnboxMethod(unboxMethod);
283 enumLiteralType->SetValueOfMethod(valueOfMethod);
284 enumLiteralType->SetToStringMethod(toStringMethod);
285 enumLiteralType->SetValuesMethod(valuesMethod);
286 }
287 return enumType;
288 }
289
CreateEnumIntTypeFromEnumDeclaration(ir::TSEnumDeclaration const * const enumDecl)290 ETSIntEnumType *ETSChecker::CreateEnumIntTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl)
291 {
292 return CreateEnumTypeFromEnumDeclaration<ETSIntEnumType>(enumDecl);
293 }
294
CreateEnumStringTypeFromEnumDeclaration(ir::TSEnumDeclaration const * const enumDecl)295 ETSStringEnumType *ETSChecker::CreateEnumStringTypeFromEnumDeclaration(ir::TSEnumDeclaration const *const enumDecl)
296 {
297 return CreateEnumTypeFromEnumDeclaration<ETSStringEnumType>(enumDecl);
298 }
299
CreateETSUnionType(Span<Type * const> constituentTypes)300 Type *ETSChecker::CreateETSUnionType(Span<Type *const> constituentTypes)
301 {
302 if (constituentTypes.empty()) {
303 return nullptr;
304 }
305
306 ArenaVector<Type *> newConstituentTypes(Allocator()->Adapter());
307 newConstituentTypes.assign(constituentTypes.begin(), constituentTypes.end());
308
309 ETSUnionType::NormalizeTypes(Relation(), newConstituentTypes);
310 if (newConstituentTypes.size() == 1) {
311 return newConstituentTypes[0];
312 }
313 return Allocator()->New<ETSUnionType>(this, std::move(newConstituentTypes));
314 }
315
CreateETSFunctionType(ArenaVector<Signature * > & signatures)316 ETSFunctionType *ETSChecker::CreateETSFunctionType(ArenaVector<Signature *> &signatures)
317 {
318 auto *funcType = Allocator()->New<ETSFunctionType>(signatures[0]->Function()->Id()->Name(), Allocator());
319
320 for (auto *it : signatures) {
321 funcType->AddCallSignature(it);
322 }
323
324 return funcType;
325 }
326
CreateETSFunctionType(Signature * signature)327 ETSFunctionType *ETSChecker::CreateETSFunctionType(Signature *signature)
328 {
329 return Allocator()->New<ETSFunctionType>(signature->Function()->Id()->Name(), signature, Allocator());
330 }
331
CreateETSFunctionType(Signature * signature,util::StringView name)332 ETSFunctionType *ETSChecker::CreateETSFunctionType(Signature *signature, util::StringView name)
333 {
334 return Allocator()->New<ETSFunctionType>(name, signature, Allocator());
335 }
336
CreateETSFunctionType(ir::ScriptFunction * func,Signature * signature,util::StringView name)337 ETSFunctionType *ETSChecker::CreateETSFunctionType(ir::ScriptFunction *func, Signature *signature,
338 util::StringView name)
339 {
340 if (func->IsDynamic()) {
341 return Allocator()->New<ETSDynamicFunctionType>(name, signature, Allocator(), func->Language());
342 }
343
344 return Allocator()->New<ETSFunctionType>(name, signature, Allocator());
345 }
346
CreateSignature(SignatureInfo * info,Type * returnType,ir::ScriptFunction * func)347 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunction *func)
348 {
349 return Allocator()->New<Signature>(info, returnType, func);
350 }
351
CreateSignature(SignatureInfo * info,Type * returnType,util::StringView internalName)352 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, util::StringView internalName)
353 {
354 return Allocator()->New<Signature>(info, returnType, internalName);
355 }
356
CreateSignatureInfo()357 SignatureInfo *ETSChecker::CreateSignatureInfo()
358 {
359 return Allocator()->New<SignatureInfo>(Allocator());
360 }
361
CreateTypeParameter()362 ETSTypeParameter *ETSChecker::CreateTypeParameter()
363 {
364 return Allocator()->New<ETSTypeParameter>();
365 }
366
CreateETSFunctionType(util::StringView name)367 ETSFunctionType *ETSChecker::CreateETSFunctionType(util::StringView name)
368 {
369 return Allocator()->New<ETSFunctionType>(name, Allocator());
370 }
371
CreateETSExtensionFuncHelperType(ETSFunctionType * classMethodType,ETSFunctionType * extensionFunctionType)372 ETSExtensionFuncHelperType *ETSChecker::CreateETSExtensionFuncHelperType(ETSFunctionType *classMethodType,
373 ETSFunctionType *extensionFunctionType)
374 {
375 return Allocator()->New<ETSExtensionFuncHelperType>(classMethodType, extensionFunctionType);
376 }
377
GetNameToTypeIdMap()378 std::map<util::StringView, GlobalTypeId> &GetNameToTypeIdMap()
379 {
380 static std::map<util::StringView, GlobalTypeId> nameToTypeId = {
381 {compiler::Signatures::BUILTIN_BIGINT_CLASS, GlobalTypeId::ETS_BIG_INT_BUILTIN},
382 {compiler::Signatures::BUILTIN_STRING_CLASS, GlobalTypeId::ETS_STRING_BUILTIN},
383 {compiler::Signatures::BUILTIN_OBJECT_CLASS, GlobalTypeId::ETS_OBJECT_BUILTIN},
384 {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, GlobalTypeId::ETS_EXCEPTION_BUILTIN},
385 {compiler::Signatures::BUILTIN_ERROR_CLASS, GlobalTypeId::ETS_ERROR_BUILTIN},
386 {compiler::Signatures::BUILTIN_TYPE_CLASS, GlobalTypeId::ETS_TYPE_BUILTIN},
387 {compiler::Signatures::BUILTIN_PROMISE_CLASS, GlobalTypeId::ETS_PROMISE_BUILTIN},
388 {compiler::Signatures::BUILTIN_BOX_CLASS, GlobalTypeId::ETS_BOX_BUILTIN},
389 {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, GlobalTypeId::ETS_BOOLEAN_BOX_BUILTIN},
390 {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, GlobalTypeId::ETS_BYTE_BOX_BUILTIN},
391 {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, GlobalTypeId::ETS_CHAR_BOX_BUILTIN},
392 {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, GlobalTypeId::ETS_SHORT_BOX_BUILTIN},
393 {compiler::Signatures::BUILTIN_INT_BOX_CLASS, GlobalTypeId::ETS_INT_BOX_BUILTIN},
394 {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, GlobalTypeId::ETS_LONG_BOX_BUILTIN},
395 {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, GlobalTypeId::ETS_FLOAT_BOX_BUILTIN},
396 {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, GlobalTypeId::ETS_DOUBLE_BOX_BUILTIN},
397 };
398
399 return nameToTypeId;
400 }
401
GetNameToGlobalTypeMap()402 std::map<util::StringView, std::function<ETSObjectType *(const ETSChecker *)>> &GetNameToGlobalTypeMap()
403 {
404 static std::map<util::StringView, std::function<ETSObjectType *(const ETSChecker *)>> nameToGlobalType = {
405 {compiler::Signatures::BUILTIN_BIGINT_CLASS, &ETSChecker::GlobalBuiltinETSBigIntType},
406 {compiler::Signatures::BUILTIN_STRING_CLASS, &ETSChecker::GlobalBuiltinETSStringType},
407 {compiler::Signatures::BUILTIN_OBJECT_CLASS, &ETSChecker::GlobalETSObjectType},
408 {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, &ETSChecker::GlobalBuiltinExceptionType},
409 {compiler::Signatures::BUILTIN_ERROR_CLASS, &ETSChecker::GlobalBuiltinErrorType},
410 {compiler::Signatures::BUILTIN_TYPE_CLASS, &ETSChecker::GlobalBuiltinTypeType},
411 {compiler::Signatures::BUILTIN_PROMISE_CLASS, &ETSChecker::GlobalBuiltinPromiseType},
412 };
413
414 return nameToGlobalType;
415 }
416
GetNameToGlobalBoxTypeMap()417 std::map<util::StringView, std::function<Type *(const ETSChecker *)>> &GetNameToGlobalBoxTypeMap()
418 {
419 static std::map<util::StringView, std::function<Type *(const ETSChecker *)>> nameToGlobalBoxType = {
420 {compiler::Signatures::BUILTIN_BOX_CLASS, &ETSChecker::GlobalETSObjectType},
421 {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, &ETSChecker::GlobalETSBooleanType},
422 {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, &ETSChecker::GlobalByteType},
423 {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, &ETSChecker::GlobalCharType},
424 {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, &ETSChecker::GlobalShortType},
425 {compiler::Signatures::BUILTIN_INT_BOX_CLASS, &ETSChecker::GlobalIntType},
426 {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, &ETSChecker::GlobalLongType},
427 {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, &ETSChecker::GlobalFloatType},
428 {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, &ETSChecker::GlobalDoubleType},
429 };
430
431 return nameToGlobalBoxType;
432 }
433
UpdateBoxedGlobalType(ETSObjectType * objType,util::StringView name)434 ETSObjectType *ETSChecker::UpdateBoxedGlobalType(ETSObjectType *objType, util::StringView name)
435 {
436 auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap();
437 auto nameToTypeId = GetNameToTypeIdMap();
438
439 if (nameToGlobalBoxType.find(name) != nameToGlobalBoxType.end()) {
440 std::function<Type *(const ETSChecker *)> globalType = nameToGlobalBoxType[name];
441 if (GlobalBuiltinBoxType(globalType(this)) != nullptr) {
442 return GlobalBuiltinBoxType(globalType(this));
443 }
444
445 auto id = nameToTypeId.find(name);
446 if (id != nameToTypeId.end()) {
447 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(id->second)] = objType;
448 }
449 }
450
451 return objType;
452 }
453
UpdateGlobalType(ETSObjectType * objType,util::StringView name)454 ETSObjectType *ETSChecker::UpdateGlobalType(ETSObjectType *objType, util::StringView name)
455 {
456 auto nameToGlobalType = GetNameToGlobalTypeMap();
457 auto nameToTypeId = GetNameToTypeIdMap();
458
459 if (nameToGlobalType.find(name) != nameToGlobalType.end()) {
460 std::function<ETSObjectType *(const ETSChecker *)> globalType = nameToGlobalType[name];
461 if (globalType(this) != nullptr) {
462 return globalType(this);
463 }
464
465 auto id = nameToTypeId.find(name);
466 if (id != nameToTypeId.end()) {
467 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(id->second)] = objType;
468 }
469
470 if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) {
471 auto *nullish = CreateETSUnionType({objType, GlobalETSNullType(), GlobalETSUndefinedType()});
472 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_NULLISH_OBJECT)] = nullish;
473 nullish = CreateETSUnionType({GlobalETSNullType(), GlobalETSUndefinedType()});
474 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_NULLISH_TYPE)] = nullish;
475 }
476 }
477
478 return objType;
479 }
480
CreateETSObjectTypeCheckBuiltins(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)481 ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode,
482 ETSObjectFlags flags)
483 {
484 if (name == compiler::Signatures::BUILTIN_BIGINT_CLASS) {
485 if (GlobalBuiltinETSBigIntType() != nullptr) {
486 return GlobalBuiltinETSBigIntType();
487 }
488
489 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_BIG_INT_BUILTIN)] =
490 CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_BIGINT);
491 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_BIG_INT)] =
492 Allocator()->New<ETSBigIntType>(Allocator(), GlobalBuiltinETSBigIntType());
493
494 return GlobalBuiltinETSBigIntType();
495 }
496
497 if (name == compiler::Signatures::BUILTIN_STRING_CLASS) {
498 if (GlobalBuiltinETSStringType() != nullptr) {
499 return GlobalBuiltinETSStringType();
500 }
501 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_STRING_BUILTIN)] =
502 CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_STRING | ETSObjectFlags::STRING);
503
504 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_STRING)] =
505 Allocator()->New<ETSStringType>(Allocator(), GlobalBuiltinETSStringType(), Relation());
506 return GlobalBuiltinETSStringType();
507 }
508
509 auto *objType = CreateNewETSObjectType(name, declNode, flags);
510 auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap();
511
512 return UpdateGlobalType(objType, name);
513 }
514
CreateETSObjectType(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)515 ETSObjectType *ETSChecker::CreateETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags)
516 {
517 auto res = primitiveWrappers_.Wrappers().find(name);
518 if (res == primitiveWrappers_.Wrappers().end()) {
519 return CreateETSObjectTypeCheckBuiltins(name, declNode, flags);
520 }
521
522 if (res->second.first != nullptr) {
523 return res->second.first;
524 }
525
526 auto *objType = CreateNewETSObjectType(name, declNode, flags | res->second.second);
527 primitiveWrappers_.Wrappers().at(name).first = objType;
528 return objType;
529 }
530
CheckForDynamicLang(ir::AstNode * declNode,util::StringView assemblerName)531 std::tuple<Language, bool> ETSChecker::CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName)
532 {
533 Language lang(Language::Id::ETS);
534 bool hasDecl = false;
535
536 if (declNode->IsClassDefinition()) {
537 auto *clsDef = declNode->AsClassDefinition();
538 lang = clsDef->Language();
539 hasDecl = clsDef->IsDeclare();
540 }
541
542 if (declNode->IsTSInterfaceDeclaration()) {
543 auto *ifaceDecl = declNode->AsTSInterfaceDeclaration();
544 lang = ifaceDecl->Language();
545 hasDecl = ifaceDecl->IsDeclare();
546 }
547
548 auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8());
549 if (res) {
550 lang = *res;
551 }
552
553 return std::make_tuple(lang, hasDecl);
554 }
555
CreateNewETSObjectType(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)556 ETSObjectType *ETSChecker::CreateNewETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags)
557 {
558 util::StringView assemblerName = name;
559 util::StringView prefix {};
560
561 auto *containingObjType = util::Helpers::GetContainingObjectType(declNode->Parent());
562
563 if (declNode->IsClassDefinition()) {
564 if (declNode->AsClassDefinition()->IsLocal()) {
565 util::UString localName(declNode->AsClassDefinition()->LocalPrefix(), Allocator());
566 localName.Append(name);
567 assemblerName = localName.View();
568 }
569 }
570
571 if (containingObjType != nullptr) {
572 prefix = containingObjType->AssemblerName();
573 } else if (const auto *topStatement = declNode->GetTopStatement();
574 topStatement->Type() !=
575 ir::AstNodeType::ETS_SCRIPT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION
576 ASSERT(declNode->IsTSInterfaceDeclaration());
577 assemblerName = declNode->AsTSInterfaceDeclaration()->InternalName();
578 } else {
579 auto program = static_cast<ir::ETSScript *>(declNode->GetTopStatement())->Program();
580 prefix = program->OmitModuleName() ? util::StringView() : program->ModuleName();
581 }
582
583 if (!prefix.Empty()) {
584 assemblerName =
585 util::UString(prefix.Mutf8() + compiler::Signatures::METHOD_SEPARATOR.data() + assemblerName.Mutf8(),
586 Allocator())
587 .View();
588 }
589
590 auto [lang, hasDecl] = CheckForDynamicLang(declNode, assemblerName);
591 if (lang.IsDynamic()) {
592 return Allocator()->New<ETSDynamicType>(Allocator(), std::make_tuple(name, assemblerName, lang),
593 std::make_tuple(declNode, flags, Relation()), hasDecl);
594 }
595
596 return Allocator()->New<ETSObjectType>(Allocator(), name, assemblerName,
597 std::make_tuple(declNode, flags, Relation()));
598 }
599
CreateBuiltinArraySignatureInfo(ETSArrayType * arrayType,size_t dim)600 std::tuple<util::StringView, SignatureInfo *> ETSChecker::CreateBuiltinArraySignatureInfo(ETSArrayType *arrayType,
601 size_t dim)
602 {
603 std::stringstream ss;
604 arrayType->ToAssemblerTypeWithRank(ss);
605 ss << compiler::Signatures::METHOD_SEPARATOR << compiler::Signatures::CTOR << compiler::Signatures::MANGLE_BEGIN;
606 arrayType->ToAssemblerTypeWithRank(ss);
607
608 auto *info = CreateSignatureInfo();
609 info->minArgCount = dim;
610
611 for (size_t i = 0; i < dim; i++) {
612 util::UString param(std::to_string(i), Allocator());
613 auto *paramVar =
614 varbinder::Scope::CreateVar(Allocator(), param.View(), varbinder::VariableFlags::NONE, nullptr);
615 paramVar->SetTsType(GlobalIntType());
616
617 info->params.push_back(paramVar);
618
619 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_INT;
620 }
621
622 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_VOID
623 << compiler::Signatures::MANGLE_SEPARATOR;
624 auto internalName = util::UString(ss.str(), Allocator()).View();
625
626 return {internalName, info};
627 }
628
CreateBuiltinArraySignature(ETSArrayType * arrayType,size_t dim)629 Signature *ETSChecker::CreateBuiltinArraySignature(ETSArrayType *arrayType, size_t dim)
630 {
631 auto res = globalArraySignatures_.find(arrayType);
632 if (res != globalArraySignatures_.end()) {
633 return res->second;
634 }
635
636 auto [internalName, info] = CreateBuiltinArraySignatureInfo(arrayType, dim);
637 auto *signature = CreateSignature(info, GlobalVoidType(), internalName);
638 globalArraySignatures_.insert({arrayType, signature});
639
640 return signature;
641 }
642
FunctionTypeToFunctionalInterfaceType(Signature * signature)643 ETSObjectType *ETSChecker::FunctionTypeToFunctionalInterfaceType(Signature *signature)
644 {
645 auto *retType = signature->ReturnType();
646 if (signature->RestVar() != nullptr) {
647 auto *functionN = GlobalBuiltinFunctionType(GlobalBuiltinFunctionTypeVariadicThreshold())->AsETSObjectType();
648 auto *substitution = NewSubstitution();
649 substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), MaybePromotedBuiltinType(retType));
650 return functionN->Substitute(Relation(), substitution);
651 }
652
653 auto *funcIface = GlobalBuiltinFunctionType(signature->Params().size())->AsETSObjectType();
654 auto *substitution = NewSubstitution();
655 for (size_t i = 0; i < signature->Params().size(); i++) {
656 substitution->emplace(funcIface->TypeArguments()[i]->AsETSTypeParameter(),
657 MaybePromotedBuiltinType(signature->Params()[i]->TsType()));
658 }
659 substitution->emplace(funcIface->TypeArguments()[signature->Params().size()]->AsETSTypeParameter(),
660 MaybePromotedBuiltinType(signature->ReturnType()));
661 return funcIface->Substitute(Relation(), substitution);
662 }
663
664 } // namespace ark::es2panda::checker
665