Skip to content

Commit 0177c12

Browse files
committed
[Compile Time Constant Extraction] Add extraction of tuples
1 parent 186e55f commit 0177c12

File tree

3 files changed

+159
-41
lines changed

3 files changed

+159
-41
lines changed

include/swift/AST/ConstTypeInfo.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Type;
2727
/// in a type property initializer expression
2828
class CompileTimeValue {
2929
public:
30-
enum ValueKind { RawLiteral, InitCall, Builder, Dictionary, Runtime };
30+
enum ValueKind { RawLiteral, InitCall, Builder, Dictionary, Runtime, Tuple };
3131

3232
ValueKind getKind() const { return Kind; }
3333

@@ -104,6 +104,28 @@ class DictionaryValue : public CompileTimeValue {
104104
}
105105
};
106106

107+
struct TupleElement {
108+
Optional<std::string> Label;
109+
swift::Type Type;
110+
std::shared_ptr<CompileTimeValue> Value;
111+
};
112+
113+
/// A representation of a tuple and each tuple-element
114+
class TupleValue : public CompileTimeValue {
115+
public:
116+
TupleValue(std::vector<TupleElement> Elements)
117+
: CompileTimeValue(ValueKind::Tuple), Elements(Elements) {}
118+
119+
static bool classof(const CompileTimeValue *T) {
120+
return T->getKind() == ValueKind::Tuple;
121+
}
122+
123+
std::vector<TupleElement> getElements() const { return Elements; }
124+
125+
private:
126+
std::vector<TupleElement> Elements;
127+
};
128+
107129
/// A representation of an arbitrary value that does not fall under
108130
/// any of the above categories.
109131
class RuntimeValue : public CompileTimeValue {

lib/ConstExtract/ConstExtract.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
125125
switch (expr->getKind()) {
126126
case ExprKind::Array:
127127
case ExprKind::Dictionary:
128-
case ExprKind::Tuple:
129128

130129
case ExprKind::BooleanLiteral:
131130
case ExprKind::FloatLiteral:
@@ -141,6 +140,33 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
141140
break;
142141
}
143142

143+
case ExprKind::Tuple: {
144+
auto tupleExpr = cast<TupleExpr>(expr);
145+
146+
std::vector<TupleElement> elements;
147+
if (tupleExpr->hasElementNames()) {
148+
for (auto pair : llvm::zip(tupleExpr->getElements(),
149+
tupleExpr->getElementNames())) {
150+
auto elementExpr = std::get<0>(pair);
151+
auto elementName = std::get<1>(pair);
152+
153+
Optional<std::string> label =
154+
elementName.empty()
155+
? Optional<std::string>()
156+
: Optional<std::string>(elementName.str().str());
157+
158+
elements.push_back({label, elementExpr->getType(),
159+
extractCompileTimeValue(elementExpr)});
160+
}
161+
} else {
162+
for (auto elementExpr : tupleExpr->getElements()) {
163+
elements.push_back({Optional<std::string>(), elementExpr->getType(),
164+
extractCompileTimeValue(elementExpr)});
165+
}
166+
}
167+
return std::make_shared<TupleValue>(elements);
168+
}
169+
144170
case ExprKind::Call: {
145171
auto callExpr = cast<CallExpr>(expr);
146172
if (callExpr->getFn()->getKind() == ExprKind::ConstructorRefCall) {
@@ -287,6 +313,22 @@ void writeValue(llvm::json::OStream &JSON,
287313
break;
288314
}
289315

316+
case CompileTimeValue::ValueKind::Tuple: {
317+
auto tupleValue = cast<TupleValue>(value);
318+
319+
JSON.attribute("valueKind", "Tuple");
320+
JSON.attributeArray("value", [&] {
321+
for (auto TV : tupleValue->getElements()) {
322+
JSON.object([&] {
323+
JSON.attribute("label", TV.Label);
324+
JSON.attribute("type", toFullyQualifiedTypeNameString(TV.Type));
325+
writeValue(JSON, TV.Value);
326+
});
327+
}
328+
});
329+
break;
330+
}
331+
290332
case CompileTimeValue::ValueKind::Builder: {
291333
JSON.attribute("valueKind", "Builder");
292334
break;

test/ConstExtraction/fields.swift

Lines changed: 93 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,22 @@
2020
// CHECK-NEXT: },
2121
// CHECK-NEXT: {
2222
// CHECK-NEXT: "label": "p5",
23-
// CHECK-NEXT: "type": "[Swift.Int]",
24-
// CHECK-NEXT: "isStatic": "false",
25-
// CHECK-NEXT: "isComputed": "false",
26-
// CHECK-NEXT: "valueKind": "RawLiteral",
27-
// CHECK-NEXT: "value": "[1, 2, 3, 4, 5, 6, 7, 8, 9]"
28-
// CHECK-NEXT: },
29-
// CHECK-NEXT: {
30-
// CHECK-NEXT: "label": "p6",
3123
// CHECK-NEXT: "type": "Swift.Bool",
3224
// CHECK-NEXT: "isStatic": "false",
3325
// CHECK-NEXT: "isComputed": "false",
3426
// CHECK-NEXT: "valueKind": "RawLiteral",
3527
// CHECK-NEXT: "value": "false"
3628
// CHECK-NEXT: },
3729
// CHECK-NEXT: {
38-
// CHECK-NEXT: "label": "p7",
30+
// CHECK-NEXT: "label": "p6",
3931
// CHECK-NEXT: "type": "Swift.Bool?",
4032
// CHECK-NEXT: "isStatic": "false",
4133
// CHECK-NEXT: "isComputed": "false",
4234
// CHECK-NEXT: "valueKind": "RawLiteral",
4335
// CHECK-NEXT: "value": "nil"
4436
// CHECK-NEXT: },
4537
// CHECK-NEXT: {
46-
// CHECK-NEXT: "label": "p8",
47-
// CHECK-NEXT: "type": "(Swift.Int, Swift.Float)",
48-
// CHECK-NEXT: "isStatic": "false",
49-
// CHECK-NEXT: "isComputed": "false",
50-
// CHECK-NEXT: "valueKind": "RawLiteral",
51-
// CHECK-NEXT: "value": "(42, 6.6)"
52-
// CHECK-NEXT: },
53-
// CHECK-NEXT: {
54-
// CHECK-NEXT: "label": "p9",
55-
// CHECK-NEXT: "type": "[Swift.String : Swift.Int]",
56-
// CHECK-NEXT: "isStatic": "false",
57-
// CHECK-NEXT: "isComputed": "false",
58-
// CHECK-NEXT: "valueKind": "RawLiteral",
59-
// CHECK-NEXT: "value": "[(\"One\", 1), (\"Two\", 2), (\"Three\", 3)]"
60-
// CHECK-NEXT: },
61-
// CHECK-NEXT: {
62-
// CHECK-NEXT: "label": "p10",
38+
// CHECK-NEXT: "label": "p7",
6339
// CHECK-NEXT: "type": "fields.Bar",
6440
// CHECK-NEXT: "isStatic": "false",
6541
// CHECK-NEXT: "isComputed": "false",
@@ -70,7 +46,7 @@
7046
// CHECK-NEXT: }
7147
// CHECK-NEXT: },
7248
// CHECK-NEXT: {
73-
// CHECK-NEXT: "label": "p11",
49+
// CHECK-NEXT: "label": "p8",
7450
// CHECK-NEXT: "type": "fields.Bat",
7551
// CHECK-NEXT: "isStatic": "false",
7652
// CHECK-NEXT: "isComputed": "false",
@@ -94,7 +70,7 @@
9470
// CHECK-NEXT: }
9571
// CHECK-NEXT: },
9672
// CHECK-NEXT: {
97-
// CHECK-NEXT: "label": "p12",
73+
// CHECK-NEXT: "label": "p9",
9874
// CHECK-NEXT: "type": "fields.Bat",
9975
// CHECK-NEXT: "isStatic": "false",
10076
// CHECK-NEXT: "isComputed": "false",
@@ -117,13 +93,82 @@
11793
// CHECK-NEXT: }
11894
// CHECK-NEXT: },
11995
// CHECK-NEXT: {
120-
// CHECK-NEXT: "label": "p13",
96+
// CHECK-NEXT: "label": "p10",
12197
// CHECK-NEXT: "type": "Swift.Int",
12298
// CHECK-NEXT: "isStatic": "false",
12399
// CHECK-NEXT: "isComputed": "false",
124100
// CHECK-NEXT: "valueKind": "Runtime"
125101
// CHECK-NEXT: },
126102
// CHECK-NEXT: {
103+
// CHECK-NEXT: "label": "a1",
104+
// CHECK-NEXT: "type": "[Swift.Int]",
105+
// CHECK-NEXT: "isStatic": "false",
106+
// CHECK-NEXT: "isComputed": "false",
107+
// CHECK-NEXT: "valueKind": "RawLiteral",
108+
// CHECK-NEXT: "value": "[1, 2, 3, 4, 5, 6, 7, 8, 9]"
109+
// CHECK-NEXT: },
110+
// CHECK-NEXT: {
111+
// CHECK-NEXT: "label": "d1",
112+
// CHECK-NEXT: "type": "[Swift.String : Swift.Int]",
113+
// CHECK-NEXT: "isStatic": "false",
114+
// CHECK-NEXT: "isComputed": "false",
115+
// CHECK-NEXT: "valueKind": "RawLiteral",
116+
// CHECK-NEXT: "value": "[(\"One\", 1), (\"Two\", 2), (\"Three\", 3)]"
117+
// CHECK-NEXT: },
118+
// CHECK-NEXT: {
119+
// CHECK-NEXT: "label": "t1",
120+
// CHECK-NEXT: "type": "(Swift.String, fields.Bar)",
121+
// CHECK-NEXT: "isStatic": "false",
122+
// CHECK-NEXT: "isComputed": "false",
123+
// CHECK-NEXT: "valueKind": "Tuple",
124+
// CHECK-NEXT: "value": [
125+
// CHECK-NEXT: {
126+
// CHECK-NEXT: "label": null,
127+
// CHECK-NEXT: "type": "Swift.String",
128+
// CHECK-NEXT: "valueKind": "RawLiteral",
129+
// CHECK-NEXT: "value": "\"foo\""
130+
// CHECK-NEXT: },
131+
// CHECK-NEXT: {
132+
// CHECK-NEXT: "label": null,
133+
// CHECK-NEXT: "type": "fields.Bar",
134+
// CHECK-NEXT: "valueKind": "InitCall",
135+
// CHECK-NEXT: "value": {
136+
// CHECK-NEXT: "type": "fields.Bar",
137+
// CHECK-NEXT: "arguments": []
138+
// CHECK-NEXT: }
139+
// CHECK-NEXT: }
140+
// CHECK-NEXT: ]
141+
// CHECK-NEXT: },
142+
// CHECK-NEXT: {
143+
// CHECK-NEXT: "label": "t2",
144+
// CHECK-NEXT: "type": "(lat: Swift.Float, lng: Swift.Float)",
145+
// CHECK-NEXT: "isStatic": "false",
146+
// CHECK-NEXT: "isComputed": "false",
147+
// CHECK-NEXT: "valueKind": "Tuple",
148+
// CHECK-NEXT: "value": [
149+
// CHECK-NEXT: {
150+
// CHECK-NEXT: "label": "lat",
151+
// CHECK-NEXT: "type": "Swift.Float",
152+
// CHECK-NEXT: "valueKind": "RawLiteral",
153+
// CHECK-NEXT: "value": "42.7"
154+
// CHECK-NEXT: },
155+
// CHECK-NEXT: {
156+
// CHECK-NEXT: "label": "lng",
157+
// CHECK-NEXT: "type": "Swift.Float",
158+
// CHECK-NEXT: "valueKind": "RawLiteral",
159+
// CHECK-NEXT: "value": "-73.9"
160+
// CHECK-NEXT: }
161+
// CHECK-NEXT: ]
162+
// CHECK-NEXT: },
163+
// CHECK-NEXT: {
164+
// CHECK-NEXT: "label": "t3",
165+
// CHECK-NEXT: "type": "Swift.Void",
166+
// CHECK-NEXT: "isStatic": "false",
167+
// CHECK-NEXT: "isComputed": "false",
168+
// CHECK-NEXT: "valueKind": "Tuple",
169+
// CHECK-NEXT: "value": []
170+
// CHECK-NEXT: },
171+
// CHECK-NEXT: {
127172
// CHECK-NEXT: "label": "p0",
128173
// CHECK-NEXT: "type": "Swift.Int",
129174
// CHECK-NEXT: "isStatic": "true",
@@ -160,7 +205,11 @@
160205
// CHECK-NEXT: "type": "fields.Foo.Boo",
161206
// CHECK-NEXT: "isStatic": "false",
162207
// CHECK-NEXT: "isComputed": "true",
163-
// CHECK-NEXT: "valueKind": "Runtime"
208+
// CHECK-NEXT: "valueKind": "InitCall",
209+
// CHECK-NEXT: "value": {
210+
// CHECK-NEXT: "type": "fields.Foo.Boo",
211+
// CHECK-NEXT: "arguments": []
212+
// CHECK-NEXT: }
164213
// CHECK-NEXT: }
165214
// CHECK-NEXT: ]
166215
// CHECK-NEXT: }
@@ -174,15 +223,20 @@ public struct Foo {
174223
static let p2: Float = 42.2
175224
var p3: Int {3}
176225
static var p4: Int { return 3 }
177-
let p5: [Int] = [1,2,3,4,5,6,7,8,9]
178-
let p6: Bool = false
179-
let p7: Bool? = nil
180-
let p8: (Int, Float) = (42, 6.6)
181-
let p9: [String: Int] = ["One": 1, "Two": 2, "Three": 3]
182-
let p10 = Bar()
183-
let p11: Bat = .init()
184-
let p12 = Bat(buz: "hello", fuz: adder(2, 3))
185-
let p13: Int = adder(2, 3)
226+
let p5: Bool = false
227+
let p6: Bool? = nil
228+
let p7 = Bar()
229+
let p8: Bat = .init()
230+
let p9 = Bat(buz: "hello", fuz: adder(2, 3))
231+
let p10: Int = adder(2, 3)
232+
233+
let a1: [Int] = [1,2,3,4,5,6,7,8,9]
234+
235+
let d1: [String: Int] = ["One": 1, "Two": 2, "Three": 3]
236+
237+
let t1: (String, Bar) = ("foo", Bar())
238+
let t2: (lat: Float, lng: Float) = (lat: 42.7, lng: -73.9)
239+
let t3: Void = ()
186240
}
187241

188242
extension Foo {

0 commit comments

Comments
 (0)