adt4j - Algebraic Data Types for Java
This library implements Algebraic Data Types for Java.
ADT4J provides annotation processor for @GenerateValueClassForVisitor
annotation.
ADT4J generates new class for each @GenerateValueClassForVisitor
annotation.
It allows you to easily define custom data types. Like this:
// Define Expression data type
@WrapsGeneratedValueClass(visitor = ExpressionVisitor.class)
// ExpressionBase class will be automatically generated by annotation processor
// You can use any other name instead of ExpressionBase, like VeryLongNameThatYouShouldNeverActuallyUse
class Expression extends ExpressionBase {
public static void main(String[] args) {
// Static constructor methods are automatically generated for Expression class
Expression e = mul(sum(lit(5), lit(1)), lit(2));
// Reasonable default toString implementation is provided:
System.out.println(e + " = " + e.eval());
}
// This is the required boilerplate for wrapper-class
Expression(ExpressionBase base) {
super(base);
}
// Example of "pattern-matching"
int eval() {
return accept(new ExpressionVisitor<Integer>() {
Integer lit(int i) {
return i;
}
Integer sum(Expression e1, Expression e2) {
return e1.eval() + e2.eval();
}
Integer mul(Expression e1, Expression e2) {
return e1.eval() * e2.eval();
}
});
}
// Actual data-type definition
// Data type is recursive. No special treatment of recursive definition is required.
@GenerateValueClassForVisitor(wrapperClass = Expression.class)
@Visitor(resultVariableName="R")
interface ExpressionVisitor<R> {
@GeneratePredicate(name = "isLiteral");
R lit(int i);
R sum(@Getter(name = "leftOperand") Expression e1, @Getter(name = "rightOperand") Expression e2);
R mul(@Getter(name = "leftOperand") Expression e1, @Getter(name = "rightOperand") Expression e2);
}
}
Features
- Support recursive data types
- Generate hashCode, equals and toString implementations with value semantics
- Generate predicates, getters and "updaters" with additional annotations
- Fully customizable API: custom names and access levels for generated methods
- Optionally generate Comparable implementation with precise compile-time type-check if it is possible
- Optionally generate serializable classes with precise compile-time type-check if it is possible
- Sensible error messages
- Support generated class extention through standard Java's inheritance.
- Reasonably fast
Known Issues
-
maven-compiler-plugin version 3.2 and later doesn't work nicely with annotation processors, see MCOMPILER-235. Only clean builds work. Repeated compilation causes duplicate class errors.
-
It is possible to support explicit recursive data-types definitions without
selfReferenceVariableName
hack, but javac bug prevents it from working. It works when no type-parameters are used, see [IntListVisitor.java example](https://github.com/sviperll/adt4j/blob/master/adt4j-examples/src/main/java/com/github/sviperll/adt4j/examples/IntListVisitor.java.
License
ADT4J is under BSD 3-clause license.
Flattr
Installation
Use maven dependency to use ADT4J:
<dependency>
<groupId>com.github.sviperll</groupId>
<artifactId>adt4j</artifactId>
<version>3.2</version>
</dependency>
You can use adt4j-shaded
artifact to simplify deployment and to avoid dependencies' conflicts. adt4j-shaded
has no dependencies and does not pollute classpath. All java-packages provided by adt4j-shaded
are rooted at com.github.sviperll.adt4j
package.
<dependency>
<groupId>com.github.sviperll</groupId>
<artifactId>adt4j-shaded</artifactId>
<version>3.2</version>
</dependency>
Changelog
See NEWS file.
Usage
See Tutorial
Build
$ git clone git@github.com:sviperll/adt4j.git
$ cd adt4j
$ mvn test
Check for errors and warnings.
ADT4J is built to be compatible with Java 7. See universal-maven-parent project's documentation for instructions about building projects compatible with JDK7.