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