📜 ⬆️ ⬇️

Haskell Code Generator

Some time ago I decided to experiment with Haskell microservices. The project architecture involves the creation of a large number of micro-projects, each of which is responsible for one small volume of tasks. After some time, I was bored with creating these projects manually, as well as writing template code for each entity from the database. To solve this problem, I developed a small utility that allows you to generate template code. Under the cut - more.


image In principle, the code generators around are a dime a dozen, but they are all specific and, as a rule, are designed for one particular language or even a project in that language. Of course, looking at how easy it is to generate code for entities, for example, in Ruby on Rails, you begin to really envy the rubists. Among the Haskell packages, I found only two more or less worthwhile code generator: Hi and Haskeleton .

Hi is able to generate the code of the whole project, which is very cool. But this little spoon of honey is generously diluted with a barrel of tar. In order to generate the project code, you need to pass the Hi link to the URL of the project template that you still need to find somewhere. Each time, Hi will download the templates from this link, instead of downloading the downloaded ones. Hi supports only a few variables for substitution: package-name, moduleName, author, email, and this is a complete file.
')
Haskeleton is a fancy design pattern for Hi, very well thought out . It even incorporates the Haskeleton.hs utility, which allows you to create empty modules and insert imports of these modules into all suitable places. However, empty modules are not what I need.

The requirements that I imposed on the code generator were the following:


Based on these requirements and the availability of ready-made Haskell libraries, I chose the hastache package for Mustache's template code, as well as aeson, so that the parameters to the template can be transferred in JSON format.

The local template repository is located in the ~ / .trurl / repo directory, where all the templates of entities and projects downloaded from the global repository are added. The project template is a tarball. An entity template is just a file. For example, suppose there is a file myentity.hs with the following template code:

data {{entityName}} = {{entityName}}{{#props}} {{type}}{{/props}} insert{{entityName}} :: Pool Connection -> Maybe {{entityName}} -> ActionT Text IO () insert{{entityName}} _ Nothing = return () insert{{entityName}} pool (Just ({{entityName}} _{{#props}} {{name}}{{/props}})) = do liftIO $ execSqlT pool [{{#props}}(show {{name}}){{^last}}, {{/last}}{{/props}}] "INSERT INTO {{entityName}}({{#props}}{{name}}{{^last}}, {{/last}}{{/props}}) VALUES({{#props}}?{{^last}},{{/last}}{{/props}})" return () 

Run the trurl with the following parameters:

trurl new Article myentity '{"entityName": "Article", "props": [{"name": "title", "type": "String"}, {"name": "body", "type": "String"}, {"name": "year", "type": "Integer", "last": true}]} '

As a result, we get the following code:

 data Article = Article String String Integer insertArticle :: Pool Connection -> Maybe Article -> ActionT Text IO () insertArticle _ Nothing = return () insertArticle pool (Just (Article _ title body year)) = do liftIO $ execSqlT pool [(show title), (show body), (show year)] "INSERT INTO Article(title, body, year) VALUES(?,?,?)" return () 

Similarly, you can generate and template projects using the create command. The truth here is to follow the following rules:


In order to download all available templates from the global repository, you must run the command "trurl update".

Using the “trurl list” command you can get a list of all available templates.

The "trurl help [template]" command will show a hint on how to use the specified template.

The "trurl new [newfilename] [file_template] [json_params]" command is designed to generate exactly one file.

The "trurl create [newprojname] [project_template] <json_params>" command is intended to generate a whole project, JSON parameters are not required here.

Currently, only a few templates are available for trurl in the global repository. These are templates for my micro services (scotty-mysql and scotty entity), and haskeleton, which I added at the request of one of the users of the trurl. You can create your templates, just send me a pull-request at github.com/dbushenko/trurl/tree/master/devrepo , and I will add them to the master repository.

The trurl project is young and therefore not without flaws. It is not always convenient to transfer long JSON strings to generate entities, not any template can be generated using mustache, the main template repository is not very conveniently arranged. All of these are directions for improvements that I actively pursue and will be glad if others join me.

And the last. I chose the name trurl in honor of the space designer Trurl from the works of Stanislav Lem "The seven journeys of Truer and Klapautsiya", it was you who saw the portrait of Trurl at the beginning of the article.

Source: https://habr.com/ru/post/260239/


All Articles