Skip to content

Commit 2338c50

Browse files
committed
[Compile Time Constant Extraction] Add extraction of arrays
1 parent 0b74e7b commit 2338c50

File tree

4 files changed

+222
-4
lines changed

4 files changed

+222
-4
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/ExtractGroups.swift

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,61 @@
1414
// CHECK-NEXT: "type": "[Swift.Int]",
1515
// CHECK-NEXT: "isStatic": "false",
1616
// CHECK-NEXT: "isComputed": "false",
17-
// CHECK-NEXT: "valueKind": "RawLiteral",
18-
// CHECK-NEXT: "value": "[1, 2, 3]"
17+
// CHECK-NEXT: "valueKind": "Array",
18+
// CHECK-NEXT: "value": [
19+
// CHECK-NEXT: {
20+
// CHECK-NEXT: "valueKind": "RawLiteral",
21+
// CHECK-NEXT: "value": "1"
22+
// CHECK-NEXT: },
23+
// CHECK-NEXT: {
24+
// CHECK-NEXT: "valueKind": "RawLiteral",
25+
// CHECK-NEXT: "value": "2"
26+
// CHECK-NEXT: },
27+
// CHECK-NEXT: {
28+
// CHECK-NEXT: "valueKind": "RawLiteral",
29+
// CHECK-NEXT: "value": "3"
30+
// CHECK-NEXT: }
31+
// CHECK-NEXT: ]
32+
// CHECK-NEXT: },
33+
// CHECK-NEXT: {
34+
// CHECK-NEXT: "label": "array2",
35+
// CHECK-NEXT: "type": "[ExtractGroups.Foo]",
36+
// CHECK-NEXT: "isStatic": "false",
37+
// CHECK-NEXT: "isComputed": "false",
38+
// CHECK-NEXT: "valueKind": "Array",
39+
// CHECK-NEXT: "value": [
40+
// CHECK-NEXT: {
41+
// CHECK-NEXT: "valueKind": "InitCall",
42+
// CHECK-NEXT: "value": {
43+
// CHECK-NEXT: "type": "ExtractGroups.Bar",
44+
// CHECK-NEXT: "arguments": []
45+
// CHECK-NEXT: }
46+
// CHECK-NEXT: },
47+
// CHECK-NEXT: {
48+
// CHECK-NEXT: "valueKind": "RawLiteral",
49+
// CHECK-NEXT: "value": "1"
50+
// CHECK-NEXT: },
51+
// CHECK-NEXT: {
52+
// CHECK-NEXT: "valueKind": "RawLiteral",
53+
// CHECK-NEXT: "value": "\"hi\""
54+
// CHECK-NEXT: }
55+
// CHECK-NEXT: ]
56+
// CHECK-NEXT: },
57+
// CHECK-NEXT: {
58+
// CHECK-NEXT: "label": "array3",
59+
// CHECK-NEXT: "type": "[ExtractGroups.Bar]",
60+
// CHECK-NEXT: "isStatic": "false",
61+
// CHECK-NEXT: "isComputed": "false",
62+
// CHECK-NEXT: "valueKind": "Array",
63+
// CHECK-NEXT: "value": [
64+
// CHECK-NEXT: {
65+
// CHECK-NEXT: "valueKind": "InitCall",
66+
// CHECK-NEXT: "value": {
67+
// CHECK-NEXT: "type": "ExtractGroups.Bar",
68+
// CHECK-NEXT: "arguments": []
69+
// CHECK-NEXT: }
70+
// CHECK-NEXT: }
71+
// CHECK-NEXT: ]
1972
// CHECK-NEXT: }
2073
// CHECK-NEXT: ]
2174
// CHECK-NEXT: },
@@ -53,6 +106,8 @@ protocol MyProto {}
53106

54107
public struct Arrays : MyProto {
55108
let array1: [Int] = [1, 2, 3]
109+
let array2: [Foo] = [Bar(), 1, "hi"]
110+
let array3: [Bar] = [Bar()]
56111
}
57112

58113
public struct Dictionaries : MyProto {
@@ -62,3 +117,8 @@ public struct Dictionaries : MyProto {
62117
public struct Tuples : MyProto {
63118
let tuple1: (Int, Float) = (42, 6.6)
64119
}
120+
121+
public protocol Foo {}
122+
public struct Bar: Foo {}
123+
extension Int: Foo {}
124+
extension String: Foo {}

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 {}

0 commit comments

Comments
 (0)