diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-03-17 22:33:15 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-03-18 08:00:10 +0000 |
| commit | cea82209e5aa312f4a513308c148d3e944004cb4 (patch) | |
| tree | 6f7e5fa7bb1656b4650bb227866195f35bc962e0 /src/main/java | |
| parent | 5687fd7f88485f95e970b3d93fbf2800e84eb3b8 (diff) | |
Improve support for generics
Diffstat (limited to 'src/main/java')
12 files changed, 130 insertions, 33 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java index 43993b8..0078002 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java @@ -16,16 +16,36 @@ public class MethodCallNode implements ExpressionNode { String className, String methodName, List<ExpressionNode> arguments, - Type type) { + Type type) + { return staticMethodCall(ScalarType.of(className), methodName, arguments, type); } public static ExpressionNode staticMethodCall( + String className, + String methodName, + List<ExpressionNode> arguments, + MethodSignature signature) + { + return staticMethodCall(ScalarType.of(className), methodName, arguments, signature); + } + + public static ExpressionNode staticMethodCall( ScalarType className, String methodName, List<ExpressionNode> arguments, - Type type) { - return MethodCallNode.methodCall(staticReceiver(className), methodName, arguments, type); + Type type) + { + return methodCall(staticReceiver(className), methodName, arguments, type); + } + + public static ExpressionNode staticMethodCall( + ScalarType className, + String methodName, + List<ExpressionNode> arguments, + MethodSignature signature) + { + return methodCall(staticReceiver(className), methodName, arguments, signature); } public static MethodCallNode methodCall( @@ -38,29 +58,51 @@ public class MethodCallNode implements ExpressionNode { } public static MethodCallNode methodCall( + ExpressionNode receiver, + String methodName, + List<ExpressionNode> arguments, + MethodSignature signature) + { + return methodCall(instanceReceiver(receiver), methodName, arguments, signature); + } + + public static MethodCallNode methodCall( Receiver receiver, String methodName, List<ExpressionNode> arguments, Type type) { - return new MethodCallNode(receiver, methodName, arguments, type); + MethodSignature signature = new MethodSignature( + methodName, + eagerMap(arguments, argument -> argument.getType()), + type); + return methodCall(receiver, methodName, arguments, signature); + } + + public static MethodCallNode methodCall( + Receiver receiver, + String methodName, + List<ExpressionNode> arguments, + MethodSignature signature) + { + return new MethodCallNode(receiver, methodName, arguments, signature); } private final Receiver receiver; private final String methodName; private final List<ExpressionNode> arguments; - private final Type type; + private final MethodSignature signature; private MethodCallNode( Receiver receiver, String methodName, List<ExpressionNode> arguments, - Type type) + MethodSignature signature) { this.receiver = receiver; this.methodName = methodName; this.arguments = arguments; - this.type = type; + this.signature = signature; } public Receiver getReceiver() { @@ -74,16 +116,14 @@ public class MethodCallNode implements ExpressionNode { public List<ExpressionNode> getArguments() { return arguments; } - + + @Override public Type getType() { - return type; + return signature.getReturnType(); } public MethodSignature signature() { - return new MethodSignature( - methodName, - eagerMap(arguments, argument -> argument.getType()), - type); + return signature; } @Override @@ -97,13 +137,13 @@ public class MethodCallNode implements ExpressionNode { transformer.transformReceiver(receiver), transformer.transformMethodName(signature()), transformer.transformExpressions(arguments), - transformer.transform(type)); + transformer.transform(signature)); } @Override public String toString() { return "MethodCallNode(receiver=" + receiver + ", methodName=" - + methodName + ", arguments=" + arguments + ", type=" + type + + methodName + ", arguments=" + arguments + ", signature=" + signature + ")"; } @@ -117,7 +157,7 @@ public class MethodCallNode implements ExpressionNode { + ((methodName == null) ? 0 : methodName.hashCode()); result = prime * result + ((receiver == null) ? 0 : receiver.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((signature == null) ? 0 : signature.hashCode()); return result; } @@ -145,10 +185,10 @@ public class MethodCallNode implements ExpressionNode { return false; } else if (!receiver.equals(other.receiver)) return false; - if (type == null) { - if (other.type != null) + if (signature == null) { + if (other.signature != null) return false; - } else if (!type.equals(other.type)) + } else if (!signature.equals(other.signature)) return false; return true; } diff --git a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java index 93d4f58..4cb04fb 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java @@ -5,6 +5,10 @@ import org.zwobble.couscous.ast.types.Type; import java.util.List; public class MethodSignature { + public static MethodSignature signature(String name, List<Type> arguments, Type returnType) { + return new MethodSignature(name, arguments, returnType); + } + private final String name; private final List<Type> arguments; private final Type returnType; diff --git a/src/main/java/org/zwobble/couscous/ast/types/TypeParameter.java b/src/main/java/org/zwobble/couscous/ast/types/TypeParameter.java index 0dee75e..9cda882 100644 --- a/src/main/java/org/zwobble/couscous/ast/types/TypeParameter.java +++ b/src/main/java/org/zwobble/couscous/ast/types/TypeParameter.java @@ -13,6 +13,10 @@ public class TypeParameter implements Type { this.name = name; } + public ScalarType getDeclaringType() { + return declaringType; + } + public String getName() { return name; } diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java index 38c5709..0998564 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java @@ -13,6 +13,8 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import static org.zwobble.couscous.util.ExtraLists.eagerMap; + public class NodeTransformer { public static NodeTransformer replaceExpressions(Map<ExpressionNode, ExpressionNode> replacements) { return builder(). @@ -197,6 +199,13 @@ public class NodeTransformer { this.transformMethodName = transformMethodName; } + public MethodSignature transform(MethodSignature signature) { + return new MethodSignature( + transformMethodName(signature), + eagerMap(signature.getArguments(), this::transform), + transform(signature.getReturnType())); + } + public Type transform(Type type) { return transformType.apply(type); } diff --git a/src/main/java/org/zwobble/couscous/backends/Names.java b/src/main/java/org/zwobble/couscous/backends/Names.java index 1e9600a..4adbec3 100644 --- a/src/main/java/org/zwobble/couscous/backends/Names.java +++ b/src/main/java/org/zwobble/couscous/backends/Names.java @@ -25,7 +25,7 @@ public class Names { @Override public String visit(TypeParameter parameter) { - return parameter.getName(); + return typeToString(parameter.getDeclaringType()) + "_" + parameter.getName(); } @Override diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java index 49e7b80..fc3aa98 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java @@ -39,6 +39,7 @@ import static org.zwobble.couscous.backends.python.ast.PythonReturnNode.pythonRe import static org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode.pythonStringLiteral; import static org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode.pythonVariableReference; import static org.zwobble.couscous.backends.python.ast.PythonWhileNode.pythonWhile; +import static org.zwobble.couscous.backends.python.ast.visitors.PythonExpressionStatement.pythonExpressionStatement; import static org.zwobble.couscous.util.Casts.tryCast; import static org.zwobble.couscous.util.ExtraLists.list; @@ -195,10 +196,10 @@ public class PythonCodeGenerator { @Override public PythonStatementNode visit(ExpressionStatementNode expressionStatement) { if (expressionStatement.getExpression() instanceof AssignmentNode) { - final org.zwobble.couscous.ast.AssignmentNode assignment = (AssignmentNode)expressionStatement.getExpression(); + AssignmentNode assignment = (AssignmentNode)expressionStatement.getExpression(); return pythonAssignment(assignment.getTarget().accept(EXPRESSION_GENERATOR), generateExpression(assignment.getValue())); } else { - throw new UnsupportedOperationException(); + return pythonExpressionStatement(generateExpression(expressionStatement.getExpression())); } } 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 d3771d3..7732a87 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java @@ -2,6 +2,7 @@ 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.PythonExpressionStatement; import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; public class PythonSerializer implements PythonNodeVisitor { @@ -101,7 +102,14 @@ public class PythonSerializer implements PythonNodeVisitor { writer.writeSpace(); writeParenthesised(operation.getRight(), operation); } - + + @Override + public void visit(PythonExpressionStatement statement) { + writer.writeStatement(() -> { + write(statement.getExpression()); + }); + } + @Override public void visit(PythonReturnNode pythonReturn) { writer.writeStatement(() -> { diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonExpressionStatement.java b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonExpressionStatement.java new file mode 100644 index 0000000..0ba1c38 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonExpressionStatement.java @@ -0,0 +1,25 @@ +package org.zwobble.couscous.backends.python.ast.visitors; + +import org.zwobble.couscous.backends.python.ast.PythonExpressionNode; +import org.zwobble.couscous.backends.python.ast.PythonStatementNode; + +public class PythonExpressionStatement implements PythonStatementNode { + public static PythonExpressionStatement pythonExpressionStatement(PythonExpressionNode expression) { + return new PythonExpressionStatement(expression); + } + + private final PythonExpressionNode expression; + + public PythonExpressionStatement(PythonExpressionNode expression) { + this.expression = expression; + } + + public PythonExpressionNode getExpression() { + return expression; + } + + @Override + public void accept(PythonNodeVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java index 8f04787..d43691d 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java @@ -13,7 +13,8 @@ public interface PythonNodeVisitor { void visit(PythonGetSliceNode getSlice); void visit(PythonNotNode notOperation); void visit(PythonBinaryOperation operation); - + + void visit(PythonExpressionStatement statement); void visit(PythonReturnNode pythonReturn); void visit(PythonPassNode pass); void visit(PythonClassNode pythonClass); @@ -24,5 +25,4 @@ public interface PythonNodeVisitor { void visit(PythonWhileNode whileLoop); void visit(PythonModuleNode module); - } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java index 096162f..46d2ab4 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -185,7 +185,6 @@ public class JavaExpressionReader { expression.resolveMethodBinding(), expression.arguments()); MethodSignature signature = JavaMethods.signature(expression.resolveMethodBinding()); - final Type type = signature.getReturnType(); IMethodBinding methodBinding = expression.resolveMethodBinding(); Type receiverType = typeOf(methodBinding.getDeclaringClass()); @@ -194,7 +193,7 @@ public class JavaExpressionReader { Types.erasure(receiverType), methodName, arguments, - type); + signature); } else { ExpressionNode receiver = expression.getExpression() == null ? ThisReferenceNode.thisReference(receiverType) @@ -203,7 +202,7 @@ public class JavaExpressionReader { receiver, methodName, arguments, - type); + signature); } } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java index 42211fe..0273faa 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaMethods.java @@ -34,10 +34,17 @@ class JavaMethods { eagerMap( argumentTypes, asList(erasedMethod.getParameterTypes()), - (argumentType, erasedParameterType) -> new BoundTypeParameter((TypeParameter) typeOf(erasedParameterType), argumentType)), - new BoundTypeParameter( - (TypeParameter) typeOf(erasedMethod.getReturnType()), - returnType)); + (argumentType, erasedParameterType) -> typeParameterForGeneric(erasedParameterType, argumentType)), + typeParameterForGeneric(erasedMethod.getReturnType(), returnType)); + } + } + + private static Type typeParameterForGeneric(ITypeBinding erasedTypeBinding, Type type) { + Type erasedType = typeOf(erasedTypeBinding); + if (erasedType.equals(type)) { + return type; + } else { + return new BoundTypeParameter((TypeParameter) typeOf(erasedTypeBinding), type); } } } diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java index 4afe02b..42d8f28 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -417,7 +417,7 @@ public class JavaReader { thisReference(type), methodNode.getName(), eagerMap(arguments, argument -> reference(argument)), - methodNode.getReturnType()), + methodNode.signature()), override.getReturnType())) ))); }); |
