Skip to content

Instantly share code, notes, and snippets.

@lucaswerkmeister
Created April 24, 2014 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucaswerkmeister/11257094 to your computer and use it in GitHub Desktop.
Save lucaswerkmeister/11257094 to your computer and use it in GitHub Desktop.

Goals

Create a ceylon.ast module

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.

Use that module in the ceylon.formatter

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.

Benefits

  • 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment