Skip to content

Commit f1ab59c

Browse files
committed
[Compile Time Constant Extraction] Add extraction of arrays
1 parent d6efe55 commit f1ab59c

File tree

4 files changed

+175
-26
lines changed

4 files changed

+175
-26
lines changed

include/swift/AST/ConstTypeInfo.h

Lines changed: 18 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, Array, Runtime };
3131

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

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

107+
/// An arrary literal value representation
108+
class ArrayValue : public CompileTimeValue {
109+
public:
110+
ArrayValue(std::vector<std::shared_ptr<CompileTimeValue>> Elements)
111+
: CompileTimeValue(ValueKind::Array), Elements(Elements) {}
112+
113+
static bool classof(const CompileTimeValue *T) {
114+
return T->getKind() == ValueKind::Array;
115+
}
116+
std::vector<std::shared_ptr<CompileTimeValue>> getElements() const {
117+
return Elements;
118+
}
119+
120+
private:
121+
std::vector<std::shared_ptr<CompileTimeValue>> Elements;
122+
};
123+
107124
/// A representation of an arbitrary value that does not fall under
108125
/// any of the above categories.
109126
class RuntimeValue : public CompileTimeValue {

lib/ConstExtract/ConstExtract.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ parseProtocolListFromFile(StringRef protocolListFilePath,
123123
static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
124124
if (expr) {
125125
switch (expr->getKind()) {
126-
case ExprKind::Array:
127126
case ExprKind::Dictionary:
128127
case ExprKind::Tuple:
129128

@@ -141,6 +140,15 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
141140
break;
142141
}
143142

143+
case ExprKind::Array: {
144+
auto arrayExpr = cast<ArrayExpr>(expr);
145+
std::vector<std::shared_ptr<CompileTimeValue>> elementValues;
146+
for (const auto elementExpr : arrayExpr->getElements()) {
147+
elementValues.push_back(extractCompileTimeValue(elementExpr));
148+
}
149+
return std::make_shared<ArrayValue>(elementValues);
150+
}
151+
144152
case ExprKind::Call: {
145153
auto callExpr = cast<CallExpr>(expr);
146154
if (callExpr->getFn()->getKind() == ExprKind::ConstructorRefCall) {
@@ -164,6 +172,11 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
164172
break;
165173
}
166174

175+
case ExprKind::Erasure: {
176+
auto erasureExpr = cast<ErasureExpr>(expr);
177+
return extractCompileTimeValue(erasureExpr->getSubExpr());
178+
}
179+
167180
default: {
168181
break;
169182
}
@@ -297,6 +310,18 @@ void writeValue(llvm::json::OStream &JSON,
297310
break;
298311
}
299312

313+
case CompileTimeValue::ValueKind::Array: {
314+
auto arrayValue = cast<ArrayValue>(value);
315+
316+
JSON.attribute("valueKind", "Array");
317+
JSON.attributeArray("value", [&] {
318+
for (auto FP : arrayValue->getElements()) {
319+
JSON.object([&] { writeValue(JSON, FP); });
320+
}
321+
});
322+
break;
323+
}
324+
300325
case CompileTimeValue::ValueKind::Runtime: {
301326
JSON.attribute("valueKind", "Runtime");
302327
break;

test/ConstExtraction/arrays.swift

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/inputs)
3+
// RUN: echo "[MyProto]" > %t/inputs/protocols.json
4+
5+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/arrays.swiftconstvalues -const-gather-protocols-file %t/inputs/protocols.json -primary-file %s
6+
// RUN: cat %t/arrays.swiftconstvalues 2>&1 | %FileCheck %s
7+
8+
// CHECK: [
9+
// CHECK-NEXT: {
10+
// CHECK-NEXT: "typeName": "arrays.Foo",
11+
// CHECK-NEXT: "kind": "struct",
12+
// CHECK-NEXT: "properties": [
13+
// CHECK-NEXT: {
14+
// CHECK-NEXT: "label": "a1",
15+
// CHECK-NEXT: "type": "[Swift.Int]",
16+
// CHECK-NEXT: "isStatic": "false",
17+
// CHECK-NEXT: "isComputed": "false",
18+
// CHECK-NEXT: "valueKind": "Array",
19+
// CHECK-NEXT: "value": [
20+
// CHECK-NEXT: {
21+
// CHECK-NEXT: "valueKind": "RawLiteral",
22+
// CHECK-NEXT: "value": "1"
23+
// CHECK-NEXT: },
24+
// CHECK-NEXT: {
25+
// CHECK-NEXT: "valueKind": "RawLiteral",
26+
// CHECK-NEXT: "value": "2"
27+
// CHECK-NEXT: },
28+
// CHECK-NEXT: {
29+
// CHECK-NEXT: "valueKind": "RawLiteral",
30+
// CHECK-NEXT: "value": "3"
31+
// CHECK-NEXT: },
32+
// CHECK-NEXT: {
33+
// CHECK-NEXT: "valueKind": "RawLiteral",
34+
// CHECK-NEXT: "value": "4"
35+
// CHECK-NEXT: },
36+
// CHECK-NEXT: {
37+
// CHECK-NEXT: "valueKind": "RawLiteral",
38+
// CHECK-NEXT: "value": "5"
39+
// CHECK-NEXT: },
40+
// CHECK-NEXT: {
41+
// CHECK-NEXT: "valueKind": "RawLiteral",
42+
// CHECK-NEXT: "value": "6"
43+
// CHECK-NEXT: },
44+
// CHECK-NEXT: {
45+
// CHECK-NEXT: "valueKind": "RawLiteral",
46+
// CHECK-NEXT: "value": "7"
47+
// CHECK-NEXT: },
48+
// CHECK-NEXT: {
49+
// CHECK-NEXT: "valueKind": "RawLiteral",
50+
// CHECK-NEXT: "value": "8"
51+
// CHECK-NEXT: },
52+
// CHECK-NEXT: {
53+
// CHECK-NEXT: "valueKind": "RawLiteral",
54+
// CHECK-NEXT: "value": "9"
55+
// CHECK-NEXT: }
56+
// CHECK-NEXT: ]
57+
// CHECK-NEXT: },
58+
// CHECK-NEXT: {
59+
// CHECK-NEXT: "label": "a2",
60+
// CHECK-NEXT: "type": "[arrays.Buildable]",
61+
// CHECK-NEXT: "isStatic": "false",
62+
// CHECK-NEXT: "isComputed": "false",
63+
// CHECK-NEXT: "valueKind": "Array",
64+
// CHECK-NEXT: "value": [
65+
// CHECK-NEXT: {
66+
// CHECK-NEXT: "valueKind": "InitCall"
67+
// CHECK-NEXT: "value": {
68+
// CHECK-NEXT: "type": "arrays.Bar",
69+
// CHECK-NEXT: "arguments": []
70+
// CHECK-NEXT: }
71+
// CHECK-NEXT: },
72+
// CHECK-NEXT: {
73+
// CHECK-NEXT: "valueKind": "RawLiteral",
74+
// CHECK-NEXT: "value": "1"
75+
// CHECK-NEXT: }
76+
// CHECK-NEXT: {
77+
// CHECK-NEXT: "valueKind": "RawLiteral",
78+
// CHECK-NEXT: "value": "\"hi\""
79+
// CHECK-NEXT: }
80+
// CHECK-NEXT: ]
81+
// CHECK-NEXT: },
82+
// CHECK-NEXT: {
83+
// CHECK-NEXT: "label": "a3",
84+
// CHECK-NEXT: "type": "[arrays.Bar]",
85+
// CHECK-NEXT: "isStatic": "false",
86+
// CHECK-NEXT: "isComputed": "false",
87+
// CHECK-NEXT: "valueKind": "Array",
88+
// CHECK-NEXT: "value": [
89+
// CHECK-NEXT: {
90+
// CHECK-NEXT: "valueKind": "InitCall",
91+
// CHECK-NEXT: "value": {
92+
// CHECK-NEXT: "type": "arrays.Bar",
93+
// CHECK-NEXT: "arguments": []
94+
// CHECK-NEXT: }
95+
// CHECK-NEXT: }
96+
// CHECK-NEXT: ]
97+
// CHECK-NEXT: }
98+
// CHECK-NEXT: ]
99+
// CHECK-NEXT: }
100+
// CHECK-NEXT:]
101+
102+
protocol MyProto {}
103+
104+
public struct Foo {
105+
let a1: [Int] = [1,2,3,4,5,6,7,8,9]
106+
let a2: [Buildable] = [Bar(), 1, "hi"]
107+
let a3: [Bar] = [Bar()]
108+
}
109+
110+
protocol Buildable {}
111+
112+
public struct Bar: Buildable {}
113+
extension Int: Buildable {}
114+
extension String: Buildable {}
115+
116+
extension Foo : MyProto {}

test/ConstExtraction/fields.swift

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,38 @@
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",
38+
// CHECK-NEXT: "label": "p7",
4739
// CHECK-NEXT: "type": "(Swift.Int, Swift.Float)",
4840
// CHECK-NEXT: "isStatic": "false",
4941
// CHECK-NEXT: "isComputed": "false",
5042
// CHECK-NEXT: "valueKind": "RawLiteral",
5143
// CHECK-NEXT: "value": "(42, 6.6)"
5244
// CHECK-NEXT: },
5345
// CHECK-NEXT: {
54-
// CHECK-NEXT: "label": "p9",
46+
// CHECK-NEXT: "label": "p8",
5547
// CHECK-NEXT: "type": "[Swift.String : Swift.Int]",
5648
// CHECK-NEXT: "isStatic": "false",
5749
// CHECK-NEXT: "isComputed": "false",
5850
// CHECK-NEXT: "valueKind": "RawLiteral",
5951
// CHECK-NEXT: "value": "[(\"One\", 1), (\"Two\", 2), (\"Three\", 3)]"
6052
// CHECK-NEXT: },
6153
// CHECK-NEXT: {
62-
// CHECK-NEXT: "label": "p10",
54+
// CHECK-NEXT: "label": "p9",
6355
// CHECK-NEXT: "type": "fields.Bar",
6456
// CHECK-NEXT: "isStatic": "false",
6557
// CHECK-NEXT: "isComputed": "false",
@@ -70,7 +62,7 @@
7062
// CHECK-NEXT: }
7163
// CHECK-NEXT: },
7264
// CHECK-NEXT: {
73-
// CHECK-NEXT: "label": "p11",
65+
// CHECK-NEXT: "label": "p10",
7466
// CHECK-NEXT: "type": "fields.Bat",
7567
// CHECK-NEXT: "isStatic": "false",
7668
// CHECK-NEXT: "isComputed": "false",
@@ -94,7 +86,7 @@
9486
// CHECK-NEXT: }
9587
// CHECK-NEXT: },
9688
// CHECK-NEXT: {
97-
// CHECK-NEXT: "label": "p12",
89+
// CHECK-NEXT: "label": "p11",
9890
// CHECK-NEXT: "type": "fields.Bat",
9991
// CHECK-NEXT: "isStatic": "false",
10092
// CHECK-NEXT: "isComputed": "false",
@@ -117,7 +109,7 @@
117109
// CHECK-NEXT: }
118110
// CHECK-NEXT: },
119111
// CHECK-NEXT: {
120-
// CHECK-NEXT: "label": "p13",
112+
// CHECK-NEXT: "label": "p12",
121113
// CHECK-NEXT: "type": "Swift.Int",
122114
// CHECK-NEXT: "isStatic": "false",
123115
// CHECK-NEXT: "isComputed": "false",
@@ -178,15 +170,14 @@ public struct Foo {
178170
static let p2: Float = 42.2
179171
var p3: Int {3}
180172
static var p4: Int { return 3 }
181-
let p5: [Int] = [1,2,3,4,5,6,7,8,9]
182-
let p6: Bool = false
183-
let p7: Bool? = nil
184-
let p8: (Int, Float) = (42, 6.6)
185-
let p9: [String: Int] = ["One": 1, "Two": 2, "Three": 3]
186-
let p10 = Bar()
187-
let p11: Bat = .init()
188-
let p12 = Bat(buz: "hello", fuz: adder(2, 3))
189-
let p13: Int = adder(2, 3)
173+
let p5: Bool = false
174+
let p6: Bool? = nil
175+
let p7: (Int, Float) = (42, 6.6)
176+
let p8: [String: Int] = ["One": 1, "Two": 2, "Three": 3]
177+
let p9 = Bar()
178+
let p10: Bat = .init()
179+
let p11 = Bat(buz: "hello", fuz: adder(2, 3))
180+
let p12: Int = adder(2, 3)
190181
}
191182

192183
extension Foo {

0 commit comments

Comments
 (0)