• 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 "etsArrayType.h"
17 
18 #include "varbinder/variable.h"
19 #include "checker/ETSchecker.h"
20 #include "checker/ets/conversion.h"
21 #include "checker/types/typeRelation.h"
22 
23 namespace ark::es2panda::checker {
ToString(std::stringstream & ss,bool precise) const24 void ETSArrayType::ToString(std::stringstream &ss, bool precise) const
25 {
26     if (HasTypeFlag(TypeFlag::READONLY)) {
27         ss << "readonly ";
28     }
29     bool needParens = (element_->IsETSUnionType() || element_->IsETSFunctionType());
30     if (needParens) {
31         ss << "(";
32     }
33     element_->ToString(ss, precise);
34     if (needParens) {
35         ss << ")";
36     }
37     ss << "[]";
38 }
39 
ToAssemblerType(std::stringstream & ss) const40 void ETSArrayType::ToAssemblerType(std::stringstream &ss) const
41 {
42     element_->ToAssemblerType(ss);
43 }
44 
ToAssemblerTypeWithRank(std::stringstream & ss) const45 void ETSArrayType::ToAssemblerTypeWithRank(std::stringstream &ss) const
46 {
47     element_->ToAssemblerType(ss);
48 
49     for (uint32_t i = Rank(); i > 0; --i) {
50         ss << "[]";
51     }
52 }
53 
ToDebugInfoType(std::stringstream & ss) const54 void ETSArrayType::ToDebugInfoType(std::stringstream &ss) const
55 {
56     ss << "[";
57     element_->ToDebugInfoType(ss);
58 }
59 
Rank() const60 uint32_t ETSArrayType::Rank() const
61 {
62     uint32_t rank = 1;
63     auto iter = element_;
64     while (iter->IsETSArrayType() && iter->AsETSArrayType()->ElementType() != iter) {
65         iter = iter->AsETSArrayType()->ElementType();
66         rank++;
67     }
68 
69     return rank;
70 }
71 
Identical(TypeRelation * relation,Type * other)72 void ETSArrayType::Identical(TypeRelation *relation, Type *other)
73 {
74     if (other->IsETSArrayType()) {
75         // will be removed, if wildcard type is assigned to array type, not element type
76         if (element_->IsWildcardType() || other->AsETSArrayType()->ElementType()->IsWildcardType()) {
77             relation->Result(true);
78             return;
79         }
80         relation->IsIdenticalTo(element_, other->AsETSArrayType()->ElementType());
81     }
82 }
83 
AssignmentTarget(TypeRelation * relation,Type * source)84 void ETSArrayType::AssignmentTarget(TypeRelation *relation, Type *source)
85 {
86     if (source->HasTypeFlag(TypeFlag::READONLY)) {
87         relation->Result(false);
88         return;
89     }
90     if (source->IsETSArrayType()) {
91         if (AsETSArrayType()->ElementType()->IsETSPrimitiveType() ||
92             source->AsETSArrayType()->ElementType()->IsETSPrimitiveType()) {
93             return;
94         }
95         relation->IsAssignableTo(source->AsETSArrayType()->ElementType(), element_);
96     }
97 }
98 
Cast(TypeRelation * const relation,Type * const target)99 void ETSArrayType::Cast(TypeRelation *const relation, Type *const target)
100 {
101     if (target->HasTypeFlag(TypeFlag::ETS_ARRAY)) {
102         conversion::Identity(relation, this, target->AsETSArrayType());
103         if (relation->IsTrue()) {
104             return;
105         }
106 
107         conversion::WideningReference(relation, this, target->AsETSArrayType());
108         if (relation->IsTrue()) {
109             return;
110         }
111 
112         conversion::NarrowingReference(relation, this, target->AsETSArrayType());
113         if (relation->IsTrue()) {
114             return;
115         }
116 
117         if (ElementType()->IsETSTypeParameter()) {
118             // unchecked cast!
119             relation->Result(true);
120             return;
121         }
122 
123         conversion::Forbidden(relation);
124         return;
125     }
126 
127     if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) {
128         conversion::WideningReference(relation, this, target->AsETSObjectType());
129         if (relation->IsTrue()) {
130             return;
131         }
132 
133         conversion::Forbidden(relation);
134         return;
135     }
136 
137     conversion::Forbidden(relation);
138 }
139 
IsSupertypeOf(TypeRelation * const relation,Type * source)140 void ETSArrayType::IsSupertypeOf(TypeRelation *const relation, Type *source)
141 {
142     relation->Result(false);
143     // 3.8.3 Subtyping among Array Types
144     if (source->IsETSArrayType()) {
145         auto *const sourceElemType = this->AsETSArrayType()->ElementType();
146         auto *const targetElemType = source->AsETSArrayType()->ElementType();
147         if (targetElemType->IsETSReferenceType() && sourceElemType->IsETSReferenceType()) {
148             sourceElemType->IsSupertypeOf(relation, targetElemType);
149         }
150     }
151 }
152 
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)153 Type *ETSArrayType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
154 {
155     auto *elementType = element_->Instantiate(allocator, relation, globalTypes);
156     bool needAllocator = HasTypeFlag(TypeFlag::READONLY);
157     ETSArrayType *arrayType = needAllocator ? relation->GetChecker()->Allocator()->New<ETSArrayType>(elementType)
158                                             : relation->GetChecker()->AsETSChecker()->CreateETSArrayType(elementType);
159     arrayType->typeFlags_ = typeFlags_;
160     return arrayType;
161 }
162 
Substitute(TypeRelation * relation,const Substitution * substitution)163 Type *ETSArrayType::Substitute(TypeRelation *relation, const Substitution *substitution)
164 {
165     if (substitution == nullptr || substitution->empty()) {
166         return this;
167     }
168 
169     auto *resultElt = element_->Substitute(relation, substitution);
170 
171     if (resultElt == element_) {
172         return this;
173     }
174 
175     ETSArrayType *result = relation->GetChecker()->AsETSChecker()->CreateETSArrayType(resultElt);
176     result->typeFlags_ = typeFlags_;
177     return result;
178 }
179 
180 }  // namespace ark::es2panda::checker
181