Skip to content

Commit

Permalink
Fix comprehensions starting with multiple "if" clauses
Browse files Browse the repository at this point in the history
This also significantly simplifies the $next$0() method – see the test
case.

CC ceylon/ceylon-spec#869
  • Loading branch information
lucaswerkmeister committed Jan 19, 2014
1 parent 0006dd2 commit 024c4b8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4663,36 +4663,47 @@ public List<JCStatement> getResult() {

private void transformIfClause(Tree.IfComprehensionClause clause) {
List<JCStatement> body;
if (clause == comp.getInitialComprehensionClause()) {
//No previous context
ctxtName = naming.synthetic(Prefix.$next$, idx);
if (prevItemVar == null) {
List<JCStatement> initBlock;
if (clause == comp.getInitialComprehensionClause()) {
//No previous context
assert (ctxtName == null);
ctxtName = naming.synthetic(Prefix.$next$, idx);
//define a variable that records if the expression was already evaluated
SyntheticName exhaustedName = ctxtName.suffixedBy(Suffix.$exhausted$);
JCVariableDecl exhaustedDef = make().VarDef(make().Modifiers(Flags.PRIVATE),
exhaustedName.asName(), makeJavaType(typeFact().getBooleanDeclaration().getType()), null);
fields.add(exhaustedDef);
JCStatement returnIfExhausted = make().If(exhaustedName.makeIdent(), make().Return(makeBoolean(false)), null);
JCStatement setExhaustedTrue = make().Exec(make().Assign(exhaustedName.makeIdent(), makeBoolean(true)));
initBlock = List.<JCStatement>of(
//if we already evaluated the expression, return
returnIfExhausted,
//record that we will have evaluated the expression
setExhaustedTrue);
} else {
assert (ctxtName != null);
JCStatement returnIfExhausted = make().If(
//if the previous comprehension is false or was already evaluated...
make().Unary(JCTree.NOT, make().Apply(null,
ctxtName.makeIdentWithThis(), List.<JCExpression>nil())),
//return false
make().Return(makeBoolean(false)), null);
ctxtName = naming.synthetic(Prefix.$next$, idx);
initBlock = List.<JCStatement>of(returnIfExhausted);
}

SyntheticName exhaustedName = ctxtName.suffixedBy(Suffix.$exhausted$);
JCVariableDecl exhaustedDef = make().VarDef(make().Modifiers(Flags.PRIVATE),
exhaustedName.asName(), makeJavaType(typeFact().getBooleanDeclaration().getType()), null);
fields.add(exhaustedDef);
JCStatement returnIfExhausted = make().If(exhaustedName.makeIdent(), make().Return(makeBoolean(false)), null);
SyntheticName resultName = naming.temp("result");
JCVariableDecl declareResult = make().VarDef(make().Modifiers(0),
resultName.asName(), makeJavaType(typeFact().getBooleanDeclaration().getType()), makeBoolean(false));
JCStatement setResultTrue = make().Exec(make().Assign(resultName.makeIdent(), makeBoolean(true)));
JCStatement setExhaustedTrue = make().Exec(make().Assign(exhaustedName.makeIdent(), makeBoolean(true)));
JCStatement returnResult = make().Return(resultName.makeIdent());
JCStatement returnTrue = make().Return(makeBoolean(true));
JCStatement returnFalse = make().Return(makeBoolean(false));

body = new IfComprehensionCondList(clause.getConditionList().getConditions(),
initBlock,
List.<JCStatement>of(
//if we already evaluated the expression, return
returnIfExhausted,
//declare the result variable that's going to store the result of the conditions (init to false)
declareResult),
List.<JCStatement>of(
//if the conditions apply: set the result variable to true
setResultTrue),
//if the conditions apply: return true
returnTrue),
List.<JCStatement>of(
//we evaluated the expression
setExhaustedTrue,
//and return the result
returnResult)).getResult();
//the conditions did not apply: return false
returnFalse)).getResult();
} else {
//Filter contexts need to check if the previous context applies and then check the condition
JCExpression condExpr = make().Apply(null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,23 @@ final class ifFor_ {
{
}
private boolean $next$0$exhausted$;
private .java.lang.String x$2;
private .java.lang.String x$1;

private final boolean $next$0() {
if ($next$0$exhausted$) return false;
boolean $ceylontmp$result$0 = false;
.ceylon.language.String x$1 = null;
if ((x$1 = x) != null) {
x$2 = x$1.toString();
$ceylontmp$result$0 = true;
}
$next$0$exhausted$ = true;
return $ceylontmp$result$0;
.ceylon.language.String x$0 = null;
if ((x$0 = x) != null) {
x$1 = x$0.toString();
return true;
}
return false;
}

public final .java.lang.Object next() {
if (this.$next$0()) {
final .java.lang.String x$2 = this.x$2;
return .ceylon.language.String.instance(x$2);
final .java.lang.String x$1 = this.x$1;
return .ceylon.language.String.instance(x$1);
} else return .ceylon.language.finished_.get_();
}
};
Expand Down

0 comments on commit 024c4b8

Please sign in to comment.