• 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     bool needParens = (element_->IsETSUnionType() || element_->IsETSFunctionType());
27     if (needParens) {
28         ss << "(";
29     }
30     element_->ToString(ss, precise);
31     if (needParens) {
32         ss << ")";
33     }
34     ss << "[]";
35 }
36 
ToAssemblerType(std::stringstream & ss) const37 void ETSArrayType::ToAssemblerType(std::stringstream &ss) const
38 {
39     element_->ToAssemblerType(ss);
40 }
41 
ToAssemblerTypeWithRank(std::stringstream & ss) const42 void ETSArrayType::ToAssemblerTypeWithRank(std::stringstream &ss) const
43 {
44     element_->ToAssemblerType(ss);
45 
46     for (uint32_t i = Rank(); i > 0; --i) {
47         ss << "[]";
48     }
49 }
50 
ToDebugInfoType(std::stringstream & ss) const51 void ETSArrayType::ToDebugInfoType(std::stringstream &ss) const
52 {
53     ss << "[";
54     element_->ToDebugInfoType(ss);
55 }
56 
Rank() const57 uint32_t ETSArrayType::Rank() const
58 {
59     uint32_t rank = 1;
60     auto iter = element_;
61     while (iter->IsETSArrayType()) {
62         iter = iter->AsETSArrayType()->ElementType();
63         rank++;
64     }
65 
66     return rank;
67 }
68 
Identical(TypeRelation * relation,Type * other)69 void ETSArrayType::Identical(TypeRelation *relation, Type *other)
70 {
71     if (other->IsETSArrayType()) {
72         // will be removed, if wildcard type is assigned to array type, not element type
73         if (element_->IsWildcardType() || other->AsETSArrayType()->ElementType()->IsWildcardType()) {
74             relation->Result(true);
75             return;
76         }
77         relation->IsIdenticalTo(element_, other->AsETSArrayType()->ElementType());
78     }
79 }
80 
AssignmentTarget(TypeRelation * relation,Type * source)81 void ETSArrayType::AssignmentTarget(TypeRelation *relation, Type *source)
82 {
83     if (source->IsETSArrayType()) {
84         if (AsETSArrayType()->ElementType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) ||
85             source->AsETSArrayType()->ElementType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) {
86             return;
87         }
88         relation->IsAssignableTo(source->AsETSArrayType()->ElementType(), element_);
89     }
90 }
91 
Cast(TypeRelation * const relation,Type * const target)92 void ETSArrayType::Cast(TypeRelation *const relation, Type *const target)
93 {
94     if (target->HasTypeFlag(TypeFlag::ETS_ARRAY)) {
95         conversion::Identity(relation, this, target->AsETSArrayType());
96         if (relation->IsTrue()) {
97             return;
98         }
99 
100         conversion::WideningReference(relation, this, target->AsETSArrayType());
101         if (relation->IsTrue()) {
102             return;
103         }
104 
105         conversion::NarrowingReference(relation, this, target->AsETSArrayType());
106         if (relation->IsTrue()) {
107             return;
108         }
109 
110         if (ElementType()->IsETSTypeParameter()) {
111             // unchecked cast!
112             relation->Result(true);
113             return;
114         }
115 
116         conversion::Forbidden(relation);
117         return;
118     }
119 
120     if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) {
121         conversion::WideningReference(relation, this, target->AsETSObjectType());
122         if (relation->IsTrue()) {
123             return;
124         }
125 
126         conversion::Forbidden(relation);
127         return;
128     }
129 
130     conversion::Forbidden(relation);
131 }
132 
IsSupertypeOf(TypeRelation * const relation,Type * source)133 void ETSArrayType::IsSupertypeOf(TypeRelation *const relation, Type *source)
134 {
135     relation->Result(false);
136     // 3.8.3 Subtyping among Array Types
137     if (source->IsETSArrayType()) {
138         auto *const sourceElemType = this->AsETSArrayType()->ElementType();
139         auto *const targetElemType = source->AsETSArrayType()->ElementType();
140         if (targetElemType->IsETSReferenceType() && sourceElemType->IsETSReferenceType()) {
141             sourceElemType->IsSupertypeOf(relation, targetElemType);
142         }
143     }
144 }
145 
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)146 Type *ETSArrayType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
147 {
148     return relation->GetChecker()->AsETSChecker()->CreateETSArrayType(
149         element_->Instantiate(allocator, relation, globalTypes));
150 }
151 
Substitute(TypeRelation * relation,const Substitution * substitution)152 Type *ETSArrayType::Substitute(TypeRelation *relation, const Substitution *substitution)
153 {
154     if (substitution == nullptr || substitution->empty()) {
155         return this;
156     }
157 
158     auto *resultElt = element_->Substitute(relation, substitution);
159     return resultElt == element_ ? this : relation->GetChecker()->AsETSChecker()->CreateETSArrayType(resultElt);
160 }
161 
162 }  // namespace ark::es2panda::checker
163