aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-11-15 13:56:34 +0000
committerMichael Williamson <mike@zwobble.org>2015-11-15 13:56:34 +0000
commitf4019f5ed78b0d9c0eb7c7a1b4d97e5c83003ff1 (patch)
tree0d1993d8d965995ecfd26a21268c535630f3033a /src/main/java
parent63956680fa5f6e61210e090036c797d94e4a340c (diff)
Split out statement and expression reading
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java279
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java373
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java86
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java25
4 files changed, 399 insertions, 364 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
new file mode 100644
index 0000000..f9ba55e
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java
@@ -0,0 +1,279 @@
+package org.zwobble.couscous.frontends.java;
+
+import org.eclipse.jdt.core.dom.*;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.values.BooleanValue;
+import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.ObjectValues;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static java.util.Arrays.asList;
+import static org.zwobble.couscous.ast.LiteralNode.literal;
+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;
+
+public class JavaExpressionReader {
+ static ExpressionNode readExpression(TypeName targetType, Expression expression) {
+ ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression);
+ return handleBoxing(targetType, couscousExpression);
+ }
+
+ private static ExpressionNode handleBoxing(TypeName targetType, ExpressionNode couscousExpression) {
+ if (isIntegerBox(targetType, couscousExpression)) {
+ return StaticMethodCallNode.boxInt(couscousExpression);
+ } else if (isIntegerUnbox(targetType, couscousExpression)) {
+ return StaticMethodCallNode.unboxInt(couscousExpression);
+ } else if (isBooleanBox(targetType, couscousExpression)) {
+ return StaticMethodCallNode.boxBoolean(couscousExpression);
+ } else if (isBooleanUnbox(targetType, couscousExpression)) {
+ return StaticMethodCallNode.unboxBoolean(couscousExpression);
+ } else {
+ return couscousExpression;
+ }
+ }
+
+ private static TypeName unboxedType(TypeName type) {
+ if (type.equals(ObjectValues.BOXED_INT)) {
+ return IntegerValue.REF;
+ } else if (type.equals(ObjectValues.BOXED_BOOLEAN)) {
+ return BooleanValue.REF;
+ } else {
+ return type;
+ }
+ }
+
+ private static boolean isIntegerBox(TypeName targetType, ExpressionNode expression) {
+ return expression.getType().equals(IntegerValue.REF) &&
+ !targetType.equals(IntegerValue.REF);
+ }
+
+ private static boolean isIntegerUnbox(TypeName targetType, ExpressionNode expression) {
+ return !expression.getType().equals(IntegerValue.REF) &&
+ targetType.equals(IntegerValue.REF);
+ }
+
+ private static boolean isBooleanBox(TypeName targetType, ExpressionNode expression) {
+ return expression.getType().equals(BooleanValue.REF) &&
+ !targetType.equals(BooleanValue.REF);
+ }
+
+ private static boolean isBooleanUnbox(TypeName targetType, ExpressionNode expression) {
+ return !expression.getType().equals(BooleanValue.REF) &&
+ targetType.equals(BooleanValue.REF);
+ }
+
+ static ExpressionNode readExpressionWithoutBoxing(Expression expression) {
+ switch (expression.getNodeType()) {
+ case ASTNode.BOOLEAN_LITERAL:
+ return readBooleanLiteral((BooleanLiteral)expression);
+
+ case ASTNode.NUMBER_LITERAL:
+ return readNumberLiteral((NumberLiteral)expression);
+
+ case ASTNode.STRING_LITERAL:
+ return readStringLiteral((StringLiteral)expression);
+
+ case ASTNode.SIMPLE_NAME:
+ return readSimpleName((SimpleName)expression);
+
+ case ASTNode.THIS_EXPRESSION:
+ return readThisExpression((ThisExpression)expression);
+
+ case ASTNode.FIELD_ACCESS:
+ return readFieldAccess((FieldAccess)expression);
+
+ case ASTNode.METHOD_INVOCATION:
+ return readMethodInvocation((MethodInvocation)expression);
+
+ case ASTNode.CLASS_INSTANCE_CREATION:
+ return readClassInstanceCreation((ClassInstanceCreation)expression);
+
+ case ASTNode.INFIX_EXPRESSION:
+ return readInfixExpression((InfixExpression)expression);
+
+ case ASTNode.PREFIX_EXPRESSION:
+ return readPrefixExpression((PrefixExpression)expression);
+
+ case ASTNode.CONDITIONAL_EXPRESSION:
+ return readConditionalExpression((ConditionalExpression)expression);
+
+ case ASTNode.ASSIGNMENT:
+ return readAssignment((Assignment)expression);
+
+ default:
+ throw new RuntimeException("Unsupported expression: " + expression.getClass());
+
+ }
+ }
+
+ private static ExpressionNode readBooleanLiteral(BooleanLiteral expression) {
+ return literal(expression.booleanValue());
+ }
+
+ private static LiteralNode readNumberLiteral(NumberLiteral expression) {
+ return literal(Integer.parseInt(expression.getToken()));
+ }
+
+ private static ExpressionNode readStringLiteral(StringLiteral expression) {
+ return literal(expression.getLiteralValue());
+ }
+
+ private static ExpressionNode readSimpleName(SimpleName expression) {
+ IBinding binding = expression.resolveBinding();
+ if (binding.getKind() == IBinding.VARIABLE) {
+ return readVariableBinding((IVariableBinding)binding);
+ } else {
+ throw new RuntimeException("Unsupported binding: " + binding.getClass());
+ }
+ }
+
+ private static ExpressionNode readVariableBinding(IVariableBinding binding) {
+ TypeName type = typeOf(binding);
+ if (binding.getDeclaringClass() == null) {
+ return reference(var(binding.getKey(), binding.getName(), type));
+ } else {
+ return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type);
+ }
+ }
+
+ private static ExpressionNode readThisExpression(ThisExpression expression) {
+ return ThisReferenceNode.thisReference(typeOf(expression));
+ }
+
+ private static ExpressionNode readFieldAccess(FieldAccess expression) {
+ return FieldAccessNode.fieldAccess(readExpressionWithoutBoxing(expression.getExpression()), expression.getName().getIdentifier(), typeOf(expression));
+ }
+
+ private static ExpressionNode readMethodInvocation(MethodInvocation expression) {
+ String methodName = expression.getName().getIdentifier();
+ @SuppressWarnings("unchecked")
+ List<ExpressionNode> arguments = readArguments(
+ expression.resolveMethodBinding(),
+ expression.arguments());
+ final TypeName type = typeOf(expression);
+
+ IMethodBinding methodBinding = expression.resolveMethodBinding();
+ TypeName receiverType = typeOf(methodBinding.getDeclaringClass());
+ if ((methodBinding.getModifiers() & Modifier.STATIC) != 0) {
+ return StaticMethodCallNode.staticMethodCall(
+ receiverType,
+ methodName,
+ arguments,
+ type);
+ } else {
+ ExpressionNode receiver = expression.getExpression() == null
+ ? ThisReferenceNode.thisReference(receiverType)
+ : readExpressionWithoutBoxing(expression.getExpression());
+ return MethodCallNode.methodCall(
+ receiver,
+ methodName,
+ arguments,
+ type);
+ }
+ }
+
+ private static ExpressionNode readClassInstanceCreation(ClassInstanceCreation expression) {
+ @SuppressWarnings("unchecked")
+ List<Expression> arguments = expression.arguments();
+ return ConstructorCallNode.constructorCall(
+ typeOf(expression),
+ readArguments(expression.resolveConstructorBinding(), arguments));
+ }
+
+ private static List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) {
+ return IntStream.range(0, javaArguments.size())
+ .mapToObj(index -> readExpression(
+ typeOf(method.getParameterTypes()[index]),
+ javaArguments.get(index)))
+ .collect(Collectors.toList());
+ }
+
+ private static ExpressionNode readInfixExpression(InfixExpression expression) {
+ if (isPrimitiveOperation(expression)) {
+ Operator operator = readOperator(expression.getOperator());
+ return readPrimitiveOperation(
+ operator,
+ expression.getLeftOperand(),
+ expression.getRightOperand());
+ } else {
+ ExpressionNode left = readExpression(ObjectValues.OBJECT, expression.getLeftOperand());
+ ExpressionNode right = readExpression(ObjectValues.OBJECT, expression.getRightOperand());
+ if (expression.getOperator() == InfixExpression.Operator.EQUALS) {
+ return StaticMethodCallNode.same(left, right);
+ } else if (expression.getOperator() == InfixExpression.Operator.NOT_EQUALS) {
+ return MethodCallNode.not(StaticMethodCallNode.same(left, right));
+ } else {
+ throw new IllegalArgumentException("Unsupported operator: " + expression.getOperator());
+ }
+ }
+ }
+
+ private static boolean isPrimitiveOperation(InfixExpression expression) {
+ TypeName leftOperandType = typeOf(expression.getLeftOperand());
+ TypeName rightOperandType = typeOf(expression.getRightOperand());
+ return isPrimitive(leftOperandType)
+ || isPrimitive(rightOperandType)
+ || (expression.getOperator() != InfixExpression.Operator.NOT_EQUALS
+ && expression.getOperator() != InfixExpression.Operator.EQUALS);
+ }
+
+ private static boolean isPrimitive(TypeName type) {
+ return type.equals(BooleanValue.REF) || type.equals(IntegerValue.REF);
+ }
+
+ private static ExpressionNode readPrefixExpression(PrefixExpression expression) {
+ Operator operator = readOperator(expression.getOperator());
+ return AssignmentNode.assign(
+ (AssignableExpressionNode) readExpressionWithoutBoxing(expression.getOperand()),
+ MethodCallNode.methodCall(
+ readExpression(IntegerValue.REF, expression.getOperand()),
+ operator.getMethodName(),
+ asList(literal(1)),
+ IntegerValue.REF));
+ }
+
+ private static ExpressionNode readConditionalExpression(ConditionalExpression expression) {
+ TypeName type = typeOf(expression);
+ return TernaryConditionalNode.ternaryConditional(
+ readExpression(BooleanValue.REF, expression.getExpression()),
+ readExpression(type, expression.getThenExpression()),
+ readExpression(type, expression.getElseExpression()));
+ }
+
+ private static ExpressionNode readAssignment(Assignment expression) {
+ AssignableExpressionNode left = (AssignableExpressionNode)readExpressionWithoutBoxing(expression.getLeftHandSide());
+ if (expression.getOperator() == Assignment.Operator.ASSIGN) {
+ ExpressionNode right = readExpression(left.getType(), expression.getRightHandSide());
+ return AssignmentNode.assign(left, right);
+ } else {
+ ExpressionNode right = readUnboxedExpression(expression.getRightHandSide());
+ Operator operator = readOperator(expression.getOperator());
+ return AssignmentNode.assign(
+ left,
+ handleBoxing(
+ left.getType(),
+ readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide())));
+ }
+ }
+
+ private static ExpressionNode readPrimitiveOperation(Operator operator, Expression leftJava, Expression rightJava) {
+ ExpressionNode left = readUnboxedExpression(leftJava);
+ ExpressionNode right = readUnboxedExpression(rightJava);
+ return MethodCallNode.methodCall(
+ left,
+ operator.getMethodName(),
+ asList(right),
+ operator.isBoolean() ? BooleanValue.REF : left.getType());
+ }
+
+ private static ExpressionNode readUnboxedExpression(Expression expression) {
+ return readExpression(
+ unboxedType(typeOf(expression)),
+ expression);
+ }
+}
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 32662a6..a54ca55 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -1,30 +1,17 @@
package org.zwobble.couscous.frontends.java;
+import org.eclipse.jdt.core.dom.*;
+import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.ClassNodeBuilder;
+import org.zwobble.couscous.ast.StatementNode;
+
import java.io.IOException;
import java.nio.file.Path;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-import org.eclipse.jdt.core.dom.*;
-import org.zwobble.couscous.ast.*;
-import org.zwobble.couscous.ast.ClassNodeBuilder.MethodBuilder;
-import org.zwobble.couscous.values.BooleanValue;
-import org.zwobble.couscous.values.IntegerValue;
-import org.zwobble.couscous.values.ObjectValues;
-import static java.util.Arrays.asList;
-import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement;
-import static org.zwobble.couscous.ast.LiteralNode.literal;
-import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration;
-import static org.zwobble.couscous.ast.VariableDeclaration.var;
-import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
-import static org.zwobble.couscous.ast.WhileNode.whileLoop;
-import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator;
-import static org.zwobble.couscous.util.ExtraLists.eagerMap;
+import static org.zwobble.couscous.frontends.java.JavaStatementReader.readStatement;
+import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
public class JavaReader {
-
private final JavaParser parser = new JavaParser();
public ClassNode readClassFromFile(Path root, Path sourcePath) throws IOException {
@@ -67,8 +54,8 @@ public class JavaReader {
classBuilder.method(method.getName().getIdentifier(), true, builder -> buildMethod(method, builder));
}
}
-
- private static <T> MethodBuilder<T> buildMethod(MethodDeclaration method, MethodBuilder<T> builder) {
+
+ private static <T> ClassNodeBuilder.MethodBuilder<T> buildMethod(MethodDeclaration method, ClassNodeBuilder.MethodBuilder<T> builder) {
for (IAnnotationBinding annotation : method.resolveBinding().getAnnotations()) {
builder.annotation(typeOf(annotation.getAnnotationType()));
}
@@ -83,351 +70,9 @@ public class JavaReader {
}
return builder;
}
-
- private static List<StatementNode> readStatement(Statement statement) {
- switch (statement.getNodeType()) {
- case ASTNode.BLOCK:
- return readBlock((Block)statement);
-
- case ASTNode.RETURN_STATEMENT:
- return asList(readReturnStatement((ReturnStatement)statement));
-
- case ASTNode.EXPRESSION_STATEMENT:
- return asList(readExpressionStatement((ExpressionStatement)statement));
-
- case ASTNode.IF_STATEMENT:
- return asList(readIfStatement((IfStatement)statement));
-
- case ASTNode.WHILE_STATEMENT:
- return asList(readWhileStatement((WhileStatement)statement));
-
- case ASTNode.VARIABLE_DECLARATION_STATEMENT:
- return readVariableDeclarationStatement((VariableDeclarationStatement)statement);
-
- default:
- throw new RuntimeException("Unsupported statement: " + statement.getClass());
- }
- }
-
- private static List<StatementNode> readBlock(Block block) {
- @SuppressWarnings("unchecked")
- List<Statement> statements = block.statements();
- return statements.stream()
- .flatMap(statement -> readStatement(statement).stream())
- .collect(Collectors.toList());
- }
-
- private static StatementNode readReturnStatement(ReturnStatement statement) {
- // TODO: set target type
- return ReturnNode.returns(readExpressionWithoutBoxing(statement.getExpression()));
- }
-
- private static StatementNode readExpressionStatement(ExpressionStatement statement) {
- return expressionStatement(readExpressionWithoutBoxing(statement.getExpression()));
- }
-
- private static StatementNode readIfStatement(IfStatement statement) {
- return IfStatementNode.ifStatement(
- readExpression(BooleanValue.REF, statement.getExpression()),
- readStatement(statement.getThenStatement()),
- readStatement(statement.getElseStatement()));
- }
-
- private static WhileNode readWhileStatement(WhileStatement statement) {
- return whileLoop(
- readExpression(BooleanValue.REF, statement.getExpression()),
- readStatement(statement.getBody()));
- }
-
- private static List<StatementNode> readVariableDeclarationStatement(VariableDeclarationStatement statement) {
- @SuppressWarnings("unchecked")
- List<VariableDeclarationFragment> fragments = statement.fragments();
- TypeName type = typeOf(statement.getType());
- return eagerMap(fragments, fragment ->
- localVariableDeclaration(
- fragment.resolveBinding().getKey(),
- fragment.getName().getIdentifier(),
- type,
- readExpression(type, fragment.getInitializer())));
- }
-
- private static ExpressionNode readExpression(TypeName targetType, Expression expression) {
- ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression);
- return handleBoxing(targetType, couscousExpression);
- }
-
- private static ExpressionNode handleBoxing(TypeName targetType, ExpressionNode couscousExpression) {
- if (isIntegerBox(targetType, couscousExpression)) {
- return StaticMethodCallNode.boxInt(couscousExpression);
- } else if (isIntegerUnbox(targetType, couscousExpression)) {
- return StaticMethodCallNode.unboxInt(couscousExpression);
- } else if (isBooleanBox(targetType, couscousExpression)) {
- return StaticMethodCallNode.boxBoolean(couscousExpression);
- } else if (isBooleanUnbox(targetType, couscousExpression)) {
- return StaticMethodCallNode.unboxBoolean(couscousExpression);
- } else {
- return couscousExpression;
- }
- }
-
- private static TypeName unboxedType(TypeName type) {
- if (type.equals(ObjectValues.BOXED_INT)) {
- return IntegerValue.REF;
- } else if (type.equals(ObjectValues.BOXED_BOOLEAN)) {
- return BooleanValue.REF;
- } else {
- return type;
- }
- }
-
- private static boolean isIntegerBox(TypeName targetType, ExpressionNode expression) {
- return expression.getType().equals(IntegerValue.REF) &&
- !targetType.equals(IntegerValue.REF);
- }
-
- private static boolean isIntegerUnbox(TypeName targetType, ExpressionNode expression) {
- return !expression.getType().equals(IntegerValue.REF) &&
- targetType.equals(IntegerValue.REF);
- }
-
- private static boolean isBooleanBox(TypeName targetType, ExpressionNode expression) {
- return expression.getType().equals(BooleanValue.REF) &&
- !targetType.equals(BooleanValue.REF);
- }
-
- private static boolean isBooleanUnbox(TypeName targetType, ExpressionNode expression) {
- return !expression.getType().equals(BooleanValue.REF) &&
- targetType.equals(BooleanValue.REF);
- }
-
- private static ExpressionNode readExpressionWithoutBoxing(Expression expression) {
- switch (expression.getNodeType()) {
- case ASTNode.BOOLEAN_LITERAL:
- return readBooleanLiteral((BooleanLiteral)expression);
-
- case ASTNode.NUMBER_LITERAL:
- return readNumberLiteral((NumberLiteral)expression);
-
- case ASTNode.STRING_LITERAL:
- return readStringLiteral((StringLiteral)expression);
-
- case ASTNode.SIMPLE_NAME:
- return readSimpleName((SimpleName)expression);
-
- case ASTNode.THIS_EXPRESSION:
- return readThisExpression((ThisExpression)expression);
-
- case ASTNode.FIELD_ACCESS:
- return readFieldAccess((FieldAccess)expression);
-
- case ASTNode.METHOD_INVOCATION:
- return readMethodInvocation((MethodInvocation)expression);
-
- case ASTNode.CLASS_INSTANCE_CREATION:
- return readClassInstanceCreation((ClassInstanceCreation)expression);
-
- case ASTNode.INFIX_EXPRESSION:
- return readInfixExpression((InfixExpression)expression);
-
- case ASTNode.PREFIX_EXPRESSION:
- return readPrefixExpression((PrefixExpression)expression);
-
- case ASTNode.CONDITIONAL_EXPRESSION:
- return readConditionalExpression((ConditionalExpression)expression);
-
- case ASTNode.ASSIGNMENT:
- return readAssignment((Assignment)expression);
-
- default:
- throw new RuntimeException("Unsupported expression: " + expression.getClass());
-
- }
- }
-
- private static ExpressionNode readBooleanLiteral(BooleanLiteral expression) {
- return literal(expression.booleanValue());
- }
-
- private static LiteralNode readNumberLiteral(NumberLiteral expression) {
- return literal(Integer.parseInt(expression.getToken()));
- }
-
- private static ExpressionNode readStringLiteral(StringLiteral expression) {
- return literal(expression.getLiteralValue());
- }
-
- private static ExpressionNode readSimpleName(SimpleName expression) {
- IBinding binding = expression.resolveBinding();
- if (binding.getKind() == IBinding.VARIABLE) {
- return readVariableBinding((IVariableBinding)binding);
- } else {
- throw new RuntimeException("Unsupported binding: " + binding.getClass());
- }
- }
-
- private static ExpressionNode readVariableBinding(IVariableBinding binding) {
- TypeName type = typeOf(binding);
- if (binding.getDeclaringClass() == null) {
- return reference(var(binding.getKey(), binding.getName(), type));
- } else {
- return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type);
- }
- }
-
- private static ExpressionNode readThisExpression(ThisExpression expression) {
- return ThisReferenceNode.thisReference(typeOf(expression));
- }
-
- private static ExpressionNode readFieldAccess(FieldAccess expression) {
- return FieldAccessNode.fieldAccess(readExpressionWithoutBoxing(expression.getExpression()), expression.getName().getIdentifier(), typeOf(expression));
- }
-
- private static ExpressionNode readMethodInvocation(MethodInvocation expression) {
- String methodName = expression.getName().getIdentifier();
- @SuppressWarnings("unchecked")
- List<ExpressionNode> arguments = readArguments(
- expression.resolveMethodBinding(),
- expression.arguments());
- final TypeName type = typeOf(expression);
-
- IMethodBinding methodBinding = expression.resolveMethodBinding();
- TypeName receiverType = typeOf(methodBinding.getDeclaringClass());
- if ((methodBinding.getModifiers() & Modifier.STATIC) != 0) {
- return StaticMethodCallNode.staticMethodCall(
- receiverType,
- methodName,
- arguments,
- type);
- } else {
- ExpressionNode receiver = expression.getExpression() == null
- ? ThisReferenceNode.thisReference(receiverType)
- : readExpressionWithoutBoxing(expression.getExpression());
- return MethodCallNode.methodCall(
- receiver,
- methodName,
- arguments,
- type);
- }
- }
-
- private static ExpressionNode readClassInstanceCreation(ClassInstanceCreation expression) {
- @SuppressWarnings("unchecked")
- List<Expression> arguments = expression.arguments();
- return ConstructorCallNode.constructorCall(
- typeOf(expression),
- readArguments(expression.resolveConstructorBinding(), arguments));
- }
-
- private static List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) {
- return IntStream.range(0, javaArguments.size())
- .mapToObj(index -> readExpression(
- typeOf(method.getParameterTypes()[index]),
- javaArguments.get(index)))
- .collect(Collectors.toList());
- }
-
- private static ExpressionNode readInfixExpression(InfixExpression expression) {
- if (isPrimitiveOperation(expression)) {
- Operator operator = readOperator(expression.getOperator());
- return readPrimitiveOperation(
- operator,
- expression.getLeftOperand(),
- expression.getRightOperand());
- } else {
- ExpressionNode left = readExpression(ObjectValues.OBJECT, expression.getLeftOperand());
- ExpressionNode right = readExpression(ObjectValues.OBJECT, expression.getRightOperand());
- if (expression.getOperator() == InfixExpression.Operator.EQUALS) {
- return StaticMethodCallNode.same(left, right);
- } else if (expression.getOperator() == InfixExpression.Operator.NOT_EQUALS) {
- return MethodCallNode.not(StaticMethodCallNode.same(left, right));
- } else {
- throw new IllegalArgumentException("Unsupported operator: " + expression.getOperator());
- }
- }
- }
-
- private static boolean isPrimitiveOperation(InfixExpression expression) {
- TypeName leftOperandType = typeOf(expression.getLeftOperand());
- TypeName rightOperandType = typeOf(expression.getRightOperand());
- return isPrimitive(leftOperandType)
- || isPrimitive(rightOperandType)
- || (expression.getOperator() != InfixExpression.Operator.NOT_EQUALS
- && expression.getOperator() != InfixExpression.Operator.EQUALS);
- }
-
- private static boolean isPrimitive(TypeName type) {
- return type.equals(BooleanValue.REF) || type.equals(IntegerValue.REF);
- }
-
- private static ExpressionNode readPrefixExpression(PrefixExpression expression) {
- Operator operator = readOperator(expression.getOperator());
- return AssignmentNode.assign(
- (AssignableExpressionNode) readExpressionWithoutBoxing(expression.getOperand()),
- MethodCallNode.methodCall(
- readExpression(IntegerValue.REF, expression.getOperand()),
- operator.getMethodName(),
- asList(literal(1)),
- IntegerValue.REF));
- }
-
- private static ExpressionNode readConditionalExpression(ConditionalExpression expression) {
- TypeName type = typeOf(expression);
- return TernaryConditionalNode.ternaryConditional(
- readExpression(BooleanValue.REF, expression.getExpression()),
- readExpression(type, expression.getThenExpression()),
- readExpression(type, expression.getElseExpression()));
- }
-
- private static ExpressionNode readAssignment(Assignment expression) {
- AssignableExpressionNode left = (AssignableExpressionNode)readExpressionWithoutBoxing(expression.getLeftHandSide());
- if (expression.getOperator() == Assignment.Operator.ASSIGN) {
- ExpressionNode right = readExpression(left.getType(), expression.getRightHandSide());
- return AssignmentNode.assign(left, right);
- } else {
- ExpressionNode right = readUnboxedExpression(expression.getRightHandSide());
- Operator operator = readOperator(expression.getOperator());
- return AssignmentNode.assign(
- left,
- handleBoxing(
- left.getType(),
- readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide())));
- }
- }
-
- private static ExpressionNode readPrimitiveOperation(Operator operator, Expression leftJava, Expression rightJava) {
- ExpressionNode left = readUnboxedExpression(leftJava);
- ExpressionNode right = readUnboxedExpression(rightJava);
- return MethodCallNode.methodCall(
- left,
- operator.getMethodName(),
- asList(right),
- operator.isBoolean() ? BooleanValue.REF : left.getType());
- }
-
- private static ExpressionNode readUnboxedExpression(Expression expression) {
- return readExpression(
- unboxedType(typeOf(expression)),
- expression);
- }
private static String generateClassName(CompilationUnit ast) {
TypeDeclaration type = (TypeDeclaration)ast.types().get(0);
return ast.getPackage().getName().getFullyQualifiedName() + "." + type.getName().getFullyQualifiedName();
}
-
- private static TypeName typeOf(Expression expression) {
- return typeOf(expression.resolveTypeBinding());
- }
-
- private static TypeName typeOf(IVariableBinding variableBinding) {
- return typeOf(variableBinding.getType());
- }
-
- private static TypeName typeOf(Type type) {
- return typeOf(type.resolveBinding());
- }
-
- private static TypeName typeOf(ITypeBinding typeBinding) {
- return TypeName.of(typeBinding.getQualifiedName());
- }
} \ 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
new file mode 100644
index 0000000..c5194b4
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
@@ -0,0 +1,86 @@
+package org.zwobble.couscous.frontends.java;
+
+import org.eclipse.jdt.core.dom.*;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.values.BooleanValue;
+
+import java.util.List;
+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.JavaExpressionReader.readExpression;
+import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpressionWithoutBoxing;
+import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
+
+public class JavaStatementReader {
+ static List<StatementNode> readStatement(Statement statement) {
+ switch (statement.getNodeType()) {
+ case ASTNode.BLOCK:
+ return readBlock((Block)statement);
+
+ case ASTNode.RETURN_STATEMENT:
+ return asList(readReturnStatement((ReturnStatement)statement));
+
+ case ASTNode.EXPRESSION_STATEMENT:
+ return asList(readExpressionStatement((ExpressionStatement)statement));
+
+ case ASTNode.IF_STATEMENT:
+ return asList(readIfStatement((IfStatement)statement));
+
+ case ASTNode.WHILE_STATEMENT:
+ return asList(readWhileStatement((WhileStatement)statement));
+
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ return readVariableDeclarationStatement((VariableDeclarationStatement)statement);
+
+ default:
+ throw new RuntimeException("Unsupported statement: " + statement.getClass());
+ }
+ }
+
+ private static List<StatementNode> readBlock(Block block) {
+ @SuppressWarnings("unchecked")
+ List<Statement> statements = block.statements();
+ return statements.stream()
+ .flatMap(statement -> readStatement(statement).stream())
+ .collect(Collectors.toList());
+ }
+
+ private static StatementNode readReturnStatement(ReturnStatement statement) {
+ // TODO: set target type
+ return ReturnNode.returns(readExpressionWithoutBoxing(statement.getExpression()));
+ }
+
+ private static StatementNode readExpressionStatement(ExpressionStatement statement) {
+ return expressionStatement(readExpressionWithoutBoxing(statement.getExpression()));
+ }
+
+ private static StatementNode readIfStatement(IfStatement statement) {
+ return IfStatementNode.ifStatement(
+ readExpression(BooleanValue.REF, statement.getExpression()),
+ readStatement(statement.getThenStatement()),
+ readStatement(statement.getElseStatement()));
+ }
+
+ private static WhileNode readWhileStatement(WhileStatement statement) {
+ return whileLoop(
+ readExpression(BooleanValue.REF, statement.getExpression()),
+ readStatement(statement.getBody()));
+ }
+
+ private static List<StatementNode> readVariableDeclarationStatement(VariableDeclarationStatement statement) {
+ @SuppressWarnings("unchecked")
+ List<VariableDeclarationFragment> fragments = statement.fragments();
+ TypeName type = typeOf(statement.getType());
+ return eagerMap(fragments, fragment ->
+ localVariableDeclaration(
+ fragment.resolveBinding().getKey(),
+ fragment.getName().getIdentifier(),
+ type,
+ readExpression(type, fragment.getInitializer())));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java
new file mode 100644
index 0000000..d6b2160
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java
@@ -0,0 +1,25 @@
+package org.zwobble.couscous.frontends.java;
+
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.Type;
+import org.zwobble.couscous.ast.TypeName;
+
+class JavaTypes {
+ static TypeName typeOf(Expression expression) {
+ return typeOf(expression.resolveTypeBinding());
+ }
+
+ static TypeName typeOf(IVariableBinding variableBinding) {
+ return typeOf(variableBinding.getType());
+ }
+
+ static TypeName typeOf(Type type) {
+ return typeOf(type.resolveBinding());
+ }
+
+ static TypeName typeOf(ITypeBinding typeBinding) {
+ return TypeName.of(typeBinding.getQualifiedName());
+ }
+}