Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FunctionBuilderでコンパイラを表現しようとした

yosshi
June 18, 2019

 FunctionBuilderでコンパイラを表現しようとした

FunctionBuilderでコンパイラを表現しようとしたけど、できなかったしユースケースも違った話

yosshi

June 18, 2019
Tweet

More Decks by yosshi

Other Decks in Technology

Transcript

  1. ͜͏ॻ͚ͨΒؾ࣋ͪྑ͍ͷͰ͸ʂ var body: some VMCommand { Function(name: “mult”) {
 Push(.constant,

    0) Pop(.local, 0) Push(.argument, 1) Pop(.local, 1) Label(“LOOP”)
 …. Label(“END”) Return }
 ɹ… } var commands: [Command] = []
 func build() -> String { commands.append(Push(.constant, 0)) commands.append(Pop(.argument, 1)) commands.append(Pop(.local, 1)) commands.append(Label(“Loop”)) return commands .map { $0.generate() }
 .joined(separator: “\n”) } ݱঢ় FunctionBuilder΁ͷظ଴
  2. FunctionBuilder @_functionBuilder struct CommandBuilder { public static func buildBlock<Content>(_ content:

    Content) -> String where Content: Command { content.body } public static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> String where T1: Command, T2: Command { [t1.body, t2.body] .joined(separator: "\n") } struct TupleCommand<T>ͷར༻͸ఘΊͨ protocol Command { var body: String { get } } struct AssemblyCommand: Command { var body: String init(@CommandBuilder builder: () -> String) { body = builder() } }
  3. ͜͏ॻ͚ΔΑ͏ʹͳΓ·ͨ͠ struct Add: Command { var body: String { AssemblyCommand

    { A.symbol(.sp) C.assign(destination: .am, computation: .mMinusOne) C.assign(destination: .d, computation: .m) C.assign(destination: .a, computation: .aMinusOne) C.assign(destination: .m, computation: .dPlusM) }.body } }
  4. ίϯύΠϧ࣌ & ৘ใ͚ͭͨ͠ struct Add: Command { var body: String

    { AssemblyCommand { () -> String in … ᶃ CommandBuilder.buildBlock( … ᶄ A.symbol(.sp), C.assign(destination: .am, computation: .mMinusOne), C.assign(destination: .d, computation: .m), C.assign(destination: .a, computation: .aMinusOne), C.assign(destination: .m, computation: .dPlusM)
 ) }.body } } @_functionBuilder struct CommandBuilder { public static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> String where T1: Command, T2: Command { [t1.body, t2.body] .joined(separator: "\n") } ᶃ ΫϩʔδϟͷฦΓ஋ ᶄ CommandBuilder
  5. Ϣʔεέʔε͕ҧͬͨ…ͳͥʁ SwiftUI͸ɺ։ൃऀ͕ࣗ༝ʹViewStackΛ૊ΊΔ struct MyGroupView : View { var category: String

    var categorizedItems: [Item] var body: some View { VStack(alignment: .leading, spacing: 10) { Text(category) .padding(.top, 10) .padding(.leading, 8) .background(Color.green) .cornerRadius(5) .padding(5) Group { ForEach(categorizedItems) { item in ListRow(item: item) } } } .padding(.bottom, 10) } }