aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/backends/csharp/primitives
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-07-15 16:21:12 +0100
committerMichael Williamson <mike@zwobble.org>2016-07-15 20:38:26 +0100
commit39556c29e0913bdb4e597d4fc629fa101c555959 (patch)
treef7b7731b0e38ba7a1146ef4e2efc3c665c165471 /src/main/java/org/zwobble/couscous/backends/csharp/primitives
parent351567960bd825fbdd4a3f15719f7074a13cdfd3 (diff)
Transform subnodes in NodeTransformer
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/csharp/primitives')
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/CsharpPrimitiveMethods.java195
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethod.java25
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodCall.java51
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodGenerator.java10
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethod.java25
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodCall.java46
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodGenerator.java10
7 files changed, 362 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/CsharpPrimitiveMethods.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/CsharpPrimitiveMethods.java
new file mode 100644
index 0000000..6a5c084
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/CsharpPrimitiveMethods.java
@@ -0,0 +1,195 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import com.google.common.collect.ImmutableMap;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.types.ScalarType;
+import org.zwobble.couscous.types.Types;
+import org.zwobble.couscous.values.InternalCouscousValue;
+
+import java.util.Map;
+import java.util.Optional;
+
+import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess;
+import static org.zwobble.couscous.ast.MethodCallNode.methodCall;
+import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall;
+import static org.zwobble.couscous.ast.OperationNode.operation;
+import static org.zwobble.couscous.ast.Operations.boxInt;
+import static org.zwobble.couscous.ast.Operations.integerSubtract;
+import static org.zwobble.couscous.types.Types.erasure;
+import static org.zwobble.couscous.util.Casts.tryCast;
+import static org.zwobble.couscous.util.ExtraLists.list;
+
+public class CsharpPrimitiveMethods {
+ public static final NodeTransformer TRANSFORMER = NodeTransformer.builder()
+ .transformExpression(CsharpPrimitiveMethods::transformExpression)
+ .build();
+
+
+ private static Optional<ExpressionNode> transformExpression(ExpressionNode expression) {
+ return tryCast(MethodCallNode.class, expression)
+ .flatMap(CsharpPrimitiveMethods::transformMethodCall);
+ }
+
+ private static Optional<ExpressionNode> transformMethodCall(MethodCallNode call) {
+ return call.getReceiver().accept(new Receiver.Mapper<Optional<ExpressionNode>>() {
+ @Override
+ public Optional<ExpressionNode> visit(ExpressionNode receiver) {
+ return CsharpPrimitiveMethods.getPrimitiveMethod(erasure(receiver.getType()), call.getMethodName())
+ .map(method -> new PrimitiveInstanceMethodCall(method, receiver, call.getArguments()));
+ }
+
+ @Override
+ public Optional<ExpressionNode> visit(ScalarType receiver) {
+ return CsharpPrimitiveMethods.getPrimitiveStaticMethod(receiver, call.getMethodName())
+ .map(method -> new PrimitiveStaticMethodCall(method, call.getArguments()));
+ }
+ });
+ }
+
+ private static final Map<String, PrimitiveInstanceMethod> BOOLEAN_METHODS;
+
+ static {
+ ImmutableMap.Builder<String, PrimitiveInstanceMethod> methods = ImmutableMap.builder();
+ BOOLEAN_METHODS = methods.build();
+ }
+
+ private static final Map<String, PrimitiveInstanceMethod> BOXED_INT_METHODS;
+
+ static {
+ ImmutableMap.Builder<String, PrimitiveInstanceMethod> methods = ImmutableMap.builder();
+ methods.put("toString", new PrimitiveInstanceMethod(
+ (receiver, arguments) -> methodCall(
+ receiver,
+ "ToString",
+ list(),
+ Types.STRING
+ ),
+ Types.STRING
+ ));
+ BOXED_INT_METHODS = methods.build();
+ }
+
+ private static final Map<String, PrimitiveInstanceMethod> STRING_METHODS;
+
+ static {
+ ImmutableMap.Builder<String, PrimitiveInstanceMethod> methods = ImmutableMap.builder();
+ methods.put("length", new PrimitiveInstanceMethod(
+ (receiver, arguments) -> fieldAccess(receiver, "Length", Types.INT),
+ Types.INT
+ ));
+ methods.put("substring", new PrimitiveInstanceMethod(
+ (receiver, arguments) -> {
+ ExpressionNode startIndex = arguments.get(0);
+ ExpressionNode endIndex = arguments.get(1);
+ ExpressionNode length = integerSubtract(endIndex, startIndex);
+ // TODO: handle length going beyond end-of-string
+ return methodCall(
+ receiver,
+ "Substring",
+ list(startIndex, length),
+ Types.STRING);
+ },
+ Types.STRING
+ ));
+ methods.put("toLowerCase", new PrimitiveInstanceMethod(
+ (receiver, arguments) -> methodCall(
+ receiver,
+ "ToLower",
+ list(),
+ Types.STRING
+ ),
+ Types.STRING
+ ));
+ methods.put("equals", new PrimitiveInstanceMethod(
+ (receiver, arguments) -> methodCall(
+ receiver,
+ "Equals",
+ arguments,
+ Types.STRING
+ ),
+ Types.STRING
+ ));
+ STRING_METHODS = methods.build();
+ }
+
+ private static final Map<ScalarType, Map<String, PrimitiveInstanceMethod>> METHODS =
+ ImmutableMap.<ScalarType, Map<String, PrimitiveInstanceMethod>>builder()
+ .put(Types.BOOLEAN, BOOLEAN_METHODS)
+ .put(Types.STRING, STRING_METHODS)
+ .put(Types.BOXED_INT, BOXED_INT_METHODS)
+ .build();
+
+ private static final Map<String, PrimitiveStaticMethod> STATIC_INT_METHODS =
+ ImmutableMap.<String, PrimitiveStaticMethod>builder()
+
+ .put("toString", new PrimitiveStaticMethod(
+ arguments -> methodCall(
+ arguments.get(0),
+ "ToString",
+ list(),
+ Types.STRING
+ ),
+ Types.STRING
+ ))
+
+ .put("parseInt", new PrimitiveStaticMethod(
+ arguments -> staticMethodCall(
+ ScalarType.of("int"),
+ "Parse",
+ list(arguments.get(0)),
+ ScalarType.of("int")
+ ),
+ Types.INT
+ ))
+
+ .put("valueOf", new PrimitiveStaticMethod(
+ arguments -> boxInt(arguments.get(0)),
+ Types.BOXED_INT
+ ))
+
+ .build();
+
+ private static final Map<String, PrimitiveStaticMethod> STATIC_STRING_METHODS =
+ ImmutableMap.<String, PrimitiveStaticMethod>builder()
+
+ .put("join", new PrimitiveStaticMethod(
+ arguments -> staticMethodCall(
+ ScalarType.of("java.lang.String"),
+ "join",
+ arguments,
+ Types.STRING
+ ),
+ Types.STRING
+ ))
+
+ .build();
+
+ private static final Map<String, PrimitiveStaticMethod> STATIC_INTERNAL_METHODS =
+ ImmutableMap.<String, PrimitiveStaticMethod>builder()
+
+ .put("same", new PrimitiveStaticMethod(
+ arguments -> operation(Operator.EQUALS, arguments, Types.BOOLEAN),
+ Types.BOOLEAN
+ ))
+
+ .build();
+
+ private static final Map<ScalarType, Map<String, PrimitiveStaticMethod>> STATIC_METHODS =
+ ImmutableMap.<ScalarType, Map<String, PrimitiveStaticMethod>>builder()
+ .put(Types.BOXED_INT, STATIC_INT_METHODS)
+ .put(Types.STRING, STATIC_STRING_METHODS)
+ .put(InternalCouscousValue.REF, STATIC_INTERNAL_METHODS)
+ .build();
+
+ private static Optional<PrimitiveInstanceMethod> getPrimitiveMethod(ScalarType type, String methodName) {
+ return Optional.ofNullable(METHODS.get(type))
+ .flatMap(methodsForType -> Optional.ofNullable(methodsForType.get(methodName)));
+ }
+
+ private static Optional<PrimitiveStaticMethod> getPrimitiveStaticMethod(ScalarType type, String methodName) {
+ return Optional.ofNullable(STATIC_METHODS.get(type))
+ .flatMap(methodsForType -> Optional.ofNullable(methodsForType.get(methodName)));
+ }
+
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethod.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethod.java
new file mode 100644
index 0000000..bb94145
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethod.java
@@ -0,0 +1,25 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.Node;
+import org.zwobble.couscous.types.Type;
+
+import java.util.List;
+
+class PrimitiveInstanceMethod {
+ private final PrimitiveInstanceMethodGenerator generate;
+ private final Type returnType;
+
+ PrimitiveInstanceMethod(PrimitiveInstanceMethodGenerator generate, Type returnType) {
+ this.generate = generate;
+ this.returnType = returnType;
+ }
+
+ public Type getReturnType() {
+ return returnType;
+ }
+
+ public Node generate(ExpressionNode receiver, List<ExpressionNode> arguments) {
+ return generate.generate(receiver, arguments);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodCall.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodCall.java
new file mode 100644
index 0000000..daa6de8
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodCall.java
@@ -0,0 +1,51 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.Node;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.backends.csharp.CsharpNodeTypes;
+import org.zwobble.couscous.types.Type;
+
+import java.util.List;
+
+import static org.zwobble.couscous.util.ExtraIterables.lazyCons;
+
+public class PrimitiveInstanceMethodCall implements ExpressionNode {
+ private final PrimitiveInstanceMethod method;
+ private final ExpressionNode receiver;
+ private final List<ExpressionNode> arguments;
+
+ public PrimitiveInstanceMethodCall(PrimitiveInstanceMethod method, ExpressionNode receiver, List<ExpressionNode> arguments) {
+ this.method = method;
+ this.receiver = receiver;
+ this.arguments = arguments;
+ }
+
+ @Override
+ public Type getType() {
+ return method.getReturnType();
+ }
+
+ @Override
+ public int type() {
+ return CsharpNodeTypes.PRIMITIVE_INSTANCE_METHOD_CALL;
+ }
+
+ @Override
+ public Iterable<? extends Node> childNodes() {
+ return lazyCons(receiver, arguments);
+ }
+
+ @Override
+ public ExpressionNode transform(NodeTransformer transformer) {
+ return new PrimitiveInstanceMethodCall(
+ method,
+ transformer.transformExpression(receiver),
+ transformer.transformExpressions(arguments)
+ );
+ }
+
+ public Node generate() {
+ return method.generate(receiver, arguments);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodGenerator.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodGenerator.java
new file mode 100644
index 0000000..99e3a46
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveInstanceMethodGenerator.java
@@ -0,0 +1,10 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+
+import java.util.List;
+
+@FunctionalInterface
+interface PrimitiveInstanceMethodGenerator {
+ ExpressionNode generate(ExpressionNode receiver, List<ExpressionNode> arguments);
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethod.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethod.java
new file mode 100644
index 0000000..23cceb0
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethod.java
@@ -0,0 +1,25 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.Node;
+import org.zwobble.couscous.types.Type;
+
+import java.util.List;
+
+class PrimitiveStaticMethod {
+ private final PrimitiveStaticMethodGenerator generate;
+ private final Type returnType;
+
+ PrimitiveStaticMethod(PrimitiveStaticMethodGenerator generate, Type returnType) {
+ this.generate = generate;
+ this.returnType = returnType;
+ }
+
+ public Type getReturnType() {
+ return returnType;
+ }
+
+ public Node generate(List<ExpressionNode> arguments) {
+ return generate.generate(arguments);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodCall.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodCall.java
new file mode 100644
index 0000000..d7953ce
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodCall.java
@@ -0,0 +1,46 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.Node;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.backends.csharp.CsharpNodeTypes;
+import org.zwobble.couscous.types.Type;
+
+import java.util.List;
+
+public class PrimitiveStaticMethodCall implements ExpressionNode {
+ private final PrimitiveStaticMethod method;
+ private final List<ExpressionNode> arguments;
+
+ public PrimitiveStaticMethodCall(PrimitiveStaticMethod method, List<ExpressionNode> arguments) {
+ this.method = method;
+ this.arguments = arguments;
+ }
+
+ @Override
+ public Type getType() {
+ return method.getReturnType();
+ }
+
+ @Override
+ public int type() {
+ return CsharpNodeTypes.PRIMITIVE_STATIC_METHOD_CALL;
+ }
+
+ @Override
+ public Iterable<? extends Node> childNodes() {
+ return arguments;
+ }
+
+ @Override
+ public ExpressionNode transform(NodeTransformer transformer) {
+ return new PrimitiveStaticMethodCall(
+ method,
+ transformer.transformExpressions(arguments)
+ );
+ }
+
+ public Node generate() {
+ return method.generate(arguments);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodGenerator.java b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodGenerator.java
new file mode 100644
index 0000000..1a2e2e0
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/primitives/PrimitiveStaticMethodGenerator.java
@@ -0,0 +1,10 @@
+package org.zwobble.couscous.backends.csharp.primitives;
+
+import org.zwobble.couscous.ast.ExpressionNode;
+
+import java.util.List;
+
+@FunctionalInterface
+interface PrimitiveStaticMethodGenerator {
+ ExpressionNode generate(List<ExpressionNode> arguments);
+}