• 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 "etsTypeParameter.h"
17 #include "ir/expressions/identifier.h"
18 #include "ir/ts/tsTypeParameter.h"
19 #include "checker/ETSchecker.h"
20 #include "checker/ets/conversion.h"
21 
22 namespace panda::es2panda::checker {
ToString(std::stringstream & ss) const23 void ETSTypeParameter::ToString(std::stringstream &ss) const
24 {
25     ss << declNode_->Name()->Name();
26 
27     if (IsNullish()) {
28         if (ContainsNull()) {
29             ss << "|null";
30         }
31         if (ContainsUndefined()) {
32             ss << "|undefined";
33         }
34     }
35 }
36 
Identical(TypeRelation * relation,Type * other)37 void ETSTypeParameter::Identical([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *other)
38 {
39     if ((ContainsNull() != other->ContainsNull()) || (ContainsUndefined() != other->ContainsUndefined())) {
40         return;
41     }
42 
43     if (other->IsETSTypeParameter() && other->AsETSTypeParameter()->GetOriginal() == GetOriginal()) {
44         relation->Result(true);
45     }
46 }
47 
AssignmentSource(TypeRelation * relation,Type * target)48 bool ETSTypeParameter::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target)
49 {
50     return relation->Result(false);
51 }
52 
AssignmentTarget(TypeRelation * relation,Type * source)53 void ETSTypeParameter::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source)
54 {
55     if (source->IsETSNullType()) {
56         relation->Result(ContainsNull());
57         return;
58     }
59     if (source->IsETSUndefinedType()) {
60         relation->Result(ContainsUndefined());
61         return;
62     }
63 
64     if ((source->ContainsNull() && !ContainsNull()) || (source->ContainsUndefined() && !ContainsUndefined())) {
65         relation->Result(false);
66         return;
67     }
68     if (source->IsETSTypeParameter() && source->AsETSTypeParameter()->GetOriginal() == GetOriginal()) {
69         relation->Result(true);
70         return;
71     }
72 
73     relation->IsSupertypeOf(this, source);
74 }
75 
Cast(TypeRelation * relation,Type * target)76 void ETSTypeParameter::Cast(TypeRelation *relation, Type *target)
77 {
78     if (relation->IsSupertypeOf(target, this)) {
79         relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST);
80         return;
81     }
82 
83     // NOTE(vpukhov): adjust UNCHECKED_CAST flags
84     if (target->IsETSObjectType()) {
85         relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST);
86     }
87     relation->Result(relation->InCastingContext());
88 }
89 
CastTarget(TypeRelation * relation,Type * source)90 void ETSTypeParameter::CastTarget(TypeRelation *relation, Type *source)
91 {
92     if (relation->IsSupertypeOf(this, source)) {
93         relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST);
94         return;
95     }
96 
97     relation->Result(relation->InCastingContext());
98 }
99 
IsSupertypeOf(TypeRelation * relation,Type * source)100 void ETSTypeParameter::IsSupertypeOf([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source)
101 {
102     relation->Result(false);
103 }
104 
IsSubtypeOf(TypeRelation * relation,Type * target)105 void ETSTypeParameter::IsSubtypeOf([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target)
106 {
107     if (relation->IsSupertypeOf(target, GetConstraintType())) {
108         return;
109     }
110 
111     relation->Result(false);
112 }
113 
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)114 Type *ETSTypeParameter::Instantiate([[maybe_unused]] ArenaAllocator *allocator, [[maybe_unused]] TypeRelation *relation,
115                                     [[maybe_unused]] GlobalTypesHolder *globalTypes)
116 {
117     auto *const checker = relation->GetChecker()->AsETSChecker();
118 
119     auto *const copiedType = checker->CreateTypeParameter();
120     copiedType->AddTypeFlag(TypeFlag::GENERIC);
121     copiedType->SetDeclNode(GetDeclNode());
122     copiedType->SetDefaultType(GetDefaultType());
123     copiedType->SetConstraintType(GetConstraintType());
124     copiedType->SetVariable(Variable());
125     return copiedType;
126 }
127 
Substitute(TypeRelation * relation,const Substitution * substitution)128 Type *ETSTypeParameter::Substitute(TypeRelation *relation, const Substitution *substitution)
129 {
130     if (substitution == nullptr || substitution->empty()) {
131         return this;
132     }
133     auto *const checker = relation->GetChecker()->AsETSChecker();
134     auto *original = GetOriginal();
135     if (auto repl = substitution->find(original); repl != substitution->end()) {
136         auto *replType = repl->second;
137         /* Any other flags we need to copy? */
138 
139         /* The check this != base is a kludge to distinguish bare type parameter T
140            with a nullish constraint (like the default Object?) from explicitly nullish T?
141         */
142         if (this != original && ((ContainsNull() && !replType->ContainsNull()) ||
143                                  (ContainsUndefined() && !replType->ContainsUndefined()))) {
144             // this type is explicitly marked as nullish
145             ASSERT(ETSChecker::IsReferenceType(replType));
146             auto nullishFlags = TypeFlag(TypeFlags() & TypeFlag::NULLISH);
147             auto *newReplType = checker->CreateNullishType(replType, nullishFlags, checker->Allocator(), relation,
148                                                            checker->GetGlobalTypesHolder());
149             replType = newReplType;
150         }
151         return replType;
152     }
153 
154     return this;
155 }
156 
ToAssemblerType(std::stringstream & ss) const157 void ETSTypeParameter::ToAssemblerType(std::stringstream &ss) const
158 {
159     GetConstraintType()->ToAssemblerType(ss);
160 }
161 
ToDebugInfoType(std::stringstream & ss) const162 void ETSTypeParameter::ToDebugInfoType(std::stringstream &ss) const
163 {
164     GetConstraintType()->ToDebugInfoType(ss);
165 }
166 
GetOriginal() const167 ETSTypeParameter *ETSTypeParameter::GetOriginal() const
168 {
169     return GetDeclNode()->Name()->Variable()->TsType()->AsETSTypeParameter();
170 }
171 
172 }  // namespace panda::es2panda::checker
173