From 81cab75d3b50e47ee6db414c38d5f31b95fc5b06 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Mon, 4 Jan 2016 23:41:34 +0000 Subject: Python backend: don't box ints of static type Integer --- .../couscous/backends/python/PrimitiveMethods.java | 5 +- .../backends/python/PythonCodeGenerator.java | 84 ++++++++++++---------- 2 files changed, 49 insertions(+), 40 deletions(-) (limited to 'src') 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 imports = generateImports(classNode).iterator(); - + PythonImportNode internalsImport = pythonImport( importPathToRoot(classNode), asList(pythonImportAlias("_couscous"))); - + PythonFunctionDefinitionNode constructor = generateConstructor(classNode.getConstructor()); - + Iterable 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 generateImports(ClassNode classNode) { Set 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 findReferencedClasses(ClassNode classNode) { return NodeStructure.descendantNodes(classNode) .flatMap(node -> node.accept(new NodeMapperWithDefault>(Stream.empty()) { @@ -101,39 +101,39 @@ public class PythonCodeGenerator { })) .collect(Collectors.toSet()); } - + public static PythonExpressionNode generateCode(PrimitiveValue value) { return value.accept(new PrimitiveValueVisitor(){ - + @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 explicitArgumentNames = Iterables.transform(constructor.getArguments(), argument -> argument.getName()); Iterable argumentNames = Iterables.concat(asList("self"), explicitArgumentNames); List 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 explicitArgumentNames = Iterables.transform(method.getArguments(), argument -> argument.getName()); Iterable argumentNames = Iterables.concat( @@ -142,23 +142,23 @@ public class PythonCodeGenerator { List pythonBody = generateStatements(method.getBody()); return pythonFunctionDefinition(method.getName(), ImmutableList.copyOf(argumentNames), new PythonBlock(pythonBody)); } - + private static List generateStatements(List 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 { @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 generateExpressions(Iterable expressions) { return ImmutableList.copyOf(Iterables.transform(expressions, PythonCodeGenerator::generateExpression)); } private static final ExpressionGenerator EXPRESSION_GENERATOR = new ExpressionGenerator(); - + private static class ExpressionGenerator implements ExpressionNodeMapper { @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 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 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 arguments) { return pythonCall(pythonAttributeAccess(pythonVariableReference("_couscous"), name), arguments); } } - + private static boolean isPrimitive(ExpressionNode value) { return PrimitiveMethods.isPrimitive(value.getType()); } -- cgit v1.2.3