adl icon indicating copy to clipboard operation
adl copied to clipboard

Customizable code generation

Open bitc opened this issue 3 years ago • 4 comments

This is probably most relevant for the Haskell generator, but maybe could be interesting for other languages.

In Haskell there are many different styles for defining records:

  • Prefixed or non-prefixed field names. Example: personName, personAge vs name, age. Some teams prefer a 3rd alternative: person_name, person_age. The non-prefixed alternative usually requires the OverloadedRecordFields extension.

  • Various typeclass instances should be derived. Most people always want (Show, Eq, Ord). But some teams also will always want additional instances for things like Read or Hashable or Binary. Each team will have their own preference and standards.

  • Support for lenses / optics / others. Each team has there own way of doing this, some using generic-lens, some use generic-lens-labels, others use generic-optics or generic-optics-lite, etc... In the future there will be new alternatives...

  • Strict fields or not (Related to #97)

I think it would be too cumbersome to try to make ADL natively support all of these different styles (whether through command line flags or ADL annotations). And people would always come up with their own personal use case that isn't supported.

I think a better approach would be some kind of plugin-system, where users would be able to write their own custom code that would generate the Haskell source files.

For me personally, it is crucial that the ADL generated code will use non-prefixed record names, and will have support for lens/optics (depending on the project). But I know that everyone will have their own preference, which is why I propose this idea to allow customization.

Thank you

bitc avatar Jul 20 '20 14:07 bitc

There is already some support for "plugin" or custom code generators:

One runs adlc in ast mode, and after parsing and checking the adl source, a single json file is written containing the ast. The json has adl type StringMap<sys.adlast.Module>. Then, a custom code generator written in any of ADL's target languages can be used to generate arbitrary code from the typed ADL AST.

This approach has been used for a variety of purposes - eg we use it for generating sql schemas from adl definitions.

Having said that, it's quite an undertaking to implement from scratch a generator for a language like haskell that supports all ADL features.

I'm wondering what a plugin customization approach would look like (as you suggest). It seems to sit somewhere between "writing a new generator from scratch" as above, and a growing list of annotations on the existing generator.

timbod7 avatar Jul 20 '20 23:07 timbod7

Note that your first customization on prefixed fields is already handled with the existing HaskellFieldPrefix annotation.

And the need for optics generation is raised here: https://github.com/timbod7/adl/issues/58

timbod7 avatar Jul 20 '20 23:07 timbod7

I suppose that it is possible that annotations could work for most of this stuff (ADL's annotation merging feature is very useful here!).

But I am a bit worried that for most of these things, you want to make the decision once on the project level, and not have to copy-paste the same annotations onto every single ADL declaration that you write.

For me personally, optics are very important, I will be following #58 :+1:

Thank you

bitc avatar Jul 21 '20 13:07 bitc

not have to copy-paste the same annotations onto every single ADL declaration that you write.

The interpretation of annotations is up to the various language backends. But where appropriate, annotations can be applied at the module level, to affect all declarations in that module.

timbod7 avatar Jul 22 '20 13:07 timbod7