我如何在 Ceylon 中编写代码生成器

How can I write a code generator in Ceylon

我想编写一个代码生成器,根据另一个锡兰 class 的元模型生成一个 class。我希望代码生成器在编译时 运行。对我来说最好的方法是什么。我可能可以通过为 gradle 或锡兰构建系统编写一个插件来实现这一点,但我希望有一个更简单的解决方案。不幸的是,我在锡兰没有看到任何对代码生成器的支持。另外,锡兰有代码生成器的计划吗?

我想编写这个代码生成器,因为我正在考虑为 Ceylon 编写一个简单的 Web 框架,它使用元模型查看 class 如下所示: 控制器

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

我打算让它像 Spring MVC。该框架将从控制器 class 生成一个 restful API,允许某人像这样编写一个 AJAX 调用:

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

我想通过 GWT 之类的东西让事情变得更方便、更高级、更简单。我想创建一个自动生成 class 的代码生成器,如下所示:

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

RemoteController 在用户浏览器中将 运行 作为 javaScript 并允许客户端 Ceylon 代码执行这样的 Ajax 调用:

RemoteController().doSomething();

这最终会在服务器上调用 Controller().doSomething() 以便打印 "did it!"。

AST Transformers已被提出,但仍处于早期设计阶段。现在,要进行编译时代码生成,您必须自己组装一些东西。

要实际生成代码,我建议使用 ceylon.ast and ceylon.formatter。工作流程大致是:

  1. 分析源代码 –
    • 要么用 ceylon.ast (ceylon.ast.redhat::compileAnyCompilationUnit) 解析它,然后在不进行类型检查的情况下分析它,
    • 或使用编译器解析它,运行类型检查器,然后将其转换为ceylon.astceylon.ast.redhat::anyCompilationUnitToCeylon),使用新的update hooks保留类型检查器信息即将发布的 1.2.0 版本
  2. 编辑源代码 AST 以添加新代码(使用将新的 class 定义注入 CompilationUnit 的自定义 ceylon.ast.core::Editor),或者创建全新的编译单元如果 RemoteController 住在不同的模块中
  3. ceylon.ast AST 转换为编译器 AST 并将其输入 ceylon.formatter 以再次将 AST 转换为代码(参见 here 的示例)

或者,如果将其集成到构建步骤中,则可以跳过步骤 3 的 ceylon.formatter 部分,而是将转换后的编译器 AST 直接输入类型检查器和编译器的其余部分。