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 "etsObjectType.h"
17
18 #include "checker/ETSchecker.h"
19 #include "checker/ets/conversion.h"
20 #include "checker/types/ts/objectType.h"
21 #include "checker/types/typeFlag.h"
22 #include "checker/types/typeRelation.h"
23 #include "checker/types/globalTypesHolder.h"
24 #include "ir/base/scriptFunction.h"
25 #include "ir/expressions/identifier.h"
26
27 namespace ark::es2panda::checker {
28
Iterate(const PropertyTraverser & cb) const29 void ETSObjectType::Iterate(const PropertyTraverser &cb) const
30 {
31 for (const auto *prop : GetAllProperties()) {
32 cb(prop);
33 }
34
35 if (superType_ != nullptr) {
36 superType_->Iterate(cb);
37 }
38
39 for (const auto *interface : interfaces_) {
40 interface->Iterate(cb);
41 }
42 }
43
SearchFieldsDecls(const util::StringView & name,PropertySearchFlags flags) const44 varbinder::LocalVariable *ETSObjectType::SearchFieldsDecls(const util::StringView &name,
45 PropertySearchFlags flags) const
46 {
47 varbinder::LocalVariable *res {};
48 if ((flags & PropertySearchFlags::SEARCH_INSTANCE_FIELD) != 0) {
49 res = GetOwnProperty<PropertyType::INSTANCE_FIELD>(name);
50 }
51
52 if (res == nullptr && ((flags & PropertySearchFlags::SEARCH_STATIC_FIELD) != 0)) {
53 res = GetOwnProperty<PropertyType::STATIC_FIELD>(name);
54 }
55
56 if (res == nullptr && ((flags & PropertySearchFlags::SEARCH_INSTANCE_DECL) != 0)) {
57 res = GetOwnProperty<PropertyType::INSTANCE_DECL>(name);
58 }
59
60 if (res == nullptr && ((flags & PropertySearchFlags::SEARCH_STATIC_DECL) != 0)) {
61 res = GetOwnProperty<PropertyType::STATIC_DECL>(name);
62 }
63 return res;
64 }
65
GetProperty(const util::StringView & name,PropertySearchFlags flags) const66 varbinder::LocalVariable *ETSObjectType::GetProperty(const util::StringView &name, PropertySearchFlags flags) const
67 {
68 varbinder::LocalVariable *res = SearchFieldsDecls(name, flags);
69 if (res == nullptr && (flags & PropertySearchFlags::SEARCH_METHOD) != 0) {
70 if ((flags & PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION) != 0) {
71 if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) {
72 res = GetOwnProperty<PropertyType::INSTANCE_METHOD>(name);
73 }
74
75 if (res == nullptr && ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0)) {
76 res = GetOwnProperty<PropertyType::STATIC_METHOD>(name);
77 }
78 } else {
79 res = CreateSyntheticVarFromEverySignature(name, flags);
80 }
81 }
82
83 if (res == nullptr && (flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) {
84 for (auto *interface : interfaces_) {
85 res = interface->GetProperty(name, flags);
86 if (res != nullptr) {
87 return res;
88 }
89 }
90 }
91
92 if (res == nullptr && superType_ != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) {
93 res = superType_->GetProperty(name, flags);
94 }
95
96 return res;
97 }
98
IsPropertyInherited(const varbinder::Variable * var)99 bool ETSObjectType::IsPropertyInherited(const varbinder::Variable *var)
100 {
101 if (var->HasFlag(varbinder::VariableFlags::PRIVATE)) {
102 return GetProperty(var->Name(), PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL) == var;
103 }
104
105 if (var->HasFlag(varbinder::VariableFlags::PROTECTED)) {
106 return (GetProperty(var->Name(), PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL) ==
107 var) ||
108 this->IsPropertyOfAscendant(var);
109 }
110
111 return true;
112 }
113
IsPropertyOfAscendant(const varbinder::Variable * var) const114 bool ETSObjectType::IsPropertyOfAscendant(const varbinder::Variable *var) const
115 {
116 if (this->SuperType() == nullptr) {
117 return false;
118 }
119
120 if (this->SuperType()->GetProperty(var->Name(),
121 PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL) == var) {
122 return true;
123 }
124
125 return this->SuperType()->IsPropertyOfAscendant(var);
126 }
127
IsSignatureInherited(Signature * signature)128 bool ETSObjectType::IsSignatureInherited(Signature *signature)
129 {
130 if (signature->HasSignatureFlag(SignatureFlags::PRIVATE)) {
131 return signature->Owner() == this;
132 }
133
134 if (signature->HasSignatureFlag(SignatureFlags::PROTECTED)) {
135 return signature->Owner() == this || this->IsDescendantOf(signature->Owner());
136 }
137
138 return true;
139 }
140
IsDescendantOf(const ETSObjectType * ascendant) const141 bool ETSObjectType::IsDescendantOf(const ETSObjectType *ascendant) const
142 {
143 if (this->SuperType() == nullptr) {
144 return false;
145 }
146
147 if (this->SuperType() == ascendant) {
148 return true;
149 }
150
151 return this->SuperType()->IsDescendantOf(ascendant);
152 }
153
CreateSyntheticVarFromEverySignature(const util::StringView & name,PropertySearchFlags flags) const154 varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(const util::StringView &name,
155 PropertySearchFlags flags) const
156 {
157 varbinder::LocalVariable *res = allocator_->New<varbinder::LocalVariable>(varbinder::VariableFlags::SYNTHETIC |
158 varbinder::VariableFlags::METHOD);
159 ETSFunctionType *funcType = CreateETSFunctionType(name);
160
161 varbinder::LocalVariable *functionalInterface = CollectSignaturesForSyntheticType(funcType, name, flags);
162
163 if (functionalInterface != nullptr) {
164 return functionalInterface;
165 }
166
167 if (funcType->CallSignatures().empty()) {
168 return nullptr;
169 }
170
171 res->SetTsType(funcType);
172 funcType->SetVariable(res);
173 return res;
174 }
175
CreateETSFunctionType(const util::StringView & name) const176 ETSFunctionType *ETSObjectType::CreateETSFunctionType(const util::StringView &name) const
177 {
178 return allocator_->New<ETSFunctionType>(name, allocator_);
179 }
180
CollectSignaturesForSyntheticType(ETSFunctionType * funcType,const util::StringView & name,PropertySearchFlags flags) const181 varbinder::LocalVariable *ETSObjectType::CollectSignaturesForSyntheticType(ETSFunctionType *funcType,
182 const util::StringView &name,
183 PropertySearchFlags flags) const
184 {
185 if (funcType == nullptr) {
186 return nullptr;
187 }
188
189 auto const addSignature = [funcType, flags](varbinder::LocalVariable *found) -> void {
190 for (auto *it : found->TsType()->AsETSFunctionType()->CallSignatures()) {
191 if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) &&
192 it->HasSignatureFlag(SignatureFlags::ABSTRACT)) {
193 continue;
194 }
195
196 funcType->AddCallSignature(it);
197 }
198 };
199
200 if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) {
201 if (auto *found = GetOwnProperty<PropertyType::STATIC_METHOD>(name); found != nullptr) {
202 ASSERT(found->TsType()->IsETSFunctionType());
203 addSignature(found);
204 }
205 }
206
207 if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) {
208 if (auto *found = GetOwnProperty<PropertyType::INSTANCE_METHOD>(name); found != nullptr) {
209 ASSERT(found->TsType()->IsETSFunctionType());
210 addSignature(found);
211 }
212 }
213
214 if (superType_ != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) {
215 return superType_->CollectSignaturesForSyntheticType(funcType, name, flags);
216 }
217
218 return nullptr;
219 }
220
GetAllProperties() const221 std::vector<varbinder::LocalVariable *> ETSObjectType::GetAllProperties() const
222 {
223 std::vector<varbinder::LocalVariable *> allProperties;
224 for (const auto &[_, prop] : InstanceFields()) {
225 (void)_;
226 allProperties.push_back(prop);
227 }
228
229 for (const auto &[_, prop] : StaticFields()) {
230 (void)_;
231 allProperties.push_back(prop);
232 }
233
234 for (const auto &[_, prop] : InstanceMethods()) {
235 (void)_;
236 allProperties.push_back(prop);
237 }
238
239 for (const auto &[_, prop] : StaticMethods()) {
240 (void)_;
241 allProperties.push_back(prop);
242 }
243
244 for (const auto &[_, prop] : InstanceDecls()) {
245 (void)_;
246 allProperties.push_back(prop);
247 }
248
249 for (const auto &[_, prop] : StaticDecls()) {
250 (void)_;
251 allProperties.push_back(prop);
252 }
253
254 return allProperties;
255 }
256
Methods() const257 std::vector<varbinder::LocalVariable *> ETSObjectType::Methods() const
258 {
259 std::vector<varbinder::LocalVariable *> methods;
260 for (const auto &[_, prop] : InstanceMethods()) {
261 (void)_;
262 methods.push_back(prop);
263 }
264
265 for (const auto &[_, prop] : StaticMethods()) {
266 (void)_;
267 methods.push_back(prop);
268 }
269
270 return methods;
271 }
272
Fields() const273 std::vector<varbinder::LocalVariable *> ETSObjectType::Fields() const
274 {
275 std::vector<varbinder::LocalVariable *> fields;
276 for (const auto &[_, prop] : InstanceFields()) {
277 (void)_;
278 fields.push_back(prop);
279 }
280
281 for (const auto &[_, prop] : StaticFields()) {
282 (void)_;
283 fields.push_back(prop);
284 }
285
286 return fields;
287 }
288
ForeignProperties() const289 std::vector<const varbinder::LocalVariable *> ETSObjectType::ForeignProperties() const
290 {
291 std::vector<const varbinder::LocalVariable *> foreignProps;
292 std::unordered_set<util::StringView> ownProps;
293
294 EnsurePropertiesInstantiated();
295 ownProps.reserve(properties_.size());
296
297 for (const auto *prop : GetAllProperties()) {
298 ownProps.insert(prop->Name());
299 }
300
301 auto allProps = CollectAllProperties();
302 for (const auto &[name, var] : allProps) {
303 if (ownProps.find(name) == ownProps.end()) {
304 foreignProps.push_back(var);
305 }
306 }
307
308 return foreignProps;
309 }
310
CollectAllProperties() const311 ArenaMap<util::StringView, const varbinder::LocalVariable *> ETSObjectType::CollectAllProperties() const
312 {
313 ArenaMap<util::StringView, const varbinder::LocalVariable *> propMap(allocator_->Adapter());
314 EnsurePropertiesInstantiated();
315 Iterate([&propMap](const varbinder::LocalVariable *var) { propMap.emplace(var->Name(), var); });
316
317 return propMap;
318 }
319
ToString(std::stringstream & ss,bool precise) const320 void ETSObjectType::ToString(std::stringstream &ss, bool precise) const
321 {
322 if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) {
323 GetFunctionalInterfaceInvokeType()->ToString(ss, precise);
324 return;
325 }
326
327 const bool isRequiredType = HasObjectFlag(ETSObjectFlags::REQUIRED);
328 if (isRequiredType) {
329 ss << "Required" << compiler::Signatures::GENERIC_BEGIN;
330 }
331
332 if (precise) {
333 ss << assemblerName_; // NOTE(gogabr): need full qualified name
334 } else {
335 ss << name_;
336 }
337
338 if (!typeArguments_.empty()) {
339 ss << compiler::Signatures::GENERIC_BEGIN;
340 for (auto arg = typeArguments_.cbegin(); arg != typeArguments_.cend(); ++arg) {
341 (*arg)->ToString(ss, precise);
342
343 if (next(arg) != typeArguments_.cend()) {
344 ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_COMMA);
345 }
346 }
347 ss << compiler::Signatures::GENERIC_END;
348 }
349
350 if (isRequiredType) {
351 ss << compiler::Signatures::GENERIC_END;
352 }
353 }
354
IdenticalUptoTypeArguments(TypeRelation * relation,Type * other)355 void ETSObjectType::IdenticalUptoTypeArguments(TypeRelation *relation, Type *other)
356 {
357 relation->Result(false);
358 if (!other->IsETSObjectType() || !CheckIdenticalFlags(other->AsETSObjectType())) {
359 return;
360 }
361
362 auto *thisBase = GetOriginalBaseType();
363 auto *otherBase = other->AsETSObjectType()->GetOriginalBaseType();
364 if (thisBase->Variable() != otherBase->Variable()) {
365 return;
366 }
367
368 if ((relation->IgnoreTypeParameters() && !HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) || (this == other)) {
369 relation->Result(true);
370 return;
371 }
372
373 auto const sourceTypeArguments = other->AsETSObjectType()->TypeArguments();
374 if (typeArguments_.empty() != sourceTypeArguments.empty()) {
375 return;
376 }
377
378 relation->Result(true);
379 }
380
Identical(TypeRelation * relation,Type * other)381 void ETSObjectType::Identical(TypeRelation *relation, Type *other)
382 {
383 IdenticalUptoTypeArguments(relation, other);
384
385 if (!relation->IsTrue() || !HasTypeFlag(TypeFlag::GENERIC)) {
386 return;
387 }
388
389 auto const otherTypeArguments = other->AsETSObjectType()->TypeArguments();
390
391 auto const argsNumber = typeArguments_.size();
392 if (argsNumber != otherTypeArguments.size()) {
393 relation->Result(false);
394 return;
395 }
396
397 for (size_t idx = 0U; idx < argsNumber; ++idx) {
398 if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) {
399 continue;
400 }
401 if (!relation->IsIdenticalTo(typeArguments_[idx], otherTypeArguments[idx])) {
402 return;
403 }
404 }
405
406 relation->Result(true);
407 }
408
CheckIdenticalFlags(ETSObjectType * other) const409 bool ETSObjectType::CheckIdenticalFlags(ETSObjectType *other) const
410 {
411 constexpr auto FLAGS_TO_REMOVE = ETSObjectFlags::INCOMPLETE_INSTANTIATION |
412 ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS |
413 ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY | ETSObjectFlags::READONLY;
414 // note(lujiahui): we support assigning T to Readonly<T>, but do not support assigning Readonly<T> to T
415 // more details in spec
416 if (!HasObjectFlag(ETSObjectFlags::READONLY) && other->HasObjectFlag(ETSObjectFlags::READONLY)) {
417 return false;
418 }
419 auto cleanedTargetFlags = other->ObjectFlags();
420 cleanedTargetFlags &= ~FLAGS_TO_REMOVE;
421
422 auto cleanedSelfFlags = ObjectFlags();
423 cleanedSelfFlags &= ~FLAGS_TO_REMOVE;
424
425 return cleanedSelfFlags == cleanedTargetFlags;
426 }
427
AssignmentSource(TypeRelation * const relation,Type * const target)428 bool ETSObjectType::AssignmentSource(TypeRelation *const relation, [[maybe_unused]] Type *const target)
429 {
430 return relation->Result(false);
431 }
432
AssignmentTarget(TypeRelation * const relation,Type * source)433 void ETSObjectType::AssignmentTarget(TypeRelation *const relation, Type *source)
434 {
435 if (source->IsETSObjectType() && source->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::READONLY)) {
436 relation->Result(false);
437 return;
438 }
439
440 if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL) && source->IsETSFunctionType()) {
441 EnsurePropertiesInstantiated();
442 auto found = properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)].find(
443 FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME);
444 ASSERT(found != properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)].end());
445 source = source->AsETSFunctionType()->BoxPrimitives(relation->GetChecker()->AsETSChecker());
446 relation->IsAssignableTo(source, found->second->TsType());
447 return;
448 }
449
450 relation->IsSupertypeOf(this, source);
451 }
452
CastWideningNarrowing(TypeRelation * const relation,Type * const target,TypeFlag unboxFlags,TypeFlag wideningFlags,TypeFlag narrowingFlags)453 bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *const target, TypeFlag unboxFlags,
454 TypeFlag wideningFlags, TypeFlag narrowingFlags)
455 {
456 if (target->HasTypeFlag(unboxFlags)) {
457 conversion::Unboxing(relation, this);
458 return true;
459 }
460 if (target->HasTypeFlag(wideningFlags)) {
461 conversion::UnboxingWideningPrimitive(relation, this, target);
462 return true;
463 }
464 if (target->HasTypeFlag(narrowingFlags)) {
465 conversion::UnboxingNarrowingPrimitive(relation, this, target);
466 return true;
467 }
468 return false;
469 }
470
TryCastByte(TypeRelation * const relation,Type * const target)471 bool ETSObjectType::TryCastByte(TypeRelation *const relation, Type *const target)
472 {
473 if (target->HasTypeFlag(TypeFlag::BYTE)) {
474 conversion::Unboxing(relation, this);
475 return true;
476 }
477 if (target->HasTypeFlag(TypeFlag::SHORT | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) {
478 conversion::UnboxingWideningPrimitive(relation, this, target);
479 return true;
480 }
481 if (target->HasTypeFlag(TypeFlag::CHAR)) {
482 conversion::UnboxingWideningNarrowingPrimitive(relation, this, target);
483 return true;
484 }
485 return false;
486 }
487
TryCastIntegral(TypeRelation * const relation,Type * const target)488 bool ETSObjectType::TryCastIntegral(TypeRelation *const relation, Type *const target)
489 {
490 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE) && TryCastByte(relation, target)) {
491 return true;
492 }
493 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT) &&
494 CastWideningNarrowing(relation, target, TypeFlag::SHORT,
495 TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE,
496 TypeFlag::BYTE | TypeFlag::CHAR)) {
497 return true;
498 }
499 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR) &&
500 CastWideningNarrowing(relation, target, TypeFlag::CHAR,
501 TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE,
502 TypeFlag::BYTE | TypeFlag::SHORT)) {
503 return true;
504 }
505 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) &&
506 CastWideningNarrowing(relation, target, TypeFlag::INT, TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE,
507 TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR)) {
508 return true;
509 }
510 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) &&
511 CastWideningNarrowing(relation, target, TypeFlag::LONG, TypeFlag::FLOAT | TypeFlag::DOUBLE,
512 TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT)) {
513 return true;
514 }
515 return false;
516 }
517
TryCastFloating(TypeRelation * const relation,Type * const target)518 bool ETSObjectType::TryCastFloating(TypeRelation *const relation, Type *const target)
519 {
520 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT) &&
521 CastWideningNarrowing(relation, target, TypeFlag::FLOAT, TypeFlag::DOUBLE,
522 TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG)) {
523 return true;
524 }
525 if (auto narrowingFlags =
526 TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT;
527 this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) &&
528 CastWideningNarrowing(relation, target, TypeFlag::DOUBLE, TypeFlag::NONE, narrowingFlags)) {
529 return true;
530 }
531 return false;
532 }
533
TryCastUnboxable(TypeRelation * const relation,Type * const target)534 bool ETSObjectType::TryCastUnboxable(TypeRelation *const relation, Type *const target)
535 {
536 if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) {
537 if (!target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) {
538 conversion::WideningReference(relation, this, target->AsETSObjectType());
539 return true;
540 }
541 auto unboxedTarget = relation->GetChecker()->AsETSChecker()->ETSBuiltinTypeAsPrimitiveType(target);
542 CastNumericObject(relation, unboxedTarget);
543 if (relation->IsTrue()) {
544 conversion::Boxing(relation, unboxedTarget);
545 return true;
546 }
547 conversion::WideningReference(relation, this, target->AsETSObjectType());
548 return true;
549 }
550 conversion::Forbidden(relation);
551 return true;
552 }
553
CastNumericObject(TypeRelation * const relation,Type * const target)554 bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const target)
555 {
556 if (!target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG |
557 TypeFlag::FLOAT | TypeFlag::DOUBLE | TypeFlag::ETS_BOOLEAN)) {
558 return false;
559 }
560 if (relation->IsIdenticalTo(this, target)) {
561 return true;
562 }
563 if (TryCastIntegral(relation, target)) {
564 return true;
565 }
566 if (TryCastFloating(relation, target)) {
567 return true;
568 }
569 if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN) && target->HasTypeFlag(TypeFlag::ETS_BOOLEAN)) {
570 conversion::Unboxing(relation, this);
571 return true;
572 }
573 if (this->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) {
574 return TryCastUnboxable(relation, target);
575 }
576 if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG |
577 TypeFlag::FLOAT | TypeFlag::DOUBLE | TypeFlag::ETS_BOOLEAN)) {
578 conversion::NarrowingReferenceUnboxing(relation, this, target);
579 return true;
580 }
581 return false;
582 }
583
Cast(TypeRelation * const relation,Type * const target)584 void ETSObjectType::Cast(TypeRelation *const relation, Type *const target)
585 {
586 conversion::Identity(relation, this, target);
587 if (relation->IsTrue()) {
588 return;
589 }
590
591 if (CastNumericObject(relation, target)) {
592 return;
593 }
594
595 if (target->HasTypeFlag(TypeFlag::ETS_ARRAY)) {
596 conversion::NarrowingReference(relation, this, target->AsETSArrayType());
597 return;
598 }
599
600 if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) {
601 conversion::WideningReference(relation, this, target->AsETSObjectType());
602 if (relation->IsTrue()) {
603 return;
604 }
605
606 conversion::NarrowingReference(relation, this, target->AsETSObjectType());
607 if (relation->IsTrue()) {
608 return;
609 }
610 }
611
612 if (target->IsETSEnumType()) {
613 relation->GetNode()->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOX_TO_ENUM);
614 relation->Result(true);
615 return;
616 }
617 conversion::Forbidden(relation);
618 }
619
DefaultObjectTypeChecks(const ETSChecker * const etsChecker,TypeRelation * const relation,Type * const source)620 bool ETSObjectType::DefaultObjectTypeChecks(const ETSChecker *const etsChecker, TypeRelation *const relation,
621 Type *const source)
622 {
623 relation->Result(false);
624
625 // 3.8.3 Subtyping among Array Types
626 auto const *const base = GetConstOriginalBaseType();
627 if (base == etsChecker->GlobalETSObjectType() && source->IsETSArrayType()) {
628 relation->Result(true);
629 return true;
630 }
631
632 if (!source->IsETSObjectType() ||
633 !source->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE)) {
634 return true;
635 }
636
637 // All classes and interfaces are subtypes of Object
638 if (base == etsChecker->GlobalETSObjectType()) {
639 relation->Result(true);
640 return true;
641 }
642
643 IdenticalUptoTypeArguments(relation, source);
644 if (relation->IsTrue() && HasTypeFlag(TypeFlag::GENERIC)) {
645 IsGenericSupertypeOf(relation, source);
646 }
647 return relation->IsTrue();
648 }
649
IsSupertypeOf(TypeRelation * relation,Type * source)650 void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source)
651 {
652 relation->Result(false);
653 auto *const etsChecker = relation->GetChecker()->AsETSChecker();
654
655 if (DefaultObjectTypeChecks(etsChecker, relation, source)) {
656 return;
657 }
658
659 ETSObjectType *sourceObj = source->AsETSObjectType();
660 if (auto *sourceSuper = sourceObj->SuperType(); sourceSuper != nullptr) {
661 if (relation->IsSupertypeOf(this, sourceSuper)) {
662 return;
663 }
664 }
665
666 if (HasObjectFlag(ETSObjectFlags::INTERFACE)) {
667 for (auto *itf : sourceObj->Interfaces()) {
668 if (relation->IsSupertypeOf(this, itf)) {
669 return;
670 }
671 }
672 }
673 }
674
IsGenericSupertypeOf(TypeRelation * relation,Type * source)675 void ETSObjectType::IsGenericSupertypeOf(TypeRelation *relation, Type *source)
676 {
677 ASSERT(HasTypeFlag(TypeFlag::GENERIC));
678
679 auto *sourceType = source->AsETSObjectType();
680 auto const &sourceTypeArguments = sourceType->TypeArguments();
681 auto const typeArgumentsNumber = typeArguments_.size();
682 if (typeArgumentsNumber > sourceTypeArguments.size()) {
683 relation->Result(false);
684 return;
685 }
686
687 ASSERT(declNode_ == sourceType->GetDeclNode());
688
689 auto *typeParamsDecl = GetTypeParams();
690 ASSERT(typeParamsDecl != nullptr || typeArguments_.empty());
691
692 if (typeParamsDecl == nullptr) {
693 return;
694 }
695
696 auto &typeParams = typeParamsDecl->Params();
697 ASSERT(typeParams.size() == typeArgumentsNumber);
698
699 for (size_t idx = 0U; idx < typeArgumentsNumber; ++idx) {
700 auto *typeArg = typeArguments_[idx];
701 auto *sourceTypeArg = sourceTypeArguments[idx];
702 auto *typeParam = typeParams[idx];
703
704 relation->Result(false);
705 if (typeArg->IsWildcardType() || sourceTypeArg->IsWildcardType()) {
706 continue;
707 }
708 if (typeParam->IsOut()) {
709 relation->IsSupertypeOf(typeArg, sourceTypeArg);
710 } else if (typeParam->IsIn()) {
711 relation->IsSupertypeOf(sourceTypeArg, typeArg);
712 } else {
713 relation->IsIdenticalTo(typeArg, sourceTypeArg);
714 }
715
716 if (!relation->IsTrue()) {
717 return;
718 }
719 }
720
721 relation->Result(true);
722 }
723
AsSuper(Checker * checker,varbinder::Variable * sourceVar)724 Type *ETSObjectType::AsSuper(Checker *checker, varbinder::Variable *sourceVar)
725 {
726 if (sourceVar == nullptr) {
727 return nullptr;
728 }
729
730 if (variable_ == sourceVar) {
731 return this;
732 }
733
734 if (HasObjectFlag(ETSObjectFlags::INTERFACE)) {
735 Type *res = nullptr;
736 for (auto *const it : checker->AsETSChecker()->GetInterfaces(this)) {
737 res = it->AsSuper(checker, sourceVar);
738 if (res != nullptr) {
739 return res;
740 }
741 }
742 return checker->GetGlobalTypesHolder()->GlobalETSObjectType()->AsSuper(checker, sourceVar);
743 }
744
745 Type *const superType = checker->AsETSChecker()->GetSuperType(this);
746
747 if (superType == nullptr) {
748 return nullptr;
749 }
750
751 if (!superType->IsETSObjectType()) {
752 return nullptr;
753 }
754
755 if (ETSObjectType *const superObj = superType->AsETSObjectType(); superObj->HasObjectFlag(ETSObjectFlags::CLASS)) {
756 Type *const res = superObj->AsSuper(checker, sourceVar);
757 if (res != nullptr) {
758 return res;
759 }
760 }
761
762 if (sourceVar->TsType()->IsETSObjectType() &&
763 sourceVar->TsType()->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) {
764 for (auto *const it : checker->AsETSChecker()->GetInterfaces(this)) {
765 Type *const res = it->AsSuper(checker, sourceVar);
766 if (res != nullptr) {
767 return res;
768 }
769 }
770 }
771
772 return nullptr;
773 }
774
CopyProperty(varbinder::LocalVariable * prop,ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)775 varbinder::LocalVariable *ETSObjectType::CopyProperty(varbinder::LocalVariable *prop, ArenaAllocator *allocator,
776 TypeRelation *relation, GlobalTypesHolder *globalTypes)
777 {
778 auto *const copiedProp = prop->Copy(allocator, prop->Declaration());
779 auto *const copiedPropType = ETSChecker::TryToInstantiate(
780 relation->GetChecker()->AsETSChecker()->GetTypeOfVariable(prop), allocator, relation, globalTypes);
781 // NOTE: don't change type variable if it differs from copying one!
782 if (copiedPropType->Variable() == prop) {
783 copiedPropType->SetVariable(copiedProp);
784 }
785 copiedProp->SetTsType(copiedPropType);
786 return copiedProp;
787 }
788
Instantiate(ArenaAllocator * const allocator,TypeRelation * const relation,GlobalTypesHolder * const globalTypes)789 Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation *const relation,
790 GlobalTypesHolder *const globalTypes)
791 {
792 auto *const checker = relation->GetChecker()->AsETSChecker();
793 std::lock_guard guard {*checker->Mutex()};
794 auto *const base = GetOriginalBaseType();
795
796 if (!relation->TypeInstantiationPossible(base)) {
797 return this;
798 }
799 relation->IncreaseTypeRecursionCount(base);
800
801 auto *const copiedType = checker->CreateNewETSObjectType(name_, declNode_, flags_);
802 copiedType->typeFlags_ = typeFlags_;
803 copiedType->RemoveObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS |
804 ETSObjectFlags::INCOMPLETE_INSTANTIATION | ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY);
805 copiedType->SetAssemblerName(assemblerName_);
806 copiedType->SetVariable(variable_);
807 copiedType->SetSuperType(superType_);
808
809 for (auto *const it : interfaces_) {
810 copiedType->AddInterface(it);
811 }
812
813 for (auto *const typeArgument : TypeArguments()) {
814 copiedType->TypeArguments().emplace_back(typeArgument->Instantiate(allocator, relation, globalTypes));
815 }
816 copiedType->SetBaseType(this);
817 copiedType->propertiesInstantiated_ = false;
818 copiedType->relation_ = relation;
819 copiedType->effectiveSubstitution_ = nullptr;
820
821 relation->DecreaseTypeRecursionCount(base);
822
823 return copiedType;
824 }
825
SubstituteVariableType(TypeRelation * relation,const Substitution * substitution,Type * const varType)826 static Type *SubstituteVariableType(TypeRelation *relation, const Substitution *substitution, Type *const varType)
827 {
828 auto *substitutedType = varType->Substitute(relation, substitution);
829
830 if (varType->HasTypeFlag(TypeFlag::ETS_REQUIRED_TYPE_PARAMETER)) {
831 substitutedType = relation->GetChecker()->AsETSChecker()->HandleRequiredType(substitutedType);
832 }
833
834 return substitutedType;
835 }
836
CopyPropertyWithTypeArguments(varbinder::LocalVariable * prop,TypeRelation * relation,const Substitution * substitution)837 static varbinder::LocalVariable *CopyPropertyWithTypeArguments(varbinder::LocalVariable *prop, TypeRelation *relation,
838 const Substitution *substitution)
839 {
840 auto *const checker = relation->GetChecker()->AsETSChecker();
841 auto *const varType = ETSChecker::IsVariableGetterSetter(prop) ? prop->TsType() : checker->GetTypeOfVariable(prop);
842 auto *const copiedPropType = SubstituteVariableType(relation, substitution, varType);
843 auto *const copiedProp = prop->Copy(checker->Allocator(), prop->Declaration());
844 copiedPropType->SetVariable(copiedProp);
845 copiedProp->SetTsType(copiedPropType);
846 return copiedProp;
847 }
848
GetConstOriginalBaseType() const849 ETSObjectType const *ETSObjectType::GetConstOriginalBaseType() const noexcept
850 {
851 if (auto *baseIter = GetBaseType(); baseIter != nullptr) {
852 auto *baseIterNext = baseIter->GetBaseType();
853 while (baseIterNext != nullptr && baseIterNext != baseIter) {
854 baseIter = baseIterNext;
855 baseIterNext = baseIter->GetBaseType();
856 }
857 return baseIter;
858 }
859 return this;
860 }
861
SubstituteTypeArgs(TypeRelation * const relation,ArenaVector<Type * > & newTypeArgs,const Substitution * const substitution)862 bool ETSObjectType::SubstituteTypeArgs(TypeRelation *const relation, ArenaVector<Type *> &newTypeArgs,
863 const Substitution *const substitution)
864 {
865 bool anyChange = false;
866 newTypeArgs.reserve(typeArguments_.size());
867
868 for (auto *const arg : typeArguments_) {
869 auto *const newArg = arg->Substitute(relation, substitution);
870 newTypeArgs.push_back(newArg);
871 anyChange = anyChange || (newArg != arg);
872 }
873
874 return anyChange;
875 }
876
ComputeEffectiveSubstitution(TypeRelation * const relation,const ArenaVector<Type * > & baseTypeParams,ArenaVector<Type * > & newTypeArgs)877 static Substitution *ComputeEffectiveSubstitution(TypeRelation *const relation,
878 const ArenaVector<Type *> &baseTypeParams,
879 ArenaVector<Type *> &newTypeArgs)
880 {
881 ASSERT(baseTypeParams.size() == newTypeArgs.size());
882 auto *const checker = relation->GetChecker()->AsETSChecker();
883 auto *effectiveSubstitution = checker->NewSubstitution();
884
885 for (size_t ix = 0; ix < baseTypeParams.size(); ix++) {
886 ETSChecker::EmplaceSubstituted(effectiveSubstitution, baseTypeParams[ix]->AsETSTypeParameter(),
887 newTypeArgs[ix]);
888 }
889
890 return effectiveSubstitution;
891 }
892
SetCopiedTypeProperties(TypeRelation * const relation,ETSObjectType * const copiedType,ArenaVector<Type * > && newTypeArgs,ETSObjectType * base)893 void ETSObjectType::SetCopiedTypeProperties(TypeRelation *const relation, ETSObjectType *const copiedType,
894 ArenaVector<Type *> &&newTypeArgs, ETSObjectType *base)
895 {
896 copiedType->typeFlags_ = typeFlags_;
897 copiedType->RemoveObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS |
898 ETSObjectFlags::INCOMPLETE_INSTANTIATION | ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY);
899 copiedType->SetVariable(variable_);
900 copiedType->SetBaseType(base);
901
902 auto const &baseTypeParams = base->TypeArguments();
903 copiedType->effectiveSubstitution_ = ComputeEffectiveSubstitution(relation, baseTypeParams, newTypeArgs);
904
905 copiedType->SetTypeArguments(std::move(newTypeArgs));
906 copiedType->relation_ = relation;
907 }
908
UpdateTypeProperty(checker::ETSChecker * checker,varbinder::LocalVariable * const prop,PropertyType fieldType,PropertyProcesser const & func)909 void ETSObjectType::UpdateTypeProperty(checker::ETSChecker *checker, varbinder::LocalVariable *const prop,
910 PropertyType fieldType, PropertyProcesser const &func)
911 {
912 auto *const propType = prop->Declaration()->Node()->Check(checker);
913
914 if (propType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) {
915 checker->ThrowTypeError("Base type of a Utility type can only contain fields with reference type.",
916 prop->Declaration()->Node()->Start());
917 }
918
919 auto *const propCopy = func(prop, propType);
920 if (fieldType == PropertyType::INSTANCE_FIELD) {
921 RemoveProperty<PropertyType::INSTANCE_FIELD>(prop);
922 AddProperty<PropertyType::INSTANCE_FIELD>(propCopy);
923 } else {
924 RemoveProperty<PropertyType::STATIC_FIELD>(prop);
925 AddProperty<PropertyType::STATIC_FIELD>(propCopy);
926 }
927 }
928
UpdateTypeProperties(checker::ETSChecker * checker,PropertyProcesser const & func)929 void ETSObjectType::UpdateTypeProperties(checker::ETSChecker *checker, PropertyProcesser const &func)
930 {
931 AddObjectFlag(ETSObjectFlags::READONLY);
932 for (auto const &prop : InstanceFields()) {
933 UpdateTypeProperty(checker, prop.second, PropertyType::INSTANCE_FIELD, func);
934 }
935
936 for (auto const &prop : StaticFields()) {
937 UpdateTypeProperty(checker, prop.second, PropertyType::STATIC_FIELD, func);
938 }
939
940 if (SuperType() != nullptr) {
941 auto *const superProp = SuperType()->Clone(checker)->AsETSObjectType();
942 superProp->UpdateTypeProperties(checker, func);
943 SetSuperType(superProp);
944 }
945 }
946
Substitute(TypeRelation * relation,const Substitution * substitution,bool cache)947 ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution, bool cache)
948 {
949 if (substitution == nullptr || substitution->empty()) {
950 return this;
951 }
952
953 auto *const checker = relation->GetChecker()->AsETSChecker();
954 auto *base = GetOriginalBaseType();
955
956 ArenaVector<Type *> newTypeArgs {checker->Allocator()->Adapter()};
957 const bool anyChange = SubstituteTypeArgs(relation, newTypeArgs, substitution);
958 // Lambda types can capture type params in their bodies, normal classes cannot.
959 // NOTE: gogabr. determine precise conditions where we do not need to copy.
960 // Perhaps keep track of captured type parameters for each type.
961 if (!anyChange && !HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) {
962 return this;
963 }
964
965 const util::StringView hash = checker->GetHashFromSubstitution(substitution);
966 if (cache) {
967 if (auto *inst = GetInstantiatedType(hash); inst != nullptr) {
968 return inst;
969 }
970 }
971
972 if (!relation->TypeInstantiationPossible(base)) {
973 return this;
974 }
975 relation->IncreaseTypeRecursionCount(base);
976
977 auto *const copiedType = checker->CreateNewETSObjectType(name_, declNode_, flags_);
978 SetCopiedTypeProperties(relation, copiedType, std::move(newTypeArgs), base);
979
980 if (cache) {
981 GetInstantiationMap().try_emplace(hash, copiedType);
982 }
983
984 if (superType_ != nullptr) {
985 copiedType->SetSuperType(superType_->Substitute(relation, substitution)->AsETSObjectType());
986 }
987 for (auto *itf : interfaces_) {
988 auto *newItf = itf->Substitute(relation, substitution)->AsETSObjectType();
989 copiedType->AddInterface(newItf);
990 }
991
992 relation->DecreaseTypeRecursionCount(base);
993
994 return copiedType;
995 }
996
Substitute(TypeRelation * relation,const Substitution * substitution)997 ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution)
998 {
999 return Substitute(relation, substitution, true);
1000 }
1001
SubstituteArguments(TypeRelation * relation,ArenaVector<Type * > const & arguments)1002 ETSObjectType *ETSObjectType::SubstituteArguments(TypeRelation *relation, ArenaVector<Type *> const &arguments)
1003 {
1004 if (arguments.empty()) {
1005 return this;
1006 }
1007
1008 auto *checker = relation->GetChecker()->AsETSChecker();
1009 auto *substitution = checker->NewSubstitution();
1010
1011 ASSERT(baseType_ == nullptr);
1012 ASSERT(typeArguments_.size() == arguments.size());
1013
1014 for (size_t ix = 0; ix < typeArguments_.size(); ix++) {
1015 substitution->emplace(typeArguments_[ix]->AsETSTypeParameter(),
1016 checker->MaybePromotedBuiltinType(arguments[ix]));
1017 }
1018
1019 return Substitute(relation, substitution);
1020 }
1021
InstantiateProperties() const1022 void ETSObjectType::InstantiateProperties() const
1023 {
1024 ASSERT(relation_ != nullptr);
1025 auto *checker = relation_->GetChecker()->AsETSChecker();
1026
1027 if (baseType_ == nullptr || baseType_ == this) {
1028 checker->ResolveDeclaredMembersOfObject(this);
1029 return;
1030 }
1031
1032 ASSERT(!propertiesInstantiated_);
1033 declNode_->Check(checker);
1034
1035 for (auto *const it : baseType_->ConstructSignatures()) {
1036 auto *newSig = it->Substitute(relation_, effectiveSubstitution_);
1037 constructSignatures_.push_back(newSig);
1038 }
1039
1040 for (auto const &[_, prop] : baseType_->InstanceFields()) {
1041 (void)_;
1042 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1043 properties_[static_cast<size_t>(PropertyType::INSTANCE_FIELD)].emplace(prop->Name(), copiedProp);
1044 }
1045
1046 for (auto const &[_, prop] : baseType_->StaticFields()) {
1047 (void)_;
1048 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1049 properties_[static_cast<size_t>(PropertyType::STATIC_FIELD)].emplace(prop->Name(), copiedProp);
1050 }
1051
1052 for (auto const &[_, prop] : baseType_->InstanceMethods()) {
1053 (void)_;
1054 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1055 properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)].emplace(prop->Name(), copiedProp);
1056 }
1057
1058 for (auto const &[_, prop] : baseType_->StaticMethods()) {
1059 (void)_;
1060 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1061 properties_[static_cast<size_t>(PropertyType::STATIC_METHOD)].emplace(prop->Name(), copiedProp);
1062 }
1063
1064 for (auto const &[_, prop] : baseType_->InstanceDecls()) {
1065 (void)_;
1066 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1067 properties_[static_cast<size_t>(PropertyType::INSTANCE_DECL)].emplace(prop->Name(), copiedProp);
1068 }
1069
1070 for (auto const &[_, prop] : baseType_->StaticDecls()) {
1071 (void)_;
1072 auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_);
1073 properties_[static_cast<size_t>(PropertyType::STATIC_DECL)].emplace(prop->Name(), copiedProp);
1074 }
1075 }
1076
DebugInfoTypeFromName(std::stringstream & ss,util::StringView asmName)1077 void ETSObjectType::DebugInfoTypeFromName(std::stringstream &ss, util::StringView asmName)
1078 {
1079 ss << compiler::Signatures::CLASS_REF_BEGIN;
1080 auto copied = asmName.Mutf8();
1081 std::replace(copied.begin(), copied.end(), *compiler::Signatures::METHOD_SEPARATOR.begin(),
1082 *compiler::Signatures::NAMESPACE_SEPARATOR.begin());
1083 ss << copied;
1084 ss << compiler::Signatures::MANGLE_SEPARATOR;
1085 }
1086
GetPrecedence(checker::ETSChecker * checker,ETSObjectType const * type)1087 std::uint32_t ETSObjectType::GetPrecedence(checker::ETSChecker *checker, ETSObjectType const *type) noexcept
1088 {
1089 ASSERT(type != nullptr);
1090 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) {
1091 return 1U;
1092 }
1093 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) {
1094 return 2U;
1095 }
1096 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) {
1097 return 3U;
1098 }
1099 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) {
1100 return 4U;
1101 }
1102 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) {
1103 return 5U;
1104 }
1105 if (checker->Relation()->IsIdenticalTo(const_cast<ETSObjectType *>(type),
1106 checker->GetGlobalTypesHolder()->GlobalIntegralBuiltinType())) {
1107 return 5U;
1108 }
1109 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) {
1110 return 6U;
1111 }
1112 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) {
1113 return 7U;
1114 }
1115 if (checker->Relation()->IsIdenticalTo(const_cast<ETSObjectType *>(type),
1116 checker->GetGlobalTypesHolder()->GlobalFloatingBuiltinType())) {
1117 return 7U;
1118 }
1119 if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_BIGINT)) {
1120 return 8U;
1121 }
1122 return 0U;
1123 }
AddReExports(ETSObjectType * reExport)1124 void ETSObjectType::AddReExports(ETSObjectType *reExport)
1125 {
1126 if (std::find(reExports_.begin(), reExports_.end(), reExport) == reExports_.end()) {
1127 reExports_.push_back(reExport);
1128 }
1129 }
1130
AddReExportAlias(util::StringView const & value,util::StringView const & key)1131 void ETSObjectType::AddReExportAlias(util::StringView const &value, util::StringView const &key)
1132 {
1133 reExportAlias_.insert({key, value});
1134 }
1135
GetReExportAliasValue(util::StringView const & key) const1136 util::StringView ETSObjectType::GetReExportAliasValue(util::StringView const &key) const
1137 {
1138 auto ret = reExportAlias_.find(key);
1139 if (reExportAlias_.end() == ret) {
1140 return key;
1141 }
1142 return ret->second;
1143 }
1144
IsReExportHaveAliasValue(util::StringView const & key) const1145 bool ETSObjectType::IsReExportHaveAliasValue(util::StringView const &key) const
1146 {
1147 return std::any_of(reExportAlias_.begin(), reExportAlias_.end(),
1148 [&](const auto &val) { return val.second == key; });
1149 }
1150
ReExports() const1151 const ArenaVector<ETSObjectType *> &ETSObjectType::ReExports() const
1152 {
1153 return reExports_;
1154 }
1155
ToAssemblerType(std::stringstream & ss) const1156 void ETSObjectType::ToAssemblerType([[maybe_unused]] std::stringstream &ss) const
1157 {
1158 ss << assemblerName_;
1159 }
1160
ToDebugInfoType(std::stringstream & ss) const1161 void ETSObjectType::ToDebugInfoType(std::stringstream &ss) const
1162 {
1163 DebugInfoTypeFromName(ss, assemblerName_);
1164 }
1165
ToDebugInfoSignatureType(std::stringstream & ss) const1166 void ETSObjectType::ToDebugInfoSignatureType(std::stringstream &ss) const
1167 {
1168 ss << compiler::Signatures::GENERIC_BEGIN;
1169 ss << assemblerName_;
1170 ss << compiler::Signatures::GENERIC_END;
1171 }
1172
1173 } // namespace ark::es2panda::checker
1174