From 907cca69480959dd76afa3cb039244dd3b9833ca Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 16 Jan 2016 15:32:34 +0000 Subject: Support method arguments in C# backend --- .../couscous/backends/SourceCodeWriter.java | 15 +++++++++++ .../couscous/backends/csharp/CsharpSerializer.java | 18 +++++++++++-- .../couscous/backends/python/PythonSerializer.java | 26 ++++-------------- .../backends/csharp/CsharpCompilerEvalTests.java | 5 ---- .../backends/csharp/CsharpSerializerTests.java | 31 ++++++++++++++++++++++ 5 files changed, 67 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java b/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java index 3f135de..a50515f 100644 --- a/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java +++ b/src/main/java/org/zwobble/couscous/backends/SourceCodeWriter.java @@ -3,6 +3,11 @@ package org.zwobble.couscous.backends; import com.google.common.base.Strings; import org.zwobble.couscous.util.Action; +import java.util.List; +import java.util.function.Consumer; + +import static com.google.common.collect.Iterables.skip; + public class SourceCodeWriter { public interface WriterAction { void run(SourceCodeWriter writer); @@ -85,4 +90,14 @@ public class SourceCodeWriter { private void runAction(WriterAction action) { action.run(this); } + + public void writeWithSeparator(List values, Consumer writeValue, Action separator) { + if (!values.isEmpty()) { + writeValue.accept(values.get(0)); + for (T value : skip(values, 1)) { + separator.run(); + writeValue.accept(value); + } + } + } } 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 f034975..187a44a 100644 --- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java @@ -5,6 +5,8 @@ import org.zwobble.couscous.ast.visitors.NodeVisitor; import org.zwobble.couscous.backends.SourceCodeWriter; import org.zwobble.couscous.values.PrimitiveValueVisitor; +import java.util.List; + public class CsharpSerializer implements NodeVisitor { public static String serialize(Node node, String namespace) { SourceCodeWriter writer = new SourceCodeWriter( @@ -103,8 +105,7 @@ public class CsharpSerializer implements NodeVisitor { write(methodCall.getReceiver()); writer.writeSymbol("."); writer.writeIdentifier(methodCall.getMethodName()); - writer.writeSymbol("("); - writer.writeSymbol(")"); + writeArguments(methodCall.getArguments()); } @Override @@ -112,7 +113,12 @@ public class CsharpSerializer implements NodeVisitor { writer.writeKeyword("new"); writer.writeSpace(); writeTypeReference(call.getType()); + writeArguments(call.getArguments()); + } + + private void writeArguments(List arguments) { writer.writeSymbol("("); + writer.writeWithSeparator(arguments, this::write, () -> writer.writeSymbol(", ")); writer.writeSymbol(")"); } @@ -203,6 +209,14 @@ public class CsharpSerializer implements NodeVisitor { writer.writeSpace(); writer.writeIdentifier(method.getName()); writer.writeSymbol("("); + writer.writeWithSeparator( + method.getArguments(), + argument -> { + writer.writeKeyword("dynamic"); + writer.writeSpace(); + writer.writeIdentifier(argument.getName()); + }, + () -> writer.writeSymbol(", ")); writer.writeSymbol(")"); writer.startBlock(); for (StatementNode statement : method.getBody()) { diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java index fa71656..d3771d3 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java @@ -3,12 +3,6 @@ package org.zwobble.couscous.backends.python; import org.zwobble.couscous.backends.SourceCodeWriter; import org.zwobble.couscous.backends.python.ast.*; import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; -import org.zwobble.couscous.util.Action; - -import java.util.List; -import java.util.function.Consumer; - -import static com.google.common.collect.Iterables.skip; public class PythonSerializer implements PythonNodeVisitor { public static String serialize(PythonNode node) { @@ -75,7 +69,7 @@ public class PythonSerializer implements PythonNodeVisitor { public void visit(PythonCallNode call) { writeParenthesised(call.getCallee(), call); writer.writeSymbol("("); - writeWithSeparator(call.getArguments(), this::write, () -> { + writer.writeWithSeparator(call.getArguments(), this::write, () -> { writer.writeSymbol(","); writer.writeSpace(); }); @@ -86,7 +80,7 @@ public class PythonSerializer implements PythonNodeVisitor { public void visit(PythonGetSliceNode getSlice) { writeParenthesised(getSlice.getReceiver(), getSlice); writer.writeSymbol("["); - writeWithSeparator(getSlice.getArguments(), this::write, () -> { + writer.writeWithSeparator(getSlice.getArguments(), this::write, () -> { writer.writeSymbol(":"); }); writer.writeSymbol("]"); @@ -170,7 +164,7 @@ public class PythonSerializer implements PythonNodeVisitor { writer.writeSpace(); writer.writeKeyword("import"); writer.writeSpace(); - writeWithSeparator(importNode.getAliases(), alias -> { + writer.writeWithSeparator(importNode.getAliases(), alias -> { writer.writeIdentifier(alias.getName()); }, () -> { writer.writeSymbol(","); @@ -215,22 +209,12 @@ public class PythonSerializer implements PythonNodeVisitor { } private void writeArgumentNames(PythonFunctionDefinitionNode functionDefinition) { - writeWithSeparator(functionDefinition.getArgumentNames(), writer::writeIdentifier, () -> { + writer.writeWithSeparator(functionDefinition.getArgumentNames(), writer::writeIdentifier, () -> { writer.writeSymbol(","); writer.writeSpace(); }); } - - private void writeWithSeparator(List values, Consumer writeValue, Action separator) { - if (!values.isEmpty()) { - writeValue.accept(values.get(0)); - for (T value : skip(values, 1)) { - separator.run(); - writeValue.accept(value); - } - } - } - + @Override public void visit(PythonModuleNode module) { for (PythonStatementNode statement : module.getStatements()) { 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 2348acf..b8aa1b4 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 @@ -45,11 +45,6 @@ public class CsharpCompilerEvalTests extends BackendEvalTests { public void canCallStaticMethodFromUserDefinedStaticMethod() { } - @Test - @Ignore - public void canCallInstanceMethodWithArgumentsOnUserDefinedClass() { - } - @Test @Ignore public void constructorIsExecutedOnConstruction() { 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 1139e3c..377712c 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 @@ -7,6 +7,7 @@ import org.zwobble.couscous.tests.TestIds; import static org.junit.Assert.assertEquals; import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall; +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.ReturnNode.returns; @@ -65,6 +66,16 @@ public class CsharpSerializerTests { assertEquals("x.y()", output); } + @Test + public void methodCallWithArguments() { + String output = serialize(methodCall( + reference(var(TestIds.ANY_ID, "x", TypeName.of("X"))), + "y", + list(literal(1), literal(2)), + TypeName.of("Y"))); + assertEquals("x.y(1, 2)", output); + } + @Test public void constructorCallWithNoArguments() { String output = serialize(constructorCall( @@ -73,6 +84,14 @@ public class CsharpSerializerTests { assertEquals("new Couscous.X()", output); } + @Test + public void constructorCallWithArguments() { + String output = serialize(constructorCall( + TypeName.of("X"), + list(literal(1), literal(2)))); + assertEquals("new Couscous.X(1, 2)", output); + } + @Test public void returnStatementUsesReturnStatement() { String output = serialize(returns(literal(true))); @@ -91,6 +110,18 @@ public class CsharpSerializerTests { assertEquals("internal dynamic nothing() {\n}\n", output); } + @Test + public void methodWithArguments() { + MethodNode methodNode = MethodNode.staticMethod("nothing") + .argument(formalArg(var(TestIds.id("x"), "x", TypeName.of("X")))) + .argument(formalArg(var(TestIds.id("y"), "y", TypeName.of("Y")))) + .build(); + + String output = serialize(methodNode); + + assertEquals("internal static dynamic nothing(dynamic x, dynamic y) {\n}\n", output); + } + @Test public void methodHasSerializedBody() { MethodNode method = MethodNode.staticMethod("nothing") -- cgit v1.2.3