blob: 2109672444603cf3280276b14d6be244d15617a2 [file] [log] [blame]
//===--- ASTSynthesis.h - Convenient Swift AST synthesis --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_ASTSYNTHESIS_H
#define SWIFT_ASTSYNTHESIS_H
#include "swift/AST/Types.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/ParameterList.h"
namespace swift {
struct SynthesisContext {
ASTContext &Context;
DeclContext *DC;
GenericParamList *GenericParams = nullptr;
SynthesisContext(ASTContext &ctx, DeclContext *DC)
: Context(ctx), DC(DC) {}
};
/// Allow literal types to be passed at an arbitrary position
/// in the type-synthesis DSL.
inline Type synthesizeType(SynthesisContext &SC, Type type) {
return type;
}
/// A synthesizer which generates a specific type.
enum SingletonTypeSynthesizer {
_any,
_bridgeObject,
_error,
_job,
_nativeObject,
_never,
_rawPointer,
_void,
_word,
};
inline Type synthesizeType(SynthesisContext &SC,
SingletonTypeSynthesizer kind) {
switch (kind) {
case _any: return SC.Context.TheAnyType;
case _bridgeObject: return SC.Context.TheBridgeObjectType;
case _error: return SC.Context.getExceptionType();
case _job: return SC.Context.TheJobType;
case _nativeObject: return SC.Context.TheNativeObjectType;
case _never: return SC.Context.getNeverType();
case _rawPointer: return SC.Context.TheRawPointerType;
case _void: return SC.Context.TheEmptyTupleType;
case _word: return BuiltinIntegerType::get(BuiltinIntegerWidth::pointer(),
SC.Context);
}
}
/// A synthesizer which generates an integer type.
struct IntegerTypeSynthesizer {
unsigned BitWidth;
};
constexpr inline IntegerTypeSynthesizer _int(unsigned bitWidth) {
return {bitWidth};
}
inline Type synthesizeType(SynthesisContext &SC, IntegerTypeSynthesizer S) {
return BuiltinIntegerType::get(S.BitWidth, SC.Context);
}
/// A synthesizer which generates a vector type.
template <class S>
struct VectorTypeSynthesizer {
unsigned Count;
S Sub;
};
template <class S>
constexpr VectorTypeSynthesizer<S> _vector(unsigned count, S sub) {
return {count, sub};
}
template <class S>
Type synthesizeType(SynthesisContext &SC,
const VectorTypeSynthesizer<S> &V) {
return BuiltinVectorType::get(SC.Context, synthesizeType(SC, V.Sub),
V.Count);
}
/// A synthesizer which generates a metatype type.
template <class S>
struct MetatypeTypeSynthesizer {
S Sub;
};
template <class S>
constexpr MetatypeTypeSynthesizer<S> _metatype(S sub) {
return {sub};
}
template <class S>
Type synthesizeType(SynthesisContext &SC,
const MetatypeTypeSynthesizer<S> &M) {
return MetatypeType::get(synthesizeType(SC, M.Sub));
}
/// A synthesizer which generates an existential metatype type.
template <class S>
struct ExistentialMetatypeTypeSynthesizer {
S Sub;
};
template <class S>
constexpr ExistentialMetatypeTypeSynthesizer<S> _existentialMetatype(S sub) {
return {sub};
}
template <class S>
Type synthesizeType(SynthesisContext &SC,
const ExistentialMetatypeTypeSynthesizer<S> &M) {
return ExistentialMetatypeType::get(synthesizeType(SC, M.Sub));
}
/// Helper types for variadic synthesis.
template <class... Ss>
struct VariadicSynthesizerStorage;
template <>
struct VariadicSynthesizerStorage<> {
constexpr VariadicSynthesizerStorage() {}
template <class Fn>
void visit(const Fn &fn) const {}
};
template <class Head, class... Tail>
struct VariadicSynthesizerStorage<Head, Tail...> {
Head head;
VariadicSynthesizerStorage<Tail...> tail;
constexpr VariadicSynthesizerStorage(Head head, Tail... tail)
: head(head), tail(tail...) {}
template <class Fn>
void visit(const Fn &fn) const {
fn(head);
tail.visit(fn);
}
};
/// A synthesizer which generates a generic type parameter.
struct TypeParamTypeSynthesizer {
unsigned Index;
};
constexpr inline TypeParamTypeSynthesizer _typeparam(unsigned index) {
return {index};
}
inline Type synthesizeType(SynthesisContext &SC,
const TypeParamTypeSynthesizer &S) {
assert(SC.GenericParams);
return SC.GenericParams->getParams()[S.Index]->getDeclaredInterfaceType();
}
/// Synthesize tuple type elements.
template <class S>
TupleTypeElt synthesizeTupleTypeElt(SynthesisContext &SC, S s) {
return synthesizeType(SC, s);
}
struct CollectTupleTypeElements {
SynthesisContext &SC;
SmallVectorImpl<TupleTypeElt> &Elts;
template <class S>
void operator()(const S &s) const {
Elts.push_back(synthesizeTupleTypeElt(SC, s));
}
};
/// Synthesize tuple types.
template <class... Elts>
struct TupleSynthesizer {
VariadicSynthesizerStorage<Elts...> Elements;
};
template <class... Elts>
constexpr TupleSynthesizer<Elts...> _tuple(Elts... elts) {
return {{elts...}};
}
template <class... Elts>
Type synthesizeType(SynthesisContext &SC,
const TupleSynthesizer<Elts...> &tuple) {
SmallVector<TupleTypeElt, sizeof...(Elts)> elts;
tuple.Elements.visit(CollectTupleTypeElements{SC, elts});
return TupleType::get(elts, SC.Context);
}
/// Synthesize parameter declarations.
template <class S>
ParamDecl *synthesizeParamDecl(SynthesisContext &SC, const S &s) {
auto type = synthesizeType(SC, s);
auto PD = new (SC.Context) ParamDecl(SourceLoc(), SourceLoc(),
Identifier(), SourceLoc(),
Identifier(), SC.DC);
PD->setSpecifier(ParamSpecifier::Default);
PD->setInterfaceType(type);
PD->setImplicit();
return PD;
}
template <class S>
FunctionType::Param synthesizeParamType(SynthesisContext &SC, const S &s) {
auto type = synthesizeType(SC, s);
return type;
}
/// Parameter specifiers.
template <class S>
struct SpecifiedParamSynthesizer { ParamSpecifier specifier; S sub; };
template <class G>
constexpr SpecifiedParamSynthesizer<G> _owned(G sub) {
return {ParamSpecifier::Owned, sub};
}
template <class G>
constexpr SpecifiedParamSynthesizer<G> _inout(G sub) {
return {ParamSpecifier::InOut, sub};
}
template <class S>
ParamDecl *synthesizeParamDecl(SynthesisContext &SC,
const SpecifiedParamSynthesizer<S> &s) {
auto param = synthesizeParamDecl(SC, s.sub);
param->setSpecifier(s.specifier);
return param;
}
template <class S>
FunctionType::Param synthesizeParamType(SynthesisContext &SC,
const SpecifiedParamSynthesizer<S> &s) {
auto param = synthesizeParamType(SC, s.sub);
auto flags = param.getParameterFlags();
if (s.specifier == ParamSpecifier::Owned)
flags = flags.withOwned(true);
if (s.specifier == ParamSpecifier::InOut)
flags = flags.withInOut(true);
return param.withFlags(flags);
}
/// Synthesize a parameter list.
template <class... Params>
struct ParameterListSynthesizer {
VariadicSynthesizerStorage<Params...> params;
};
template <class... Params>
constexpr ParameterListSynthesizer<Params...> _parameters(Params... ps) {
return {{ps...}};
}
struct CollectParamDecls {
SynthesisContext &SC;
SmallVectorImpl<ParamDecl*> &Results;
template <class S>
void operator()(const S &s) const {
// Found by argument-dependent lookup.
Results.push_back(synthesizeParamDecl(SC, s));
}
};
template <class... Params>
ParameterList *synthesizeParameterList(SynthesisContext &SC,
const ParameterListSynthesizer<Params...> &list) {
SmallVector<ParamDecl*, 4> decls;
list.params.visit(CollectParamDecls{SC, decls});
return ParameterList::create(SC.Context, decls);
}
struct CollectParamTypes {
SynthesisContext &SC;
SmallVectorImpl<FunctionType::Param> &Results;
template <class S>
void operator()(const S &s) const {
// Found by argument-dependent lookup.
Results.push_back(synthesizeParamType(SC, s));
}
};
template <class... Params>
void synthesizeParameterTypes(SynthesisContext &SC,
const ParameterListSynthesizer<Params...> &list,
SmallVectorImpl<FunctionType::Param> &types) {
list.params.visit(CollectParamTypes{SC, types});
}
/// Synthesize function ExtInfo.
enum FunctionRepresentationSynthesizer {
_thin,
_thick
};
template <class S> struct ThrowsSynthesizer { S sub; };
template <class S> struct AsyncSynthesizer { S sub; };
template <class S>
constexpr ThrowsSynthesizer<S> _throws(S sub) { return {sub}; }
template <class S>
constexpr AsyncSynthesizer<S> _async(S sub) { return {sub}; }
inline ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
FunctionRepresentationSynthesizer kind) {
switch (kind) {
case _thin: return ASTExtInfo().withRepresentation(
FunctionTypeRepresentation::Thin);
case _thick: return ASTExtInfo().withRepresentation(
FunctionTypeRepresentation::Swift);
}
}
template <class S>
ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
const ThrowsSynthesizer<S> &s) {
return synthesizeExtInfo(SC, s.sub).withThrows();
}
template <class S>
ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
const AsyncSynthesizer<S> &s) {
return synthesizeExtInfo(SC, s.sub).withAsync();
}
/// Synthesize a function type.
template <class ExtInfoS, class ResultS, class ParamsS>
struct FunctionTypeSynthesizer {
ExtInfoS extInfo;
ResultS result;
ParamsS parameters;
};
template <class ExtInfoS, class ResultS, class ParamsS>
FunctionTypeSynthesizer<ExtInfoS, ResultS, ParamsS>
_function(ExtInfoS extInfo, ResultS result, ParamsS params) {
return {extInfo, result, params};
}
template <class ExtInfoS, class ResultS, class ParamsS>
Type synthesizeType(SynthesisContext &SC,
const FunctionTypeSynthesizer<ExtInfoS, ResultS, ParamsS> &fn) {
SmallVector<FunctionType::Param, 4> paramTypes;
synthesizeParameterTypes(SC, fn.parameters, paramTypes);
auto extInfo = synthesizeExtInfo(SC, fn.extInfo);
auto resultType = synthesizeType(SC, fn.result);
return FunctionType::get(paramTypes, resultType, extInfo);
}
/// Synthesize optionals.
template <class S>
struct OptionalSynthesizer {
S sub;
};
template <class S>
constexpr OptionalSynthesizer<S> _optional(S sub) { return {sub}; }
template <class S>
Type synthesizeType(SynthesisContext &SC, const OptionalSynthesizer<S> &s) {
return OptionalType::get(synthesizeType(SC, s.sub));
}
} // end namespace swift
#endif