aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-01-01 20:00:02 +0000
committerMichael Williamson <mike@zwobble.org>2016-01-01 20:01:19 +0000
commitd5a4fb60e3b62f4dc1b67c83cd62c1a264bb4a12 (patch)
treecc5e2dfaf6468370a841e41dd91285b76e6cfd2f
parent4fd8b4132fd8f49b5368b86ebdbcdb84a0bdf7d0 (diff)
Generate variable IDs without Eclipse keys
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java3
-rw-r--r--src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java3
-rw-r--r--src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java10
-rw-r--r--src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java3
-rw-r--r--src/main/java/org/zwobble/couscous/ast/identifiers/Identifier.java44
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java10
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java18
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaLambdaExpressionReader.java22
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java178
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java25
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaVariableDeclarationReader.java8
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/Scope.java91
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/UniqueIdentifiers.java17
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Environment.java11
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/UnboundVariable.java8
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/VariableNotInScope.java8
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraMaps.java18
-rw-r--r--src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java8
-rw-r--r--src/test/java/org/zwobble/couscous/tests/TestIds.java8
-rw-r--r--src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java7
-rw-r--r--src/test/java/org/zwobble/couscous/tests/frontends/java/FreeVariablesTests.java7
-rw-r--r--src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java1
22 files changed, 331 insertions, 177 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
index 9be591c..b41c972 100644
--- a/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
+++ b/src/main/java/org/zwobble/couscous/ast/ClassNodeBuilder.java
@@ -1,6 +1,7 @@
package org.zwobble.couscous.ast;
import com.google.common.collect.ImmutableList;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import java.util.Optional;
import java.util.function.Function;
@@ -110,7 +111,7 @@ public class ClassNodeBuilder {
return ThisReferenceNode.thisReference(name);
}
- public MethodBuilder<T> argument(String id, String name, TypeName type) {
+ public MethodBuilder<T> argument(Identifier id, String name, TypeName type) {
arguments.add(formalArg(var(id, name, type)));
return this;
}
diff --git a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java
index 3499e26..a165070 100644
--- a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java
@@ -1,5 +1,6 @@
package org.zwobble.couscous.ast;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import org.zwobble.couscous.ast.visitors.StatementNodeMapper;
import java.util.function.Function;
@@ -8,7 +9,7 @@ import static org.zwobble.couscous.ast.VariableDeclaration.var;
public class LocalVariableDeclarationNode implements VariableNode, StatementNode {
public static LocalVariableDeclarationNode localVariableDeclaration(
- String id,
+ Identifier id,
String name,
TypeName type,
ExpressionNode initialValue) {
diff --git a/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java b/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java
index 713f3a6..5932371 100644
--- a/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java
+++ b/src/main/java/org/zwobble/couscous/ast/VariableDeclaration.java
@@ -1,21 +1,23 @@
package org.zwobble.couscous.ast;
+import org.zwobble.couscous.ast.identifiers.Identifier;
+
public class VariableDeclaration {
- public static VariableDeclaration var(String id, String name, TypeName type) {
+ public static VariableDeclaration var(Identifier id, String name, TypeName type) {
return new VariableDeclaration(id, name, type);
}
- private final String id;
+ private final Identifier id;
private final String name;
private final TypeName type;
- private VariableDeclaration(String id, String name, TypeName type) {
+ private VariableDeclaration(Identifier id, String name, TypeName type) {
this.id = id;
this.name = name;
this.type = type;
}
- public String getId() {
+ public Identifier getId() {
return id;
}
diff --git a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
index b576389..50462e9 100644
--- a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
@@ -1,5 +1,6 @@
package org.zwobble.couscous.ast;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import org.zwobble.couscous.ast.visitors.AssignableExpressionNodeVisitor;
import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper;
@@ -34,7 +35,7 @@ public class VariableReferenceNode implements AssignableExpressionNode {
return this;
}
- public String getReferentId() {
+ public Identifier getReferentId() {
return referent.getId();
}
diff --git a/src/main/java/org/zwobble/couscous/ast/identifiers/Identifier.java b/src/main/java/org/zwobble/couscous/ast/identifiers/Identifier.java
new file mode 100644
index 0000000..29a33eb
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/ast/identifiers/Identifier.java
@@ -0,0 +1,44 @@
+package org.zwobble.couscous.ast.identifiers;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+public class Identifier {
+ public static final Identifier TOP = new Identifier(ImmutableList.of());
+
+ private final List<String> parts;
+
+ private Identifier(List<String> parts) {
+ this.parts = parts;
+ }
+
+ public Identifier extend(String name) {
+ ImmutableList.Builder<String> parts = ImmutableList.builder();
+ parts.addAll(this.parts);
+ parts.add(name);
+ return new Identifier(parts.build());
+ }
+
+ @Override
+ public String toString() {
+ return "Identifier(" +
+ "parts=" + parts +
+ ')';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Identifier that = (Identifier) o;
+
+ return parts.equals(that.parts);
+ }
+
+ @Override
+ public int hashCode() {
+ return parts.hashCode();
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java
index d07d1de..8780082 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionMethodReferenceReader.java
@@ -10,18 +10,16 @@ import org.zwobble.couscous.ast.sugar.Lambda;
import java.util.List;
-import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
import static org.zwobble.couscous.ast.ReturnNode.returns;
import static org.zwobble.couscous.ast.StaticMethodCallNode.staticMethodCall;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
import static org.zwobble.couscous.ast.sugar.Lambda.lambda;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
public class JavaExpressionMethodReferenceReader {
- public static Lambda javaExpressionMethodReferenceToLambda(ExpressionMethodReference expression) {
+ public static Lambda expressionMethodReferenceToLambda(Scope scope, ExpressionMethodReference expression) {
IMethodBinding functionalInterfaceMethod = expression.resolveTypeBinding().getFunctionalInterfaceMethod();
- List<FormalArgumentNode> formalArguments = formalArguments(functionalInterfaceMethod);
+ List<FormalArgumentNode> formalArguments = formalArguments(scope, functionalInterfaceMethod);
return lambda(
formalArguments,
@@ -34,13 +32,13 @@ public class JavaExpressionMethodReferenceReader {
typeOf(expression.resolveMethodBinding().getReturnType()))))));
}
- private static List<FormalArgumentNode> formalArguments(IMethodBinding functionalInterfaceMethod) {
+ private static List<FormalArgumentNode> formalArguments(Scope scope, IMethodBinding functionalInterfaceMethod) {
ImmutableList.Builder<FormalArgumentNode> arguments = ImmutableList.builder();
ITypeBinding[] parameterTypes = functionalInterfaceMethod.getParameterTypes();
for (int index = 0; index < parameterTypes.length; index++) {
ITypeBinding parameterType = parameterTypes[index];
- arguments.add(formalArg(var("arg" + index, "arg" + index, typeOf(parameterType))));
+ arguments.add(scope.formalArgument("arg" + index, typeOf(parameterType)));
}
return arguments.build();
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 2c0ab22..15a910c 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
@@ -14,17 +14,17 @@ import static java.util.Arrays.asList;
import static org.zwobble.couscous.ast.ConstructorCallNode.constructorCall;
import static org.zwobble.couscous.ast.LiteralNode.literal;
import static org.zwobble.couscous.ast.MethodCallNode.not;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
-import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.concat;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
public class JavaExpressionReader {
+ private final Scope scope;
private final JavaReader javaReader;
- JavaExpressionReader(JavaReader javaReader) {
+ JavaExpressionReader(Scope scope, JavaReader javaReader) {
+ this.scope = scope;
this.javaReader = javaReader;
}
@@ -139,7 +139,7 @@ public class JavaExpressionReader {
return literal(expression.getLiteralValue());
}
- private static ExpressionNode readSimpleName(SimpleName expression) {
+ private ExpressionNode readSimpleName(SimpleName expression) {
IBinding binding = expression.resolveBinding();
if (binding.getKind() == IBinding.VARIABLE) {
return readVariableBinding((IVariableBinding)binding);
@@ -148,10 +148,10 @@ public class JavaExpressionReader {
}
}
- private static ExpressionNode readVariableBinding(IVariableBinding binding) {
+ private ExpressionNode readVariableBinding(IVariableBinding binding) {
TypeName type = typeOf(binding);
if (binding.getDeclaringClass() == null) {
- return reference(var(binding.getKey(), binding.getName(), type));
+ return scope.reference(binding.getKey());
} else {
return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type);
}
@@ -201,7 +201,7 @@ public class JavaExpressionReader {
if (constructor.getDeclaringClass().isAnonymous()) {
GeneratedClosure closure =
- javaReader.readAnonymousClass(expression.getAnonymousClassDeclaration());
+ javaReader.readAnonymousClass(scope, expression.getAnonymousClassDeclaration());
return constructorCall(
closure.getType(),
concat(captureArguments(closure), arguments));
@@ -211,14 +211,14 @@ public class JavaExpressionReader {
}
private ExpressionNode readLambdaExpression(LambdaExpression expression) {
- GeneratedClosure closure = javaReader.readLambda(expression);
+ GeneratedClosure closure = javaReader.readLambda(scope, expression);
return constructorCall(
closure.getType(),
captureArguments(closure));
}
private ExpressionNode readExpressionMethodReference(ExpressionMethodReference expression) {
- GeneratedClosure closure = javaReader.readExpressionMethodReference(expression);
+ GeneratedClosure closure = javaReader.readExpressionMethodReference(scope, expression);
return constructorCall(
closure.getType(),
captureArguments(closure));
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaLambdaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaLambdaExpressionReader.java
index 44a0f2d..c8b5f4c 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaLambdaExpressionReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaLambdaExpressionReader.java
@@ -10,9 +10,7 @@ import java.util.List;
import java.util.Optional;
import static java.util.Arrays.asList;
-import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
import static org.zwobble.couscous.ast.ReturnNode.returns;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
import static org.zwobble.couscous.ast.sugar.Lambda.lambda;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
@@ -24,35 +22,35 @@ public class JavaLambdaExpressionReader {
this.reader = reader;
}
- public Lambda javaLambdaToLambda(LambdaExpression expression) {
+ public Lambda toLambda(Scope scope, LambdaExpression expression) {
List<FormalArgumentNode> formalArguments = eagerMap(
(List<?>)expression.parameters(),
- this::readLambdaExpressionParameter);
+ parameter -> readLambdaExpressionParameter(scope, parameter));
- return lambda(formalArguments, readLambdaExpressionBody(expression));
+ return lambda(formalArguments, readLambdaExpressionBody(scope, expression));
}
- private FormalArgumentNode readLambdaExpressionParameter(Object parameter) {
+ private FormalArgumentNode readLambdaExpressionParameter(Scope scope, Object parameter) {
if (parameter instanceof SingleVariableDeclaration) {
- return JavaVariableDeclarationReader.read((SingleVariableDeclaration) parameter);
+ return JavaVariableDeclarationReader.read(scope, (SingleVariableDeclaration) parameter);
} else {
VariableDeclarationFragment fragment = (VariableDeclarationFragment)parameter;
- return formalArg(var(
+ return scope.formalArgument(
fragment.resolveBinding().getKey(),
fragment.getName().getIdentifier(),
- typeOf(fragment.resolveBinding().getType())));
+ typeOf(fragment.resolveBinding().getType()));
}
}
- private List<StatementNode> readLambdaExpressionBody(LambdaExpression expression) {
+ private List<StatementNode> readLambdaExpressionBody(Scope scope, LambdaExpression expression) {
TypeName returnType = typeOf(expression.resolveTypeBinding().getFunctionalInterfaceMethod().getReturnType());
if (expression.getBody() instanceof Block) {
@SuppressWarnings("unchecked")
List<Statement> statements = ((Block) expression.getBody()).statements();
- return reader.readStatements(statements, Optional.of(returnType));
+ return reader.readStatements(scope, statements, Optional.of(returnType));
} else {
Expression body = (Expression) expression.getBody();
- return asList(returns(reader.readExpression(returnType, body)));
+ return asList(returns(reader.readExpression(scope, returnType, body)));
}
}
}
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 4efd0bf..86ad12d 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -5,6 +5,7 @@ import com.google.common.collect.Maps;
import org.eclipse.jdt.core.dom.*;
import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.ast.VariableDeclaration;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import org.zwobble.couscous.ast.sugar.Lambda;
import org.zwobble.couscous.util.ExtraLists;
@@ -18,6 +19,7 @@ import java.util.function.Function;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Maps.immutableEntry;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.zwobble.couscous.ast.AnnotationNode.annotation;
@@ -27,13 +29,13 @@ import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess;
import static org.zwobble.couscous.ast.FieldDeclarationNode.field;
import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
import static org.zwobble.couscous.ast.ThisReferenceNode.thisReference;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariables;
-import static org.zwobble.couscous.frontends.java.JavaExpressionMethodReferenceReader.javaExpressionMethodReferenceToLambda;
+import static org.zwobble.couscous.frontends.java.JavaExpressionMethodReferenceReader.expressionMethodReferenceToLambda;
import static org.zwobble.couscous.frontends.java.JavaTypes.*;
import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraLists.*;
+import static org.zwobble.couscous.util.ExtraMaps.toMap;
public class JavaReader {
public static List<ClassNode> readClassFromFile(Path root, Path sourcePath) throws IOException {
@@ -46,7 +48,6 @@ public class JavaReader {
return cons(reader.readCompilationUnit(ast), reader.classes.build());
}
- private final UniqueIdentifiers identifiers = new UniqueIdentifiers();
private final ImmutableList.Builder<ClassNode> classes;
private int anonymousClassCount = 0;
@@ -56,8 +57,9 @@ public class JavaReader {
private ClassNode readCompilationUnit(CompilationUnit ast) {
TypeName name = generateClassName(ast);
+ Scope scope = Scope.create().enterClass(name);
TypeDeclaration type = (TypeDeclaration)ast.types().get(0);
- TypeDeclarationBody body = readTypeDeclarationBody(type.bodyDeclarations());
+ TypeDeclarationBody body = readTypeDeclarationBody(scope, type.bodyDeclarations());
return ClassNode.declareClass(
name,
superTypes(type),
@@ -66,28 +68,27 @@ public class JavaReader {
body.getMethods());
}
- GeneratedClosure readExpressionMethodReference(ExpressionMethodReference expression) {
+ GeneratedClosure readExpressionMethodReference(Scope outerScope, ExpressionMethodReference expression) {
+ TypeName name = generateAnonymousName(expression);
+ Scope scope = outerScope.enterClass(name);
return generateClosure(
- expression,
+ scope,
+ name,
expression.resolveTypeBinding().getFunctionalInterfaceMethod(),
- javaExpressionMethodReferenceToLambda(expression));
- }
-
- private ITypeBinding findDeclaringClass(ASTNode node) {
- while (!(node instanceof AbstractTypeDeclaration)) {
- node = node.getParent();
- }
- return ((AbstractTypeDeclaration)node).resolveBinding();
+ expressionMethodReferenceToLambda(scope, expression));
}
- GeneratedClosure readLambda(LambdaExpression expression) {
+ GeneratedClosure readLambda(Scope outerScope, LambdaExpression expression) {
+ TypeName name = generateAnonymousName(expression);
+ Scope scope = outerScope.enterClass(name);
return generateClosure(
- expression,
+ scope,
+ name,
expression.resolveTypeBinding().getFunctionalInterfaceMethod(),
- new JavaLambdaExpressionReader(this).javaLambdaToLambda(expression));
+ new JavaLambdaExpressionReader(this).toLambda(scope, expression));
}
- GeneratedClosure generateClosure(ASTNode node, IMethodBinding functionalInterfaceMethod, Lambda lambda) {
+ GeneratedClosure generateClosure(Scope scope, TypeName name, IMethodBinding functionalInterfaceMethod, Lambda lambda) {
MethodNode method = MethodNode.method(
emptyList(),
false,
@@ -96,7 +97,8 @@ public class JavaReader {
lambda.getBody());
GeneratedClosure closure = classWithCapture(
- generateAnonymousClassName(findDeclaringClass(node)),
+ scope,
+ name,
superTypesAndSelf(functionalInterfaceMethod.getDeclaringClass()),
emptyList(),
ImmutableList.of(method));
@@ -110,7 +112,7 @@ public class JavaReader {
List<StatementNode> body,
List<VariableDeclaration> freeVariables)
{
- Map<String, ExpressionNode> freeVariablesById = Maps.transformValues(
+ Map<Identifier, ExpressionNode> freeVariablesById = Maps.transformValues(
Maps.uniqueIndex(freeVariables, VariableDeclaration::getId),
freeVariable -> captureAccess(className, freeVariable));
Function<ExpressionNode, ExpressionNode> replaceExpression = new CaptureReplacer(freeVariablesById);
@@ -118,9 +120,9 @@ public class JavaReader {
}
private class CaptureReplacer implements Function<ExpressionNode, ExpressionNode> {
- private final Map<String, ExpressionNode> freeVariablesById;
+ private final Map<Identifier, ExpressionNode> freeVariablesById;
- public CaptureReplacer(Map<String, ExpressionNode> freeVariablesById) {
+ public CaptureReplacer(Map<Identifier, ExpressionNode> freeVariablesById) {
this.freeVariablesById = freeVariablesById;
}
@@ -132,16 +134,22 @@ public class JavaReader {
}
}
- private ConstructorNode buildConstructor(TypeName type, List<VariableDeclaration> freeVariables) {
- Map<String, VariableDeclaration> argumentDeclarationsById = Maps.transformValues(
- Maps.uniqueIndex(freeVariables, VariableDeclaration::getId),
- freeVariable -> var(identifiers.generate(freeVariable.getId() + "__capture"), freeVariable.getName(), freeVariable.getType()));
+ private ConstructorNode buildConstructor(Scope outerScope, TypeName type, List<VariableDeclaration> freeVariables) {
+ Scope scope = outerScope.enterConstructor();
+ Map<Identifier, VariableDeclaration> argumentDeclarationsById = toMap(
+ freeVariables,
+ freeVariable -> immutableEntry(
+ freeVariable.getId(),
+ scope.generateVariable(freeVariable.getName(), freeVariable.getType())));
+
List<FormalArgumentNode> arguments = eagerMap(
freeVariables,
freeVariable -> formalArg(argumentDeclarationsById.get(freeVariable.getId())));
+
List<StatementNode> body = eagerMap(freeVariables, freeVariable -> assignStatement(
captureAccess(type, freeVariable),
reference(argumentDeclarationsById.get(freeVariable.getId()))));
+
return constructor(arguments, body);
}
@@ -149,10 +157,12 @@ public class JavaReader {
return fieldAccess(thisReference(type), freeVariable.getName(), freeVariable.getType());
}
- GeneratedClosure readAnonymousClass(AnonymousClassDeclaration declaration) {
- TypeName className = generateClassName(declaration);
- TypeDeclarationBody bodyDeclarations = readTypeDeclarationBody(declaration.bodyDeclarations());
+ GeneratedClosure readAnonymousClass(Scope outerScope, AnonymousClassDeclaration declaration) {
+ TypeName className = generateAnonymousName(declaration);
+ Scope scope = outerScope.enterClass(className);
+ TypeDeclarationBody bodyDeclarations = readTypeDeclarationBody(scope, declaration.bodyDeclarations());
GeneratedClosure closure = classWithCapture(
+ scope,
className,
superTypes(declaration),
bodyDeclarations.getFields(),
@@ -162,6 +172,7 @@ public class JavaReader {
}
private GeneratedClosure classWithCapture(
+ Scope scope,
TypeName className,
Set<TypeName> superTypes,
List<FieldDeclarationNode> declaredFields,
@@ -178,24 +189,27 @@ public class JavaReader {
className,
superTypes,
fields,
- buildConstructor(className, freeVariables),
+ buildConstructor(scope, className, freeVariables),
eagerMap(methods, method ->
method.mapBody(body -> replaceCaptureReferences(className, body, freeVariables))));
return new GeneratedClosure(classNode, freeVariables);
}
- private TypeName generateClassName(AnonymousClassDeclaration declaration) {
- ITypeBinding type = declaration.resolveBinding();
- return generateAnonymousClassName(type);
- }
-
- private TypeName generateAnonymousClassName(ITypeBinding type) {
+ private TypeName generateAnonymousName(ASTNode node) {
+ ITypeBinding type = findDeclaringClass(node);
while (type.isAnonymous()) {
type = type.getDeclaringClass();
}
return TypeName.of(type.getQualifiedName() + "_Anonymous_" + (anonymousClassCount++));
}
+ private ITypeBinding findDeclaringClass(ASTNode node) {
+ while (!(node instanceof AbstractTypeDeclaration)) {
+ node = node.getParent();
+ }
+ return ((AbstractTypeDeclaration)node).resolveBinding();
+ }
+
private static class TypeDeclarationBody {
private final List<FieldDeclarationNode> fields;
private final ConstructorNode constructor;
@@ -220,11 +234,11 @@ public class JavaReader {
}
}
- private TypeDeclarationBody readTypeDeclarationBody(List<Object> bodyDeclarations) {
+ private TypeDeclarationBody readTypeDeclarationBody(Scope scope, List<Object> bodyDeclarations) {
ImmutableList.Builder<MethodNode> methods = ImmutableList.builder();
ConstructorNode constructor = ConstructorNode.DEFAULT;
- for (CallableNode callable : readMethods(ofType(bodyDeclarations, MethodDeclaration.class))) {
+ for (CallableNode callable : readMethods(scope, ofType(bodyDeclarations, MethodDeclaration.class))) {
if (callable instanceof ConstructorNode) {
constructor = (ConstructorNode) callable;
} else {
@@ -249,81 +263,61 @@ public class JavaReader {
field(fragment.getName().getIdentifier(), type));
}
- private List<CallableNode> readMethods(List<MethodDeclaration> methods) {
- return eagerMap(methods, this::readMethod);
+ private List<CallableNode> readMethods(Scope scope, List<MethodDeclaration> methods) {
+ return eagerMap(methods, method -> readMethod(scope, method));
}
- private CallableNode readMethod(MethodDeclaration method) {
- FunctionDeclaration function = functionDeclaration(method);
+ private CallableNode readMethod(Scope outerScope, MethodDeclaration method) {
+ Scope scope = outerScope.enterMethod(method.getName().getIdentifier());
+
+ List<FormalArgumentNode> formalArguments = readFormalArguments(scope, method);
+ List<StatementNode> body = readBody(scope, method);
+ List<AnnotationNode> annotations = readAnnotations(method);
+
if (method.isConstructor()) {
return constructor(
- function.getFormalArguments(),
- function.getBody());
+ formalArguments,
+ body);
} else {
return MethodNode.method(
- function.getAnnotations(),
+ annotations,
Modifier.isStatic(method.getModifiers()),
method.getName().getIdentifier(),
- function.getFormalArguments(),
- function.getBody());
+ formalArguments,
+ body);
}
}
- private FunctionDeclaration functionDeclaration(MethodDeclaration method) {
- @SuppressWarnings("unchecked")
- List<SingleVariableDeclaration> parameters = method.parameters();
- List<FormalArgumentNode> formalArguments = eagerMap(parameters, JavaVariableDeclarationReader::read);
- @SuppressWarnings("unchecked")
- List<Statement> statements = method.getBody().statements();
- Optional<TypeName> returnType = Optional.ofNullable(method.getReturnType2())
- .map(Type::resolveBinding)
- .map(JavaTypes::typeOf);
-
- return new FunctionDeclaration(
- eagerMap(asList(method.resolveBinding().getAnnotations()), this::readAnnotation),
- formalArguments,
- readStatements(statements, returnType));
+ private List<AnnotationNode> readAnnotations(MethodDeclaration method) {
+ return eagerMap(asList(method.resolveBinding().getAnnotations()), this::readAnnotation);
}
private AnnotationNode readAnnotation(IAnnotationBinding annotationBinding) {
return annotation(typeOf(annotationBinding.getAnnotationType()));
}
- private class FunctionDeclaration {
- private final List<AnnotationNode> annotations;
- private final List<FormalArgumentNode> formalArguments;
- private final List<StatementNode> body;
-
- private FunctionDeclaration(
- List<AnnotationNode> annotations,
- List<FormalArgumentNode> formalArguments,
- List<StatementNode> body)
- {
- this.annotations = annotations;
- this.formalArguments = formalArguments;
- this.body = body;
- }
-
- public List<AnnotationNode> getAnnotations() {
- return annotations;
- }
-
- public List<FormalArgumentNode> getFormalArguments() {
- return formalArguments;
- }
+ private List<FormalArgumentNode> readFormalArguments(Scope scope, MethodDeclaration method) {
+ @SuppressWarnings("unchecked")
+ List<SingleVariableDeclaration> parameters = method.parameters();
+ return eagerMap(parameters, parameter -> JavaVariableDeclarationReader.read(scope, parameter));
+ }
- public List<StatementNode> getBody() {
- return body;
- }
+ private List<StatementNode> readBody(Scope scope, MethodDeclaration method) {
+ @SuppressWarnings("unchecked")
+ List<Statement> statements = method.getBody().statements();
+ Optional<TypeName> returnType = Optional.ofNullable(method.getReturnType2())
+ .map(Type::resolveBinding)
+ .map(JavaTypes::typeOf);
+ return readStatements(scope, statements, returnType);
}
- List<StatementNode> readStatements(List<Statement> body, Optional<TypeName> returnType) {
- JavaStatementReader statementReader = new JavaStatementReader(expressionReader(), returnType);
+ List<StatementNode> readStatements(Scope scope, List<Statement> body, Optional<TypeName> returnType) {
+ JavaStatementReader statementReader = new JavaStatementReader(scope, expressionReader(scope), returnType);
return eagerFlatMap(body, statementReader::readStatement);
}
- ExpressionNode readExpression(TypeName targetType, Expression body) {
- return expressionReader().readExpression(targetType, body);
+ ExpressionNode readExpression(Scope scope, TypeName targetType, Expression body) {
+ return expressionReader(scope).readExpression(targetType, body);
}
private TypeName generateClassName(CompilationUnit ast) {
@@ -333,7 +327,7 @@ public class JavaReader {
return TypeName.of(packageName + "." + className);
}
- private JavaExpressionReader expressionReader() {
- return new JavaExpressionReader(this);
+ private JavaExpressionReader expressionReader(Scope scope) {
+ return new JavaExpressionReader(scope, this);
}
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
index 725882f..6a12a72 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
@@ -10,16 +10,21 @@ import java.util.stream.Collectors;
import static java.util.Arrays.asList;
import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement;
-import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration;
import static org.zwobble.couscous.ast.WhileNode.whileLoop;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.*;
class JavaStatementReader {
+ private final Scope scope;
private final JavaExpressionReader expressionReader;
private final Optional<TypeName> returnType;
- JavaStatementReader(JavaExpressionReader expressionReader, Optional<TypeName> returnType) {
+ JavaStatementReader(
+ Scope scope,
+ JavaExpressionReader expressionReader,
+ Optional<TypeName> returnType
+ ) {
+ this.scope = scope;
this.expressionReader = expressionReader;
this.returnType = returnType;
}
@@ -108,13 +113,15 @@ class JavaStatementReader {
return readDeclarationFragments(fragments, type);
}
- private List<StatementNode> readDeclarationFragments(List<VariableDeclarationFragment> fragments, TypeName type) {
- return eagerMap(fragments, fragment ->
- localVariableDeclaration(
- fragment.resolveBinding().getKey(),
- fragment.getName().getIdentifier(),
- type,
- readExpression(type, fragment.getInitializer())));
+ private List<StatementNode> readDeclarationFragments(
+ List<VariableDeclarationFragment> fragments,
+ TypeName type
+ ) {
+ return eagerMap(fragments, fragment -> scope.localVariable(
+ fragment.resolveBinding().getKey(),
+ fragment.getName().getIdentifier(),
+ type,
+ readExpression(type, fragment.getInitializer())));
}
private ExpressionNode readExpressionWithoutBoxing(Expression expression) {
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaVariableDeclarationReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaVariableDeclarationReader.java
index 992475d..812e5d4 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaVariableDeclarationReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaVariableDeclarationReader.java
@@ -3,15 +3,13 @@ package org.zwobble.couscous.frontends.java;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.zwobble.couscous.ast.FormalArgumentNode;
-import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
class JavaVariableDeclarationReader {
- static FormalArgumentNode read(SingleVariableDeclaration parameter) {
- return formalArg(var(
+ static FormalArgumentNode read(Scope scope, SingleVariableDeclaration parameter) {
+ return scope.formalArgument(
parameter.resolveBinding().getKey(),
parameter.getName().getIdentifier(),
- typeOf(parameter.resolveBinding())));
+ typeOf(parameter.resolveBinding()));
}
}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/Scope.java b/src/main/java/org/zwobble/couscous/frontends/java/Scope.java
new file mode 100644
index 0000000..caf0a96
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/frontends/java/Scope.java
@@ -0,0 +1,91 @@
+package org.zwobble.couscous.frontends.java;
+
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.identifiers.Identifier;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class Scope {
+ public static Scope create() {
+ return new Scope(new HashMap<>(), new HashSet<>(), Identifier.TOP);
+ }
+
+ private final Map<String, VariableDeclaration> variablesByKey;
+ private final Set<Identifier> identifiers;
+ private final Identifier identifier;
+
+ private Scope(Map<String, VariableDeclaration> variablesByKey, Set<Identifier> identifiers, Identifier identifier) {
+ this.variablesByKey = variablesByKey;
+ this.identifiers = identifiers;
+ this.identifier = identifier;
+ }
+
+ public Scope enterClass(TypeName className) {
+ return new Scope(variablesByKey, identifiers, identifier.extend("class#" + className.getQualifiedName()));
+ }
+
+ public Scope enterConstructor() {
+ return new Scope(variablesByKey, identifiers, identifier.extend("constructor"));
+ }
+
+ public Scope enterMethod(String name) {
+ // TODO: distinguish overloads
+ return new Scope(variablesByKey, identifiers, identifier.extend("method#" + name));
+ }
+
+ public FormalArgumentNode formalArgument(String name, TypeName type) {
+ VariableDeclaration declaration = generateVariable(name, type);
+ return FormalArgumentNode.formalArg(declaration);
+ }
+
+ public FormalArgumentNode formalArgument(String key, String name, TypeName type) {
+ VariableDeclaration declaration = generateVariable(key, name, type);
+ return FormalArgumentNode.formalArg(declaration);
+ }
+
+ public LocalVariableDeclarationNode localVariable(
+ String key,
+ String name,
+ TypeName type,
+ ExpressionNode initialValue
+ ) {
+ VariableDeclaration declaration = generateVariable(key, name, type);
+ return LocalVariableDeclarationNode.localVariableDeclaration(declaration, initialValue);
+ }
+
+ public ExpressionNode reference(String key) {
+ VariableDeclaration variable = variablesByKey.get(key);
+ if (variable == null) {
+ throw new IllegalArgumentException("variable not found: " + key);
+ }
+ return VariableReferenceNode.reference(variable);
+ }
+
+ private VariableDeclaration generateVariable(String key, String name, TypeName type) {
+ if (variablesByKey.containsKey(key)) {
+ throw new IllegalArgumentException(key + " is already mapped");
+ }
+ VariableDeclaration variable = generateVariable(name, type);
+ variablesByKey.put(key, variable);
+ return variable;
+ }
+
+ public VariableDeclaration generateVariable(String name, TypeName type) {
+ Identifier identifier = generateIdentifier(name);
+ return VariableDeclaration.var(identifier, name, type);
+ }
+
+ private Identifier generateIdentifier(String name) {
+ Identifier identifier = this.identifier.extend(name);
+ int index = 0;
+ while (identifiers.contains(identifier)) {
+ identifier = this.identifier.extend(name + "_" + index);
+ index++;
+ }
+ identifiers.add(identifier);
+ return identifier;
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/UniqueIdentifiers.java b/src/main/java/org/zwobble/couscous/frontends/java/UniqueIdentifiers.java
deleted file mode 100644
index 1d28de0..0000000
--- a/src/main/java/org/zwobble/couscous/frontends/java/UniqueIdentifiers.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.zwobble.couscous.frontends.java;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class UniqueIdentifiers {
- private final Map<String, Integer> identifiers;
-
- public UniqueIdentifiers() {
- identifiers = new HashMap<>();
- }
-
- public String generate(String identifier) {
- int index = identifiers.computeIfAbsent(identifier, x -> 0);
- return identifier + "__" + index;
- }
-}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Environment.java b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
index b1d59e2..23e2fdf 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Environment.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Environment.java
@@ -5,6 +5,7 @@ import java.util.Optional;
import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.ast.VariableDeclaration;
import org.zwobble.couscous.ast.VariableNode;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import org.zwobble.couscous.interpreter.values.ConcreteType;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
import static java.util.stream.Collectors.toMap;
@@ -12,7 +13,7 @@ import static java.util.stream.Collectors.toMap;
public class Environment {
private final Project project;
private final Optional<InterpreterValue> thisValue;
- private final Map<String, VariableEntry> stackFrame;
+ private final Map<Identifier, VariableEntry> stackFrame;
public Environment(Project project, Optional<InterpreterValue> thisValue, Map<VariableDeclaration, Optional<InterpreterValue>> stackFrame) {
this.project = project;
@@ -27,13 +28,13 @@ public class Environment {
return thisValue;
}
- public InterpreterValue get(String variableId) {
+ public InterpreterValue get(Identifier variableId) {
checkVariableIsInScope(variableId);
final org.zwobble.couscous.interpreter.Environment.VariableEntry entry = stackFrame.get(variableId);
return entry.getValue().orElseThrow(() -> new UnboundVariable(variableId));
}
- public void put(String variableId, InterpreterValue value) {
+ public void put(Identifier variableId, InterpreterValue value) {
checkVariableIsInScope(variableId);
checkVariableType(variableId, value);
stackFrame.get(variableId).setValue(Optional.of(value));
@@ -51,13 +52,13 @@ public class Environment {
return new Environment(project, thisValue, stackFrame);
}
- private void checkVariableIsInScope(String variableId) {
+ private void checkVariableIsInScope(Identifier variableId) {
if (!stackFrame.containsKey(variableId)) {
throw new VariableNotInScope(variableId);
}
}
- private void checkVariableType(String variableId, InterpreterValue value) {
+ private void checkVariableType(Identifier variableId, InterpreterValue value) {
TypeName variableType = stackFrame.get(variableId).getType();
InterpreterTypes.checkIsInstance(variableType, value);
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/UnboundVariable.java b/src/main/java/org/zwobble/couscous/interpreter/UnboundVariable.java
index e0131f0..1dba54b 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/UnboundVariable.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/UnboundVariable.java
@@ -1,14 +1,16 @@
package org.zwobble.couscous.interpreter;
+import org.zwobble.couscous.ast.identifiers.Identifier;
+
public final class UnboundVariable extends InterpreterException {
private static final long serialVersionUID = 1L;
- private final String variableId;
+ private final Identifier variableId;
- public UnboundVariable(final String variableId) {
+ public UnboundVariable(final Identifier variableId) {
this.variableId = variableId;
}
- public String getVariableId() {
+ public Identifier getVariableId() {
return this.variableId;
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/VariableNotInScope.java b/src/main/java/org/zwobble/couscous/interpreter/VariableNotInScope.java
index 54b66bd..c5a425e 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/VariableNotInScope.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/VariableNotInScope.java
@@ -1,14 +1,16 @@
package org.zwobble.couscous.interpreter;
+import org.zwobble.couscous.ast.identifiers.Identifier;
+
public final class VariableNotInScope extends InterpreterException {
private static final long serialVersionUID = 1L;
- private final String variableId;
+ private final Identifier variableId;
- public VariableNotInScope(final String variableId) {
+ public VariableNotInScope(final Identifier variableId) {
this.variableId = variableId;
}
- public String getVariableId() {
+ public Identifier getVariableId() {
return this.variableId;
}
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraMaps.java b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
new file mode 100644
index 0000000..c27e77c
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
@@ -0,0 +1,18 @@
+package org.zwobble.couscous.util;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+import java.util.function.Function;
+
+public class ExtraMaps {
+ public static <T, K, V> Map<K, V> toMap(Iterable<T> iterable, Function<T, Map.Entry<K, V>> function) {
+ ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
+
+ for (T value : iterable) {
+ builder.put(function.apply(value));
+ }
+
+ return builder.build();
+ }
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java b/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
index a325dcb..a5a8d2c 100644
--- a/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
@@ -114,8 +114,8 @@ public abstract class BackendMethodTests {
@Test
public void whileLoopIsExecutedWhileConditionIsTrue() {
- LocalVariableDeclarationNode x = localVariableDeclaration("x", "x", IntegerValue.REF, literal(0));
- LocalVariableDeclarationNode y = localVariableDeclaration("y", "y", IntegerValue.REF, literal(2));
+ LocalVariableDeclarationNode x = localVariableDeclaration(TestIds.id("x"), "x", IntegerValue.REF, literal(0));
+ LocalVariableDeclarationNode y = localVariableDeclaration(TestIds.id("y"), "y", IntegerValue.REF, literal(2));
MethodNode.Builder method = staticMethod("hello")
.statement(x)
.statement(y)
@@ -128,8 +128,8 @@ public abstract class BackendMethodTests {
@Test
public void returnWillExitWhileLoopEarly() {
- LocalVariableDeclarationNode x = localVariableDeclaration("x", "x", IntegerValue.REF, literal(0));
- LocalVariableDeclarationNode y = localVariableDeclaration("y", "y", IntegerValue.REF, literal(2));
+ LocalVariableDeclarationNode x = localVariableDeclaration(TestIds.id("x"), "x", IntegerValue.REF, literal(0));
+ LocalVariableDeclarationNode y = localVariableDeclaration(TestIds.id("y"), "y", IntegerValue.REF, literal(2));
MethodNode.Builder method = staticMethod("hello")
.statement(x)
.statement(y)
diff --git a/src/test/java/org/zwobble/couscous/tests/TestIds.java b/src/test/java/org/zwobble/couscous/tests/TestIds.java
index 50f0ad9..b32cf84 100644
--- a/src/test/java/org/zwobble/couscous/tests/TestIds.java
+++ b/src/test/java/org/zwobble/couscous/tests/TestIds.java
@@ -1,5 +1,11 @@
package org.zwobble.couscous.tests;
+import org.zwobble.couscous.ast.identifiers.Identifier;
+
public class TestIds {
- public static final String ANY_ID = "[id]";
+ public static final Identifier ANY_ID = Identifier.TOP.extend("[any id]");
+
+ public static Identifier id(String name) {
+ return ANY_ID.extend(name);
+ }
}
diff --git a/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java b/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java
index 022e7ed..b9ca169 100644
--- a/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/ValueObjectTests.java
@@ -15,6 +15,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.identifiers.Identifier;
import org.zwobble.couscous.util.ExtraArrays;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.StringValue;
@@ -131,6 +132,8 @@ public class ValueObjectTests {
return asList("[list 1]");
} else if (type.equals(Set.class)) {
return Collections.singleton("[set 1]");
+ } else if (type.equals(Identifier.class)) {
+ return TestIds.id((String)generateFirstInstance(String.class));
} else if (type.equals(PrimitiveValue.class)) {
return generateFirstInstance(StringValue.class);
} else if (type.equals(ExpressionNode.class)) {
@@ -151,6 +154,8 @@ public class ValueObjectTests {
return asList("[list 2]");
} else if (type.equals(Set.class)) {
return Collections.singleton("[set 2]");
+ } else if (type.equals(Identifier.class)) {
+ return TestIds.id((String)generateSecondInstance(String.class));
} else if (type.equals(PrimitiveValue.class)) {
return generateSecondInstance(StringValue.class);
} else if (type.equals(ExpressionNode.class)) {
@@ -171,6 +176,8 @@ public class ValueObjectTests {
return asList("[list]");
} else if (type.equals(Set.class)) {
return Collections.singleton("[set]");
+ } else if (type.equals(Identifier.class)) {
+ return TestIds.id((String)generateInstance(String.class));
} else if (type.equals(PrimitiveValue.class)) {
return generateInstance(StringValue.class);
} else if (type.equals(ExpressionNode.class)) {
diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/FreeVariablesTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/FreeVariablesTests.java
index bd860f7..afded63 100644
--- a/src/test/java/org/zwobble/couscous/tests/frontends/java/FreeVariablesTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/FreeVariablesTests.java
@@ -2,6 +2,7 @@ package org.zwobble.couscous.tests.frontends.java;
import org.junit.Test;
import org.zwobble.couscous.ast.VariableDeclaration;
+import org.zwobble.couscous.tests.TestIds;
import org.zwobble.couscous.values.StringValue;
import java.util.List;
@@ -19,14 +20,14 @@ import static org.zwobble.couscous.frontends.java.FreeVariables.findFreeVariable
public class FreeVariablesTests {
@Test
public void referenceIsFreeIfThereIsNoAssociatedDeclaration() {
- VariableDeclaration declaration = var("[id]", "[name]", StringValue.REF);
+ VariableDeclaration declaration = var(TestIds.ANY_ID, "[name]", StringValue.REF);
List<VariableDeclaration> freeVariables = findFreeVariables(asList(reference(declaration)));
assertEquals(asList(declaration), freeVariables);
}
@Test
public void referenceIsNotFreeIfIsDeclaredAsArgument() {
- VariableDeclaration declaration = var("[id]", "[name]", StringValue.REF);
+ VariableDeclaration declaration = var(TestIds.ANY_ID, "[name]", StringValue.REF);
List<VariableDeclaration> freeVariables = findFreeVariables(
asList(formalArg(declaration), reference(declaration)));
assertEquals(emptyList(), freeVariables);
@@ -34,7 +35,7 @@ public class FreeVariablesTests {
@Test
public void referenceIsNotFreeIfIsReferenceToLocalDefinedInBody() {
- VariableDeclaration declaration = var("[id]", "[name]", StringValue.REF);
+ VariableDeclaration declaration = var(TestIds.ANY_ID, "[name]", StringValue.REF);
List<VariableDeclaration> freeVariables = findFreeVariables(
asList(
localVariableDeclaration(declaration, literal("[value]")),
diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
index 3aab776..15404a4 100644
--- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
@@ -186,7 +186,6 @@ public class JavaReaderTests {
"java.util.function.Function<Integer, Integer> function = (Integer x) -> x;")));
}
- @Ignore("This works except for making the IDs match up")
@Test
public void expressionMethodReferenceIsReadAsLambda() {
assertEquals(