Skip to content

Redux

Redux

The :tools:redux module is a pluggable AST-to-AST transformation framework. It runs a pipeline of Transformers over JavaParser nodes, rewriting the tree step by step — the foundation for desugaring, feature reduction and code generation. Each transformer is either wired in programmatically or discovered via ServiceLoader and toggled through a ReduxConfig.

Usage

val config = ReduxConfig()
config.disable(AddForeachCountVariable::class.java)   // opt out per transformer
val facade = ReduxFacade.create(config)               // load enabled transformers

val rewritten: List<Node?> = facade.apply(listOf(cu))

ReduxFacade applies every enabled transformer in sequence to each node, so later transformers see the output of earlier ones:

class ReduxFacade(private val config: ReduxConfig) {
    fun apply(nodes: List<Node>): List<Node?>
    companion object { fun create(config: ReduxConfig): ReduxFacade } // ServiceLoader
}

Built-in transformers

TransformerEffect
AddForeachCountVariablewraps every for-each loop in a block that declares a JML ghost counter \count (int \count), incrementing it at the top of each iteration — gives loop bodies explicit access to the iteration index in specifications
LambdaReplacerlifts a LambdaExpr into a synthetic inner class implementing the target functional interface, then replaces the lambda with new InnerClass(...) — makes lambdas digestible by tools that only handle classic Java
RecordClassBuildertransforms a RecordDeclaration into a plain final class extending java.lang.Record (with optional JML invariants — invariant_free or axiom — and generated bodies), for targets without record support

Status

Library-only: there is no dedicated CLI subcommand. Redux is the canonical way for other tools to normalize Java additions (lambdas, records, enhanced for) before processing them further.

The Transformer interface is open — implement it, register it as a service provider (META-INF/services/io.github.jmltoolkit.redux.Transformer), and it joins the pipeline automatically unless disabled in the config.