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