jamescourtney / FlatSharp

Fast, idiomatic C# implementation of Flatbuffers
Apache License 2.0
511 stars 51 forks source link

F# support #29

Closed endeavour closed 4 years ago

endeavour commented 4 years ago

Would be fantastic to be able to generate F# code as well as C#. In particular, F# supports discriminated unions natively so the clunky FlatBufferUnion could be removed.

jamescourtney commented 4 years ago

Ignoring the discriminated union issue, what's to stop you from referencing a C# assembly from F#? That is -- why not just use C# to define your contracts and serializers, then invoke them from your F# code? I don't have any experience with F#, but my understanding is that these types of scenarios are supported.

endeavour commented 4 years ago

You're right, that is absolutely supported and it's what I'm using currently. The FlatBufferUnion thing just kind of bugs me :)

jamescourtney commented 4 years ago

Ah, okay. Makes more sense now. I played with unions for a few minutes. This F#:

type Shape =
    | Rectangle of width : float * length : float
    | Circle of radius : float
    | Prism of width : float * float * height : float

Decompiles into this pile of c#. It's almost 800 lines long!

That's not something that I'm eager to try and codegen. I have a few questions for you:

endeavour commented 4 years ago

I was more thinking of writing an alternative Flatsharp.Compiler project that generates .fs files instead of .cs, but it looks like it uses some Roslyn stuff so I guess this isn't (easily) possible?

endeavour commented 4 years ago

Another option might be to generate a .fs file containing a bunch of Active Patterns so that the C# type can be used with pattern matching in F#. I guess this wouldn't be quite as good as native DUs because the syntax would be a bit different it would lack exhaustiveness checking but it could be a quick win. If I get some time over the next few days I'll try and knock a prototype up.

jamescourtney commented 4 years ago

Feel free to give it a try :) I don't know enough F# to undertake anything like that at this time. However, it looks like the F# compiler is open source, so you may be able to do something analogous to what I'm doing with Roslyn. The flow right now for CodeGening FBS files is a two-pass process:

Pass 1: Use Antlr to parse the .fbs file and generate C# contracts with FlatSharp attributes. This just creates class definitions for tables and structs, but no serializers or rpc definitions.

Pass 2 (necessary when fbs file calls for a precompiled serializer or gRPC stuff): Take the C# from pass 1 (data contracts), and compile an in-memory assembly with it. Then pipe that through FlatSharp to generate serializers just like you would as if you defined your contracts in C#. Take the resulting C# serializer code, merge it with the C# contracts we just generated, and dump it to the output file.

While it's a little convoluted, the advantage is I only have to write each part of the CodeGen once. The only thing the .FBS files really do is generate contracts. The serializer code still comes from the same place.

jamescourtney commented 4 years ago

Closing due to inactivity