aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/backends/csharp
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-01-17 18:02:27 +0000
committerMichael Williamson <mike@zwobble.org>2016-01-17 18:02:27 +0000
commitcd244418efb005c27b1018458767c57dfa09e046 (patch)
tree9a536359b38446a6271659337cc6803aab1529b9 /src/main/java/org/zwobble/couscous/backends/csharp
parent013265afb2432181de05a109fd8fe7823d8f3d69 (diff)
Add transformation pass to C# backend
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/csharp')
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java68
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java19
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java67
3 files changed, 89 insertions, 65 deletions
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
new file mode 100644
index 0000000..9e48e9a
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
@@ -0,0 +1,68 @@
+package org.zwobble.couscous.backends.csharp;
+
+import com.google.common.collect.ImmutableMap;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.values.*;
+
+import java.util.Map;
+import java.util.Optional;
+
+public class CsharpCodeGenerator extends NodeTransformer {
+ private final static Map<TypeName, TypeName> PRIMITIVES = ImmutableMap.<TypeName, TypeName>builder()
+ .put(IntegerValue.REF, TypeName.of("int"))
+ .put(StringValue.REF, TypeName.of("string"))
+ .put(BooleanValue.REF, TypeName.of("bool"))
+ .put(ObjectValues.OBJECT, TypeName.of("object"))
+ .put(ObjectValues.CLASS, TypeName.of("System.Type"))
+ .put(UnitValue.REF, TypeName.of("void"))
+ .build();
+
+ private final String namespace;
+
+ public static Node generateCode(Node node, String namespace) {
+ return new CsharpCodeGenerator(namespace).generateCode(node);
+ }
+
+ private CsharpCodeGenerator(String namespace) {
+ this.namespace = namespace;
+ }
+
+ private Node generateCode(Node node) {
+ return node.accept(this);
+ }
+
+ @Override
+ public TypeName transform(TypeName type) {
+ if (PRIMITIVES.containsKey(type)) {
+ return PRIMITIVES.get(type);
+ } else {
+ return addPrefix(type, namespace);
+ }
+ }
+
+ @Override
+ public ExpressionNode visit(MethodCallNode call) {
+ return toPrimitiveMethod(call).orElseGet(() -> super.visit(call));
+ }
+
+ private Optional<ExpressionNode> toPrimitiveMethod(MethodCallNode call) {
+ return call.getReceiver().accept(new Receiver.Mapper<Optional<ExpressionNode>>() {
+ @Override
+ public Optional<ExpressionNode> visit(ExpressionNode receiver) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ExpressionNode> visit(TypeName receiver) {
+ return CsharpPrimitiveMethods.getPrimitiveStaticMethod(receiver, call.getMethodName())
+ .map(generator -> generator.generate(call.getArguments()));
+ }
+ });
+
+ }
+
+ private TypeName addPrefix(TypeName name, String namespace) {
+ return TypeName.of(namespace + "." + name.getQualifiedName());
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
index b53560d..9424b2d 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
@@ -3,25 +3,24 @@ package org.zwobble.couscous.backends.csharp;
import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.ExpressionNode;
import org.zwobble.couscous.ast.TypeName;
-import org.zwobble.couscous.backends.SourceCodeWriter;
import org.zwobble.couscous.values.ObjectValues;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall;
+import static org.zwobble.couscous.util.ExtraLists.list;
+
public class CsharpPrimitiveMethods {
private static final Map<String, PrimitiveStaticMethodGenerator> STATIC_INT_METHODS =
ImmutableMap.<String, PrimitiveStaticMethodGenerator>builder()
- .put("parseInt", (arguments, writer) -> {
- writer.writeIdentifier("int");
- writer.writeSymbol(".");
- writer.writeIdentifier("Parse");
- writer.writeSymbol("(");
- writer.writeIdentifier(CsharpSerializer.serialize(arguments.get(0), ""));
- writer.writeSymbol(")");
- })
+ .put("parseInt", arguments -> staticMethodCall(
+ TypeName.of("int"),
+ "Parse",
+ list(arguments.get(0)),
+ TypeName.of("int")))
.build();
@@ -37,6 +36,6 @@ public class CsharpPrimitiveMethods {
@FunctionalInterface
public interface PrimitiveStaticMethodGenerator {
- void generate(List<ExpressionNode> arguments, SourceCodeWriter writer);
+ ExpressionNode generate(List<ExpressionNode> arguments);
}
}
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 275ae13..ffd2f02 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java
@@ -1,24 +1,13 @@
package org.zwobble.couscous.backends.csharp;
-import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.ast.visitors.NodeVisitor;
import org.zwobble.couscous.backends.SourceCodeWriter;
-import org.zwobble.couscous.values.*;
+import org.zwobble.couscous.values.PrimitiveValueVisitor;
import java.util.List;
-import java.util.Map;
public class CsharpSerializer implements NodeVisitor {
- private final static Map<TypeName, String> PRIMITIVES = ImmutableMap.<TypeName, String>builder()
- .put(IntegerValue.REF, "int")
- .put(StringValue.REF, "string")
- .put(BooleanValue.REF, "bool")
- .put(ObjectValues.OBJECT, "object")
- .put(ObjectValues.CLASS, "System.Type")
- .put(UnitValue.REF, "void")
- .build();
-
public static String serialize(Node node, String namespace) {
SourceCodeWriter writer = new SourceCodeWriter(
(writer2) -> {
@@ -29,17 +18,16 @@ public class CsharpSerializer implements NodeVisitor {
writer2.writeStatement(() -> writer2.writeSymbol("}"));
}
);
- CsharpSerializer serializer = new CsharpSerializer(writer, namespace);
- serializer.write(node);
+ CsharpSerializer serializer = new CsharpSerializer(writer);
+
+ serializer.write(CsharpCodeGenerator.generateCode(node, namespace));
return writer.asString();
}
private final SourceCodeWriter writer;
- private final String namespace;
- private CsharpSerializer(SourceCodeWriter writer, String namespace) {
+ private CsharpSerializer(SourceCodeWriter writer) {
this.writer = writer;
- this.namespace = namespace;
}
private void write(Node node) {
@@ -117,32 +105,10 @@ public class CsharpSerializer implements NodeVisitor {
@Override
public void visit(MethodCallNode methodCall) {
- if (!writePrimitiveMethod(methodCall)) {
- write(methodCall.getReceiver());
- writer.writeSymbol(".");
- writer.writeIdentifier(methodCall.getMethodName());
- writeArguments(methodCall.getArguments());
- }
- }
-
- private boolean writePrimitiveMethod(MethodCallNode methodCall) {
- return methodCall.getReceiver().accept(new Receiver.Mapper<Boolean>() {
- @Override
- public Boolean visit(ExpressionNode receiver) {
- return false;
- }
-
- @Override
- public Boolean visit(TypeName receiver) {
- // TODO: transform AST before serialisation instead of exposing write to CsharpPrimitiveMethods
- return CsharpPrimitiveMethods.getPrimitiveStaticMethod(receiver, methodCall.getMethodName())
- .map(generator -> {
- generator.generate(methodCall.getArguments(), writer);
- return true;
- })
- .orElse(false);
- }
- });
+ write(methodCall.getReceiver());
+ writer.writeSymbol(".");
+ writer.writeIdentifier(methodCall.getMethodName());
+ writeArguments(methodCall.getArguments());
}
@Override
@@ -278,13 +244,9 @@ public class CsharpSerializer implements NodeVisitor {
@Override
public void visit(ClassNode classNode) {
- String namespace = this.namespace +
- classNode.getName().getPackage()
- .map(packageName -> "." + packageName)
- .orElse("");
writer.writeKeyword("namespace");
writer.writeSpace();
- writer.writeIdentifier(namespace);
+ writer.writeIdentifier(classNode.getName().getPackage().get());
writer.startBlock();
writer.writeStatement(() -> {
writer.writeKeyword("internal");
@@ -323,15 +285,10 @@ public class CsharpSerializer implements NodeVisitor {
}
private void writeTypeReference(TypeName value) {
- // TODO: process the nodes before serialization
- if (PRIMITIVES.containsKey(value)) {
- writer.writeIdentifier(PRIMITIVES.get(value));
- } else {
- writer.writeIdentifier(typeReference(value));
- }
+ writer.writeIdentifier(typeReference(value));
}
private String typeReference(TypeName value) {
- return namespace + "." + value.getQualifiedName();
+ return value.getQualifiedName();
}
}