Skip to content

Instantly share code, notes, and snippets.

@lucaswerkmeister
Last active January 3, 2016 09:59
Show Gist options
  • Save lucaswerkmeister/8446472 to your computer and use it in GitHub Desktop.
Save lucaswerkmeister/8446472 to your computer and use it in GitHub Desktop.
Ceylon comprehension compilation for the Java platform as I understand it

Take this Ceylon code:

{ for (x in foo) if (bar) for (y in baz) op(x, y) }

The compiler generates an anonymous AbstractIterable class for this with a chain of boolean "has thing" methods:

  • next() (the only non-boolean method) calls y() to get the next element, if possible
  • y() checks $iterator$2 to request an iterator for baz, then gets the next item – if it exists, y is set, else y$exhausted$ is set
  • $iterator$2() checks if the x iterator isn’t exhausted, if the y iterator exists and if it doesn’t, checks $next$1() to see if it should generate another iterator
  • $next$1() checks x() to see if it should even check the expression, then checks the expression (I abbreviated it below to bar)
  • x() checks if the "root" iterator isn’t exhausted, and sets x in that case
/** see the full version in test/src/com/redhat/ceylon/compiler/java/test/expression/comprehensions/for_if_for.src */
new AbstractIterator(){
{
$iterator$0 = foo.iterator();
}
private final Iterator $iterator$0;
private Integer x;
private boolean x$exhausted$;
private final boolean x() {
final Object $ceylontmp$item$0 = $iterator$0.next();
x$exhausted$ = $ceylontmp$item$0 == finished;
if (x$exhausted$) {
return false;
} else {
x = $ceylontmp$item$0;
return true;
}
}
private final boolean $next$1() {
while (true) {
if (!this.x()) break;
if (bar) {
break;
}
}
return !x$exhausted$;
}
private Iterator $iterator$2;
private final boolean $iterator$2() {
if (x$exhausted$) return false;
if ($iterator$2 != null) return true;
if (!this.$next$1()) return false;
$iterator$2 = baz.iterator();
return true;
}
private Integer y;
private boolean y$exhausted$;
private final boolean y() {
while (this.$iterator$2()) {
final Object $ceylontmp$item$1 = $iterator$2.next();
y$exhausted$ = $ceylontmp$item$1 == finished;
if (y$exhausted$) {
$iterator$2 = null;
} else {
y = $ceylontmp$item$1;
return true;
}
}
if (x$exhausted$) y$exhausted$ = true;
return false;
}
public final Object next() {
if (this.y()) {
final Integer x = this.x;
final Integer y = this.y;
return op(x, y);
} else return finished;
}
@lucaswerkmeister
Copy link
Author

(read result.java from bottom to top)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment