aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodNode.java58
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java4
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java62
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java48
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java19
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraIterables.java47
6 files changed, 161 insertions, 77 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodNode.java b/src/main/java/org/zwobble/couscous/ast/MethodNode.java
index 024541f..8863619 100644
--- a/src/main/java/org/zwobble/couscous/ast/MethodNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/MethodNode.java
@@ -31,7 +31,9 @@ public class MethodNode implements Node {
private Type returnType = Types.VOID;
private final ImmutableList.Builder<StatementNode> body =
ImmutableList.builder();
-
+ private final ImmutableList.Builder<MethodSignature> overrides =
+ ImmutableList.builder();
+
public Builder(String name) {
this.name = name;
}
@@ -83,7 +85,8 @@ public class MethodNode implements Node {
name,
arguments.build(),
returnType,
- isAbstract ? Optional.empty() : Optional.of(body.build()));
+ isAbstract ? Optional.empty() : Optional.of(body.build()),
+ overrides.build());
}
}
@@ -93,9 +96,10 @@ public class MethodNode implements Node {
String name,
List<FormalArgumentNode> arguments,
Type returnType,
- Optional<List<StatementNode>> body)
+ Optional<List<StatementNode>> body,
+ List<MethodSignature> overrides)
{
- return new MethodNode(annotations, isStatic, name, arguments, returnType, body);
+ return new MethodNode(annotations, isStatic, name, arguments, returnType, body, overrides);
}
private final List<AnnotationNode> annotations;
@@ -104,14 +108,16 @@ public class MethodNode implements Node {
private final List<FormalArgumentNode> arguments;
private final Type returnType;
private final Optional<List<StatementNode>> body;
-
+ private final List<MethodSignature> overrides;
+
private MethodNode(
List<AnnotationNode> annotations,
boolean isStatic,
String name,
List<FormalArgumentNode> arguments,
Type returnType,
- Optional<List<StatementNode>> body)
+ Optional<List<StatementNode>> body,
+ List<MethodSignature> overrides)
{
this.annotations = annotations;
this.isStatic = isStatic;
@@ -119,6 +125,7 @@ public class MethodNode implements Node {
this.arguments = arguments;
this.returnType = returnType;
this.body = body;
+ this.overrides = overrides;
}
public List<AnnotationNode> getAnnotations() {
@@ -145,6 +152,10 @@ public class MethodNode implements Node {
return body;
}
+ public List<MethodSignature> getOverrides() {
+ return overrides;
+ }
+
public boolean isAbstract() {
return !body.isPresent();
}
@@ -157,7 +168,7 @@ public class MethodNode implements Node {
}
public MethodNode mapBody(Function<List<StatementNode>, List<StatementNode>> function) {
- return new MethodNode(annotations, isStatic, name, arguments, returnType, body.map(function));
+ return new MethodNode(annotations, isStatic, name, arguments, returnType, body.map(function), overrides);
}
@Override
@@ -172,19 +183,8 @@ public class MethodNode implements Node {
transformer.transformMethodName(signature()),
transformer.transformFormalArguments(arguments),
transformer.transform(returnType),
- body.map(transformer::transformStatements));
- }
-
- @Override
- public String toString() {
- return "MethodNode(" +
- "annotations=" + annotations +
- ", isStatic=" + isStatic +
- ", name=" + name +
- ", arguments=" + arguments +
- ", returnType=" + returnType +
- ", body=" + body +
- ')';
+ body.map(transformer::transformStatements),
+ eagerMap(overrides, transformer::transform));
}
@Override
@@ -199,7 +199,8 @@ public class MethodNode implements Node {
if (!name.equals(that.name)) return false;
if (!arguments.equals(that.arguments)) return false;
if (!returnType.equals(that.returnType)) return false;
- return body.equals(that.body);
+ if (!body.equals(that.body)) return false;
+ return overrides.equals(that.overrides);
}
@@ -211,6 +212,21 @@ public class MethodNode implements Node {
result = 31 * result + arguments.hashCode();
result = 31 * result + returnType.hashCode();
result = 31 * result + body.hashCode();
+ result = 31 * result + overrides.hashCode();
return result;
}
+
+ @Override
+ public String toString() {
+ return "MethodNode(" +
+ "annotations=" + annotations +
+ ", isStatic=" + isStatic +
+ ", name=" + name +
+ ", arguments=" + arguments +
+ ", returnType=" + returnType +
+ ", body=" + body +
+ ", overrides=" + overrides +
+ ')';
+ }
+
}
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 8bd8b11..00de205 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
@@ -17,6 +17,8 @@ import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
public class CsharpCodeGenerator {
+ public static final Naming NAMING = Naming.noMangling();
+
private final static Map<ScalarType, ScalarType> PRIMITIVES = ImmutableMap.<ScalarType, ScalarType>builder()
.put(Types.INT, ScalarType.of("int"))
.put(Types.STRING, ScalarType.of("string"))
@@ -29,7 +31,7 @@ public class CsharpCodeGenerator {
private final NodeTransformer nodeTransformer;
public static Node generateCode(Node node, String namespace) {
- return new CsharpCodeGenerator(Naming.signaturesContainSimpleNames(), namespace).generateCode(node);
+ return new CsharpCodeGenerator(NAMING, namespace).generateCode(node);
}
private CsharpCodeGenerator(Naming naming, String namespace) {
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 a6922e4..73e6ced 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
@@ -6,15 +6,17 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.ast.structure.NodeStructure;
-import org.zwobble.couscous.types.ScalarType;
-import org.zwobble.couscous.types.Type;
import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper;
import org.zwobble.couscous.ast.visitors.NodeMapperWithDefault;
import org.zwobble.couscous.ast.visitors.StatementNodeMapper;
import org.zwobble.couscous.backends.naming.Names;
import org.zwobble.couscous.backends.python.ast.*;
+import org.zwobble.couscous.types.ScalarType;
+import org.zwobble.couscous.types.Type;
import org.zwobble.couscous.types.Types;
-import org.zwobble.couscous.values.*;
+import org.zwobble.couscous.values.InternalCouscousValue;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.TypeValue;
import java.util.*;
import java.util.stream.Collectors;
@@ -23,8 +25,14 @@ import java.util.stream.Stream;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Iterators.singletonIterator;
-import static org.zwobble.couscous.backends.python.ast.PythonListNode.pythonList;
-import static org.zwobble.couscous.types.Types.erasure;
+import static java.util.Collections.emptyList;
+import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement;
+import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
+import static org.zwobble.couscous.ast.ReturnNode.returns;
+import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference;
+import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion;
+import static org.zwobble.couscous.ast.VariableDeclaration.var;
+import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.backends.python.ast.PythonAssignmentNode.pythonAssignment;
import static org.zwobble.couscous.backends.python.ast.PythonAttributeAccessNode.pythonAttributeAccess;
import static org.zwobble.couscous.backends.python.ast.PythonBooleanLiteralNode.pythonBooleanLiteral;
@@ -36,15 +44,17 @@ import static org.zwobble.couscous.backends.python.ast.PythonIfStatementNode.pyt
import static org.zwobble.couscous.backends.python.ast.PythonImportAliasNode.pythonImportAlias;
import static org.zwobble.couscous.backends.python.ast.PythonImportNode.pythonImport;
import static org.zwobble.couscous.backends.python.ast.PythonIntegerLiteralNode.pythonIntegerLiteral;
+import static org.zwobble.couscous.backends.python.ast.PythonListNode.pythonList;
import static org.zwobble.couscous.backends.python.ast.PythonModuleNode.pythonModule;
import static org.zwobble.couscous.backends.python.ast.PythonReturnNode.pythonReturn;
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.types.Types.erasure;
import static org.zwobble.couscous.util.Casts.tryCast;
-import static org.zwobble.couscous.util.ExtraLists.eagerMap;
-import static org.zwobble.couscous.util.ExtraLists.list;
+import static org.zwobble.couscous.util.ExtraIterables.*;
+import static org.zwobble.couscous.util.ExtraLists.*;
public class PythonCodeGenerator {
public static PythonModuleNode generateCode(TypeNode typeNode) {
@@ -63,9 +73,9 @@ public class PythonCodeGenerator {
.map(node -> generateStatements(node.getStaticConstructor()))
.orElse(list());
- Iterable<PythonFunctionDefinitionNode> pythonMethods = transform(
+ Iterable<PythonFunctionDefinitionNode> pythonMethods = lazyFlatMap(
filter(typeNode.getMethods(), method -> !method.isAbstract()),
- PythonCodeGenerator::generateFunction);
+ method -> generateMethods(typeNode.getName(), method));
PythonClassNode pythonClass = pythonClass(
typeNode.getName().getSimpleName(),
@@ -171,6 +181,40 @@ public class PythonCodeGenerator {
return pythonFunctionDefinition("__init__", ImmutableList.copyOf(argumentNames), new PythonBlock(pythonBody));
}
+ private static Iterable<PythonFunctionDefinitionNode> generateMethods(ScalarType type, MethodNode method) {
+ return lazyMap(
+ lazyCons(method, generateOverrideMethods(type, method)),
+ PythonCodeGenerator::generateFunction);
+ }
+
+ private static Iterable<MethodNode> generateOverrideMethods(ScalarType type, MethodNode methodNode) {
+ return transform(
+ methodNode.getOverrides(),
+ override -> {
+ List<FormalArgumentNode> arguments = eagerMapWithIndex(
+ override.getArguments(),
+ (argument, index) -> formalArg(var(null, "arg" + index, argument)));
+ MethodCallNode call = MethodCallNode.methodCall(
+ thisReference(type),
+ methodNode.getName(),
+ eagerMap(arguments, argument -> reference(argument)),
+ methodNode.signature());
+
+ StatementNode body = override.getReturnType().equals(Types.VOID)
+ ? expressionStatement(call)
+ : returns(typeCoercion(call, override.getReturnType()));
+
+ return MethodNode.method(
+ methodNode.getAnnotations(),
+ methodNode.isStatic(),
+ methodNode.getName(),
+ arguments,
+ override.getReturnType(),
+ Optional.of(list(body)),
+ emptyList());
+ });
+ }
+
private static PythonFunctionDefinitionNode generateFunction(MethodNode method) {
Iterable<String> explicitArgumentNames = transform(method.getArguments(), argument -> argument.getName());
Iterable<String> argumentNames = Iterables.concat(
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 fc93345..9055746 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -40,6 +40,7 @@ import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference;
import static org.zwobble.couscous.ast.TypeCoercionNode.typeCoercion;
import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariables;
+import static org.zwobble.couscous.frontends.java.JavaMethods.signature;
import static org.zwobble.couscous.frontends.java.JavaTypes.*;
import static org.zwobble.couscous.types.Types.erasure;
import static org.zwobble.couscous.util.Casts.tryCast;
@@ -155,14 +156,13 @@ public class JavaReader {
functionalInterfaceMethod.getName(),
lambda.getFormalArguments(),
typeOf(functionalInterfaceMethod.getReturnType()),
- Optional.of(lambda.getBody()));
-
- Iterable<MethodNode> overrides = generateOverrideMethods(name, functionalInterfaceMethod, scope, method);
+ Optional.of(lambda.getBody()),
+ overrides(functionalInterfaceMethod));
return new AnonymousClass(
superTypesAndSelf(functionalInterfaceMethod.getDeclaringClass()),
list(),
- ExtraLists.cons(method, overrides));
+ list(method));
}
private List<StatementNode> replaceCaptureReferences(
@@ -397,45 +397,14 @@ public class JavaReader {
methodName,
formalArguments,
returnType.get(),
- body);
+ body,
+ overrides(method.resolveBinding()));
builder.addMethod(methodNode);
-
- Iterable<MethodNode> overrideMethods = generateOverrideMethods(type, method.resolveBinding(), scope, methodNode);
-
- for (MethodNode overrideMethod : overrideMethods) {
- builder.addMethod(overrideMethod);
- }
}
}
- private Iterable<MethodNode> generateOverrideMethods(ScalarType type, IMethodBinding method, Scope scope, MethodNode methodNode) {
- return transform(
- filter(
- overrides(method),
- override -> !override.equals(methodNode.signature())),
- override -> {
- List<FormalArgumentNode> arguments = eagerMapWithIndex(override.getArguments(), (argument, index) -> scope.formalArgument("arg" + index, argument));
- MethodCallNode call = MethodCallNode.methodCall(
- thisReference(type),
- methodNode.getName(),
- eagerMap(arguments, argument -> reference(argument)),
- methodNode.signature());
-
- StatementNode body = override.getReturnType().equals(Types.VOID)
- ? expressionStatement(call)
- : returns(typeCoercion(call, override.getReturnType()));
-
- return MethodNode.method(
- methodNode.getAnnotations(),
- methodNode.isStatic(),
- methodNode.getName(),
- arguments,
- override.getReturnType(),
- Optional.of(list(body)));
- });
- }
-
- private Iterable<MethodSignature> overrides(IMethodBinding methodBinding) {
+ private List<MethodSignature> overrides(IMethodBinding methodBinding) {
+ MethodSignature overrideSignature = signature(methodBinding);
ITypeBinding declaringClass = methodBinding.getDeclaringClass();
// TODO: remove duplication with JavaTypes
@@ -444,6 +413,7 @@ public class JavaReader {
.stream()
.flatMap(type -> asList(type.getDeclaredMethods()).stream().filter(superMethod -> methodBinding.overrides(superMethod)))
.map(JavaMethods::signature)
+ .filter(signature -> !overrideSignature.equals(signature))
.collect(Collectors.toList());
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
index c26fb32..b8c007b 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
@@ -19,10 +19,10 @@ import java.util.Set;
import static com.google.common.collect.Iterables.filter;
import static org.zwobble.couscous.types.ParameterizedType.parameterizedType;
import static org.zwobble.couscous.util.Casts.tryCast;
-import static org.zwobble.couscous.util.ExtraLists.eagerMap;
-import static org.zwobble.couscous.util.ExtraLists.list;
-import static org.zwobble.couscous.util.ExtraMaps.map;
-import static org.zwobble.couscous.util.ExtraMaps.toMapWithKeys;
+import static org.zwobble.couscous.util.ExtraIterables.lazyFlatMap;
+import static org.zwobble.couscous.util.ExtraIterables.lazyMap;
+import static org.zwobble.couscous.util.ExtraLists.*;
+import static org.zwobble.couscous.util.ExtraMaps.*;
public class UserDefinedInterpreterType implements InterpreterType {
private final TypeNode type;
@@ -34,9 +34,14 @@ public class UserDefinedInterpreterType implements InterpreterType {
this.fields = tryCast(ClassNode.class, type)
.map(classNode -> toMapWithKeys(classNode.getFields(), FieldDeclarationNode::getName))
.orElse(map());
- this.methods = toMapWithKeys(
- filter(type.getMethods(), method -> !method.isAbstract()),
- method -> method.signature().generic());
+
+ Iterable<MethodNode> concreteMethods = filter(type.getMethods(), method -> !method.isAbstract());
+
+ Iterable<Map.Entry<MethodSignature, MethodNode>> entries = lazyFlatMap(concreteMethods, method -> {
+ List<MethodSignature> signatures = cons(method.signature(), method.getOverrides());
+ return lazyMap(signatures, signature -> entry(signature.generic(), method));
+ });
+ this.methods = toMap(entries);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraIterables.java b/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
index 1fd9fca..cd9b3df 100644
--- a/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
+++ b/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
@@ -1,7 +1,14 @@
package org.zwobble.couscous.util;
+import com.google.common.collect.Iterables;
+
import java.util.Iterator;
import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import static org.zwobble.couscous.util.ExtraLists.list;
public class ExtraIterables {
private ExtraIterables() {}
@@ -69,4 +76,44 @@ public class ExtraIterables {
}
};
}
+
+ public static <T> Iterable<T> lazyCons(T head, Iterable<T> tails) {
+ return Iterables.concat(list(head), tails);
+ }
+
+ public static <T, R> Iterable<R> lazyMap(Iterable<T> iterable, Function<T, R> function) {
+ return new Iterable<R>() {
+ @Override
+ public Iterator<R> iterator() {
+ return map(iterable.iterator(), function);
+ }
+ };
+ }
+
+ private static <T, R> Iterator<R> map(Iterator<T> iterator, Function<T, R> function) {
+ return new Iterator<R>() {
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public R next() {
+ return function.apply(iterator.next());
+ }
+ };
+ }
+
+ public static <T, R> Iterable<R> lazyFlatMap(Iterable<T> iterable, Function<T, Iterable<R>> function) {
+ return new Iterable<R>() {
+ @Override
+ public Iterator<R> iterator() {
+ return stream(iterable).flatMap(element -> stream(function.apply(element))).iterator();
+ }
+ };
+ }
+
+ public static <T> Stream<T> stream(Iterable<T> iterable) {
+ return StreamSupport.stream(iterable.spliterator(), false);
+ }
}