aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/transforms
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-07-31 18:06:33 +0100
committerMichael Williamson <mike@zwobble.org>2016-07-31 18:06:33 +0100
commit1b0bd2dd2eac9883d81d9e2ccb0eecdb50add59c (patch)
tree07aa3ae827d79991f0fc62193d584fec399a651a /src/main/java/org/zwobble/couscous/transforms
parent879f53add0eb030ba6eee502d11b919d9ae25997 (diff)
Read for-each as sugared statements
Diffstat (limited to 'src/main/java/org/zwobble/couscous/transforms')
-rw-r--r--src/main/java/org/zwobble/couscous/transforms/DesugarForEachToWhile.java49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/couscous/transforms/DesugarForEachToWhile.java b/src/main/java/org/zwobble/couscous/transforms/DesugarForEachToWhile.java
new file mode 100644
index 0000000..ab6f1e5
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/transforms/DesugarForEachToWhile.java
@@ -0,0 +1,49 @@
+package org.zwobble.couscous.transforms;
+
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.frontends.java.JavaTypes;
+import org.zwobble.couscous.frontends.java.Scope;
+import org.zwobble.couscous.types.Type;
+import org.zwobble.couscous.types.Types;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration;
+import static org.zwobble.couscous.ast.MethodCallNode.methodCall;
+import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
+import static org.zwobble.couscous.ast.WhileNode.whileLoop;
+import static org.zwobble.couscous.types.BoundTypeParameter.boundTypeParameter;
+import static org.zwobble.couscous.util.ExtraLists.cons;
+import static org.zwobble.couscous.util.ExtraLists.list;
+
+public class DesugarForEachToWhile {
+ public static NodeTransformer transformer() {
+ Scope scope = Scope.create().temporaryPrefix("_couscous_desugar_foreach_to_while");
+ return NodeTransformer.builder()
+ .transformStatement(statement -> {
+ if (statement.type() == NodeTypes.FOR_EACH) {
+ return Optional.of(desugar(scope, ((ForEachNode) statement)));
+ } else {
+ return Optional.empty();
+ }
+ })
+ .build();
+ }
+
+ public static List<StatementNode> desugar(Scope scope, ForEachNode forEach) {
+ Type elementType = forEach.getTarget().getType();
+ ExpressionNode iteratorValue = methodCall(forEach.getIterable(), "iterator", list(), JavaTypes.iterator(elementType));
+ LocalVariableDeclarationNode iterator = scope.temporaryVariable(iteratorValue);
+
+ ExpressionNode hasNext = methodCall(reference(iterator), "hasNext", list(), Types.BOOLEAN);
+ ExpressionNode next = methodCall(reference(iterator), "next", list(), boundTypeParameter(JavaTypes.ITERATOR_TYPE_PARAMETER, elementType));
+ WhileNode loop = whileLoop(hasNext, cons(
+ localVariableDeclaration(forEach.getTarget(), next),
+ forEach.getStatements()
+ ));
+
+ return list(iterator, loop);
+ }
+}