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 #include "signature.h"
17
18 namespace panda::es2panda::checker {
19
Copy(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)20 Signature *Signature::Copy(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
21 {
22 checker::SignatureInfo *copiedInfo = allocator->New<checker::SignatureInfo>(signatureInfo_, allocator);
23
24 CHECK_NOT_NULL(copiedInfo);
25 for (auto *it : copiedInfo->params) {
26 it->SetTsType(it->TsType()->Instantiate(allocator, relation, globalTypes));
27 }
28
29 Type *copiedReturnType = returnType_->Instantiate(allocator, relation, globalTypes);
30
31 return allocator->New<Signature>(copiedInfo, copiedReturnType);
32 }
33
ToString(std::stringstream & ss,const binder::Variable * variable,bool printAsMethod) const34 void Signature::ToString(std::stringstream &ss, const binder::Variable *variable, bool printAsMethod) const
35 {
36 ss << "(";
37
38 for (auto it = signatureInfo_->params.begin(); it != signatureInfo_->params.end(); it++) {
39 ss << (*it)->Name();
40
41 if ((*it)->HasFlag(binder::VariableFlags::OPTIONAL)) {
42 ss << "?";
43 }
44
45 ss << ": ";
46
47 (*it)->TsType()->ToString(ss);
48
49 if (std::next(it) != signatureInfo_->params.end()) {
50 ss << ", ";
51 }
52 }
53
54 if (signatureInfo_->restVar) {
55 if (!signatureInfo_->params.empty()) {
56 ss << ", ";
57 }
58
59 ss << "...";
60 ss << signatureInfo_->restVar->Name();
61 ss << ": ";
62 signatureInfo_->restVar->TsType()->ToString(ss);
63 ss << "[]";
64 }
65
66 ss << ")";
67
68 if (printAsMethod || (variable && variable->HasFlag(binder::VariableFlags::METHOD))) {
69 ss << ": ";
70 } else {
71 ss << " => ";
72 }
73
74 returnType_->ToString(ss);
75 }
76
Identical(TypeRelation * relation,Signature * other)77 void Signature::Identical(TypeRelation *relation, Signature *other)
78 {
79 if (signatureInfo_->minArgCount != other->MinArgCount() ||
80 signatureInfo_->params.size() != other->Params().size()) {
81 relation->Result(false);
82 return;
83 }
84
85 relation->IsIdenticalTo(returnType_, other->ReturnType());
86
87 if (relation->IsTrue()) {
88 for (uint64_t i = 0; i < signatureInfo_->params.size(); i++) {
89 relation->IsIdenticalTo(signatureInfo_->params[i]->TsType(), other->Params()[i]->TsType());
90 if (!relation->IsTrue()) {
91 return;
92 }
93 }
94
95 if (signatureInfo_->restVar && other->RestVar()) {
96 relation->IsIdenticalTo(signatureInfo_->restVar->TsType(), other->RestVar()->TsType());
97 } else if ((signatureInfo_->restVar && !other->RestVar()) || (!signatureInfo_->restVar && other->RestVar())) {
98 relation->Result(false);
99 }
100 }
101 }
102
AssignmentTarget(TypeRelation * relation,Signature * source)103 void Signature::AssignmentTarget(TypeRelation *relation, Signature *source)
104 {
105 if (!signatureInfo_->restVar &&
106 (source->Params().size() - source->OptionalArgCount()) > signatureInfo_->params.size()) {
107 relation->Result(false);
108 return;
109 }
110
111 for (size_t i = 0; i < source->Params().size(); i++) {
112 if (!signatureInfo_->restVar && i >= Params().size()) {
113 break;
114 }
115
116 if (signatureInfo_->restVar) {
117 relation->IsAssignableTo(source->Params()[i]->TsType(), signatureInfo_->restVar->TsType());
118
119 if (!relation->IsTrue()) {
120 return;
121 }
122
123 continue;
124 }
125
126 relation->IsAssignableTo(source->Params()[i]->TsType(), Params()[i]->TsType());
127
128 if (!relation->IsTrue()) {
129 return;
130 }
131 }
132
133 relation->IsAssignableTo(source->ReturnType(), returnType_);
134
135 if (relation->IsTrue() && signatureInfo_->restVar && source->RestVar()) {
136 relation->IsAssignableTo(source->RestVar()->TsType(), signatureInfo_->restVar->TsType());
137 }
138 }
139
140 } // namespace panda::es2panda::checker
141