aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-01-04 23:41:34 +0000
committerMichael Williamson <mike@zwobble.org>2016-01-04 23:42:04 +0000
commit81cab75d3b50e47ee6db414c38d5f31b95fc5b06 (patch)
tree138c381d9858e7291e042f2810861f6f9f48f5ad /src
parent75b69c7f4e7ed84f82c549e36a3928a48720cc26 (diff)
Python backend: don't box ints of static type Integer
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java84
2 files changed, 49 insertions, 40 deletions
diff --git a/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java b/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java
index 0d6fd80..d2721ae 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java
@@ -9,10 +9,7 @@ import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.backends.python.ast.PythonBinaryOperation;
import org.zwobble.couscous.backends.python.ast.PythonExpressionNode;
import org.zwobble.couscous.backends.python.ast.PythonNotNode;
-import org.zwobble.couscous.values.BooleanValue;
-import org.zwobble.couscous.values.IntegerValue;
-import org.zwobble.couscous.values.InternalCouscousValue;
-import org.zwobble.couscous.values.StringValue;
+import org.zwobble.couscous.values.*;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
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 ada7dea..47b007b 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
@@ -42,28 +42,28 @@ import static org.zwobble.couscous.backends.python.ast.PythonWhileNode.pythonWhi
public class PythonCodeGenerator {
public static PythonModuleNode generateCode(ClassNode classNode) {
Iterator<PythonImportNode> imports = generateImports(classNode).iterator();
-
+
PythonImportNode internalsImport = pythonImport(
importPathToRoot(classNode),
asList(pythonImportAlias("_couscous")));
-
+
PythonFunctionDefinitionNode constructor =
generateConstructor(classNode.getConstructor());
-
+
Iterable<PythonFunctionDefinitionNode> pythonMethods = Iterables.transform(
classNode.getMethods(),
PythonCodeGenerator::generateFunction);
-
+
PythonClassNode pythonClass = pythonClass(
classNode.getSimpleName(),
ImmutableList.copyOf(Iterables.concat(asList(constructor), pythonMethods)));
-
+
return pythonModule(ImmutableList.copyOf(Iterators.concat(
singletonIterator(pythonClass),
imports,
singletonIterator(internalsImport))));
}
-
+
private static Stream<PythonImportNode> generateImports(ClassNode classNode) {
Set<TypeName> classes = findReferencedClasses(classNode);
return classes.stream()
@@ -74,7 +74,7 @@ public class PythonCodeGenerator {
private static String importPathToRoot(ClassNode classNode) {
return Strings.repeat(".", packageDepth(classNode) + 1);
}
-
+
private static int packageDepth(ClassNode classNode) {
int depth = 0;
final java.lang.String qualifiedName = classNode.getName().getQualifiedName();
@@ -85,7 +85,7 @@ public class PythonCodeGenerator {
}
return depth;
}
-
+
private static Set<TypeName> findReferencedClasses(ClassNode classNode) {
return NodeStructure.descendantNodes(classNode)
.flatMap(node -> node.accept(new NodeMapperWithDefault<Stream<TypeName>>(Stream.empty()) {
@@ -101,39 +101,39 @@ public class PythonCodeGenerator {
}))
.collect(Collectors.toSet());
}
-
+
public static PythonExpressionNode generateCode(PrimitiveValue value) {
return value.accept(new PrimitiveValueVisitor<PythonExpressionNode>(){
-
+
@Override
public PythonExpressionNode visit(IntegerValue value) {
return pythonIntegerLiteral(value.getValue());
}
-
+
@Override
public PythonExpressionNode visit(StringValue value) {
return pythonStringLiteral(value.getValue());
}
-
+
@Override
public PythonExpressionNode visit(BooleanValue value) {
return pythonBooleanLiteral(value.getValue());
}
-
+
@Override
public PythonExpressionNode visit(UnitValue unitValue) {
throw new UnsupportedOperationException();
}
});
}
-
+
private static PythonFunctionDefinitionNode generateConstructor(ConstructorNode constructor) {
Iterable<String> explicitArgumentNames = Iterables.transform(constructor.getArguments(), argument -> argument.getName());
Iterable<String> argumentNames = Iterables.concat(asList("self"), explicitArgumentNames);
List<PythonStatementNode> pythonBody = constructor.getBody().stream().map(PythonCodeGenerator::generateStatement).collect(Collectors.toList());
return pythonFunctionDefinition("__init__", ImmutableList.copyOf(argumentNames), new PythonBlock(pythonBody));
}
-
+
private static PythonFunctionDefinitionNode generateFunction(MethodNode method) {
Iterable<String> explicitArgumentNames = Iterables.transform(method.getArguments(), argument -> argument.getName());
Iterable<String> argumentNames = Iterables.concat(
@@ -142,23 +142,23 @@ public class PythonCodeGenerator {
List<PythonStatementNode> pythonBody = generateStatements(method.getBody());
return pythonFunctionDefinition(method.getName(), ImmutableList.copyOf(argumentNames), new PythonBlock(pythonBody));
}
-
+
private static List<PythonStatementNode> generateStatements(List<StatementNode> statements) {
return statements.stream()
.map(PythonCodeGenerator::generateStatement)
.collect(Collectors.toList());
}
-
+
private static PythonStatementNode generateStatement(StatementNode statement) {
return statement.accept(new StatementGenerator());
}
-
+
private static class StatementGenerator implements StatementNodeMapper<PythonStatementNode> {
@Override
public PythonStatementNode visit(ReturnNode returnNode) {
return pythonReturn(generateExpression(returnNode.getValue()));
}
-
+
@Override
public PythonStatementNode visit(ExpressionStatementNode expressionStatement) {
if (expressionStatement.getExpression() instanceof AssignmentNode) {
@@ -168,7 +168,7 @@ public class PythonCodeGenerator {
throw new UnsupportedOperationException();
}
}
-
+
@Override
public PythonStatementNode visit(LocalVariableDeclarationNode declaration) {
return pythonAssignment(pythonVariableReference(declaration.getDeclaration().getName()), generateExpression(declaration.getInitialValue()));
@@ -189,42 +189,42 @@ public class PythonCodeGenerator {
generateStatements(whileLoop.getBody()));
}
}
-
+
private static PythonExpressionNode generateExpression(ExpressionNode expression) {
return expression.accept(EXPRESSION_GENERATOR);
}
-
+
private static List<PythonExpressionNode> generateExpressions(Iterable<? extends ExpressionNode> expressions) {
return ImmutableList.copyOf(Iterables.transform(expressions, PythonCodeGenerator::generateExpression));
}
private static final ExpressionGenerator EXPRESSION_GENERATOR = new ExpressionGenerator();
-
+
private static class ExpressionGenerator implements ExpressionNodeMapper<PythonExpressionNode> {
@Override
public PythonExpressionNode visit(LiteralNode literal) {
return generateCode(literal.getValue());
}
-
+
@Override
public PythonVariableReferenceNode visit(VariableReferenceNode variableReference) {
return pythonVariableReference(variableReference.getReferent().getName());
}
-
+
@Override
public PythonExpressionNode visit(ThisReferenceNode reference) {
return pythonVariableReference("self");
}
-
+
@Override
public PythonExpressionNode visit(AssignmentNode assignment) {
throw new UnsupportedOperationException();
}
-
+
@Override
public PythonExpressionNode visit(TernaryConditionalNode ternaryConditional) {
return pythonConditionalExpression(generateExpression(ternaryConditional.getCondition()), generateExpression(ternaryConditional.getIfTrue()), generateExpression(ternaryConditional.getIfFalse()));
}
-
+
@Override
public PythonExpressionNode visit(MethodCallNode methodCall) {
PythonExpressionNode receiver = generateExpression(methodCall.getReceiver());
@@ -236,19 +236,19 @@ public class PythonCodeGenerator {
return pythonCall(pythonAttributeAccess(receiver, methodCall.getMethodName()), arguments);
}
}
-
+
@Override
public PythonExpressionNode visit(StaticMethodCallNode staticMethodCall) {
TypeName className = staticMethodCall.getClassName();
PythonVariableReferenceNode classReference = pythonVariableReference(className.getSimpleName());
PythonAttributeAccessNode methodReference = pythonAttributeAccess(classReference, staticMethodCall.getMethodName());
List<PythonExpressionNode> arguments = generateExpressions(staticMethodCall.getArguments());
-
+
return PrimitiveMethods.getPrimitiveStaticMethod(className, staticMethodCall.getMethodName())
.map(generator -> generator.generate(arguments))
- .orElseGet(() -> pythonCall(methodReference, arguments));
+ .orElseGet(() -> pythonCall(methodReference, arguments));
}
-
+
@Override
public PythonExpressionNode visit(ConstructorCallNode call) {
final org.zwobble.couscous.ast.TypeName className = call.getType();
@@ -256,7 +256,7 @@ public class PythonCodeGenerator {
final java.util.List<org.zwobble.couscous.backends.python.ast.PythonExpressionNode> arguments = generateExpressions(call.getArguments());
return pythonCall(classReference, arguments);
}
-
+
@Override
public PythonExpressionNode visit(FieldAccessNode fieldAccess) {
return pythonAttributeAccess(generateExpression(fieldAccess.getLeft()), fieldAccess.getFieldName());
@@ -265,20 +265,32 @@ public class PythonCodeGenerator {
@Override
public PythonExpressionNode visit(TypeCoercionNode typeCoercion) {
PythonExpressionNode value = generateExpression(typeCoercion.getExpression());
- if (typeCoercion.isIntegerBox()) {
+ if (isIntegerBox(typeCoercion)) {
return internalMethod("boxInt", asList(value));
- } else if (typeCoercion.isIntegerUnbox()) {
+ } else if (isIntegerUnbox(typeCoercion)) {
return internalMethod("unboxInt", asList(value));
} else {
return value;
}
}
+ private boolean isIntegerBox(TypeCoercionNode typeCoercion) {
+ return isInteger(typeCoercion.getExpression().getType()) && !isInteger(typeCoercion.getType());
+ }
+
+ private boolean isIntegerUnbox(TypeCoercionNode typeCoercion) {
+ return !isInteger(typeCoercion.getExpression().getType()) && isInteger(typeCoercion.getType());
+ }
+
+ private boolean isInteger(TypeName type) {
+ return type.equals(IntegerValue.REF) || type.equals(ObjectValues.BOXED_INT);
+ }
+
private PythonExpressionNode internalMethod(String name, List<PythonExpressionNode> arguments) {
return pythonCall(pythonAttributeAccess(pythonVariableReference("_couscous"), name), arguments);
}
}
-
+
private static boolean isPrimitive(ExpressionNode value) {
return PrimitiveMethods.isPrimitive(value.getType());
}