Skip to content

Commit 71e64bb

Browse files
authored
Merge pull request #69193 from kubamracek/embedded-string-interpolation
[embedded] Make ExpressibleByStringInterpolation available in embedded Swift
2 parents b257a02 + 624df4d commit 71e64bb

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

stdlib/public/core/CompilerProtocols.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -762,10 +762,10 @@ public protocol ExpressibleByDictionaryLiteral {
762762
/// `StringInterpolationProtocol` and have a matching `StringLiteralType`.
763763
///
764764
/// For more information, see the `StringInterpolationProtocol` documentation.
765-
@_unavailableInEmbedded
766765
public protocol ExpressibleByStringInterpolation
767766
: ExpressibleByStringLiteral {
768767

768+
#if !$Embedded
769769
/// The type each segment of a string literal containing interpolations
770770
/// should be appended to.
771771
///
@@ -774,6 +774,10 @@ public protocol ExpressibleByStringInterpolation
774774
associatedtype StringInterpolation: StringInterpolationProtocol
775775
= DefaultStringInterpolation
776776
where StringInterpolation.StringLiteralType == StringLiteralType
777+
#else
778+
associatedtype StringInterpolation: StringInterpolationProtocol
779+
where StringInterpolation.StringLiteralType == StringLiteralType
780+
#endif
777781

778782
/// Creates an instance from a string interpolation.
779783
///
@@ -788,7 +792,7 @@ public protocol ExpressibleByStringInterpolation
788792
init(stringInterpolation: StringInterpolation)
789793
}
790794

791-
@_unavailableInEmbedded
795+
#if !$Embedded
792796
extension ExpressibleByStringInterpolation
793797
where StringInterpolation == DefaultStringInterpolation {
794798

@@ -811,6 +815,7 @@ extension ExpressibleByStringInterpolation
811815
self.init(stringLiteral: stringInterpolation.make())
812816
}
813817
}
818+
#endif
814819

815820
/// Represents the contents of a string literal with interpolations while it's
816821
/// being built up.

test/embedded/Inputs/print.swift

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@_silgen_name("putchar")
22
func putchar(_: UInt8)
33

4-
public func print(_ s: StaticString, terminator: StaticString = "\n") {
4+
func print(_ s: StaticString, terminator: StaticString = "\n") {
55
var p = s.utf8Start
66
while p.pointee != 0 {
77
putchar(p.pointee)
@@ -13,3 +13,54 @@ public func print(_ s: StaticString, terminator: StaticString = "\n") {
1313
p += 1
1414
}
1515
}
16+
17+
func printCharacters(_ buf: UnsafeRawBufferPointer) {
18+
for c in buf {
19+
putchar(c)
20+
}
21+
}
22+
23+
func printCharacters(_ buf: UnsafeBufferPointer<UInt8>) {
24+
printCharacters(UnsafeRawBufferPointer(buf))
25+
}
26+
27+
extension BinaryInteger {
28+
func writeToStdout(radix: Int = 10) {
29+
if self == (0 as Self) {
30+
print("0", terminator: "")
31+
return
32+
}
33+
34+
func _ascii(_ digit: UInt8) -> UInt8 {
35+
if digit < 10 {
36+
UInt8(("0" as Unicode.Scalar).value) + digit
37+
} else {
38+
UInt8(("a" as Unicode.Scalar).value) + (digit - 10)
39+
}
40+
}
41+
let isNegative = Self.isSigned && self < (0 as Self)
42+
var value = magnitude
43+
withUnsafeTemporaryAllocation(byteCount: 64, alignment: 1) { buffer in
44+
var index = buffer.count - 1
45+
while value != 0 {
46+
let (quotient, remainder) = value.quotientAndRemainder(dividingBy: Magnitude(radix))
47+
buffer[index] = _ascii(UInt8(truncatingIfNeeded: remainder))
48+
index -= 1
49+
value = quotient
50+
}
51+
if isNegative {
52+
buffer[index] = UInt8(("-" as Unicode.Scalar).value)
53+
index -= 1
54+
}
55+
let start = index + 1
56+
let end = buffer.count - 1
57+
let count = end - start + 1
58+
printCharacters(UnsafeBufferPointer(start: buffer.baseAddress?.advanced(by: start).assumingMemoryBound(to: UInt8.self), count: count))
59+
}
60+
}
61+
}
62+
63+
func print(_ n: some BinaryInteger, terminator: StaticString = "\n") {
64+
n.writeToStdout()
65+
print("", terminator: terminator)
66+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %target-run-simple-swift(%S/Inputs/print.swift -enable-experimental-feature Embedded -Xfrontend -throws-as-traps -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
// REQUIRES: optimized_stdlib
5+
// REQUIRES: VENDOR=apple
6+
// REQUIRES: OS=macosx
7+
8+
public struct MyInterpolation : StringInterpolationProtocol {
9+
public typealias StringLiteralType = StaticString
10+
public init(literalCapacity: Int, interpolationCount: Int) {}
11+
12+
var literalCount = 0
13+
var interpolationCount = 0
14+
15+
public mutating func appendLiteral(_ literal: StaticString) {
16+
print("appendLiteral")
17+
literalCount += 1
18+
}
19+
20+
public mutating func appendInterpolation<T>(_ value: @autoclosure @escaping () -> T) {
21+
print("appendInterpolation<T>")
22+
interpolationCount += 1
23+
}
24+
}
25+
26+
public struct MyMessage : ExpressibleByStringInterpolation {
27+
public typealias StringInterpolation = MyInterpolation
28+
var interpolation: MyInterpolation
29+
30+
public init(stringInterpolation: MyInterpolation) {
31+
self.interpolation = stringInterpolation
32+
}
33+
34+
public init(stringLiteral value: StaticString) {
35+
self.interpolation = MyInterpolation(literalCapacity: 0, interpolationCount: 0)
36+
self.interpolation.appendLiteral(value)
37+
}
38+
}
39+
40+
public func print_interpolation(_ message: MyMessage) {
41+
print(message.interpolation.literalCount)
42+
print(message.interpolation.interpolationCount)
43+
}
44+
45+
@main
46+
struct Main {
47+
static func main() {
48+
print_interpolation("hello \(42) \(123) abc")
49+
}
50+
}
51+
52+
// CHECK: appendLiteral
53+
// CHECK: appendInterpolation<T>
54+
// CHECK: appendLiteral
55+
// CHECK: appendInterpolation<T>
56+
// CHECK: appendLiteral
57+
// CHECK: 3
58+
// CHECK: 2

0 commit comments

Comments
 (0)