jgleoj23
jgleoj23

Reputation: 262

How can I write a code generator in Ceylon

I want to write a code generator that generates a class based on the meta model of another ceylon class. I want the code generator to run at compile time. What is the best way for me to do this. I could probably accomplish this by writing a plugin for gradle or the ceylon build system but I'm hoping for a simpler solution. Unfortunately, I don't see any support for code generators in ceylon. Also, are there any plans for code generators in ceylon?

I want to write this code generator because I'm thinking about writing a simple web framework for ceylon that look at a class like the following using the meta-model: controller

shared class Controller() {
    shared void doSomething() => print("did it!");
}

I plan for it to be like Spring MVC. This framework would make a restful API from the Controller class that allows someone to write an AJAX call like this:

$http.get("/Controller/doSomething");

I want to make things more convenient, high level, and simple by doing something like GWT. I want to create a code generator that automatically generates a class like this:

shared class RemoteController() {
    shared void doSomething() {
        $http.get("/Controller/doSomething");
    }
}

The RemoteController would be run in a user's browser as javaScript and allow client side ceylon code to do an Ajax call like this:

RemoteController().doSomething();

That would end up calling the Controller().doSomething() on the server so "did it!" would be printed.

Upvotes: 1

Views: 124

Answers (1)

Lucas Werkmeister
Lucas Werkmeister

Reputation: 2742

AST Transformers have been proposed, but are still in the early design phase. For now, to do compile-time code generation, you’ll have to rig up something of your own.

To actually generate the code, I would recommend use of ceylon.ast and ceylon.formatter. The workflow would roughly be:

  1. analyze source code –
    • either parse it with ceylon.ast (ceylon.ast.redhat::compileAnyCompilationUnit) and analyze it without typechecking,
    • or parse it using the compiler, run the typechecker, then convert it to ceylon.ast (ceylon.ast.redhat::anyCompilationUnitToCeylon), keeping the typechecker information using the new update hooks in the very soon upcoming 1.2.0 release
  2. edit the source code AST to add your new code (using a custom ceylon.ast.core::Editor that injects new class definitions into the CompilationUnits), or perhaps create entirely new compilation units if the RemoteController lives in a different module
  3. convert the ceylon.ast AST to a compiler AST and feed it into ceylon.formatter to turn the AST into code again (see here for an example of that)

Alternatively, if you integrate this into your build step, you could skip the ceylon.formatter part of step 3 and instead feed the converted compiler AST into the typechecker and rest of the compiler directly.

Upvotes: 4

Related Questions