“Blocks of code” is a leaky, untyped abstraction. It’s better to have something like a DOM API for the target language, where each node in the parse tree is represented as a typed object with properties and children. (For example, if you’re generating C, an #include directive would be represented as a typed object that’s part of a larger object.) Then you can use the same API to generate, analyze, or transform code. It looks like overkill in toy examples, but can be impressively concise in longer examples.
Long ago, I worked on a Java IDE that effectively worked this way. Our captive compiler did some basic error correction on the source (so it kept working even while typing), then generated an annotated https://en.wikipedia.org/wiki/Abstract_syntax_tree, which the visual elements could read to generate their displays. The cool aspect of code generation is that our tools could also update the tree, and the code generator would insert/delete/refactor the code to match.
“Blocks of code” is a leaky, untyped abstraction. It’s better to have something like a DOM API for the target language, where each node in the parse tree is represented as a typed object with properties and children. (For example, if you’re generating C, an #include directive would be represented as a typed object that’s part of a larger object.) Then you can use the same API to generate, analyze, or transform code. It looks like overkill in toy examples, but can be impressively concise in longer examples.
Long ago, I worked on a Java IDE that effectively worked this way. Our captive compiler did some basic error correction on the source (so it kept working even while typing), then generated an annotated https://en.wikipedia.org/wiki/Abstract_syntax_tree, which the visual elements could read to generate their displays. The cool aspect of code generation is that our tools could also update the tree, and the code generator would insert/delete/refactor the code to match.