@@ -703,5 +703,69 @@ tuplify(true) { c in
703
703
}
704
704
}
705
705
706
+ // Test the use of function builders partly implemented through a protocol.
707
+ indirect enum FunctionBuilder < Expression> {
708
+ case expression( Expression )
709
+ case block( [ FunctionBuilder ] )
710
+ case either( Either < FunctionBuilder , FunctionBuilder > )
711
+ case optional( FunctionBuilder ? )
712
+ }
713
+
714
+ protocol FunctionBuilderProtocol {
715
+ associatedtype Expression
716
+ typealias Component = FunctionBuilder < Expression >
717
+ associatedtype Return
718
+
719
+ static func buildExpression( _ expression: Expression ) -> Component
720
+ static func buildBlock( _ components: Component ... ) -> Component
721
+ static func buildDo( _ components: Component ... ) -> Component
722
+ static func buildOptional( _ optional: Component ? ) -> Component
723
+ static func buildArray( _ components: [ Component ] ) -> Component
724
+ static func buildLimitedAvailability( _ component: Component ) -> Component
725
+
726
+ static func buildFinalResult( _ components: Component ) -> Return
727
+ }
728
+
729
+ extension FunctionBuilderProtocol {
730
+ static func buildExpression( _ expression: Expression ) -> Component { . expression( expression) }
731
+ static func buildBlock( _ components: Component ... ) -> Component { . block( components) }
732
+ static func buildDo( _ components: Component ... ) -> Component { . block( components) }
733
+ static func buildOptional( _ optional: Component ? ) -> Component { . optional( optional) }
734
+ static func buildArray( _ components: [ Component ] ) -> Component { . block( components) }
735
+ static func buildLimitedAvailability( _ component: Component ) -> Component { component }
736
+ }
737
+
738
+ @_functionBuilder
739
+ enum ArrayBuilder < E> : FunctionBuilderProtocol {
740
+ typealias Expression = E
741
+ typealias Component = FunctionBuilder < E >
742
+ typealias Return = [ E ]
743
+
744
+ static func buildFinalResult( _ components: Component ) -> Return {
745
+ switch components {
746
+ case . expression( let e) : return [ e]
747
+ case . block( let children) : return children. flatMap ( buildFinalResult)
748
+ case . either( . first( let child) ) : return buildFinalResult ( child)
749
+ case . either( . second( let child) ) : return buildFinalResult ( child)
750
+ case . optional( let child? ) : return buildFinalResult ( child)
751
+ case . optional( nil ) : return [ ]
752
+ }
753
+ }
754
+ }
755
+
756
+
757
+ func buildArray( @ArrayBuilder < String > build: ( ) -> [ String ] ) -> [ String ] {
758
+ return build ( )
759
+ }
706
760
707
761
762
+ let a = buildArray {
763
+ " 1 "
764
+ " 2 "
765
+ if Bool . random ( ) {
766
+ " maybe 3 "
767
+ }
768
+ }
769
+ // CHECK: ["1", "2"
770
+ print ( a)
771
+
0 commit comments