• 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 <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 *> &params, 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