This will allow to use Ceylon’s named arguments to create a Ceylon AST. For example:
value actions = {
"greet"->"Hello, World!",
"offerHelp"->"How can I help you?",
"bye"->"Goodbye!",
// ...
"praise"->"Ceylon is great!"
};
value printerMethods = CompilationUnit {
for (action in actions)
MethodDefinition {
name = action.key;
Block {
InvocationExpression {
primary = "print";
PositionalArgumentList {
StringLiteral(action.value)
}
}
}
}
};
Here, we create 4+ functions that all behave exactly the same, differing only in their name and their output. Without code generation, you would have to copy and paste the entire function each time you wanted to add one; with code generation, it’s a simple matter of adding one line.
This example is, of course, fairly simple, and doesn’t yet benefit much from use of code generation. For a real-world use case, see the next section.
Constructing an AST can be tedious for more complex instructions. Two techniques will mediate this:
- “sugar” parameters (for example, you’ll usually be able to use name instead of Identifier(name))
- functions that parse a given string into a certain AST element; these functions will use the Ceylon compiler as backend.
In my ceylon.formatter, I already generate code for the options. I have the following classes and functions:
- SparseFormattingOptions, where all attributes have an optional type
- FormattingOptions, where they have their normal type
- CombinedOptions, which searches other options for an option value
- VariableOptions, an internal class that declares its attributes variable
- parseFormattingOptions, which parses key->value pairs to options
The options with their documentation, type, name and default value are defined in one 300 line file (most of which is documentation), from which a 1000 line file and several smaller “auxiliary” files are then generated.
However, this code generation is currently entirely string-based, which is ugly. Instead, it will be rewritten to use the ceylon.ast module to construct the code, and then the ceylon.formatter to write it to a file.
- Dynamically generating code is useful in general
- As the ceylon.ast module is not generated code, it can contain extensive documentation, which the AST is sorely lacking at the moment
- This could be a nice showcase of Ceylon’s named arguments, similar to the ceylon.html module
- Stéphane Épardaud suggested that this could be used for macro support in the language (although this isn’t in the scope of this proposal)