I want to encode/decode an AST in Golang but am running up against a roadblock with the lack of sumtypes.
A very trivial AST to demonstrate the problem:
data BoolAST = Or BoolAST BoolAST | And BoolAST BoolAST | Lit Bool
Approach 1
type BoolStatement interface {
ComputeBool() bool
Serialize() []byte
}
type Or struct {
Left BoolStatement
Right BoolStatement
}
type And struct {
Left BoolStatement
Right BoolStatement
}
type BoolFunc struct {
Value bool
}
Now this structure serializes very well, But what I am having trouble with is deserializing (msgpack, json, etc). So You would have to wrap the interface in a struct so you can add a deserializer method. This to me also seems sloppy as I dont want to have to hand craft a serializer
Approach 2
To solve this I changed my struct a little bit. Everything is the same struct, but only one field is populated at a time. This code makes deserialization a breeze.
type BoolAST struct {
Or []BoolAST
And []BoolAST
Lit bool
}
This works well to deserialize because empty fields are left nil, but then I have these empty fields. When interpreting the AST I have to use switch statements to find what field is null and that adds a tiny bit of overhead.
This also makes the json nice:
{
"and": [
{"lit": true},
{"or": [
{"lit": false},
{"lit": true}}
]
]
}
But this can get crazy when the ast has many types of branching paths. You might end up with 10 nil fields on the struct.
It seems very hard with no sum types to solve this problem. Is this the right approach?