1 /*
2 * Copyright (c) 2021-2025 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 "etsDynamicType.h"
17 #include "checker/ETSchecker.h"
18 #include "checker/ets/conversion.h"
19 #include "checker/types/ets/etsDynamicFunctionType.h"
20
21 namespace ark::es2panda::checker {
22
GetPropertyDynamic(const util::StringView & name,const ETSChecker * checker) const23 varbinder::LocalVariable *ETSDynamicType::GetPropertyDynamic(const util::StringView &name,
24 const ETSChecker *checker) const
25 {
26 auto it = propertiesCache_.find(name);
27 if (it != propertiesCache_.end()) {
28 return it->second;
29 }
30
31 varbinder::LocalVariable *var = varbinder::Scope::CreateVar<varbinder::PropertyDecl>(
32 Allocator(), name, varbinder::VariableFlags::BUILTIN_TYPE, nullptr);
33 ES2PANDA_ASSERT(var != nullptr);
34 var->SetTsType(checker->GlobalBuiltinDynamicType(lang_));
35 propertiesCache_.emplace(name, var);
36
37 return var;
38 }
39
AssignmentTarget(TypeRelation * relation,Type * source)40 void ETSDynamicType::AssignmentTarget(TypeRelation *relation, Type *source)
41 {
42 if (hasDecl_) {
43 return ETSObjectType::AssignmentTarget(relation, source);
44 }
45
46 if (relation->ApplyBoxing() && !relation->IsTrue() && IsConvertible(source)) {
47 relation->Result(true);
48 return;
49 }
50
51 if (source->IsETSDynamicType()) {
52 relation->Result(true);
53 }
54 }
55
AssignmentSource(TypeRelation * relation,Type * target)56 bool ETSDynamicType::AssignmentSource(TypeRelation *relation, Type *target)
57 {
58 if (hasDecl_) {
59 return ETSObjectType::AssignmentSource(relation, target);
60 }
61
62 if (relation->ApplyUnboxing() && IsConvertible(target)) {
63 relation->Result(true);
64 return true;
65 }
66
67 if (target->IsETSDynamicType()) {
68 relation->Result(true);
69 }
70 return relation->IsTrue();
71 }
72
Cast(TypeRelation * relation,Type * target)73 void ETSDynamicType::Cast(TypeRelation *relation, Type *target)
74 {
75 if (hasDecl_) {
76 return ETSObjectType::Cast(relation, target);
77 }
78
79 if (relation->InCastingContext() || IsConvertible(target)) {
80 relation->Result(true);
81 return;
82 }
83
84 conversion::Forbidden(relation);
85 }
86
CastTarget(TypeRelation * relation,Type * source)87 void ETSDynamicType::CastTarget(TypeRelation *relation, Type *source)
88 {
89 if (hasDecl_) {
90 ETSObjectType::CastTarget(relation, source);
91 return;
92 }
93
94 if (relation->InCastingContext() || IsConvertible(source)) {
95 relation->Result(true);
96 return;
97 }
98
99 conversion::Forbidden(relation);
100 }
101
IsConvertible(Type const * target)102 bool ETSDynamicType::IsConvertible(Type const *target)
103 {
104 return target->IsETSDynamicType() || target->IsETSObjectType() || target->IsETSArrayType() ||
105 target->IsETSTupleType() || target->IsETSFunctionType() ||
106 target->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC | checker::TypeFlag::ETS_BOOLEAN);
107 }
108
CreateMethodTypeForProp(const util::StringView & name) const109 ETSFunctionType *ETSDynamicType::CreateMethodTypeForProp(const util::StringView &name) const
110 {
111 auto checker = GetRelation()->GetChecker()->AsETSChecker();
112 return checker->CreateETSDynamicMethodType(name, {{}, Allocator()->Adapter()}, lang_);
113 }
114
ToAssemblerType(std::stringstream & ss) const115 void ETSDynamicType::ToAssemblerType(std::stringstream &ss) const
116 {
117 ss << compiler::Signatures::Dynamic::Type(lang_);
118 }
119
120 } // namespace ark::es2panda::checker
121