| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/torque/declarable.h" |
| |
| #include <fstream> |
| #include <iostream> |
| |
| #include "src/torque/ast.h" |
| #include "src/torque/global-context.h" |
| #include "src/torque/type-inference.h" |
| #include "src/torque/type-visitor.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace torque { |
| |
| DEFINE_CONTEXTUAL_VARIABLE(CurrentScope) |
| |
| std::ostream& operator<<(std::ostream& os, const QualifiedName& name) { |
| for (const std::string& qualifier : name.namespace_qualification) { |
| os << qualifier << "::"; |
| } |
| return os << name.name; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const Callable& m) { |
| os << "callable " << m.ReadableName() << "("; |
| if (m.signature().implicit_count != 0) { |
| os << "implicit "; |
| TypeVector implicit_parameter_types( |
| m.signature().parameter_types.types.begin(), |
| m.signature().parameter_types.types.begin() + |
| m.signature().implicit_count); |
| os << implicit_parameter_types << ")("; |
| TypeVector explicit_parameter_types( |
| m.signature().parameter_types.types.begin() + |
| m.signature().implicit_count, |
| m.signature().parameter_types.types.end()); |
| os << explicit_parameter_types; |
| } else { |
| os << m.signature().parameter_types; |
| } |
| os << "): " << *m.signature().return_type; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const Builtin& b) { |
| os << "builtin " << *b.signature().return_type << " " << b.ReadableName() |
| << b.signature().parameter_types; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) { |
| os << "runtime function " << *b.signature().return_type << " " |
| << b.ReadableName() << b.signature().parameter_types; |
| return os; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const GenericCallable& g) { |
| os << "generic " << g.name() << "<"; |
| PrintCommaSeparatedList(os, g.generic_parameters(), |
| [](const GenericParameter& identifier) { |
| return identifier.name->value; |
| }); |
| os << ">"; |
| |
| return os; |
| } |
| |
| SpecializationRequester::SpecializationRequester(SourcePosition position, |
| Scope* scope, std::string name) |
| : position(position), name(std::move(name)) { |
| // Skip scopes that are not related to template specializations, they might be |
| // stack-allocated and not live for long enough. |
| while (scope && scope->GetSpecializationRequester().IsNone()) |
| scope = scope->ParentScope(); |
| this->scope = scope; |
| } |
| |
| std::vector<Declarable*> Scope::Lookup(const QualifiedName& name) { |
| if (name.namespace_qualification.size() >= 1 && |
| name.namespace_qualification[0] == "") { |
| return GlobalContext::GetDefaultNamespace()->Lookup( |
| name.DropFirstNamespaceQualification()); |
| } |
| std::vector<Declarable*> result; |
| if (ParentScope()) { |
| result = ParentScope()->Lookup(name); |
| } |
| for (Declarable* declarable : LookupShallow(name)) { |
| result.push_back(declarable); |
| } |
| return result; |
| } |
| |
| base::Optional<std::string> TypeConstraint::IsViolated(const Type* type) const { |
| if (upper_bound && !type->IsSubtypeOf(*upper_bound)) { |
| if (type->IsTopType()) { |
| return TopType::cast(type)->reason(); |
| } else { |
| return { |
| ToString("expected ", *type, " to be a subtype of ", **upper_bound)}; |
| } |
| } |
| return base::nullopt; |
| } |
| |
| base::Optional<std::string> FindConstraintViolation( |
| const std::vector<const Type*>& types, |
| const std::vector<TypeConstraint>& constraints) { |
| DCHECK_EQ(constraints.size(), types.size()); |
| for (size_t i = 0; i < types.size(); ++i) { |
| if (auto violation = constraints[i].IsViolated(types[i])) { |
| return {"Could not instantiate generic, " + *violation + "."}; |
| } |
| } |
| return base::nullopt; |
| } |
| |
| std::vector<TypeConstraint> ComputeConstraints( |
| Scope* scope, const GenericParameters& parameters) { |
| CurrentScope::Scope scope_scope(scope); |
| std::vector<TypeConstraint> result; |
| for (const GenericParameter& parameter : parameters) { |
| if (parameter.constraint) { |
| result.push_back(TypeConstraint::SubtypeConstraint( |
| TypeVisitor::ComputeType(*parameter.constraint))); |
| } else { |
| result.push_back(TypeConstraint::Unconstrained()); |
| } |
| } |
| return result; |
| } |
| |
| TypeArgumentInference GenericCallable::InferSpecializationTypes( |
| const TypeVector& explicit_specialization_types, |
| const std::vector<base::Optional<const Type*>>& arguments) { |
| const std::vector<TypeExpression*>& parameters = |
| declaration()->parameters.types; |
| CurrentScope::Scope generic_scope(ParentScope()); |
| TypeArgumentInference inference(generic_parameters(), |
| explicit_specialization_types, parameters, |
| arguments); |
| if (!inference.HasFailed()) { |
| if (auto violation = |
| FindConstraintViolation(inference.GetResult(), Constraints())) { |
| inference.Fail(*violation); |
| } |
| } |
| return inference; |
| } |
| |
| base::Optional<Statement*> GenericCallable::CallableBody() { |
| if (auto* decl = TorqueMacroDeclaration::DynamicCast(declaration())) { |
| return decl->body; |
| } else if (auto* decl = |
| TorqueBuiltinDeclaration::DynamicCast(declaration())) { |
| return decl->body; |
| } else { |
| return base::nullopt; |
| } |
| } |
| |
| bool Namespace::IsDefaultNamespace() const { |
| return this == GlobalContext::GetDefaultNamespace(); |
| } |
| |
| bool Namespace::IsTestNamespace() const { return name() == kTestNamespaceName; } |
| |
| const Type* TypeAlias::Resolve() const { |
| if (!type_) { |
| CurrentScope::Scope scope_activator(ParentScope()); |
| CurrentSourcePosition::Scope position_activator(Position()); |
| TypeDeclaration* decl = *delayed_; |
| if (being_resolved_) { |
| std::stringstream s; |
| s << "Cannot create type " << decl->name->value |
| << " due to circular dependencies."; |
| ReportError(s.str()); |
| } |
| type_ = TypeVisitor::ComputeType(decl); |
| } |
| return *type_; |
| } |
| |
| } // namespace torque |
| } // namespace internal |
| } // namespace v8 |