Skip to content

Instantly share code, notes, and snippets.

@fwbrasil
Last active August 28, 2017 01:41
Show Gist options
  • Save fwbrasil/6d8d7f443f7487524a6a8db2ed70eb1d to your computer and use it in GitHub Desktop.
Save fwbrasil/6d8d7f443f7487524a6a8db2ed70eb1d to your computer and use it in GitHub Desktop.
Java macro DSL
/**
*
* THIS IS JUST A DSL PROTOTYPE
*
* First tentative of a DSL for defining macro transformations in Java.
* There's a lot of noise because of the absence of pattern matching and tuples.
* This is a prototype of one of the if/else transformations in Monadless:
*
* case q"if($cond) $ifTrue else $ifFalse" =>
* (ifTrue, ifFalse) match {
* case (Transform(ifTrue), Transform(ifFalse)) =>
* Some(q"if($cond) $ifTrue else $ifFalse")
* case (Transform(ifTrue), ifFalse) =>
* Some(q"if($cond) $ifTrue else ${Resolve.apply(tree.pos)}($ifFalse)")
* case (ifTrue, Transform(ifFalse)) =>
* Some(q"if($cond) ${Resolve.apply(tree.pos)}($ifTrue) else $ifFalse")
* case (ifTrue, ifFalse) =>
* None
* }
*
* https://github.com/monadless/monadless/blob/master/monadless-core/src/main/scala/io/monadless/impl/Transformer.scala#L31
*
* `when` is similar to pattern matching quasiquotes in Scala. The lambda
* inputs are the variables and the body, the pattern.
*
* For instance,
* case q"if($pred) $a else $b" =>
* becomes
* when((Tree<Boolean> pred, Tree<T> a, Tree<T> b) -> pred.splice() ? a.splice() : b.splice())
*
* `splice` within a `tree` call indicates that the tree must be inserted
* at the specified position.
*/
class AsyncMacro {
@Macro
public <T> Tree<Future<T>> async(Tree<T> t) {
return transform(t).orElse(tree(Future.apply(t.splice())));
}
private <T> Optional<Tree<Future<T>>> transform(Tree<T> t) {
return when((Tree<Future<T>> f) -> await(f.splice())).then(f -> tree(f.splice()))
.when((Tree<Boolean> pred, Tree<T> a, Tree<T> b) -> pred.splice() ? a.splice() : b.splice())
.thenMaybe((pred, a, b) ->
transform(a).flatMap(tA ->
transform(b).map(tB ->
tree(pred.splice() ? tA.splice() : tB.splice())
)
)
)
.thenMaybe((pred, a, b) ->
transform(a).map(tA ->
tree(pred.splice() ? tA.splice() : Future.apply(b.splice()))
)
)
.thenMaybe((pred, a, b) ->
transform(b).map(tB ->
tree(pred.splice() ? Future.apply(a.splice()) : tB.splice())
)
)
.apply(t);
}
}
class Example {
Future<Integer> test(boolean b) {
return async(b ? await(callServiceA()) : await(callServiceB()));
}
private Future<Integer> callServiceA() {
return null; // remote call
}
private Future<Integer> callServiceB() {
return null; // remote call
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment