blob: 122f07d7b1b50db822268c647ad8990da3d15b5f [file] [log] [blame]
//===--- TypeRepr.cpp - Swift Language Type Representation ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the TypeRepr and related classes.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ExprHandle.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Defer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
SourceLoc TypeRepr::getLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceLoc TypeRepr::getStartLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getStartLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceLoc TypeRepr::getEndLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getEndLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceRange TypeRepr::getSourceRange() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: { \
auto Ty = static_cast<const CLASS##TypeRepr*>(this); \
return SourceRange(Ty->getStartLocImpl(), Ty->getEndLocImpl()); \
}
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
/// Standard allocator for TypeReprs.
void *TypeRepr::operator new(size_t Bytes, const ASTContext &C,
unsigned Alignment) {
return C.Allocate(Bytes, Alignment);
}
Identifier ComponentIdentTypeRepr::getIdentifier() const {
if (IdOrDecl.is<Identifier>())
return IdOrDecl.get<Identifier>();
return IdOrDecl.get<ValueDecl *>()->getName();
}
static void printTypeRepr(const TypeRepr *TyR, ASTPrinter &Printer,
const PrintOptions &Opts) {
if (TyR == nullptr)
Printer << "<null>";
else
TyR->print(Printer, Opts);
}
void TypeRepr::print(raw_ostream &OS, const PrintOptions &Opts) const {
StreamPrinter Printer(OS);
print(Printer, Opts);
}
void TypeRepr::print(ASTPrinter &Printer, const PrintOptions &Opts) const {
// The type part of a NamedTypeRepr will get the callback.
if (!isa<NamedTypeRepr>(this))
Printer.printTypePre(TypeLoc(const_cast<TypeRepr *>(this)));
SWIFT_DEFER {
if (!isa<NamedTypeRepr>(this))
Printer.printTypePost(TypeLoc(const_cast<TypeRepr *>(this)));
};
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: { \
auto Ty = static_cast<const CLASS##TypeRepr*>(this); \
return Ty->printImpl(Printer, Opts); \
}
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
namespace {
class CloneVisitor : public TypeReprVisitor<CloneVisitor, TypeRepr *> {
const ASTContext &Ctx;
public:
explicit CloneVisitor(const ASTContext &ctx) : Ctx(ctx) { }
#define TYPEREPR(CLASS, PARENT) \
TypeRepr *visit##CLASS##TypeRepr(CLASS##TypeRepr* type);
#include "swift/AST/TypeReprNodes.def"
};
}
TypeRepr *CloneVisitor::visitErrorTypeRepr(ErrorTypeRepr *T) {
return new (Ctx) ErrorTypeRepr(T->getSourceRange());
}
TypeRepr *CloneVisitor::visitAttributedTypeRepr(AttributedTypeRepr *T) {
return new (Ctx) AttributedTypeRepr(T->getAttrs(), visit(T->getTypeRepr()));
}
TypeRepr *CloneVisitor::visitSimpleIdentTypeRepr(SimpleIdentTypeRepr *T) {
return new (Ctx) SimpleIdentTypeRepr(T->getIdLoc(), T->getIdentifier());
}
TypeRepr *CloneVisitor::visitGenericIdentTypeRepr(GenericIdentTypeRepr *T) {
// Clone the generic arguments.
auto genericArgs = Ctx.Allocate<TypeRepr*>(T->getGenericArgs().size());
for (unsigned argI : indices(genericArgs)) {
genericArgs[argI] = visit(T->getGenericArgs()[argI]);
}
return new (Ctx) GenericIdentTypeRepr(T->getIdLoc(), T->getIdentifier(),
genericArgs, T->getAngleBrackets());
}
TypeRepr *CloneVisitor::visitCompoundIdentTypeRepr(CompoundIdentTypeRepr *T) {
// Clone the components.
auto components = Ctx.Allocate<ComponentIdentTypeRepr*>(T->Components.size());
for (unsigned I : indices(components)) {
components[I] = cast<ComponentIdentTypeRepr>(visit(T->Components[I]));
}
return new (Ctx) CompoundIdentTypeRepr(components);
}
TypeRepr *CloneVisitor::visitFunctionTypeRepr(FunctionTypeRepr *T) {
return new (Ctx) FunctionTypeRepr(/*FIXME: Clone?*/T->getGenericParams(),
visit(T->getArgsTypeRepr()),
T->getThrowsLoc(),
T->getArrowLoc(),
visit(T->getResultTypeRepr()));
}
TypeRepr *CloneVisitor::visitArrayTypeRepr(ArrayTypeRepr *T) {
return new (Ctx) ArrayTypeRepr(visit(T->getBase()), T->getBrackets());
}
TypeRepr *CloneVisitor::visitDictionaryTypeRepr(DictionaryTypeRepr *T) {
return new (Ctx) DictionaryTypeRepr(visit(T->getKey()), visit(T->getValue()),
T->getColonLoc(), T->getBrackets());
}
TypeRepr *CloneVisitor::visitOptionalTypeRepr(OptionalTypeRepr *T) {
return new (Ctx) OptionalTypeRepr(visit(T->getBase()), T->getQuestionLoc());
}
TypeRepr * CloneVisitor::visitImplicitlyUnwrappedOptionalTypeRepr(
ImplicitlyUnwrappedOptionalTypeRepr *T) {
return new (Ctx) ImplicitlyUnwrappedOptionalTypeRepr(visit(T->getBase()),
T->getExclamationLoc());
}
TypeRepr *CloneVisitor::visitTupleTypeRepr(TupleTypeRepr *T) {
// Clone the tuple elements.
auto elements = Ctx.Allocate<TypeRepr*>(T->getElements().size());
for (unsigned argI : indices(elements)) {
elements[argI] = visit(T->getElements()[argI]);
}
return new (Ctx) TupleTypeRepr(elements, T->getParens(), T->getEllipsisLoc(),
T->getEllipsisIndex());
}
TypeRepr *CloneVisitor::visitNamedTypeRepr(NamedTypeRepr *T) {
return new (Ctx) NamedTypeRepr(T->getName(), visit(T->getTypeRepr()),
T->getNameLoc());
}
TypeRepr *CloneVisitor::visitProtocolCompositionTypeRepr(
ProtocolCompositionTypeRepr *T) {
// Clone the protocols.
auto protocols = Ctx.Allocate<IdentTypeRepr*>(T->getProtocols().size());
for (unsigned argI : indices(protocols)) {
protocols[argI] = cast<IdentTypeRepr>(visit(T->getProtocols()[argI]));
}
return new (Ctx) ProtocolCompositionTypeRepr(protocols,
T->getStartLoc(),
T->getCompositionRange());
}
TypeRepr *CloneVisitor::visitMetatypeTypeRepr(MetatypeTypeRepr *T) {
return new (Ctx) MetatypeTypeRepr(visit(T->getBase()), T->getMetaLoc());
}
TypeRepr *CloneVisitor::visitProtocolTypeRepr(ProtocolTypeRepr *T) {
return new (Ctx) ProtocolTypeRepr(visit(T->getBase()), T->getProtocolLoc());
}
TypeRepr *CloneVisitor::visitInOutTypeRepr(InOutTypeRepr *T) {
return new (Ctx) InOutTypeRepr(visit(T->getBase()), T->getInOutLoc());
}
TypeRepr *CloneVisitor::visitFixedTypeRepr(FixedTypeRepr *T) {
return new (Ctx) FixedTypeRepr(T->getType(), T->getLoc());
}
TypeRepr *TypeRepr::clone(const ASTContext &ctx) const {
CloneVisitor visitor(ctx);
return visitor.visit(const_cast<TypeRepr *>(this));
}
void TypeRepr::visitTopLevelTypeReprs(
llvm::function_ref<void(IdentTypeRepr *)> visitor) {
TypeRepr *typeRepr = this;
// Look through attributed type representations.
while (auto attr = dyn_cast<AttributedTypeRepr>(typeRepr))
typeRepr = attr->getTypeRepr();
// Handle identifier type representations.
if (auto ident = dyn_cast<IdentTypeRepr>(typeRepr)) {
visitor(ident);
return;
}
// Recurse into protocol compositions.
if (auto composition = dyn_cast<ProtocolCompositionTypeRepr>(typeRepr)) {
for (auto ident : composition->getProtocols())
ident->visitTopLevelTypeReprs(visitor);
return;
}
}
void ErrorTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "<<error type>>";
}
void AttributedTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printAttrs(Printer);
printTypeRepr(Ty, Printer, Opts);
}
void AttributedTypeRepr::printAttrs(llvm::raw_ostream &OS) const {
StreamPrinter Printer(OS);
printAttrs(Printer);
}
void AttributedTypeRepr::printAttrs(ASTPrinter &Printer) const {
const TypeAttributes &Attrs = getAttrs();
if (Attrs.has(TAK_autoclosure)) Printer << "@autoclosure ";
if (Attrs.has(TAK_escaping)) Printer << "@escaping ";
if (Attrs.has(TAK_thin)) Printer << "@thin ";
if (Attrs.has(TAK_thick)) Printer << "@thick ";
if (Attrs.convention.hasValue()) {
Printer << "@convention(" << Attrs.convention.getValue() << ") ";
}
}
IdentTypeRepr *IdentTypeRepr::create(ASTContext &C,
ArrayRef<ComponentIdentTypeRepr *> Components) {
assert(!Components.empty());
if (Components.size() == 1)
return Components.front();
return new (C) CompoundIdentTypeRepr(C.AllocateCopy(Components));
}
static void printGenericArgs(ASTPrinter &Printer, const PrintOptions &Opts,
ArrayRef<TypeRepr *> Args) {
if (Args.empty())
return;
Printer << "<";
bool First = true;
for (auto Arg : Args) {
if (First)
First = false;
else
Printer << ", ";
printTypeRepr(Arg, Printer, Opts);
}
Printer << ">";
}
void ComponentIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(getBoundDecl())) {
if (auto MD = dyn_cast<ModuleDecl>(TD))
Printer.printModuleRef(MD, getIdentifier());
else
Printer.printTypeRef(Type(), TD, getIdentifier());
} else {
Printer.printName(getIdentifier());
}
if (auto GenIdT = dyn_cast<GenericIdentTypeRepr>(this))
printGenericArgs(Printer, Opts, GenIdT->getGenericArgs());
}
void CompoundIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Components.front(), Printer, Opts);
for (auto C : Components.slice(1)) {
Printer << ".";
printTypeRepr(C, Printer, Opts);
}
}
void FunctionTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.callPrintStructurePre(PrintStructureKind::FunctionType);
printTypeRepr(ArgsTy, Printer, Opts);
if (throws()) {
Printer << " ";
Printer.printKeyword("throws");
}
Printer << " -> ";
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
printTypeRepr(RetTy, Printer, Opts);
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
Printer.printStructurePost(PrintStructureKind::FunctionType);
}
void ArrayTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "[";
printTypeRepr(getBase(), Printer, Opts);
Printer << "]";
}
void DictionaryTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "[";
printTypeRepr(Key, Printer, Opts);
Printer << " : ";
printTypeRepr(Value, Printer, Opts);
Printer << "]";
}
void OptionalTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << "?";
}
void ImplicitlyUnwrappedOptionalTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << "!";
}
TupleTypeRepr *TupleTypeRepr::create(ASTContext &C,
ArrayRef<TypeRepr *> Elements,
SourceRange Parens,
SourceLoc Ellipsis,
unsigned EllipsisIdx) {
assert(Ellipsis.isValid() ? EllipsisIdx < Elements.size()
: EllipsisIdx == Elements.size());
return new (C) TupleTypeRepr(C.AllocateCopy(Elements),
Parens, Ellipsis, EllipsisIdx);
}
void TupleTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.callPrintStructurePre(PrintStructureKind::TupleType);
SWIFT_DEFER { Printer.printStructurePost(PrintStructureKind::TupleType); };
Printer << "(";
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
if (i) Printer << ", ";
Printer.callPrintStructurePre(PrintStructureKind::TupleElement);
printTypeRepr(Elements[i], Printer, Opts);
Printer.printStructurePost(PrintStructureKind::TupleElement);
if (hasEllipsis() && getEllipsisIndex() == i)
Printer << "...";
}
Printer << ")";
}
void NamedTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
if (!Id.empty()) {
Printer.printName(Id, PrintNameContext::TupleElement);
Printer << ": ";
}
printTypeRepr(Ty, Printer, Opts);
}
ProtocolCompositionTypeRepr *
ProtocolCompositionTypeRepr::create(ASTContext &C,
ArrayRef<IdentTypeRepr *> Protocols,
SourceLoc FirstTypeLoc,
SourceRange CompositionRange) {
return new (C) ProtocolCompositionTypeRepr(C.AllocateCopy(Protocols),
FirstTypeLoc, CompositionRange);
}
void ProtocolCompositionTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
if (Protocols.empty()) {
Printer << "Any";
} else {
bool First = true;
for (auto Proto : Protocols) {
if (First)
First = false;
else
Printer << " & ";
printTypeRepr(Proto, Printer, Opts);
}
}
}
void MetatypeTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << ".Type";
}
void ProtocolTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << ".Protocol";
}
void InOutTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.printKeyword("inout");
Printer << " ";
printTypeRepr(Base, Printer, Opts);
}
void FixedTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
getType().print(Printer, Opts);
}