diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-01-24 16:13:33 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-01-24 16:13:33 +0000 |
| commit | 5fe2fa7934197d73bc1f6a3e361149923279b35a (patch) | |
| tree | 3850ffc02c864875084c174e26466a052ccc6368 /src | |
| parent | f2ed6b591da6149319c149d1c78694bfa9641a73 (diff) | |
Implement negation in C# backend
Diffstat (limited to 'src')
8 files changed, 67 insertions, 27 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/OperationNode.java b/src/main/java/org/zwobble/couscous/ast/OperationNode.java index 0840044..6be841f 100644 --- a/src/main/java/org/zwobble/couscous/ast/OperationNode.java +++ b/src/main/java/org/zwobble/couscous/ast/OperationNode.java @@ -28,6 +28,10 @@ public class OperationNode implements ExpressionNode { type); } + public Operator getOperator() { + return operator; + } + public List<ExpressionNode> getArguments() { return arguments; } diff --git a/src/main/java/org/zwobble/couscous/ast/Operations.java b/src/main/java/org/zwobble/couscous/ast/Operations.java index 5af2f8b..0ae4923 100644 --- a/src/main/java/org/zwobble/couscous/ast/Operations.java +++ b/src/main/java/org/zwobble/couscous/ast/Operations.java @@ -5,9 +5,6 @@ import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.InternalCouscousValue; import org.zwobble.couscous.values.ObjectValues; -import java.util.Collections; - -import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall; import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion; import static org.zwobble.couscous.util.ExtraLists.list; @@ -19,7 +16,9 @@ public class Operations { public static ExpressionNode not(ExpressionNode value) { if (value.getType().equals(BooleanValue.REF)) { - return methodCall(value, "negate", Collections.emptyList(), BooleanValue.REF); + return OperationNode.operation( + Operator.BOOLEAN_NOT, list(value), + BooleanValue.REF); } else { throw new IllegalArgumentException("Can only negate booleans"); } diff --git a/src/main/java/org/zwobble/couscous/ast/Operator.java b/src/main/java/org/zwobble/couscous/ast/Operator.java index a215138..a51a01b 100644 --- a/src/main/java/org/zwobble/couscous/ast/Operator.java +++ b/src/main/java/org/zwobble/couscous/ast/Operator.java @@ -1,30 +1,37 @@ package org.zwobble.couscous.ast; public enum Operator { - BOOLEAN_AND("and", true), - BOOLEAN_OR("or", true), - - ADD("add", false), - SUBTRACT("subtract", false), - MULTIPLY("multiply", false), - DIVIDE("divide", false), - MOD("mod", false), - - EQUALS("equals", true), - NOT_EQUALS("notEquals", true), - GREATER_THAN("greaterThan", true), - GREATER_THAN_OR_EQUAL("greaterThanOrEqual", true), - LESS_THAN("lessThan", true), - LESS_THAN_OR_EQUAL("lessThanOrEqual", true); + BOOLEAN_AND("&&", "and", true), + BOOLEAN_OR("||", "or", true), + BOOLEAN_NOT("!", "negate", true), + ADD("+", "add", false), + SUBTRACT("-", "subtract", false), + MULTIPLY("*", "multiply", false), + DIVIDE("/", "divide", false), + MOD("%", "mod", false), + + EQUALS("==", "equals", true), + NOT_EQUALS("!=", "notEquals", true), + GREATER_THAN(">", "greaterThan", true), + GREATER_THAN_OR_EQUAL(">=", "greaterThanOrEqual", true), + LESS_THAN("<", "lessThan", true), + LESS_THAN_OR_EQUAL("<=", "lessThanOrEqual", true); + + private final String symbol; private final String methodName; private final boolean isBoolean; - Operator(String methodName, boolean isBoolean) { + Operator(String symbol, String methodName, boolean isBoolean) { + this.symbol = symbol; this.methodName = methodName; this.isBoolean = isBoolean; } + public String getSymbol() { + return symbol; + } + public String getMethodName() { return methodName; } 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 9e48e9a..ab55e0d 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java @@ -50,7 +50,8 @@ public class CsharpCodeGenerator extends NodeTransformer { return call.getReceiver().accept(new Receiver.Mapper<Optional<ExpressionNode>>() { @Override public Optional<ExpressionNode> visit(ExpressionNode receiver) { - return Optional.empty(); + return CsharpPrimitiveMethods.getPrimitiveMethod(receiver.getType(), call.getMethodName()) + .map(generator -> generator.generate(receiver, call.getArguments())); } @Override 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 9424b2d..e094258 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java @@ -3,6 +3,8 @@ 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.python.ast.PythonExpressionNode; +import org.zwobble.couscous.values.BooleanValue; import org.zwobble.couscous.values.ObjectValues; import java.util.List; @@ -13,6 +15,18 @@ import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall; import static org.zwobble.couscous.util.ExtraLists.list; public class CsharpPrimitiveMethods { + private static final Map<String, PrimitiveMethodGenerator> BOOLEAN_METHODS; + + static { + ImmutableMap.Builder<String, PrimitiveMethodGenerator> methods = ImmutableMap.builder(); + BOOLEAN_METHODS = methods.build(); + } + + private static final Map<TypeName, Map<String, PrimitiveMethodGenerator>> METHODS = + ImmutableMap.<TypeName, Map<String, PrimitiveMethodGenerator>>builder() + .put(BooleanValue.REF, BOOLEAN_METHODS) + .build(); + private static final Map<String, PrimitiveStaticMethodGenerator> STATIC_INT_METHODS = ImmutableMap.<String, PrimitiveStaticMethodGenerator>builder() @@ -29,6 +43,16 @@ public class CsharpPrimitiveMethods { .put(ObjectValues.BOXED_INT, STATIC_INT_METHODS) .build(); + public static Optional<PrimitiveMethodGenerator> getPrimitiveMethod(TypeName type, String methodName) { + return Optional.ofNullable(METHODS.get(type)) + .flatMap(methodsForType -> Optional.ofNullable(methodsForType.get(methodName))); + } + + @FunctionalInterface + public interface PrimitiveMethodGenerator { + ExpressionNode generate(ExpressionNode receiver, List<ExpressionNode> arguments); + } + public static Optional<PrimitiveStaticMethodGenerator> getPrimitiveStaticMethod(TypeName 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/CsharpSerializer.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java index 06dafbb..6f20310 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java @@ -121,7 +121,9 @@ public class CsharpSerializer implements NodeVisitor { @Override public void visit(OperationNode operation) { - write(operation.desugar()); + // TODO: distinguish operator types (prefix, infix) + writer.writeSymbol(operation.getOperator().getSymbol()); + write(operation.getArguments().get(0)); } private void writeArguments(List<? extends ExpressionNode> arguments) { diff --git a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpCompilerEvalTests.java b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpCompilerEvalTests.java index 24588df..60df2a9 100644 --- a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpCompilerEvalTests.java +++ b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpCompilerEvalTests.java @@ -12,11 +12,6 @@ import java.util.List; public class CsharpCompilerEvalTests extends BackendEvalTests { @Test @Ignore - public void canEvaluateOperationsOnBooleans() { - } - - @Test - @Ignore public void canEvaluateOperationsOnIntegers() { } 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 011fcd3..199f144 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 @@ -15,6 +15,7 @@ import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg; import static org.zwobble.couscous.ast.LiteralNode.literal; import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall; +import static org.zwobble.couscous.ast.Operations.not; import static org.zwobble.couscous.ast.ReturnNode.returns; import static org.zwobble.couscous.ast.TernaryConditionalNode.ternaryConditional; import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference; @@ -123,6 +124,13 @@ public class CsharpSerializerTests { } @Test + public void prefixExpression() { + String output = serialize(not( + reference(var(TestIds.ANY_ID, "x", BooleanValue.REF)))); + assertEquals("!x", output); + } + + @Test public void fieldAccessSeparatesReceiverAndNameWithDot() { String output = serialize(fieldAccess( reference(var(TestIds.ANY_ID, "x", TypeName.of("X"))), |
