Skip to content

Commit c2ca7b0

Browse files
author
James Paolantonio
committed
[Const extract] Extract static function calls
1 parent ad00063 commit c2ca7b0

File tree

4 files changed

+165
-14
lines changed

4 files changed

+165
-14
lines changed

include/swift/AST/ConstTypeInfo.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class CompileTimeValue {
3939
Type,
4040
KeyPath,
4141
FunctionCall,
42+
StaticFunctionCall,
4243
MemberReference,
4344
InterpolatedString,
4445
Runtime
@@ -392,6 +393,30 @@ class FunctionCallValue : public CompileTimeValue {
392393
std::optional<std::vector<FunctionParameter>> Parameters;
393394
};
394395

396+
/// A static function reference representation such as
397+
/// let foo = MyStruct.bar(item: "")
398+
/// let foo = MyStruct.bar()
399+
class StaticFunctionCallValue : public CompileTimeValue {
400+
public:
401+
StaticFunctionCallValue(std::string Label, swift::Type Type,
402+
std::vector<FunctionParameter> Parameters)
403+
: CompileTimeValue(ValueKind::StaticFunctionCall), Label(Label),
404+
Type(Type), Parameters(Parameters) {}
405+
406+
static bool classof(const CompileTimeValue *T) {
407+
return T->getKind() == ValueKind::StaticFunctionCall;
408+
}
409+
410+
std::string getLabel() const { return Label; }
411+
swift::Type getType() const { return Type; }
412+
std::vector<FunctionParameter> getParameters() const { return Parameters; }
413+
414+
private:
415+
std::string Label;
416+
swift::Type Type;
417+
std::vector<FunctionParameter> Parameters;
418+
};
419+
395420
/// A member reference representation such as
396421
/// let foo = MyStruct.bar
397422
class MemberReferenceValue : public CompileTimeValue {

lib/ConstExtract/ConstExtract.cpp

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,12 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
294294

295295
if (functionKind == ExprKind::DeclRef) {
296296
auto declRefExpr = cast<DeclRefExpr>(callExpr->getFn());
297-
auto caseName =
297+
auto identifier =
298298
declRefExpr->getDecl()->getName().getBaseIdentifier().str().str();
299299

300300
std::vector<FunctionParameter> parameters =
301301
extractFunctionArguments(callExpr->getArgs());
302-
return std::make_shared<FunctionCallValue>(caseName, parameters);
302+
return std::make_shared<FunctionCallValue>(identifier, parameters);
303303
}
304304

305305
if (functionKind == ExprKind::ConstructorRefCall) {
@@ -313,12 +313,33 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
313313
auto fn = dotSyntaxCallExpr->getFn();
314314
if (fn->getKind() == ExprKind::DeclRef) {
315315
auto declRefExpr = cast<DeclRefExpr>(fn);
316-
auto caseName =
316+
auto baseIdentifierName =
317317
declRefExpr->getDecl()->getName().getBaseIdentifier().str().str();
318318

319319
std::vector<FunctionParameter> parameters =
320320
extractFunctionArguments(callExpr->getArgs());
321-
return std::make_shared<EnumValue>(caseName, parameters);
321+
322+
auto declRef = dotSyntaxCallExpr->getFn()->getReferencedDecl();
323+
switch (declRef.getDecl()->getKind()) {
324+
case DeclKind::EnumElement: {
325+
return std::make_shared<EnumValue>(baseIdentifierName, parameters);
326+
}
327+
328+
case DeclKind::Func: {
329+
auto identifier = declRefExpr->getDecl()
330+
->getName()
331+
.getBaseIdentifier()
332+
.str()
333+
.str();
334+
335+
return std::make_shared<StaticFunctionCallValue>(
336+
identifier, callExpr->getType(), parameters);
337+
}
338+
339+
default: {
340+
break;
341+
}
342+
}
322343
}
323344
}
324345

@@ -836,6 +857,27 @@ void writeValue(llvm::json::OStream &JSON,
836857
break;
837858
}
838859

860+
case CompileTimeValue::ValueKind::StaticFunctionCall: {
861+
auto staticFunctionCallValue = cast<StaticFunctionCallValue>(value);
862+
863+
JSON.attribute("valueKind", "StaticFunctionCall");
864+
JSON.attributeObject("value", [&]() {
865+
JSON.attribute("type", toFullyQualifiedTypeNameString(
866+
staticFunctionCallValue->getType()));
867+
JSON.attribute("memberLabel", staticFunctionCallValue->getLabel());
868+
JSON.attributeArray("arguments", [&] {
869+
for (auto FP : staticFunctionCallValue->getParameters()) {
870+
JSON.object([&] {
871+
JSON.attribute("label", FP.Label);
872+
JSON.attribute("type", toFullyQualifiedTypeNameString(FP.Type));
873+
writeValue(JSON, FP.Value);
874+
});
875+
}
876+
});
877+
});
878+
break;
879+
}
880+
839881
case CompileTimeValue::ValueKind::MemberReference: {
840882
auto memberReferenceValue = cast<MemberReferenceValue>(value);
841883
JSON.attribute("valueKind", "MemberReference");
@@ -846,6 +888,7 @@ void writeValue(llvm::json::OStream &JSON,
846888
});
847889
break;
848890
}
891+
849892
case CompileTimeValue::ValueKind::InterpolatedString: {
850893
auto interpolatedStringValue = cast<InterpolatedStringLiteralValue>(value);
851894
JSON.attribute("valueKind", "InterpolatedStringLiteral");
@@ -1049,14 +1092,11 @@ createBuilderCompileTimeValue(CustomAttr *AttachedResultBuilder,
10491092
void writeSingleBuilderMemberElement(
10501093
llvm::json::OStream &JSON, std::shared_ptr<CompileTimeValue> Element) {
10511094
switch (Element.get()->getKind()) {
1052-
case CompileTimeValue::ValueKind::Enum: {
1053-
auto enumValue = cast<EnumValue>(Element.get());
1054-
if (enumValue->getIdentifier() == "buildExpression") {
1055-
if (enumValue->getParameters().has_value()) {
1056-
auto params = enumValue->getParameters().value();
1057-
for (auto FP : params) {
1058-
writeValue(JSON, FP.Value);
1059-
}
1095+
case CompileTimeValue::ValueKind::StaticFunctionCall: {
1096+
auto staticFunctionCallValue = cast<StaticFunctionCallValue>(Element.get());
1097+
if (staticFunctionCallValue->getLabel() == "buildExpression") {
1098+
for (auto FP : staticFunctionCallValue->getParameters()) {
1099+
writeValue(JSON, FP.Value);
10601100
}
10611101
}
10621102
break;

test/ConstExtraction/ExtractCalls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ public struct Bat {
115115
// CHECK-NEXT: "name": "adder",
116116
// CHECK-NEXT: "arguments": [
117117
// CHECK-NEXT: {
118-
// CHECK-NEXT: "label": "",
119-
// CHECK-NEXT: "type": "Swift.Int",
118+
// CHECK-NEXT: "label": "",
119+
// CHECK-NEXT: "type": "Swift.Int",
120120
// CHECK-NEXT: "valueKind": "RawLiteral",
121121
// CHECK-NEXT: "value": "2"
122122
// CHECK-NEXT: },
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: echo "[MyProto]" > %t/protocols.json
3+
4+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractStaticFunctions.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s
5+
// RUN: cat %t/ExtractStaticFunctions.swiftconstvalues 2>&1 | %FileCheck %s
6+
7+
protocol MyProto {}
8+
protocol Foo {}
9+
10+
enum Bar: Foo {
11+
case one
12+
case two(item: String)
13+
}
14+
15+
struct Baz: Foo {
16+
static var one: Baz {
17+
Baz()
18+
}
19+
20+
static func two(item: String) -> Baz {
21+
return Baz()
22+
}
23+
24+
static func three() -> Baz {
25+
return Baz()
26+
}
27+
}
28+
29+
struct Statics: MyProto {
30+
var bar1 = Bar.one
31+
var bar2 = Bar.two(item: "bar")
32+
var baz1 = Baz.one
33+
var baz2 = Baz.two(item: "baz")
34+
var baz3 = Baz.three()
35+
}
36+
37+
// CHECK: "label": "bar1",
38+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Bar",
39+
// CHECK: "valueKind": "Enum",
40+
// CHECK-NEXT: "value": {
41+
// CHECK-NEXT: "name": "one"
42+
// CHECK-NEXT: }
43+
// CHECK: "label": "bar2",
44+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Bar",
45+
// CHECK: "valueKind": "Enum",
46+
// CHECK-NEXT: "value": {
47+
// CHECK-NEXT: "name": "two",
48+
// CHECK-NEXT: "arguments": [
49+
// CHECK-NEXT: {
50+
// CHECK-NEXT: "label": "item",
51+
// CHECK-NEXT: "type": "Swift.String",
52+
// CHECK-NEXT: "valueKind": "RawLiteral",
53+
// CHECK-NEXT: "value": "bar"
54+
// CHECK-NEXT: }
55+
// CHECK-NEXT: ]
56+
// CHECK-NEXT: }
57+
// CHECK: "label": "baz1",
58+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
59+
// CHECK: "valueKind": "MemberReference"
60+
// CHECK-NEXT: "value": {
61+
// CHECK-NEXT: "baseType": "ExtractStaticFunctions.Baz",
62+
// CHECK-NEXT: "memberLabel": "one"
63+
// CHECK-NEXT: }
64+
// CHECK: "label": "baz2",
65+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
66+
// CHECK: "valueKind": "StaticFunctionCall",
67+
// CHECK-NEXT: "value": {
68+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
69+
// CHECK-NEXT: "memberLabel": "two",
70+
// CHECK-NEXT: "arguments": [
71+
// CHECK-NEXT: {
72+
// CHECK-NEXT: "label": "item",
73+
// CHECK-NEXT: "type": "Swift.String",
74+
// CHECK-NEXT: "valueKind": "RawLiteral",
75+
// CHECK-NEXT: "value": "baz"
76+
// CHECK-NEXT: }
77+
// CHECK-NEXT: ]
78+
// CHECK-NEXT: }
79+
// CHECK: "label": "baz3",
80+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
81+
// CHECK: "valueKind": "StaticFunctionCall",
82+
// CHECK-NEXT: "value": {
83+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
84+
// CHECK-NEXT: "memberLabel": "three",
85+
// CHECK-NEXT: "arguments": []
86+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)