1 /**
2 * Copyright (c) 2021 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 #ifndef ES2PANDA_COMPILER_TYPESCRIPT_TYPES_OBJECT_TYPE_H
17 #define ES2PANDA_COMPILER_TYPESCRIPT_TYPES_OBJECT_TYPE_H
18
19 #include "type.h"
20
21 #include <typescript/types/objectDescriptor.h>
22 #include <binder/variable.h>
23
24 #include <util/ustring.h>
25 #include <util/enumbitops.h>
26
27 namespace panda::es2panda::binder {
28 class LocalVariable;
29 } // namespace panda::es2panda::binder
30
31 namespace panda::es2panda::checker {
32
33 class Signature;
34 class IndexInfo;
35
36 #define DECLARE_OBJECT_TYPENAMES(objectKind, typeName) class typeName;
37 OBJECT_TYPE_MAPPING(DECLARE_OBJECT_TYPENAMES)
38 #undef DECLARE_OBJECT_TYPENAMES
39
40 enum class ObjectFlags {
41 NO_OPTS = 0,
42 CHECK_EXCESS_PROPS = 1 << 0,
43 RESOLVED_MEMBERS = 1 << 1,
44 RESOLVED_BASE_TYPES = 1 << 2,
45 RESOLVED_DECLARED_MEMBERS = 1 << 3,
46 };
47
DEFINE_BITOPS(ObjectFlags)48 DEFINE_BITOPS(ObjectFlags)
49
50 class ObjectType : public Type {
51 public:
52 enum class ObjectTypeKind {
53 LITERAL,
54 CLASS,
55 INTERFACE,
56 TUPLE,
57 FUNCTION,
58 };
59
60 #define OBJECT_TYPE_IS_CHECKS(objectKind, typeName) \
61 bool Is##typeName() const \
62 { \
63 return kind_ == objectKind; \
64 }
65 OBJECT_TYPE_MAPPING(OBJECT_TYPE_IS_CHECKS)
66 #undef OBJECT_TYPE_IS_CHECKS
67
68 #define OBJECT_TYPE_AS_CASTS(objectKind, typeName) \
69 typeName *As##typeName() \
70 { \
71 ASSERT(Is##typeName()); \
72 return reinterpret_cast<typeName *>(this); \
73 } \
74 const typeName *As##typeName() const \
75 { \
76 ASSERT(Is##typeName()); \
77 return reinterpret_cast<const typeName *>(this); \
78 }
79 OBJECT_TYPE_MAPPING(OBJECT_TYPE_AS_CASTS)
80 #undef OBJECT_TYPE_AS_CASTS
81
82 explicit ObjectType(ObjectType::ObjectTypeKind kind)
83 : Type(TypeFlag::OBJECT), kind_(kind), desc_(nullptr), objFlag_(ObjectFlags::NO_OPTS)
84 {
85 }
86
87 ObjectType(ObjectType::ObjectTypeKind kind, ObjectDescriptor *desc)
88 : Type(TypeFlag::OBJECT), kind_(kind), desc_(desc), objFlag_(ObjectFlags::NO_OPTS)
89 {
90 }
91
92 ObjectType::ObjectTypeKind Kind() const
93 {
94 return kind_;
95 }
96
97 virtual ArenaVector<Signature *> CallSignatures()
98 {
99 return desc_->callSignatures;
100 }
101
102 virtual ArenaVector<Signature *> ConstructSignatures()
103 {
104 return desc_->constructSignatures;
105 }
106
107 virtual const IndexInfo *StringIndexInfo() const
108 {
109 return desc_->stringIndexInfo;
110 }
111
112 virtual const IndexInfo *NumberIndexInfo() const
113 {
114 return desc_->numberIndexInfo;
115 }
116
117 virtual IndexInfo *StringIndexInfo()
118 {
119 return desc_->stringIndexInfo;
120 }
121
122 virtual IndexInfo *NumberIndexInfo()
123 {
124 return desc_->numberIndexInfo;
125 }
126
127 virtual ArenaVector<binder::LocalVariable *> Properties()
128 {
129 return desc_->properties;
130 }
131
132 ObjectDescriptor *Desc()
133 {
134 return desc_;
135 }
136
137 const ObjectDescriptor *Desc() const
138 {
139 return desc_;
140 }
141
142 void AddProperty(binder::LocalVariable *prop)
143 {
144 desc_->properties.push_back(prop);
145 }
146
147 virtual binder::LocalVariable *GetProperty(const util::StringView &name, [[maybe_unused]] bool searchInBase) const
148 {
149 for (auto *it : desc_->properties) {
150 if (name == it->Name()) {
151 return it;
152 }
153 }
154
155 return nullptr;
156 }
157
158 void AddCallSignature(Signature *signature)
159 {
160 desc_->callSignatures.push_back(signature);
161 }
162
163 void AddConstructSignature(Signature *signature)
164 {
165 desc_->constructSignatures.push_back(signature);
166 }
167
168 void AddObjectFlag(ObjectFlags flag)
169 {
170 objFlag_ |= flag;
171 }
172
173 void RemoveObjectFlag(ObjectFlags flag)
174 {
175 flag &= ~flag;
176 }
177
178 bool HasObjectFlag(ObjectFlags flag) const
179 {
180 return (objFlag_ & flag) != 0;
181 }
182
183 static bool SignatureRelatedToSomeSignature(TypeRelation *relation, Signature *sourceSignature,
184 ArenaVector<Signature *> *targetSignatures);
185
186 static bool EachSignatureRelatedToSomeSignature(TypeRelation *relation,
187 const ArenaVector<Signature *> &sourceSignatures,
188 const ArenaVector<Signature *> &targetSignatures);
189
190 void Identical(TypeRelation *relation, Type *other) override;
191 void AssignmentTarget(TypeRelation *relation, Type *source) override;
192
193 void checkExcessProperties(TypeRelation *relation, ObjectType *source);
194 void AssignProperties(TypeRelation *relation, ObjectType *source);
195 void AssignSignatures(TypeRelation *relation, ObjectType *source, bool assignCallSignatures = true);
196 void AssignIndexInfo(TypeRelation *relation, ObjectType *source, bool assignNumberInfo = true);
197
198 protected:
199 ObjectTypeKind kind_;
200 ObjectDescriptor *desc_;
201 ObjectFlags objFlag_;
202 };
203
204 } // namespace panda::es2panda::checker
205
206 #endif /* TYPESCRIPT_TYPES_OBJECT_TYPE_H */
207