1+ // ===--- ASTSynthesis.h - Convenient Swift AST synthesis --------*- C++ -*-===//
2+ //
3+ // This source file is part of the Swift.org open source project
4+ //
5+ // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+ // Licensed under Apache License v2.0 with Runtime Library Exception
7+ //
8+ // See https://swift.org/LICENSE.txt for license information
9+ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+ //
11+ // ===----------------------------------------------------------------------===//
12+
13+ #ifndef SWIFT_ASTSYNTHESIS_H
14+ #define SWIFT_ASTSYNTHESIS_H
15+
16+ #include " swift/AST/Types.h"
17+ #include " swift/AST/ASTContext.h"
18+ #include " swift/AST/Decl.h"
19+ #include " swift/AST/ParameterList.h"
20+
21+ namespace swift {
22+
23+ struct SynthesisContext {
24+ ASTContext &Context;
25+ DeclContext *DC;
26+
27+ SynthesisContext (ASTContext &ctx, DeclContext *DC)
28+ : Context(ctx), DC(DC) {}
29+ };
30+
31+ // / A synthesizer which generates a specific type.
32+ enum SingletonTypeSynthesizer {
33+ _void,
34+ _nativeObject,
35+ _job,
36+ };
37+ inline Type synthesizeType (SynthesisContext &SC,
38+ SingletonTypeSynthesizer kind) {
39+ switch (kind) {
40+ case _void: return SC.Context .TheEmptyTupleType ;
41+ case _nativeObject: return SC.Context .TheNativeObjectType ;
42+ case _job: return SC.Context .TheJobType ;
43+ }
44+ }
45+
46+ // / Helper types for variadic synthesis.
47+ template <class ... Ss>
48+ struct VariadicSynthesizerStorage ;
49+
50+ template <>
51+ struct VariadicSynthesizerStorage <> {
52+ constexpr VariadicSynthesizerStorage () {}
53+
54+ template <class T , class Fn >
55+ void collect (SynthesisContext &SC, SmallVectorImpl<T> &results,
56+ Fn fn) const {}
57+ };
58+ template <class Head , class ... Tail>
59+ struct VariadicSynthesizerStorage <Head, Tail...> {
60+ Head head;
61+ VariadicSynthesizerStorage<Tail...> tail;
62+ constexpr VariadicSynthesizerStorage (Head head, Tail... tail)
63+ : head(head), tail(tail...) {}
64+
65+ template <class T , class Fn >
66+ void collect (SynthesisContext &SC,
67+ SmallVectorImpl<T> &results,
68+ Fn fn) const {
69+ results.push_back (fn (SC, head));
70+ tail.collect (SC, results, fn);
71+ }
72+ };
73+
74+ // / Synthesize tuple type elements.
75+ template <class S >
76+ TupleTypeElt synthesizeTupleTypeElt (SynthesisContext &SC, S s) {
77+ return synthesizeType (SC, s);
78+ }
79+ struct SynthesizeTupleTypeElt {
80+ template <class S >
81+ TupleTypeElt operator ()(SynthesisContext &SC, const S &s) {
82+ synthesizeTupleTypeElt (SC, s);
83+ }
84+ };
85+
86+ // / Synthesize tuple types.
87+ template <class ... Elts>
88+ struct TupleSynthesizer {
89+ VariadicSynthesizerStorage<Elts...> Elements;
90+ };
91+ template <class ... Elts>
92+ constexpr TupleSynthesizer<Elts...> _tuple (Elts... elts) {
93+ return {{elts...}};
94+ }
95+ template <class ... Elts>
96+ Type synthesizeType (SynthesisContext &SC,
97+ const TupleSynthesizer<Elts...> &tuple) {
98+ SmallVector<TupleTypeElt, sizeof ...(Elts)> elts;
99+ tuple.Elements .collect (SC, elts, SynthesizeTupleTypeElt ());
100+ return TupleType::get (elts, SC.Context );
101+ }
102+
103+ // / Synthesize parameter declarations.
104+ template <class S >
105+ ParamDecl *synthesizeParamDecl (SynthesisContext &SC, const S &s) {
106+ auto type = synthesizeType (SC, s);
107+ auto PD = new (SC.Context ) ParamDecl (SourceLoc (), SourceLoc (),
108+ Identifier (), SourceLoc (),
109+ Identifier (), SC.DC );
110+ PD->setInterfaceType (type);
111+ PD->setImplicit ();
112+ return PD;
113+ }
114+ template <class S >
115+ FunctionType::Param synthesizeParamType (SynthesisContext &SC, const S &s) {
116+ auto type = synthesizeType (SC, s);
117+ return type;
118+ }
119+
120+ // / Parameter specifiers.
121+ template <class S >
122+ struct SpecifiedParamSynthesizer { ParamSpecifier specifier; S sub; };
123+ template <class G >
124+ constexpr SpecifiedParamSynthesizer<G> _owned (G sub) {
125+ return {ParamSpecifier::Owned, sub};
126+ }
127+ template <class G >
128+ constexpr SpecifiedParamSynthesizer<G> _inout (G sub) {
129+ return {ParamSpecifier::InOut, sub};
130+ }
131+ template <class S >
132+ ParamDecl *synthesizeParamDecl (SynthesisContext &SC,
133+ const SpecifiedParamSynthesizer<S> &s) {
134+ auto param = synthesizeParamDecl (SC, s.sub );
135+ param->setSpecifier (s.specifier );
136+ return param;
137+ }
138+ template <class S >
139+ FunctionType::Param synthesizeParamType (SynthesisContext &SC,
140+ const SpecifiedParamSynthesizer<S> &s) {
141+ auto param = synthesizeParamType (SC, s.sub );
142+ auto flags = param.getParameterFlags ();
143+ if (s.specifier == ParamSpecifier::Owned)
144+ flags = flags.withOwned (true );
145+ if (s.specifier == ParamSpecifier::InOut)
146+ flags = flags.withInOut (true );
147+ return param.withFlags (flags);
148+ }
149+
150+ // / Synthesize a parameter list.
151+ template <class ... Params>
152+ struct ParameterListSynthesizer {
153+ VariadicSynthesizerStorage<Params...> params;
154+ };
155+ template <class ... Params>
156+ constexpr ParameterListSynthesizer<Params...> _parameters (Params... ps) {
157+ return {{ps...}};
158+ }
159+
160+ struct SynthesizeParamDecl {
161+ template <class S >
162+ ParamDecl *operator ()(SynthesisContext &SC, const S &s) {
163+ // Found by argument-dependent lookup.
164+ return synthesizeParamDecl (SC, s);
165+ }
166+ };
167+ template <class ... Params>
168+ ParameterList *synthesizeParameterList (SynthesisContext &SC,
169+ const ParameterListSynthesizer<Params...> &list) {
170+ SmallVector<ParamDecl*, 4 > decls;
171+ list.params .collect (SC, decls, SynthesizeParamDecl ());
172+ return ParameterList::create (SC.Context , decls);
173+ }
174+
175+ struct SynthesizeParamType {
176+ template <class S >
177+ FunctionType::Param operator ()(SynthesisContext &SC, const S &s) {
178+ // Found by argument-dependent lookup.
179+ return synthesizeParamType (SC, s);
180+ }
181+ };
182+ template <class ... Params>
183+ void synthesizeParameterTypes (SynthesisContext &SC,
184+ const ParameterListSynthesizer<Params...> &list,
185+ SmallVectorImpl<FunctionType::Param> &types) {
186+ list.params .collect (SC, types, SynthesizeParamType ());
187+ }
188+
189+ // / Synthesize function ExtInfo.
190+ enum FunctionRepresentationSynthesizer {
191+ _thin,
192+ _thick
193+ };
194+ template <class S > struct ThrowsSynthesizer { S sub; };
195+ template <class S > struct AsyncSynthesizer { S sub; };
196+ template <class S >
197+ constexpr ThrowsSynthesizer<S> _throws (S sub) { return {sub}; }
198+ template <class S >
199+ constexpr AsyncSynthesizer<S> _async (S sub) { return {sub}; }
200+
201+ inline ASTExtInfo synthesizeExtInfo (SynthesisContext &SC,
202+ FunctionRepresentationSynthesizer kind) {
203+ switch (kind) {
204+ case _thin: return ASTExtInfo ().withRepresentation (
205+ FunctionTypeRepresentation::Thin);
206+ case _thick: return ASTExtInfo ().withRepresentation (
207+ FunctionTypeRepresentation::Swift);
208+ }
209+ }
210+ template <class S >
211+ ASTExtInfo synthesizeExtInfo (SynthesisContext &SC,
212+ const ThrowsSynthesizer<S> &s) {
213+ return synthesizeExtInfo (SC, s.sub ).withThrows ();
214+ }
215+ template <class S >
216+ ASTExtInfo synthesizeExtInfo (SynthesisContext &SC,
217+ const AsyncSynthesizer<S> &s) {
218+ return synthesizeExtInfo (SC, s.sub ).withAsync ();
219+ }
220+
221+ // / Synthesize a function type.
222+ template <class ExtInfoS , class ResultS , class ParamsS >
223+ struct FunctionTypeSynthesizer {
224+ ExtInfoS extInfo;
225+ ResultS result;
226+ ParamsS parameters;
227+ };
228+ template <class ExtInfoS , class ResultS , class ParamsS >
229+ FunctionTypeSynthesizer<ExtInfoS, ResultS, ParamsS>
230+ _function (ExtInfoS extInfo, ResultS result, ParamsS params) {
231+ return {extInfo, result, params};
232+ }
233+ template <class ExtInfoS , class ResultS , class ParamsS >
234+ Type synthesizeType (SynthesisContext &SC,
235+ const FunctionTypeSynthesizer<ExtInfoS, ResultS, ParamsS> &fn) {
236+ SmallVector<FunctionType::Param, 4 > paramTypes;
237+ synthesizeParameterTypes (SC, fn.parameters , paramTypes);
238+ auto extInfo = synthesizeExtInfo (SC, fn.extInfo );
239+ auto resultType = synthesizeType (SC, fn.result );
240+ return FunctionType::get (paramTypes, resultType, extInfo);
241+ }
242+
243+ // / Synthesize optionals.
244+ template <class S >
245+ struct OptionalSynthesizer {
246+ S sub;
247+ };
248+ template <class S >
249+ constexpr OptionalSynthesizer<S> _optional (S sub) { return {sub}; }
250+ template <class S >
251+ Type synthesizeType (SynthesisContext &SC, const OptionalSynthesizer<S> &s) {
252+ return OptionalType::get (synthesizeType (SC, s.sub ));
253+ }
254+
255+ } // end namespace swift
256+
257+ #endif
0 commit comments