Skip to content

Commit 4c3439f

Browse files
author
Venkatesh Sriram
committed
[Compile Time Constant Extraction] Extract Result Builder Expressions
1 parent 3c6b0bd commit 4c3439f

File tree

3 files changed

+847
-96
lines changed

3 files changed

+847
-96
lines changed

include/swift/AST/ConstTypeInfo.h

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,155 @@ class InitCallValue : public CompileTimeValue {
9696
std::vector<FunctionParameter> Parameters;
9797
};
9898

99-
/// A representation of a Builder pattern initialization expression
99+
/// A representation of a Builder pattern initialization expression. For
100+
/// example:
101+
///
102+
/// @FooBuilder
103+
/// public static var foos: [Foo] {
104+
/// Foo(name: "foos.1")
105+
/// Foo(name: "foos.2")
106+
/// }
107+
///
108+
/// In this example, the result builder type is FooBuilder
109+
/// The members are Foo(name: "foos.1") and Foo(name: "foos.2")
110+
///
100111
class BuilderValue : public CompileTimeValue {
101112
public:
102-
BuilderValue() : CompileTimeValue(ValueKind::Builder) {}
113+
enum MemberKind {
114+
Expression,
115+
Either,
116+
Optional,
117+
LimitedAvailability,
118+
Array,
119+
Unknown
120+
};
121+
122+
/// A base class for individual members being declared inside the result
123+
/// builder
124+
class BuilderMember {
125+
public:
126+
MemberKind getKind() const { return Kind; }
127+
128+
protected:
129+
BuilderMember(MemberKind MemberKind) : Kind(MemberKind) {}
130+
131+
private:
132+
MemberKind Kind;
133+
};
134+
135+
/// A basic expression that is defined inside the result builder. For example:
136+
/// {
137+
/// Foo(name: "1")
138+
/// }
139+
///
140+
class SingleMember : public BuilderMember {
141+
public:
142+
SingleMember(std::shared_ptr<CompileTimeValue> Element)
143+
: BuilderMember(MemberKind::Expression), Element(Element) {}
144+
145+
static bool classof(const BuilderMember *T) {
146+
return T->getKind() == MemberKind::Expression;
147+
}
148+
149+
std::shared_ptr<CompileTimeValue> getElement() const { return Element; }
150+
151+
private:
152+
std::shared_ptr<CompileTimeValue> Element;
153+
};
154+
155+
/// A member that represents when the individual values are defined by
156+
/// iterating over an array. For example:
157+
/// for i in 1...3 {
158+
/// Foo(name: "MyFooProviderInferred.foos.Array.\(i)")
159+
/// }
160+
///
161+
class ArrayMember : public BuilderMember {
162+
public:
163+
ArrayMember(std::vector<std::shared_ptr<BuilderMember>> Elements)
164+
: BuilderMember(MemberKind::Array), Elements(Elements) {}
165+
166+
static bool classof(const BuilderMember *T) {
167+
return T->getKind() == MemberKind::Array;
168+
}
169+
170+
std::vector<std::shared_ptr<BuilderMember>> getElements() const {
171+
return Elements;
172+
}
173+
174+
private:
175+
std::vector<std::shared_ptr<BuilderMember>> Elements;
176+
};
177+
178+
/// A member that is defined conditionally. It can be of the following types:
179+
///
180+
/// 1. A regular if-else condition
181+
/// if condition {
182+
/// Foo(name: "1")
183+
/// } else {
184+
/// Foo(name: "2")
185+
/// }
186+
///
187+
/// 2. An optional
188+
/// if condition {
189+
/// Foo(name: "1")
190+
/// }
191+
///
192+
/// 3. Limited availability
193+
/// if #available(macOS 99, *) {
194+
/// Foo(name: "1")
195+
/// Foo(name: "2")
196+
/// }
197+
///
198+
class ConditionalMember : public BuilderMember {
199+
public:
200+
ConditionalMember(MemberKind MemberKind,
201+
std::vector<std::shared_ptr<BuilderMember>> IfElements,
202+
std::vector<std::shared_ptr<BuilderMember>> ElseElements)
203+
: BuilderMember(MemberKind), IfElements(IfElements),
204+
ElseElements(ElseElements) {}
205+
206+
static bool classof(const BuilderMember *T) {
207+
auto Kind = T->getKind();
208+
return (Kind == MemberKind::Either) ||
209+
(Kind == MemberKind::LimitedAvailability) ||
210+
(Kind == MemberKind::Optional);
211+
}
212+
213+
std::vector<std::shared_ptr<BuilderMember>> getIfElements() const {
214+
return IfElements;
215+
}
216+
std::vector<std::shared_ptr<BuilderMember>> getElseElements() const {
217+
return ElseElements;
218+
}
219+
220+
private:
221+
std::vector<std::shared_ptr<BuilderMember>> IfElements;
222+
std::vector<std::shared_ptr<BuilderMember>> ElseElements;
223+
};
224+
225+
BuilderValue(std::vector<std::shared_ptr<BuilderMember>> Members)
226+
: CompileTimeValue(ValueKind::Builder), ResultBuilderType(std::nullopt),
227+
Members(Members) {}
228+
229+
BuilderValue(CustomAttr *ResultBuilderType,
230+
std::vector<std::shared_ptr<BuilderMember>> Members)
231+
: CompileTimeValue(ValueKind::Builder),
232+
ResultBuilderType(ResultBuilderType), Members(Members) {}
233+
234+
std::optional<CustomAttr *> getResultBuilderType() const {
235+
return ResultBuilderType;
236+
}
237+
std::vector<std::shared_ptr<BuilderMember>> getMembers() const {
238+
return Members;
239+
}
103240

104241
static bool classof(const CompileTimeValue *T) {
105242
return T->getKind() == ValueKind::Builder;
106243
}
107244

108245
private:
109-
std::vector<CompileTimeValue> Members;
246+
std::optional<CustomAttr *> ResultBuilderType;
247+
std::vector<std::shared_ptr<BuilderMember>> Members;
110248
};
111249

112250
struct TupleElement {

0 commit comments

Comments
 (0)