Alright, since I'm taking the day off warp, let's do some #ocaml instead.

We'll build a #rust favorite: serde

So first things first, we'll want to define some intermediate representation, the serde.ml language.

Then we can make something that reads/writes to that from some specific format (json, toml, etc).

Then we can make something that transforms serde.ml into typed ml data.

Currently reading how the serde derived serialization works.

Okay, so this is what I've got so far.

Here's the serde.ml data model, more or less fitting the basic types you can build up (or that come with) #ocaml:

Now on its own it isn't very interesting, its just a small AST for data structures.

The magic is that this is really an ✨intermediate representation✨

A shared interface really, between the ser and de parts of serde.

So for the serialization use-case on one side, we have a tiny @@deriving that generates a function (like shown in the picture) that turns your data into this IR.

And on the other side we have modules that consume this IR and spit out other formats like JSON, s-expressions, TOML, KDL, XML, what have you.

I haven't sketched any of those yet enough to show a screenshot.

fml why did i choose metaquot. this is going to take a little bit. bear with me.

yeah, no. these meta-quotation libraries are unusable to me. I'll need tons more documentation and examples on how to do common things. I'm getting too spoiled by the amazing efforts in Rust to keep libraries well documented.

Going back to ast_builder.

ocaml i am so angry at you right now
seriously, at some point this is just smashing the keyboard until the types magically fit

so i got a deriver for serializers into the serde.ml language somewhat working, and this is already making it so much eaiser to test stuff -- viva la #metaprogramming!

#ocaml #rust #serde

(yes, i know this is outputting cursed ocaml right now, bear with me)

fork yes! its valid #ocaml now. i think.

it also derives:

* newtypes
* tuples
* variants (unit, tuple, and record ones)

and knows how to follow modules/etc

ok, will add support for records next

ofc you'd never see any of this code, its all generates for you, what you see is this:
oh no, what did i break now

friggin' brew. we're back on track. I wrote a sexpr serializer to iron out the serializer implementator interface, and it feels good!

(minus all the explicit first-class module signatures type escaping)

the important bits is that this is what you normally write as a user:

type t = { ... } [@@deriving serializer]

and then you can call

t |> serialize_t |> Serde_sexpr.to_string

wanna go to json? just change to Serde_json.to_string

maybe someone will finally implement a deriving(debug) with this!

but for authors of serializers, there's a few things that always get in the way:

1. error handling (esp. over collections)

2. mapping over the serde.ml data definition language

3. parametrizing over the kind of output you want to have (usually a string, but could be a buffer/channel that goes straight to stdout/disk/network)

all of those are provided by the Ser.Mapper interface, which is created at runtime based on the definition of the serializer you are using.

See this cursed module: https://github.com/ostera/serde.ml/blob/main/serde/ser.ml#L163-L185

serde.ml/ser.ml at main · ostera/serde.ml

Serialization framework for OCaml. Contribute to ostera/serde.ml development by creating an account on GitHub.

GitHub
GitHub - ostera/serde.ml: Serialization framework for OCaml

Serialization framework for OCaml. Contribute to ostera/serde.ml development by creating an account on GitHub.

GitHub

uuuuugh yojson why don't you have a clean clear exported ast WHY

folks, we need more _type-only_ packages. like we have for http type defs.

in any case, here we go: one line change and we got serialization to json.

sweet.

i heard you also liked xml