From 8711de89810f1cd6782d98e0e4745c30532a77ac Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 10 Jan 2016 17:52:18 +0000 Subject: Support type literals in the backends --- .../couscous/backends/python/PythonBackend.java | 14 +++---- .../backends/python/PythonCodeGenerator.java | 20 ++++++++-- .../interpreter/values/InterpreterValues.java | 3 +- .../interpreter/values/TypeInterpreterValue.java | 44 ++++++++++++++++++++++ .../org/zwobble/couscous/values/TypeValue.java | 16 +++++--- .../resources/python/runtime/java/lang/String.py | 2 + .../zwobble/couscous/tests/BackendEvalTests.java | 1 + .../tests/backends/python/PythonMethodRunner.java | 40 ++++++++++++++------ 8 files changed, 108 insertions(+), 32 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java create mode 100644 src/main/resources/python/runtime/java/lang/String.py (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java index de36ed6..731faeb 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java @@ -1,20 +1,17 @@ package org.zwobble.couscous.backends.python; +import com.google.common.collect.ImmutableList; +import com.google.common.io.Resources; +import org.zwobble.couscous.Backend; +import org.zwobble.couscous.ast.ClassNode; + import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.stream.Stream; - -import com.google.common.collect.ImmutableList; -import org.zwobble.couscous.Backend; -import org.zwobble.couscous.ast.ClassNode; - -import com.google.common.io.Resources; -import static java.util.Arrays.asList; import static org.zwobble.couscous.backends.python.PythonCodeGenerator.generateCode; import static org.zwobble.couscous.backends.python.PythonSerializer.serialize; import static org.zwobble.couscous.util.ExtraLists.list; @@ -24,6 +21,7 @@ public class PythonBackend implements Backend { "java.lang.Object", "java.lang.Boolean", "java.lang.Integer", + "java.lang.String", "_couscous"); private final Path root; 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 311d065..414d04b 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java @@ -105,6 +105,15 @@ public class PythonCodeGenerator { return Stream.empty(); } } + + @Override + public Stream visit(LiteralNode literal) { + if (literal.getValue() instanceof TypeValue) { + return Stream.of(((TypeValue)literal.getValue()).getValue()); + } else { + return Stream.empty(); + } + } })) .collect(Collectors.toSet()); } @@ -134,8 +143,7 @@ public class PythonCodeGenerator { @Override public PythonExpressionNode visit(TypeValue value) { - // TODO: - throw new UnsupportedOperationException(); + return typeReference(value.getValue()); } }); } @@ -270,7 +278,7 @@ public class PythonCodeGenerator { @Override public PythonExpressionNode visit(ConstructorCallNode call) { final org.zwobble.couscous.ast.TypeName className = call.getType(); - final org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode classReference = pythonVariableReference(className.getSimpleName()); + final org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode classReference = typeReference(className); final java.util.List arguments = generateExpressions(call.getArguments()); return pythonCall(classReference, arguments); } @@ -305,7 +313,7 @@ public class PythonCodeGenerator { @Override public PythonExpressionNode visit(TypeName receiver) { - return pythonVariableReference(receiver.getSimpleName()); + return typeReference(receiver); } }); } @@ -322,6 +330,10 @@ public class PythonCodeGenerator { return type.equals(IntegerValue.REF) || type.equals(ObjectValues.BOXED_INT); } + private static PythonVariableReferenceNode typeReference(TypeName className) { + return pythonVariableReference(className.getSimpleName()); + } + public static String toName(MethodSignature signature) { return Joiner.on("__").join(Iterables.concat( list(signature.getName()), diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java index c405fe3..db33b9d 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValues.java @@ -39,8 +39,7 @@ public class InterpreterValues { @Override public InterpreterValue visit(TypeValue value) { - // TODO: - throw new UnsupportedOperationException(); + return TypeInterpreterValue.of(value.getValue()); } }); } diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java new file mode 100644 index 0000000..97cf6ec --- /dev/null +++ b/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java @@ -0,0 +1,44 @@ +package org.zwobble.couscous.interpreter.values; + +import org.zwobble.couscous.ast.TypeName; +import org.zwobble.couscous.interpreter.NoSuchField; +import org.zwobble.couscous.values.ObjectValues; +import org.zwobble.couscous.values.PrimitiveValue; +import org.zwobble.couscous.values.PrimitiveValues; + +import java.util.Optional; + +public class TypeInterpreterValue implements InterpreterValue { + public static final ConcreteType TYPE = ConcreteType.builder(TypeInterpreterValue.class, ObjectValues.CLASS) + .build(); + + public static InterpreterValue of(TypeName type) { + return new TypeInterpreterValue(type); + } + + private final TypeName type; + + public TypeInterpreterValue(TypeName type) { + this.type = type; + } + + @Override + public ConcreteType getType() { + return TYPE; + } + + @Override + public Optional toPrimitiveValue() { + return Optional.of(PrimitiveValues.value(type)); + } + + @Override + public InterpreterValue getField(String fieldName) { + throw new NoSuchField(fieldName); + } + + @Override + public void setField(String fieldName, InterpreterValue value) { + throw new NoSuchField(fieldName); + } +} diff --git a/src/main/java/org/zwobble/couscous/values/TypeValue.java b/src/main/java/org/zwobble/couscous/values/TypeValue.java index 43dfc33..269839a 100644 --- a/src/main/java/org/zwobble/couscous/values/TypeValue.java +++ b/src/main/java/org/zwobble/couscous/values/TypeValue.java @@ -3,10 +3,14 @@ package org.zwobble.couscous.values; import org.zwobble.couscous.ast.TypeName; public class TypeValue implements PrimitiveValue { - private final TypeName type; + private final TypeName value; - public TypeValue(TypeName type) { - this.type = type; + public TypeValue(TypeName value) { + this.value = value; + } + + public TypeName getValue() { + return value; } @Override @@ -22,7 +26,7 @@ public class TypeValue implements PrimitiveValue { @Override public String toString() { return "TypeValue(" + - "type=" + type + + "value=" + value + ')'; } @@ -33,12 +37,12 @@ public class TypeValue implements PrimitiveValue { TypeValue typeValue = (TypeValue) o; - return type.equals(typeValue.type); + return value.equals(typeValue.value); } @Override public int hashCode() { - return type.hashCode(); + return value.hashCode(); } } diff --git a/src/main/resources/python/runtime/java/lang/String.py b/src/main/resources/python/runtime/java/lang/String.py new file mode 100644 index 0000000..9a1e025 --- /dev/null +++ b/src/main/resources/python/runtime/java/lang/String.py @@ -0,0 +1,2 @@ +class String(object): + pass \ No newline at end of file diff --git a/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java index 814cfa6..bdd492d 100644 --- a/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java +++ b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java @@ -34,6 +34,7 @@ public abstract class BackendEvalTests { assertEquals(value(true), evalExpression(literal(true))); assertEquals(value(false), evalExpression(literal(false))); assertEquals(value(42), evalExpression(literal(42))); + assertEquals(value(StringValue.REF), evalExpression(literal(StringValue.REF))); } @Test diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java index 5818de0..421c1aa 100644 --- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java +++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java @@ -1,23 +1,28 @@ package org.zwobble.couscous.tests.backends.python; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; +import com.google.common.base.Charsets; +import com.google.common.base.Joiner; +import com.google.common.io.CharStreams; import org.zwobble.couscous.ast.ClassNode; import org.zwobble.couscous.ast.MethodSignature; import org.zwobble.couscous.ast.TypeName; -import org.zwobble.couscous.backends.python.PythonCodeGenerator; import org.zwobble.couscous.backends.python.PythonBackend; +import org.zwobble.couscous.backends.python.PythonCodeGenerator; import org.zwobble.couscous.backends.python.PythonSerializer; import org.zwobble.couscous.tests.MethodRunner; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.PrimitiveValues; -import com.google.common.base.Charsets; -import com.google.common.base.Joiner; -import com.google.common.io.CharStreams; +import org.zwobble.couscous.values.StringValue; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import static java.lang.Integer.parseInt; import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively; import static org.zwobble.couscous.util.ExtraLists.eagerMap; @@ -63,9 +68,20 @@ public class PythonMethodRunner implements MethodRunner { return readPrimitive(output); } } - + + private static final Pattern TYPE_REGEX = Pattern.compile("^$"); + private static final String TYPE_NAME_PREFIX = "couscous."; + private static PrimitiveValue readPrimitive(String output) { - if (output.equals("None")) { + Matcher matcher = TYPE_REGEX.matcher(output); + if (matcher.matches()) { + String name = matcher.group(1); + if (name.equals("couscous.java.lang.String.String")) { + return value(StringValue.REF); + } else { + throw new UnsupportedOperationException(); + } + } else if (output.equals("None")) { return PrimitiveValues.UNIT; } else if (output.startsWith("\'")) { return value(output.substring(1, output.length() - 1)); -- cgit v1.2.3