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
19 DEFINE_CONTEXTUAL_VARIABLE(CurrentScope)
20
21 std::ostream& operator<<(std::ostream& os, const QualifiedName& name) {
22 for (const std::string& qualifier : name.namespace_qualification) {
23 os << qualifier << "::";
24 }
25 return os << name.name;
26 }
27
operator <<(std::ostream & os,const Callable & m)28 std::ostream& operator<<(std::ostream& os, const Callable& m) {
29 os << "callable " << m.ReadableName() << "(";
30 if (m.signature().implicit_count != 0) {
31 os << "implicit ";
32 TypeVector implicit_parameter_types(
33 m.signature().parameter_types.types.begin(),
34 m.signature().parameter_types.types.begin() +
35 m.signature().implicit_count);
36 os << implicit_parameter_types << ")(";
37 TypeVector explicit_parameter_types(
38 m.signature().parameter_types.types.begin() +
39 m.signature().implicit_count,
40 m.signature().parameter_types.types.end());
41 os << explicit_parameter_types;
42 } else {
43 os << m.signature().parameter_types;
44 }
45 os << "): " << *m.signature().return_type;
46 return os;
47 }
48
operator <<(std::ostream & os,const Builtin & b)49 std::ostream& operator<<(std::ostream& os, const Builtin& b) {
50 os << "builtin " << *b.signature().return_type << " " << b.ReadableName()
51 << b.signature().parameter_types;
52 return os;
53 }
54
operator <<(std::ostream & os,const RuntimeFunction & b)55 std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
56 os << "runtime function " << *b.signature().return_type << " "
57 << b.ReadableName() << b.signature().parameter_types;
58 return os;
59 }
60
operator <<(std::ostream & os,const GenericCallable & g)61 std::ostream& operator<<(std::ostream& os, const GenericCallable& g) {
62 os << "generic " << g.name() << "<";
63 PrintCommaSeparatedList(os, g.generic_parameters(),
64 [](const GenericParameter& identifier) {
65 return identifier.name->value;
66 });
67 os << ">";
68
69 return os;
70 }
71
SpecializationRequester(SourcePosition position,Scope * scope,std::string name)72 SpecializationRequester::SpecializationRequester(SourcePosition position,
73 Scope* scope, std::string name)
74 : position(position), name(std::move(name)) {
75 // Skip scopes that are not related to template specializations, they might be
76 // stack-allocated and not live for long enough.
77 while (scope && scope->GetSpecializationRequester().IsNone())
78 scope = scope->ParentScope();
79 this->scope = scope;
80 }
81
Lookup(const QualifiedName & name)82 std::vector<Declarable*> Scope::Lookup(const QualifiedName& name) {
83 if (name.namespace_qualification.size() >= 1 &&
84 name.namespace_qualification[0] == "") {
85 return GlobalContext::GetDefaultNamespace()->Lookup(
86 name.DropFirstNamespaceQualification());
87 }
88 std::vector<Declarable*> result;
89 if (ParentScope()) {
90 result = ParentScope()->Lookup(name);
91 }
92 for (Declarable* declarable : LookupShallow(name)) {
93 result.push_back(declarable);
94 }
95 return result;
96 }
97
IsViolated(const Type * type) const98 base::Optional<std::string> TypeConstraint::IsViolated(const Type* type) const {
99 if (upper_bound && !type->IsSubtypeOf(*upper_bound)) {
100 if (type->IsTopType()) {
101 return TopType::cast(type)->reason();
102 } else {
103 return {
104 ToString("expected ", *type, " to be a subtype of ", **upper_bound)};
105 }
106 }
107 return base::nullopt;
108 }
109
FindConstraintViolation(const std::vector<const Type * > & types,const std::vector<TypeConstraint> & constraints)110 base::Optional<std::string> FindConstraintViolation(
111 const std::vector<const Type*>& types,
112 const std::vector<TypeConstraint>& constraints) {
113 DCHECK_EQ(constraints.size(), types.size());
114 for (size_t i = 0; i < types.size(); ++i) {
115 if (auto violation = constraints[i].IsViolated(types[i])) {
116 return {"Could not instantiate generic, " + *violation + "."};
117 }
118 }
119 return base::nullopt;
120 }
121
ComputeConstraints(Scope * scope,const GenericParameters & parameters)122 std::vector<TypeConstraint> ComputeConstraints(
123 Scope* scope, const GenericParameters& parameters) {
124 CurrentScope::Scope scope_scope(scope);
125 std::vector<TypeConstraint> result;
126 for (const GenericParameter& parameter : parameters) {
127 if (parameter.constraint) {
128 result.push_back(TypeConstraint::SubtypeConstraint(
129 TypeVisitor::ComputeType(*parameter.constraint)));
130 } else {
131 result.push_back(TypeConstraint::Unconstrained());
132 }
133 }
134 return result;
135 }
136
InferSpecializationTypes(const TypeVector & explicit_specialization_types,const std::vector<base::Optional<const Type * >> & arguments)137 TypeArgumentInference GenericCallable::InferSpecializationTypes(
138 const TypeVector& explicit_specialization_types,
139 const std::vector<base::Optional<const Type*>>& arguments) {
140 const std::vector<TypeExpression*>& parameters =
141 declaration()->parameters.types;
142 CurrentScope::Scope generic_scope(ParentScope());
143 TypeArgumentInference inference(generic_parameters(),
144 explicit_specialization_types, parameters,
145 arguments);
146 if (!inference.HasFailed()) {
147 if (auto violation =
148 FindConstraintViolation(inference.GetResult(), Constraints())) {
149 inference.Fail(*violation);
150 }
151 }
152 return inference;
153 }
154
CallableBody()155 base::Optional<Statement*> GenericCallable::CallableBody() {
156 if (auto* decl = TorqueMacroDeclaration::DynamicCast(declaration())) {
157 return decl->body;
158 } else if (auto* decl =
159 TorqueBuiltinDeclaration::DynamicCast(declaration())) {
160 return decl->body;
161 } else {
162 return base::nullopt;
163 }
164 }
165
IsDefaultNamespace() const166 bool Namespace::IsDefaultNamespace() const {
167 return this == GlobalContext::GetDefaultNamespace();
168 }
169
IsTestNamespace() const170 bool Namespace::IsTestNamespace() const { return name() == kTestNamespaceName; }
171
Resolve() const172 const Type* TypeAlias::Resolve() const {
173 if (!type_) {
174 CurrentScope::Scope scope_activator(ParentScope());
175 CurrentSourcePosition::Scope position_activator(Position());
176 TypeDeclaration* decl = *delayed_;
177 if (being_resolved_) {
178 std::stringstream s;
179 s << "Cannot create type " << decl->name->value
180 << " due to circular dependencies.";
181 ReportError(s.str());
182 }
183 type_ = TypeVisitor::ComputeType(decl);
184 }
185 return *type_;
186 }
187
188 } // namespace torque
189 } // namespace internal
190 } // namespace v8
191