aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/backends/python
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/python')
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java41
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java36
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonAttributeAccessNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonBinaryOperation.java61
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonBooleanLiteralNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonCallNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonConditionalExpressionNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java2
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonGetSliceNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonNotNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java5
13 files changed, 144 insertions, 47 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 403e7ac..78624b0 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PrimitiveMethods.java
@@ -12,6 +12,7 @@ import org.zwobble.couscous.values.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.function.BiFunction;
import static org.zwobble.couscous.backends.python.ast.PythonAttributeAccessNode.pythonAttributeAccess;
import static org.zwobble.couscous.backends.python.ast.PythonBinaryOperation.pythonIs;
@@ -39,7 +40,7 @@ public class PrimitiveMethods {
pythonCall(pythonAttributeAccess(receiver, "lower"), list()))
.put("equals", (receiver, arguments) ->
- PythonBinaryOperation.pythonEq(receiver, arguments.get(0)))
+ PythonBinaryOperation.pythonEqual(receiver, arguments.get(0)))
.build();
@@ -51,8 +52,8 @@ public class PrimitiveMethods {
methods.put("negate", (receiver, arguments) ->
PythonNotNode.pythonNot(receiver));
- addOperation(methods, Operator.BOOLEAN_AND, "and");
- addOperation(methods, Operator.BOOLEAN_OR, "or");
+ addOperation(methods, Operator.BOOLEAN_AND, PythonBinaryOperation::pythonAnd);
+ addOperation(methods, Operator.BOOLEAN_OR, PythonBinaryOperation::pythonOr);
BOOLEAN_METHODS = methods.build();
}
@@ -65,9 +66,9 @@ public class PrimitiveMethods {
methods.put("toString", (receiver, arguments) ->
pythonCall(pythonVariableReference("str"), list(receiver)));
- addOperation(methods, Operator.ADD, "+");
- addOperation(methods, Operator.SUBTRACT, "-");
- addOperation(methods, Operator.MULTIPLY, "*");
+ addOperation(methods, Operator.ADD, PythonBinaryOperation::pythonAdd);
+ addOperation(methods, Operator.SUBTRACT, PythonBinaryOperation::pythonSubtract);
+ addOperation(methods, Operator.MULTIPLY, PythonBinaryOperation::pythonMultiply);
methods.put(Operator.DIVIDE.getMethodName(), (receiver, arguments) ->
pythonCall(
@@ -78,12 +79,12 @@ public class PrimitiveMethods {
internalReference("_mod_round_to_zero"),
list(receiver, arguments.get(0))));
- addOperation(methods, Operator.EQUALS, "==");
- addOperation(methods, Operator.NOT_EQUALS, "!=");
- addOperation(methods, Operator.GREATER_THAN, ">");
- addOperation(methods, Operator.GREATER_THAN_OR_EQUAL, ">=");
- addOperation(methods, Operator.LESS_THAN, "<");
- addOperation(methods, Operator.LESS_THAN_OR_EQUAL, "<=");
+ addOperation(methods, Operator.EQUALS, PythonBinaryOperation::pythonEqual);
+ addOperation(methods, Operator.NOT_EQUALS, PythonBinaryOperation::pythonNotEqual);
+ addOperation(methods, Operator.GREATER_THAN, PythonBinaryOperation::pythonGreaterThan);
+ addOperation(methods, Operator.GREATER_THAN_OR_EQUAL, PythonBinaryOperation::pythonGreatThanOrEqual);
+ addOperation(methods, Operator.LESS_THAN, PythonBinaryOperation::pythonLessThan);
+ addOperation(methods, Operator.LESS_THAN_OR_EQUAL, PythonBinaryOperation::pythonLessThanOrEqual);
INT_METHODS = methods.build();
}
@@ -95,20 +96,18 @@ public class PrimitiveMethods {
private static void addOperation(
Builder<String, PrimitiveMethodGenerator> methods,
Operator operator,
- String operatorSymbol)
+ BiFunction<PythonExpressionNode, PythonExpressionNode, PythonExpressionNode> build)
{
- addOperation(methods, operator.getMethodName(), operatorSymbol);
+ addOperation(methods, operator.getMethodName(), build);
}
private static void addOperation(
- Builder<String, PrimitiveMethodGenerator> methods,
- String methodName,
- String operatorSymbol) {
+ Builder<String, PrimitiveMethodGenerator> methods,
+ String methodName,
+ BiFunction<PythonExpressionNode, PythonExpressionNode, PythonExpressionNode> build)
+ {
methods.put(methodName, (receiver, arguments) ->
- new PythonBinaryOperation(
- operatorSymbol,
- receiver,
- arguments.get(0)));
+ build.apply(receiver, arguments.get(0)));
}
private static final Map<TypeName, Map<String, PrimitiveMethodGenerator>> METHODS =
diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
index 6501d1b..45739da 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
@@ -1,11 +1,12 @@
package org.zwobble.couscous.backends.python;
-import java.util.List;
-import java.util.function.Consumer;
-
import org.zwobble.couscous.backends.python.ast.*;
import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor;
import org.zwobble.couscous.util.Action;
+
+import java.util.List;
+import java.util.function.Consumer;
+
import static com.google.common.collect.Iterables.skip;
public class PythonSerializer implements PythonNodeVisitor {
@@ -48,27 +49,27 @@ public class PythonSerializer implements PythonNodeVisitor {
@Override
public void visit(PythonConditionalExpressionNode conditional) {
- writeParenthesised(conditional.getTrueValue());
+ writeParenthesised(conditional.getTrueValue(), conditional);
writer.writeSpace();
writer.writeKeyword("if");
writer.writeSpace();
- writeParenthesised(conditional.getCondition());
+ writeParenthesised(conditional.getCondition(), conditional);
writer.writeSpace();
writer.writeKeyword("else");
writer.writeSpace();
- writeParenthesised(conditional.getFalseValue());
+ writeParenthesised(conditional.getFalseValue(), conditional);
}
@Override
public void visit(PythonAttributeAccessNode attributeAccess) {
- writeParenthesised(attributeAccess.getLeft());
+ writeParenthesised(attributeAccess.getLeft(), attributeAccess);
writer.writeSymbol(".");
writer.writeIdentifier(attributeAccess.getAttributeName());
}
@Override
public void visit(PythonCallNode call) {
- writeParenthesised(call.getCallee());
+ writeParenthesised(call.getCallee(), call);
writer.writeSymbol("(");
writeWithSeparator(call.getArguments(), this::write, () -> {
writer.writeSymbol(",");
@@ -79,7 +80,7 @@ public class PythonSerializer implements PythonNodeVisitor {
@Override
public void visit(PythonGetSliceNode getSlice) {
- writeParenthesised(getSlice.getReceiver());
+ writeParenthesised(getSlice.getReceiver(), getSlice);
writer.writeSymbol("[");
writeWithSeparator(getSlice.getArguments(), this::write, () -> {
writer.writeSymbol(":");
@@ -91,16 +92,16 @@ public class PythonSerializer implements PythonNodeVisitor {
public void visit(PythonNotNode notOperation) {
writer.writeKeyword("not");
writer.writeSpace();
- writeParenthesised(notOperation.getOperand());
+ writeParenthesised(notOperation.getOperand(), notOperation);
}
@Override
public void visit(PythonBinaryOperation operation) {
- writeParenthesised(operation.getLeft());
+ writeParenthesised(operation.getLeft(), operation);
writer.writeSpace();
writer.writeKeyword(operation.getOperator());
writer.writeSpace();
- writeParenthesised(operation.getRight());
+ writeParenthesised(operation.getRight(), operation);
}
@Override
@@ -198,10 +199,15 @@ public class PythonSerializer implements PythonNodeVisitor {
});
}
- private void writeParenthesised(PythonExpressionNode expression) {
- writer.writeSymbol("(");
+ private void writeParenthesised(PythonExpressionNode expression, PythonExpressionNode parent) {
+ boolean requiresParens = parent.precedence() >= expression.precedence();
+ if (requiresParens) {
+ writer.writeSymbol("(");
+ }
write(expression);
- writer.writeSymbol(")");
+ if (requiresParens) {
+ writer.writeSymbol(")");
+ }
}
private void writeArgumentNames(PythonFunctionDefinitionNode functionDefinition) {
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonAttributeAccessNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonAttributeAccessNode.java
index 95e6cf0..e2b8d8b 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonAttributeAccessNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonAttributeAccessNode.java
@@ -32,4 +32,9 @@ public final class PythonAttributeAccessNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonAttributeAccessNode(left=" + this.getLeft() + ", attributeName=" + this.getAttributeName() + ")";
}
+
+ @Override
+ public int precedence() {
+ return 160;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBinaryOperation.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBinaryOperation.java
index 8d6b9ce..ecaf038 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBinaryOperation.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBinaryOperation.java
@@ -4,26 +4,66 @@ import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor;
public class PythonBinaryOperation implements PythonExpressionNode {
public static PythonExpressionNode pythonIs(PythonExpressionNode left, PythonExpressionNode right) {
- return new PythonBinaryOperation("is", left, right);
+ return new PythonBinaryOperation("is", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonAnd(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("and", 20, left, right);
+ }
+
+ public static PythonExpressionNode pythonOr(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("or", 20, left, right);
}
public static PythonExpressionNode pythonAdd(PythonExpressionNode left, PythonExpressionNode right) {
- return new PythonBinaryOperation("+", left, right);
+ return new PythonBinaryOperation("+", 100, left, right);
+ }
+
+ public static PythonExpressionNode pythonSubtract(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("-", 100, left, right);
}
- public static PythonExpressionNode pythonEq(PythonExpressionNode left, PythonExpressionNode right) {
- return new PythonBinaryOperation("==", left, right);
+ public static PythonExpressionNode pythonMultiply(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("*", 110, left, right);
+ }
+
+ public static PythonExpressionNode pythonEqual(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("==", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonNotEqual(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("!=", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonLessThan(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("<", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonLessThanOrEqual(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation("<=", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonGreaterThan(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation(">", 50, left, right);
+ }
+
+ public static PythonExpressionNode pythonGreatThanOrEqual(PythonExpressionNode left, PythonExpressionNode right) {
+ return new PythonBinaryOperation(">=", 50, left, right);
}
private final String operator;
+ private final int precedence;
private final PythonExpressionNode left;
private final PythonExpressionNode right;
- public PythonBinaryOperation(
- String operator,
- PythonExpressionNode left,
- PythonExpressionNode right) {
+ private PythonBinaryOperation(
+ String operator,
+ int precedence,
+ PythonExpressionNode left,
+ PythonExpressionNode right)
+ {
this.operator = operator;
+ this.precedence = precedence;
this.left = left;
this.right = right;
}
@@ -44,4 +84,9 @@ public class PythonBinaryOperation implements PythonExpressionNode {
public void accept(PythonNodeVisitor visitor) {
visitor.visit(this);
}
+
+ @Override
+ public int precedence() {
+ return precedence;
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBooleanLiteralNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBooleanLiteralNode.java
index 893f2e1..fd902ee 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBooleanLiteralNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBooleanLiteralNode.java
@@ -26,4 +26,9 @@ public final class PythonBooleanLiteralNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonBooleanLiteralNode(value=" + this.getValue() + ")";
}
+
+ @Override
+ public int precedence() {
+ return Integer.MAX_VALUE;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonCallNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonCallNode.java
index ae3761b..3adb4fb 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonCallNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonCallNode.java
@@ -1,8 +1,9 @@
package org.zwobble.couscous.backends.python.ast;
-import java.util.List;
import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor;
+import java.util.List;
+
public final class PythonCallNode implements PythonExpressionNode {
private final PythonExpressionNode callee;
private final List<PythonExpressionNode> arguments;
@@ -33,4 +34,9 @@ public final class PythonCallNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonCallNode(callee=" + this.getCallee() + ", arguments=" + this.getArguments() + ")";
}
+
+ @Override
+ public int precedence() {
+ return 150;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonConditionalExpressionNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonConditionalExpressionNode.java
index a320cd2..75f9e15 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonConditionalExpressionNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonConditionalExpressionNode.java
@@ -38,4 +38,9 @@ public final class PythonConditionalExpressionNode implements PythonExpressionNo
public java.lang.String toString() {
return "PythonConditionalExpressionNode(condition=" + this.getCondition() + ", trueValue=" + this.getTrueValue() + ", falseValue=" + this.getFalseValue() + ")";
}
+
+ @Override
+ public int precedence() {
+ return 10;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java
index 9c8a259..8105271 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java
@@ -1,5 +1,5 @@
package org.zwobble.couscous.backends.python.ast;
public interface PythonExpressionNode extends PythonNode {
-
+ int precedence();
}
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonGetSliceNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonGetSliceNode.java
index 70343d8..1a245cd 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonGetSliceNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonGetSliceNode.java
@@ -1,8 +1,9 @@
package org.zwobble.couscous.backends.python.ast;
-import java.util.List;
import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor;
+import java.util.List;
+
public final class PythonGetSliceNode implements PythonExpressionNode {
private final PythonExpressionNode receiver;
private final List<PythonExpressionNode> arguments;
@@ -33,4 +34,9 @@ public final class PythonGetSliceNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonGetSliceNode(receiver=" + this.getReceiver() + ", arguments=" + this.getArguments() + ")";
}
+
+ @Override
+ public int precedence() {
+ return 150;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java
index ce09767..18156ad 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java
@@ -26,4 +26,9 @@ public final class PythonIntegerLiteralNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonIntegerLiteralNode(value=" + this.getValue() + ")";
}
+
+ @Override
+ public int precedence() {
+ return Integer.MAX_VALUE;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNotNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNotNode.java
index 6fe7dc6..e24d0d8 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNotNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNotNode.java
@@ -21,4 +21,9 @@ public class PythonNotNode implements PythonExpressionNode {
public void accept(PythonNodeVisitor visitor) {
visitor.visit(this);
}
+
+ @Override
+ public int precedence() {
+ return 40;
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java
index d64be5f..f3ee201 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java
@@ -26,4 +26,9 @@ public final class PythonStringLiteralNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonStringLiteralNode(value=" + this.getValue() + ")";
}
+
+ @Override
+ public int precedence() {
+ return Integer.MAX_VALUE;
+ }
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java
index 876ac14..f8c2b4a 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java
@@ -26,4 +26,9 @@ public final class PythonVariableReferenceNode implements PythonExpressionNode {
public java.lang.String toString() {
return "PythonVariableReferenceNode(name=" + this.getName() + ")";
}
+
+ @Override
+ public int precedence() {
+ return Integer.MAX_VALUE;
+ }
} \ No newline at end of file