• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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