patefacio

patefacio

Elixir for targeting code generation?

I have a setup for code generation that I love, but is now moribund. I will describe the aspects that are great and I would like to know what elixir might offer for solving this problem.

My current solution uses the Dart programming language. With dart there are now a few implementations of the language - one for web, one for flutter and another vm for console work. My stuff is all console vm. I say my setup is moribund because all my code is written in Dart 1 and the recent move to Dart 2 has killed it for me. While the language is still awesome IMHO, my m.o. for using it no longer works because version two of the language moved to an ahead of time compilation approach.

I made a decision early on to model items I want to generate code for in the Dart language itself - rather than in json, xml or some data language. My thinking was so often I want to transform models that it did not make sense to even deal with json to dart every time I want to make a change. Plus, by modeling my data in the language I get the intellisense. So, if I’m targeting c++ I model classes, templates, members, statics, consts etc and then at a higher levels of abstraction implementation files, header files, build scripts - etc. The libraries supporting those models, once written don’t change too frequently. The issue with Dart 2 is startup time went from under 1 second to over 8 seconds which killed the workflow. So prior to 2 I could generate 20 files in less than a couple seconds and now its over 10 seconds. Similar issue for testing. The language has support for snapshots which is great for scripts run repeatedly, but does not help my situation because I create my models in the language directly and therefore every change is a “recompile”. Currently there is no real support for “incremental” compilation with the snapshots (e.g. no way to just compile the one script that has changed and patch it in to preexisting snapshot(s)).

Some features I love in current (Dart 1) setup is:

  • Fast turnaround since language was in scripting space - make change, save and less than two seconds all files updated
  • Great support for string interpolation “class ${className} …”. I’ve used template libraries in other languages and I’m ok with them but have no strong attraction to them and don’t mind piecing together all text in code. String interpolation makes it easy.
  • They have this nice syntax called cascades that turns any set of chained method calls into a kind of fluid API automatically. So - a small sample:
        class_('change_tracker')
        ..descr = '''
  Tracks current/previous values of the given type of data. For some
  algorithms it is useful to be able to examine/perform logic on
  current value and compare or evalutate how it has changed since
  previous value.'''
        ..template = [ 'typename T' ]
        ..customBlocks = [clsPublic]
        ..members = [
          member('current')..type = 'T'..access = ro,
          member('previous')..type = 'T'..access = ro,
        ],
  • Excellent libraries for xml, json, yaml etc. One use case is to read xml from protocol schema definitions and generate library support.
  • Excellent error identification (type related) from the IDE before even running the code.

So, I don’t know much about elixir yet and am willing to learn new paradigms if they are good for this problem. What are your thoughts on elixir for this problem?

Most Liked

easco

easco

Elixir is a compiled language. Once you have downloaded dependencies it can take a while to compile everything the first time. Once you’ve got the thing built, however, updates happen fairly quickly.

I spend a lot of time with applications in the Elixir REPL, iex where I will make a small change to a file, reload the module in the REPL and try the change out there.

In Elixir, your string interpolation would probably look like like “class #{class_name}”

The built in templating in Elixir comes from the EEx module. The nice thing about EEx is that it takes the template and compiles it into a function (into executable code) so running the template is fast.

Never having seen Dart before I’m not sure what this code snippet means – what you are trying to demonstrate with it.

I know from first hand experience that Elixir parses JSON well. I’ve not used XML or Yaml from Elixir. You might look here: GitHub - h4cc/awesome-elixir: A curated list of amazingly awesome Elixir and Erlang libraries, resources and shiny things. Updates: · GitHub and GitHub - h4cc/awesome-elixir: A curated list of amazingly awesome Elixir and Erlang libraries, resources and shiny things. Updates: · GitHub

Elixir is a dynamically typed language. There is support from a tool called Dialyzer to help type-check your code, but you have to run that tool as a separate step. Given your remarks about your desired turnaround time on code changes, I suspect you would find those unsatisfactory.

blatyo

blatyo

Conduit Core Team

Elixir has code generation built into the language in the form of macros. Elixir supports incremental builds as well. Also, if you do want to pull in a file to generate code, macros can be used for that and you can signal to the elixir compiler that you’re doing so, so that it knows to recompile when that file changes. Pipes (|>) are used for fluid API’s in elixir, but you likely won’t need them if you want to build a DSL.

Dart probably has stricter typing than Elixir. You can use Dialyzer in elixir, but it uses success typing.

sribe

sribe

Sensitive readers should look away now and read no further:

#pragma once

#include "<%= fileBaseName %>_Row_fwd.h"
<% baseMetas.each do |m| %>
#include "<%= m.fileBaseName %>_Row.h"
<% end %>
#include "Buffer_fwd.h"
#include "Model.h"

#define RowIncludeHeaders 1
#include "<%= fileBaseName %>_Row_adds.h"
#undef RowIncludeHeaders


<%= openNameSpaceStr %>

using namespace DbApp::Model; using DbApp::NullValReader; using DbApp::NullValWriter; using DbApp::Buffer;


#define RowIncludeDefs 1
#include "<%= fileBaseName %>_Row_adds.h"
#undef RowIncludeDefs


#if IsClientBuild
int32_t	ReadFromResult( Buffer * dbr, RowBaseVec * v );
int32_t	ReadFromResult( Buffer * dbr, RowVecT * v );
int32_t	ReadFromResult( Buffer * dbr );
#endif

#pragma mark Meta

enum PropIdE {
	<%= fields[0].constantName %> = 0, 
<% fieldsTail.each do |f| %>
	<%= f.constantName %>, 
<% end %>
	kNumFields
};

...

Yes, that’s embedded Ruby, embedded in C++ :wink:

sribe

sribe

The Elixir tools in VS Code run it automatically on file save, so its results are always available, basically instantly, in the same panel as compiler errors & warnings.

sribe

sribe

Elixir would be approximately equal to Ruby in terms of convenience for this task, but would execute much faster. That’s assuming keeping the source defs in YAML files as I do now, if you were really ambitious you could use macros to put together a DSL…

Where Next?

Popular in Discussions Top

chuck
Let me start by stating an assumption: Phoenix is a great approach to building REST APIs. There are many reasons for this, but I will ass...
New
pillaiindu
I want to convert a Phoenix LiveView CRUD website to a CRUD mobile app. What do you think is the easiest way to do so?
New
ricklove
I was just introduced to Elixir and Phoenix. I was told about the 2 million websocket test that was done 2 years ago. From my research, t...
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 19568 166
New
sergio
There’s a new TIOBE index report that came out that shows Elixir is still not in the top 50 used languages. It also goes on to call Elix...
New
restack_oslo
Hello, Please pardon me for any faux paux. I am 46 and this is my first time on a forum of any kind. I wanted to to get answers from tho...
New
jsonify
So, is Heroku the only free option for hosting Phoenix/Elixir at this point? I’m not ready to commit to paying monthly and was wondering ...
New
tomekowal
Hey guys! I want to create a toy project that shows a chart of temperature over time and updates every 5 seconds. I feel LiveView is per...
New
joeerl
I’m playing with Elixir - It’s fun. I think @rvirding does give Elixir courses these days. Re: files and database - when I given Erlang ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Other popular topics Top

skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

We're in Beta

About us Mission Statement