1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/torque/declarable.h"
6
7 #include <fstream>
8 #include <iostream>
9
10 #include "src/torque/ast.h"
11 #include "src/torque/global-context.h"
12 #include "src/torque/type-inference.h"
13 #include "src/torque/type-visitor.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace torque {
18
DEFINE_CONTEXTUAL_VARIABLE(CurrentScope)19 DEFINE_CONTEXTUAL_VARIABLE(CurrentScope)
20
21 QualifiedName QualifiedName::Parse(std::string qualified_name) {
22 std::vector<std::string> qualifications;
23 while (true) {
24 size_t namespace_delimiter_index = qualified_name.find("::");
25 if (namespace_delimiter_index == std::string::npos) break;
26 qualifications.push_back(
27 qualified_name.substr(0, namespace_delimiter_index));
28 qualified_name = qualified_name.substr(namespace_delimiter_index + 2);
29 }
30 return QualifiedName(qualifications, qualified_name);
31 }
32
operator <<(std::ostream & os,const QualifiedName & name)33 std::ostream& operator<<(std::ostream& os, const QualifiedName& name) {
34 for (const std::string& qualifier : name.namespace_qualification) {
35 os << qualifier << "::";
36 }
37 return os << name.name;
38 }
39
operator <<(std::ostream & os,const Callable & m)40 std::ostream& operator<<(std::ostream& os, const Callable& m) {
41 os << "callable " << m.ReadableName() << "(";
42 if (m.signature().implicit_count != 0) {
43 os << "implicit ";
44 TypeVector implicit_parameter_types(
45 m.signature().parameter_types.types.begin(),
46 m.signature().parameter_types.types.begin() +
47 m.signature().implicit_count);
48 os << implicit_parameter_types << ")(";
49 TypeVector explicit_parameter_types(
50 m.signature().parameter_types.types.begin() +
51 m.signature().implicit_count,
52 m.signature().parameter_types.types.end());
53 os << explicit_parameter_types;
54 } else {
55 os << m.signature().parameter_types;
56 }
57 os << "): " << *m.signature().return_type;
58 return os;
59 }
60
operator <<(std::ostream & os,const Builtin & b)61 std::ostream& operator<<(std::ostream& os, const Builtin& b) {
62 os << "builtin " << *b.signature().return_type << " " << b.ReadableName()
63 << b.signature().parameter_types;
64 return os;
65 }
66
operator <<(std::ostream & os,const RuntimeFunction & b)67 std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
68 os << "runtime function " << *b.signature().return_type << " "
69 << b.ReadableName() << b.signature().parameter_types;
70 return os;
71 }
72
operator <<(std::ostream & os,const GenericCallable & g)73 std::ostream& operator<<(std::ostream& os, const GenericCallable& g) {
74 os << "generic " << g.name() << "<";
75 PrintCommaSeparatedList(os, g.generic_parameters(),
76 [](const GenericParameter& identifier) {
77 return identifier.name->value;
78 });
79 os << ">";
80
81 return os;
82 }
83
SpecializationRequester(SourcePosition position,Scope * s,std::string name)84 SpecializationRequester::SpecializationRequester(SourcePosition position,
85 Scope* s, std::string name)
86 : position(position), name(std::move(name)) {
87 // Skip scopes that are not related to template specializations, they might be
88 // stack-allocated and not live for long enough.
89 while (s && s->GetSpecializationRequester().IsNone()) s = s->ParentScope();
90 this->scope = s;
91 }
92
Lookup(const QualifiedName & name)93 std::vector<Declarable*> Scope::Lookup(const QualifiedName& name) {
94 if (name.namespace_qualification.size() >= 1 &&
95 name.namespace_qualification[0] == "") {
96 return GlobalContext::GetDefaultNamespace()->Lookup(
97 name.DropFirstNamespaceQualification());
98 }
99 std::vector<Declarable*> result;
100 if (ParentScope()) {
101 result = ParentScope()->Lookup(name);
102 }
103 for (Declarable* declarable : LookupShallow(name)) {
104 result.push_back(declarable);
105 }
106 return result;
107 }
108
IsViolated(const Type * type) const109 base::Optional<std::string> TypeConstraint::IsViolated(const Type* type) const {
110 if (upper_bound && !type->IsSubtypeOf(*upper_bound)) {
111 if (type->IsTopType()) {
112 return TopType::cast(type)->reason();
113 } else {
114 return {
115 ToString("expected ", *type, " to be a subtype of ", **upper_bound)};
116 }
117 }
118 return base::nullopt;
119 }
120
FindConstraintViolation(const std::vector<const Type * > & types,const std::vector<TypeConstraint> & constraints)121 base::Optional<std::string> FindConstraintViolation(
122 const std::vector<const Type*>& types,
123 const std::vector<TypeConstraint>& constraints) {
124 DCHECK_EQ(constraints.size(), types.size());
125 for (size_t i = 0; i < types.size(); ++i) {
126 if (auto violation = constraints[i].IsViolated(types[i])) {
127 return {"Could not instantiate generic, " + *violation + "."};
128 }
129 }
130 return base::nullopt;
131 }
132
ComputeConstraints(Scope * scope,const GenericParameters & parameters)133 std::vector<TypeConstraint> ComputeConstraints(
134 Scope* scope, const GenericParameters& parameters) {
135 CurrentScope::Scope scope_scope(scope);
136 std::vector<TypeConstraint> result;
137 for (const GenericParameter& parameter : parameters) {
138 if (parameter.constraint) {
139 result.push_back(TypeConstraint::SubtypeConstraint(
140 TypeVisitor::ComputeType(*parameter.constraint)));
141 } else {
142 result.push_back(TypeConstraint::Unconstrained());
143 }
144 }
145 return result;
146 }
147
InferSpecializationTypes(const TypeVector & explicit_specialization_types,const std::vector<base::Optional<const Type * >> & arguments)148 TypeArgumentInference GenericCallable::InferSpecializationTypes(
149 const TypeVector& explicit_specialization_types,
150 const std::vector<base::Optional<const Type*>>& arguments) {
151 const std::vector<TypeExpression*>& parameters =
152 declaration()->parameters.types;
153 CurrentScope::Scope generic_scope(ParentScope());
154 TypeArgumentInference inference(generic_parameters(),
155 explicit_specialization_types, parameters,
156 arguments);
157 if (!inference.HasFailed()) {
158 if (auto violation =
159 FindConstraintViolation(inference.GetResult(), Constraints())) {
160 inference.Fail(*violation);
161 }
162 }
163 return inference;
164 }
165
CallableBody()166 base::Optional<Statement*> GenericCallable::CallableBody() {
167 if (auto* macro_decl = TorqueMacroDeclaration::DynamicCast(declaration())) {
168 return macro_decl->body;
169 } else if (auto* builtin_decl =
170 TorqueBuiltinDeclaration::DynamicCast(declaration())) {
171 return builtin_decl->body;
172 } else {
173 return base::nullopt;
174 }
175 }
176
IsDefaultNamespace() const177 bool Namespace::IsDefaultNamespace() const {
178 return this == GlobalContext::GetDefaultNamespace();
179 }
180
IsTestNamespace() const181 bool Namespace::IsTestNamespace() const { return name() == kTestNamespaceName; }
182
Resolve() const183 const Type* TypeAlias::Resolve() const {
184 if (!type_) {
185 CurrentScope::Scope scope_activator(ParentScope());
186 CurrentSourcePosition::Scope position_activator(Position());
187 TypeDeclaration* decl = *delayed_;
188 if (being_resolved_) {
189 std::stringstream s;
190 s << "Cannot create type " << decl->name->value
191 << " due to circular dependencies.";
192 ReportError(s.str());
193 }
194 type_ = TypeVisitor::ComputeType(decl);
195 }
196 return *type_;
197 }
198
199 } // namespace torque
200 } // namespace internal
201 } // namespace v8
202