https://github.com/forax/destructured-visitor
Destructured Visitors are a fast but type-unsafe implementation of recursive Visitor in Java
https://github.com/forax/destructured-visitor
method-handle pattern-matcher pattern-matching visitor-pattern
Last synced: 4 months ago
JSON representation
Destructured Visitors are a fast but type-unsafe implementation of recursive Visitor in Java
- Host: GitHub
- URL: https://github.com/forax/destructured-visitor
- Owner: forax
- License: apache-2.0
- Created: 2023-09-30T06:31:15.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2023-10-07T07:15:13.000Z (over 2 years ago)
- Last Synced: 2023-10-07T08:21:40.240Z (over 2 years ago)
- Topics: method-handle, pattern-matcher, pattern-matching, visitor-pattern
- Language: Java
- Homepage:
- Size: 24.4 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Destructured Visitor
Destructured Visitor is a fast by type-unsafe implementation of a recursive Visitor in Java.
Unlike a classical recursive visitor or the pattern-matching (switch on types), this implementation
uses a specific inlining cache that is not shared in between different part of the tree of instances.
Let suppose we have the following hierarchies
```java
interface Unit {}
record Marine() implements Unit {}
record Sailor() implements Unit {}
record Soldier() implements Unit {}
interface Carrier {}
record Boat(List units) implements Carrier { }
record Tank(List units) implements Carrier { }
```
A way to traverse those hierarchies to compute something is to use the pattern matching
```java
static int visitCarrier(Carrier carrier) {
return switch (carrier) {
case Boat(var units) -> visitUnits(units);
case Tank(var units) -> visitUnits(units);
};
}
static int visitUnits(List units) {
return units.stream().mapToInt(PatternMatching::visitUnit).sum();
}
static int visitUnit(Unit unit) {
return switch (unit) {
case Marine marine -> 10;
case Sailor sailor -> 12;
case Soldier soldier -> 14;
};
}
public static void main(String[] args) {
var boat = new Boat(List.of(new Marine(), new Sailor(), new Soldier()));
System.out.println(PatternMatching.visitCarrier(boat))); // 36
...
```
This is how to do it using the destructured visitor
```java
static int visit(Marine marine) { return 10; }
static int visit(Sailor sailor) { return 12; }
static int visit(Soldier soldier) { return 14; }
static int visit(Boat boat, @Signature({int.class, Unit.class}) MethodHandle dispatchUnit) throws Throwable {
return visitUnits(boat.units(), dispatchUnit);
}
static int visit(Tank tank, @Signature({int.class, Unit.class}) MethodHandle dispatchUnit) throws Throwable {
return visitUnits(tank.units(), dispatchUnit);
}
static int visitUnits(List units, MethodHandle dispatchUnit) throws Throwable {
var sum = 0;
for(var unit: units) {
sum += (int) dispatchUnit.invokeExact(unit);
}
return sum;
}
static final DestructuredVisitor VISITOR = DestructuredVisitor.of(MethodHandles.lookup(),
Arrays.stream(Visitor.class.getDeclaredMethods())
.filter(m -> m.getName().equals("visit"))
.toList());
static final MethodHandle DISPATCH_CARRIER = VISITOR.createDispatch(int.class, Carrier.class);
static int accept(Carrier carrier) throws Throwable {
return (int) DISPATCH_CARRIER.invokeExact(carrier);
}
public static void main(String[] args) throws Throwable {
var boat = new Boat(List.of(new Marine(), new Sailor(), new Soldier()));
System.out.println(Visitor.accept(boat))); // 36
...
```
### How to build the code
You need Java 21. The code of the DestructuredVisitor is compatible with Java 8 but the tests required Java 21.
To build with maven
```
mvn package
```