Important
Documentation and packaging ongoing. But feel free to try it out!
Well kid, have you ever wanted real compile-time features in C and C++ that are encoded in the original language and with full code visibility?
Running true C(++) code at compile time for C(++) programs; none of that string interpolation using an external templating language!
Have you ever wanted to unlock the ULTIMATE POWER, the secret of life and a way to save her?
Sorry mate, you are not assured the senate is going to be you, but there is not evidence to counter this future.
The principle is actually quite simple, but the whole process can be a bit convoluted, so I am going to spend few words on that.
The metac preprocessor takes your source code, and checks for special macros inside; if found, it adds extra functions at the end of your compile unit, one for each instance, and the original macros are replaced with function calls to those we just added.
This extended code gets compiled and linked into a dynamic library, so that your original code and functions are also made available at compile-time, not just those we generated.
Next, metac runs again against the original source, but this time linking the new dynamic library. This way, instead of adding new functions we run the associated code and paste its result right in place of the macros in the original source.
The final result is a modified version of our original source where all special macros have been replaced by text, without needing external languages or a custom templating languages: it is all C(++) from start to finish!
In practice, this process is a bit more convoluted when considering the action of the default C preprocessor and its interference with ours.
Our preprocessor operates before the C preprocessor can, preventing visibility of our meta code between different files (even if within the same compile unit), as includes are yet to be resolved.
Hence, metac should be applied on sources which have been previously processed into *.i files, or accept the many restrictions of not doing it.
To simplify this process further for most basic applications, metac has the option of generating a Makefile from a json configuration file, but you will probably want to ship your own wrapper of metac for the build system of choice.
There are a few special macros which are introduced by this preprocessor:
$evalrun whatever code is passed in there at compile-time and replace this macro with that.$emitpaste the string generated by the code run at compile-time and replace this macro with that.$exec_evalrun a program and replace this macro with its returned value in stdout.$exec_emitrun a program and paste the output on stdout replacing this macro.$if_comptimecode emitted only if running at compile time (no errors can be emitted).$comptime_onlycode emitted only if running at compile time.
This library tries to keep complexity as low as reasonable; most of the codegen utilities (like generating a structure from an array of fields, etc) are delegated to downstream libraries or your custom code.
More documentation and examples to come, for now there is a simple reference one in this repo.
make allThere is currently no automatic install, you will have to manually move libmetac.so, metac and headers into proper locations.
This is mostly because it is still alpha software and I don't want to make the process of messing up your PC too easy.
If you want to test it, remember to change some paths in the generated Makefile for the example, as it assumes metac is properly installed.
For reference check here.
For now, it is linux only; sorry mate!
It is likely going to work on generic unix systems, inluding MacOS, but that has not been tested.
The main issue is the exec features which would require quite a bit of rework in windows, and I don't even have a platform to try that out.
But PRs to make metac more portable would not be turned down.
The code for metac is released under the terms of AGPL3.0.
Its runtime libmetac.c is released under the terms of LGPL3.0.
Documentation, configuration files and anything else in this repo is released as CC0, basically do what you want with those files.
Basically, you are free to improve metac sharing alike, but any sourcecode which is being processed and generated stays your own.
The metac run-time library used during compile-time generation must be shared alike as well, but it is not viral and does not affect the state of your generated code.
Yes, a good chunk of the code in this repo is not "human-made", deal with it.
For context, I have a prompt describing this application, which I often use to benchmark LLMs and see how well they cope with some mildly complex CLI tools.
This was the very first time I got something usable within a small number of iterations, and since the initial idea sounded good in my head, I continued working on it myself.
Few iterations after that, and this is what I got!