From 351567960bd825fbdd4a3f15719f7074a13cdfd3 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 15 Jul 2016 14:34:15 +0100 Subject: Generate switch statements in C# backend --- .../java/org/zwobble/couscous/ast/NodeTypes.java | 4 +++ .../couscous/backends/SourceCodeWriter.java | 12 ++++++-- .../backends/csharp/CsharpCodeGenerator.java | 6 +--- .../couscous/backends/csharp/CsharpSerializer.java | 32 ++++++++++++++++++++++ .../backends/csharp/CsharpSerializerTests.java | 17 ++++++++++++ 5 files changed, 64 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/ast/NodeTypes.java b/src/main/java/org/zwobble/couscous/ast/NodeTypes.java index 86703ff..41ba8af 100644 --- a/src/main/java/org/zwobble/couscous/ast/NodeTypes.java +++ b/src/main/java/org/zwobble/couscous/ast/NodeTypes.java @@ -1,6 +1,8 @@ package org.zwobble.couscous.ast; import com.google.common.collect.ImmutableMap; +import org.zwobble.couscous.ast.sugar.SwitchCaseNode; +import org.zwobble.couscous.ast.sugar.SwitchNode; import java.util.Map; @@ -69,6 +71,8 @@ public class NodeTypes { .put(OperationNode.class, OPERATION) .put(ReturnNode.class, RETURN) .put(StaticReceiver.class, STATIC_RECEIVER) + .put(SwitchNode.class, SWITCH) + .put(SwitchCaseNode.class, SWITCH_CASE) .put(TernaryConditionalNode.class, TERNARY_CONDITIONAL) .put(ThisReferenceNode.class, THIS_REFERENCE) .put(ThrowNode.class, THROW) diff --git a/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java b/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java index 57959fd..eb29a4e 100644 --- a/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java +++ b/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java @@ -69,15 +69,23 @@ public class SourceCodeWriter { public void startBlock() { runAction(blockStart); - depth++; + indent(); builder.append("\n"); } public void endBlock() { - depth--; + dedent(); runAction(blockEnd); } + public void indent() { + depth++; + } + + public void dedent() { + depth--; + } + public void writeStatement(Action action) { startStatement(); action.run(); diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java index 23743d0..537184c 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java @@ -7,8 +7,6 @@ import org.zwobble.couscous.ast.Node; import org.zwobble.couscous.ast.Receiver; import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.backends.naming.Naming; -import org.zwobble.couscous.frontends.java.Scope; -import org.zwobble.couscous.transforms.DesugarSwitchToIfElse; import org.zwobble.couscous.types.*; import java.util.Map; @@ -50,9 +48,7 @@ public class CsharpCodeGenerator { } private Node generateCode(Node node) { - return node - .transform(DesugarSwitchToIfElse.transformer(Scope.create())) - .transform(nodeTransformer); + return node.transform(nodeTransformer); } private Type transformType(Type type) { diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java index 91a4400..6164d04 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java @@ -2,6 +2,8 @@ package org.zwobble.couscous.backends.csharp; import com.google.common.collect.ImmutableSet; import org.zwobble.couscous.ast.*; +import org.zwobble.couscous.ast.sugar.SwitchCaseNode; +import org.zwobble.couscous.ast.sugar.SwitchNode; import org.zwobble.couscous.ast.visitors.DynamicNodeMapper; import org.zwobble.couscous.ast.visitors.DynamicNodeVisitor; import org.zwobble.couscous.backends.SourceCodeWriter; @@ -366,6 +368,36 @@ public class CsharpSerializer { } } + public void visit(SwitchNode switchNode) { + writer.writeStatement(() -> { + writer.writeKeyword("switch"); + writer.writeSpace(); + writer.writeSymbol("("); + write(switchNode.getValue()); + writer.writeSymbol(")"); + writer.startBlock(); + switchNode.getCases().forEach(this::visit); + writer.endBlock(); + }); + } + + private void visit(SwitchCaseNode switchCase) { + writer.writeStatement(() -> { + if (switchCase.getValue().isPresent()) { + writer.writeKeyword("case"); + writer.writeSpace(); + write(switchCase.getValue().get()); + } else { + writer.writeKeyword("default"); + } + writer.writeSymbol(":"); + }); + writer.indent(); + writeAll(switchCase.getStatements()); + writer.dedent(); + + } + public void visit(WhileNode whileLoop) { writer.writeStatement(() -> { writer.writeKeyword("while"); diff --git a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java index 3cb723e..40653af 100644 --- a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java +++ b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpSerializerTests.java @@ -3,6 +3,7 @@ package org.zwobble.couscous.tests.backends.csharp; import org.junit.Test; import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.identifiers.Identifiers; +import org.zwobble.couscous.ast.sugar.SwitchNode; import org.zwobble.couscous.backends.csharp.CsharpSerializer; import org.zwobble.couscous.tests.TestIds; import org.zwobble.couscous.types.ScalarType; @@ -35,6 +36,7 @@ import static org.zwobble.couscous.ast.TryNode.tryStatement; import static org.zwobble.couscous.ast.VariableDeclaration.var; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; import static org.zwobble.couscous.ast.WhileNode.whileLoop; +import static org.zwobble.couscous.ast.sugar.SwitchCaseNode.switchCase; import static org.zwobble.couscous.types.TypeParameter.typeParameter; import static org.zwobble.couscous.util.ExtraLists.list; @@ -307,6 +309,21 @@ public class CsharpSerializerTests { assertEquals("if (true) {\n return 1;\n} else if (false) {\n return 2;\n} else {\n return 3;\n}\n", output); } + @Test + public void switchStatement() { + Node node = new SwitchNode( + literal(1), + list( + switchCase(literal(1), list(returns(literal(10)))), + switchCase(list(returns(literal(0)))) + ) + ); + + String output = serialize(node); + + assertEquals("switch (1) {\n case 1:\n return 10;\n default:\n return 0;\n}\n", output); + } + @Test public void whileLoopPrintsConditionAndBody() { String output = serialize(whileLoop( -- cgit v1.2.3