diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-01-17 18:02:27 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-01-17 18:02:27 +0000 |
| commit | cd244418efb005c27b1018458767c57dfa09e046 (patch) | |
| tree | 9a536359b38446a6271659337cc6803aab1529b9 /src/main/java/org/zwobble/couscous/backends/csharp | |
| parent | 013265afb2432181de05a109fd8fe7823d8f3d69 (diff) | |
Add transformation pass to C# backend
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/csharp')
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(); } } |
