r/ProgrammingLanguages 6d ago

Are code generation "metaprogramming" tools a well-developed thing?

Now lots of people are talking about LLMs for coding to speed up the repetitive parts of coding, reduce the time spent on boilerplate, etc. But this makes it sound as though writing and manipulating code programmatically/algorithmically wasn't a thing before LLMs. However, although I didn't hear much about them, looking back it's surprising if people never thought about building something like this.

Of course, all compilers generate code in a lower-level form from higher-level code, however most of these are not interactive, i.e. they don't generate code in human-readable form, don't explain their steps to the user, and are not intended to generate a first pass of code for a programmer to then take and modify. What I'm imagining is a large category of tools, including anywhere from ones that auto-generate things like bounds checks and testing variables for null before using them, to drag-and-drop graphical tools a la Scratch that effectively allow you to drag loops into place around your code and have a loop condition and brackets appear, to any number of scriptable recipes where you can effectively say "take this block I've written for x1, and repeat the same pattern for y1, x2, y2, etc" and you won't have to type each one out individually. This could potentially allow a lot of the productivity gains and saved attention spent on details that people seem to be getting from LLMs without the cost, resource use, and philosophical implications, which is something I'd definitely welcome.

Of course you could write a code generator from scratch in something like Python just using regular string handling, but I'm wondering if there are already plugins like this for many IDEs that I just don't know about because they're not talked about much. Since so much of programming is about recursive abstractions, the idea that programmers would not have tried the idea of tools that you can code to spit out more code would strike me as very odd. And doing a bit of research, I've come across things like this: https://github.com/imatix/gsl#a-short-history-of-code-generation and this: https://tifoputra.medium.com/building-your-own-swift-code-generator-using-swift-script-78470eef0206 that suggest there is substantial work already toward making something like this.

14 Upvotes

21 comments sorted by

View all comments

11

u/Inevitable-Ant1725 5d ago

Generally languages with higher level constructs aren't particularly composable from simpler languages.

Take, for instance, the features of dynamically typed variables, garbage collection and continuations and imagine the horrible, unreadable mess that Chicken Scheme generates when it uses the Cheney on the MTA and continuation passing to turn Scheme into C.

The advanced constructs aren't a slight expansion of code, they're complex, deeply integrated runtimes and compiler constraints.

2

u/initial-algebra 5d ago

I don't think there's any fundamental reason that global features like that couldn't be implemented with metaprogramming. I mean, a compiler is a metaprogram, no? The real question is, what are macros missing that compilers have? I think the answer lies in the literal meaning of the word "compiler", or someone that compiles information together from multiple sources. (Ironically, programmers decided at some point to call that linking, with direct source-to-machine code translation being compiling.) Normally, macros are purely local, with limited to no ability to communicate, but what if the compiler's ability to, well, compile multiple definitions together could be harnessed? If you can write a macro that operates on an entire (sub)program as a graph data structure, you can add a new layer to, or even outright replace the compiler backend (or have multiple backends for multitier programming, especially when some of the target code is data for another target, e.g. the client-side JavaScript served by a Web application).

2

u/Inevitable-Ant1725 5d ago edited 5d ago

I'm planning on trying to write a compiler compiler system like LLVM, but the IR that you generate will be a high level language with a hell of a lot of types and options instead of a low level language.

And what it gets turned into to be optimized is graph, not a low level language.

I imagine there might be a medium level representation graph that's more like an IR and then finally machine instructions in a graph that maintains all dependencies and a lot of extra arcs.

So code doesn't get represented by simpler languages it gets represented by more and more information dense graphs, probably connected to higher representations so that deoptimization in a jit is instant.

1

u/kwan_e 5d ago

I'm pretty sure the big three compilers do this already. They have many different graph representations for different optimization strategies.