Xamarin.SwiftUI icon indicating copy to clipboard operation
Xamarin.SwiftUI copied to clipboard

Generate bindings automatically from swiftinterface

Open chkn opened this issue 5 years ago • 11 comments

We are reaching a point where we've bound enough APIs by hand to have mostly figured out the design. Now it's mostly a matter of repeating those boilerplate patterns for every SwiftUI view, protocol, etc. We should automate this with a binding generator.

The Swift equivalent of a header file is the swiftinterface file. For the Mac version of SwiftUI we can find this at:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/x86_64-apple-macos.swiftinterface

This file is a subset of Swift syntax that we can parse. Swift has good documentation on its syntax and grammar.

  • [x] Parse the swiftinterface file into an AST. ~~I've already started a parser using the FParsec library that might be useful: https://github.com/chkn/Xamarin.SwiftUI/compare/swift-parser~~ We are moving to use SwiftSyntax to do the parsing instead: https://github.com/chkn/Xamarin.SwiftUI/compare/swift-parser2
  • [ ] Walk the AST to generate our bindings

Those are pretty large tasks, so we should probably split them into separate PRs.

chkn avatar Jun 06 '20 07:06 chkn

Is the iOS sdk different?

7sharp9 avatar Jun 08 '20 10:06 7sharp9

Yeah unfortunately SwiftUI exposes a slightly different API surface on each platform (macOS, iOS, tvOS, watchOS). In my limited experience with it so far, I think the differences are fairly minor, but this tool would let us parse the APIs into an AST that we can diff and see exactly what the situation is.

chkn avatar Jun 09 '20 05:06 chkn

Did Frank make a parser for swift at one time?

7sharp9 avatar Jun 11 '20 23:06 7sharp9

Yep I believe so, but I think it was many years ago and I'm not sure how complete it was. @praeclarum 👋

chkn avatar Jun 12 '20 00:06 chkn

I've written two parsers in fact :-) But that was Swift 1.0 and a lot has changed since then. It's not an LR(1) language so you'll need to use a powerful GLR or PEG to get through it (I'm guessing Apple hand-wrote the parser since this is a Lattner joint).

For SwiftUI, I took a different approach and parsed their interface definitions baked into the libs. That approach was working well, but I got bored of it.

Edit: The interfaces declarations are much easier to parse so I would still recommend machine parsing those to make sure you're getting 100% API coverage.

praeclarum avatar Jun 12 '20 18:06 praeclarum

We are not all brain boxes like you @praeclarum :-)

I would like to see if F# could have a sane interface into SwiftUI, it is quite hard mapping it over to a CE though. Theres about 50 View implementations and default protocols for all the .font(...) settings etc

7sharp9 avatar Jun 12 '20 19:06 7sharp9

I mean Im not averse to getting the C# ones nice too. @chkn Does your source generator deal with nesting and calling the view protocol functions fluently etc?

7sharp9 avatar Jun 12 '20 19:06 7sharp9

For SwiftUI, I took a different approach and parsed their interface definitions baked into the libs.

@praeclarum Oh wow I didn't know you've done SwiftUI stuff! By "interface definitions baked into the libs," do you mean like the type metadata, type descriptors, etc in the symbol table? There is a ton of info there and it's almost enough. But the textual swiftinterface files have a few things like attributes that we need, and so far I'm really digging this FParsec parser.. https://github.com/chkn/Xamarin.SwiftUI/blob/swift-parser/src/Swift.Parser/SwiftParser.fs

I mean Im not averse to getting the C# ones nice too. @chkn Does your source generator deal with nesting and calling the view protocol functions fluently etc?

@7sharp9 Nope I don't think the C# source generator would deal with nesting, now that you mention it. But just to make sure there's no confusion, the C# source generator only deals with the ViewBuilder transform that we're talking about on #24, it doesn't generate bindings (what this issue is about). But if you want to take a look at that, the nugets should pull in the version of roslyn you need automatically.

I would like to see if F# could have a sane interface into SwiftUI, it is quite hard mapping it over to a CE though. Theres about 50 View implementations and default protocols for all the .font(...) settings etc

Yeah this is why I want to write this parser to generate all those bindings automatically. We just need to figure out a template for a CE (or something else--if there's a better solution I'm happy exploring it.. it just seemed like a CE was conceptually the closest to what Swift is doing)

chkn avatar Jun 13 '20 02:06 chkn

@chkn There was talk of a similar API here too: https://github.com/fsprojects/Fabulous/issues/738#issuecomment-626395314

What about supporting SwiftUI from the aspect of using lists etc, even if it did mean a code generator that would be possible using Myriad to generate the API calls with all the generic parameters etc.

7sharp9 avatar Jun 16 '20 11:06 7sharp9

@7sharp9 I've been a bit on the fence. I still think CEs are a good choice for a couple reasons:

  1. The syntax and semantics match the Swift version more closely
  2. It's a built in language feature that would expose the strongly-typed view hierarchy without any post processing

That said, if the list syntax is more familiar/productive for people who are already familiar with Fabulous/Elmish/etc, then perhaps it is worth investigating. I've always wanted to ultimately expose an elmish-style API for SwiftUI, so perhaps we can start thinking about that now. Do you have some ideas on how it might look?

chkn avatar Jun 19 '20 01:06 chkn

Although writing our own parser has been a fun experiment, it turns out there's already a nice Swift library that can parse the swiftinterface files. I've started working on a code generator using that, and it's already stubbing type signatures for views and shapes: https://github.com/chkn/Xamarin.SwiftUI/compare/swift-parser2

chkn avatar Jul 25 '20 06:07 chkn