• 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 
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