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);
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 enumDecl)290 ETSIntEnumType *ETSChecker::CreateEnumIntTypeFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl)
291 {
292 auto etsEnumType = CreateEnumTypeFromEnumDeclaration<ETSIntEnumType>(enumDecl);
293 enumDecl->SetTsType(etsEnumType);
294 return etsEnumType;
295 }
296
CreateEnumStringTypeFromEnumDeclaration(ir::TSEnumDeclaration * const enumDecl)297 ETSStringEnumType *ETSChecker::CreateEnumStringTypeFromEnumDeclaration(ir::TSEnumDeclaration *const enumDecl)
298 {
299 auto etsEnumType = CreateEnumTypeFromEnumDeclaration<ETSStringEnumType>(enumDecl);
300 enumDecl->SetTsType(etsEnumType);
301 return etsEnumType;
302 }
303
CreateETSUnionType(Span<Type * const> constituentTypes)304 Type *ETSChecker::CreateETSUnionType(Span<Type *const> constituentTypes)
305 {
306 if (constituentTypes.empty()) {
307 return nullptr;
308 }
309
310 ArenaVector<Type *> newConstituentTypes(Allocator()->Adapter());
311 newConstituentTypes.assign(constituentTypes.begin(), constituentTypes.end());
312
313 ETSUnionType::NormalizeTypes(Relation(), newConstituentTypes);
314 if (newConstituentTypes.size() == 1) {
315 return newConstituentTypes[0];
316 }
317 return Allocator()->New<ETSUnionType>(this, std::move(newConstituentTypes));
318 }
319
CreateETSTypeAliasType(util::StringView name,const ir::AstNode * declNode,bool isRecursive)320 ETSTypeAliasType *ETSChecker::CreateETSTypeAliasType(util::StringView name, const ir::AstNode *declNode,
321 bool isRecursive)
322 {
323 return Allocator()->New<ETSTypeAliasType>(this, name, declNode, isRecursive);
324 }
325
CreateETSFunctionType(ArenaVector<Signature * > & signatures)326 ETSFunctionType *ETSChecker::CreateETSFunctionType(ArenaVector<Signature *> &signatures)
327 {
328 auto *funcType = Allocator()->New<ETSFunctionType>(signatures[0]->Function()->Id()->Name(), Allocator());
329
330 for (auto *it : signatures) {
331 funcType->AddCallSignature(it);
332 }
333
334 return funcType;
335 }
336
CreateETSFunctionType(Signature * signature)337 ETSFunctionType *ETSChecker::CreateETSFunctionType(Signature *signature)
338 {
339 return Allocator()->New<ETSFunctionType>(signature->Function()->Id()->Name(), signature, Allocator());
340 }
341
CreateETSFunctionType(Signature * signature,util::StringView name)342 ETSFunctionType *ETSChecker::CreateETSFunctionType(Signature *signature, util::StringView name)
343 {
344 return Allocator()->New<ETSFunctionType>(name, signature, Allocator());
345 }
346
CreateETSFunctionType(ir::ScriptFunction * func,Signature * signature,util::StringView name)347 ETSFunctionType *ETSChecker::CreateETSFunctionType(ir::ScriptFunction *func, Signature *signature,
348 util::StringView name)
349 {
350 if (func->IsDynamic()) {
351 return Allocator()->New<ETSDynamicFunctionType>(name, signature, Allocator(), func->Language());
352 }
353
354 return Allocator()->New<ETSFunctionType>(name, signature, Allocator());
355 }
356
CreateETSFunctionType(ir::ScriptFunction * func,ArenaVector<Signature * > && signatures,util::StringView name)357 ETSFunctionType *ETSChecker::CreateETSFunctionType(ir::ScriptFunction *func, ArenaVector<Signature *> &&signatures,
358 util::StringView name)
359 {
360 if (func->IsDynamic()) {
361 return Allocator()->New<ETSDynamicFunctionType>(this, name, std::move(signatures), func->Language());
362 }
363
364 return Allocator()->New<ETSFunctionType>(this, name, std::move(signatures));
365 }
366
CreateSignature(SignatureInfo * info,Type * returnType,ir::ScriptFunction * func)367 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunction *func)
368 {
369 return Allocator()->New<Signature>(info, returnType, func);
370 }
371
CreateSignature(SignatureInfo * info,Type * returnType,util::StringView internalName)372 Signature *ETSChecker::CreateSignature(SignatureInfo *info, Type *returnType, util::StringView internalName)
373 {
374 return Allocator()->New<Signature>(info, returnType, internalName);
375 }
376
CreateSignatureInfo()377 SignatureInfo *ETSChecker::CreateSignatureInfo()
378 {
379 return Allocator()->New<SignatureInfo>(Allocator());
380 }
381
CreateTypeParameter()382 ETSTypeParameter *ETSChecker::CreateTypeParameter()
383 {
384 return Allocator()->New<ETSTypeParameter>();
385 }
386
CreateETSFunctionType(util::StringView name)387 ETSFunctionType *ETSChecker::CreateETSFunctionType(util::StringView name)
388 {
389 return Allocator()->New<ETSFunctionType>(name, Allocator());
390 }
391
CreateETSExtensionFuncHelperType(ETSFunctionType * classMethodType,ETSFunctionType * extensionFunctionType)392 ETSExtensionFuncHelperType *ETSChecker::CreateETSExtensionFuncHelperType(ETSFunctionType *classMethodType,
393 ETSFunctionType *extensionFunctionType)
394 {
395 return Allocator()->New<ETSExtensionFuncHelperType>(classMethodType, extensionFunctionType);
396 }
397
GetNameToTypeIdMap()398 std::map<util::StringView, GlobalTypeId> &GetNameToTypeIdMap()
399 {
400 static std::map<util::StringView, GlobalTypeId> nameToTypeId = {
401 {compiler::Signatures::BUILTIN_BIGINT_CLASS, GlobalTypeId::ETS_BIG_INT_BUILTIN},
402 {compiler::Signatures::BUILTIN_STRING_CLASS, GlobalTypeId::ETS_STRING_BUILTIN},
403 {compiler::Signatures::BUILTIN_OBJECT_CLASS, GlobalTypeId::ETS_OBJECT_BUILTIN},
404 {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, GlobalTypeId::ETS_EXCEPTION_BUILTIN},
405 {compiler::Signatures::BUILTIN_ERROR_CLASS, GlobalTypeId::ETS_ERROR_BUILTIN},
406 {compiler::Signatures::BUILTIN_TYPE_CLASS, GlobalTypeId::ETS_TYPE_BUILTIN},
407 {compiler::Signatures::BUILTIN_PROMISE_CLASS, GlobalTypeId::ETS_PROMISE_BUILTIN},
408 {compiler::Signatures::BUILTIN_BOX_CLASS, GlobalTypeId::ETS_BOX_BUILTIN},
409 {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, GlobalTypeId::ETS_BOOLEAN_BOX_BUILTIN},
410 {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, GlobalTypeId::ETS_BYTE_BOX_BUILTIN},
411 {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, GlobalTypeId::ETS_CHAR_BOX_BUILTIN},
412 {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, GlobalTypeId::ETS_SHORT_BOX_BUILTIN},
413 {compiler::Signatures::BUILTIN_INT_BOX_CLASS, GlobalTypeId::ETS_INT_BOX_BUILTIN},
414 {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, GlobalTypeId::ETS_LONG_BOX_BUILTIN},
415 {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, GlobalTypeId::ETS_FLOAT_BOX_BUILTIN},
416 {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, GlobalTypeId::ETS_DOUBLE_BOX_BUILTIN},
417 };
418
419 return nameToTypeId;
420 }
421
GetNameToGlobalTypeMap()422 std::map<util::StringView, std::function<ETSObjectType *(const ETSChecker *)>> &GetNameToGlobalTypeMap()
423 {
424 static std::map<util::StringView, std::function<ETSObjectType *(const ETSChecker *)>> nameToGlobalType = {
425 {compiler::Signatures::BUILTIN_BIGINT_CLASS, &ETSChecker::GlobalBuiltinETSBigIntType},
426 {compiler::Signatures::BUILTIN_STRING_CLASS, &ETSChecker::GlobalBuiltinETSStringType},
427 {compiler::Signatures::BUILTIN_OBJECT_CLASS, &ETSChecker::GlobalETSObjectType},
428 {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, &ETSChecker::GlobalBuiltinExceptionType},
429 {compiler::Signatures::BUILTIN_ERROR_CLASS, &ETSChecker::GlobalBuiltinErrorType},
430 {compiler::Signatures::BUILTIN_TYPE_CLASS, &ETSChecker::GlobalBuiltinTypeType},
431 {compiler::Signatures::BUILTIN_PROMISE_CLASS, &ETSChecker::GlobalBuiltinPromiseType},
432 };
433
434 return nameToGlobalType;
435 }
436
GetNameToGlobalBoxTypeMap()437 std::map<util::StringView, std::function<Type *(const ETSChecker *)>> &GetNameToGlobalBoxTypeMap()
438 {
439 static std::map<util::StringView, std::function<Type *(const ETSChecker *)>> nameToGlobalBoxType = {
440 {compiler::Signatures::BUILTIN_BOX_CLASS, &ETSChecker::GlobalETSObjectType},
441 {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, &ETSChecker::GlobalETSBooleanType},
442 {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, &ETSChecker::GlobalByteType},
443 {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, &ETSChecker::GlobalCharType},
444 {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, &ETSChecker::GlobalShortType},
445 {compiler::Signatures::BUILTIN_INT_BOX_CLASS, &ETSChecker::GlobalIntType},
446 {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, &ETSChecker::GlobalLongType},
447 {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, &ETSChecker::GlobalFloatType},
448 {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, &ETSChecker::GlobalDoubleType},
449 };
450
451 return nameToGlobalBoxType;
452 }
453
UpdateBoxedGlobalType(ETSObjectType * objType,util::StringView name)454 ETSObjectType *ETSChecker::UpdateBoxedGlobalType(ETSObjectType *objType, util::StringView name)
455 {
456 auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap();
457 auto nameToTypeId = GetNameToTypeIdMap();
458
459 if (nameToGlobalBoxType.find(name) != nameToGlobalBoxType.end()) {
460 std::function<Type *(const ETSChecker *)> globalType = nameToGlobalBoxType[name];
461 if (GlobalBuiltinBoxType(globalType(this)) != nullptr) {
462 return GlobalBuiltinBoxType(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
471 return objType;
472 }
473
UpdateGlobalType(ETSObjectType * objType,util::StringView name)474 ETSObjectType *ETSChecker::UpdateGlobalType(ETSObjectType *objType, util::StringView name)
475 {
476 auto nameToGlobalType = GetNameToGlobalTypeMap();
477 auto nameToTypeId = GetNameToTypeIdMap();
478
479 if (nameToGlobalType.find(name) != nameToGlobalType.end()) {
480 std::function<ETSObjectType *(const ETSChecker *)> globalType = nameToGlobalType[name];
481 if (globalType(this) != nullptr) {
482 return globalType(this);
483 }
484
485 auto id = nameToTypeId.find(name);
486 if (id != nameToTypeId.end()) {
487 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(id->second)] = objType;
488 }
489
490 if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) {
491 auto *nullish = CreateETSUnionType({objType, GlobalETSNullType(), GlobalETSUndefinedType()});
492 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_NULLISH_OBJECT)] = nullish;
493 nullish = CreateETSUnionType({GlobalETSNullType(), GlobalETSUndefinedType()});
494 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_NULLISH_TYPE)] = nullish;
495 }
496 }
497
498 return objType;
499 }
500
CreateETSObjectTypeCheckBuiltins(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)501 ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode,
502 ETSObjectFlags flags)
503 {
504 if (name == compiler::Signatures::BUILTIN_BIGINT_CLASS) {
505 if (GlobalBuiltinETSBigIntType() != nullptr) {
506 return GlobalBuiltinETSBigIntType();
507 }
508
509 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_BIG_INT_BUILTIN)] =
510 CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_BIGINT);
511 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_BIG_INT)] =
512 Allocator()->New<ETSBigIntType>(Allocator(), GlobalBuiltinETSBigIntType());
513
514 return GlobalBuiltinETSBigIntType();
515 }
516
517 if (name == compiler::Signatures::BUILTIN_STRING_CLASS) {
518 if (GlobalBuiltinETSStringType() != nullptr) {
519 return GlobalBuiltinETSStringType();
520 }
521 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_STRING_BUILTIN)] =
522 CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_STRING | ETSObjectFlags::STRING);
523
524 GetGlobalTypesHolder()->GlobalTypes()[static_cast<size_t>(GlobalTypeId::ETS_STRING)] =
525 Allocator()->New<ETSStringType>(Allocator(), GlobalBuiltinETSStringType(), Relation());
526 return GlobalBuiltinETSStringType();
527 }
528
529 auto *objType = CreateNewETSObjectType(name, declNode, flags);
530 auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap();
531
532 return UpdateGlobalType(objType, name);
533 }
534
CreateETSObjectType(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)535 ETSObjectType *ETSChecker::CreateETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags)
536 {
537 auto res = primitiveWrappers_.Wrappers().find(name);
538 if (res == primitiveWrappers_.Wrappers().end()) {
539 return CreateETSObjectTypeCheckBuiltins(name, declNode, flags);
540 }
541
542 if (res->second.first != nullptr) {
543 return res->second.first;
544 }
545
546 auto *objType = CreateNewETSObjectType(name, declNode, flags | res->second.second);
547 primitiveWrappers_.Wrappers().at(name).first = objType;
548 return objType;
549 }
550
CheckForDynamicLang(ir::AstNode * declNode,util::StringView assemblerName)551 std::tuple<Language, bool> ETSChecker::CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName)
552 {
553 Language lang(Language::Id::ETS);
554 bool hasDecl = false;
555
556 if (declNode->IsClassDefinition()) {
557 auto *clsDef = declNode->AsClassDefinition();
558 lang = clsDef->Language();
559 hasDecl = clsDef->IsDeclare();
560 }
561
562 if (declNode->IsTSInterfaceDeclaration()) {
563 auto *ifaceDecl = declNode->AsTSInterfaceDeclaration();
564 lang = ifaceDecl->Language();
565 hasDecl = ifaceDecl->IsDeclare();
566 }
567
568 auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8());
569 if (res) {
570 lang = *res;
571 }
572
573 return std::make_tuple(lang, hasDecl);
574 }
575
CreateNewETSObjectType(util::StringView name,ir::AstNode * declNode,ETSObjectFlags flags)576 ETSObjectType *ETSChecker::CreateNewETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags)
577 {
578 util::StringView assemblerName = name;
579 util::StringView prefix {};
580
581 auto *containingObjType = util::Helpers::GetContainingObjectType(declNode->Parent());
582
583 if (declNode->IsClassDefinition()) {
584 if (declNode->AsClassDefinition()->IsLocal()) {
585 util::UString localName(declNode->AsClassDefinition()->LocalPrefix(), Allocator());
586 localName.Append(name);
587 assemblerName = localName.View();
588 }
589 if (declNode->AsClassDefinition()->OrigEnumDecl() != nullptr) {
590 flags |= ETSObjectFlags::BOXED_ENUM;
591 }
592 }
593
594 if (containingObjType != nullptr) {
595 prefix = containingObjType->AssemblerName();
596 } else if (const auto *topStatement = declNode->GetTopStatement();
597 topStatement->Type() !=
598 ir::AstNodeType::ETS_SCRIPT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION
599 ASSERT(declNode->IsTSInterfaceDeclaration());
600 assemblerName = declNode->AsTSInterfaceDeclaration()->InternalName();
601 } else {
602 auto program = static_cast<ir::ETSScript *>(declNode->GetTopStatement())->Program();
603 prefix = program->OmitModuleName() ? util::StringView() : program->ModuleName();
604 }
605
606 if (!prefix.Empty()) {
607 assemblerName =
608 util::UString(prefix.Mutf8() + compiler::Signatures::METHOD_SEPARATOR.data() + assemblerName.Mutf8(),
609 Allocator())
610 .View();
611 }
612
613 auto [lang, hasDecl] = CheckForDynamicLang(declNode, assemblerName);
614 if (lang.IsDynamic()) {
615 return Allocator()->New<ETSDynamicType>(Allocator(), std::make_tuple(name, assemblerName, lang),
616 std::make_tuple(declNode, flags, Relation()), hasDecl);
617 }
618
619 return Allocator()->New<ETSObjectType>(Allocator(), name, assemblerName,
620 std::make_tuple(declNode, flags, Relation()));
621 }
622
CreateBuiltinArraySignatureInfo(ETSArrayType * arrayType,size_t dim)623 std::tuple<util::StringView, SignatureInfo *> ETSChecker::CreateBuiltinArraySignatureInfo(ETSArrayType *arrayType,
624 size_t dim)
625 {
626 std::stringstream ss;
627 arrayType->ToAssemblerTypeWithRank(ss);
628 ss << compiler::Signatures::METHOD_SEPARATOR << compiler::Signatures::CTOR << compiler::Signatures::MANGLE_BEGIN;
629 arrayType->ToAssemblerTypeWithRank(ss);
630
631 auto *info = CreateSignatureInfo();
632 info->minArgCount = dim;
633
634 for (size_t i = 0; i < dim; i++) {
635 util::UString param(std::to_string(i), Allocator());
636 auto *paramVar =
637 varbinder::Scope::CreateVar(Allocator(), param.View(), varbinder::VariableFlags::NONE, nullptr);
638 paramVar->SetTsType(GlobalIntType());
639
640 info->params.push_back(paramVar);
641
642 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_INT;
643 }
644
645 ss << compiler::Signatures::MANGLE_SEPARATOR << compiler::Signatures::PRIMITIVE_VOID
646 << compiler::Signatures::MANGLE_SEPARATOR;
647 auto internalName = util::UString(ss.str(), Allocator()).View();
648
649 return {internalName, info};
650 }
651
CreateBuiltinArraySignature(ETSArrayType * arrayType,size_t dim)652 Signature *ETSChecker::CreateBuiltinArraySignature(ETSArrayType *arrayType, size_t dim)
653 {
654 auto res = globalArraySignatures_.find(arrayType);
655 if (res != globalArraySignatures_.end()) {
656 return res->second;
657 }
658
659 auto [internalName, info] = CreateBuiltinArraySignatureInfo(arrayType, dim);
660 auto *signature = CreateSignature(info, GlobalVoidType(), internalName);
661 globalArraySignatures_.insert({arrayType, signature});
662
663 return signature;
664 }
665
FunctionTypeToFunctionalInterfaceType(Signature * signature)666 ETSObjectType *ETSChecker::FunctionTypeToFunctionalInterfaceType(Signature *signature)
667 {
668 auto *retType = signature->ReturnType();
669 if (signature->RestVar() != nullptr) {
670 auto *functionN =
671 GlobalBuiltinFunctionType(GlobalBuiltinFunctionTypeVariadicThreshold(), signature->Function()->Flags())
672 ->AsETSObjectType();
673 auto *substitution = NewSubstitution();
674 substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), MaybeBoxType(retType));
675 return functionN->Substitute(Relation(), substitution);
676 }
677
678 // Note: FunctionN is not supported yet
679 if (signature->Params().size() >= GetGlobalTypesHolder()->VariadicFunctionTypeThreshold()) {
680 return nullptr;
681 }
682
683 auto *funcIface =
684 GlobalBuiltinFunctionType(signature->Params().size(), signature->Function()->Flags())->AsETSObjectType();
685 auto *substitution = NewSubstitution();
686
687 for (size_t i = 0; i < signature->Params().size(); i++) {
688 substitution->emplace(funcIface->TypeArguments()[i]->AsETSTypeParameter(),
689 MaybeBoxType(signature->Params()[i]->TsType()));
690 }
691 substitution->emplace(funcIface->TypeArguments()[signature->Params().size()]->AsETSTypeParameter(),
692 MaybeBoxType(signature->ReturnType()));
693 return funcIface->Substitute(Relation(), substitution);
694 }
695
ResolveFunctionalInterfaces(ArenaVector<Signature * > & signatures)696 Type *ETSChecker::ResolveFunctionalInterfaces(ArenaVector<Signature *> &signatures)
697 {
698 ArenaVector<Type *> types(Allocator()->Adapter());
699 for (auto *signature : signatures) {
700 types.push_back(FunctionTypeToFunctionalInterfaceType(signature));
701 }
702 return CreateETSUnionType(std::move(types));
703 }
704
CreatePromiseOf(Type * type)705 ETSObjectType *ETSChecker::CreatePromiseOf(Type *type)
706 {
707 ETSObjectType *const promiseType = GlobalBuiltinPromiseType();
708 ASSERT(promiseType->TypeArguments().size() == 1);
709 Substitution *substitution = NewSubstitution();
710 ETSChecker::EmplaceSubstituted(substitution, promiseType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(),
711 type);
712
713 return promiseType->Substitute(Relation(), substitution);
714 }
715
716 } // namespace ark::es2panda::checker
717