Skip to content

Macro #51

@bloderxd

Description

@bloderxd

Macro

This is a proposal to implement a function that intercepts and apply effects in different parts of the compilation.

Motivation

Since K2 release Kotlin stabilized FIR and IR APIs so developers apply metaprogramming with compiler plugins. There're some considerations a developer should have in mind when create a compiler plugin: A basic knowledge about compilers and Kotlin compiler is necessary, compiler plugins documentation in general is poor, a good amount of code is necessary to apply simple checks or transformations in FIR / IR.

Macro functions

The proposal to mitigate these considerations is provide a function that intercepts parts of the compilation and provides a way to developers apply effects on it. Macros are declared using the annotation @Macro:

private val FOO by diagnosticError()

@Macro
fun MacroContext.foo(klass: FirClass): MacroCompilation {
  return diagnostics {
    if (klass.nameOrSpecialName.identifier == "Foo") {
      klass.report(FOO, "A class cannot be called Foo")
    }
  }
}

class Foo // Compile time error: A class cannot be called Foo

In Kotlin most of metaprogramming related solutions uses annotations as an entry point to some compile time logic, so macros support that natively:

annotation class Warning

private val WarningReport by diagnosticWarning()

@Macro(target = Warning::class)
fun MacroContext.foo(klass: FirClass): MacroCompilation {
  return diagnostics {
    klass.report(WarningReport, "A sample warning message")
  }
}

@Warning
class Foo // Compile time warning: A sample warning message

Conventions

To create a macro, the function structure should follow some conventions:

  • The function should be annotated with @Macro annotation
  • The first parameter or context should be a MacroContext
  • The second parameter should be a FIR or IR element
  • The return type should be a MacroCompilation

A macro will be created to verify those and alert developers if it breaks some convention

Macro annotation

This is the entry point to let arrow-reflection internals scans macro functions before FIR / IR extension registrations.

MacroContext

A type responsible to build a MacroCompilation type. diagnostics {} is an example of function provided by this type which creates a diagnostic macro compilation type.

MacroCompilation

This type is responsible to wrap some kind of effect that will be done during the compilation phase, because of this wrapping we can have a better control in how and what order this effect is applied. DiagnosticsCompilation is one example of effect we can apply during the compilation.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions