Skip to content

Commit

Permalink
[Compile Time Constant Extraction] Add extraction of tuples (swiftlan…
Browse files Browse the repository at this point in the history
  • Loading branch information
jPaolantonio authored Dec 13, 2022
1 parent 850c280 commit 0d666e2
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 6 deletions.
24 changes: 23 additions & 1 deletion include/swift/AST/ConstTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Type;
/// in a type property initializer expression
class CompileTimeValue {
public:
enum ValueKind { RawLiteral, InitCall, Builder, Dictionary, Runtime };
enum ValueKind { RawLiteral, InitCall, Builder, Dictionary, Runtime, Tuple };

ValueKind getKind() const { return Kind; }

Expand Down Expand Up @@ -104,6 +104,28 @@ class DictionaryValue : public CompileTimeValue {
}
};

struct TupleElement {
Optional<std::string> Label;
swift::Type Type;
std::shared_ptr<CompileTimeValue> Value;
};

/// A representation of a tuple and each tuple-element
class TupleValue : public CompileTimeValue {
public:
TupleValue(std::vector<TupleElement> Elements)
: CompileTimeValue(ValueKind::Tuple), Elements(Elements) {}

static bool classof(const CompileTimeValue *T) {
return T->getKind() == ValueKind::Tuple;
}

std::vector<TupleElement> getElements() const { return Elements; }

private:
std::vector<TupleElement> Elements;
};

/// A representation of an arbitrary value that does not fall under
/// any of the above categories.
class RuntimeValue : public CompileTimeValue {
Expand Down
46 changes: 45 additions & 1 deletion lib/ConstExtract/ConstExtract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
switch (expr->getKind()) {
case ExprKind::Array:
case ExprKind::Dictionary:
case ExprKind::Tuple:

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

case ExprKind::Tuple: {
auto tupleExpr = cast<TupleExpr>(expr);

std::vector<TupleElement> elements;
if (tupleExpr->hasElementNames()) {
for (auto pair : llvm::zip(tupleExpr->getElements(),
tupleExpr->getElementNames())) {
auto elementExpr = std::get<0>(pair);
auto elementName = std::get<1>(pair);

Optional<std::string> label =
elementName.empty()
? Optional<std::string>()
: Optional<std::string>(elementName.str().str());

elements.push_back({label, elementExpr->getType(),
extractCompileTimeValue(elementExpr)});
}
} else {
for (auto elementExpr : tupleExpr->getElements()) {
elements.push_back({Optional<std::string>(), elementExpr->getType(),
extractCompileTimeValue(elementExpr)});
}
}
return std::make_shared<TupleValue>(elements);
}

case ExprKind::Call: {
auto callExpr = cast<CallExpr>(expr);
if (callExpr->getFn()->getKind() == ExprKind::ConstructorRefCall) {
Expand Down Expand Up @@ -287,6 +313,24 @@ void writeValue(llvm::json::OStream &JSON,
break;
}

case CompileTimeValue::ValueKind::Tuple: {
auto tupleValue = cast<TupleValue>(value);

JSON.attribute("valueKind", "Tuple");
JSON.attributeArray("value", [&] {
for (auto TV : tupleValue->getElements()) {
JSON.object([&] {
if (auto Label = TV.Label) {
JSON.attribute("label", Label);
}
JSON.attribute("type", toFullyQualifiedTypeNameString(TV.Type));
writeValue(JSON, TV.Value);
});
}
});
break;
}

case CompileTimeValue::ValueKind::Builder: {
JSON.attribute("valueKind", "Builder");
break;
Expand Down
55 changes: 51 additions & 4 deletions test/ConstExtraction/ExtractGroups.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,54 @@
// CHECK-NEXT: "properties": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "tuple1",
// CHECK-NEXT: "type": "(Swift.Int, Swift.Float)",
// CHECK-NEXT: "type": "(Swift.String, ExtractGroups.Bar)",
// CHECK-NEXT: "isStatic": "false",
// CHECK-NEXT: "isComputed": "false",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "(42, 6.6)"
// CHECK-NEXT: "valueKind": "Tuple",
// CHECK-NEXT: "value": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "\"foo\""
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ExtractGroups.Bar",
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractGroups.Bar",
// CHECK-NEXT: "arguments": []
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "tuple2",
// CHECK-NEXT: "type": "(lat: Swift.Float, lng: Swift.Float)",
// CHECK-NEXT: "isStatic": "false",
// CHECK-NEXT: "isComputed": "false",
// CHECK-NEXT: "valueKind": "Tuple",
// CHECK-NEXT: "value": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "lat",
// CHECK-NEXT: "type": "Swift.Float",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "42.7"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "lng",
// CHECK-NEXT: "type": "Swift.Float",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "-73.9"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "tuple3",
// CHECK-NEXT: "type": "Swift.Void",
// CHECK-NEXT: "isStatic": "false",
// CHECK-NEXT: "isComputed": "false",
// CHECK-NEXT: "valueKind": "Tuple",
// CHECK-NEXT: "value": []
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
Expand All @@ -60,5 +103,9 @@ public struct Dictionaries : MyProto {
}

public struct Tuples : MyProto {
let tuple1: (Int, Float) = (42, 6.6)
let tuple1: (String, Bar) = ("foo", Bar())
let tuple2: (lat: Float, lng: Float) = (lat: 42.7, lng: -73.9)
let tuple3: Void = ()
}

public struct Bar {}

0 comments on commit 0d666e2

Please sign in to comment.