Skip to content

Commit d6ecc2a

Browse files
author
James Paolantonio
committed
[Const extract] Extract static function calls
1 parent 488581f commit d6ecc2a

File tree

4 files changed

+164
-14
lines changed

4 files changed

+164
-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: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
9+
enum Bar {
10+
case one
11+
case two(item: String)
12+
}
13+
14+
struct Baz {
15+
static var one: Baz {
16+
Baz()
17+
}
18+
19+
static func two(item: String) -> Baz {
20+
return Baz()
21+
}
22+
23+
static func three() -> Baz {
24+
return Baz()
25+
}
26+
}
27+
28+
struct Statics: MyProto {
29+
var bar1 = Bar.one
30+
var bar2 = Bar.two(item: "bar")
31+
var baz1 = Baz.one
32+
var baz2 = Baz.two(item: "baz")
33+
var baz3 = Baz.three()
34+
}
35+
36+
// CHECK: "label": "bar1",
37+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Bar",
38+
// CHECK: "valueKind": "Enum",
39+
// CHECK-NEXT: "value": {
40+
// CHECK-NEXT: "name": "one"
41+
// CHECK-NEXT: }
42+
// CHECK: "label": "bar2",
43+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Bar",
44+
// CHECK: "valueKind": "Enum",
45+
// CHECK-NEXT: "value": {
46+
// CHECK-NEXT: "name": "two",
47+
// CHECK-NEXT: "arguments": [
48+
// CHECK-NEXT: {
49+
// CHECK-NEXT: "label": "item",
50+
// CHECK-NEXT: "type": "Swift.String",
51+
// CHECK-NEXT: "valueKind": "RawLiteral",
52+
// CHECK-NEXT: "value": "bar"
53+
// CHECK-NEXT: }
54+
// CHECK-NEXT: ]
55+
// CHECK-NEXT: }
56+
// CHECK: "label": "baz1",
57+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
58+
// CHECK: "valueKind": "MemberReference"
59+
// CHECK-NEXT: "value": {
60+
// CHECK-NEXT: "baseType": "ExtractStaticFunctions.Baz",
61+
// CHECK-NEXT: "memberLabel": "one"
62+
// CHECK-NEXT: }
63+
// CHECK: "label": "baz2",
64+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
65+
// CHECK: "valueKind": "StaticFunctionCall",
66+
// CHECK-NEXT: "value": {
67+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
68+
// CHECK-NEXT: "memberLabel": "two",
69+
// CHECK-NEXT: "arguments": [
70+
// CHECK-NEXT: {
71+
// CHECK-NEXT: "label": "item",
72+
// CHECK-NEXT: "type": "Swift.String",
73+
// CHECK-NEXT: "valueKind": "RawLiteral",
74+
// CHECK-NEXT: "value": "baz"
75+
// CHECK-NEXT: }
76+
// CHECK-NEXT: ]
77+
// CHECK-NEXT: }
78+
// CHECK: "label": "baz3",
79+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
80+
// CHECK: "valueKind": "StaticFunctionCall",
81+
// CHECK-NEXT: "value": {
82+
// CHECK-NEXT: "type": "ExtractStaticFunctions.Baz",
83+
// CHECK-NEXT: "memberLabel": "three",
84+
// CHECK-NEXT: "arguments": []
85+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)